#include "jt808_msg_parse.h" #include "jt808_pkg_transmit.h" #include "local_tts.h" #include "jt808_electronic_fence.h" #include "attr_broadcast.h" PrsResult_t PrsResult; // 消息体解析 static int jt808_BodyParse(void *Prsmsg_body, PrsResult_t *Result){ switch (Result->msg_head.msg_id){ case ID_Plat_GenResp:{// 平台通用应答 memcpy(&(Result->Rsp_flow_num), Prsmsg_body, sizeof(Plat_GenResp_t)); // 转小端 Result->Rsp_flow_num = Swap16(Result->msg_head.msg_flow_num); Result->Rsp_msg_id = Swap16(Result->msg_head.msg_id); // Result->Rsp_result = Result->Rsp_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; } 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); } 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:{// 查询终端参数 break; } case ID_GetSpecificTermParams:{// 查询指定终端参数 break; } case ID_Term_Ctrl:{// 终端控制 break; } case ID_GetTermAttr:{// 查询终端属性 jt808_pkg_send(ID_GetTermAttrResp, 0);// 发送查询终端属性应答,设置本消息无发送应答 break; } case ID_Term_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(50); // 设置音量大小 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(80); // 设置音量大小 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) 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); // 设置响应结果 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:{// 设置多边形区域 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; }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; } 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; }