From 3093935b231094fbdcac0dd69d7a703e9e7af365 Mon Sep 17 00:00:00 2001 From: zsx <1543588107@qq.com> Date: Fri, 18 Oct 2024 00:41:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=AC=AC=E4=B8=89=E6=96=B9jt?= =?UTF-8?q?808=E5=8D=8F=E8=AE=AE=E5=BA=93=20zsxfly20241013?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + custom/custom.mk | 1 + custom/custom_main/src/custom_main.c | 34 +- custom/jt808/inc/bcd.h | 29 ++ custom/jt808/inc/client_manager.h | 64 +++ custom/jt808/inc/gbk_utf8.h | 29 ++ custom/jt808/inc/jt808_debug.h | 13 + custom/jt808/inc/jt808_packager.h | 19 + custom/jt808/inc/jt808_parser.h | 19 + custom/jt808/inc/location_report.h | 333 ++++++++++++++ custom/jt808/inc/protocol_parameter.h | 315 +++++++++++++ custom/jt808/inc/set_terminal_parameter.h | 21 + custom/jt808/inc/terminal_control.h | 35 ++ custom/jt808/inc/terminal_parameter.h | 504 +++++++++++++++++++++ custom/jt808/inc/terminal_register.h | 64 +++ custom/jt808/inc/util.h | 54 +++ custom/jt808/jt808.mk | 14 + custom/jt808/src/bcd.c | 70 +++ custom/jt808/src/client_manager.c | 497 +++++++++++++++++++++ custom/jt808/src/gbk_utf8.c | 133 ++++++ custom/jt808/src/jt808_packager.c | 519 ++++++++++++++++++++++ custom/jt808/src/jt808_parser.c | 453 +++++++++++++++++++ custom/jt808/src/location_report.c | 74 +++ custom/jt808/src/set_terminal_parameter.c | 304 +++++++++++++ custom/jt808/src/terminal_register.c | 56 +++ custom/jt808/src/util.c | 162 +++++++ 26 files changed, 3816 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 custom/jt808/inc/bcd.h create mode 100644 custom/jt808/inc/client_manager.h create mode 100644 custom/jt808/inc/gbk_utf8.h create mode 100644 custom/jt808/inc/jt808_debug.h create mode 100644 custom/jt808/inc/jt808_packager.h create mode 100644 custom/jt808/inc/jt808_parser.h create mode 100644 custom/jt808/inc/location_report.h create mode 100644 custom/jt808/inc/protocol_parameter.h create mode 100644 custom/jt808/inc/set_terminal_parameter.h create mode 100644 custom/jt808/inc/terminal_control.h create mode 100644 custom/jt808/inc/terminal_parameter.h create mode 100644 custom/jt808/inc/terminal_register.h create mode 100644 custom/jt808/inc/util.h create mode 100644 custom/jt808/jt808.mk create mode 100644 custom/jt808/src/bcd.c create mode 100644 custom/jt808/src/client_manager.c create mode 100644 custom/jt808/src/gbk_utf8.c create mode 100644 custom/jt808/src/jt808_packager.c create mode 100644 custom/jt808/src/jt808_parser.c create mode 100644 custom/jt808/src/location_report.c create mode 100644 custom/jt808/src/set_terminal_parameter.c create mode 100644 custom/jt808/src/terminal_register.c create mode 100644 custom/jt808/src/util.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..667bb48 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.vscode/ +out/ diff --git a/custom/custom.mk b/custom/custom.mk index 25bee14..ecf35ce 100644 --- a/custom/custom.mk +++ b/custom/custom.mk @@ -6,4 +6,5 @@ ifeq ($(strip $(DEMO_SUPPORT)),n) include $(CUSTOM_DIR)/custom_main/custom_main.mk include $(CUSTOM_DIR)/nmealib/nmealib.mk include $(CUSTOM_DIR)/GPS/gps.mk +include $(CUSTOM_DIR)/jt808/jt808.mk endif \ No newline at end of file diff --git a/custom/custom_main/src/custom_main.c b/custom/custom_main/src/custom_main.c index d066d3b..c39df77 100644 --- a/custom/custom_main/src/custom_main.c +++ b/custom/custom_main/src/custom_main.c @@ -40,10 +40,17 @@ // #include "cm_demo_ssl.h" #include "app_uart.h" #include "gps_config.h" +#include "client_manager.h" +#include "jt808_packager.h" osThreadId_t OC_APP_TaskHandle; void my_appimg_enter(char *param){ + int isRegistered=0; + int isAuthenticated=0; + unsigned int v_alarm_value = 0; + unsigned int v_status_value = 0; + cm_gpio_cfg_t cfg = {0}; cfg.direction = CM_GPIO_DIRECTION_OUTPUT; @@ -57,10 +64,33 @@ void my_appimg_enter(char *param){ app_uart_init(); gps_config_init(); app_printf("Hello, world!\r\n"); + initSystemParameters(0); + //设置手机号(唯一识别id) + setUUID(); + //终端注册 + if(isRegistered == 0){ + jt808TerminalRegister(&isRegistered); + if(isRegistered==0){ + // system_reboot(); + // continue; + } + } + //终端鉴权 + if(isAuthenticated == 0){ + jt808TerminalAuthentication(&isAuthenticated); + if(isAuthenticated==0){ + // system_reboot(); + // continue; + } + } + + //设置位置上报警报位、状态位 + initLocationInfo(v_alarm_value, v_status_value); + setStatusBit(); while(1){ - osDelay(300/5);//300ms + osDelay(200/5);//300ms cm_gpio_set_level(0, 1); - osDelay(300/5);//300ms + osDelay(200/5);//300ms cm_gpio_set_level(0, 0); // app_printf("Hello, world!\r\n"); } diff --git a/custom/jt808/inc/bcd.h b/custom/jt808/inc/bcd.h new file mode 100644 index 0000000..3924cb5 --- /dev/null +++ b/custom/jt808/inc/bcd.h @@ -0,0 +1,29 @@ + + +#ifndef JT808_BCD_H_ +#define JT808_BCD_H_ + +#include +#include + +#include + + + +unsigned char HexToBcd(unsigned char src); +unsigned char BcdToHex(unsigned char src); +unsigned char *jt808StringToBcdCompress(const unsigned char *src, unsigned char *dst, int srclen); +unsigned char *jt808BcdToStringCompress(const unsigned char *src, unsigned char *dst, int srclen); +unsigned char *jt808BcdToStringCompressFillingZero(const unsigned char *src, unsigned char *dst, int srclen); + +// uint8_t HexToBcd(uint8_t const &src); +// uint8_t BcdToHex(uint8_t const &src); +// uint8_t *StringToBcdCompress(const uint8_t *src, uint8_t *dst, const int & srclen); +// uint8_t *BcdToStringCompress(const uint8_t *src, uint8_t *dst, const int & srclen); +// uint8_t *BcdToStringCompressFillingZero(const uint8_t *src, uint8_t *dst, const int &srclen); +// int StringToBcd(std::string const &in, std::vector *out); +// int BcdToString(std::vector const &in, std::string *out); +// int BcdToStringFillZero(std::vector const &in, std::string *out); + + +#endif // JT808_BCD_H_ diff --git a/custom/jt808/inc/client_manager.h b/custom/jt808/inc/client_manager.h new file mode 100644 index 0000000..edddece --- /dev/null +++ b/custom/jt808/inc/client_manager.h @@ -0,0 +1,64 @@ +#ifndef JT808_CLIENT_MANAGER_H_ +#define JT808_CLIENT_MANAGER_H_ +#include +#include +#include + +#include "cm_os.h" + +//#define __JT808_DEBUG +#define FLASH_ADDR (uint32_t)0x0803c000 +//#define ID_FLASH_ADDR (uint32_t)0x0803b800 +#define FLASH_BUFFER_SIZE 128 + +#define JT808_delay_ms(_ms) osDelay(_ms/5);//ms + +extern struct ProtocolParameter parameter_; + +void setTerminalPhoneNumber(const char *phone_num, unsigned int phoneSize); + +/****************************************************************************** + * @description: 数据打包并发送接口 + * @param {unsigned int} msg_id 消息ID + * @return {*} + * @author: ZTL + *******************************************************************************/ +int packagingAndSendMessage(unsigned int msg_id); + +/****************************************************************************** + * @description: 数据打包接口 + * @param {unsigned int} msg_id JT808消息ID + * @param { unsigned int} *realBufSize 用于记录实际打包待发送的buffer长度 + * @return {0}成功 {-1}失败 + * @author: ZTL + *******************************************************************************/ +int packagingMessage(unsigned int msg_id); + +/****************************************************************************** + * @description: 从终端打包器命令数组中查找是否有当前相应的消息ID,以便根据该命令数组中的消息ID调用相应的接口 + * @param {unsigned int} msg_id 消息ID + * @return {0}失败 {1}成功 + * @author: ZTL + *******************************************************************************/ +int findMsgIDFromTerminalPackagerCMD(unsigned int msg_id); +int findParameterIDFromArray(unsigned int para_id); +int parsingMessage(const unsigned char *in, unsigned int in_len); +int jt808TerminalRegister(int *isRegistered); +int jt808TerminalAuthentication(int *isAuthenticated); +int jt808LocationReport(void); +int jt808TerminalLogOut(void); +int jt808TerminalHeartBeat(void); +int jt808TerminalUpgradeResultReport(void); +int jt808TerminalGeneralResponse(void); +void setTerminalId(const char *TerminalId, unsigned int lenTerminalId); +void setStatusBit(void); +int FlashWrite(void); +void setUUID(void); +int IPFlashWrite(void); +void File_upload(void); +void initSystemParameters(int i); +void initLocationInfo(unsigned int v_alarm_value, unsigned int v_status_value); +void updateLocation(double const v_latitude, double const v_longitude, float const v_altitude, + float const v_speed, float const v_bearing, unsigned char *v_timestamp); + +#endif // JT808_CLIENT_MANAGER_H_ diff --git a/custom/jt808/inc/gbk_utf8.h b/custom/jt808/inc/gbk_utf8.h new file mode 100644 index 0000000..a089be9 --- /dev/null +++ b/custom/jt808/inc/gbk_utf8.h @@ -0,0 +1,29 @@ + + +#ifndef JT808_GBK_UTF8_H_ +#define JT808_GBK_UTF8_H_ + +#include +#include +#include +#include +/* +namespace libjt808 +{ +#ifdef _WIN32 + std::string GbkToUtf8(const char *src_str); + std::string Utf8ToGbk(const char *src_str); +#else + int GbkToUtf8(char *str_str, size_t src_len, char *dst_str, size_t dst_len); + int Utf8ToGbk(char *src_str, size_t src_len, char *dst_str, size_t dst_len); +#endif + + std::string gbk_to_utf8_str(const std::vector &gbk_src); + std::string gbk_to_utf8_str(const std::string &str_gbk_src); +} +s + + +*/ +#endif // JT808_GBK_UTF8_H_ + diff --git a/custom/jt808/inc/jt808_debug.h b/custom/jt808/inc/jt808_debug.h new file mode 100644 index 0000000..561d454 --- /dev/null +++ b/custom/jt808/inc/jt808_debug.h @@ -0,0 +1,13 @@ +#ifndef _JT808_DEBUG_H_ +#define _JT808_DEBUG_H_ + +#define JT808_DEBUG_ENABLE 1 + +#if JT808_DEBUG_ENABLE +#include "app_uart.h" +#define JT808_DEBUG(fmt, args...) app_printf("[JT808]" fmt, ##args) +#else +#define JT808_DEBUG(fmt, arg...) +#endif + +#endif \ No newline at end of file diff --git a/custom/jt808/inc/jt808_packager.h b/custom/jt808/inc/jt808_packager.h new file mode 100644 index 0000000..ba1ba12 --- /dev/null +++ b/custom/jt808/inc/jt808_packager.h @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +#define PACKAGER_NUM 9 //终端打包器命令相应消息ID数量 +#define BUFFER_SIZE_SEND 1024 // buffer size 发送缓存大小 + +#include "protocol_parameter.h" +#include "terminal_register.h" +#include "bcd.h" + + +extern unsigned short kTerminalPackagerCMD[PACKAGER_NUM]; +extern unsigned char BufferSend[BUFFER_SIZE_SEND]; //发送缓存 +extern unsigned int RealBufferSendSize; + +int jt808FramePackage(struct ProtocolParameter *para); + diff --git a/custom/jt808/inc/jt808_parser.h b/custom/jt808/inc/jt808_parser.h new file mode 100644 index 0000000..00d1baf --- /dev/null +++ b/custom/jt808/inc/jt808_parser.h @@ -0,0 +1,19 @@ + + +#ifndef JT808_PARSER_H_ +#define JT808_PARSER_H_ + +#include +#include +#include +#include +#include "protocol_parameter.h" + +#define PARSER_NUM 9 +#define BUFFER_SIZE_RECEIVE 1024 // buffer size 发送缓存大小 + +extern unsigned short kTerminalParserCMD[PARSER_NUM]; + +int jt808FrameParse(const unsigned char *in, unsigned int in_len, struct ProtocolParameter *para); + +#endif // JT808_PARSER_H_ diff --git a/custom/jt808/inc/location_report.h b/custom/jt808/inc/location_report.h new file mode 100644 index 0000000..f213ce0 --- /dev/null +++ b/custom/jt808/inc/location_report.h @@ -0,0 +1,333 @@ +#include +// 报警标志位 +union AlarmBit +{ + struct + { + // bit_0 紧急报瞥触动报警开关后触发.收到应答后清零 + unsigned int sos : 1; + // bit_1 超速报警. + unsigned int overspeed : 1; + // bit_2 疲劳驾驶. + unsigned int fatigue : 1; + // bit_3 危险预警. + unsigned int early_warning : 1; + // bit_4 GNSS模块发生故障. + unsigned int gnss_fault : 1; + // bit_5 GNSS天线未接或被剪断. + unsigned int gnss_antenna_cut : 1; + // bit_6 GNSS天线短路. + unsigned int gnss_antenna_shortcircuit : 1; + // bit_7 终端主电源欠压. + unsigned int power_low : 1; + // bit_8 终端主电源掉电. + unsigned int power_cut : 1; + // bit_9 终端LCD或显示器故障. + unsigned int lcd_fault : 1; + // bit_10 TTS模块故障. + unsigned int tts_fault : 1; + // bit_11 摄像头故障. + unsigned int camera_fault : 1; + + // // OBD故障码. + // unsigned int obd_fault_code : 1; + // // 保留5位. + // unsigned int retain1 : 5; + + // bit_12 道路运输证 IC 卡模块故障. + unsigned int transport_license_IC_card_fault : 1; + + // bit_1 超速预警. + unsigned int overspeed_notice : 1; + // bit_2 疲劳驾驶预警. + unsigned int fatigue_notice : 1; + + // 保留3位. + unsigned int retain1 : 3; + + // bit_18 当天累计驾驶超时. + unsigned int day_drive_overtime : 1; + // bit_19 超时停车. + unsigned int stop_driving_overtime : 1; + // bit_20 进出区域.收到应答后清零 + unsigned int in_out_area : 1; + // bit_21 进出路线.收到应答后清零 + unsigned int in_out_road : 1; + // bit_22 路段行驶时间不足/过长.收到应答后清零 + unsigned int road_drive_time : 1; + // bit_23 路线偏离报警. + unsigned int road_deviate : 1; + // bit_24 车辆VSS故障. + unsigned int vss_fault : 1; + // bit_25 车辆油量异常. + unsigned int oil_fault : 1; + // bit_26 车辆被盗(通过车辆防盗器). + unsigned int car_alarm : 1; + // bit_27 车辆非法点火.收到应答后清零 + unsigned int car_acc_alarm : 1; + // bit_28 车辆非法位移.收到应答后清零 + unsigned int car_move : 1; + // 碰撞侧翻报警. + unsigned int collision : 1; + // 保留2位. + unsigned int retain2 : 2; + } bit; + unsigned int value; +}; + +// 状态位 +union StatusBit +{ + struct + { + // ACC开关, 0:ACC关; 1:ACC开. + unsigned int acc : 1; + // 定位标志, 0:未定位; 1:定位. + unsigned int positioning : 1; + // 纬度半球, 0:北纬: 1:南纬. + unsigned int sn_latitude : 1; + // 经度半球, 0:东经; 1:西经. + unsigned int ew_longitude : 1; + // 0:运营状态; 1:停运状态. + unsigned int operation : 1; // 0:运营状态; 1:停运状态. + // 0:经纬度未经保密插件加密; 1:经纬度已经保密插件加密. + unsigned int gps_encrypt : 1; + // 保留2位. + unsigned int retain1 : 2; + // 00: 空车; 01: 半载; 10: 保留; 11: 满载. + unsigned int trip_status : 2; + // 0:车辆油路正常; 1:车辆油路断开. + unsigned int oil_cut : 1; + // 0:车辆电路正常; 1:车辆电路断开. + unsigned int circuit_cut : 1; + // 0:车门解锁; 1: 车门加锁. + unsigned int door_lock : 1; + // 0:门1 关; 1: 门1 开; (前门). + unsigned int door1_status : 1; + // 0:门2 关; 1: 门2 开; (中门). + unsigned int door2_status : 1; + // 0:门 3 关; 1: 门 3 开; (后门). + unsigned int door3_status : 1; + // 0:门 4 关; 1: 门 4 开; (驾驶席门). + unsigned int door4_status : 1; + // 0:门 5 关; 1: 门 5 开; (自定义). + unsigned int door5_status : 1; + // 0: 未使用 GPS 卫星进行定位; 1: 使用 GPS 卫星进行定位. + unsigned int gps_en : 1; + // 0: 未使用北斗卫星进行定位; 1: 使用北斗卫星进行定位. + unsigned int beidou_en : 1; + // 0: 未使用 GLONASS 卫星进行定位; 1: 使用 GLONASS 卫星进行定位. + unsigned int glonass_en : 1; + // 0: 未使用 Galileo 卫星进行定位; 1: 使用 Galileo 卫星进行定位. + unsigned int galileo_en : 1; + // 保留10位. + unsigned int retain2 : 10; + } bit; + unsigned int value; +}; + +// 位置基本信息数据. +struct LocationBasicInformation +{ + // 报警标志 4B + union AlarmBit alarm; + // 状态位定义 4B + union StatusBit status; + // 纬度(以度为单位的纬度值乘以10的6次方, 精确到百万分之一度) 4B + unsigned int latitude; + // 经度(以度为单位的纬度值乘以10的6次方, 精确到百万分之一度) 4B + unsigned int longitude; + // 海拔高度, 单位为米(m) 2B + unsigned short altitude; + // 速度 1/10km/h 2B + unsigned short speed; + // 方向 0-359,正北为0, 顺时针 2B + unsigned short bearing; + // 时间, "YYMMDDhhmmss"(GMT+8时间, 本标准之后涉及的时间均采用此时区).12B + // std::string time; + unsigned char time[13]; +}; + +// 扩展车辆信号状态位 +union ExtendedVehicleSignalBit +{ + struct + { + // 近光灯信号 + unsigned int near_lamp : 1; + // 远光灯信号 + unsigned int farl_amp : 1; + // 右转向灯信号 + unsigned int right_turn_lamp : 1; + // 左转向灯信号 + unsigned int left_turn_lamp : 1; + // 制动信号 + unsigned int breaking : 1; + // 倒档信号 + unsigned int reversing : 1; + // 雾灯信号 + unsigned int fog_lamp : 1; + // 示廓灯 + unsigned int outline_lamp : 1; + // 喇叭信号 + unsigned int horn : 1; + // 空调状态 + unsigned int air_conditioner : 1; + // 空挡信号 + unsigned int neutral : 1; + // 缓速器工作 + unsigned int retarder : 1; + // ABS 工作 + unsigned int abs : 1; + // 加热器工作 + unsigned int heater : 1; + // 离合器状态 + unsigned int clutch : 1; + // 保留17位. + unsigned int retain : 17; + } bit; + unsigned int value; +}; + +// 位置信息上报附加项ID. +enum LocationExtensionId +{ + // 里程, 1/10km, 对应车上里程表读数, DWORD + kMileage = 0x01, + // 油量, 1/10L, 对应车上油量表读数, WORD + kOilMass = 0x02, + // 行驶记录功能获取的速度, 1/10km/h, WORD + kTachographSpeed = 0x03, + // 需要人工确认报警事件的 ID, 从 1 开始计数, WORD + kAlarmCount = 0x04, + // 超速报警附加信息, BYTE or BYTE+DWORD + kOverSpeedAlarm = 0x11, + // 进出区域/路线报警附加信息, BYTE+DWORD+BYTE + kAccessAreaAlarm = 0x12, + // 路段行驶时间不足/过长报警附加信息, DWORD+WORD+BYTE + kDrivingTimeAlarm = 0x13, + // 扩展车辆信号状态位, DWORD + kVehicleSignalStatus = 0x25, + // IO 状态位, WORD + kIoStatus = 0x2A, + // 模拟量, DWORD + kAnalogQuantity = 0x2B, + // 无线通信网络信号强度, BYTE + kNetworkQuantity = 0x30, + // GNSS 定位卫星数, BYTE + kGnssSatellites = 0x31, + // 后续自定义信息长度, BYTE + kCustomInformationLength = 0xE0, + // 定位解状态, BYTE + kPositioningStatus = 0xEE, + + //称重信息ID + kWeightInfo = 0xF3, + + // 视频报警上报 + kAlarm_video = 0x14, // 视频相关报警,附加信息长度 4B + kAlarm_video_Signal_Lost = 0x15, // 视频信号丢失报警状态,附加信息长度 4B + kAlarm_video_Signal_Occlusion = 0x16, // 视频信号遮挡报警状态,附加信息长度 4B + kAlarm_Memory_Bad = 0x17, // 存储器故障报警状态,附加信息长度 2B + kAlarm_Abnormal_Drive_Behavior = 0x18, // 异常驾驶行为报警详细描述,附加信息长度 2B + +}; + +// 位置信息附加项存储定义: key: itemid, value: itemvalue. +// using LocationExtensions = std::map>; + +// 超速报警附加信息位置类型, BYTE. +enum kOverSpeedAlarmLocationType +{ + // 0:无特定位置. + kOverSpeedAlarmNoSpecificLocation = 0x0, + // 1:圆形区域. + kOverSpeedAlarmCircularArea, + // 2:矩形区域. + kOverSpeedAlarmRectangleArea, + // 3:多边形区域. + kOverSpeedAlarmPolygonArea, + // 4:路段. + kOverSpeedAlarmRoadSection +}; + +// 进出区域/路线报警附加信息消息体位置类型, BYTE. +enum kAccessAreaAlarmLocationType +{ + // 1:圆形区域. + kAccessAreaAlarmCircularArea, + // 2:矩形区域. + kAccessAreaAlarmRectangleArea, + // 3:多边形区域. + kAccessAreaAlarmPolygonArea, + // 4:路线. + kOverSpeedAlarmRoute +}; + +// 进出区域/路线报警附加信息消息体方向类型, BYTE. +enum kAccessAreaAlarmDirectionType +{ + // 进入区域. + kAccessAreaAlarmInArea = 0x0, + // 离开区域. + kAccessAreaAlarmOutArea +}; + +// IO 状态位 +union IoStatusBit +{ + struct + { + // 深度休眠状态 + unsigned short deep_rmancy : 1; + // 休眠状态 + unsigned short dormancy : 1; + // 保留14位. + unsigned short retain : 14; + } bit; + unsigned short value; +}; + +// 临时位置跟踪控制信息. +struct LocationTrackingControl +{ + // 时间间隔. + unsigned short interval; + // 单位为秒(s), 有效时间. + unsigned int tracking_time; +}; +/* + // 设置超速报警附加信息消息体. + int SetOverSpeedAlarmBody(unsigned char const &location_type, + unsigned int const &area_route_id, + std::vector *out); + + // 获得超速报警报警附加信息消息体. + int GetOverSpeedAlarmBody(std::vector const &out, + unsigned char *location_type, + unsigned int *area_route_id); + + // 设置进出区域/路线报警附加信息消息体. + int SetAccessAreaAlarmBody(unsigned char const &location_type, + unsigned int const &area_route_id, + unsigned char const &direction, + std::vector *out); + + // 获得进出区域/路线报警附加信息消息体. + int GetAccessAreaAlarmBody(std::vector const &out, + unsigned char *location_type, + unsigned int *area_route_id, + unsigned char *direction); +*/ + +// void initGPSInfo(struct ProtocolParameter *para); +// void initGPSInfo(struct LocationBasicInformation *para); +// void UpdateLocation(double const latitude, double const longitude, float const altitude, float const speed, +// float const bearing, unsigned char *timestamp); + +// void initGPSInfo(struct ProtocolParameter *para, unsigned int v_alarm_value, +// unsigned int v_status_value, double const v_latitude, +// double const v_longitude, float const v_altitude, +// float const v_speed, float const v_bearing, +// unsigned char *v_timestamp); + diff --git a/custom/jt808/inc/protocol_parameter.h b/custom/jt808/inc/protocol_parameter.h new file mode 100644 index 0000000..e9c0e45 --- /dev/null +++ b/custom/jt808/inc/protocol_parameter.h @@ -0,0 +1,315 @@ +#ifndef JT808_PROTOCOL_PARAMETER_H_ +#define JT808_PROTOCOL_PARAMETER_H_ + +#include +#include +#include + +#include "location_report.h" +#include "terminal_parameter.h" +#include "terminal_control.h" + +// #define PACKAGER_NUM 9 +// #define PARSER_NUM 9 + +// 已支持的协议命令. +enum SupportedCommands +{ + kTerminalGeneralResponse = 0x0001, // 终端通用应答. + kPlatformGeneralResponse = 0x8001, // 平台通用应答. + kTerminalHeartBeat = 0x0002, // 终端心跳. + kFillPacketRequest = 0x8003, // 补传分包请求. + kTerminalRegister = 0x0100, // 终端注册. + kTerminalRegisterResponse = 0x8100, // 终端注册应答. + kTerminalLogOut = 0x0003, // 终端注销. + kTerminalAuthentication = 0x0102, // 终端鉴权. + kSetTerminalParameters = 0x8103, // 设置终端参数. + kGetTerminalParameters = 0x8104, // 查询终端参数. + kGetSpecificTerminalParameters = 0x8106, // 查询指定终端参数. + kGetTerminalParametersResponse = 0x0104, // 查询终端参数应答. + kTerminalControl = 0x8105, //终端控制 + kTerminalUpgrade = 0x8108, // 下发终端升级包. + kTerminalUpgradeResultReport = 0x0108, // 终端升级结果通知. + kLocationReport = 0x0200, // 位置信息汇报. + kGetLocationInformation = 0x8201, // 位置信息查询. + kGetLocationInformationResponse = 0x0201, // 位置信息查询应答. + kLocationTrackingControl = 0x8202, // 临时位置跟踪控制. + +}; + +// // 所有应答命令. +// unsigned short kResponseCommand[] = { +// kTerminalGeneralResponse, //终端通用应答 +// kPlatformGeneralResponse, //平台通用应答 +// kTerminalRegisterResponse, //终端注册应答 +// kGetTerminalParametersResponse, //查询终端参数应答 +// kGetLocationInformationResponse, //位置信息查询应答 +// }; + +// // 所有终端解析命令. +// unsigned short kTerminalParserCMD[PARSER_NUM] = { +// kPlatformGeneralResponse, //平台通用应答 +// kFillPacketRequest, // 补传分包请求. +// kTerminalRegisterResponse, // 终端注册应答. +// kSetTerminalParameters, // 设置终端参数. +// kGetTerminalParameters, // 查询终端参数. +// kGetSpecificTerminalParameters, // 查询指定终端参数. +// kTerminalControl, //终端控制 +// kTerminalUpgrade, // 下发终端升级包. +// kGetLocationInformation, // 位置信息查询. +// }; + +// // 所有终端数据打包命令. +// unsigned short kTerminalPackagerCMD[PACKAGER_NUM] = { +// kTerminalGeneralResponse, // 终端通用应答. +// kTerminalHeartBeat, // 终端心跳. +// kTerminalRegister, // 终端注册. +// kTerminalLogOut, // 终端注销. +// kTerminalAuthentication, // 终端鉴权. +// kGetTerminalParametersResponse, // 查询终端参数应答. +// kTerminalUpgradeResultReport, // 终端升级结果通知. +// kLocationReport, // 位置信息汇报. +// kGetLocationInformationResponse, // 位置信息查询应答. +// }; + +// 车牌颜色. +enum VehiclePlateColor +{ + kVin = 0x0, // 车辆未上牌. + kBlue, + kYellow, + kBlack, + kWhite, + kOther +}; + +// 通用应答结果. +enum GeneralResponseResult +{ + kSuccess = 0x0, // 成功/确认. + kFailure = 0x1, // 失败. + kMessageHasWrong =0x2, // 消息有误. + kNotSupport = 0x3, // 不支持. + kAlarmHandlingConfirmation = 0x4, // 报警处理确认, 仅平台应答使用. +}; + +// 注册应答结果. +enum RegisterResponseResult +{ + kRegisterSuccess = 0x0, // 成功. + kVehiclesHaveBeenRegistered = 0x1, // 车辆已被注册. + kNoSuchVehicleInTheDatabase =0x2, // 数据库中无该车辆. + kTerminalHaveBeenRegistered = 0x3, // 终端已被注册. + kNoSuchTerminalInTheDatabase = 0x4, // 数据库中无该终端. +}; + +// 消息体属性. +union MsgBodyAttribute +{ + struct + { + // 消息体长度, 占用10bit. + unsigned short msglen : 10; + // 数据加密方式, 当此三位都为0, 表示消息体不加密, + // 当第10位为1, 表示消息体经过RSA算法加密. + unsigned short encrypt : 3; + // 分包标记. + unsigned short packet : 1; + // 保留2位. + unsigned short retain : 2; + } bit; + unsigned short u16val; +}; + +// 消息内容起始位置. +enum MsgBodyPos +{ + MSGBODY_NOPACKET_POS = 13, // 短消息体消息内容起始位置.SMS + MSGBODY_PACKET_POS = 17, // 长消息体消息内容起始位置. +}; + +// 转义相关标识. +enum ProtocolEscapeFlag +{ + PROTOCOL_SIGN = 0x7E, // 标识位. + PROTOCOL_ESCAPE = 0x7D, // 转义标识. + PROTOCOL_ESCAPE_SIGN = 0x02, // 0x7E<-->0x7D后紧跟一个0x02. + PROTOCOL_ESCAPE_ESCAPE = 0x01, // 0x7D<-->0x7D后紧跟一个0x01. +}; + +// 消息头. +struct MsgHead +{ + // 消息ID. + unsigned short msg_id; + // 消息体属性. + union MsgBodyAttribute msgbody_attr; + // 终端手机号. + unsigned char phone_num[13]; + // 消息流水号. + unsigned short msg_flow_num; + // 总包数, 分包情况下使用. + unsigned short total_packet; + // 当前包编号, 分包情况下使用. + unsigned short packet_seq; +}; + +// 注册信息. +struct RegisterInfo +{ + // 省域ID. + unsigned short province_id; + + // 市县域ID. + unsigned short city_id; + + // 制造商ID, 固定5个字节. + unsigned char manufacturer_id[5]; + + // 终端型号, 固定20个字节, 位数不足后补0x00. + unsigned char terminal_model[20]; + + // 终端ID, 固定7个字节, 位数不足后补0x00. + unsigned char terminal_id[7]; + + // 车牌颜色, 0表示未上牌. + unsigned char car_plate_color; + + // 车辆标识, 仅在上牌时使用. + unsigned char car_plate_num[12]; +}; + +//struct RegisterID +//{ +// unsigned char PhoneNumber[20]; +// unsigned char TerminalId[20]; +//}; + +// 升级类型. +enum kTerminalUpgradeType +{ + // 终端. + kTerminal = 0x0, + // 道路运输证 IC 卡读卡器 + kICCardReader = 0xc, + // 北斗卫星定位模块. + kGNSS = 0x34, +}; + +// 升级结果. +enum kTerminalUpgradeResultType +{ + // 终端升级成功. + kTerminalUpgradeSuccess = 0x0, + // 终端升级失败. + kTerminalUpgradeFailed, + // 终端升级取消. + kTerminalUpgradeCancel +}; + +// 升级信息. +struct UpgradeInfo +{ + // 升级类型. + unsigned char upgrade_type; + // 升级结果. + unsigned char upgrade_result; + // 制造商ID, 固定5个字节. + unsigned char manufacturer_id[5]; + // 升级版本号. + const char *version_id; + // 升级包总长度. + unsigned int upgrade_data_total_len; + // 升级数据包. + char *upgrade_data; +}; + +// 补传分包信息. +struct FillPacket +{ + // 分包数据首包的消息流水号. + unsigned short first_packet_msg_flow_num; + // 需要重传包的ID. + const char packet_id[50]; +}; + +// 协议格式、各消息ID等相关参数. +struct ProtocolParameter +{ + unsigned char respone_result; + unsigned short respone_msg_id; + unsigned short respone_flow_num; + // 消息头. + struct MsgHead msg_head; + // 终端注册时需填充注册信息. + struct RegisterInfo register_info; +// struct RegisterID register_id; + // 平台随机生成鉴权码. + uint8_t authentication_code[40]; + + //IMEI + uint8_t IMEI[15]; + //软件版本号 + uint8_t softwareVersion[20]; + // 设置终端参数项. + struct TerminalParameters terminal_parameters; + // 查询终端参数ID列表. + // std::vector terminal_parameter_ids; + // 位置上报时填充位置基本信息, 必须项. + struct LocationBasicInformation location_info; + // 位置上报时填充位置附加信息, 可选项. + // LocationExtensions location_extension; + // 临时位置跟踪控制信息. + struct LocationTrackingControl location_tracking_control; + + // 升级信息. + struct UpgradeInfo upgrade_info; + // 补传分包信息. + struct FillPacket fill_packet; + + //终端控制 + struct TerminalControl terminal_control; + + // // 保留字段. + // std::vector retain; + + // 用于解析消息. + struct + { + unsigned char respone_result; + unsigned short respone_msg_id; + unsigned short respone_flow_num; + // 解析出的消息头. + struct MsgHead msg_head; + // 解析出的注册信息. + struct RegisterInfo register_info; + // 解析出的鉴权码. + // 平台随机生成鉴权码. + unsigned char *authentication_code; + // 解析出的设置终端参数项. + struct TerminalParameters terminal_parameters; + // 解析出的查询终端参数ID列表. + // std::vector terminal_parameter_ids; + // 解析出的位置基本信息. + struct LocationBasicInformation location_info; + // 解析出的位置附加信息. + // LocationExtensions location_extension; + // 解析出的临时位置跟踪控制信息. + struct LocationTrackingControl location_tracking_control; + + // 解析出的升级信息. + struct UpgradeInfo upgrade_info; + // 解析出的补传分包信息. + struct FillPacket fill_packet; + + //终端控制 + struct TerminalControl terminal_control; + + // 解析出的保留字段. + // std::vector retain; + + } parse; +}; + + +#endif // JT808_PROTOCOL_PARAMETER_H_ diff --git a/custom/jt808/inc/set_terminal_parameter.h b/custom/jt808/inc/set_terminal_parameter.h new file mode 100644 index 0000000..03eaf67 --- /dev/null +++ b/custom/jt808/inc/set_terminal_parameter.h @@ -0,0 +1,21 @@ +#include "protocol_parameter.h" +#include "bcd.h" +#include "util.h" + + +#define PARA_SETTING_LIMIT 10 //终端打包器命令相应消息ID数量 + +// 所有终端数据打包命令. +extern unsigned short kParameterSettingCMD[PARA_SETTING_LIMIT]; + +void jt808ParameterSettingParse(unsigned int id,unsigned char *buf,unsigned char buf_len, struct ProtocolParameter *para); +void handle_HeartBeatInterval(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); +void handle_MainServerAddress(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); +void handle_ServerPort(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); +void handle_DefaultTimeReportTimeInterval(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); +void handle_CornerPointRetransmissionAngle(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); +void handle_MaxSpeed(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); +void handle_ProvinceID(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); +void handle_CityID(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); +void handle_CarPlateNum(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); +void handle_CarPlateColor(unsigned char *buf,unsigned char buf_len,struct ProtocolParameter *para); diff --git a/custom/jt808/inc/terminal_control.h b/custom/jt808/inc/terminal_control.h new file mode 100644 index 0000000..b6ff4ec --- /dev/null +++ b/custom/jt808/inc/terminal_control.h @@ -0,0 +1,35 @@ +#ifndef JT808_TERMINAL_CONTROL_H_ +#define JT808_TERMINAL_CONTROL_H_ + +#include +#include +//#include +#include +#include "util.h" + +// 0x8105终端控制命令字. +union TerminalCtrlCmdByte +{ + struct + { + unsigned char u8val_0 : 1; // + unsigned char u8val_1 : 1; // 无线升级 + unsigned char u8val_2 : 1; // 控制终端连接指定服务器 + unsigned char u8val_3 : 1; // 终端关机 + unsigned char u8val_4 : 1; // 终端复位 + unsigned char u8val_5 : 1; // 终端恢复出厂设置 + unsigned char u8val_6 : 1; // 关闭数据通信 + unsigned char u8val_7 : 1; // 关闭所有无线通信 + } bit; + unsigned char u8val; +}; + +// 0x8105终端控制. +struct TerminalControl +{ + // TerminalCtrlCmdByte cmdByte; // 命令字 + unsigned char cmdByte; // 命令字 1:无线升级;2:控制终端连接指定服务器;3:终端关机;4:终端复位;5:终端恢复出厂设置;6:关闭数据通信;7:关闭所有无线通信 + const char *cmdParameter; // 命令参数 +}; + +#endif diff --git a/custom/jt808/inc/terminal_parameter.h b/custom/jt808/inc/terminal_parameter.h new file mode 100644 index 0000000..77b6dda --- /dev/null +++ b/custom/jt808/inc/terminal_parameter.h @@ -0,0 +1,504 @@ +#ifndef JT808_TERMINAL_PARAMETER_H_ +#define JT808_TERMINAL_PARAMETER_H_ + +#include +#include +//#include +#include +#include "util.h" + +// 终端参数设置项参数ID. +enum TerminalParameterID +{ + // DWORD, 终端心跳发送间隔(s). + kTerminalHeartBeatInterval = 0x0001, + + //STRING, 主服务器地址,IP 或域名 + kMainServerAddress = 0x0013, + + //DWORD, 服务器 TCP 端口 + kServerPort = 0x0018, + + // DWORD, 缺省时间汇报间隔 + kDefaultTimeReportTimeInterval = 0x0029, + + // DWORD, 拐点补传角度, < 180°. + kCornerPointRetransmissionAngle = 0x0030, + + // DWORD, 最高速度, km/h. + kMaxSpeed = 0x0055, + + // WORD, 车辆所在的省域 ID + kProvinceID = 0x0081, + + // WORD, 车辆所在的市域 ID + kCityID = 0x0082, + + //STRING, 公安交通管理部门颁发的机动车号牌 + kCarPlateNum = 0x0083, + + //车牌颜色,按照 JT/T415-2006 的 5.4.12 + kCarPlateColor = 0x0084, +}; + +struct TerminalParameters +{ + // DWORD, 终端心跳发送间隔(s). + unsigned int HeartBeatInterval; + + //STRING, 主服务器地址,IP 或域名 + unsigned char MainServerAddress[50]; + + //DWORD, 服务器 TCP 端口 + unsigned int ServerPort; + + // DWORD, 缺省时间汇报间隔 + unsigned int DefaultTimeReportTimeInterval; + + // DWORD, 拐点补传角度, < 180°. + unsigned int CornerPointRetransmissionAngle; + + // DWORD, 最高速度, km/h. + unsigned int MaxSpeed; + + // WORD, 车辆所在的省域 ID + unsigned short ProvinceID; + + // WORD, 车辆所在的市域 ID + unsigned short CityID; + + //STRING, 公安交通管理部门颁发的机动车号牌 + unsigned char CarPlateNum[12]; + + //车牌颜色,按照 JT/T415-2006 的 5.4.12 + unsigned char CarPlateColor; + + // DWORD, 判断是否已经进行出厂化参数设置 + unsigned int initFactoryParameters; + + //STRING, 版本号 + unsigned char version[12]; + + char PhoneNumber[20]; + char TerminalId[20]; + +}; + + +#endif // JT808_TERMINAL_PARAMETER_H_ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//#ifndef JT808_TERMINAL_PARAMETER_H_ +//#define JT808_TERMINAL_PARAMETER_H_ + +//#include +//#include +////#include +//#include +//#include "util.h" + +//// namespace libjt808 //原C++名称空间部分 +//// { //原C++名称空间部分 + +// // 终端参数设置项参数ID. +// enum TerminalParameterID +// { +// // DWORD, 终端心跳发送间隔(s). +// kTerminalHeartBeatInterval = 0x0001, +//// // DWORD, TCP消息应答超时时间(s). +//// kTCPResponseTimeout = 0x0002, +//// // DWORD, TCP消息重传次数. +//// kTCPMsgRetransmissionTimes = 0x0003, +//// // DWORD, UDP消息应答超时时间(s). +//// kUDPResponseTimeout = 0x0004, +//// // DWORD, UDP消息重传次数 +//// kUDPMsgRetransmissionTimes = 0x0005, +//// // DWORD, SMS消息应答超时时间(s). +//// kSMSResponseTimeout = 0x0006, +//// // DWORD, SMS消息重传次数. +//// kSMSMsgRetransmissionTimes = 0x0007, +//// // DWORD, 位置汇报策略, 0:定时汇报; 1:定距汇报; 2:定时和定距汇报. + +// +// kMainServerAddress = 0x0013, +// //STRING, 主服务器地址,IP 或域名 +// +// kServerPort = 0x0018, +// //DWORD, 服务器 TCP 端口 +// +//// kLocationReportWay = 0x0020, +//// // DWORD, 位置汇报方案, 0:根据 ACC 状态; 1:根据登录状态和ACC +//// // 状态, 先判断登录状态, 若登录再根据 ACC 状态. +//// kLocationReportPlan = 0x0021, +//// // DWORD, 驾驶员未登录汇报时间间隔. +//// kDriverNotLoginReportTimeInterval = 0x0022, +//// // DWORD, 休眠时汇报时间间隔 +//// kSleepingReportTimeInterval = 0x0027, +//// // DWORD, 紧急报警时汇报时间间隔 +//// kAlarmingReportTimeInterval = 0x0028, +//// // DWORD, 缺省时间汇报间隔 +// kDefaultTimeReportTimeInterval = 0x0029, +// // DWORD, 缺省距离汇报间隔 +//// kDefaultReportDistanceInterval = 0x002C, +//// // DWORD, 驾驶员未登录汇报距离间隔. +//// kDriverNotLoginReportDistanceInterval = 0x002D, +//// // DWORD, 休眠时汇报距离间隔 +//// kSleepingReportDistanceInterval = 0x002E, +//// // DWORD, 紧急报警时汇报距离间隔 +//// kAlarmingReportDistanceInterval = 0x002F, +//// // DWORD, 拐点补传角度, < 180°. +// kCornerPointRetransmissionAngle = 0x0030, +// // DWORD, 报警屏蔽字, 与位置信息汇报消息中的报警标志相对 +// // 应, 相应位为1则相应报警被屏蔽. +//// kAlarmShieldWord = 0x0050, +//// // DWORD, 报警发送文本SMS开关, 与位置信息汇报消息中的报警 +//// // 标志相对应, 相应位为1则相应报警时发送文本SMS. +//// kAlarmSendSMSText = 0x0051, +//// // DWORD, 报警拍摄开关, 与位置信息汇报消息中的报警标志相 +//// // 对应, 相应位为1则相应报警时摄像头拍摄. +//// kAlarmShootSwitch = 0x0052, +//// // DWORD, 报警拍摄存储标志, 与位置信息汇报消息中的报警标 +//// // 志相对应, 相应位为1则对相应报警时拍的照片进行 +//// // 存储, 否则实时上传. +//// kAlarmShootSaveFlag = 0x0053, +//// // DWORD, 关键标志, 与位置信息汇报消息中的报警标志相对应, +//// // 相应位为1则对相应报警为关键报警. +//// kAlarmKeyFlag = 0x0054, +// // DWORD, 最高速度, km/h. +// kMaxSpeed = 0x0055, +//// // BYTE, GNSS定位模式, 定义如下: +//// // bit0, 0: 禁用GPS定位, 1: 启用GPS定位; +//// // bit1, 0: 禁用北斗定位, 1: 启用北斗定位; +//// // bit2, 0: 禁用GLONASS定位, 1: 启用GLONASS定位; +//// // bit3, 0: 禁用Galileo定位, 1: 启用Galileo定位. +// kProvinceID = 0x0081, +// // WORD, 车辆所在的省域 ID +// +// KCityID = 0x0082, +// // WORD, 车辆所在的市域 ID +// +// KCarPlateNum = 0x0083, +// //STRING, 公安交通管理部门颁发的机动车号牌 +// +// KCarPlateColor = 0x0084, +// //车牌颜色,按照 JT/T415-2006 的 5.4.12 +// +// kGNSSPositionMode = 0x0090, +// // BYTE, GNSS波特率, 定义如下: +// // 0x00: 4800; 0x01: 9600: 0x02: 19200; +// // 0x03: 38400; 0x04: 57600; 0x05: 115200. +// kGNSSBaudeRate = 0x0091, +// // BYTE, GNSS模块详细定位数据输出频率, 定义如下: +// // 0x00: 500ms; 0x01: 1000ms(默认值); +// // 0x02: 2000ms; 0x03: 3000ms; 0x04: 4000m. +// kGNSSOutputFrequency = 0x0092, +// // DWORD, GNSS模块详细定位数据采集频率(s), 默认为1. +// kGNSSOutputCollectFrequency = 0x0093, +// // BYTE, GNSS模块详细定位数据上传方式: +// // 0x00, 本地存储, 不上传(默认值); +// // 0x01, 按时间间隔上传; +// // 0x02, 按距离间隔上传; +// // 0x0B, 按累计时间上传, 达到传输时间后自动停止上传; +// // 0x0C, 按累计距离上传, 达到距离后自动停止上传; +// // 0x0D, 按累计条数上传, 达到上传条数后自动停止上传. +// kGNSSOutputUploadWay = 0x0094, +// // DWORD, GNSS模块详细定位数据上传设置: +// // 上传方式为0x01时, 单位为秒; +// // 上传方式为0x02时, 单位为米; +// // 上传方式为0x0B时, 单位为秒; +// // 上传方式为0x0C时, 单位为米; +// // 上传方式为0x0D时, 单位为条. +// kSetGNSSDataUpload = 0x0095, +// // DWORD, CAN总线通道1采集时间间隔(ms), 0表示不采集. +// kCANBus1CollectInterval = 0x0100, +// // WORD, CAN总线通道1上传时间间隔(s), 0表示不上传. +// kCANBus1UploadInterval = 0x0101, +// // DWORD, CAN总线通道2采集时间间隔(ms), 0表示不采集. +// kCANBus2CollectInterval = 0x0102, +// // WORD, CAN总线通道2上传时间间隔(s), 0表示不上传. +// kCANBus2UploadInterval = 0x0103, +// // BYTE[8], CAN总线ID单独采集设置: +// // bit63-bit32 表示此ID采集时间间隔(ms), 0表示不采集; +// // bit31 表示CAN通道号, 0: CAN1, 1: CAN2; +// // bit30 表示帧类型, 0: 标准帧, 1: 扩展帧; +// // bit29 表示数据采集方式, 0: 原始数据, 1: 采集区间的计算值; +// // bit28-bit0 表示CAN总线ID. +// kSetCANBusSpecial = 0x0110, +// }; + +// // GNSS模块数据输出波特率. +// enum GNSSModelBaudeRate +// { +// kBDRT4800 = 0x0, +// kBDRT9600, +// kBDRT19200, +// kBDRT38400, +// kBDRT57600, +// kBDRT115200, +// }; + +/* + // 终端参数存储定义: key: itemid, value: itemvalue. + // using TerminalParameters = std::map>;//原C++相关定义 + + // + // 终端参数转换. + // + // undefined type --> terminal parameter item. + template + inline int SetTerminalParameter(unsigned int const &key, T const &value, TerminalParameters *items) + { + return -1; + } + + // terminal parameter item --> undefined type. + template + inline int GetTerminalParameter(TerminalParameters const &items, unsigned int const &key, T *value) + { + return -1; + } + + // unsigned char --> terminal parameter item. + template <> + inline int SetTerminalParameter(unsigned int const &key, unsigned char const &value, TerminalParameters *items) + { + if (items == nullptr) + return -1; + auto it = items->find(key); + if (it != items->end()) + { + it->second.clear(); + it->second.push_back(value); + } + else + { + items->insert(std::make_pair(key, std::vector{value})); + } + return 0; + } + + // terminal parameter item --> unsigned char . + template <> + inline int GetTerminalParameter(TerminalParameters const &items, unsigned int const &key, unsigned char *value) + { + if (value == nullptr) + return -1; + auto const &it = items.find(key); + if (it != items.end()) + { + if (it->second.size() != 1) + return -1; + *value = it->second[0]; + return 0; + } + return -1; + } + + // unsigned short --> terminal parameter item. + template <> + inline int SetTerminalParameter(unsigned int const &key, unsigned short const &value, TerminalParameters *items) + { + if (items == nullptr) + return -1; + U16ToU8Array cvt; + cvt.u16val = EndianSwap16(value); + auto it = items->find(key); + if (it != items->end()) + { + it->second.clear(); + it->second.assign(cvt.u8array, cvt.u8array + 2); + } + else + { + items->insert(std::make_pair(key, + std::vector(cvt.u8array, cvt.u8array + 2))); + } + return 0; + } + + // terminal parameter item --> unsigned short . + template <> + inline int GetTerminalParameter(TerminalParameters const &items, unsigned int const &key, unsigned short *value) + { + if (value == nullptr) + return -1; + auto const &it = items.find(key); + if (it != items.end()) + { + if (it->second.size() != 2) + return -1; + *value = it->second[0] * 256 + it->second[1]; + return 0; + } + return -1; + } + + // unsigned int --> terminal parameter item. + template <> + inline int SetTerminalParameter(unsigned int const &key, unsigned int const &value, TerminalParameters *items) + { + if (items == nullptr) + return -1; + U32ToU8Array cvt; + cvt.u32val = EndianSwap32(value); + auto it = items->find(key); + if (it != items->end()) + { + it->second.clear(); + it->second.assign(cvt.u8array, cvt.u8array + 4); + } + else + { + items->insert(std::make_pair(key, + std::vector(cvt.u8array, cvt.u8array + 4))); + } + return 0; + } + + // terminal parameter item --> unsigned int . + template <> + inline int GetTerminalParameter(TerminalParameters const &items, unsigned int const &key, unsigned int *value) + { + if (value == nullptr) + return -1; + auto const &it = items.find(key); + if (it != items.end()) + { + if (it->second.size() != 4) + return -1; + *value = it->second[0] * 65536 * 256 + + it->second[1] * 65536 + + it->second[2] * 256 + + it->second[3]; + return 0; + } + return -1; + } + + // std::string --> terminal parameter item. + template <> + inline int SetTerminalParameter(unsigned int const &key, std::string const &value, TerminalParameters *items) + { + if (items == nullptr) + return -1; + auto it = items->find(key); + if (it != items->end()) + { + it->second.clear(); + it->second.assign(value.begin(), value.end()); + } + else + { + items->insert(std::make_pair(key, + std::vector(value.begin(), value.end()))); + } + return 0; + } + + // terminal parameter item --> std::string. + template <> + inline int GetTerminalParameter(TerminalParameters const &items, unsigned int const &key, std::string *value) + { + if (value == nullptr) + return -1; + auto const &it = items.find(key); + if (it != items.end()) + { + value->clear(); + value->assign(it->second.begin(), it->second.end()); + return 0; + } + return -1; + } + + // + // 协议支持的终端参数项封装/解析. + // + + // 封装终端心跳发送间隔配置. + // Args: + // intv: 终端心跳时间间隔. + // Returns: + // 成功返回0, 失败返回-1. + inline int PackagingTerminalParameterTerminalHeartBeatInterval(unsigned int const &intv, TerminalParameters *items) + { + return SetTerminalParameter(kTerminalHeartBeatInterval, intv, items); + } + + // 解析终端心跳发送间隔配置. + // Args: + // items: 终端参数项的map容器. + // intv: 保存解析的终端心跳时间间隔. + // Returns: + // 成功返回0, 失败返回-1. + inline int ParseTerminalParameterTerminalHeartBeatInterval(TerminalParameters const &items, unsigned int *intv) + { + return GetTerminalParameter(items, kTerminalHeartBeatInterval, intv); + } +*/ + +// } // namespace libjt808 //原C++名称空间部分 + +//#endif // JT808_TERMINAL_PARAMETER_H_ diff --git a/custom/jt808/inc/terminal_register.h b/custom/jt808/inc/terminal_register.h new file mode 100644 index 0000000..da8ff7a --- /dev/null +++ b/custom/jt808/inc/terminal_register.h @@ -0,0 +1,64 @@ +#ifndef JT808_TERMINAL_REGISTER_H_ +#define JT808_TERMINAL_REGISTER_H_ + + +#include +#include +//#include +#include +#include "protocol_parameter.h" + + +/// @brief 设置注册省域ID +/// @param provinceId +void setRegisterProvinceId(unsigned short provinceId); + +/// @brief 获取省域ID +/// @return +unsigned short getRegisterProvinceId(void); + +/// @brief 设置市县域ID +/// @param cityId +void setRegisterCityId(unsigned short cityId); + +/// @brief 获取市县域ID +/// @return +unsigned short getRegisterCityId(void); + +// 制造商ID, 固定5个字节. +void setRegister_manufacturer_id(const char *manufacturerId, unsigned int manufacturer_id_size); + +const char *getRegister_manufacturer_id(void); + +// 终端型号, 固定20个字节, 位数不足后补0x00. +void setRegister_terminal_model(const char *terminalModel, unsigned int terminalModel_size); + +/// @brief 获取终端型号 +/// @return +const char *getRegister_terminal_model(void); + +// 终端ID, 固定7个字节, 位数不足后补0x00. +void setRegister_terminal_id(const char *terminal_id, unsigned int terminal_id_size); + +/// @brief 获取终端型号 +/// @return +const char *getRegister_terminal_id(void); + +// 车牌颜色, 0表示未上牌. +void setRegister_car_plate_color(unsigned char car_plate_color); + +/// @brief 获取市县域ID +/// @return +unsigned char getRegister_car_plate_color(void); + +// 车辆标识, 仅在上牌时使用. +void setRegister_car_plate_num(const char *car_plate_num, unsigned int car_plate_num_size); + +/// @brief 获取终端型号 +/// @return +//const char *getRegister_car_plate_num(void); + +void initRegisterInfo(struct ProtocolParameter *para); + +#endif //JT808_TERMINAL_REGISTER_H_ + diff --git a/custom/jt808/inc/util.h b/custom/jt808/inc/util.h new file mode 100644 index 0000000..dd13b8b --- /dev/null +++ b/custom/jt808/inc/util.h @@ -0,0 +1,54 @@ + +#ifndef JT808_UTIL_H_ +#define JT808_UTIL_H_ + +#include +#include +#include +#include +#include +// #include + +// namespace libjt808 +// { + +// 无符号64位整型转无符号字节数组. +union U64ToU8Array +{ + unsigned long u64val; + unsigned char u8array[8]; +}; + +// 无符号32位整型转无符号字节数组. +union U32ToU8Array +{ + unsigned int u32val; + unsigned char u8array[4]; +}; + +// 无符号16位整型转无符号字节数组. +union U16ToU8Array +{ + unsigned short u16val; + unsigned char u8array[2]; +}; + +// 大小端互换. +unsigned short EndianSwap16(unsigned short u16val); + +// 大小端互换. +unsigned int EndianSwap32(unsigned int u32val); + + +// 转义函数. +int Escape_C(unsigned char *in, unsigned int inlen, unsigned char *out, unsigned int *outlen); +int ReverseEscape_C(unsigned char *in, unsigned int inlen, unsigned char *out, unsigned int *outlen); + +// 异或校验. +unsigned char BccCheckSum(const unsigned char *src, unsigned long len); + +//处理字符串,返回子串在母串的第一个字符的位置 +int strStr(const char * haystack, const char * needle); + + +#endif // JT808_UTIL_H_ diff --git a/custom/jt808/jt808.mk b/custom/jt808/jt808.mk new file mode 100644 index 0000000..81b7c7d --- /dev/null +++ b/custom/jt808/jt808.mk @@ -0,0 +1,14 @@ + +CUSTOM_MAIN_DIR := custom/jt808 + +OC_FILES += $(CUSTOM_MAIN_DIR)/src/bcd.c +OC_FILES += $(CUSTOM_MAIN_DIR)/src/client_manager.c +OC_FILES += $(CUSTOM_MAIN_DIR)/src/gbk_utf8.c +OC_FILES += $(CUSTOM_MAIN_DIR)/src/jt808_packager.c +OC_FILES += $(CUSTOM_MAIN_DIR)/src/jt808_parser.c +OC_FILES += $(CUSTOM_MAIN_DIR)/src/location_report.c +OC_FILES += $(CUSTOM_MAIN_DIR)/src/set_terminal_parameter.c +OC_FILES += $(CUSTOM_MAIN_DIR)/src/terminal_register.c +OC_FILES += $(CUSTOM_MAIN_DIR)/src/util.c + +INC += -I'$(CUSTOM_MAIN_DIR)/inc' \ No newline at end of file diff --git a/custom/jt808/src/bcd.c b/custom/jt808/src/bcd.c new file mode 100644 index 0000000..50d85b3 --- /dev/null +++ b/custom/jt808/src/bcd.c @@ -0,0 +1,70 @@ +#include "bcd.h" +#include "jt808_debug.h" + +unsigned char HexToBcd(unsigned char src) +{ + unsigned char temp; + temp = ((src / 10) << 4) + (src % 10); + return temp; +} + + unsigned char BcdToHex(unsigned char src) +{ + unsigned char temp; + temp = (src >> 4) * 10 + (src & 0x0f); + return temp; +} + +unsigned char *jt808StringToBcdCompress(const unsigned char *src, unsigned char *dst, int srclen) +{ + unsigned char *ptr = dst; + unsigned char temp; + if (srclen % 2 != 0) + { + *ptr++ = HexToBcd(*src++ - '0'); + } + while (*src) + { + temp = *src++ - '0'; + temp *= 10; + temp += *src++ - '0'; + *ptr++ = HexToBcd(temp); + } + *ptr = 0; + return dst; +} + +unsigned char *jt808BcdToStringCompress(const unsigned char *src, unsigned char *dst, int srclen) +{ + unsigned char *ptr = dst; + unsigned char temp; + int cnt = srclen; + while (cnt--) + { + temp = BcdToHex(*src); + *ptr++ = temp / 10 + '0'; + if (dst[0] == '0') + { + ptr = dst; + } + *ptr++ = temp % 10 + '0'; + ++src; + } + return dst; +} + + +unsigned char *jt808BcdToStringCompressFillingZero(const unsigned char *src, unsigned char *dst, int srclen) +{ + unsigned char *ptr = dst; + unsigned char temp; + int cnt = srclen; + while (cnt--) + { + temp = BcdToHex(*src); + *ptr++ = temp / 10 + '0'; + *ptr++ = temp % 10 + '0'; + ++src; + } + return dst; +} diff --git a/custom/jt808/src/client_manager.c b/custom/jt808/src/client_manager.c new file mode 100644 index 0000000..0bf6654 --- /dev/null +++ b/custom/jt808/src/client_manager.c @@ -0,0 +1,497 @@ +#include "client_manager.h" +#include "protocol_parameter.h" +#include "set_terminal_parameter.h" +#include "jt808_parser.h" +#include "util.h" +#include "bcd.h" +#include "jt808_packager.h" +#include "jt808_parser.h" +#include "jt808_debug.h" + +uint8_t Non_transliterated_receive[1024]; +struct ProtocolParameter parameter_; + +void initSystemParameters(int i) +{ + // Internal_ReadFlash(FLASH_ADDR, (uint8_t*)¶meter_.parse.terminal_parameters , sizeof(parameter_.parse.terminal_parameters)); + parameter_.parse.terminal_parameters.initFactoryParameters = i; + + JT808_DEBUG("initFactoryParameters == %d \r\n", parameter_.parse.terminal_parameters.initFactoryParameters); + + if (parameter_.parse.terminal_parameters.initFactoryParameters == 0) + { + FlashWrite(); + // Internal_ReadFlash(FLASH_ADDR, (uint8_t*)¶meter_.parse.terminal_parameters , sizeof(parameter_.parse.terminal_parameters)); + } + JT808_DEBUG("-->---------------------------\r\n"); + JT808_DEBUG("--> \r\n"); + JT808_DEBUG("--> Version = %s \r\n", parameter_.parse.terminal_parameters.version); + JT808_DEBUG("--> \r\n"); + JT808_DEBUG("-->---------------------------\r\n"); + JT808_DEBUG("HeartBeatInterval == %d \r\n", parameter_.parse.terminal_parameters.HeartBeatInterval); + JT808_DEBUG("MainServerAddress == \"%s\" \r\n", parameter_.parse.terminal_parameters.MainServerAddress); + JT808_DEBUG("ServerPort == %d \r\n", parameter_.parse.terminal_parameters.ServerPort); + JT808_DEBUG("DefaultTimeReportTimeInterval == %d \r\n", parameter_.parse.terminal_parameters.DefaultTimeReportTimeInterval); + JT808_DEBUG("CornerPointRetransmissionAngle == %d \r\n", parameter_.parse.terminal_parameters.CornerPointRetransmissionAngle); + JT808_DEBUG("MaxSpeed == %d \r\n", parameter_.parse.terminal_parameters.MaxSpeed); + JT808_DEBUG("ProvinceID == %d \r\n", parameter_.parse.terminal_parameters.ProvinceID); + JT808_DEBUG("CityID == %d \r\n", parameter_.parse.terminal_parameters.CityID); + JT808_DEBUG("CarPlateNum == %s \r\n", parameter_.parse.terminal_parameters.CarPlateNum); + JT808_DEBUG("CarPlateColor == %02x \r\n", parameter_.parse.terminal_parameters.CarPlateColor); + JT808_DEBUG("\r\n"); + JT808_DEBUG("initSystemParameters SUCCESS!!!!!!\r\n"); + JT808_DEBUG("\r\n"); +} + +int FlashWrite() +{ + parameter_.parse.terminal_parameters.HeartBeatInterval = 2; + + memset(parameter_.parse.terminal_parameters.MainServerAddress, 0, sizeof(parameter_.parse.terminal_parameters.MainServerAddress)); + + // 研究院平台 + memcpy(parameter_.parse.terminal_parameters.MainServerAddress, "123.160.246.146", sizeof("123.160.246.146")); + // memcpy(parameter_.parse.terminal_parameters.MainServerAddress,"http://jt808.gps.ciicp.com", sizeof("http://jt808.gps.ciicp.com")); + + // //客户平台 + // memcpy(parameter_.parse.terminal_parameters.MainServerAddress,"123.60.47.210", sizeof("123.60.47.210")); + + parameter_.parse.terminal_parameters.ServerPort = 7611; + + parameter_.parse.terminal_parameters.DefaultTimeReportTimeInterval = 2; + + parameter_.parse.terminal_parameters.CornerPointRetransmissionAngle = 10; + + parameter_.parse.terminal_parameters.MaxSpeed = 60; + + parameter_.parse.terminal_parameters.ProvinceID = 0x0029; + + parameter_.parse.terminal_parameters.CityID = 0x0066; + + parameter_.parse.terminal_parameters.CarPlateColor = 0x02; + + parameter_.parse.terminal_parameters.initFactoryParameters = 1; + + memset(parameter_.parse.terminal_parameters.version, 0, sizeof(parameter_.parse.terminal_parameters.version)); + memcpy(parameter_.parse.terminal_parameters.version, "v1.2", 5); + + + memset(parameter_.parse.terminal_parameters.PhoneNumber, 0, 12); + memset(parameter_.parse.terminal_parameters.CarPlateNum, 0, sizeof(parameter_.parse.terminal_parameters.CarPlateNum)); + memset(parameter_.parse.terminal_parameters.TerminalId, 0, 8); + + memcpy(parameter_.parse.terminal_parameters.PhoneNumber, "00000000100211609999", 20); + memcpy(parameter_.parse.terminal_parameters.TerminalId, "1609999", 8); + memcpy(parameter_.parse.terminal_parameters.CarPlateNum, "A:123456", 9); + + // FLASH_WriteByte(FLASH_ADDR , (uint8_t*)¶meter_.parse.terminal_parameters , sizeof(parameter_.parse.terminal_parameters)); + JT808_DEBUG("FLASH_Write SUCCESS!!!!!!\r\n"); + JT808_DEBUG("initFactoryParameters == %d \r\n", parameter_.parse.terminal_parameters.initFactoryParameters); + + return 0; +} + +int IPFlashWrite() +{ + memset(parameter_.parse.terminal_parameters.MainServerAddress, 0, sizeof(parameter_.parse.terminal_parameters.MainServerAddress)); + // memcpy(parameter_.parse.terminal_parameters.MainServerAddress,"121.5.140.126", sizeof("121.5.140.126")); + memcpy(parameter_.parse.terminal_parameters.MainServerAddress, "123.60.47.210", sizeof("123.60.47.210")); + + parameter_.parse.terminal_parameters.ServerPort = 7611; + + parameter_.parse.terminal_parameters.DefaultTimeReportTimeInterval = 5; + + // FLASH_WriteByte(FLASH_ADDR , (uint8_t*)¶meter_.parse.terminal_parameters , sizeof(parameter_.parse.terminal_parameters)); + JT808_DEBUG("IPFLASH_Write SUCCESS!!!!!!\r\n"); + + return 0; +} + +void setUUID(void) +{ + // Internal_ReadFlash(FLASH_ADDR, (uint8_t *) ¶meter_.parse.terminal_parameters, sizeof(parameter_.parse.terminal_parameters)); + + setTerminalPhoneNumber(parameter_.parse.terminal_parameters.PhoneNumber, 20); + setTerminalId(parameter_.parse.terminal_parameters.TerminalId, 8); + + memset(parameter_.IMEI, 0, 15); + memcpy(parameter_.IMEI, "100000000000000", 15); + memset(parameter_.softwareVersion, 0, 20); + memcpy(parameter_.softwareVersion, "10000000000000000000", 20); +} + +/// @brief 设置终端手机号 +/// @param phone +void setTerminalPhoneNumber(const char *phone_num, unsigned int phoneSize) +{ + memset(parameter_.msg_head.phone_num, 0, 13); + memcpy(parameter_.msg_head.phone_num, phone_num, phoneSize); + // parameter_.msg_head.phone_num = (unsigned char *)phone_num; + JT808_DEBUG("parameter_.msg_head.phone_num = %s\r\n", parameter_.msg_head.phone_num); +} + +void setTerminalId(const char *TerminalId, unsigned int lenTerminalId) +{ + // 终端ID + // unsigned int lenTerminalId; + // lenTerminalId = sizeof(TerminalId); + // lenTerminalId =(lenTerminalId>20)?20:lenTerminalId; + + memset(parameter_.register_info.terminal_id, 0, lenTerminalId); + memcpy(parameter_.register_info.terminal_id, TerminalId, lenTerminalId); + JT808_DEBUG("para->register_info.terminal_id = %s\r\n", parameter_.register_info.terminal_id); +} + +int packagingAndSendMessage(unsigned int msg_id) +{ + return 0; +} + +void setStatusBit() +{ + parameter_.location_info.status.bit.positioning = 1; +} + +void initLocationInfo(unsigned int v_alarm_value, unsigned int v_status_value) +{ + + JT808_DEBUG("\n\r[InitLocationInfo] OK !\r\n"); + // 报警标志 + parameter_.location_info.alarm.value = v_alarm_value; + JT808_DEBUG("para->alarm.value = %d\r\n", parameter_.location_info.alarm.value); + // 状态 + parameter_.location_info.status.value = v_status_value; + JT808_DEBUG("para->status.value = %d\r\n", parameter_.location_info.status.value); +} + +void updateLocation(double const v_latitude, double const v_longitude, float const v_altitude, + float const v_speed, float const v_bearing, unsigned char *v_timestamp) +{ +#ifdef __JT808_DEBUG + JT808_DEBUG("\n\r[updateLocationInfo] OK !\r\n"); +#endif + // if (speed >= 10) //默认车速大于等于10公里时为正常行驶状态 + // { + // isCarMoving.store(true); + // } + // else + // { + // isCarMoving.store(false); + // } + parameter_.location_info.latitude = v_latitude * 1e6; + parameter_.location_info.longitude = v_longitude * 1e6; + parameter_.location_info.altitude = v_altitude; + parameter_.location_info.speed = v_speed * 10; + parameter_.location_info.bearing = v_bearing; + memcpy(parameter_.location_info.time, v_timestamp, 13); +#ifdef __JT808_DEBUG + JT808_DEBUG("para->latitude = %d\r\n", parameter_.location_info.latitude); + JT808_DEBUG("para->longitude = %d\r\n", parameter_.location_info.longitude); + JT808_DEBUG("para->altitude = %d\r\n", parameter_.location_info.altitude); + JT808_DEBUG("para->speed = %d\r\n", parameter_.location_info.speed); + JT808_DEBUG("para->bearing = %d\r\n", parameter_.location_info.bearing); + JT808_DEBUG("para->time = %s\r\n", parameter_.location_info.time); +#endif +} + +int packagingMessage(unsigned int msg_id) +{ + + // 查找当前msgID是否存在于待打包消息ID数组中 + if (0 == findMsgIDFromTerminalPackagerCMD(msg_id)) + { + JT808_DEBUG("[findMsgIDFromTerminalPackagerCMD] no msg_id \r\n"); + return -1; + } +#ifdef __JT808_DEBUG + JT808_DEBUG("[findMsgIDFromTerminalPackagerCMD] OK !\r\n"); +#endif + parameter_.msg_head.msg_id = msg_id; // 设置消息ID. + if (jt808FramePackage(¶meter_) < 0) + { + JT808_DEBUG("[jt808FramePackage]: FAILED !!!\r\n"); + return -1; + } + ++parameter_.msg_head.msg_flow_num; // 每正确生成一条命令, 消息流水号增加1. + return 0; +} + +int findMsgIDFromTerminalPackagerCMD(unsigned int msg_id) +{ + int result = 0; + int i; + for (i = 0; i < PACKAGER_NUM; ++i) + { + if (kTerminalPackagerCMD[i] == msg_id) + { + result = 1; + } + } + return result; +} + +int findParameterIDFromArray(unsigned int para_id) +{ + int result = 0; + int i; + for (i = 0; i < PARA_SETTING_LIMIT; ++i) + { + if (kParameterSettingCMD[i] == para_id) + { + result = 1; + } + } + return result; +} + +int jt808TerminalRegister(int *isRegistered) +{ + int i = 0; + uint16_t msgRecvLength =0; + while (i < 3) + { + packagingMessage(kTerminalRegister); +#ifdef __JT808_DEBUG + uint8_t j = 0; + for (j = 0; j < RealBufferSendSize; j++) + { + JT808_DEBUG("%02x ", BufferSend[j]); + } + JT808_DEBUG("\r\n"); +#endif + // UartSend_Non_transliterated(USART2,BufferSend,RealBufferSendSize); + + // while(1) + // { + + // if(USART2_RX_STA&0X8000) //接收到数据 + // { + // USART2_RX_STA = USART2_RX_STA&0x7FFF;//获取到实际字符数量 + + // msgRecvLength = UartRecv_Non_transliterated(); + + // if(msgRecvLength!=0) + // { + // USART2_RX_STA=0; + // break; + // } + + // USART2_RX_STA=0; + // } + // } + + parsingMessage(Non_transliterated_receive, msgRecvLength); // 校验 + + if ((parameter_.parse.respone_result == kRegisterSuccess) && (parameter_.parse.msg_head.msg_id == kTerminalRegisterResponse)) + { + *isRegistered = 1; + JT808_DEBUG("\r\n"); + JT808_DEBUG("TerminalRegister SUCCESS!!!!!!!!!!\r\n"); + JT808_DEBUG("\r\n"); + // USART2_RX_STA=0; + break; + } + + JT808_DEBUG("\r\n"); + JT808_DEBUG("TerminalRegister FAILED!!!!!!\r\n"); + JT808_DEBUG("\r\n"); + i++; + } + + return 0; +} + +int jt808TerminalAuthentication(int *isAuthenticated) +{ + int i = 0; + uint16_t msgRecvLength =0; + while (i < 3) + { + packagingMessage(kTerminalAuthentication); + + // #ifdef __JT808_DEBUG + // uint8_t j=0; + // for(j=0; j &gbk_src) + { + + //?GBK??????utf-8?? + size_t lenSRC = gbk_src.size(); + size_t lenDst = lenSRC * 2; + char *dst_str = new char[lenDst]; + // Utf8ToGbk((char *)(txt8300_2013.data()), len, dst_str, 1024); + if (GbkToUtf8((char *)(gbk_src.data()), lenSRC, dst_str, lenDst) != 0) + return ""; + std::string str_GbkToUtf8(dst_str); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + delete[] dst_str; + + return str_GbkToUtf8; + } + + std::string gbk_to_utf8_str(const std::string &str_gbk_src) + { + + //?GBK??????utf-8?? + size_t lenSRC = str_gbk_src.size(); + size_t lenDst = lenSRC * 2; + char *dst_str = new char[lenDst]; + // Utf8ToGbk((char *)(txt8300_2013.data()), len, dst_str, 1024); + if (GbkToUtf8((char *)(str_gbk_src.data()), lenSRC, dst_str, lenDst) != 0) + return ""; + std::string str_GbkToUtf8(dst_str); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + delete[] dst_str; + + return str_GbkToUtf8; + } +} +*/ diff --git a/custom/jt808/src/jt808_packager.c b/custom/jt808/src/jt808_packager.c new file mode 100644 index 0000000..328d980 --- /dev/null +++ b/custom/jt808/src/jt808_packager.c @@ -0,0 +1,519 @@ +#include "jt808_packager.h" +#include "util.h" +#include "terminal_parameter.h" +#include "client_manager.h" +#include "jt808_debug.h" + +// 所有终端数据打包命令. +unsigned short kTerminalPackagerCMD[PACKAGER_NUM] = { + kTerminalGeneralResponse, // 终端通用应答. + kTerminalHeartBeat, // 终端心跳. + kTerminalRegister, // 终端注册. + kTerminalLogOut, // 终端注销. + kTerminalAuthentication, // 终端鉴权. + kGetTerminalParametersResponse, // 查询终端参数应答. + kTerminalUpgradeResultReport, // 终端升级结果通知. + kLocationReport, // 位置信息汇报. + kGetLocationInformationResponse // 位置信息查询应答. +}; + +/// @brief 发送缓存 +unsigned char BufferSend[BUFFER_SIZE_SEND] = {0}; + +/// @brief 实际打包发送数据的长度 +unsigned int RealBufferSendSize = 0; +// int RealBufferSendSize = 0; + +void clearBufferSend() +{ + memset(BufferSend, 0, BUFFER_SIZE_SEND); + RealBufferSendSize = 0; +} + +void bufferSendPushByte(unsigned char byte) +{ + BufferSend[RealBufferSendSize] = byte; + ++RealBufferSendSize; +} + +int bufferSendPushBytes(const unsigned char *bytes, unsigned int size) +{ + unsigned int i; + if (bytes == NULL) + { + return 0; + } + for (i = 0; i < size; ++i) + { + bufferSendPushByte(*(bytes + i)); + } + + return 1; +} + +int bufferSendChangeByte(unsigned char byte, unsigned int index) +{ + if (index > RealBufferSendSize) + { + return 0; + } + else if (index == RealBufferSendSize) + { + BufferSend[index] = byte; + ++RealBufferSendSize; + } + else + { + BufferSend[index] = byte; + } + return 1; +} + +int copyU16ToU8ArrayToBufferSend(const unsigned char *u8array) +{ + return bufferSendPushBytes(u8array, 2); +} + +int copyU32ToU8ArrayToBufferSend(const unsigned char *u8array) +{ + return bufferSendPushBytes(u8array, 4); +} + +// 终端通用应答. +int handle_kTerminalGeneralResponse(struct ProtocolParameter *para) +{ + + int msg_len = 5; + union U16ToU8Array u16converter; + JT808_DEBUG("[%s] msg_id = 0x%04x \r\n", __FUNCTION__, kTerminalGeneralResponse); + // 应答消息流水号. + u16converter.u16val = EndianSwap16(para->parse.msg_head.msg_flow_num); + copyU16ToU8ArrayToBufferSend(u16converter.u8array); + JT808_DEBUG(" flow_num == 0x%04x \r\n", para->parse.msg_head.msg_flow_num); + + // 应答消息ID. + u16converter.u16val = EndianSwap16(para->parse.msg_head.msg_id); + copyU16ToU8ArrayToBufferSend(u16converter.u8array); + JT808_DEBUG(" msg_id == 0x%04x \r\n", para->parse.msg_head.msg_id); + + // 应答结果. + bufferSendPushByte(para->respone_result); + JT808_DEBUG(" respone_result == 0x%02x \r\n", para->parse.respone_result); + + return msg_len; +} + +// 终端心跳. +int handle_kTerminalHeartBeat(struct ProtocolParameter *para) +{ +#ifdef __JT808_DEBUG + JT808_DEBUG("[%s] msg_id = 0x%04x \r\n ", __FUNCTION__, kTerminalHeartBeat); +#endif + return 0; +} + +// 终端注册. +int handle_kTerminalRegister(struct ProtocolParameter *para) +{ + int msg_len; + union U16ToU8Array u16converter; + + JT808_DEBUG("[%s] msg_id = 0x%04x \r\n", __FUNCTION__, kTerminalRegister); + + initRegisterInfo(para); // 初始化注册参数 + + msg_len = 37; + + // 省域ID. + u16converter.u16val = EndianSwap16(para->register_info.province_id); + copyU16ToU8ArrayToBufferSend(u16converter.u8array); + + // 市县域ID. + u16converter.u16val = EndianSwap16(para->register_info.city_id); + copyU16ToU8ArrayToBufferSend(u16converter.u8array); + + // 制造商ID. + bufferSendPushBytes(para->register_info.manufacturer_id, sizeof(para->register_info.manufacturer_id)); + + // 终端型号. + bufferSendPushBytes(para->register_info.terminal_model, sizeof(para->register_info.terminal_model)); + + // 终端ID. + bufferSendPushBytes(para->register_info.terminal_id, sizeof(para->register_info.terminal_id)); + + // 车牌颜色. + bufferSendPushByte(para->register_info.car_plate_color); + + // 车牌标识,即车牌号 + if (para->register_info.car_plate_color != 0x00) + { + unsigned int len_car_num = strlen(para->register_info.car_plate_num); + bufferSendPushBytes(para->register_info.car_plate_num, len_car_num); + msg_len += len_car_num; + } + + return msg_len; +} + +// 终端注销. +int handle_kTerminalLogOut(struct ProtocolParameter *para) +{ + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kTerminalLogOut); + + // 空消息体. + return 0; +} + +// 终端鉴权. +int handle_kTerminalAuthentication(struct ProtocolParameter *para) +{ + int msg_len = strlen(para->parse.authentication_code); + JT808_DEBUG("[%s] msg_id = 0x%04x \r\n", __FUNCTION__, kTerminalAuthentication); + // 鉴权码. + bufferSendPushBytes(para->parse.authentication_code, msg_len); + + return msg_len; +} + +// 查询终端参数应答. +int handle_kGetTerminalParametersResponse(struct ProtocolParameter *para) +{ + JT808_DEBUG("[%s] msg_id = 0x%04x\n", __FUNCTION__, kGetTerminalParametersResponse); + return 0; +} + +// 终端升级结果通知. +int handle_kTerminalUpgradeResultReport(struct ProtocolParameter *para) +{ + + int msg_len = 2; + int result = 0; + JT808_DEBUG("[%s] msg_id = 0x%04x\n", __FUNCTION__, kTerminalUpgradeResultReport); + bufferSendPushByte(kTerminal); // 升级类型 终端 + msg_len += 1; + + // 升级结果 0成功 1失败 2取消 + if (result == 0) + { + bufferSendPushByte(kTerminalUpgradeSuccess); + } + else if (result == 1) + { + bufferSendPushByte(kTerminalUpgradeFailed); + } + else + { + bufferSendPushByte(kTerminalUpgradeCancel); + } + msg_len += 1; + + return msg_len; +} + +// 位置信息汇报. +int handle_kLocationReport(struct ProtocolParameter *para) +{ + unsigned char time_bcd[6] = {0}; + int msg_len = 28; + union U32ToU8Array u32converter; + union U16ToU8Array u16converter; + +#ifdef JT808_DEBUG + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kLocationReport); +#endif + + // 报警标志. + u32converter.u32val = EndianSwap32(para->location_info.alarm.value); + copyU32ToU8ArrayToBufferSend(u32converter.u8array); + // 状态. + u32converter.u32val = EndianSwap32(para->location_info.status.value); + copyU32ToU8ArrayToBufferSend(u32converter.u8array); + // 纬度. + u32converter.u32val = EndianSwap32(para->location_info.latitude); + copyU32ToU8ArrayToBufferSend(u32converter.u8array); + // 经度. + u32converter.u32val = EndianSwap32(para->location_info.longitude); + copyU32ToU8ArrayToBufferSend(u32converter.u8array); + // union U16ToU8Array u16converter; + // 海拔高程. + u16converter.u16val = EndianSwap16(para->location_info.altitude); + copyU16ToU8ArrayToBufferSend(u16converter.u8array); + // 速度. + u16converter.u16val = EndianSwap16(para->location_info.speed); + copyU16ToU8ArrayToBufferSend(u16converter.u8array); + // 方向. + u16converter.u16val = EndianSwap16(para->location_info.bearing); + copyU16ToU8ArrayToBufferSend(u16converter.u8array); + + jt808StringToBcdCompress(para->location_info.time, time_bcd, strlen(para->location_info.time)); + bufferSendPushBytes(time_bcd, 6); + + bufferSendPushByte(kNetworkQuantity); // 附加信息ID 0x30 + bufferSendPushByte(1); // 附加信息长度 + bufferSendPushByte(0x53); // 附加信息,无线信号强度 + msg_len += 3; + + bufferSendPushByte(kGnssSatellites); // 附加信息ID 0x31 + bufferSendPushByte(1); // 附加信息长度 + bufferSendPushByte(11); // 附加信息,卫星数量 + msg_len += 3; + + bufferSendPushByte(kCustomInformationLength); // 附加信息ID 0xe0 + bufferSendPushByte(1); // 附加信息长度 + bufferSendPushByte(3); // 附加信息,后续数据长度 + msg_len += 3; + + bufferSendPushByte(kPositioningStatus); // 附加信息ID 0xee + bufferSendPushByte(1); // 附加信息长度 + bufferSendPushByte(2); // 附加信息,定位解状态 + msg_len += 3; + + return msg_len; +} + +// 位置信息查询应答. +int handle_kGetLocationInformationResponse(struct ProtocolParameter *para) +{ + JT808_DEBUG("[%s] msg_id = 0x%04x\n", __FUNCTION__, kGetLocationInformationResponse); + return 0; +} + +int jt808FrameBodyPackage(struct ProtocolParameter *para) +{ + unsigned short msg_id = para->msg_head.msg_id; + int result = -1; +#ifdef __JT808_DEBUG + JT808_DEBUG("[jt808FrameBodyPackage] msg_id: 0x%04x\r\n", para->msg_head.msg_id); +#endif + + switch (msg_id) + { + // 终端通用应答. + case kTerminalGeneralResponse: + { + result = handle_kTerminalGeneralResponse(para); + } + break; + + // 终端心跳. + case kTerminalHeartBeat: + { + result = handle_kTerminalHeartBeat(para); + } + break; + + // 终端注册. + case kTerminalRegister: + { + result = handle_kTerminalRegister(para); + } + break; + + // 终端注销. + case kTerminalLogOut: + { + result = handle_kTerminalLogOut(para); + } + break; + + // 终端鉴权. + case kTerminalAuthentication: + { + result = handle_kTerminalAuthentication(para); + } + break; + + // 查询终端参数应答. + case kGetTerminalParametersResponse: + { + result = handle_kGetTerminalParametersResponse(para); + } + break; + + // 终端升级结果通知. + case kTerminalUpgradeResultReport: + { + result = handle_kTerminalUpgradeResultReport(para); + } + break; + + // 位置信息汇报 + case kLocationReport: + { + result = handle_kLocationReport(para); + } + break; + + // 位置信息查询应答. + case kGetLocationInformationResponse: + { + result = handle_kGetLocationInformationResponse(para); + } + break; + + default: + break; + } + + return result; +} + +// 消息内容长度修正. +int jt808MsgBodyLengthFix(struct MsgHead *msg_head, unsigned int msgBody_len) +{ + union U16ToU8Array u16converter; + union MsgBodyAttribute msgbody_attr; + if (RealBufferSendSize < 12) + { + JT808_DEBUG("%d \r\n", RealBufferSendSize); + return -1; + } + + msgbody_attr = msg_head->msgbody_attr; + msgbody_attr.bit.msglen = msgBody_len; + // union U16ToU8Array u16converter; + u16converter.u16val = EndianSwap16(msgbody_attr.u16val); + BufferSend[3] = u16converter.u8array[0]; + BufferSend[4] = u16converter.u8array[1]; + +#ifdef __JT808_DEBUG + JT808_DEBUG("[%s] OK !\r\n", __FUNCTION__); +#endif + return 0; +} + +// JT808协议转义. +int jt808MsgEscape() +{ + unsigned int outBufferSize; + unsigned char *outBuffer; + BufferSend[0] = 0x00; + BufferSend[RealBufferSendSize - 1] = 0x00; + + outBufferSize = RealBufferSendSize * 2; + outBuffer = (unsigned char *)malloc(outBufferSize); + + if (Escape_C(BufferSend, RealBufferSendSize, outBuffer, &outBufferSize) < 0) + { + JT808_DEBUG("[%s] FAILED \r\n", __FUNCTION__); + return -1; + } + + *(outBuffer + 0) = PROTOCOL_SIGN; + *(outBuffer + (outBufferSize - 1)) = PROTOCOL_SIGN; + + memcpy(BufferSend, outBuffer, outBufferSize); + RealBufferSendSize = outBufferSize; + + if (outBuffer != NULL) + { + free(outBuffer); + outBuffer = NULL; + } +#ifdef __JT808_DEBUG + JT808_DEBUG("[%s] OK !\r\n", __FUNCTION__); +#endif + return 0; +} + +void jt808SetFrameFlagHeader() +{ + // BufferSend[0] = PROTOCOL_SIGN; //设置头标识 + // ++RealBufferSendSize; //发送buf长度自加 + // bufferSendPushByte(PROTOCOL_SIGN); + bufferSendChangeByte(PROTOCOL_SIGN, 0); +} + +int jt808FrameHeadPackage(struct MsgHead *msg_head) +{ + union U16ToU8Array u16converter; + unsigned char phone_num_bcd[6] = {0}; + // 1消息ID. + u16converter.u16val = EndianSwap16(msg_head->msg_id); + copyU16ToU8ArrayToBufferSend(u16converter.u8array); + + // 2消息体属性. + u16converter.u16val = EndianSwap16(msg_head->msgbody_attr.u16val); + copyU16ToU8ArrayToBufferSend(u16converter.u8array); + + // 3终端手机号(BCD码). + // msg_head->phone_num = "17737702736"; //测试用2022.10.25 + // unsigned char phone_num_bcd[6] = {0}; + jt808StringToBcdCompress(msg_head->phone_num, phone_num_bcd, strlen(msg_head->phone_num)); + bufferSendPushBytes(phone_num_bcd, 6); + + // 4消息流水号. + u16converter.u16val = EndianSwap16(msg_head->msg_flow_num); + bufferSendPushBytes(u16converter.u8array, 2); + + // 5封包项. + if ((msg_head->msgbody_attr.bit.packet == 1) && + (msg_head->total_packet > 1)) + { + u16converter.u16val = EndianSwap16(msg_head->total_packet); + + bufferSendPushBytes(u16converter.u8array, 2); + + u16converter.u16val = EndianSwap16(msg_head->packet_seq); + bufferSendPushBytes(u16converter.u8array, 2); + } + return 0; +} + +int jt808FramePackage(struct ProtocolParameter *para) +{ + int ret; + unsigned char valueCheck; + // 清空发送缓存,避免缓存中会有前一次的数据 + clearBufferSend(); + // 0、设置头标志位 + jt808SetFrameFlagHeader(); + +#ifdef __JT808_DEBUG + JT808_DEBUG("[jt808SetFrameFlagHeader] OK !\r\n"); +#endif + + // 1、生成消息头 + if (jt808FrameHeadPackage(&(para->msg_head)) < 0) + { + JT808_DEBUG("jt808FrameHeadPackage FAILED \r\n"); + return -1; + } + +#ifdef __JT808_DEBUG + JT808_DEBUG("[jt808FrameHeadPackage] OK !\r\n"); +#endif + + // 2、封装消息内容. + ret = jt808FrameBodyPackage(para); + + if (ret >= 0) + { + // 3、修正消息长度. + if (jt808MsgBodyLengthFix(&(para->msg_head), ret) < 0) + { + JT808_DEBUG("jt808FrameHeadPackage FAILED \r\n"); + return -1; + } + + // 4、获取校验码,并将其写入发送缓存. + // valueCheck = BccCheckSum(BufferSend, RealBufferSendSize); + valueCheck = BccCheckSum((BufferSend + 1), (RealBufferSendSize - 1)); // 参考接收解析 + bufferSendPushByte(valueCheck); + + // 5、写入发送缓存结束标识位. + bufferSendPushByte(PROTOCOL_SIGN); +#ifdef __JT808_DEBUG + JT808_DEBUG("[Write buffersend end PROTOCOL_SIGN] OK !\r\n"); +#endif + // 6、处理转义. + if (jt808MsgEscape() < 0) + { + JT808_DEBUG("[jt808MsgEscape] FAILED"); + return -1; + } + return 0; + } + + return -1; +} diff --git a/custom/jt808/src/jt808_parser.c b/custom/jt808/src/jt808_parser.c new file mode 100644 index 0000000..719c5f6 --- /dev/null +++ b/custom/jt808/src/jt808_parser.c @@ -0,0 +1,453 @@ +#include "jt808_parser.h" +#include "set_terminal_parameter.h" +#include "client_manager.h" +#include "util.h" +#include "bcd.h" +#include "jt808_debug.h" + +// 所有终端解析命令. +unsigned short kTerminalParserCMD[PARSER_NUM] = { + kPlatformGeneralResponse, // 平台通用应答 + kFillPacketRequest, // 补传分包请求. + kTerminalRegisterResponse, // 终端注册应答. + kSetTerminalParameters, // 设置终端参数. + kGetTerminalParameters, // 查询终端参数. + kGetSpecificTerminalParameters, // 查询指定终端参数. + kTerminalControl, // 终端控制 + kTerminalUpgrade, // 下发终端升级包. + kGetLocationInformation, // 位置信息查询. +}; + +/// @brief 接收缓存 +unsigned char BufferReceive[BUFFER_SIZE_RECEIVE] = {0}; + +/// @brief 实际接收的数据长度 +unsigned int RealBufferReceiveSize = 0; + +// 解析消息头. +int jt808FrameHeadParse(const unsigned char *in, unsigned int in_len, struct MsgHead *msg_head) +{ + if (msg_head == NULL || in_len < 15) + { + JT808_DEBUG("msg_head == NULL || in_len < 15"); + return -1; + } + + // 消息ID. + msg_head->msg_id = (in[1] << 8) + in[2]; + + // 消息体属性. + msg_head->msgbody_attr.u16val = (in[3] << 8) + in[4]; + + // 终端手机号. + + memset(msg_head->phone_num, 0, 12); + + if (jt808BcdToStringCompress((&(in[5])), msg_head->phone_num, 6) == NULL) + { + JT808_DEBUG("jt808BcdToStringCompress error \r\n"); + return -1; + } + + // 消息流水号. + msg_head->msg_flow_num = (in[11] << 8) + in[12]; + + // 出现封包. + if ((msg_head->msgbody_attr.bit.packet == 1) && + ((in_len - 15 - msg_head->msgbody_attr.bit.msglen) == 4)) + { + msg_head->total_packet = (in[13] << 8) + in[14]; + msg_head->packet_seq = (in[15] << 8) + in[16]; + } + else + { + msg_head->total_packet = 0; + msg_head->packet_seq = 0; + } + +#ifdef __JT808_DEBUG + JT808_DEBUG("[jt808FrameHeadParse] msg_head->msg_id = 0x%02x\r\n", msg_head->msg_id); + JT808_DEBUG("[jt808FrameHeadParse] msg_head->msgbody_attr.u16val = 0x%02x\r\n", msg_head->msgbody_attr.u16val); + JT808_DEBUG("[jt808FrameHeadParse] msg_head->phone_num = %s !!!\r\n", msg_head->phone_num); + JT808_DEBUG("[jt808FrameHeadParse] msg_head->msg_flow_num = 0x%02x !!!\r\n", msg_head->msg_flow_num); +#endif + + return 0; +} + +// 平台通用应答 +int handle_kPlatformGeneralResponse(struct ProtocolParameter *para) +{ + uint16_t pos; +#ifdef __JT808_DEBUG + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kPlatformGeneralResponse); +#endif + if (para == NULL) + return -1; + pos = MSGBODY_NOPACKET_POS; + if (para->msg_head.msgbody_attr.bit.packet == 1) + pos = MSGBODY_PACKET_POS; + // 应答流水号. + para->parse.respone_flow_num = (BufferReceive[pos] << 8) + BufferReceive[pos + 1]; + + // 应答消息ID. + para->parse.respone_msg_id = (BufferReceive[pos + 2] << 8) + BufferReceive[pos + 3]; + + // 应答结果. + para->parse.respone_result = BufferReceive[pos + 4]; + +#ifdef __JT808_DEBUG + JT808_DEBUG("[%s] respone_flow_num = 0x%04x\r\n", __FUNCTION__, para->parse.respone_flow_num); + JT808_DEBUG("[%s] respone_msg_id = 0x%04x\r\n", __FUNCTION__, para->parse.respone_msg_id); + JT808_DEBUG("[%s] respone_result = 0x%04x\r\n", __FUNCTION__, para->parse.respone_result); +#endif + + return 0; +} + +// 补传分包请求. +int handle_kFillPacketRequest(struct ProtocolParameter *para) +{ + uint16_t pos; + // unsigned short cnt; + // unsigned char i; + // unsigned short id; + + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kFillPacketRequest); + + if (para == NULL) + { + return -1; + } + pos = MSGBODY_NOPACKET_POS; + if (para->parse.msg_head.msgbody_attr.bit.packet == 1) + { + pos = MSGBODY_PACKET_POS; + } + + para->fill_packet.first_packet_msg_flow_num = (BufferReceive[pos] << 8) + BufferReceive[pos + 1]; + pos += 2; + + // cnt = BufferReceive[pos+2]; + ++pos; + + // if(para->msg_head.msgbody_attr.bit.msglen -3 != (cnt * 2)) + // { + // return -1; + // } + // + //// memset(para->fill_packet.packet_id, 0, sizeof(para->fill_packet.packet_id)); + // for(i=0;ifill_packet.packet_id[pos], id, 2); + // pos += 2; + // } + + File_upload(); + + return 0; +} + +// 终端注册应答.. +int handle_kTerminalRegisterResponse(struct ProtocolParameter *para) +{ + unsigned short pos; + unsigned short len_code; + + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kTerminalRegisterResponse); + + if (para == NULL) + return -1; + pos = MSGBODY_NOPACKET_POS; + if (para->parse.msg_head.msgbody_attr.bit.packet == 1) + pos = MSGBODY_PACKET_POS; + // 应答流水号. + para->parse.respone_flow_num = (BufferReceive[pos] << 8) + BufferReceive[pos + 1]; + JT808_DEBUG("[%s] respone_flow_num = 0x%04x\r\n", __FUNCTION__, para->parse.respone_flow_num); + // 应答结果. + para->parse.respone_result = BufferReceive[pos + 2]; + JT808_DEBUG("[%s] respone_result = 0x%02x\r\n", __FUNCTION__, para->parse.respone_result); + // 应答结果为0(成功)时解析出附加的鉴权码. + if (para->parse.respone_result == kRegisterSuccess) + { + len_code = para->parse.msg_head.msgbody_attr.bit.msglen - 3; + para->parse.authentication_code = (unsigned char *)malloc((len_code + 1) * sizeof(unsigned char)); + memcpy(para->parse.authentication_code, &(BufferReceive[pos + 3]), len_code); + + JT808_DEBUG("[%s] authentication_code = %s\r\n", __FUNCTION__, para->parse.authentication_code); + } + + return 0; +} + +// 设置终端参数.. +int handle_kSetTerminalParameters(struct ProtocolParameter *para) +{ + uint16_t pos; + unsigned short msg_len; + unsigned int p_id; + unsigned char cnt; + union U32ToU8Array u32converter; + int isFind = 0, i; + unsigned len; + + jt808TerminalGeneralResponse(); + + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kSetTerminalParameters); + if (para == NULL) + { + return -1; + } + pos = MSGBODY_NOPACKET_POS; + if (para->parse.msg_head.msgbody_attr.bit.packet == 1) + { + pos = MSGBODY_PACKET_POS; + } + msg_len = para->parse.msg_head.msgbody_attr.bit.msglen; + if (msg_len < 1) + { + return -1; + } + // 解析设置的参数总个数. + cnt = BufferReceive[pos]; + pos++; + + if (cnt <= 0) + { + return -1; + } + + for (i = 0; i < cnt; ++i) + { + // 查找参数项的参数ID + memcpy(u32converter.u8array, (BufferReceive + pos), 4); + p_id = EndianSwap32(u32converter.u32val); + pos += 4; + // 从已支持的参数项数组中查找是否有当前参数ID + isFind = findParameterIDFromArray(p_id); + len = BufferReceive[pos]; + pos++; + if (isFind == 1) + { + jt808ParameterSettingParse(p_id, (BufferReceive + pos), len, para); + } + pos += len; + } + + return 0; +} + +// 查询终端参数.. +int handle_kGetTerminalParameters(struct ProtocolParameter *para) +{ + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kGetTerminalParameters); + + return 0; +} + +// 查询指定终端参数.. +int handle_kGetSpecificTerminalParameters(struct ProtocolParameter *para) +{ + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kGetSpecificTerminalParameters); + + return 0; +} + +// 终端控制 +int handle_kTerminalControl(struct ProtocolParameter *para) +{ + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kTerminalControl); + + return 0; +} + +// 下发终端升级包. +int handle_kTerminalUpgrade(struct ProtocolParameter *para) +{ + uint16_t pos; + // uint16_t beg = pos; + int i; + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kTerminalUpgrade); + jt808TerminalGeneralResponse(); + if (para == NULL) + { + return -1; + } + + pos = MSGBODY_NOPACKET_POS; + if (para->parse.msg_head.msgbody_attr.bit.packet == 1) + { + pos = MSGBODY_PACKET_POS; + } + + para->upgrade_info.upgrade_type = BufferReceive[pos++]; + + memset(para->upgrade_info.manufacturer_id, 0, sizeof(para->upgrade_info.manufacturer_id)); + for (i = 0; i < 5; i++) + { + } + + jt808TerminalUpgradeResultReport(); + return 0; +} + +// 位置信息查询.. +int handle_kGetLocationInformation(struct ProtocolParameter *para) +{ + JT808_DEBUG("[%s] msg_id = 0x%04x\r\n", __FUNCTION__, kGetLocationInformation); + + return 0; +} + +int jt808FrameBodyParse(struct ProtocolParameter *para) +{ + unsigned short msg_id = para->parse.msg_head.msg_id; + int result = -1; + +#ifdef __JT808_DEBUG + JT808_DEBUG("[%s] current msg_id: 0x%04x\r\n", __FUNCTION__, msg_id); +#endif + + switch (msg_id) + { + // +平台通用应答. + case kPlatformGeneralResponse: + { + result = handle_kPlatformGeneralResponse(para); + } + break; + + // 补传分包请求. + case kFillPacketRequest: + { + result = handle_kFillPacketRequest(para); + } + break; + + // 终端注册应答.. + case kTerminalRegisterResponse: + { + result = handle_kTerminalRegisterResponse(para); + } + break; + + // 设置终端参数.. + case kSetTerminalParameters: + { + result = handle_kSetTerminalParameters(para); + } + break; + + // 查询终端参数.. + case kGetTerminalParameters: + { + result = handle_kGetTerminalParameters(para); + } + break; + + // 查询指定终端参数.. + case kGetSpecificTerminalParameters: + { + result = handle_kGetSpecificTerminalParameters(para); + } + break; + + // 终端控制 + case kTerminalControl: + { + result = handle_kTerminalControl(para); + } + break; + + // 下发终端升级包. + case kTerminalUpgrade: + { + result = handle_kTerminalUpgrade(para); + } + break; + + // 位置信息查询.. + case kGetLocationInformation: + { + result = handle_kGetLocationInformation(para); + } + break; + + default: + break; + } + + return result; +} + +int jt808FrameParse(const unsigned char *in, unsigned int in_len, struct ProtocolParameter *para) +{ + int ret; + unsigned int outBufferSize; + unsigned char *outBuffer; + +#ifdef __JT808_DEBUG + JT808_DEBUG("%s[%d]: jt808FrameParse -->1 !!! \r\n", __FUNCTION__, __LINE__); +#endif + if (para == NULL) + { + JT808_DEBUG("para == NULL \r\n"); + return -1; + } + memcpy(BufferReceive, in, in_len); + RealBufferReceiveSize = in_len; + outBufferSize = RealBufferReceiveSize; + outBuffer = (unsigned char *)malloc(outBufferSize * sizeof(unsigned char)); + memset(outBuffer, 0, outBufferSize); + +#ifdef __JT808_DEBUG + JT808_DEBUG("%s[%d]: outBufferSize = %d \r\n", __FUNCTION__, __LINE__, outBufferSize); +#endif + + // 逆转义. + if (ReverseEscape_C(BufferReceive, RealBufferReceiveSize, outBuffer, &outBufferSize) < 0) + { + JT808_DEBUG("ReverseEscape_C ERROR\r\n"); + return -1; + } + + RealBufferReceiveSize = outBufferSize; + +#ifdef __JT808_DEBUG + JT808_DEBUG("%s[%d]: ReverseEscape_C. outBufferSize = %d !!!\r\n", __FUNCTION__, __LINE__, outBufferSize); +#endif + + // 异或校验检查. + if (BccCheckSum(&(outBuffer[1]), (outBufferSize - 3)) != *(outBuffer + outBufferSize - 2)) + { + JT808_DEBUG("BccCheckSum ERROR\r\n"); + return -1; + } + +#ifdef __JT808_DEBUG + JT808_DEBUG("%s[%d]: BccCheckSum. -->3 !!!\r\n", __FUNCTION__, __LINE__); +#endif + // 解析消息头. + if (jt808FrameHeadParse(outBuffer, outBufferSize, &(para->parse.msg_head)) != 0) + { + JT808_DEBUG("jt808FrameHeadParse ERROR\r\n"); + return -1; + } +#ifdef __JT808_DEBUG + JT808_DEBUG("%s[%d]: jt808FrameHeadParse. -->4 !!!\r\n", __FUNCTION__, __LINE__); +#endif + memcpy(para->msg_head.phone_num, para->parse.msg_head.phone_num, 11); + + // 解析消息内容. + ret = jt808FrameBodyParse(para); + + // 释放缓存 + if (outBuffer != NULL) + { + free(outBuffer); + outBuffer = NULL; + } + + return ret; +} diff --git a/custom/jt808/src/location_report.c b/custom/jt808/src/location_report.c new file mode 100644 index 0000000..b91e624 --- /dev/null +++ b/custom/jt808/src/location_report.c @@ -0,0 +1,74 @@ +#include "location_report.h" +#include +#include "util.h" +#include "jt808_debug.h" + +// double const v_latitude = 23.123456; +// double const v_longitude = 123.123456; +// float const v_altitude=10; +// float const v_speed=10; +// float const v_bearing=100; +// unsigned char *v_timestamp = "211221213045"; + +// void initGPSInfo(struct ProtocolParameter *para, unsigned int v_alarm_value, +// unsigned int v_status_value, double const v_latitude, +// double const v_longitude, float const v_altitude, +// float const v_speed, float const v_bearing, +// unsigned char *v_timestamp) +// { +// JT808_DEBUG("\n\r[initGPSInfo] OK !\n"); +// //报警标志 +// para->location_info.alarm.value = v_alarm_value; +// JT808_DEBUG("para->alarm.value = %d\n", para->location_info.alarm.value); +// //状态 +// para->location_info.status.value = v_status_value; +// JT808_DEBUG("para->status.value = %d\n", para->location_info.status.value); + +// // if (speed >= 10) //默认车速大于等于10公里时为正常行驶状态 +// // { +// // isCarMoving.store(true); +// // } +// // else +// // { +// // isCarMoving.store(false); +// // } +// para->location_info.latitude = v_latitude * 1e6; +// JT808_DEBUG("para->latitude = %d\n", para->location_info.latitude); + +// para->location_info.longitude = v_longitude * 1e6; +// JT808_DEBUG("para->longitude = %d\n", para->location_info.longitude); + +// para->location_info.altitude = v_altitude; +// JT808_DEBUG("para->altitude = %d\n", para->location_info.altitude); + +// para->location_info.speed = v_speed * 10; +// JT808_DEBUG("para->speed = %d\n", para->location_info.speed); + +// para->location_info.bearing = v_bearing; +// JT808_DEBUG("para->bearing = %d\n", para->location_info.bearing); + +// para->location_info.time = v_timestamp; +// JT808_DEBUG("para->time = %s\n", para->location_info.time); +// } + +// void UpdateLocation(double const latitude, double const longitude, +// float const altitude, float const speed, +// float const bearing, unsigned char *timestamp) +// { +// // if (speed >= 10) //默认车速大于等于10公里时为正常行驶状态 +// // { +// // isCarMoving.store(true); +// // } +// // else +// // { +// // isCarMoving.store(false); +// // } +// para->location_info.latitude = static_cast(latitude * 1e6); +// para->location_info.longitude = static_cast(longitude * 1e6); +// para->location_info.altitude = static_cast(altitude); +// para->location_info.speed = static_cast(speed * 10); +// para->location_info.bearing = static_cast(bearing); +// para->location_info.time.assign(timestamp.begin(), timestamp.end()); + +// // spdlog::info("[{}] [{}] 更新上报位置信息 ", libjt808::getCurrentFileName(__FILE__), __LINE__); +// } diff --git a/custom/jt808/src/set_terminal_parameter.c b/custom/jt808/src/set_terminal_parameter.c new file mode 100644 index 0000000..aa628b6 --- /dev/null +++ b/custom/jt808/src/set_terminal_parameter.c @@ -0,0 +1,304 @@ +#include "set_terminal_parameter.h" +#include "terminal_parameter.h" +#include "client_manager.h" +#include "jt808_debug.h" + +unsigned short kParameterSettingCMD[PARA_SETTING_LIMIT] = { + kTerminalHeartBeatInterval, // DWORD, 终端心跳发送间隔(s). + kMainServerAddress, // STRING, 主服务器地址,IP 或域名 + kServerPort, // DWORD, 服务器 TCP 端口 + kDefaultTimeReportTimeInterval, // DWORD, 缺省时间汇报间隔 + kCornerPointRetransmissionAngle, // DWORD, 拐点补传角度, < 180°. + kMaxSpeed, // DWORD, 最高速度, km/h. + kProvinceID, // WORD, 车辆所在的省域 ID + kCityID, // WORD, 车辆所在的市域 ID + kCarPlateNum, // STRING, 公安交通管理部门颁发的机动车号牌 + kCarPlateColor, // 车牌颜色,按照 JT/T415-2006 的 5.4.12 +}; + +void jt808ParameterSettingParse(unsigned int id, unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + switch (id) + { + case kTerminalHeartBeatInterval: + { + handle_HeartBeatInterval(buf, buf_len, para); + } + break; + + case kMainServerAddress: + { + handle_MainServerAddress(buf, buf_len, para); + } + break; + + case kServerPort: + { + handle_ServerPort(buf, buf_len, para); + } + break; + + case kDefaultTimeReportTimeInterval: + { + handle_DefaultTimeReportTimeInterval(buf, buf_len, para); + } + break; + + case kCornerPointRetransmissionAngle: + { + handle_CornerPointRetransmissionAngle(buf, buf_len, para); + } + break; + + case kMaxSpeed: + { + handle_MaxSpeed(buf, buf_len, para); + } + break; + + case kProvinceID: + { + handle_ProvinceID(buf, buf_len, para); + } + break; + + case kCityID: + { + handle_CityID(buf, buf_len, para); + } + break; + + case kCarPlateNum: + { + handle_CarPlateNum(buf, buf_len, para); + } + break; + + case kCarPlateColor: + { + handle_CarPlateColor(buf, buf_len, para); + } + break; + + default: + break; + } +} + +void handle_HeartBeatInterval(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + union U32ToU8Array u32converter; // 注意大小端转换 + unsigned char *p = NULL; + unsigned int heartBeatInterval; + if ((buf == NULL) || (buf_len == 0)) + return; + + p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); + memcpy(p, buf, buf_len); + + memcpy(u32converter.u8array, p, buf_len); + heartBeatInterval = EndianSwap32(u32converter.u32val); + + para->parse.terminal_parameters.HeartBeatInterval = heartBeatInterval; + JT808_DEBUG("handle_HeartBeatInterval ==== %d \r\n", para->parse.terminal_parameters.HeartBeatInterval); + // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + + free(p); + + return; +} + +void handle_MainServerAddress(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + unsigned char *p = NULL; + if ((buf == NULL) || (buf_len == 0)) + return; + + p = (unsigned char *)malloc(sizeof(unsigned char) * (buf_len + 1)); + memcpy(p, buf, buf_len); + + // 字符串注意GBK转码 + memset(para->parse.terminal_parameters.MainServerAddress, 0, sizeof(para->parse.terminal_parameters.MainServerAddress)); + memcpy(para->parse.terminal_parameters.MainServerAddress, p, buf_len); + // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + JT808_DEBUG("handle_MainServerAddress ==== %s \r\n", para->parse.terminal_parameters.MainServerAddress); + free(p); + + return; +} + +void handle_ServerPort(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + union U32ToU8Array u32converter; // 注意大小端转换 + unsigned char *p = NULL; + unsigned int serverPort; + + if ((buf == NULL) || (buf_len == 0)) + return; + + p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); + memcpy(p, buf, buf_len); + + memcpy(u32converter.u8array, p, buf_len); + serverPort = EndianSwap32(u32converter.u32val); + + para->parse.terminal_parameters.ServerPort = serverPort; + // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + JT808_DEBUG("handle_ServerPort ==== %d \r\n", para->parse.terminal_parameters.ServerPort); + free(p); + + return; +} + +void handle_DefaultTimeReportTimeInterval(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + union U32ToU8Array u32converter; // 注意大小端转换 + unsigned char *p = NULL; + unsigned int DefaultTimeReportTimeInterval; + if ((buf == NULL) || (buf_len == 0)) + return; + + p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); + memcpy(p, buf, buf_len); + + memcpy(u32converter.u8array, p, buf_len); + DefaultTimeReportTimeInterval = EndianSwap32(u32converter.u32val); + if (DefaultTimeReportTimeInterval >= 30) + { + DefaultTimeReportTimeInterval = 30; + } + if (DefaultTimeReportTimeInterval <= 2) + { + DefaultTimeReportTimeInterval = 2; + } + para->parse.terminal_parameters.DefaultTimeReportTimeInterval = DefaultTimeReportTimeInterval; + // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + JT808_DEBUG("handle_DefaultTimeReportTimeInterval ==== %d \r\n", para->parse.terminal_parameters.DefaultTimeReportTimeInterval); + free(p); + + return; +} + +void handle_CornerPointRetransmissionAngle(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + union U32ToU8Array u32converter; // 注意大小端转换 + unsigned char *p = NULL; + unsigned int CornerPointRetransmissionAngle; + if ((buf == NULL) || (buf_len == 0)) + return; + + p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); + memcpy(p, buf, buf_len); + + memcpy(u32converter.u8array, p, buf_len); + CornerPointRetransmissionAngle = EndianSwap32(u32converter.u32val); + + para->parse.terminal_parameters.CornerPointRetransmissionAngle = CornerPointRetransmissionAngle; + // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + JT808_DEBUG("handle_DefaultTimeReportTimeInterval ==== %d \r\n", para->parse.terminal_parameters.DefaultTimeReportTimeInterval); + free(p); + + return; +} + +void handle_MaxSpeed(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + union U32ToU8Array u32converter; // 注意大小端转换 + unsigned char *p = NULL; + unsigned int MaxSpeed; + if ((buf == NULL) || (buf_len == 0)) + return; + + p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); + memcpy(p, buf, buf_len); + + memcpy(u32converter.u8array, p, buf_len); + MaxSpeed = EndianSwap32(u32converter.u32val); + + para->parse.terminal_parameters.MaxSpeed = MaxSpeed; + // FLASH_WriteByte(FLASH_ADDR, (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + JT808_DEBUG("handle_MaxSpeed ==== %d \r\n", para->parse.terminal_parameters.MaxSpeed); + free(p); + + return; +} + +void handle_ProvinceID(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + union U16ToU8Array u16converter; // 注意大小端转换 + unsigned char *p = NULL; + unsigned short ProvinceID; + if ((buf == NULL) || (buf_len == 0)) + return; + + p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); + memcpy(p, buf, buf_len); + + memcpy(u16converter.u8array, p, buf_len); + ProvinceID = EndianSwap16(u16converter.u16val); + + para->parse.terminal_parameters.ProvinceID = ProvinceID; + // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + JT808_DEBUG("handle_ProvinceID ==== %d \r\n", para->parse.terminal_parameters.ProvinceID); + free(p); + + return; +} + +void handle_CityID(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + union U16ToU8Array u16converter; // 注意大小端转换 + unsigned char *p = NULL; + unsigned short CityID; + if ((buf == NULL) || (buf_len == 0)) + return; + + p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); + memcpy(p, buf, buf_len); + + memcpy(u16converter.u8array, p, buf_len); + CityID = EndianSwap16(u16converter.u16val); + + para->parse.terminal_parameters.CityID = CityID; + // FLASH_WriteByte(FLASH_ADDR, (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + JT808_DEBUG("handle_CityID ==== %d \r\n", para->parse.terminal_parameters.CityID); + free(p); + + return; +} + +void handle_CarPlateNum(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + // 字符串注意GBK转码 + unsigned char *p = NULL; + if ((buf == NULL) || (buf_len == 0)) + return; + + p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len + 1); + memcpy(p, buf, buf_len); + + memset(para->parse.terminal_parameters.CarPlateNum, 0, sizeof(para->parse.terminal_parameters.CarPlateNum)); + memcpy(para->parse.terminal_parameters.CarPlateNum, p, buf_len); + // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + JT808_DEBUG("handle_CarPlateNum ==== %s \r\n", para->parse.terminal_parameters.CarPlateNum); + free(p); + + return; +} + +void handle_CarPlateColor(unsigned char *buf, unsigned char buf_len, struct ProtocolParameter *para) +{ + unsigned char *p = NULL; + // unsigned char write_buf[FLASH_BUFFER_SIZE] = {0}; + if ((buf == NULL) || (buf_len == 0)) + return; + p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len + 1); + memcpy(p, buf, buf_len); + + para->parse.terminal_parameters.CarPlateColor = *p; + // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) ¶->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); + JT808_DEBUG("handle_CarPlateColor ==== 0x%02x \r\n", para->parse.terminal_parameters.CarPlateColor); + free(p); + + return; +} diff --git a/custom/jt808/src/terminal_register.c b/custom/jt808/src/terminal_register.c new file mode 100644 index 0000000..0f2be82 --- /dev/null +++ b/custom/jt808/src/terminal_register.c @@ -0,0 +1,56 @@ +#include "terminal_register.h" +#include "string.h" +#include "jt808_debug.h" + +struct RegisterInfo registerInfo_; + +void initRegisterInfo(struct ProtocolParameter *para) +{ + int lenManufacturer, lenTModel;//, lenTerminalId; + JT808_DEBUG("\r\n[ initRegisterInfo ] OK !\r\n"); + // 省域ID + para->register_info.province_id = para->parse.terminal_parameters.ProvinceID; + JT808_DEBUG("para->register_info.province_id = %d\r\n", para->register_info.province_id); + + // 市域ID + para->register_info.city_id = para->parse.terminal_parameters.CityID; + JT808_DEBUG("para->register_info.city_id = %04d\r\n", para->register_info.city_id); + + // 制造商ID + lenManufacturer = sizeof("XINDA"); + lenManufacturer = (lenManufacturer > 5) ? 5 : lenManufacturer; + + memset(para->register_info.manufacturer_id, 0, lenManufacturer); + memcpy(para->register_info.manufacturer_id, "XINDA", lenManufacturer); + JT808_DEBUG("para->register_info.manufacturer_id = %s\r\n", para->register_info.manufacturer_id); + + // 终端型号 + lenTModel = sizeof("ZXIAT-CZ01"); + lenTModel = (lenTModel > 20) ? 20 : lenTModel; + + memset(para->register_info.terminal_model, 0, lenTModel); + memcpy(para->register_info.terminal_model, "ZXIAT-CZ01", lenTModel); + JT808_DEBUG("para->register_info.terminal_model = %s\r\n", para->register_info.terminal_model); + + // //终端ID + // lenTerminalId = sizeof("1000000"); + // lenTerminalId=(lenTerminalId>20)?20:lenTerminalId; + + // memset(para->register_info.terminal_id, 0, lenTerminalId); + // memcpy(para->register_info.terminal_id, "1000000", lenTerminalId); + // JT808_DEBUG("para->register_info.terminal_id = %s\r\n", para->register_info.terminal_id); + + // 车牌颜色 + para->register_info.car_plate_color = para->parse.terminal_parameters.CarPlateColor; + JT808_DEBUG("para->register_info.car_plate_color = 0x%02x\r\n", para->register_info.car_plate_color); + + // 车牌号 + if (para->register_info.car_plate_color != 0x00) + { + memcpy(para->register_info.car_plate_num, para->parse.terminal_parameters.CarPlateNum, 12); + JT808_DEBUG("para->register_info.car_plate_num = %s\r\n", para->register_info.car_plate_num); + } + JT808_DEBUG("\r\n"); + JT808_DEBUG("注册信息更新完成\r\n"); + JT808_DEBUG("\r\n"); +} diff --git a/custom/jt808/src/util.c b/custom/jt808/src/util.c new file mode 100644 index 0000000..303e8af --- /dev/null +++ b/custom/jt808/src/util.c @@ -0,0 +1,162 @@ +#include "util.h" +#include "protocol_parameter.h" +#include "client_manager.h" +#include "jt808_debug.h" + +union U16ToU8Array u16converter; +union U32ToU8Array u32converter; + +// 双字节大小段互换 +unsigned short EndianSwap16(unsigned short u16val) +{ + return (((u16val & 0x00FF) << 8) + + ((u16val & 0xFF00) >> 8)); +} + +// 四字节大小端互换. +unsigned int EndianSwap32(unsigned int u32val) +{ + return (((u32val & 0x000000FF) << 24) + + ((u32val & 0x0000FF00) << 8) + + ((u32val & 0x00FF0000) >> 8) + + ((u32val & 0xFF000000) >> 24)); +} + +// 转义函数. outlen应大于inlen 建议outlen >= 2*inlen; +int Escape_C(unsigned char *in, unsigned int inlen, unsigned char *out, unsigned int *outlen) +{ + unsigned int i; + int offset_num; + if ((out == NULL) || ((*outlen) < 2 * inlen)) + { + JT808_DEBUG("[%s] FAILED \r\n", __FUNCTION__); + return -1; + } + + memset(out, 0, *outlen); + + offset_num = 0; + for (i = 0; i < inlen; ++i) + { + if (in[i] == PROTOCOL_SIGN) + { + out[i + offset_num] = PROTOCOL_ESCAPE; + out[i + 1 + offset_num] = PROTOCOL_ESCAPE_SIGN; + offset_num++; + } + else if (in[i] == PROTOCOL_ESCAPE) + { + out[i + offset_num] = PROTOCOL_ESCAPE; + out[i + 1 + offset_num] = PROTOCOL_ESCAPE_ESCAPE; + offset_num++; + } + else + { + out[i + offset_num] = in[i]; + } + } + *outlen = inlen + offset_num; + + return 0; +} + +// 逆转义函数. outlen >= (inlen/2) +int ReverseEscape_C(unsigned char *in, unsigned int inlen, unsigned char *out, unsigned int *outlen) +{ + // if ((out == NULL) || (inlen == 0)) + // return -1; + // memset(out, 0, *outlen); + unsigned int i; + int offset_num; +#ifdef __JT808_DEBUG + JT808_DEBUG("[ReverseEscape_C]:"); +#endif + + offset_num = 0; + for (i = 0; i < inlen; ++i) + { + if ((in[i] == PROTOCOL_ESCAPE) && (in[i + 1] == PROTOCOL_ESCAPE_SIGN)) + { + out[i - offset_num] = PROTOCOL_SIGN; + ++i; + offset_num++; + } + else if ((in[i] == PROTOCOL_ESCAPE) && (in[i + 1] == PROTOCOL_ESCAPE_ESCAPE)) + { + out[i - offset_num] = PROTOCOL_ESCAPE; + ++i; + offset_num++; + } + else + { + out[i - offset_num] = in[i]; +#ifdef __JT808_DEBUG + JT808_DEBUG("%02x ", out[i - offset_num]); +#endif + } + } +#ifdef __JT808_DEBUG + JT808_DEBUG("\r\n"); +#endif + + *outlen = inlen - offset_num; + + return 0; +} + +// 异或校验. +unsigned char BccCheckSum(const unsigned char *src, unsigned long len) +{ + unsigned char checksum = 0; + unsigned long i; + for (i = 0; i < len; ++i) + { + checksum = checksum ^ src[i]; + } +#ifdef __JT808_DEBUG + JT808_DEBUG("[BccCheckSum] OK !\r\n"); +#endif + return checksum; +} +// 处理字符串,返回子串在母串的第一个字符的位置 +int strStr(const char *haystack, const char *needle) +{ + int len1 = strlen(haystack); + int len2 = strlen(needle); + int i = 0, j = 0, k = 0; + bool jieguo = true; + if (len1 < len2) + { + jieguo = false; + } + else + { + for (i = 0; i <= len1 - len2; i++) + { + for (j = i, k = 0; j < i + len2; j++, k++) + { + if (haystack[j] != needle[k]) + { + jieguo = false; + break; + } + if (haystack[j] == needle[k]) + { + jieguo = true; + } + } + if (jieguo == true) + { + break; + } + } + } + if (jieguo == false) + { + return -1; + } + else + { + return i; + } +}