基线:UDP 收包长度校验 + SQLite 表描述符重构 + 清理设计文档
This commit is contained in:
@@ -1,128 +0,0 @@
|
||||
# PowerManager系统架构优化设计方案
|
||||
|
||||
## 1. 总体架构
|
||||
```mermaid
|
||||
classDiagram
|
||||
class PowerManagerCore {
|
||||
+startup()
|
||||
+shutdown()
|
||||
+getSystemState()
|
||||
}
|
||||
|
||||
class StateMachineService {
|
||||
+triggerEvent()
|
||||
+getCurrentState()
|
||||
+addStateListener()
|
||||
}
|
||||
|
||||
class CommunicationMediator {
|
||||
+registerHandler()
|
||||
+sendMessage()
|
||||
+addMessageListener()
|
||||
}
|
||||
|
||||
PowerManagerCore --> StateMachineService
|
||||
PowerManagerCore --> CommunicationMediator
|
||||
```
|
||||
|
||||
## 2. 状态机重构方案
|
||||
|
||||
### 2.1 状态设计模式
|
||||
```cpp
|
||||
class IPowerState {
|
||||
public:
|
||||
virtual void onEntry(PowerContext&) = 0;
|
||||
virtual void handleEvent(PowerContext&, const Event&) = 0;
|
||||
virtual void onExit(PowerContext&) = 0;
|
||||
};
|
||||
```
|
||||
|
||||
### 2.2 状态转换规则
|
||||
```yaml
|
||||
# states_config.yaml
|
||||
transitions:
|
||||
- from: STANDBY
|
||||
event: START_CMD
|
||||
to: OPERATING
|
||||
- from: OPERATING
|
||||
event: STOP_CMD
|
||||
to: STANDBY
|
||||
```
|
||||
|
||||
## 3. 通信中介者设计
|
||||
|
||||
### 3.1 核心架构
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Upper as 上位机
|
||||
participant Mediator as 通信中介者
|
||||
participant Lower as 下位机
|
||||
|
||||
Upper->>Mediator: 控制命令(JSON)
|
||||
Mediator->>Lower: 设备指令(ProtocolBuffer)
|
||||
Lower->>Mediator: 状态更新
|
||||
Mediator->>Upper: 系统报告
|
||||
```
|
||||
|
||||
### 3.2 关键实现
|
||||
```cpp
|
||||
class CommunicationMediator {
|
||||
// 线程安全消息队列
|
||||
moodycamel::ConcurrentQueue<Message> queue;
|
||||
|
||||
// 消息处理线程
|
||||
void processMessages() {
|
||||
while (running) {
|
||||
Message msg;
|
||||
if (queue.try_dequeue(msg)) {
|
||||
handlers[msg.type]->handle(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 4. 数据库服务设计
|
||||
|
||||
### 4.1 日志策略模式
|
||||
```cpp
|
||||
class ILogStrategy {
|
||||
public:
|
||||
virtual bool log(const SystemLog& log) = 0;
|
||||
};
|
||||
|
||||
class SQLiteLogStrategy : public ILogStrategy {
|
||||
// SQLite实现...
|
||||
};
|
||||
|
||||
class FileLogStrategy : public ILogStrategy {
|
||||
// 文件系统实现...
|
||||
};
|
||||
```
|
||||
|
||||
## 5. 实施计划
|
||||
|
||||
### 5.1 阶段划分
|
||||
```mermaid
|
||||
gantt
|
||||
title 重构实施甘特图
|
||||
section 核心框架
|
||||
接口定义 :2025-04-08, 3d
|
||||
基础实现 :2025-04-11, 5d
|
||||
|
||||
section 模块重构
|
||||
状态机 :2025-04-16, 5d
|
||||
通信模块 :2025-04-21, 5d
|
||||
|
||||
section 测试验证
|
||||
单元测试 :2025-04-26, 3d
|
||||
集成测试 :2025-04-29, 5d
|
||||
```
|
||||
|
||||
## 6. 性能指标
|
||||
|
||||
| 模块 | 当前QPS | 目标QPS | 优化手段 |
|
||||
|----------------|---------|---------|-----------------------|
|
||||
| 状态机处理 | 100 | 500 | 无锁状态转换 |
|
||||
| 消息处理 | 200 | 1000 | 批量处理+线程池 |
|
||||
| 数据库写入 | 50 | 300 | 异步写入+批量提交 |
|
||||
@@ -1,277 +0,0 @@
|
||||
# 上位机控制程序设计文档
|
||||
|
||||
## 1. 程序架构设计
|
||||
|
||||
采用MVC模式设计,主要分为以下模块:
|
||||
|
||||
### 1.0 系统架构图
|
||||
```mermaid
|
||||
graph TD
|
||||
A[用户界面] -->|控制指令| B[控制器]
|
||||
B -->|发送命令| C[通信模块]
|
||||
C -->|UDP协议| D[下位机]
|
||||
D -->|状态反馈| C
|
||||
C -->|解析数据| B
|
||||
B -->|更新状态| A
|
||||
B -->|记录数据| E[数据库]
|
||||
```
|
||||
|
||||
### 1.1 消息处理流程
|
||||
1. 接收原始UDP数据
|
||||
2. 根据消息ID选择解析器
|
||||
3. 验证校验码
|
||||
4. 解析为结构化数据
|
||||
5. 触发状态更新事件
|
||||
6. 存储到数据库
|
||||
|
||||
### 1.1 通信模块 (Model) - 详细设计
|
||||
|
||||
#### 消息类型映射表
|
||||
| 消息ID | 消息名称 | 处理函数 | 更新频率 |
|
||||
|--------|----------|----------|----------|
|
||||
| 0x0005 | 高压母线状态 | parse_high_vol_bus | 1Hz |
|
||||
| 0x0006 | 高压A母线状态 | parse_high_a_vol_bus | 1Hz |
|
||||
| 0x0007 | 低压主母线状态 | parse_low_main_bus | 1Hz |
|
||||
| 0x0008 | 低压汇流排状态 | parse_low_bus | 1Hz |
|
||||
|
||||
#### 异常处理机制
|
||||
1. 校验失败:丢弃数据并记录错误日志
|
||||
2. 超时处理:3次重试后标记设备离线
|
||||
3. 数据异常:触发告警并显示在界面
|
||||
```python
|
||||
class UDPMessageHandler:
|
||||
"""UDP消息处理基类"""
|
||||
def __init__(self, ip, port):
|
||||
self.ip = ip
|
||||
self.port = port
|
||||
self.socket = None
|
||||
|
||||
def connect(self):
|
||||
"""建立UDP连接"""
|
||||
pass
|
||||
|
||||
def send_message(self, msg):
|
||||
"""发送消息"""
|
||||
pass
|
||||
|
||||
def receive_message(self):
|
||||
"""接收消息"""
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
"""关闭连接"""
|
||||
pass
|
||||
|
||||
class PowerMessageHandler(UDPMessageHandler):
|
||||
"""电源管理专用消息处理器"""
|
||||
def __init__(self, ip, port):
|
||||
super().__init__(ip, port)
|
||||
self.message_parsers = {
|
||||
0x0005: self.parse_high_vol_bus,
|
||||
0x0006: self.parse_high_a_vol_bus,
|
||||
# 其他消息类型...
|
||||
}
|
||||
|
||||
def parse_high_vol_bus(self, data):
|
||||
"""解析高压母线消息"""
|
||||
pass
|
||||
|
||||
# 其他消息解析方法...
|
||||
```
|
||||
|
||||
### 1.2 界面模块 (View) - 详细设计
|
||||
|
||||
#### 主界面布局
|
||||
```mermaid
|
||||
graph LR
|
||||
A[标题栏] --> B[状态区]
|
||||
B --> C[电压电流仪表盘]
|
||||
B --> D[断路器状态指示灯]
|
||||
A --> E[控制区]
|
||||
E --> F[电源控制按钮组]
|
||||
E --> G[参数设置面板]
|
||||
A --> H[日志区]
|
||||
H --> I[实时消息列表]
|
||||
H --> J[历史记录查询]
|
||||
```
|
||||
|
||||
#### 组件说明
|
||||
1. 电压电流仪表盘:实时显示各母线电压电流值
|
||||
2. 断路器状态指示灯:绿色-闭合,红色-断开
|
||||
3. 电源控制按钮组:带防误触保护(需长按3秒)
|
||||
4. 参数设置面板:输入验证和范围检查
|
||||
```python
|
||||
class MainWindow(tk.Tk):
|
||||
"""主窗口"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.title("电源管理系统")
|
||||
self.geometry("1200x800")
|
||||
|
||||
self.create_widgets()
|
||||
|
||||
def create_widgets(self):
|
||||
"""创建界面组件"""
|
||||
self.status_frame = StatusFrame(self)
|
||||
self.control_frame = ControlFrame(self)
|
||||
self.log_frame = LogFrame(self)
|
||||
|
||||
# 布局管理
|
||||
self.status_frame.pack(side=tk.TOP, fill=tk.X)
|
||||
self.control_frame.pack(side=tk.LEFT, fill=tk.Y)
|
||||
self.log_frame.pack(side=tk.RIGHT, expand=True, fill=tk.BOTH)
|
||||
|
||||
class StatusFrame(tk.Frame):
|
||||
"""状态显示面板"""
|
||||
def update_status(self, data):
|
||||
"""更新状态显示"""
|
||||
pass
|
||||
|
||||
class ControlFrame(tk.Frame):
|
||||
"""控制面板"""
|
||||
def create_buttons(self):
|
||||
"""创建控制按钮"""
|
||||
pass
|
||||
```
|
||||
|
||||
### 1.3 控制器模块 (Controller) - 详细设计
|
||||
|
||||
#### 状态管理机制
|
||||
1. 使用有限状态机(FSM)管理电源系统状态
|
||||
2. 状态转换规则:
|
||||
- 仅当所有预检通过才允许上电
|
||||
- 故障时自动进入安全状态
|
||||
- 人工确认后才能复位
|
||||
|
||||
#### 命令处理流程
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
用户->>界面: 点击控制按钮
|
||||
界面->>控制器: 发送控制命令
|
||||
控制器->>业务逻辑: 验证命令有效性
|
||||
业务逻辑->>通信模块: 发送UDP指令
|
||||
通信模块->>下位机: 传输控制报文
|
||||
下位机-->>通信模块: 返回应答
|
||||
通信模块->>控制器: 更新命令状态
|
||||
控制器->>界面: 显示操作结果
|
||||
控制器->>数据库: 记录操作日志
|
||||
```
|
||||
```python
|
||||
class PowerManagerController:
|
||||
"""主控制器"""
|
||||
def __init__(self):
|
||||
self.message_handler = PowerMessageHandler("192.168.1.100", 5000)
|
||||
self.view = MainWindow()
|
||||
|
||||
# 绑定事件
|
||||
self.bind_events()
|
||||
|
||||
def bind_events(self):
|
||||
"""绑定UI事件"""
|
||||
self.view.control_frame.on_button_click = self.handle_control_command
|
||||
|
||||
def handle_control_command(self, cmd):
|
||||
"""处理控制命令"""
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
"""启动应用程序"""
|
||||
self.message_handler.connect()
|
||||
self.view.mainloop()
|
||||
```
|
||||
|
||||
## 2. 接口规范
|
||||
|
||||
### 2.1 模块交互架构
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Communication {
|
||||
+send_command(cmd: dict) bool
|
||||
+get_status() dict
|
||||
+subscribe(callback: function)
|
||||
+on_message_received(data: bytes)
|
||||
}
|
||||
|
||||
class Controller {
|
||||
+handle_ui_event(event: dict)
|
||||
+update_system_status(status: dict)
|
||||
+log_operation(log: dict)
|
||||
}
|
||||
|
||||
class UI {
|
||||
+update_status(data: dict)
|
||||
+show_alert(level: int, msg: str)
|
||||
+log_message(source: str, msg: str)
|
||||
}
|
||||
|
||||
Communication --> Controller : 状态更新通知
|
||||
Controller --> UI : 界面更新指令
|
||||
UI --> Controller : 用户操作事件
|
||||
```
|
||||
|
||||
### 2.2 详细接口定义
|
||||
|
||||
#### 通信模块 → 控制器
|
||||
```python
|
||||
# 状态更新通知
|
||||
{
|
||||
"msg_type": "status_update",
|
||||
"timestamp": "2025-05-04T10:20:00",
|
||||
"data": {
|
||||
"voltage": 220.5,
|
||||
"current": 15.2,
|
||||
"breaker_state": True
|
||||
}
|
||||
}
|
||||
|
||||
# 错误通知
|
||||
{
|
||||
"msg_type": "error",
|
||||
"code": 1001,
|
||||
"message": "校验失败"
|
||||
}
|
||||
```
|
||||
|
||||
#### 控制器 → 界面
|
||||
```python
|
||||
# 状态显示更新
|
||||
{
|
||||
"component": "voltage_meter",
|
||||
"value": 220.5,
|
||||
"unit": "V",
|
||||
"normal_range": [210, 230]
|
||||
}
|
||||
|
||||
# 告警信息
|
||||
{
|
||||
"level": 2, # 1-警告 2-错误 3-严重
|
||||
"message": "A相电压过高",
|
||||
"suggestion": "检查A相负载"
|
||||
}
|
||||
```
|
||||
|
||||
#### 界面 → 控制器
|
||||
```python
|
||||
# 按钮操作事件
|
||||
{
|
||||
"event_type": "button_click",
|
||||
"button_id": "power_on",
|
||||
"timestamp": "2025-05-04T10:20:01"
|
||||
}
|
||||
|
||||
# 参数设置事件
|
||||
{
|
||||
"event_type": "param_set",
|
||||
"param": "voltage_limit",
|
||||
"value": 230,
|
||||
"unit": "V"
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 错误处理规范
|
||||
1. 通信错误:自动重试3次后通知控制器
|
||||
2. 业务逻辑错误:记录详细日志并通知界面
|
||||
3. 界面错误:显示友好提示并保持最后正常状态
|
||||
|
||||
## 3. 数据库设计
|
||||
(之前已完成的数据库表结构...)
|
||||
@@ -342,12 +342,13 @@ bool LowerCommManager::listenThreadFunc()
|
||||
{
|
||||
try
|
||||
{
|
||||
memset(Buff, 0, sizeof(Buff));
|
||||
int nRead = m_udpComm->udpScoket->iRecieveMessage(Buff, sizeof(Buff));
|
||||
cout<<MOOS::ConsoleColours::yellow()<< "RECEVE DATA COUNT:" << nRead << MOOS::ConsoleColours::reset() << endl;
|
||||
if(nRead > 0)
|
||||
{
|
||||
try {
|
||||
if(m_udpComm->pushMsgToQueue(Buff))
|
||||
if(m_udpComm->pushMsgToQueue(Buff, nRead))
|
||||
{
|
||||
//更新当前状态
|
||||
if(!updatePoweSystemStates())
|
||||
|
||||
+352
-693
File diff suppressed because it is too large
Load Diff
@@ -66,12 +66,22 @@ private:
|
||||
bool createTableInternal(const std::string& tableName, const std::string& columns);
|
||||
bool createAllTablesUnlocked();
|
||||
|
||||
// 泛化插入:表名 + 列描述(名称 + 绑定器),所有类型共用这一条路径
|
||||
// 列描述:名称 + SQL 类型 + 绑定器(无捕获函数指针)
|
||||
struct Column {
|
||||
const char* name;
|
||||
const char* sqlType;
|
||||
void (*bind)(sqlite3_stmt*, int& idx, const void* obj);
|
||||
};
|
||||
bool insertGeneric(const std::string& table, const std::vector<Column>& cols, const void* obj);
|
||||
// 表描述:表名 + 数据列。建表(DDL)与插入(DML)共用这一份,作为唯一数据源。
|
||||
struct TableDesc {
|
||||
const char* name;
|
||||
std::vector<Column> columns;
|
||||
};
|
||||
|
||||
// 泛化插入:按表名在注册表中查找描述并绑定,所有类型共用这一条路径
|
||||
bool insertGeneric(const char* tableName, const void* obj);
|
||||
// 所有协议结构表的描述注册表(不含 msg_log 等特殊表)
|
||||
static const std::vector<TableDesc>& allTables();
|
||||
};
|
||||
|
||||
#endif // SQLITE_H
|
||||
|
||||
@@ -36,8 +36,11 @@ Checksum udpComm::calculateChecksum(const unsigned char* data, int dataSize, int
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
bool udpComm::getMsgId(char *m,unsigned short &id)
|
||||
bool udpComm::getMsgId(char *m, size_t len, unsigned short &id)
|
||||
{
|
||||
if (m == NULL || len < sizeof(m_header)) {
|
||||
return false;
|
||||
}
|
||||
m_header h;
|
||||
h = *reinterpret_cast<m_header *>(m);
|
||||
// 判断消息是否有效
|
||||
@@ -56,7 +59,11 @@ bool udpComm::getMsgId(char *m,unsigned short &id)
|
||||
// LOG_F(ERROR, "Msg Header errar start1: %d, start2: %d", h.start1, h.start2);
|
||||
return false;
|
||||
}
|
||||
bool udpComm::getMsgFromBuff(char *m, msg_CcuStateFbMsg &s) {
|
||||
bool udpComm::getMsgFromBuff(char *m, size_t len, msg_CcuStateFbMsg &s) {
|
||||
if (m == NULL || len < sizeof(msg_CcuStateFbMsg)) {
|
||||
sError.push_back("CcuStat Msg length error");
|
||||
return false;
|
||||
}
|
||||
Checksum sum;
|
||||
msg_CcuStateFbMsg *p;
|
||||
p = reinterpret_cast<msg_CcuStateFbMsg *>(m);
|
||||
@@ -69,8 +76,12 @@ bool udpComm::getMsgFromBuff(char *m, msg_CcuStateFbMsg &s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpComm::getMsgFromBuff(char *m, msg_CcuSetParmFbMsg &s)
|
||||
bool udpComm::getMsgFromBuff(char *m, size_t len, msg_CcuSetParmFbMsg &s)
|
||||
{
|
||||
if (m == NULL || len < sizeof(msg_CcuSetParmFbMsg)) {
|
||||
sError.push_back("CcuSetParm Msg length error");
|
||||
return false;
|
||||
}
|
||||
Checksum sum;
|
||||
msg_CcuSetParmFbMsg *p;
|
||||
p = reinterpret_cast<msg_CcuSetParmFbMsg *>(m);
|
||||
@@ -85,8 +96,12 @@ bool udpComm::getMsgFromBuff(char *m, msg_CcuSetParmFbMsg &s)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpComm::getMsgFromBuff(char *m, msg_disHighVolBusFbMsg &s)
|
||||
bool udpComm::getMsgFromBuff(char *m, size_t len, msg_disHighVolBusFbMsg &s)
|
||||
{
|
||||
if (m == NULL || len < sizeof(msg_disHighVolBusFbMsg)) {
|
||||
sError.push_back("DisSys HVBus Msg length error");
|
||||
return false;
|
||||
}
|
||||
cChecksum sum;
|
||||
msg_disHighVolBusFbMsg *p;
|
||||
p = reinterpret_cast<msg_disHighVolBusFbMsg *>(m);
|
||||
@@ -101,8 +116,12 @@ bool udpComm::getMsgFromBuff(char *m, msg_disHighVolBusFbMsg &s)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpComm::getMsgFromBuff(char *m, msg_disHighAVolBusFbMsg &s)
|
||||
bool udpComm::getMsgFromBuff(char *m, size_t len, msg_disHighAVolBusFbMsg &s)
|
||||
{
|
||||
if (m == NULL || len < sizeof(msg_disHighAVolBusFbMsg)) {
|
||||
sError.push_back("DisSys HVABus Msg length error");
|
||||
return false;
|
||||
}
|
||||
cChecksum sum;
|
||||
msg_disHighAVolBusFbMsg *p;
|
||||
p = reinterpret_cast<msg_disHighAVolBusFbMsg *>(m);
|
||||
@@ -115,8 +134,12 @@ bool udpComm::getMsgFromBuff(char *m, msg_disHighAVolBusFbMsg &s)
|
||||
s = *p;
|
||||
return true;
|
||||
}
|
||||
bool udpComm::getMsgFromBuff(char *m, msg_disLowMainBusFbMsg &s)
|
||||
bool udpComm::getMsgFromBuff(char *m, size_t len, msg_disLowMainBusFbMsg &s)
|
||||
{
|
||||
if (m == NULL || len < sizeof(msg_disLowMainBusFbMsg)) {
|
||||
sError.push_back("DisSys HVBBus Msg length error");
|
||||
return false;
|
||||
}
|
||||
cChecksum sum;
|
||||
msg_disLowMainBusFbMsg *p;
|
||||
p = reinterpret_cast<msg_disLowMainBusFbMsg *>(m);
|
||||
@@ -130,8 +153,12 @@ bool udpComm::getMsgFromBuff(char *m, msg_disLowMainBusFbMsg &s)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpComm::getMsgFromBuff(char *m, msg_disLowBusFbMsg &s)
|
||||
bool udpComm::getMsgFromBuff(char *m, size_t len, msg_disLowBusFbMsg &s)
|
||||
{
|
||||
if (m == NULL || len < sizeof(msg_disLowBusFbMsg)) {
|
||||
sError.push_back("DisSys LVBus Msg length error");
|
||||
return false;
|
||||
}
|
||||
cChecksum sum;
|
||||
msg_disLowBusFbMsg *p;
|
||||
p = reinterpret_cast<msg_disLowBusFbMsg *>(m);
|
||||
@@ -145,35 +172,29 @@ bool udpComm::getMsgFromBuff(char *m, msg_disLowBusFbMsg &s)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpComm::pushMsgToQueue(unsigned char *m)
|
||||
bool udpComm::pushMsgToQueue(unsigned char *m, size_t len)
|
||||
{
|
||||
if(m==NULL)
|
||||
if(m==NULL || len < sizeof(m_header))
|
||||
{
|
||||
// sError.push_back("pushMsgToQueue faile,Msg is NULL");
|
||||
LOG_F(ERROR, "pushMsgToQueue faile,Msg is NULL m: %p", m);
|
||||
LOG_F(ERROR, "pushMsgToQueue faile,Msg is NULL or too short m: %p len: %zu", m, len);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char* Buff = m;
|
||||
//消息头鉴定
|
||||
char *header = new char[sizeof(m_header)];
|
||||
unsigned short id;
|
||||
memcpy(header,Buff,sizeof(m_header));
|
||||
if(!getMsgId(header,id))
|
||||
if(!getMsgId((char *)Buff, len, id))
|
||||
{
|
||||
// sError.push_back("pushMsgToQueue faile,Msg ID error");
|
||||
// LOG_F(INFO, "pushMsgToQueue faile,Msg ID error header: %p", header);
|
||||
delete []header;
|
||||
return false;
|
||||
}
|
||||
delete []header;
|
||||
//输入消息
|
||||
switch (id)
|
||||
{
|
||||
case CCU_STATE_FB_ID: //CCU_STATE_FB 0x0051
|
||||
{
|
||||
msg_CcuStateFbMsg s;
|
||||
if(getMsgFromBuff((char *)Buff,s))
|
||||
if(getMsgFromBuff((char *)Buff, len, s))
|
||||
{
|
||||
if (m_commLogger) m_commLogger->onFrame(0, id, "ccuState", Buff, sizeof(msg_CcuStateFbMsg), true);
|
||||
std::lock_guard<std::mutex> lock(m_mutexCcuState);
|
||||
@@ -198,7 +219,7 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
|
||||
case CCU_SET_PARM_FB_ID: //CCU_SET_PARM_FB 0x0040
|
||||
{
|
||||
msg_CcuSetParmFbMsg s;
|
||||
if(getMsgFromBuff((char *)Buff,s))
|
||||
if(getMsgFromBuff((char *)Buff, len, s))
|
||||
{
|
||||
if (m_commLogger) m_commLogger->onFrame(0, id, "ccuSetParmFb", Buff, sizeof(msg_CcuSetParmFbMsg), true);
|
||||
std::lock_guard<std::mutex> lock(m_mutexCcuSetParm);
|
||||
@@ -223,7 +244,7 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
|
||||
case DIS_HVBUS_FB_ID: //DIS_HVBUS_FB 0x0020
|
||||
{
|
||||
msg_disHighVolBusFbMsg s;
|
||||
if(getMsgFromBuff((char *)Buff,s))
|
||||
if(getMsgFromBuff((char *)Buff, len, s))
|
||||
{
|
||||
if (m_commLogger) m_commLogger->onFrame(0, id, "disHighVolBusState", Buff, sizeof(msg_disHighVolBusFbMsg), true);
|
||||
std::lock_guard<std::mutex> lock(m_mutexDisHighVolBus);
|
||||
@@ -248,7 +269,7 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
|
||||
case DIS_HVBUSA_FB_ID: //DIS_HVBUSA_FB 0x0006
|
||||
{
|
||||
msg_disHighAVolBusFbMsg s;
|
||||
if(getMsgFromBuff((char *)Buff,s))
|
||||
if(getMsgFromBuff((char *)Buff, len, s))
|
||||
{
|
||||
if (m_commLogger) m_commLogger->onFrame(0, id, "disHighAVolBusState", Buff, sizeof(msg_disHighAVolBusFbMsg), true);
|
||||
std::lock_guard<std::mutex> lock(m_mutexDisHighAVolBus);
|
||||
@@ -273,7 +294,7 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
|
||||
case DIS_HVBUSB_FB_ID: //DIS_HVBUSB_FB 0x0007
|
||||
{
|
||||
msg_disLowMainBusFbMsg s;
|
||||
if(getMsgFromBuff((char *)Buff,s))
|
||||
if(getMsgFromBuff((char *)Buff, len, s))
|
||||
{
|
||||
if (m_commLogger) m_commLogger->onFrame(0, id, "disLowMainBusState", Buff, sizeof(msg_disLowMainBusFbMsg), true);
|
||||
std::lock_guard<std::mutex> lock(m_mutexDisHighBVolBus);
|
||||
@@ -298,7 +319,7 @@ bool udpComm::pushMsgToQueue(unsigned char *m)
|
||||
case DIS_LVBUS_FB_ID: //DIS_LVBUS_FB 0x0008
|
||||
{
|
||||
msg_disLowBusFbMsg s;
|
||||
if(getMsgFromBuff((char *)Buff,s))
|
||||
if(getMsgFromBuff((char *)Buff, len, s))
|
||||
{
|
||||
if (m_commLogger) m_commLogger->onFrame(0, id, "disLowBusState", Buff, sizeof(msg_disLowBusFbMsg), true);
|
||||
std::lock_guard<std::mutex> lock(m_mutexDisLowBus);
|
||||
|
||||
@@ -27,15 +27,15 @@ public:
|
||||
string ccuHost;
|
||||
long int ccuPort;
|
||||
|
||||
bool pushMsgToQueue(unsigned char *m);
|
||||
bool pushMsgToQueue(unsigned char *m, size_t len);
|
||||
bool clearMsgQueue();
|
||||
|
||||
bool getMsgFromBuff(char *m, msg_CcuStateFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, msg_CcuSetParmFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, msg_disHighVolBusFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, msg_disHighAVolBusFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, msg_disLowMainBusFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, msg_disLowBusFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, size_t len, msg_CcuStateFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, size_t len, msg_CcuSetParmFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, size_t len, msg_disHighVolBusFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, size_t len, msg_disHighAVolBusFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, size_t len, msg_disLowMainBusFbMsg &s);
|
||||
bool getMsgFromBuff(char *m, size_t len, msg_disLowBusFbMsg &s);
|
||||
|
||||
bool popMsgFormQueue(double &time,msg_CcuStateFbMsg &m);
|
||||
bool popMsgFormQueue(double &time,msg_CcuSetParmFbMsg &m);
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getMsgId(char *m,unsigned short &id);
|
||||
bool getMsgId(char *m, size_t len, unsigned short &id);
|
||||
Checksum calculateChecksum(const unsigned char* data, int size);
|
||||
Checksum calculateChecksum(const unsigned char* data, int dataSize, int checkSize);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ TEST(UdpCommTest, GetMsgId)
|
||||
h.start2 = DIS_MSG_HEAD2;
|
||||
h.id = DIS_HVBUS_FB_ID;
|
||||
memcpy(buf, &h, sizeof(h));
|
||||
EXPECT_TRUE(u.getMsgId(buf, id));
|
||||
EXPECT_TRUE(u.getMsgId(buf, sizeof(buf), id));
|
||||
EXPECT_EQ(id, DIS_HVBUS_FB_ID);
|
||||
|
||||
// CCU 头
|
||||
@@ -39,14 +39,18 @@ TEST(UdpCommTest, GetMsgId)
|
||||
h.start2 = CCU_UDPMSG_START2;
|
||||
h.id = CCU_STATE_FB_ID;
|
||||
memcpy(buf, &h, sizeof(h));
|
||||
EXPECT_TRUE(u.getMsgId(buf, id));
|
||||
EXPECT_TRUE(u.getMsgId(buf, sizeof(buf), id));
|
||||
EXPECT_EQ(id, CCU_STATE_FB_ID);
|
||||
|
||||
// 非法头
|
||||
h.start1 = 0x11;
|
||||
h.start2 = 0x22;
|
||||
memcpy(buf, &h, sizeof(h));
|
||||
EXPECT_FALSE(u.getMsgId(buf, id));
|
||||
EXPECT_FALSE(u.getMsgId(buf, sizeof(buf), id));
|
||||
|
||||
// 长度不足 m_header → 拒绝(不读越界)
|
||||
EXPECT_FALSE(u.getMsgId(buf, sizeof(m_header) - 1, id));
|
||||
EXPECT_FALSE(u.getMsgId(NULL, sizeof(m_header), id));
|
||||
}
|
||||
|
||||
TEST(UdpCommTest, GetMsgFromBuffCcu)
|
||||
@@ -63,14 +67,34 @@ TEST(UdpCommTest, GetMsgFromBuffCcu)
|
||||
m.checkCode = u.calculateChecksum((unsigned char*)&m, sizeof(m));
|
||||
|
||||
msg_CcuStateFbMsg out{};
|
||||
EXPECT_TRUE(u.getMsgFromBuff((char*)&m, out));
|
||||
EXPECT_TRUE(u.getMsgFromBuff((char*)&m, sizeof(m), out));
|
||||
EXPECT_EQ(out.data.ins_soc, 42u);
|
||||
EXPECT_EQ(out.data.dyn_soc, 66u);
|
||||
EXPECT_EQ(out.data.fc_status, 0x04u);
|
||||
|
||||
// 篡改数据 → 校验失败
|
||||
m.data.dyn_soc = 99;
|
||||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, out));
|
||||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, sizeof(m), out));
|
||||
|
||||
// 截断帧(长度不足)→ 拒绝,不写输出
|
||||
m.data.dyn_soc = 66;
|
||||
m.checkCode = u.calculateChecksum((unsigned char*)&m, sizeof(m));
|
||||
msg_CcuStateFbMsg untouched{};
|
||||
untouched.data.ins_soc = 0xEE;
|
||||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, sizeof(m) - 1, untouched));
|
||||
EXPECT_EQ(untouched.data.ins_soc, 0xEEu);
|
||||
|
||||
// 超长帧(长度超出)→ 接受,忽略尾字节
|
||||
unsigned char longBuf[sizeof(m) + 16];
|
||||
memset(longBuf, 0, sizeof(longBuf));
|
||||
memcpy(longBuf, &m, sizeof(m));
|
||||
msg_CcuStateFbMsg outLong{};
|
||||
EXPECT_TRUE(u.getMsgFromBuff((char*)longBuf, sizeof(longBuf), outLong));
|
||||
EXPECT_EQ(outLong.data.ins_soc, 42u);
|
||||
|
||||
// 空指针 / 长度不足 → 拒绝
|
||||
EXPECT_FALSE(u.getMsgFromBuff(NULL, sizeof(m), out));
|
||||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, 0, out));
|
||||
}
|
||||
|
||||
TEST(UdpCommTest, GetMsgFromBuffDis)
|
||||
@@ -86,13 +110,50 @@ TEST(UdpCommTest, GetMsgFromBuffDis)
|
||||
m.checkCode = (cChecksum)(u.calculateChecksum((unsigned char*)&m, sizeof(m), sizeof(cChecksum)) & 0xFF);
|
||||
|
||||
msg_disHighVolBusFbMsg out{};
|
||||
EXPECT_TRUE(u.getMsgFromBuff((char*)&m, out));
|
||||
EXPECT_TRUE(u.getMsgFromBuff((char*)&m, sizeof(m), out));
|
||||
EXPECT_EQ(out.data.fuelCellCircuitBreaker, 0x55u);
|
||||
EXPECT_EQ(out.data.powerBusVoltage, 5200u);
|
||||
|
||||
// 篡改 → 校验失败
|
||||
m.data.fuelCellCircuitBreaker = 0xAA;
|
||||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, out));
|
||||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, sizeof(m), out));
|
||||
|
||||
// 截断帧 → 拒绝
|
||||
m.data.fuelCellCircuitBreaker = 0x55;
|
||||
m.checkCode = (cChecksum)(u.calculateChecksum((unsigned char*)&m, sizeof(m), sizeof(cChecksum)) & 0xFF);
|
||||
EXPECT_FALSE(u.getMsgFromBuff((char*)&m, sizeof(m) - 1, out));
|
||||
}
|
||||
|
||||
TEST(UdpCommTest, PushMsgToQueueLengthGuard)
|
||||
{
|
||||
udpComm u;
|
||||
msg_CcuStateFbMsg m;
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.header.start1 = CCU_UDPMSG_START1;
|
||||
m.header.start2 = CCU_UDPMSG_START2;
|
||||
m.header.id = CCU_STATE_FB_ID;
|
||||
m.data.ins_soc = 42;
|
||||
m.checkCode = u.calculateChecksum((unsigned char*)&m, sizeof(m));
|
||||
|
||||
// 合法帧入队成功
|
||||
EXPECT_TRUE(u.pushMsgToQueue((unsigned char*)&m, sizeof(m)));
|
||||
EXPECT_EQ(u.m_qReceiveCcuStateBuffer.size(), 1u);
|
||||
EXPECT_EQ(u.m_qReceiveCcuStateBuffer.front().second.data.ins_soc, 42u);
|
||||
|
||||
// 空指针 / 长度不足 m_header → 拒绝
|
||||
EXPECT_FALSE(u.pushMsgToQueue(NULL, sizeof(m)));
|
||||
EXPECT_FALSE(u.pushMsgToQueue((unsigned char*)&m, sizeof(m_header) - 1));
|
||||
|
||||
// 截断帧(合法头 + 校验和,但长度不足整包)→ 拒绝入队
|
||||
msg_CcuStateFbMsg shortM;
|
||||
memset(&shortM, 0, sizeof(shortM));
|
||||
shortM.header.start1 = CCU_UDPMSG_START1;
|
||||
shortM.header.start2 = CCU_UDPMSG_START2;
|
||||
shortM.header.id = CCU_STATE_FB_ID;
|
||||
shortM.checkCode = u.calculateChecksum((unsigned char*)&shortM, sizeof(shortM) - 8);
|
||||
size_t before = u.m_qReceiveCcuStateBuffer.size();
|
||||
EXPECT_FALSE(u.pushMsgToQueue((unsigned char*)&shortM, sizeof(shortM) - 8));
|
||||
EXPECT_EQ(u.m_qReceiveCcuStateBuffer.size(), before);
|
||||
}
|
||||
|
||||
TEST(UdpCommTest, GetDate)
|
||||
|
||||
Reference in New Issue
Block a user