![]()
一、会话模式与等级的意义 1.1 基本概念
UDS(Unified Diagnostic Services,ISO 14229)中的0x10服务用于控制ECU的诊断会话状态。诊断会话模式本质上是一种安全机制,通过划分不同权限等级,限制敏感诊断服务的访问。
1.2 三种标准会话子功能
子功能
名称
典型可用服务
0x01
Default Session(默认会话)
22读取数据、11读取DTC、14清除DTC、3E保活
0x02
Programming Session(编程会话)
34请求下载、36传输数据、37退出传输
0x03
Extended Session(扩展会话)
27安全访问、2E写入数据、31例行程序、85DTC控制
1.3 会话模式切换示意图
┌─────────────────────────────────────────────────────────┐
│ ECU上电/复位 │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Default Session │◄──────────────────┐ │
│ │ (权限最低) │ │ │
│ └────────┬─────────┘ │ │
│ │ 10 03 │ │
│ ▼ │ 10 01
│ ┌──────────────────┐ │ │
│ │ Extended Session│ │ │
│ │ (中等级别) │ │ │
│ └────────┬─────────┘ │ │
│ │ 10 02 │ │
│ ▼ │ │
│ ┌──────────────────┐ │ │
│ │ Programming Session│──────────────────┘ │
│ │ (最高权限) │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────┘
二、会话模式跳转规则 2.1 核心规则表当前会话
目标会话
是否允许
Default
Default
重新初始化默认会话
Default
Extended
停止已配置的ResponseOnEvent
Default
Programming
必须经过Extended
Extended
Default
重置所有会话相关设置
Extended
Extended
安全访问需重新解锁
Extended
Programming
单向跳转
Programming
Default
重置并启用安全锁定
Programming
Extended
禁止反向跳转
Programming
Programming
重新初始化编程会话
2.2 超时机制(S3保活)
Tester ECU
│ │
│──────── 10 03 (进入Extended) ─────────►│
│◄─────── 50 03 (肯定响应) ─────────────│
│ │
│ (S3_client周期内) │
│──────── 3E 00 (TesterPresent) ───────►│
│◄─────── 7E 00 (保活响应) ─────────────│
│ │
│ (超过S3_server时间无诊断请求) │
│ │──┐
│ │ │ 自动切回
│ │◄─┘ Default
三、C++代码实现 3.1 诊断会话管理器类定义3.2 诊断会话管理器实现// UdsSessionManager.h
#ifndef UDS_SESSION_MANAGER_H
#define UDS_SESSION_MANAGER_H
#include
#include
#include
#include
#include
namespace Uds {
// 诊断会话类型枚举
enum class DiagnosticSession : uint8_t {
DEFAULT_SESSION = 0x01,
PROGRAMMING_SESSION = 0x02,
EXTENDED_SESSION = 0x03
};
// 服务ID枚举
enum class ServiceId : uint8_t {
DIAGNOSTIC_SESSION_CONTROL = 0x10,
ECU_RESET = 0x11,
READ_DATA_BY_ID = 0x22,
SECURITY_ACCESS = 0x27,
COMMUNICATION_CONTROL = 0x28,
READ_DTC_INFO = 0x19,
WRITE_DATA_BY_ID = 0x2E,
ROUTINE_CONTROL = 0x31,
REQUEST_DOWNLOAD = 0x34,
TRANSFER_DATA = 0x36,
REQUEST_TRANSFER_EXIT = 0x37,
TESTER_PRESENT = 0x3E
};
// 安全访问状态
enum class SecurityLevel : uint8_t {
LOCKED = 0x00,
LEVEL1_UNLOCKED = 0x01,
LEVEL2_UNLOCKED = 0x02
};
// 诊断响应结构体
struct DiagnosticResponse {
uint8_t serviceId;
std::vector data;
bool success;
std::string errorMessage;
DiagnosticResponse() : success(false) {}
};
// 会话管理器类
class UdsSessionManager {
public:
using TimerCallback = std::function;
UdsSessionManager();
~UdsSessionManager();
// 核心服务处理
DiagnosticResponse handleDiagnosticSessionControl(const std::vector& request);
DiagnosticResponse handleTesterPresent(const std::vector& request);
DiagnosticResponse handleEcuReset(const std::vector& request);
// 服务访问权限检查
bool isServiceAllowedInCurrentSession(ServiceId serviceId) const;
// 状态查询
DiagnosticSession getCurrentSession() const { return currentSession_; }
SecurityLevel getSecurityLevel() const { return securityLevel_; }
bool isSessionTimedOut() const;
// 定时器管理
void updateSessionActivity();
void setS3ServerTimeout(uint32_t milliseconds);
// 非易失性数据管理(模拟)
void setVin(const std::vector& vin);
std::vector getVin() const;private:
// 会话状态
DiagnosticSession currentSession_;
SecurityLevel securityLevel_;
// 定时器相关
uint32_t s3ServerTimeoutMs_; // S3server超时时间(默认5000ms)
std::chrono::steady_clock::time_point lastDiagnosticActivity_;
// 持久化数据(不会因会话切换而重置)
std::vector vin_; // VIN码 (2E F1 90)
// 会话相关状态(会话切换时可能重置)
bool responseOnEventActive_; // 0x86服务激活状态
bool communicationControlActive_; // 0x28服务激活状态
bool dtcControlActive_; // 0x85服务激活状态
// 服务权限映射表
std::map std :: vector > sessionAllowedServices_;
// 跳转规则验证
bool canTransitionTo(DiagnosticSession target) const ;
// 会话初始化/重置
void initializeSession(DiagnosticSession session, bool isTransition) ;
void resetSessionRelatedStates() ;
void lockSecurity() ;
// 响应构造
DiagnosticResponse buildPositiveResponse(uint8_t serviceId,
const std::vector& data) ;
DiagnosticResponse buildNegativeResponse(uint8_t serviceId,
uint8_t negativeCode) ;
// 定时器检查线程
void startSessionTimeoutMonitor() ;
void stopSessionTimeoutMonitor() ;
void sessionTimeoutHandler() ;
std :: unique_ptr < std ::thread> timeoutMonitorThread_;
bool monitorRunning_;
};
} // namespace Uds
#endif // UDS_SESSION_MANAGER_H
3.3 使用示例// UdsSessionManager.cpp
#include "UdsSessionManager.h"
#include
#include
#include
#include
#include
namespace Uds {
// NRC (Negative Response Code) 定义
namespace NRC {
constexpr uint8_t GENERAL_REJECT = 0x10;
constexpr uint8_t SERVICE_NOT_SUPPORTED = 0x11;
constexpr uint8_t SUBFUNCTION_NOT_SUPPORTED = 0x12;
constexpr uint8_t INCORRECT_MESSAGE_LENGTH = 0x13;
constexpr uint8_t CONDITIONS_NOT_CORRECT = 0x22;
constexpr uint8_t REQUEST_SEQUENCE_ERROR = 0x24;
constexpr uint8_t SECURITY_ACCESS_DENIED = 0x33;
}
UdsSessionManager::UdsSessionManager()
: currentSession_(DiagnosticSession::DEFAULT_SESSION)
, securityLevel_(SecurityLevel::LOCKED)
, s3ServerTimeoutMs_(5000) // 默认5秒
, lastDiagnosticActivity_(std::chrono::steady_clock::now())
, responseOnEventActive_(false)
, communicationControlActive_(false)
, dtcControlActive_(false)
, monitorRunning_(true)
{
// 初始化各会话允许的服务列表
// Default Session - 仅基础诊断
sessionAllowedServices_[DiagnosticSession::DEFAULT_SESSION] = {
ServiceId::DIAGNOSTIC_SESSION_CONTROL,
ServiceId::ECU_RESET,
ServiceId::READ_DATA_BY_ID,
ServiceId::READ_DTC_INFO,
ServiceId::TESTER_PRESENT
};
// Extended Session - 高级诊断服务
sessionAllowedServices_[DiagnosticSession::EXTENDED_SESSION] = {
ServiceId::DIAGNOSTIC_SESSION_CONTROL,
ServiceId::ECU_RESET,
ServiceId::READ_DATA_BY_ID,
ServiceId::SECURITY_ACCESS,
ServiceId::COMMUNICATION_CONTROL,
ServiceId::READ_DTC_INFO,
ServiceId::WRITE_DATA_BY_ID,
ServiceId::ROUTINE_CONTROL,
ServiceId::TESTER_PRESENT
};
// Programming Session - Bootloader相关服务
sessionAllowedServices_[DiagnosticSession::PROGRAMMING_SESSION] = {
ServiceId::DIAGNOSTIC_SESSION_CONTROL,
ServiceId::ECU_RESET,
ServiceId::REQUEST_DOWNLOAD,
ServiceId::TRANSFER_DATA,
ServiceId::REQUEST_TRANSFER_EXIT,
ServiceId::TESTER_PRESENT
};
// 启动超时监控线程
startSessionTimeoutMonitor();
}
UdsSessionManager::~UdsSessionManager() {
monitorRunning_ = false;
if (timeoutMonitorThread_ && timeoutMonitorThread_->joinable()) {
timeoutMonitorThread_->join();
}
}
//=============================================================================
// 核心服务: 0x10 诊断会话控制
//=============================================================================
DiagnosticResponse UdsSessionManager::handleDiagnosticSessionControl(
const std::vector& request)
{
DiagnosticResponse response;
// 1. 长度检查: 至少2字节 [SID, SubFunction]
if (request.size() < 2) {
return buildNegativeResponse(static_cast(ServiceId::DIAGNOSTIC_SESSION_CONTROL),
NRC::INCORRECT_MESSAGE_LENGTH);
}
uint8_t subFunction = request[1];
// 2. 子功能有效性检查
DiagnosticSession targetSession;
switch (subFunction) {
case 0x01: targetSession = DiagnosticSession::DEFAULT_SESSION; break;
case 0x02: targetSession = DiagnosticSession::PROGRAMMING_SESSION; break;
case 0x03: targetSession = DiagnosticSession::EXTENDED_SESSION; break;
default:
return buildNegativeResponse(static_cast(ServiceId::DIAGNOSTIC_SESSION_CONTROL),
NRC::SUBFUNCTION_NOT_SUPPORTED);
}
// 3. 跳转规则检查
if (!canTransitionTo(targetSession)) {
return buildNegativeResponse(static_cast(ServiceId::DIAGNOSTIC_SESSION_CONTROL),
NRC::CONDITIONS_NOT_CORRECT);
}
// 4. 记录旧会话用于特殊处理
DiagnosticSession oldSession = currentSession_;
// 5. 执行会话切换
initializeSession(targetSession, true); // true表示这是跳转切换
// 6. 构造肯定响应
std::vector responseData;
responseData.push_back(static_cast(targetSession));
// 可选: 添加P2/P2*定时参数(根据具体实现)
responseData.push_back(0x00); // P2 = 0ms (使用默认)
responseData.push_back(0x00); // P2* = 0ms
response = buildPositiveResponse(
static_cast(ServiceId::DIAGNOSTIC_SESSION_CONTROL),
responseData);
// 打印日志
std::cout << "[UDS] Session transition: "
<< static_cast(oldSession) << " -> "
<< static_cast(targetSession) << std::endl;
return response;
}
//=============================================================================
// 核心服务: 0x3E 保活服务
//=============================================================================
DiagnosticResponse UdsSessionManager::handleTesterPresent(
const std::vector& request)
{
DiagnosticResponse response;
// 非默认会话需要持续接收3E来维持
updateSessionActivity();
// 标准响应: 7E 00
if (request.size() >= 2 && request[1] == 0x00) {
response = buildPositiveResponse(
static_cast(ServiceId::TESTER_PRESENT),
{0x00});
} else {
response = buildPositiveResponse(
static_cast(ServiceId::TESTER_PRESENT),
{});
}
return response;
}
//=============================================================================
// 核心服务: 0x11 ECU复位
//=============================================================================
DiagnosticResponse UdsSessionManager::handleEcuReset(
const std::vector& request)
{
DiagnosticResponse response;
if (request.size() < 2) {
return buildNegativeResponse(static_cast(ServiceId::ECU_RESET),
NRC::INCORRECT_MESSAGE_LENGTH);
}
uint8_t resetType = request[1];
// 硬复位(0x01)或软复位(0x03)后回到默认会话
if (resetType == 0x01 || resetType == 0x03) {
// 重置会话状态
initializeSession(DiagnosticSession::DEFAULT_SESSION, true);
response = buildPositiveResponse(
static_cast(ServiceId::ECU_RESET),
{resetType});
std::cout << "[UDS] ECU Reset (type " << static_cast(resetType)
<< "), session reset to Default" << std::endl;
} else {
response = buildNegativeResponse(static_cast(ServiceId::ECU_RESET),
NRC::SUBFUNCTION_NOT_SUPPORTED);
}
return response;
}
//=============================================================================
// 权限检查: 当前会话是否允许指定服务
//=============================================================================
bool UdsSessionManager::isServiceAllowedInCurrentSession(ServiceId serviceId) const
{
auto it = sessionAllowedServices_.find(currentSession_);
if (it == sessionAllowedServices_.end()) {
return false;
}
const auto& allowedServices = it->second;
return std::find(allowedServices.begin(), allowedServices.end(), serviceId)
!= allowedServices.end();
}
//=============================================================================
// 会话跳转规则验证
//=============================================================================
bool UdsSessionManager::canTransitionTo(DiagnosticSession target) const
{
// 规则1: 相同会话总是允许
if (currentSession_ == target) {
return true;
}
// 规则2: 任何会话都可以回到Default
if (target == DiagnosticSession::DEFAULT_SESSION) {
return true;
}
// 规则3: Default不能直接跳转到Programming
if (currentSession_ == DiagnosticSession::DEFAULT_SESSION &&
target == DiagnosticSession::PROGRAMMING_SESSION) {
return false;
}
// 规则4: Programming不能跳转到Extended
if (currentSession_ == DiagnosticSession::PROGRAMMING_SESSION &&
target == DiagnosticSession::EXTENDED_SESSION) {
return false;
}
// 规则5: Extended可以跳转到Programming
// 规则6: Default可以跳转到Extended
return true;
}
//=============================================================================
// 会话初始化
//=============================================================================
void UdsSessionManager::initializeSession(DiagnosticSession session, bool isTransition)
{
DiagnosticSession oldSession = currentSession_;
currentSession_ = session;
// 更新活动时间戳
updateSessionActivity();
if (!isTransition) {
// 首次启动初始化
return;
}
// --- 根据ISO 14229定义的跳转规则处理 ---
// 3.1 从Default到Default: 重置所有会话相关设置
if (oldSession == DiagnosticSession::DEFAULT_SESSION &&
session == DiagnosticSession::DEFAULT_SESSION) {
resetSessionRelatedStates();
// 注意: 非易失性存储器内容(如VIN)保持不变
return;
}
// 3.2 从Default到非Default: 停止ResponseOnEvent
if (oldSession == DiagnosticSession::DEFAULT_SESSION &&
session != DiagnosticSession::DEFAULT_SESSION) {
responseOnEventActive_ = false;
// 其他状态保持
return;
}
// 3.3 从非Default到非Default: 重新锁定安全访问
if (oldSession != DiagnosticSession::DEFAULT_SESSION &&
session != DiagnosticSession::DEFAULT_SESSION) {
// 安全访问重新锁定
lockSecurity();
// 停止ResponseOnEvent
responseOnEventActive_ = false;
// CommunicationControl和ControlDTCSetting状态保持
// (communicationControlActive_, dtcControlActive_ 不重置)
return;
}
// 3.4 从非Default到Default: 重置所有会话相关设置
if (oldSession != DiagnosticSession::DEFAULT_SESSION &&
session == DiagnosticSession::DEFAULT_SESSION) {
resetSessionRelatedStates();
lockSecurity();
// 禁用所有非默认会话特有的功能
communicationControlActive_ = false;
dtcControlActive_ = false;
return;
}
}
//=============================================================================
// 重置会话相关状态(不重置非易失性数据)
//=============================================================================
void UdsSessionManager::resetSessionRelatedStates()
{
responseOnEventActive_ = false;
// 周期性调度器等被禁用
// 所有OutputControl被禁用
}
//=============================================================================
// 锁定安全访问
//=============================================================================
void UdsSessionManager::lockSecurity()
{
securityLevel_ = SecurityLevel::LOCKED;
std::cout << "[UDS] Security locked" << std::endl;
}
//=============================================================================
// 超时管理
//=============================================================================
void UdsSessionManager::updateSessionActivity()
{
lastDiagnosticActivity_ = std::chrono::steady_clock::now();
}
bool UdsSessionManager::isSessionTimedOut() const
{
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast(
now - lastDiagnosticActivity_);
return elapsed.count() > s3ServerTimeoutMs_;
}
void UdsSessionManager::setS3ServerTimeout(uint32_t milliseconds)
{
s3ServerTimeoutMs_ = milliseconds;
}
void UdsSessionManager::startSessionTimeoutMonitor()
{
timeoutMonitorThread_ = std::make_unique([this]() {
while (monitorRunning_) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
// 仅在非默认会话时检查超时
if (currentSession_ != DiagnosticSession::DEFAULT_SESSION) {
if (isSessionTimedOut()) {
std::cout << "[UDS] Session timeout! Switching to Default" << std::endl;
initializeSession(DiagnosticSession::DEFAULT_SESSION, true);
}
}
}
});
}
//=============================================================================
// 非易失性数据管理
//=============================================================================
void UdsSessionManager::setVin(const std::vector& vin)
{
vin_ = vin;
std::cout << "[UDS] VIN written to non-volatile memory" << std::endl;
}
std::vector UdsSessionManager::getVin() const
{
return vin_;
}
//=============================================================================
// 响应构造
//=============================================================================
DiagnosticResponse UdsSessionManager::buildPositiveResponse(
uint8_t serviceId, const std::vector& data)
{
DiagnosticResponse resp;
resp.serviceId = serviceId | 0x40; // 肯定响应SID = 请求SID + 0x40
resp.data = data;
resp.success = true;
return resp;
}
DiagnosticResponse UdsSessionManager::buildNegativeResponse(
uint8_t serviceId, uint8_t negativeCode)
{
DiagnosticResponse resp;
resp.serviceId = 0x7F; // 否定响应SID
resp.data = {serviceId, negativeCode};
resp.success = false;
std::stringstream ss;
ss << "NRC: 0x" << std::hex << static_cast(negativeCode);
resp.errorMessage = ss.str();
return resp;
}} // namespace Uds
3.4 编译与运行// main.cpp - 演示UDS 0x10服务的使用
#include "UdsSessionManager.h"
#include
#include
using namespace Uds;
void printResponse(const DiagnosticResponse& resp, const std::string& context)
{
std::cout << "\n=== " << context << " ===" << std::endl;
std::cout << "SID: 0x" << std::hex << static_cast(resp.serviceId) << std::endl;
if (!resp.data.empty()) {
std::cout << "Data: ";
for (uint8_t byte : resp.data) {
std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0')
<< static_cast(byte) << " ";
}
std::cout << std::endl;
}
if (resp.success) {
std::cout << "Status: SUCCESS" << std::endl;
} else {
std::cout << "Status: FAILED - " << resp.errorMessage << std::endl;
}
}int main()
{
UdsSessionManager ecu;
std::cout << "========== UDS 0x10 Diagnostic Session Control Demo ==========" << std::endl;
// 1. 查询初始状态
std::cout << "\n[Initial] Session: "
<< static_cast(ecu.getCurrentSession())
<< " (Default)" << std::endl;
// 2. Default -> Extended (合法)
auto resp1 = ecu.handleDiagnosticSessionControl({0x10, 0x03});
printResponse(resp1, "Default -> Extended (10 03)");
// 验证服务权限
std::cout << "2E (WriteData) allowed in Extended? "
<< ecu.isServiceAllowedInCurrentSession(ServiceId::WRITE_DATA_BY_ID)
<< std::endl;
// 3. Extended -> Programming (合法)
auto resp2 = ecu.handleDiagnosticSessionControl({0x10, 0x02});
printResponse(resp2, "Extended -> Programming (10 02)");
// 验证编程服务权限
std::cout << "34 (RequestDownload) allowed in Programming? "
<< ecu.isServiceAllowedInCurrentSession(ServiceId::REQUEST_DOWNLOAD)
<< std::endl;
std::cout << "2E (WriteData) allowed in Programming? "
<< ecu.isServiceAllowedInCurrentSession(ServiceId::WRITE_DATA_BY_ID)
<< std::endl;
// 4. Programming -> Extended (非法 - 应被拒绝)
auto resp3 = ecu.handleDiagnosticSessionControl({0x10, 0x03});
printResponse(resp3, "Programming -> Extended (10 03) [SHOULD FAIL]");
// 5. Programming -> Default (合法)
auto resp4 = ecu.handleDiagnosticSessionControl({0x10, 0x01});
printResponse(resp4, "Programming -> Default (10 01)");
// 6. Default -> Programming (非法 - 必须经过Extended)
auto resp5 = ecu.handleDiagnosticSessionControl({0x10, 0x02});
printResponse(resp5, "Default -> Programming (10 02) [SHOULD FAIL]");
// 7. 重新进入Extended,演示3E保活
ecu.handleDiagnosticSessionControl({0x10, 0x03});
std::cout << "\n[Extended Session Active] Sending TesterPresent..." << std::endl;
for (int i = 0; i < 3; i++) {
auto resp6 = ecu.handleTesterPresent({0x3E, 0x00});
std::cout << "3E #" << (i+1) << " response: 0x" << std::hex
<< static_cast(resp6.serviceId) << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// 8. 模拟超时(设置短超时用于演示)
ecu.setS3ServerTimeout(2000); // 2秒超时
std::cout << "\n[Timeout Demo] Waiting 3 seconds without diagnostic request..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "Session after timeout: "
<< static_cast(ecu.getCurrentSession())
<< " (should be Default)" << std::endl;
// 9. 演示非易失性数据持久化
std::cout << "\n[Persistence Demo] Writing VIN to NVM..." << std::endl;
ecu.setVin({'W','V','W','Z','Z','Z','1','Z','Z','1','2','3','4','5','6','7','8'});
// 切换到不同会话再回来
ecu.handleDiagnosticSessionControl({0x10, 0x03});
ecu.handleDiagnosticSessionControl({0x10, 0x01});
auto vin = ecu.getVin();
std::cout << "VIN after session cycle: ";
for (uint8_t c : vin) std::cout << static_cast(c);
std::cout << " (preserved!)" << std::endl;
return 0;
}
四、关键要点总结# 编译命令
g++ -std=c++17 -pthread UdsSessionManager.cpp main.cpp -o uds_demo# 运行
./uds_demo
要点
安全机制
高权限服务需要先切换到对应会话并完成安全解锁
跳转路径
Default → Extended → Programming(单向)
超时保活
非默认会话需周期性发送3E,否则自动切回Default
安全锁定
会话切换时安全访问状态会被重置(除非规则明确要求保持)
状态保持
CommunicationControl和ControlDTCSetting在非默认会话间切换时保持
持久化
NVM写入的数据(如VIN)不受会话切换影响
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.