4G_module/custom/jt808/src/jt808_msg_parse.c

393 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}