674 lines
27 KiB
C
674 lines
27 KiB
C
#include "jt808_msg_parse.h"
|
||
#include "jt808_pkg_transmit.h"
|
||
#include "local_tts.h"
|
||
#include "jt808_electronic_fence.h"
|
||
#include "attr_broadcast.h"
|
||
#include "cm_fota.h"
|
||
#include "cm_fs.h"
|
||
//#include <stdbool.h>
|
||
|
||
|
||
PrsResult_t PrsResult;
|
||
|
||
typedef int bool;
|
||
#define true 1
|
||
#define false 0
|
||
|
||
|
||
static void __cm_fota_cb(cm_fota_error_e error)
|
||
{
|
||
JT808_DEBUG("[FOTA] error code is %d\r\n", error);
|
||
}
|
||
|
||
// 检查URL是否以http://或https://开头
|
||
static bool is_valid_url(const char *url) {
|
||
if(!url) return false;
|
||
|
||
// 检查基本协议
|
||
if(strncmp(url, "http://", 7) == 0) return true;
|
||
if(strncmp(url, "https://", 8) == 0) return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
// 消息体解析
|
||
static int jt808_BodyParse(void *Prsmsg_body, PrsResult_t *Result){
|
||
switch (Result->msg_head.msg_id){
|
||
case ID_Plat_GenResp:{// 平台通用应答
|
||
Plat_GenResp_t resp_body;
|
||
//从消息体复制数据
|
||
memcpy(&resp_body, Prsmsg_body, sizeof(Plat_GenResp_t));
|
||
// 转小端
|
||
Result->Rsp_flow_num = Swap16(resp_body.msg_flow_num); // 应答流水号
|
||
Result->Rsp_msg_id = Swap16(resp_body.msg_id_ack); // 应答ID
|
||
Result->Rsp_result = resp_body.result; // 结果
|
||
break;
|
||
}
|
||
case ID_FillPktReq:{// 补传分包请求
|
||
|
||
break;
|
||
}
|
||
case ID_Term_RegResp:{// 终端注册应答
|
||
Result->Rsp_flow_num = (uint16_t)(((uint8_t *)Prsmsg_body)[0] << 8) | (((uint8_t *)Prsmsg_body)[1]);
|
||
Result->Rsp_result = ((uint8_t *)Prsmsg_body)[2];
|
||
if(Result->Rsp_result == Msg_ok){ // 成功时,读取鉴权码
|
||
if(Result->term_param_item->big_auth_info.str_auth_code != NULL){
|
||
jt808_free(Result->term_param_item->big_auth_info.str_auth_code);
|
||
Result->term_param_item->big_auth_info.str_auth_code = NULL;
|
||
}
|
||
Result->term_param_item->big_auth_info.str_auth_code = (char *)jt808_malloc(Result->msg_head.msgbody_attr.msgbodylen - 3 +1); // 加1是为了加上结束符
|
||
if(Result->term_param_item->big_auth_info.str_auth_code == NULL){
|
||
JT808_DEBUG("[%s,%s] malloc failed\r\n", __FUNCTION__,__LINE__);
|
||
return -1;
|
||
}
|
||
JT808_DEBUG("auth code =%s\r\n", Result->term_param_item->big_auth_info.str_auth_code);
|
||
memset(Result->term_param_item->big_auth_info.str_auth_code, 0, Result->msg_head.msgbody_attr.msgbodylen - 3 +1);
|
||
memcpy(Result->term_param_item->big_auth_info.str_auth_code, Prsmsg_body + 3 , Result->msg_head.msgbody_attr.msgbodylen - 3);
|
||
// 使用统一接口保存鉴权码到文件
|
||
auth_code_manage(AUTH_OP_SET, Result->term_param_item->big_auth_info.str_auth_code, 0);
|
||
}
|
||
break;
|
||
}
|
||
case ID_SetTermParams:{// 设置终端参数
|
||
Result->term_param_item->big_specific_params.param_Total_num = ((uint8_t *)Prsmsg_body)[0]; // 总参数个数
|
||
uint8_t *p_Prsmsg_body = (uint8_t *)Prsmsg_body + 1;
|
||
for(int i = 0; i < Result->term_param_item->big_specific_params.param_Total_num; i++){
|
||
// 设置终端参数
|
||
jt808_setTermParam(((uint8_t *)(p_Prsmsg_body))[0] << 24 | ((uint8_t *)(p_Prsmsg_body))[1] << 16 | ((uint8_t *)(p_Prsmsg_body))[2] << 8 | ((uint8_t *)(p_Prsmsg_body))[3], // 参数ID
|
||
(void *)(p_Prsmsg_body + 5), // 参数值
|
||
p_Prsmsg_body[4]); // 参数长度
|
||
p_Prsmsg_body += 5 + p_Prsmsg_body[4]; // 参数ID(4) + 参数长度(1) + 参数值(n)
|
||
}
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
Result->Rsp_result = Msg_ok;
|
||
jt808_pkg_send(ID_Term_GenResp, 0);// 发送终端通用应答
|
||
break;
|
||
}
|
||
case ID_GetTermParams:{// 查询终端参数
|
||
|
||
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
jt808_pkg_send(ID_GetTermParamsResp, 0);// 发送终端通用应答
|
||
break;
|
||
}
|
||
case ID_GetSpecificTermParams:{// 查询指定终端参数
|
||
|
||
break;
|
||
}
|
||
case ID_Term_Ctrl:{// 终端控制
|
||
|
||
break;
|
||
}
|
||
case ID_GetTermAttr:{// 查询终端属性
|
||
|
||
jt808_pkg_send(ID_GetTermAttrResp, 0);// 发送查询终端属性应答,设置本消息无发送应答
|
||
break;
|
||
}
|
||
case ID_Term_Upgrade:{// 下发终端升级包
|
||
|
||
// 确保消息体至少有4字节(升级类型1+CRC2+路径长度1)
|
||
if (Result->msg_head.msgbody_attr.msgbodylen < 4) {
|
||
JT808_DEBUG("Upgrade msg too short: %d bytes\n",
|
||
Result->msg_head.msgbody_attr.msgbodylen);
|
||
Result->Rsp_result = Msg_invalid;
|
||
} else {
|
||
uint8_t *p_body = (uint8_t *)Prsmsg_body;
|
||
|
||
// 解析固定字段
|
||
uint8_t upgrade_type = p_body[0]; // 升级类型(1字节)
|
||
uint16_t file_crc = (p_body[1] << 8) | p_body[2]; // 文件CRC(2字节)
|
||
uint8_t path_len = p_body[3]; // 路径长度(1字节)
|
||
|
||
// 移动到路径开始位置
|
||
p_body += 4;
|
||
|
||
// 验证路径长度是否匹配
|
||
if ((path_len + 4) != Result->msg_head.msgbody_attr.msgbodylen) {
|
||
JT808_DEBUG("Path len mismatch: expected %d, actual %d\n",
|
||
path_len, Result->msg_head.msgbody_attr.msgbodylen - 4);
|
||
Result->Rsp_result = Msg_invalid;
|
||
} else {
|
||
// 释放旧路径内存(如果有)
|
||
if (Result->term_param_item->big_upgrade_info.file_path != NULL) {
|
||
jt808_free(Result->term_param_item->big_upgrade_info.file_path);
|
||
Result->term_param_item->big_upgrade_info.file_path = NULL;
|
||
}
|
||
|
||
// 分配新路径内存
|
||
Result->term_param_item->big_upgrade_info.file_path = (char *)jt808_malloc(path_len + 1);
|
||
|
||
if (Result->term_param_item->big_upgrade_info.file_path == NULL) {
|
||
JT808_DEBUG("File path malloc failed (%d bytes)\n", path_len + 1);
|
||
Result->Rsp_result = Msg_err;
|
||
} else {
|
||
// 复制并添加终止符
|
||
memcpy(Result->term_param_item->big_upgrade_info.file_path, p_body, path_len);
|
||
Result->term_param_item->big_upgrade_info.file_path[path_len] = '\0';
|
||
|
||
// 更新升级信息
|
||
Result->term_param_item->big_upgrade_info.upgrade_type = upgrade_type;
|
||
Result->term_param_item->big_upgrade_info.file_crc = file_crc;
|
||
Result->term_param_item->big_upgrade_info.path_len = path_len;
|
||
|
||
JT808_DEBUG("Received upgrade cmd: type=%u, crc=0x%04X, path=%s\n",
|
||
upgrade_type, file_crc, Result->term_param_item->big_upgrade_info.file_path);
|
||
|
||
|
||
Result->Rsp_result = Msg_ok;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 设置应答并发送通用应答
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
jt808_pkg_send(ID_Term_GenResp, 0);
|
||
|
||
// 启动升级处理流程(同步执行)
|
||
// start_upgrade_process(&Result->big_upgrade_info);
|
||
local_tts_text_play("软件升级流程开始,请勿断电",0,0);
|
||
local_tts_text_play("升级完成后会自动重启",0,0);
|
||
const char *url = Result->term_param_item->big_upgrade_info.file_path;
|
||
if(!is_valid_url(url)) {
|
||
JT808_DEBUG("Invalid URL: %s\n", url);
|
||
jt808_free(Result->term_param_item->big_upgrade_info.file_path);
|
||
Result->term_param_item->big_upgrade_info.file_path = NULL;
|
||
break; // 不继续升级
|
||
}
|
||
int ret = 0;
|
||
cm_fota_set_ota_plan(CM_FOTA_ASR_PLAN_MINI_INTEGRATE);
|
||
cm_fota_res_callback_register((cm_fota_result_callback)__cm_fota_cb);
|
||
|
||
ret = cm_fota_set_url(Result->term_param_item->big_upgrade_info.file_path); //设置url路径
|
||
if(0 != ret)
|
||
{
|
||
JT808_DEBUG("url error\r\n");
|
||
|
||
}
|
||
else {
|
||
JT808_DEBUG("url right\r\n");
|
||
cm_fs_system_info_t fs_info = {0, 0};
|
||
cm_fs_getinfo(&fs_info);
|
||
|
||
JT808_DEBUG("free size =%u",fs_info.free_size);
|
||
|
||
//文件系统剩余空间为0时不建议执行升级,关键文件系统操作可能会失败
|
||
if (0 == fs_info.free_size)
|
||
{
|
||
JT808_DEBUG("insufficient space left in the file system\r\n");
|
||
break;
|
||
}
|
||
#define MIN_FOTA_SPACE (4 * 1024) // 512KB
|
||
if(fs_info.free_size < MIN_FOTA_SPACE)
|
||
{
|
||
JT808_DEBUG("Insufficient space: %u < %u\n", fs_info.free_size, MIN_FOTA_SPACE);
|
||
break;
|
||
}
|
||
cm_fota_info_t info = {0};
|
||
cm_fota_read_config(&info);
|
||
if (CM_FOTA_TYPE_HTTP_HTTPS == info.fixed_info.fota_mode)
|
||
{
|
||
JT808_DEBUG("HTTP server [%s]\r\n", info.fixed_info.url);
|
||
}
|
||
else
|
||
{
|
||
JT808_DEBUG("HTTP server error\r\n");
|
||
break;
|
||
}
|
||
|
||
osDelay(2000/5);
|
||
cm_fota_exec_upgrade();
|
||
|
||
}
|
||
|
||
break;
|
||
}
|
||
case ID_GetLocInfo:{// 位置信息查询
|
||
|
||
break;
|
||
}
|
||
case ID_LocTrackingCtrl:{// 临时位置跟踪控制
|
||
|
||
break;
|
||
}
|
||
case ID_TxtMsgdelivery:{// 文本信息下发
|
||
uint8_t device_volume, speed, volume, mode;
|
||
uint8_t txt_flag = ((uint8_t *)Prsmsg_body)[0];
|
||
JT808_DEBUG("ID_TxtMsgdelivery:%x\r\n", txt_flag);
|
||
Prsmsg_body = (void *)((uint8_t *)Prsmsg_body + 1); // 跳过标志位
|
||
device_volume =10*(((uint8_t *)Prsmsg_body)[0]-'0') + (((uint8_t *)Prsmsg_body)[1]-'0');
|
||
speed =10*(((uint8_t *)Prsmsg_body)[3]-'0') + (((uint8_t *)Prsmsg_body)[4]-'0');
|
||
volume =10*(((uint8_t *)Prsmsg_body)[6]-'0') + (((uint8_t *)Prsmsg_body)[7]-'0');
|
||
mode = ((uint8_t *)Prsmsg_body)[9]-'0';
|
||
|
||
Result->Rsp_result = Msg_ok;
|
||
if((((uint8_t *)Prsmsg_body)[2] == ',')&&(((uint8_t *)Prsmsg_body)[5] == ',')&&(((uint8_t *)Prsmsg_body)[8] == ',')&&(((uint8_t *)Prsmsg_body)[10] == ';')){ // 文本信息下发
|
||
if(speed > 0 && speed <= 15 && volume > 0 && volume <= 15 && mode >= 0 && mode <= 2){ // 速度、音量、模式有效
|
||
local_tts_volume(device_volume); // 设置音量大小
|
||
local_tts_set(speed, volume, mode);
|
||
}else{
|
||
JT808_DEBUG("error speed or volume or mode\r\n");
|
||
local_tts_volume(100); // 设置音量大小
|
||
local_tts_set(6, 7, CM_LOCAL_TTS_DIGIT_AUTO);
|
||
Result->Rsp_result = Msg_invalid;//消息有误
|
||
}
|
||
}else{
|
||
JT808_DEBUG("error speed or volume or mode\r\n");
|
||
local_tts_volume(100); // 设置音量大小
|
||
local_tts_set(7, 15, CM_LOCAL_TTS_DIGIT_AUTO);
|
||
Result->Rsp_result = Msg_invalid;//消息有误
|
||
}
|
||
local_tts_text_play((char *)Prsmsg_body + 11, Result->msg_head.msgbody_attr.msgbodylen -11,0); // 开始播放文本信息// 不可打断
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
// Result->Rsp_result = Msg_ok;
|
||
jt808_pkg_send(ID_Term_GenResp, 0);// 发送终端通用应答
|
||
break;
|
||
}
|
||
case ID_Car_Ctrl:{// 车辆控制
|
||
if(Result->msg_head.msgbody_attr.msgbodylen == 1){ // 车辆控制
|
||
jt808_Set_CarStatus(((uint8_t *)Prsmsg_body)[0]); // 设置车辆状态
|
||
Result->Rsp_result = Msg_ok;
|
||
}else{
|
||
Result->Rsp_result = Msg_invalid;
|
||
}
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
jt808_pkg_send(ID_Car_CtrlResp, 0);// 发送车辆控制应答,设置本消息无发送应答
|
||
break;
|
||
}
|
||
case ID_Set_Circle_Area:{// 设置圆形区域(0x8600)
|
||
// 检查是否在更新流程中
|
||
bool in_update = update_manager_is_active() && update_status.state == UPDATE_RECEIVING_DATA;
|
||
|
||
|
||
int ret = 0;
|
||
uint8_t *p = (uint8_t *)Prsmsg_body;
|
||
|
||
// 解析固定字段
|
||
uint32_t Area_ID = Swap32(*(uint32_t *)p);
|
||
uint16_t Area_att = Swap16(*(uint16_t *)(p + 4));
|
||
uint32_t center_lat = Swap32(*(uint32_t *)(p + 6));
|
||
uint32_t center_lon = Swap32(*(uint32_t *)(p + 10));
|
||
uint32_t radius = Swap32(*(uint32_t *)(p + 14));
|
||
|
||
// 解析景点名称字符串
|
||
uint16_t fixed_len = 18; // 前18字节是固定字段
|
||
uint16_t name_len = Result->msg_head.msgbody_attr.msgbodylen - fixed_len;
|
||
char *scenic_name = NULL;
|
||
|
||
if (name_len > 0) {
|
||
scenic_name = (char *)jt808_malloc(name_len + 1);
|
||
if (scenic_name) {
|
||
memcpy(scenic_name, p + fixed_len, name_len);
|
||
scenic_name[name_len] = '\0'; // 添加字符串终止符
|
||
}
|
||
}
|
||
|
||
// 转换为实际经纬度(除以10^6)
|
||
double actual_lat = (double)center_lat / 1000000.0;
|
||
double actual_lon = (double)center_lon / 1000000.0;
|
||
JT808_DEBUG("actual_lat=%f,actual_lon=%f\r\n",actual_lat,actual_lon);
|
||
|
||
|
||
|
||
// 调用区域添加函数
|
||
attr_broadcast_add_attraction(
|
||
Area_ID, // 区域ID
|
||
actual_lon, // 经度
|
||
actual_lat, // 纬度
|
||
(double)radius, // 半径(米)
|
||
scenic_name ? scenic_name : "",// 景点名称
|
||
"" // 描述(可选)
|
||
);
|
||
|
||
// 释放名称内存
|
||
if (scenic_name) jt808_free(scenic_name);
|
||
|
||
// 如果在更新流程中,标记数据包接收
|
||
if (in_update) {
|
||
update_manager_packet_received();
|
||
JT808_DEBUG("Received attr packet %d/%d\n", update_status.received_packets, update_status.expected_packets);
|
||
}
|
||
else
|
||
{
|
||
JT808_DEBUG("Direct attr packet received, please check \r\n");
|
||
|
||
}
|
||
|
||
// 设置响应结果
|
||
Result->Rsp_result = (ret == 0) ? Msg_ok : Msg_err;
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
|
||
// 发送终端通用应答
|
||
jt808_pkg_send(ID_Term_GenResp, 0);
|
||
JT808_DEBUG("attraction data accepted\r\n");
|
||
|
||
|
||
break;
|
||
}
|
||
|
||
case ID_Delete_Circle_area:{// 删除圆形区域(0x8601)
|
||
int ret = 0;
|
||
uint8_t area_count = *((uint8_t*)Prsmsg_body); // 区域个数(1字节)
|
||
uint32_t* area_ids = (uint32_t*)((uint8_t*)Prsmsg_body + 1);
|
||
|
||
// 特殊处理:0表示删除所有区域
|
||
if (area_count == 0) {
|
||
attr_broadcast_remove_all();
|
||
}
|
||
// 正常删除指定区域
|
||
else {
|
||
Result->Rsp_result = Msg_ok; //删不删干净都是ok
|
||
for (int i = 0; i < area_count; i++) {
|
||
uint32_t area_id = Swap32(area_ids[i]);
|
||
attr_broadcast_remove_attraction_by_id(area_id);
|
||
|
||
}
|
||
}
|
||
|
||
// 设置应答信息
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
jt808_pkg_send(ID_Term_GenResp, 0); // 发送终端通用应答
|
||
break;
|
||
}
|
||
case ID_Set_Polygon_area:{// 设置多边形区域
|
||
// 检查是否在更新流程中
|
||
bool in_update = update_manager_is_active() && update_status.state == UPDATE_RECEIVING_DATA;
|
||
|
||
|
||
int ret = 0;
|
||
uint32_t Area_ID; // 区域ID
|
||
uint16_t Area_att; // 区域属性
|
||
uint16_t Area_Points_Num; // 区域内点的数量
|
||
memcpy(&Area_ID, ((uint8_t *)Prsmsg_body), 4); // 区域ID
|
||
memcpy(&Area_att, ((uint8_t *)Prsmsg_body)+4, 2); // 区域属性
|
||
memcpy(&Area_Points_Num, ((uint8_t *)Prsmsg_body)+21, 2); // 区域点个数
|
||
if(Swap16(Area_Points_Num) <= 120){ // 区域点个数有效
|
||
ret = jt808_add_tail_fence_Polygon_area(Swap32(Area_ID), // 区域ID
|
||
Swap16(Area_att), // 区域属性
|
||
Swap16(Area_Points_Num), // 区域点个数
|
||
(AreaPoint_t *)(((uint8_t *)Prsmsg_body) + 23)); // 区域点坐标
|
||
if(ret == 0){
|
||
Result->Rsp_result = Msg_ok;
|
||
// 如果在更新流程中,标记数据包接收
|
||
if (in_update) {
|
||
update_manager_packet_received();
|
||
JT808_DEBUG("Received fence packet %d/%d\n", update_status.received_packets, update_status.expected_packets);
|
||
}
|
||
else
|
||
{
|
||
JT808_DEBUG("Direct fence packet received, please check\r\n");
|
||
|
||
}
|
||
}else{
|
||
Result->Rsp_result = Msg_err;
|
||
}
|
||
}else{
|
||
Result->Rsp_result = Msg_invalid;
|
||
}
|
||
|
||
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
jt808_pkg_send(ID_Term_GenResp, 0);// 发送终端通用应答
|
||
break;
|
||
}
|
||
case ID_Delete_Polygon_area:{// 删除多边形区域
|
||
int ret = 0;
|
||
uint8_t Area_ID_Num = ((uint8_t *)Prsmsg_body)[0]; // 区域ID个数
|
||
//Prsmsg_body = (void *)((uint8_t *)Prsmsg_body + 1); // 跳过1字节
|
||
uint8_t *p_id = (uint8_t *)Prsmsg_body + 1; // 指向第一个ID
|
||
Result->Rsp_result = Msg_ok;
|
||
|
||
|
||
JT808_DEBUG("Area_ID_Num=%d\r\n",Area_ID_Num);
|
||
|
||
// 区域数为0:删除所有区域
|
||
if (Area_ID_Num == 0) {
|
||
if (jt808_remove_fence_Polygon_area(0) != 0) {
|
||
Result->Rsp_result = Msg_err;
|
||
}
|
||
}
|
||
else {
|
||
for(int i = 0; i < Area_ID_Num; i++){
|
||
|
||
uint32_t area_id = (p_id[0] << 24) | (p_id[1] << 16) | (p_id[2] << 8) | p_id[3];
|
||
|
||
ret = jt808_remove_fence_Polygon_area(area_id);
|
||
if(ret != 0){
|
||
Result->Rsp_result = Msg_err;
|
||
break;
|
||
}
|
||
p_id += 4;
|
||
|
||
}
|
||
|
||
}
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
jt808_pkg_send(ID_Term_GenResp, 0);// 发送终端通用应答
|
||
|
||
break;
|
||
}
|
||
case ID_Data_Down:{// 数据下行透传
|
||
jt808_data_down_SeriaNet(((uint8_t *)Prsmsg_body)[0],((uint8_t *)Prsmsg_body) + 1, Result->msg_head.msgbody_attr.msgbodylen - 1); // 透传数据
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
Result->Rsp_result = Msg_ok;
|
||
jt808_pkg_send(ID_Term_GenResp, 0);// 发送终端通用应答
|
||
// JT808_DEBUG("ID_Data_Down\r\n");
|
||
break;
|
||
}
|
||
case ID_data_update_reply:{// 电子围栏/景点数量下发
|
||
if (update_manager_is_active()) {
|
||
// 检查消息体长度至少为5字节 (2+1+2)
|
||
if (Result->msg_head.msgbody_attr.msgbodylen < 5) {
|
||
JT808_DEBUG("Invalid update reply length: %d\n", Result->msg_head.msgbody_attr.msgbodylen);
|
||
Result->Rsp_result = Msg_invalid;
|
||
update_manager_fail();
|
||
} else {
|
||
uint8_t *p_body = (uint8_t *)Prsmsg_body;
|
||
|
||
// 手动组合应答流水号(2字节大端)
|
||
uint16_t reply_flow_num = (p_body[0] << 8) | p_body[1];
|
||
Result->Rsp_flow_num = reply_flow_num;
|
||
|
||
|
||
// 解析类型 (1字节)
|
||
uint8_t update_type = p_body[2];
|
||
|
||
// 手动组合围栏/景点数量(2字节大端)
|
||
uint16_t packet_count = (p_body[3] << 8) | p_body[4];
|
||
|
||
JT808_DEBUG("Update reply: type=%d, count=%d\n", update_type, packet_count);
|
||
|
||
// 验证类型是否匹配当前更新
|
||
if ((update_type == 1 && update_status.type == UPDATE_TYPE_FENCE) ||
|
||
(update_type == 2 && update_status.type == UPDATE_TYPE_ATTR)) {
|
||
|
||
if (packet_count == 0) {
|
||
// 无数据需要更新
|
||
update_manager_complete();
|
||
JT808_DEBUG("No data to update\n");
|
||
Result->Rsp_result = Msg_ok;
|
||
} else {
|
||
// 开始接收数据
|
||
update_manager_begin_receiving(packet_count);
|
||
JT808_DEBUG("Expecting %d data packets\n", packet_count);
|
||
Result->Rsp_result = Msg_ok;
|
||
}
|
||
} else {
|
||
// 类型不匹配
|
||
JT808_DEBUG("Type mismatch: msg_type=%d, current_type=%d\n",update_type, update_status.type);
|
||
Result->Rsp_result = Msg_invalid;
|
||
update_manager_fail();
|
||
}
|
||
}
|
||
} else {
|
||
Result->Rsp_result = Msg_err; // 更新管理器未激活
|
||
JT808_DEBUG("Received update reply without active update\n");
|
||
}
|
||
|
||
// 设置应答
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
jt808_pkg_send(ID_Term_GenResp, 0);
|
||
break;
|
||
}
|
||
case ID_data_update_complete:{// 电子围栏/景点更新完成
|
||
if (update_manager_is_complete()) {
|
||
// 检查消息体长度至少为5字节 (1字节类型+4字节版本号)
|
||
if (Result->msg_head.msgbody_attr.msgbodylen < 5) {
|
||
JT808_DEBUG("Invalid update complete length: %d\n", Result->msg_head.msgbody_attr.msgbodylen);
|
||
Result->Rsp_result = Msg_invalid;
|
||
update_manager_fail();
|
||
} else {
|
||
uint8_t *p_body = (uint8_t *)Prsmsg_body;
|
||
|
||
// 解析类型 (1字节)
|
||
uint8_t update_type = p_body[0];
|
||
|
||
// 解析版本号 (4字节大端) - 使用Swap32转换
|
||
uint32_t new_version = Swap32(*(uint32_t*)(p_body+1));
|
||
|
||
JT808_DEBUG("Update complete: type=%d, version=%u\n", update_type, new_version);
|
||
|
||
// 验证类型是否匹配当前更新
|
||
if ((update_type == 1 && update_status.type == UPDATE_TYPE_FENCE) ||
|
||
(update_type == 2 && update_status.type == UPDATE_TYPE_ATTR)) {
|
||
|
||
// 更新本地版本号
|
||
attr_broadcast_manage_version(
|
||
VERSION_OP_SET,
|
||
(update_type == 1) ? VERSION_TYPE_FENCE : VERSION_TYPE_ATTRACTION,
|
||
&new_version
|
||
);
|
||
|
||
update_manager_complete();
|
||
Result->Rsp_result = Msg_ok;
|
||
} else {
|
||
JT808_DEBUG("Type mismatch: msg_type=%d, current_type=%d\n",
|
||
update_type, update_status.type);
|
||
Result->Rsp_result = Msg_invalid;
|
||
update_manager_fail();
|
||
}
|
||
}
|
||
} else {
|
||
Result->Rsp_result = Msg_err; // 更新管理器未激活
|
||
JT808_DEBUG("Received update complete without active update\n");
|
||
}
|
||
|
||
// 设置应答
|
||
Result->Rsp_flow_num = Result->msg_head.msg_flow_num;
|
||
Result->Rsp_msg_id = Result->msg_head.msg_id;
|
||
jt808_pkg_send(ID_Term_GenResp, 0);
|
||
break;
|
||
|
||
}
|
||
default:{
|
||
return -2; // 没有对应的消息体解析函数
|
||
break;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
// jt808协议包处理
|
||
int jt808_msg_parse(const uint8_t *BufferReceive, uint16_t length, PrsResult_t *Result){
|
||
uint8_t *raw_Buffer = (uint8_t *)jt808_malloc(length * sizeof(uint8_t));
|
||
if(raw_Buffer == NULL){
|
||
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
|
||
return -1;
|
||
}
|
||
memcpy(raw_Buffer, BufferReceive, length);
|
||
|
||
// // 打印原始数据
|
||
// app_printf("raw_Buffer: %d\r\n", length);
|
||
// for(int i = 0; i < length; i++){
|
||
// app_printf("%02x ", raw_Buffer[i]);
|
||
// }
|
||
// app_printf("\r\n");
|
||
|
||
// 计算需要逆转义字符的个数
|
||
uint16_t para_length = 0;
|
||
for(int i = 1; i < (length - 2); i++){
|
||
if(((raw_Buffer[i] == PESC)&&(raw_Buffer[i+1] == PESC_SIGN)) || // 7d 02 转义7e
|
||
((raw_Buffer[i] == PESC)&&(raw_Buffer[i+1] == PESC_ESCAPE))){ // 7d 01 转义7d
|
||
para_length++;
|
||
}
|
||
}
|
||
para_length =length - para_length;
|
||
uint8_t *para_Buffer = (uint8_t *)jt808_malloc(para_length * sizeof(uint8_t));
|
||
if(para_Buffer == NULL){
|
||
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
|
||
jt808_free(raw_Buffer);
|
||
return -1;
|
||
}
|
||
para_Buffer[0] = PSIGN;
|
||
para_Buffer[para_length - 1] = PSIGN;
|
||
|
||
// 逆转义
|
||
uint16_t offset_num = 0;
|
||
for(int i = 1; i < (para_length - 1); i++){
|
||
if(((raw_Buffer[i + offset_num] == PESC)&&(raw_Buffer[i + offset_num + 1] == PESC_SIGN))){ // 7d 02 转义7e
|
||
para_Buffer[i] = PSIGN;
|
||
offset_num++;
|
||
}else if(((raw_Buffer[i + offset_num] == PESC)&&(raw_Buffer[i + offset_num + 1] == PESC_ESCAPE))){ // 7d 01 转义7d
|
||
para_Buffer[i] = PESC;
|
||
offset_num++;
|
||
}else{
|
||
para_Buffer[i] =raw_Buffer[i + offset_num];
|
||
}
|
||
}
|
||
// 释放内存
|
||
jt808_free(raw_Buffer);
|
||
|
||
if(offset_num != length - para_length){ // 转义后长度有误
|
||
JT808_DEBUG("error offset_num != length - para_length\r\n");
|
||
jt808_free(para_Buffer);
|
||
return -1;
|
||
}
|
||
|
||
// // 打印逆转义后数据
|
||
// app_printf("para_Buffer: %d\r\n", para_length);
|
||
// for(int i = 0; i < para_length; i++){
|
||
// app_printf("%02x ", para_Buffer[i]);
|
||
// }
|
||
// app_printf("\r\n");
|
||
|
||
// 异或校验
|
||
if(para_Buffer[para_length - 2] != BCC_Check(para_Buffer + 1, para_length - 2 - 1)){
|
||
JT808_DEBUG("BCC_CheckSum ERROR: %x %x\r\n",para_Buffer[para_length - 2] ,BCC_Check(para_Buffer + 1, para_length - 2 - 1));
|
||
jt808_free(para_Buffer);
|
||
return -1;
|
||
}
|
||
// 解析消息头
|
||
memcpy(&Result->msg_head, para_Buffer + 1, sizeof(MsgHead_t) - ((para_Buffer[3] & 0x02)==0? 4 : 0));
|
||
Result->msg_head.msg_id = Swap16(Result->msg_head.msg_id);// 消息ID
|
||
Result->msg_head.msgbody_attr.val16 = Swap16(Result->msg_head.msgbody_attr.val16);// 消息体属性
|
||
Result->msg_head.msg_flow_num = Swap16(Result->msg_head.msg_flow_num);// 消息流水号
|
||
Result->msg_head.total_packet = Swap16(Result->msg_head.total_packet);// 总包数, 分包情况下使用
|
||
Result->msg_head.packet_seq = Swap16(Result->msg_head.packet_seq);// 当前包序号, 分包情况下使用
|
||
|
||
JT808_DEBUG("RECV Msg_ID:0x%04X len:%d\r\n", Result->msg_head.msg_id ,para_length);
|
||
for(uint16_t i = 0; i < para_length; i++){
|
||
JT808_DEBUG_DATA("%02X ", *(para_Buffer + i));
|
||
}
|
||
JT808_DEBUG_DATA("\n");
|
||
// 消息体解析
|
||
if(0 != jt808_BodyParse((void *)(para_Buffer + 1 + sizeof(MsgHead_t) - ((para_Buffer[3] & 0x02)==0? 4 : 0)) ,Result)){
|
||
JT808_DEBUG("error jt808_BodyParse\r\n");
|
||
// 释放内存
|
||
jt808_free(para_Buffer);
|
||
return -1;
|
||
}
|
||
|
||
// 释放内存
|
||
jt808_free(para_Buffer);
|
||
return 0;
|
||
}
|