添加离线tts功能、adc检测,油门pwm功能 zsxfly20241108

This commit is contained in:
zsx 2024-11-08 18:02:29 +08:00
parent eda386aa78
commit 28ea8d867c
40 changed files with 2575 additions and 255 deletions

View File

@ -3,9 +3,19 @@
#include "cm_os.h" #include "cm_os.h"
#include "nmea/nmea.h" #include "nmea/nmea.h"
typedef struct{
uint16_t flow_num; // 流水号
nmeaINFO info; // GPS信息
nmeaPOS dpos; // 经纬度
} gps_data_t;
extern gps_data_t gps_data;
void gps_config_init(void); void gps_config_init(void);
/* 关闭串口 */ /* 关闭串口 */
void gps_config_close(void); void gps_config_close(void);
void GMTconvert(nmeaTIME *SourceTime, nmeaTIME *ConvertTime, uint8_t GMT, uint8_t AREA);
#endif /* GPS_CONFIG_H */ #endif /* GPS_CONFIG_H */

View File

@ -26,54 +26,79 @@ static osThreadId_t GPS_ThreadId = NULL; //串口数据接收、解析任务Hand
static void* gps_uart_sem = NULL; //串口数据接收、解析任务信号量 static void* gps_uart_sem = NULL; //串口数据接收、解析任务信号量
/**
* @brief trace GPS语句
* @param str: str_size:
* @retval
*/
void trace(const char *str, int str_size){
// app_printf("\r\nTrace: ");
// cm_uart_write(CM_UART_DEV_0, (void*)str, str_size, 1000);
}
/**
* @brief error
* @param str: str_size:
* @retval
*/
void error(const char *str, int str_size){
// app_printf("\r\nError: ");
// cm_uart_write(CM_UART_DEV_0, (void*)str, str_size, 1000);
}
/**
* @brief error
* @param str: str_size:
* @retval
*/
// void gps_info(const char *str, int str_size){
// app_printf("\r\nInfo: ");
// cm_uart_write(CM_UART_DEV_0, (void*)str, str_size, 1000);
// }
gps_data_t gps_data;
static nmeaPARSER parser;
/* 串口接收处理任务,平时使用信号量挂起,当收到接收事件后,释放信号量以触发读取任务 */ /* 串口接收处理任务,平时使用信号量挂起,当收到接收事件后,释放信号量以触发读取任务 */
static void gps_TaskHandle(void *param){ static void gps_TaskHandle(void *param){
int temp_len = 0; int temp_len = 0;
int it = 0; int it = 0;
// nmeaPOS dpos;
nmeaINFO info;
nmeaPARSER parser;
nmea_zero_INFO(&info); /* 设置用于输出调试信息的函数 */
nmea_property()->trace_func = &trace;
nmea_property()->error_func = &error;
// nmea_property()->info_func = &gps_info;
gps_data.flow_num =0;
nmea_zero_INFO(&gps_data.info);
nmea_parser_init(&parser); nmea_parser_init(&parser);
while(1){ while(1){
if(gps_uart_sem != NULL){ if(gps_uart_sem != NULL){
osSemaphoreAcquire(gps_uart_sem, osWaitForever);//阻塞 osSemaphoreAcquire(gps_uart_sem, osWaitForever);//阻塞
} }
temp_len = cm_uart_read(GPS_URAT, (void*)&gps_rev_data[gps_rev_len], GPS_BUF_LEN, 1000); temp_len = cm_uart_read(GPS_URAT, (void*)&gps_rev_data[gps_rev_len], GPS_BUF_LEN, 1000);
if(temp_len > 0){ gps_rev_len += temp_len;
if(gps_rev_len > 480){
nmea_parse(&parser, gps_rev_data, temp_len, &info); nmea_parse(&parser, gps_rev_data, gps_rev_len, &gps_data.info);
// nmea_info2pos(&info, &dpos); nmea_info2pos(&gps_data.info, &gps_data.dpos);
gps_data.flow_num++;
// app_printf(
// "%03d, Lat: %f, Lon: %f, Sig: %d, Fix: %d, RL= %d\n",
// it++, dpos.lat, dpos.lon, info.sig, info.fix, temp_len
// );
app_printf( app_printf(
"%03d, Lat: %f, Lon: %f, Sig: %d, Fix: %d, RL= %d\n", "\nGPS:%03d,Lat:%.02f,Lon:%.02f,Sig:%d,Fix:%d,RL=%d\n",
it++, info.lat, info.lon, info.sig, info.fix, temp_len it++, gps_data.info.lat, gps_data.info.lon, gps_data.info.sig, gps_data.info.fix, gps_rev_len
); );
// cm_uart_write(CM_UART_DEV_0, gps_rev_data, temp_len, 1000);
memset((void*)gps_rev_data, 0, temp_len); if((gps_data.info.fix == 1)||(gps_data.info.sig == 0)){ // 不可用
// app_printf("GPS no locate!\n");
led_set_event(EVENT_GPS_NO_LOCATE);
}else{
// app_printf("GPS locate success!\n");
led_set_event(EVENT_GPS_LOCATE_SUCCESS);
}
memset((void*)gps_rev_data, 0, gps_rev_len);
temp_len = 0; temp_len = 0;
gps_rev_len = 0; gps_rev_len = 0;
} }
// temp_len = cm_uart_read(GPS_URAT, (void*)&gps_rev_data[gps_rev_len], GPS_BUF_LEN - gps_rev_len, 1000);
// if(gps_rev_len < GPS_BUF_LEN){
// gps_rev_len += temp_len;
// }else{
// gps_rev_len = 0;
// }
// app_printf("uart rev data len = %d\n", gps_rev_len);
// if (gps_uart_sem != NULL && (strstr(gps_rev_data, "\r\n"))){
// //处理收到数据事件
// cm_uart_write(GPS_URAT, gps_rev_data, gps_rev_len, 1000);
// memset((void*)gps_rev_data, 0, sizeof(gps_rev_data));
// gps_rev_len = 0;
// }
} }
// nmea_parser_destroy(&parser); // nmea_parser_destroy(&parser);
} }
@ -138,7 +163,7 @@ void gps_config_init(void){
// 串口接收处理任务 // 串口接收处理任务
osThreadAttr_t gps_task_attr = {0}; osThreadAttr_t gps_task_attr = {0};
gps_task_attr.name = "gps_uart_task"; gps_task_attr.name = "gps_uart_task";
gps_task_attr.stack_size = 2048; gps_task_attr.stack_size = 4096 * 4;
gps_task_attr.priority= osPriorityNormal; gps_task_attr.priority= osPriorityNormal;
GPS_ThreadId= osThreadNew(gps_TaskHandle, 0, &gps_task_attr); GPS_ThreadId= osThreadNew(gps_TaskHandle, 0, &gps_task_attr);
@ -161,3 +186,115 @@ void gps_config_close(void){
} }
// 判断闰年(仅针对于2000以后的年份)
// iYear 两位年数
// 1:为闰年 0:为平年
static uint8_t IsLeapYear(uint8_t iYear){
uint16_t Year;
Year = 2000 + iYear;
if ((Year & 3) == 0){
return ((Year % 400 == 0) || (Year % 100 != 0));
}
return 0;
}
// 格林尼治时间换算世界各时区时间
// *DT: 表示日期时间的数组 格式 YY,MM,DD,HH,MM,SS
// GMT: 时区数
// AREA: 1(+)东区 W0(-)西区
void GMTconvert(nmeaTIME *SourceTime, nmeaTIME *ConvertTime, uint8_t GMT, uint8_t AREA){
uint32_t YY, MM, DD, hh, mm, ss; // 年月日时分秒暂存变量
if (GMT == 0)
return; // 如果处于0时区直接返回
if (GMT > 12)
return; // 时区最大为12 超过则返回
YY = SourceTime->year; // 获取年
MM = SourceTime->mon; // 获取月
DD = SourceTime->day; // 获取日
hh = SourceTime->hour; // 获取时
mm = SourceTime->min; // 获取分
ss = SourceTime->sec; // 获取秒
if(AREA){ // 东(+)时区处理
if(hh + GMT < 24){
hh += GMT; // 如果与格林尼治时间处于同一天则仅加小时即可
}else{ // 如果已经晚于格林尼治时间1天则进行日期处理
hh = hh + GMT - 24; // 先得出时间
if(MM == 1 || MM == 3 || MM == 5 || MM == 7 || MM == 8 || MM == 10){ // 大月份(12月单独处理)
if(DD < 31){
DD++;
}else{
DD = 1;
MM++;
}
}else if(MM == 4 || MM == 6 || MM == 9 || MM == 11){ // 小月份2月单独处理)
if(DD < 30){
DD++;
}else{
DD = 1;
MM++;
}
}else if (MM == 2){ // 处理2月份
if((DD == 29) || (DD == 28 && IsLeapYear(YY) == 0)){ // 本来是闰年且是2月29日 或者不是闰年且是2月28日
DD = 1;
MM++;
}else{
DD++;
}
}else if (MM == 12){ // 处理12月份
if (DD < 31){
DD++;
}else{ // 跨年最后一天
DD = 1;
MM = 1;
YY++;
}
}
}
}else{
if(hh >= GMT){
hh -= GMT; // 如果与格林尼治时间处于同一天则仅减小时即可
}else{ // 如果已经早于格林尼治时间1天则进行日期处理
hh = hh + 24 - GMT; // 先得出时间
if(MM == 2 || MM == 4 || MM == 6 || MM == 8 || MM == 9 || MM == 11){ // 上月是大月份(1月单独处理)
if(DD > 1){
DD--;
}else{
DD = 31;
MM--;
}
}else if(MM == 5 || MM == 7 || MM == 10 || MM == 12){ // 上月是小月份2月单独处理)
if(DD > 1){
DD--;
}else{
DD = 30;
MM--;
}
}else if(MM == 3){ // 处理上个月是2月份
if((DD == 1) && IsLeapYear(YY) == 0){ // 不是闰年
DD = 28;
MM--;
}else{
DD--;
}
}else if(MM == 1){ // 处理1月份
if(DD > 1){
DD--;
}else{ // 新年第一天
DD = 31;
MM = 12;
YY--;
}
}
}
}
ConvertTime->year = YY; // 更新年
ConvertTime->mon = MM; // 更新月
ConvertTime->day = DD; // 更新日
ConvertTime->hour = hh; // 更新时
ConvertTime->min = mm; // 更新分
ConvertTime->sec = ss; // 更新秒
}

View File

@ -0,0 +1,6 @@
CUSTOM_MAIN_DIR := custom/adc_dac
OC_FILES += $(CUSTOM_MAIN_DIR)/src/adc_dac.c
INC += -I'$(CUSTOM_MAIN_DIR)/inc'

View File

@ -0,0 +1,8 @@
#ifndef __ADC_DAC_H__
#define __ADC_DAC_H__
#include "cm_os.h"
void adc_dac_init(void);
#endif //__ADC_DAC_H__

View File

@ -0,0 +1,81 @@
#include "adc_dac.h"
#include <stdint.h>
#include "cm_adc.h"
#include "cm_gpio.h"
#include "cm_iomux.h"
#include "cm_pwm.h"
#define ADC_DAC_DEBUG_ENABLE 1
#if ADC_DAC_DEBUG_ENABLE
#include "app_uart.h"
#define DEBUG(fmt, args...) app_printf("[ADC]" fmt, ##args)
#else
#define DEBUG(fmt, arg...)
#endif
#define PWM0_IOMUX CM_IOMUX_PIN_74, CM_IOMUX_FUNC_FUNCTION1
#define PWM1_IOMUX CM_IOMUX_PIN_75, CM_IOMUX_FUNC_FUNCTION1
#define PWM2_IOMUX CM_IOMUX_PIN_21, CM_IOMUX_FUNC_FUNCTION2
#define PWM3_IOMUX 0, 0
osThreadId_t adc_dac_TaskHandle = NULL;
typedef enum {
ADC_power = 0,
ADC_acc = 1,
}adc_chx_t;
int32_t get_voltage(adc_chx_t chx){
int32_t voltage = 0;
if(chx == ADC_acc){
cm_gpio_set_level(CM_GPIO_NUM_20, 1);
}else if(chx == ADC_power){
cm_gpio_set_level(CM_GPIO_NUM_20, 0);
}else{
return 0;
}
osDelay(1);//5ms
if(0 != cm_adc_read(CM_ADC_0,&voltage)){
DEBUG("ADC read fail\r\n");
voltage = 0;
}
// cm_gpio_set_level(CM_GPIO_NUM_20, 1); //恢复默认状态
return voltage;
}
void adc_dac_task(void *argument){
while(1){
DEBUG("ADC_acc:%d\r\n",get_voltage(ADC_acc));
DEBUG("ADC_power:%d\r\n\n",get_voltage(ADC_power));
osDelay(500/5);
}
}
void adc_dac_init(void){
cm_gpio_cfg_t cfg = {0};
cfg.direction = CM_GPIO_DIRECTION_OUTPUT;
cfg.pull = CM_GPIO_PULL_UP;
cm_iomux_set_pin_func(CM_IOMUX_PIN_86, CM_IOMUX_FUNC_FUNCTION2);//初始化之前一定要先设置引脚复用
cm_gpio_init(CM_GPIO_NUM_20, &cfg);
cm_gpio_set_level(CM_GPIO_NUM_20, 1);
// pwm init
cm_iomux_set_pin_func(PWM0_IOMUX);
if(0 != cm_pwm_set_clk(CM_PWM_DEV_0, CM_PWM_CLK_12800K)){//时钟源选择需要放在open之前
DEBUG("pwm0 set clk fail\r\n");
return;
}
if(0 != cm_pwm_open_ns(CM_PWM_DEV_0, 100000,30000)){ //设置频率为10KHz占空比为30%
DEBUG("pwm0 open error\n");
}
osThreadAttr_t adc_dac_task_attr = {0};
adc_dac_task_attr.name = "adc_dac_task";
adc_dac_task_attr.stack_size = 1024;
adc_dac_task_attr.priority = osPriorityNormal;
adc_dac_TaskHandle = osThreadNew((osThreadFunc_t)adc_dac_task,0,&adc_dac_task_attr);
}

View File

@ -7,4 +7,7 @@ include $(CUSTOM_DIR)/custom_main/custom_main.mk
include $(CUSTOM_DIR)/nmealib/nmealib.mk include $(CUSTOM_DIR)/nmealib/nmealib.mk
include $(CUSTOM_DIR)/GPS/gps.mk include $(CUSTOM_DIR)/GPS/gps.mk
include $(CUSTOM_DIR)/jt808/jt808.mk include $(CUSTOM_DIR)/jt808/jt808.mk
include $(CUSTOM_DIR)/tcp_client/tcp_client.mk
include $(CUSTOM_DIR)/adc_dac/adc_dac.mk
include $(CUSTOM_DIR)/local_tts/local_tts.mk
endif endif

View File

@ -43,8 +43,24 @@ typedef enum{
RET_SUCCESS = 0 RET_SUCCESS = 0
}CM_RET_E; }CM_RET_E;
typedef enum{
EVENT_NETWORK_READY = 0x00000001,
EVENT_NETWORK_DISCONNECT = 0x00000002,
EVENT_GPS_LOCATE_SUCCESS = 0x00000004,
EVENT_GPS_NO_LOCATE = 0x00000008,
EVENT_ERROR = 0x80000000,
}led_event_t;
typedef union{
struct{
uint8_t network_ready : 1;
uint8_t gps_ready : 1;
uint8_t reserved : 6;
};
uint32_t val8;
}led_status_t;
void led_set_event(led_event_t event);
#endif /* __APP_COMMON_H__ */ #endif /* __APP_COMMON_H__ */

View File

@ -12,88 +12,281 @@
#include "cm_rtc.h" #include "cm_rtc.h"
#include "cm_gpio.h" #include "cm_gpio.h"
#include "cm_iomux.h" #include "cm_iomux.h"
// #include "cm_demo_i2c.h" #include "cm_modem.h"
// #include "cm_demo_adc.h"
// #include "cm_demo_spi.h"
// #include "cm_demo_lcd.h"
// #include "cm_demo_gpio.h"
// #include "cm_demo_keypad.h"
// #include "cm_demo_pwm.h"
// #include "cm_demo_pm.h"
// #include "cm_demo_http.h"
// #include "cm_demo_mqtt.h"
// #include "cm_demo_ntp.h"
// #include "cm_demo_fota.h"
// #include "cm_demo_audio.h"
// #include "cm_demo_virt_at.h"
// #include "cm_demo_lbs.h"
// #include "cm_demo_tts.h"
// #include "cm_modem.h"
// #include "cm_demo_cJSON.h"
// #include "cm_demo_sd.h"
// #include "cm_demo_gnss.h"
// #include "cm_demo_aliyun.h"
// #include "cm_demo_wifiscan.h"
// #include "cm_demo_camera.h"
// #include "cm_demo_ftp.h"
// #include "cm_demo_lwip.h"
// #include "cm_demo_ssl.h"
#include "app_uart.h" #include "app_uart.h"
#include "gps_config.h" #include "gps_config.h"
#include "client_manager.h" #include "app_common.h"
#include "jt808_packager.h"
#include "jt808_msg_pkg.h"
#include "jt808_msg_parse.h"
#include "jt808_pkg_transmit.h"
#include "tcp_client.h"
#include "local_tts.h"
#define SECOND_OF_DAY (24*60*60)
typedef struct cm_tm {
int tm_sec; /* 秒 取值区间为[0,59] */
int tm_min; /* 分 - 取值区间为[0,59] */
int tm_hour; /* 时 - 取值区间为[0,23] */
int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */
int tm_mon; /* 月份 */
int tm_year; /* 年份 */
}cm_tm_t;
// static const char * weekday[] = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
// static const char DayOfMon[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
osThreadId_t OC_APP_TaskHandle; osThreadId_t OC_APP_TaskHandle;
// void oc_ring_cb(unsigned char *param)
// {
// if(0 == strncmp((char *)param, "\r\nRING",6))//来电提示
// {
// app_printf("oc_ring_cb:%s\n",param);
// }
// else if (0 == strncmp((char *)param, "\r\n+CLCC:",8)) //来电信息
// {
// app_printf("oc_ring_cb:%s\n",param);
// }
// else if(0 == strncmp((char *)param, "\r\nNO CARRIER",12))//对方挂断
// {
// app_printf("oc_ring_cb:%s\n",param);
// }
// if (0 == strncmp((char *)param, "\r\n+CMTI:",8))//短信信息
// {
// app_printf("message:%s\n",param);
// }
// }
// static void cm_sec_to_date(long lSec, cm_tm_t *tTime)
// {
// unsigned short i,j,iDay;
// unsigned long lDay;
// lDay = lSec / SECOND_OF_DAY;
// lSec = lSec % SECOND_OF_DAY;
// i = 1970;
// while(lDay > 365)
// {
// if(((i%4==0)&&(i%100!=0)) || (i%400==0))
// {
// lDay -= 366;
// }
// else
// {
// lDay -= 365;
// }
// i++;
// }
// if((lDay == 365) && !(((i%4==0)&&(i%100!=0)) || (i%400==0)))
// {
// lDay -= 365;
// i++;
// }
// tTime->tm_year = i;
// for(j=0;j<12;j++)
// {
// if((j==1) && (((i%4==0)&&(i%100!=0)) || (i%400==0)))
// {
// iDay = 29;
// }
// else
// {
// iDay = DayOfMon[j];
// }
// if(lDay >= iDay) lDay -= iDay;
// else break;
// }
// tTime->tm_mon = j+1;
// tTime->tm_mday = lDay+1;
// tTime->tm_hour = ((lSec / 3600))%24;//这里注意世界时间已经加上北京时间差8
// tTime->tm_min = (lSec % 3600) / 60;
// tTime->tm_sec = (lSec % 3600) % 60;
// }
// static uint8_t cm_time_to_weekday(cm_tm_t *t)
// {
// uint32_t u32WeekDay = 0;
// uint32_t u32Year = t->tm_year;
// uint8_t u8Month = t->tm_mon;
// uint8_t u8Day = t->tm_mday;
// if(u8Month < 3U)
// {
// /*D = { [(23 x month) / 9] + day + 4 + year + [(year - 1) / 4] - [(year - 1) / 100] + [(year - 1) / 400] } mod 7*/
// u32WeekDay = (((23U * u8Month) / 9U) + u8Day + 4U + u32Year + ((u32Year - 1U) / 4U) - ((u32Year - 1U) / 100U) + ((u32Year - 1U) / 400U)) % 7U;
// }
// else
// {
// /*D = { [(23 x month) / 9] + day + 4 + year + [year / 4] - [year / 100] + [year / 400] - 2 } mod 7*/
// u32WeekDay = (((23U * u8Month) / 9U) + u8Day + 4U + u32Year + (u32Year / 4U) - (u32Year / 100U) + (u32Year / 400U) - 2U ) % 7U;
// }
// if (0U == u32WeekDay)
// {
// u32WeekDay = 7U;
// }
// return (uint8_t)u32WeekDay;
// }
void print_network_info(void){
cm_cereg_state_t cereg_state = {0};
if(0 == cm_modem_get_cpin()){
app_printf("sim card ready!\r\n\n");
}else{
app_printf("sim card not ready!\r\n\n");
}
if(0 ==cm_modem_get_cereg_state(&cereg_state)){ // 获取PS网络注册状态
app_printf("cereg_state:%d\n",cereg_state.state); // 注册状态
}else{
app_printf("cereg_get_state fail!\n\n");
}
if(cm_modem_get_pdp_state(1) == 1){ //网络就绪
app_printf("network ready\n");
}else{
app_printf("waiting for network...\n");
}
}
led_status_t led_status = {0};
osEventFlagsId_t LED_EventFlags = NULL;
void my_appimg_enter(char *param){ void my_appimg_enter(char *param){
int isRegistered=0;
int isAuthenticated=0;
unsigned int v_alarm_value = 0;
unsigned int v_status_value = 0;
LED_EventFlags =osEventFlagsNew(NULL);
if(NULL == LED_EventFlags){
app_printf("LED_EventFlags create fail\n");
// return;
}
cm_gpio_cfg_t cfg = {0}; cm_gpio_cfg_t cfg = {0};
cfg.direction = CM_GPIO_DIRECTION_OUTPUT; cfg.direction = CM_GPIO_DIRECTION_OUTPUT;
cfg.pull = CM_GPIO_PULL_UP; cfg.pull = CM_GPIO_PULL_UP;
cm_iomux_set_pin_func(CM_IOMUX_PIN_16, CM_IOMUX_FUNC_FUNCTION1);//初始化之前一定要先设置引脚复用 cm_iomux_set_pin_func(CM_IOMUX_PIN_16, CM_IOMUX_FUNC_FUNCTION1);//初始化之前一定要先设置引脚复用
cm_gpio_init(CM_GPIO_NUM_0, &cfg);
cm_gpio_set_level(CM_GPIO_NUM_0, 0);
cm_gpio_init(0, &cfg); // cm_iomux_set_pin_func(CM_IOMUX_PIN_77, CM_IOMUX_FUNC_FUNCTION2);//初始化之前一定要先设置引脚复用
cm_gpio_set_level(0, 1); // cm_gpio_init(CM_GPIO_NUM_13, &cfg);
// cm_gpio_set_level(CM_GPIO_NUM_13, 0);
app_uart_init(); app_uart_init();
gps_config_init();
app_printf("Hello, world!\r\n"); app_printf("Hello, world!\r\n");
initSystemParameters(0); // adc_dac_init();
//设置手机号唯一识别id local_tts_init();
setUUID();
//终端注册 local_tts_mute(0);// 取消静音
if(isRegistered == 0){ local_tts_volume(10); // 设置音量为5
jt808TerminalRegister(&isRegistered); local_tts_set(8, 15, CM_LOCAL_TTS_DIGIT_AUTO);
if(isRegistered==0){
// system_reboot(); while(1){
// continue;
cm_gpio_set_level(CM_GPIO_NUM_0, 1);
local_tts_text_play("欢迎使用莱昂特智能终端设备...。",0 ,osWaitForever); // 0:表示自动计算字符串长度,10000表示最大等待时间
// osDelay(3000/5);
cm_gpio_set_level(CM_GPIO_NUM_0, 0);
// osDelay(3000/5);
local_tts_text_play("欢迎使用游园猫,您的专属智能向导。",0 ,osWaitForever); // 0:表示自动计算字符串长度,10000表示最大等待时间
} }
//--------------------------------------------
{
// cm_tm_t t;
// int i;
int ret;
char buf[CM_VER_LEN] = {0};
int pdp_time_out=0;
cm_fs_system_info_t info = {0, 0};
cm_heap_stats_t stats = {0};
app_printf("\n\n\n\n\n");
app_printf("CM OpenCPU Starts\n");
cm_sys_get_cm_ver(buf, CM_VER_LEN);
app_printf("SDK VERSION:%s\n", buf);
cm_fs_getinfo(&info);
cm_mem_get_heap_stats(&stats);
app_printf("fs total:%d,remain:%d\n", info.total_size, info.free_size);
app_printf("heap total:%d,remain:%d\n",stats.total_size,stats.free);
// app_printf("waiting for network...\n");
// while(1){
// if(pdp_time_out>10){
// app_printf("network timeout\n");
// break;
// }
// if(cm_modem_get_pdp_state(1) == 1){
// app_printf("network ready\n");
// break;
// }
// osDelay(200);
// pdp_time_out++;
// }
}
// -----------------------------------------------------
jt808_set_term_param_init();
jt808_init();
tcp_client_init();
gps_config_init();
uint32_t led_event = 0;
while(1){
led_event = osEventFlagsWait(LED_EventFlags, 0x0000000f, osFlagsWaitAny, 0); //0等待
if (led_event & 0x80000000) { // 错误处理
// app_printf("led task error\n");
}else if(led_event & EVENT_NETWORK_READY){ // 网络就绪
app_printf("led network ready\n");
led_status.network_ready = 1;
}else if(led_event & EVENT_NETWORK_DISCONNECT){ // 网络断开
app_printf("led network disconnect\n");
led_status.network_ready = 0;
}else if(led_event & EVENT_GPS_LOCATE_SUCCESS){ // GPS定位成功
app_printf("led GPS locate success\n");
led_status.gps_ready = 1;
}else if(led_event & EVENT_GPS_NO_LOCATE){ // GPS无定位
app_printf("led GPS no locate\n");
led_status.gps_ready = 0;
}
if(led_status.network_ready && led_status.gps_ready){ // 网络就绪GPS定位成功
cm_gpio_set_level(CM_GPIO_NUM_0, 1); // 常亮
osDelay(1000/5);//300ms
}else if(led_status.network_ready && (0 ==led_status.gps_ready)){ // 网络就绪GPS无定位
cm_gpio_set_level(CM_GPIO_NUM_0, 1);
osDelay(500/5);//300ms
cm_gpio_set_level(CM_GPIO_NUM_0, 0);
osDelay(500/5);//300ms
}else if((0 ==led_status.network_ready) && led_status.gps_ready){ // 网络断开GPS定位成功
for(int i=0;i<5;i++){ // 快闪500ms灭500ms
cm_gpio_set_level(CM_GPIO_NUM_0, 1);
osDelay(100/5);//300ms
cm_gpio_set_level(CM_GPIO_NUM_0, 0);
osDelay(100/5);//300ms
}
cm_gpio_set_level(CM_GPIO_NUM_0, 0);
osDelay(500/5);//300ms
}else{ // 网络断开GPS无定位
cm_gpio_set_level(CM_GPIO_NUM_0, 1); // 快闪
osDelay(100/5);//300ms
cm_gpio_set_level(CM_GPIO_NUM_0, 0);
osDelay(100/5);//300ms
} }
//终端鉴权
if(isAuthenticated == 0){
jt808TerminalAuthentication(&isAuthenticated);
if(isAuthenticated==0){
// system_reboot();
// continue;
} }
} }
//设置位置上报警报位、状态位 void led_set_event(led_event_t event){
initLocationInfo(v_alarm_value, v_status_value); if(NULL == LED_EventFlags){
setStatusBit(); app_printf("LED_EventFlags is NULL\n");
while(1){ return;
osDelay(200/5);//300ms
cm_gpio_set_level(0, 1);
osDelay(200/5);//300ms
cm_gpio_set_level(0, 0);
// app_printf("Hello, world!\r\n");
} }
osEventFlagsSet(LED_EventFlags, event);
} }
@ -101,11 +294,10 @@ int cm_opencpu_entry(char * param)
{ {
osThreadAttr_t app_task_attr = {0}; osThreadAttr_t app_task_attr = {0};
app_task_attr.name = "main_task"; app_task_attr.name = "main_task";
app_task_attr.stack_size = 4096 * 2; app_task_attr.stack_size = 4096 * 4;
app_task_attr.priority = osPriorityNormal; app_task_attr.priority = osPriorityNormal;
OC_APP_TaskHandle = osThreadNew((osThreadFunc_t)my_appimg_enter,0,&app_task_attr); OC_APP_TaskHandle = osThreadNew((osThreadFunc_t)my_appimg_enter,0,&app_task_attr);
return 0; return 0;
return 0;
} }

View File

@ -0,0 +1,24 @@
#ifndef _JT808_CONFIG_H_
#define _JT808_CONFIG_H_
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "jt808_util.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
#include "cm_mem.h"
#define jt808_malloc(size) cm_malloc(size)
#define jt808_realloc(ptr, size) cm_realloc(ptr, size)
#define jt808_free(ptr) cm_free(ptr)
#endif

View File

@ -1,13 +0,0 @@
#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

View File

@ -0,0 +1,25 @@
#ifndef __JT808_PKG_PARSE__
#define __JT808_PKG_PARSE__
#include "jt808_protocol.h"
#include "jt808_set_TermParam.h"
#include "jt808_config.h"
#pragma pack(1)
// 解析结果以及终端参数项
typedef struct{
uint16_t Rsp_flow_num; //应答流水号
uint16_t Rsp_msg_id; // 应答消息ID
uint8_t Rsp_result; // 应答结果
MsgHead_t msg_head; // 解析的消息头
Term_Param_item_t *term_param_item; // 终端参数项
}PrsResult_t;
#pragma pack()
// ------------------------------- 全局变量声明 ----------
extern PrsResult_t PrsResult; // 解析结果以及终端参数项
int jt808_msg_parse(const uint8_t *BufferReceive, uint16_t length, PrsResult_t *PrsResult);
#endif // __JT808_PKG_PARSE__

View File

@ -0,0 +1,14 @@
#ifndef __JT808_PKG_PKG__
#define __JT808_PKG_PKG__
#include "jt808_protocol.h"
#include "jt808_config.h"
typedef struct {
uint8_t *buf; // 打包后的消息帧
uint16_t len; // 打包后的消息帧长度
} JT808MsgESC_t;
// 消息帧打包 (会自动为msgEscape->buf分配合适长度的内存注意释放)
int jt808_msg_pkg(MessageID_t Msg_ID, JT808MsgESC_t *msgEscape);
#endif // __JT808_PKG_PKG__

View File

@ -0,0 +1,33 @@
#ifndef _JT808_PKG_TRANSMIT_H_
#define _JT808_PKG_TRANSMIT_H_
#include "jt808_msg_pkg.h"
#include "jt808_msg_parse.h"
#include "jt808_config.h"
#include "tcp_client.h"
// #pragma pack(1)
typedef struct{
uint16_t msg_id;
uint32_t timeout; //超时时间单位ms
}pkg_msg_t;
// #pragma pack()
// 原型 int tcp_client_send(const char *buf, int len);
#ifdef __TCP_CLIENT_H__
#define PKG_SEND(__buf, __len) tcp_client_send(__buf, __len)
#else
#define PKG_SEND(__buf, __len) 0
#endif
extern PrsResult_t PrsResult;
// 触发消息发送
int jt808_pkg_send(MessageID_t Msg_ID, uint32_t timeout);
// 接收处理 (放入TCP接收回调中)
void jt808_pkg_handle(uint8_t *receive_buf, uint16_t receive_len);
// jt808协议初始化
int jt808_init(void);
#endif // _JT808_PKG_TRANSMIT_H_

View File

@ -0,0 +1,331 @@
#ifndef __JT808_PROTOCOL__
#define __JT808_PROTOCOL__
#include "jt808_config.h"
// 已支持的消息ID
typedef enum {
ID_Term_GenResp = 0x0001, // 终端通用应答
ID_Plat_GenResp = 0x8001, // 平台通用应答
ID_Term_HB = 0x0002, // 终端心跳
ID_FillPktReq = 0x8003, // 补传分包请求
ID_Term_Reg = 0x0100, // 终端注册
ID_Term_RegResp = 0x8100, // 终端注册应答
ID_Term_Logout = 0x0003, // 终端注销
ID_Term_Auth = 0x0102, // 终端鉴权
ID_SetTermParams = 0x8103, // 设置终端参数
ID_GetTermParams = 0x8104, // 查询终端参数
ID_GetTermParamsResp = 0x0104, // 查询终端参数应答
ID_Term_Ctrl = 0x8105, // 终端控制
ID_GetSpecificTermParams = 0x8106,// 查询指定终端参数
ID_GetTermAttr = 0x8107, // 查询终端属性
ID_GetTermAttrResp = 0x0107, // 查询终端属性应答
ID_Term_Upgrade = 0x8108, // 下发终端升级包
ID_Term_UpgradeResult = 0x0108, // 终端升级结果通知
ID_LocReport = 0x0200, // 位置信息汇报
ID_GetLocInfo = 0x8201, // 位置信息查询
ID_GetLocInfoResp = 0x0201, // 位置信息查询应答
ID_LocTrackingCtrl = 0x8202, // 临时位置跟踪控制
ID_TxtMsgdelivery = 0x8300, // 文本信息下发
ID_Car_Ctrl = 0x8500, // 车辆控制
ID_Car_CtrlResp = 0x0500, // 车辆控制应答
} MessageID_t;
#pragma pack(1)
// ----------------------------- 协议消息体结构体定义 ----------
// 终端通用应答体0x0001
typedef struct {
uint16_t msg_flow_num; // 对应的平台消息的流水号
uint16_t msg_id_ack; // 对应的平台消息的 ID
uint8_t result; // 结果 0成功/确认1失败2消息有误3不支持
}Term_GenResp_t;
// 平台通用应答体0x8001
typedef struct {
uint16_t msg_flow_num; // 对应的终端消息的流水号
uint16_t msg_id_ack; // 对应的终端消息的 ID
uint8_t result; // 结果 0成功/确认1失败2消息有误3不支持
}Plat_GenResp_t;
// 终端心跳体(0x0002空包)
// 补传分包请求体0x8003
typedef struct {
uint16_t msg_flow_num; // 对应要求补传的原始消息第一包的消息流水号
uint8_t Total_num; // 重传包总数
uint16_t *pkt_seq; // 重传包序号顺序排列,如“包 ID1 包 ID2包 IDn”。
}FillPktReq_t;
typedef enum {
none_plate = 0, // 无牌照
blue_plate = 1, // 蓝牌
yellow_plate = 2, // 黄牌
black_plate = 3, // 黑牌
white_plate = 4, // 白牌
green_plate = 5, // 绿牌
other_plate = 6, // 其他牌照
}plate_type_t;
// 终端注册体0x0100
typedef struct {
uint16_t province_id;// 省域ID
uint16_t city_id;// 市县域ID
uint8_t manufacturer_id[5];// 制造商ID, 固定5个字节
uint8_t term_model[20];// 终端型号, 固定20个字节, 位数不足后补0x00
uint8_t term_id[7];// 终端ID, 固定7个字节, 位数不足后补0x00
uint8_t car_plate_color;// 车牌颜色, 0表示未上牌
uint8_t car_plate_num[10];// 车辆标识, 仅在上牌时使用
}Term_RegInfo_t;
// 终端注册应答体0x8100
typedef struct {
uint16_t msg_flow_num; // 对应的终端注册消息的流水号
uint8_t result; // 0成功1车辆已被注册2数据库中无该车辆3终端已被注册4数据库中无该终端
// uint8_t *str_auth_code; //只有在成功后才有该字段
}Term_RegResp_t;
// 终端注销体(0x0003空包)
// 终端鉴权体0x0102
typedef struct {
void *str_auth_code; //只有在成功后才有该字段
}Term_Auth_t;
// 终端参数项数据结构体
typedef struct TermParamlist_t{
uint32_t param_id; // 参数ID
uint8_t param_len; // 参数长度
void *param_value; // 参数值
struct TermParamlist_t *next; // 下一个参数项
}TermParamlist_t;
// 设置终端参数体0x8103
typedef struct {
uint8_t param_Total_num; // 参数总数
TermParamlist_t *param_list; // 参数项列表
}SetTermParams_t;
// 查询终端参数体(0x8104空包)
// 查询指定终端参数体0x8106
typedef struct {
uint8_t param_Total_num; // 参数总数
uint32_t *param_id_list; // 参数ID列表
}GetSpecificTermParams_t;
// 查询终端参数应答体0x0104
typedef struct {
uint16_t msg_flow_num; // 对应的终端参数查询消息的流水号
uint8_t param_Total_num; // 参数总数
TermParamlist_t *param_list; // 参数项列表
}GetTermParamsResp_t;
// 终端控制命令字
typedef union {
struct{
uint8_t _0 : 1; //
uint8_t _1 : 1; // 无线升级
uint8_t _2 : 1; // 控制终端连接指定服务器
uint8_t _3 : 1; // 终端关机
uint8_t _4 : 1; // 终端复位
uint8_t _5 : 1; // 终端恢复出厂设置
uint8_t _6 : 1; // 关闭数据通信
uint8_t _7 : 1; // 关闭所有无线通信
};
uint8_t val8;
}Term_Ctrl_Cmd_t;
// 终端控制体0x8105
typedef struct {
Term_Ctrl_Cmd_t com_word; //命令字
uint8_t *str_cmd_params; //命令参数每个 STRING 字段先按 GBK 编码处理后再组成消息
}Term_Ctrl_t;
// 查询终端属性体(0x8107空包)
// 查询终端属性应答体(0x0107)
typedef struct {
uint16_t term_type; // 终端类型
uint8_t manufacturer_id[5];// 制造商ID, 固定5个字节
uint8_t term_model[20];// 终端型号, 固定20个字节, 位数不足后补0x00
uint8_t term_id[7];// 终端ID, 固定7个字节, 位数不足后补0x00
uint8_t term_ICCID[10];// ICCID,
uint8_t hw_ver_len;// 终端硬件版本号长度
uint8_t *str_hw_ver;// 终端硬件版本号
uint8_t fw_ver_len;// 终端固件版本号长度
uint8_t *str_fw_ver;// 终端固件版本号
uint8_t GnssModule_attr;// GNSS模块属性
uint8_t CommModule_attr;// 通讯模块属性
}GetTermAttrResp_t;
// 下发终端升级包体0x8108
typedef struct {
uint8_t upgrade_type; // 升级类型
uint8_t manufacturer_id[5];// 制造商ID, 固定5个字节
uint8_t ver_len;// 版本号长度
uint8_t *str_ver;// 版本号
uint32_t upgrade_pkg_len;// 升级包长度 单位为 BYTE
uint8_t *str_upgrade_pkg;// 升级包
}Term_Upgrade_t;
// 终端升级结果通知体0x0108
typedef struct {
uint8_t upgrade_type; // 升级类型 0终端12道路运输证 IC 卡读卡器52北斗卫星定位模块
uint8_t upgrade_result; // 结果 0成功1失败2取消
}Term_UpgradeResult_t;
// 报警标志位
typedef union{
struct{
uint32_t sos : 1;// bit_0 紧急报警,触动报警开关后触/收到应答后清零
uint32_t overspeed : 1;// bit_1 超速报警
uint32_t fatigue : 1;// bit_2 疲劳驾驶
uint32_t early_warning : 1;// bit_3 危险预警
uint32_t gnss_fault : 1;// bit_4 GNSS模块发生故障
uint32_t gnss_antenna_cut : 1; // bit_5 GNSS天线未接或被剪断
uint32_t gnss_antenna_shortcircuit : 1;// bit_6 GNSS天线短路
uint32_t power_low : 1;// bit_7 终端主电源欠压
uint32_t power_cut : 1;// bit_8 终端主电源掉电
uint32_t lcd_fault : 1;// bit_9 终端LCD或显示器故障
uint32_t tts_fault : 1;// bit_10 TTS模块故障
uint32_t camera_fault : 1;// bit_11 摄像头故障
uint32_t transport_license_IC_card_fault : 1;// bit_12 道路运输证 IC 卡模块故障
uint32_t overspeed_notice : 1; // bit_1 超速预警
uint32_t fatigue_notice : 1;// bit_2 疲劳驾驶预警
uint32_t retain1 : 3;// 保留3位
uint32_t day_drive_overtime : 1;// bit_18 当天累计驾驶超时
uint32_t stop_driving_overtime : 1;// bit_19 超时停车
uint32_t in_out_area : 1;// bit_20 进出区域.收到应答后清零
uint32_t in_out_road : 1; // bit_21 进出路线.收到应答后清零
uint32_t road_drive_time : 1;// bit_22 路段行驶时间不足/过长.收到应答后清零
uint32_t road_deviate : 1;// bit_23 路线偏离报警
uint32_t vss_fault : 1;// bit_24 车辆VSS故障
uint32_t oil_fault : 1;// bit_25 车辆油量异常
uint32_t car_alarm : 1;// bit_26 车辆被盗(通过车辆防盗器)
uint32_t car_acc_alarm : 1;// bit_27 车辆非法点火.收到应答后清零
uint32_t car_move : 1;// bit_28 车辆非法位移.收到应答后清零
uint32_t collision : 1;// 碰撞报警
uint32_t rollover : 1;// 侧翻报警
uint32_t Illegal_opendoor : 1;// 非法开门报警(终端未设置区域时,不判断非法开门)/收到应答后清零
};
uint32_t val32;
}LocAlarm_t;
// 状态位
typedef union{
struct{
uint32_t acc : 1;// ACC开关, 0:ACC关; 1:ACC开
uint32_t positioning : 1;// 定位标志, 0:未定位; 1:定位
uint32_t sn_latitude : 1;// 纬度半球, 0:北纬: 1:南纬
uint32_t ew_longitude : 1;// 经度半球, 0:东经; 1:西经
uint32_t operation : 1; // 0:运营状态; 1:停运状态
uint32_t gps_encrypt : 1;// 0:经纬度未经保密插件加密; 1:经纬度已经保密插件加密
uint32_t retain1 : 2;// 保留2位
uint32_t trip_status : 2;// 00: 空车; 01: 半载; 10: 保留; 11: 满载
uint32_t oil_cut : 1;// 0:车辆油路正常; 1:车辆油路断开
uint32_t circuit_cut : 1;// 0:车辆电路正常; 1:车辆电路断开
uint32_t door_lock : 1;// 0:车门解锁; 1: 车门加锁
uint32_t door1_status : 1;// 0:门1 关; 1: 门1 开; (前门)
uint32_t door2_status : 1;// 0:门2 关; 1: 门2 开; (中门)
uint32_t door3_status : 1;// 0:门 3 关; 1: 门 3 开; (后门)
uint32_t door4_status : 1;// 0:门 4 关; 1: 门 4 开; (驾驶席门)
uint32_t door5_status : 1;// 0:门 5 关; 1: 门 5 开; (自定义)
uint32_t gps_en : 1;// 0: 未使用 GPS 卫星进行定位; 1: 使用 GPS 卫星进行定位
uint32_t beidou_en : 1;// 0: 未使用北斗卫星进行定位; 1: 使用北斗卫星进行定位
uint32_t glonass_en : 1;// 0: 未使用 GLONASS 卫星进行定位; 1: 使用 GLONASS 卫星进行定位
uint32_t galileo_en : 1;// 0: 未使用 Galileo 卫星进行定位; 1: 使用 Galileo 卫星进行定位
uint32_t retain2 : 10;// 保留10位
};
uint32_t val32;
}LocStatus_t;
// 位置信息汇报消息体
typedef struct{
LocAlarm_t alarm_flag; // 报警标志
LocStatus_t status; // 状态
uint32_t latitude; // 纬度
uint32_t longitude; // 经度
uint16_t altitude; // 高度
uint16_t speed; // 速度
uint16_t direction; // 方向
uint8_t BCDtime[6]; // 时间YY-MM-DD-hh-mm-ssGMT+8 时间,本标准中之后涉及的时间均采用此时区)
}Loc_basic_info_t;
typedef enum{
MileageID = 0x01,// 里程, 1/10km, 对应车上里程表读数, DWORD
OilMassID = 0x02,// 油量, 1/10L, 对应车上油量表读数, WORD
TachographSpeedID = 0x03,// 行驶记录功能获取的速度, 1/10km/h, WORD
AlarmCountID = 0x04,// 需要人工确认报警事件的 ID, 从 1 开始计数, WORD
OverSpeedAlarmID = 0x11,// 超速报警附加信息, BYTE or BYTE+DWORD
AccessAreaAlarmID = 0x12,// 进出区域/路线报警附加信息, BYTE+DWORD+BYTE
DrivingTimeAlarmID = 0x13,// 路段行驶时间不足/过长报警附加信息, DWORD+WORD+BYTE
VehicleSignalStatusID = 0x25,// 扩展车辆信号状态位, DWORD
IoStatusID = 0x2A,// IO 状态位, WORD
AnalogQuantityID = 0x2B,// 模拟量, DWORD
NetworkQuantityID = 0x30,// 无线通信网络信号强度, BYTE
GnssSatellitesID = 0x31,// GNSS 定位卫星数, BYTE
CustomInformationLengthID = 0xE0,// 后续自定义信息长度, BYTE
}addi_infoID_t;
// 位置附加信息
typedef struct Loc_addi_info_t{
uint8_t msg_id; // 附加消息ID
uint8_t msg_len; // 附加消息长度
void *msg; // 附加消息内容
struct Loc_addi_info_t *next; // 下一个附加信息
}Loc_addi_info_t;
// 位置信息汇报体0x0200
typedef struct{
Loc_basic_info_t basic_info; // 基本信息
Loc_addi_info_t *addi_info; // 附加信息
}LocReport_t;
// 位置信息查询体(0x8201空包)
// 位置信息查询应答体0x0201
typedef struct {
uint16_t msg_flow_num; // 对应的位置信息查询消息的流水号
LocReport_t *loc_info; // 位置信息
}GetLocInfoResp_t;
// 临时位置跟踪控制体0x8202
typedef struct {
uint16_t time_intv; // 时间间隔
uint32_t eff_time; // 追踪有效时间单位为秒s
}LocTrackingCtrl_t;
// ------------------------------ 协议帧结构体定义 ----------
// 转义相关标识
typedef enum {
PSIGN = 0x7E, // 标识位
PESC = 0x7D, // 转义标识
PESC_SIGN = 0x02, // 0x7E<-->0x7D后紧跟一个0x02
PESC_ESCAPE = 0x01, // 0x7D<-->0x7D后紧跟一个0x01
} ProtocolEscapeFlag;
// 消息体属性
typedef union {
struct {
uint16_t msgbodylen : 10;// 消息体长度, 占用10bit
uint16_t encrypt : 3;// 数据加密方式, 当此三位都为0, 表示消息体不加密, 当第10位为1, 表示消息体经过RSA算法加密
uint16_t packet : 1;// 分包标记
uint16_t retain : 2;// 保留2位
};
uint16_t val16;
}MsgBodyAttr_t;
// 消息头
typedef struct {
uint16_t msg_id;// 消息ID
MsgBodyAttr_t msgbody_attr;// 消息体属性
uint8_t phone_BCDnum[6];// 终端手机号
uint16_t msg_flow_num;// 消息流水号
uint16_t total_packet;// 总包数, 分包情况下使用
uint16_t packet_seq;// 当前包序号, 分包情况下使用
}MsgHead_t;
// 消息结构体
typedef struct {
uint8_t Head_SIGN; // 头标识位
MsgHead_t msg_head; // 消息头
void *p_msg_body; // 消息体
uint8_t BCC_Check; // BCC校验码
uint8_t Tail_SIGN; // 尾标识位
}JT808_2013_MsgFrame_t;
#pragma pack()
#endif // __JT808_PROTOCOL__

View File

@ -0,0 +1,70 @@
#ifndef JT808_SET_TERM_PARAM_H_
#define JT808_SET_TERM_PARAM_H_
#include "jt808_protocol.h"
#include "jt808_config.h"
#pragma pack(1)
// 终端参数设置项参数ID
typedef enum {
HeartBeatInterval = 0x0001,// DWORD, 终端心跳发送间隔(s)
MainServerAddr = 0x0013,//STRING, 主服务器地址,IP 或域名
ServerPort = 0x0018,//DWORD, 服务器 TCP 端口
DefaultTimeReportInterval = 0x0029,// DWORD, 缺省时间汇报间隔
InflexionAngle = 0x0030,// DWORD, 拐点补传角度, < 180°
MaxSpeed = 0x0055,// DWORD, 最高速度, km/h.
ProvinceID = 0x0081,// WORD, 车辆所在的省域 ID
CityID = 0x0082,// WORD, 车辆所在的市域 ID
CarPlateNum = 0x0083,//STRING, 公安交通管理部门颁发的机动车号牌
CarPlateColor = 0x0084,//车牌颜色,按照 JT/T415-2006 的 5.4.12
}set_TermParamID_t;
typedef struct{
uint32_t HeartBeatInterval;// DWORD, 终端心跳发送间隔(s)
uint8_t MainServerAddr[50];//STRING, 主服务器地址,IP 或域名
uint32_t ServerPort;//DWORD, 服务器 TCP 端口
uint32_t DefaultTimeReportInterval;// DWORD, 缺省时间汇报间隔
uint32_t InflexionAngle;// DWORD, 拐点补传角度, < 180°
uint32_t MaxSpeed;// DWORD, 最高速度, km/h
uint16_t ProvinceID;// WORD, 车辆所在的省域 ID
uint16_t CityID;// WORD, 车辆所在的市域 ID
uint8_t CarPlateNum[10];//STRING, 公安交通管理部门颁发的机动车号牌
uint8_t CarPlateColor;//车牌颜色,按照 JT/T415-2006 的 5.4.12
}set_TermParam_t;
// big_标记的参数需以大端方式存储需手动转换为大端
typedef struct {// 终端参数项
uint8_t phone_BCDnum[6];// 终端手机号
uint16_t msg_flow_num;// 累加的消息流水号
Term_RegInfo_t big_reg_info; // 注册信息
Term_Auth_t big_auth_info; // 终端鉴权信息
set_TermParam_t set_term_param; // 设置终端参数
GetSpecificTermParams_t big_specific_params; // 解析出的待查询指定终端参数列表
Term_Ctrl_t big_ctrl_info; // 解析出的终端控制信息
Term_Upgrade_t big_upgrade_info; // 解析出的升级信息
LocReport_t big_loc_report; // 位置信息汇报
LocTrackingCtrl_t big_loc_tracking_ctrl; // 临时位置跟踪控制
}Term_Param_item_t;
#pragma pack()
extern Term_Param_item_t jt808_term_param_item;
extern osThreadFunc_t Autoreport_param_ThreadId;
// 控制车辆状态
void jt808_Set_CarStatus(uint8_t status);
// 获取车辆状态
uint8_t jt808_Get_CarStatus(void);
// 设置终端参数
int jt808_setTermParam(set_TermParamID_t param_id, void *param, uint8_t param_len);
// 启动自动上报参数
void jt808_Autoreport_param_start(void);
// 停止自动上报参数
void jt808_Autoreport_param_stop(void);
// 初始化终端参数
void jt808_set_term_param_init(void);
#endif // JT808_SET_TERM_PARAM_H_

View File

@ -0,0 +1,37 @@
#ifndef JT808_UTIL_H_
#define JT808_UTIL_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
// #include <vector>
// 双字节大小端交换
uint16_t Swap16(uint16_t val16);
// 四字节大小端交换
uint32_t Swap32(uint32_t val32);
// 异或校验
uint8_t BCC_Check(const uint8_t *src, uint32_t len);
// 十进制转BCD码
uint8_t DecToBcd(uint8_t Dec);
// BCD码转十进制
uint8_t BcdToDec(uint8_t Bcd);
// 原始字符串转BCD码 //奇数位时首位BCD码前面补0
uint8_t *rawStrToBcd(uint8_t *bcd, const uint8_t *str, uint16_t str_len);
// BCD转字符串自动去掉bcd码前导零
// bcdlen 为bcd码字节数
uint8_t *BcdToStr(uint8_t *str, const uint8_t *bcd, int bcd_len);
// 原始BCD数据转字符串
// strlen 为原始BCD数据字节数
uint8_t *rawBcdToStr(uint8_t *str, const uint8_t *bcd, int bcd_len);
#endif // JT808_UTIL_H_

View File

@ -263,7 +263,7 @@ struct ProtocolParameter
struct LocationTrackingControl location_tracking_control; struct LocationTrackingControl location_tracking_control;
// 升级信息. // 升级信息.
struct UpgradeInfo upgrade_info; struct UpgradeInfo big_upgrade_info;
// 补传分包信息. // 补传分包信息.
struct FillPacket fill_packet; struct FillPacket fill_packet;
@ -298,7 +298,7 @@ struct ProtocolParameter
struct LocationTrackingControl location_tracking_control; struct LocationTrackingControl location_tracking_control;
// 解析出的升级信息. // 解析出的升级信息.
struct UpgradeInfo upgrade_info; struct UpgradeInfo big_upgrade_info;
// 解析出的补传分包信息. // 解析出的补传分包信息.
struct FillPacket fill_packet; struct FillPacket fill_packet;

View File

@ -1,14 +1,19 @@
CUSTOM_MAIN_DIR := custom/jt808 CUSTOM_MAIN_DIR := custom/jt808
OC_FILES += $(CUSTOM_MAIN_DIR)/src/bcd.c # OC_FILES += $(CUSTOM_MAIN_DIR)/src/bcd.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/client_manager.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/gbk_utf8.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/jt808_packager.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/jt808_parser.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/location_report.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/set_terminal_parameter.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/terminal_register.c # OC_FILES += $(CUSTOM_MAIN_DIR)/src/terminal_register.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/util.c # OC_FILES += $(CUSTOM_MAIN_DIR)/src/util.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/jt808_util.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/jt808_msg_pkg.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/jt808_msg_parse.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/jt808_pkg_transmit.c
OC_FILES += $(CUSTOM_MAIN_DIR)/src/jt808_set_TermParam.c
INC += -I'$(CUSTOM_MAIN_DIR)/inc' INC += -I'$(CUSTOM_MAIN_DIR)/inc'

View File

@ -1,5 +1,5 @@
#include "bcd.h" #include "bcd.h"
#include "jt808_debug.h" #include "jt808_config.h"
unsigned char HexToBcd(unsigned char src) unsigned char HexToBcd(unsigned char src)
{ {

View File

@ -6,7 +6,7 @@
#include "bcd.h" #include "bcd.h"
#include "jt808_packager.h" #include "jt808_packager.h"
#include "jt808_parser.h" #include "jt808_parser.h"
#include "jt808_debug.h" #include "jt808_config.h"
uint8_t Non_transliterated_receive[1024]; uint8_t Non_transliterated_receive[1024];
struct ProtocolParameter parameter_; struct ProtocolParameter parameter_;

View File

@ -1,5 +1,5 @@
#include "gbk_utf8.h" #include "gbk_utf8.h"
#include "jt808_debug.h" #include "jt808_config.h"
/* /*
namespace libjt808 namespace libjt808

View File

@ -0,0 +1,183 @@
#include "jt808_msg_parse.h"
#include "jt808_pkg_transmit.h"
PrsResult_t PrsResult;
// 消息体解析
static int jt808_BodyParse(void *Prsmsg_body, PrsResult_t *PrsResult){
switch (PrsResult->msg_head.msg_id){
case ID_Plat_GenResp:{// 平台通用应答
memcpy(&(PrsResult->Rsp_flow_num), Prsmsg_body, sizeof(Plat_GenResp_t));
// 转小端
PrsResult->Rsp_flow_num = Swap16(PrsResult->Rsp_flow_num);
PrsResult->Rsp_msg_id = Swap16(PrsResult->Rsp_msg_id);
// PrsResult->Rsp_result = PrsResult->Rsp_result;
break;
}
case ID_FillPktReq:{// 补传分包请求
break;
}
case ID_Term_RegResp:{// 终端注册应答
PrsResult->Rsp_flow_num = (uint16_t)(((uint8_t *)Prsmsg_body)[0] << 8) | (((uint8_t *)Prsmsg_body)[1]);
PrsResult->Rsp_result = ((uint8_t *)Prsmsg_body)[2];
if(PrsResult->Rsp_result == 0){ // 成功时,读取鉴权码
if(PrsResult->term_param_item->big_auth_info.str_auth_code != NULL){
jt808_free(PrsResult->term_param_item->big_auth_info.str_auth_code);
PrsResult->term_param_item->big_auth_info.str_auth_code = NULL;
}
PrsResult->term_param_item->big_auth_info.str_auth_code = (char *)jt808_malloc(PrsResult->msg_head.msgbody_attr.msgbodylen - 3 +1); // 加1是为了加上结束符
if(PrsResult->term_param_item->big_auth_info.str_auth_code == NULL){
JT808_DEBUG("[%s,%s] malloc failed\r\n", __FUNCTION__,__LINE__);
return -1;
}
memset(PrsResult->term_param_item->big_auth_info.str_auth_code, 0, PrsResult->msg_head.msgbody_attr.msgbodylen - 3 +1);
memcpy(PrsResult->term_param_item->big_auth_info.str_auth_code, Prsmsg_body + 3 , PrsResult->msg_head.msgbody_attr.msgbodylen - 3);
}
break;
}
case ID_SetTermParams:{// 设置终端参数
PrsResult->term_param_item->big_specific_params.param_Total_num = ((uint8_t *)Prsmsg_body)[0]; // 总参数个数
uint16_t param_lenoffset = 1;
for(int i = 0; i < PrsResult->term_param_item->big_specific_params.param_Total_num; i++){
// 设置终端参数
jt808_setTermParam(Swap32(*(uint32_t *)(Prsmsg_body + param_lenoffset)), // 参数ID
(void *)(Prsmsg_body + param_lenoffset + 5), // 参数值
*((uint8_t*)(Prsmsg_body + param_lenoffset + 4))); // 参数长度
param_lenoffset += 5 + (*((uint8_t*)(Prsmsg_body + param_lenoffset + 4))); // 参数ID(4) + 参数长度(1) + 参数值(n)
}
jt808_pkg_send(ID_Term_GenResp, 0);// 发送终端通用应答
break;
}
case ID_GetTermParams:{// 查询终端参数
break;
}
case ID_GetSpecificTermParams:{// 查询指定终端参数
break;
}
case ID_Term_Ctrl:{// 终端控制
break;
}
case ID_GetTermAttr:{// 查询终端属性
break;
}
case ID_Term_Upgrade:{// 下发终端升级包
break;
}
case ID_GetLocInfo:{// 位置信息查询
break;
}
case ID_LocTrackingCtrl:{// 临时位置跟踪控制
break;
}
case ID_Car_Ctrl:{// 车辆控制
jt808_pkg_send(ID_Car_CtrlResp, 0);// 发送车辆控制应答,设置本消息无发送应答
break;
}
default:{
return -2; // 没有对应的消息体解析函数
break;
}
}
return 0;
}
// jt808协议包处理
int jt808_msg_parse(const uint8_t *BufferReceive, uint16_t length, PrsResult_t *PrsResult){
uint8_t *raw_Buffer = (uint8_t *)jt808_malloc(length * sizeof(uint8_t));
if(raw_Buffer == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
return -1;
}
memcpy(raw_Buffer, BufferReceive, length);
// // 打印原始数据
// app_printf("raw_Buffer: %d\r\n", length);
// for(int i = 0; i < length; i++){
// app_printf("%02x ", raw_Buffer[i]);
// }
// app_printf("\r\n");
// 计算需要逆转义字符的个数
uint16_t para_length = 0;
for(int i = 1; i < (length - 2); i++){
if(((raw_Buffer[i] == PESC)&&(raw_Buffer[i+1] == PESC_SIGN)) || // 7d 02 转义7e
((raw_Buffer[i] == PESC)&&(raw_Buffer[i+1] == PESC_ESCAPE))){ // 7d 01 转义7d
para_length++;
}
}
para_length =length - para_length;
uint8_t *para_Buffer = (uint8_t *)jt808_malloc(para_length * sizeof(uint8_t));
if(para_Buffer == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
jt808_free(raw_Buffer);
return -1;
}
para_Buffer[0] = PSIGN;
para_Buffer[para_length - 1] = PSIGN;
// 逆转义
uint16_t offset_num = 0;
for(int i = 1; i < (para_length - 1); i++){
if(((raw_Buffer[i + offset_num] == PESC)&&(raw_Buffer[i + offset_num + 1] == PESC_SIGN))){ // 7d 02 转义7e
para_Buffer[i] = PSIGN;
offset_num++;
}else if(((raw_Buffer[i + offset_num] == PESC)&&(raw_Buffer[i + offset_num + 1] == PESC_ESCAPE))){ // 7d 01 转义7d
para_Buffer[i] = PESC;
offset_num++;
}else{
para_Buffer[i] =raw_Buffer[i + offset_num];
}
}
// 释放内存
jt808_free(raw_Buffer);
if(offset_num != length - para_length){ // 转义后长度有误
JT808_DEBUG("error offset_num != length - para_length\r\n");
jt808_free(para_Buffer);
return -1;
}
// // 打印逆转义后数据
// app_printf("para_Buffer: %d\r\n", para_length);
// for(int i = 0; i < para_length; i++){
// app_printf("%02x ", para_Buffer[i]);
// }
// app_printf("\r\n");
// 异或校验
if(para_Buffer[para_length - 2] != BCC_Check(para_Buffer + 1, para_length - 2 - 1)){
JT808_DEBUG("BCC_CheckSum ERROR: %x %x\r\n",para_Buffer[para_length - 2] ,BCC_Check(para_Buffer + 1, para_length - 2 - 1));
jt808_free(para_Buffer);
return -1;
}
// 解析消息头
memcpy(&PrsResult->msg_head, para_Buffer + 1, sizeof(MsgHead_t) - ((para_Buffer[3] & 0x02)==0? 4 : 0));
PrsResult->msg_head.msg_id = Swap16(PrsResult->msg_head.msg_id);// 消息ID
PrsResult->msg_head.msgbody_attr.val16 = Swap16(PrsResult->msg_head.msgbody_attr.val16);// 消息体属性
PrsResult->msg_head.msg_flow_num = Swap16(PrsResult->msg_head.msg_flow_num);// 消息流水号
PrsResult->msg_head.total_packet = Swap16(PrsResult->msg_head.total_packet);// 总包数, 分包情况下使用
PrsResult->msg_head.packet_seq = Swap16(PrsResult->msg_head.packet_seq);// 当前包序号, 分包情况下使用
// 消息体解析
if(0 != jt808_BodyParse((void *)(para_Buffer + 1 + sizeof(MsgHead_t) - ((para_Buffer[3] & 0x02)==0? 4 : 0)) ,PrsResult)){
JT808_DEBUG("error jt808_BodyParse\r\n");
// 释放内存
jt808_free(para_Buffer);
return -1;
}
// 释放内存
jt808_free(para_Buffer);
return 0;
}

View File

@ -0,0 +1,253 @@
#include "jt808_msg_pkg.h"
#include "jt808_msg_parse.h"
// 协议消息体打包(会自动为p_msg_body分配合适长度的内存注意释放)
static int jt808_BodyPackage(JT808_2013_MsgFrame_t *p_MsgFrame, MessageID_t Msg_ID){
if(PrsResult.term_param_item == NULL){
JT808_DEBUG("[%s,%s] term_param_item is NULL \r\n", __FUNCTION__,__LINE__);
return -1;
}
p_MsgFrame->msg_head.msgbody_attr.encrypt = 0;// 数据加密方式
p_MsgFrame->msg_head.msgbody_attr.packet = 0;// 分包标记
p_MsgFrame->msg_head.msgbody_attr.retain = 0;// 保留2位
p_MsgFrame->msg_head.total_packet = 0;// 总包数, 分包情况下使用
p_MsgFrame->msg_head.packet_seq = 0;// 当前包序号, 分包情况下使用
// 填充消息体
switch(Msg_ID){
case ID_Term_GenResp:{ // 终端通用应答
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = sizeof(Term_GenResp_t);// 消息体长度
// 定义大端结构体
Term_GenResp_t *big_term_reg_resp = (Term_GenResp_t *)jt808_malloc(sizeof(Term_GenResp_t));
if(big_term_reg_resp == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
return -1;
}
memset(big_term_reg_resp, 0, sizeof(Term_GenResp_t));
// 大小端转换
big_term_reg_resp->msg_flow_num = Swap16(PrsResult.Rsp_flow_num); // 返回消息应答结果
big_term_reg_resp->msg_id_ack = Swap16(PrsResult.Rsp_msg_id);
big_term_reg_resp->result = PrsResult.Rsp_result;
p_MsgFrame->p_msg_body = (void *)big_term_reg_resp;
break;
}
case ID_Term_HB:{ // 终端心跳
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = 0;// 消息体长度
break;
}
case ID_Term_Reg:{ // 终端注册
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = sizeof(Term_RegInfo_t);// 消息体长度
// 定义大端结构体
Term_RegInfo_t *big_term_reg = (Term_RegInfo_t *)jt808_malloc(sizeof(Term_RegInfo_t));
if(big_term_reg == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
return -1;
}
// memset(big_term_reg, 0, sizeof(Term_RegInfo_t));
memcpy(big_term_reg, &PrsResult.term_param_item->big_reg_info, sizeof(Term_RegInfo_t)); // 复制注册信息内容
p_MsgFrame->p_msg_body = (void *)big_term_reg;
break;
}
case ID_Term_Logout:{ // 终端注销
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = 0;// 消息体长度
break;
}
case ID_Term_Auth:{ // 终端鉴权
// JT808_DEBUG("ID_Term_Auth\r\n");
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = strlen(PrsResult.term_param_item->big_auth_info.str_auth_code);// 消息体长度
if((NULL == PrsResult.term_param_item->big_auth_info.str_auth_code) || (1 >= p_MsgFrame->msg_head.msgbody_attr.msgbodylen)){
JT808_DEBUG("[%s,%s] auth_code len is 0 \r\n", __FUNCTION__,__LINE__);
return -1;
}
void *str_auth_code = jt808_malloc(p_MsgFrame->msg_head.msgbody_attr.msgbodylen);
if(str_auth_code == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
return -1;
}
// memset(str_auth_code, 0, p_MsgFrame->msg_head.msgbody_attr.msgbodylen);
JT808_DEBUG("auth_code:%d,%s\r\n",strlen(PrsResult.term_param_item->big_auth_info.str_auth_code),
PrsResult.term_param_item->big_auth_info.str_auth_code);
memcpy(str_auth_code, PrsResult.term_param_item->big_auth_info.str_auth_code, p_MsgFrame->msg_head.msgbody_attr.msgbodylen);
p_MsgFrame->p_msg_body = (void *)str_auth_code;
break;
}
case ID_GetTermParamsResp:{ // 查询终端参数应答
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = sizeof(GetTermParamsResp_t);// 消息体长度
GetTermParamsResp_t *get_term_params_resp = (GetTermParamsResp_t *)jt808_realloc(p_MsgFrame->p_msg_body, sizeof(GetTermParamsResp_t));
if(get_term_params_resp == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
return -1;
}
p_MsgFrame->p_msg_body = (void *)get_term_params_resp;
break;
}
case ID_GetTermAttrResp:{ // 查询终端属性应答
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = sizeof(GetTermAttrResp_t);// 消息体长度
GetTermAttrResp_t *get_term_attr_resp = (GetTermAttrResp_t *)jt808_realloc(p_MsgFrame->p_msg_body, sizeof(GetTermAttrResp_t));
if(get_term_attr_resp == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
return -1;
}
p_MsgFrame->p_msg_body = (void *)get_term_attr_resp;
break;
}
case ID_Term_UpgradeResult:{ // 终端升级结果通知
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = sizeof(Term_UpgradeResult_t);// 消息体长度
Term_UpgradeResult_t *term_upgrade_result = (Term_UpgradeResult_t *)jt808_realloc(p_MsgFrame->p_msg_body, sizeof(Term_UpgradeResult_t));
if(term_upgrade_result == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
return -1;
}
p_MsgFrame->p_msg_body = (void *)term_upgrade_result;
break;
}
case ID_LocReport:{ // 位置信息汇报
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = sizeof(Loc_basic_info_t);// 消息体长度
Loc_addi_info_t *p_loc_addi_info = PrsResult.term_param_item->big_loc_report.addi_info;
while(p_loc_addi_info != NULL){ // 计算附加信息长度
p_MsgFrame->msg_head.msgbody_attr.msgbodylen += p_loc_addi_info->msg_len + 2;
p_loc_addi_info = p_loc_addi_info->next;
}
uint8_t *loc_report_buf = (uint8_t *)jt808_malloc(p_MsgFrame->msg_head.msgbody_attr.msgbodylen);
if(loc_report_buf == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
return -1;
}
memcpy(loc_report_buf, &PrsResult.term_param_item->big_loc_report, sizeof(Loc_basic_info_t)); // 复制基本信息内容
p_loc_addi_info = PrsResult.term_param_item->big_loc_report.addi_info;
uint16_t loc_report_offset = sizeof(Loc_basic_info_t);
uint8_t loc_len = 0;
while(p_loc_addi_info != NULL){ // 填充附加信息内容
loc_len= p_loc_addi_info->msg_len + 2;
memcpy(loc_report_buf + loc_report_offset, &p_loc_addi_info->msg_id, 2);
memcpy(loc_report_buf + loc_report_offset + 2, p_loc_addi_info->msg, p_loc_addi_info->msg_len);
loc_report_offset += loc_len;
p_loc_addi_info = p_loc_addi_info->next;
}
p_MsgFrame->p_msg_body = (void *)loc_report_buf;
break;
}
case ID_GetLocInfoResp:{ // 查询位置信息应答
p_MsgFrame->msg_head.msgbody_attr.msgbodylen = sizeof(GetLocInfoResp_t);// 消息体长度
GetLocInfoResp_t *get_loc_info_resp = (GetLocInfoResp_t *)jt808_realloc(p_MsgFrame->p_msg_body, sizeof(GetLocInfoResp_t));
if(get_loc_info_resp == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
return -1;
}
p_MsgFrame->p_msg_body = (void *)get_loc_info_resp;
break;
}
default:
return -2;
break;
}
return 0;
}
// 消息帧打包 (会自动为msgEscape->buf分配合适长度的内存注意释放)
int jt808_msg_pkg(MessageID_t Msg_ID, JT808MsgESC_t *msgEscape){
JT808_2013_MsgFrame_t big_MsgFrame;// 定义大端消息帧
JT808_DEBUG("BodyPackage ID:0x%04X\r\n", Msg_ID);
big_MsgFrame.p_msg_body = NULL;
if(0 != jt808_BodyPackage(&big_MsgFrame, Msg_ID)){// 填充消息体 注意释放p_msg_body内存
JT808_DEBUG("jt808_BodyPackage failed\r\n");
return -1;
}
// 计算消息帧总长度
uint16_t msg_total_len = 1 + sizeof(MsgHead_t) - (1 ==big_MsgFrame.msg_head.msgbody_attr.packet ? 0 : 4);
uint16_t msgbody_len =big_MsgFrame.msg_head.msgbody_attr.msgbodylen;
msg_total_len += msgbody_len + 2;
JT808_DEBUG("total_len:%d,len:%d\r\n", msg_total_len, msgbody_len);
big_MsgFrame.Head_SIGN = PSIGN;
big_MsgFrame.Tail_SIGN = PSIGN;
// 大端转换
big_MsgFrame.msg_head.msg_id = Swap16(Msg_ID);// 消息ID
big_MsgFrame.msg_head.msgbody_attr.val16 = Swap16(big_MsgFrame.msg_head.msgbody_attr.val16);
memcpy(big_MsgFrame.msg_head.phone_BCDnum, PrsResult.term_param_item->phone_BCDnum, 6);
big_MsgFrame.msg_head.msg_flow_num = Swap16(PrsResult.term_param_item->msg_flow_num);// 消息流水号
big_MsgFrame.msg_head.total_packet = Swap16(big_MsgFrame.msg_head.total_packet);// 总包数, 分包情况下使用
big_MsgFrame.msg_head.packet_seq = Swap16(big_MsgFrame.msg_head.total_packet);// 当前包序号, 分包情况下使用
uint8_t *msg_buf = (uint8_t *)jt808_malloc(msg_total_len);
if(msg_buf == NULL){
JT808_DEBUG("[%s,%s] malloc failed \r\n", __FUNCTION__,__LINE__);
if(big_MsgFrame.p_msg_body != NULL){ // 释放消息体内存(必要操作)
jt808_free(big_MsgFrame.p_msg_body);
big_MsgFrame.p_msg_body = NULL;
}
return -1;
}
// 填充头标识和消息头
memcpy(msg_buf, &big_MsgFrame.Head_SIGN, msg_total_len - msgbody_len - 2);
// 填充消息体
if(0 < msgbody_len && big_MsgFrame.p_msg_body != NULL){
memcpy(msg_buf + (msg_total_len - msgbody_len - 2), big_MsgFrame.p_msg_body, msgbody_len);
}
// 计算BCC校验码
big_MsgFrame.BCC_Check = BCC_Check(msg_buf + 1, msg_total_len - 2 - 1);
memcpy(msg_buf + msg_total_len - 2, &big_MsgFrame.BCC_Check, 2);
//// DEBUG
// app_printf("JT808_2013_MsgFrame_t:\r\n");
// for (size_t i = 0; i < msg_total_len - msgbody_len - 2; i++){
// app_printf("%02X ", *((uint8_t *)(&big_MsgFrame) + i));
// }
// app_printf("\r\n");
// for (size_t i = 0; i < msgbody_len; i++){
// app_printf("%02X ", *((uint8_t *)big_MsgFrame.p_msg_body + i));
// }
// app_printf("\r\n");
// for (size_t i = 0; i < 2; i++){
// app_printf("%02X ", *((uint8_t *)(&big_MsgFrame.BCC_Check) + i));
// }
// app_printf("\r\n");
if(big_MsgFrame.p_msg_body != NULL){ // 释放消息体内存(必要操作)
jt808_free(big_MsgFrame.p_msg_body);
big_MsgFrame.p_msg_body = NULL;
}
// 7E 转义处理
uint16_t escape_len = 0;
for(uint16_t i = 1; i < msg_total_len - 1; i++){
if(msg_buf[i] == PSIGN || msg_buf[i] == PESC){
escape_len++;
}
}
msgEscape->buf = (uint8_t *)jt808_malloc(msg_total_len + escape_len);
uint16_t offset_num = 0;
msgEscape->buf[0] = PSIGN;
msgEscape->buf[msg_total_len + escape_len - 1] = PSIGN;
for(uint16_t i = 1; i < msg_total_len - 1; i++){
if(msg_buf[i] == PSIGN){
msgEscape->buf[i + offset_num++] = PESC;
msgEscape->buf[i + offset_num] = PESC_SIGN;
}else if(msg_buf[i] == PESC){
msgEscape->buf[i + offset_num++] = PESC;
msgEscape->buf[i + offset_num] = PESC_ESCAPE;
}else {
msgEscape->buf[i + offset_num] = msg_buf[i];
}
}
jt808_free(msg_buf);
// 返回消息帧总长度
msgEscape->len = msg_total_len + escape_len;
app_printf("msgEscape->buf:%d\r\n", msg_total_len + escape_len);
for(uint16_t i = 0; i < msg_total_len + escape_len; i++){
app_printf("%02X ", *(msgEscape->buf + i));
}
app_printf("\r\n");
// jt808_free(msgEscape->buf);
return 0;
}

View File

@ -2,7 +2,7 @@
#include "util.h" #include "util.h"
#include "terminal_parameter.h" #include "terminal_parameter.h"
#include "client_manager.h" #include "client_manager.h"
#include "jt808_debug.h" #include "jt808_config.h"
// 所有终端数据打包命令. // 所有终端数据打包命令.
unsigned short kTerminalPackagerCMD[PACKAGER_NUM] = { unsigned short kTerminalPackagerCMD[PACKAGER_NUM] = {
@ -391,7 +391,12 @@ int jt808MsgEscape()
BufferSend[RealBufferSendSize - 1] = 0x00; BufferSend[RealBufferSendSize - 1] = 0x00;
outBufferSize = RealBufferSendSize * 2; outBufferSize = RealBufferSendSize * 2;
outBuffer = (unsigned char *)malloc(outBufferSize); outBuffer = (unsigned char *)jt808_malloc(outBufferSize);
if(outBuffer == NULL)
{
JT808_DEBUG("[%s] malloc failed \r\n", __FUNCTION__);
return -1;
}
if (Escape_C(BufferSend, RealBufferSendSize, outBuffer, &outBufferSize) < 0) if (Escape_C(BufferSend, RealBufferSendSize, outBuffer, &outBufferSize) < 0)
{ {
@ -407,7 +412,7 @@ int jt808MsgEscape()
if (outBuffer != NULL) if (outBuffer != NULL)
{ {
free(outBuffer); jt808_free(outBuffer);
outBuffer = NULL; outBuffer = NULL;
} }
#ifdef __JT808_DEBUG #ifdef __JT808_DEBUG
@ -507,8 +512,7 @@ int jt808FramePackage(struct ProtocolParameter *para)
JT808_DEBUG("[Write buffersend end PROTOCOL_SIGN] OK !\r\n"); JT808_DEBUG("[Write buffersend end PROTOCOL_SIGN] OK !\r\n");
#endif #endif
// 6、处理转义. // 6、处理转义.
if (jt808MsgEscape() < 0) if (jt808MsgEscape() < 0){
{
JT808_DEBUG("[jt808MsgEscape] FAILED"); JT808_DEBUG("[jt808MsgEscape] FAILED");
return -1; return -1;
} }

View File

@ -3,7 +3,7 @@
#include "client_manager.h" #include "client_manager.h"
#include "util.h" #include "util.h"
#include "bcd.h" #include "bcd.h"
#include "jt808_debug.h" #include "jt808_config.h"
// 所有终端解析命令. // 所有终端解析命令.
unsigned short kTerminalParserCMD[PARSER_NUM] = { unsigned short kTerminalParserCMD[PARSER_NUM] = {
@ -172,7 +172,7 @@ int handle_kTerminalRegisterResponse(struct ProtocolParameter *para)
if (para->parse.respone_result == kRegisterSuccess) if (para->parse.respone_result == kRegisterSuccess)
{ {
len_code = para->parse.msg_head.msgbody_attr.bit.msglen - 3; len_code = para->parse.msg_head.msgbody_attr.bit.msglen - 3;
para->parse.authentication_code = (unsigned char *)malloc((len_code + 1) * sizeof(unsigned char)); para->parse.authentication_code = (unsigned char *)jt808_malloc((len_code + 1) * sizeof(unsigned char));
memcpy(para->parse.authentication_code, &(BufferReceive[pos + 3]), len_code); memcpy(para->parse.authentication_code, &(BufferReceive[pos + 3]), len_code);
JT808_DEBUG("[%s] authentication_code = %s\r\n", __FUNCTION__, para->parse.authentication_code); JT808_DEBUG("[%s] authentication_code = %s\r\n", __FUNCTION__, para->parse.authentication_code);
@ -281,9 +281,9 @@ int handle_kTerminalUpgrade(struct ProtocolParameter *para)
pos = MSGBODY_PACKET_POS; pos = MSGBODY_PACKET_POS;
} }
para->upgrade_info.upgrade_type = BufferReceive[pos++]; para->big_upgrade_info.upgrade_type = BufferReceive[pos++];
memset(para->upgrade_info.manufacturer_id, 0, sizeof(para->upgrade_info.manufacturer_id)); memset(para->big_upgrade_info.manufacturer_id, 0, sizeof(para->big_upgrade_info.manufacturer_id));
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
{ {
} }
@ -398,7 +398,15 @@ int jt808FrameParse(const unsigned char *in, unsigned int in_len, struct Protoco
memcpy(BufferReceive, in, in_len); memcpy(BufferReceive, in, in_len);
RealBufferReceiveSize = in_len; RealBufferReceiveSize = in_len;
outBufferSize = RealBufferReceiveSize; outBufferSize = RealBufferReceiveSize;
outBuffer = (unsigned char *)malloc(outBufferSize * sizeof(unsigned char)); if(outBufferSize < 1){
JT808_DEBUG("outBufferSize < 1\r\n");
return -1;
}
outBuffer = (unsigned char *)jt808_malloc(outBufferSize * sizeof(unsigned char));
if(outBuffer == NULL){
JT808_DEBUG("[%s] malloc failed \r\n", __FUNCTION__);
return -1;
}
memset(outBuffer, 0, outBufferSize); memset(outBuffer, 0, outBufferSize);
#ifdef __JT808_DEBUG #ifdef __JT808_DEBUG
@ -445,7 +453,7 @@ int jt808FrameParse(const unsigned char *in, unsigned int in_len, struct Protoco
// 释放缓存 // 释放缓存
if (outBuffer != NULL) if (outBuffer != NULL)
{ {
free(outBuffer); jt808_free(outBuffer);
outBuffer = NULL; outBuffer = NULL;
} }

View File

@ -0,0 +1,106 @@
#include "jt808_pkg_transmit.h"
static osThreadId_t jt808_pkg_send_ThreadId;
static osMessageQueueId_t jt808_send_msg_queue = NULL;
static osSemaphoreId_t jt808_send_ack_sem = NULL; // 发送成功应答信号量
static osSemaphoreId_t jt808_parse_ok_sem = NULL; // 解析完成信号量
// 触发消息发送
int jt808_pkg_send(MessageID_t Msg_ID, uint32_t timeout){
pkg_msg_t send_pkg_msg={0};
send_pkg_msg.msg_id = Msg_ID;
send_pkg_msg.timeout = timeout;
JT808_DEBUG("send pkg_msg:%04x\n", Msg_ID);
if(osOK == osMessageQueuePut(jt808_send_msg_queue, &send_pkg_msg, 0, 0)){ //
if(0 < timeout){ // 阻塞等待发送回应
osStatus_t ret =osSemaphoreAcquire(jt808_send_ack_sem, timeout);
if(ret == osOK){
return PrsResult.Rsp_result; // 发送成功应答
JT808_DEBUG("send ack success\n");
}else if(ret == osErrorTimeout){
JT808_DEBUG("send ack timeout\n");
return -1;// 发送失败
}
}
}else{
JT808_DEBUG("osMessageQueuePut fail\n");
return -1;// 发送失败
}
return 0;
}
// 接收处理 (放入TCP接收回调中)
void jt808_pkg_handle(uint8_t *receive_buf, uint16_t receive_len){
if(0 ==jt808_msg_parse(receive_buf, receive_len, &PrsResult)){ // 解析协议数据
osSemaphoreRelease(jt808_parse_ok_sem); // 释放解析完成信号量
JT808_DEBUG("jt808_msg_parse success\n");
}
}
// 发送任务
static void jt808_pkg_send_task(void *arg){
pkg_msg_t send_pkg_msg={0};
JT808MsgESC_t MsgESC={
.buf = NULL,
.len = 0,
};
while(1){
if(osOK == osMessageQueueGet(jt808_send_msg_queue, &send_pkg_msg, NULL, osWaitForever)){
if(0 == jt808_msg_pkg(send_pkg_msg.msg_id ,&MsgESC)){ // 生成协议数据成功
// 发送数据
if(NULL == MsgESC.buf){ // 协议数据为空(发生错误)
JT808_DEBUG("MsgESC.buf is NULL:len=%d\n",MsgESC.len);
continue;
}
JT808_DEBUG("tcp send %d bytes\n", MsgESC.len);
if(0 == PKG_SEND(MsgESC.buf, MsgESC.len)){ // 发送成功处理
if(NULL != jt808_parse_ok_sem){
osStatus_t ret =osSemaphoreAcquire(jt808_parse_ok_sem, send_pkg_msg.timeout);// 等待接收数据并解析完成
if(ret == osOK || 0 == send_pkg_msg.timeout){
osSemaphoreRelease(jt808_send_ack_sem); // 释放发送成功应答信号量
JT808_DEBUG("parse success\n");
if(PrsResult.term_param_item!= NULL){ // 协议参数项不为空
PrsResult.term_param_item->msg_flow_num++; // 协议流水号+1
}else{
JT808_DEBUG("PrsResult.term_param_item is NULL\n");
}
}else if(ret == osErrorTimeout){
JT808_DEBUG("parse timeout\n");
}
}else{
JT808_DEBUG("jt808_parse_ok_sem is NULL\n");
}
}
}
if(MsgESC.buf!= NULL){ // 释放发送缓存
JT808_DEBUG("jt808_free MsgESC.buf\n");
jt808_free(MsgESC.buf);
MsgESC.buf = NULL;
}
}
}
}
// jt808协议初始化
int jt808_init(void){
if(jt808_send_msg_queue == NULL){
jt808_send_msg_queue = osMessageQueueNew(1, sizeof(pkg_msg_t), NULL);
}
if(jt808_send_ack_sem == NULL){
jt808_send_ack_sem = osSemaphoreNew(1, 0, NULL);
}
if(jt808_parse_ok_sem == NULL){
jt808_parse_ok_sem = osSemaphoreNew(1, 0, NULL);
}
osThreadAttr_t jt808_pkg_send_task_attr = {
.name = "jt808_pkg_send_task",
.stack_size = 1024,
.priority = osPriorityNormal,
};
jt808_pkg_send_ThreadId = osThreadNew((osThreadFunc_t)jt808_pkg_send_task, 0, &jt808_pkg_send_task_attr);
osDelay(200); // 等待线程启动
return 0;
}

View File

@ -0,0 +1,294 @@
#include "jt808_set_TermParam.h"
#include "gps_config.h"
#include "jt808_msg_pkg.h"
#include "jt808_msg_parse.h"
#include "jt808_pkg_transmit.h"
#include "cm_sys.h"
#include "cm_sim.h"
Term_Param_item_t jt808_term_param_item; // 终端参数项
// 控制车辆状态
void jt808_Set_CarStatus(uint8_t status){
// (void)status;
// TODO: 车辆控制状态
}
// 获取车辆状态
uint8_t jt808_Get_CarStatus(void){
// TODO: 车辆控制状态
return 0;
}
// 设置终端参数
int jt808_setTermParam(set_TermParamID_t param_id, void *param, uint8_t param_len){
switch(param_id){
case HeartBeatInterval:{
jt808_term_param_item.set_term_param.HeartBeatInterval =Swap32(*(uint32_t*)param);
break;
}
case MainServerAddr:{
memcpy(jt808_term_param_item.set_term_param.MainServerAddr,param,50<param_len?param_len:50);
break;
}
case ServerPort:{
jt808_term_param_item.set_term_param.ServerPort =Swap32(*(uint32_t*)param);
break;
}
case DefaultTimeReportInterval:{
jt808_term_param_item.set_term_param.DefaultTimeReportInterval =Swap32(*(uint32_t*)param);
break;
}
case InflexionAngle:{
jt808_term_param_item.set_term_param.InflexionAngle =Swap32(*(uint32_t*)param);
break;
}
case MaxSpeed:{
jt808_term_param_item.set_term_param.MaxSpeed =Swap32(*(uint32_t*)param);
break;
}
case ProvinceID:{
jt808_term_param_item.set_term_param.ProvinceID =Swap16(*(uint16_t*)param);
break;
}
case CityID:{
jt808_term_param_item.set_term_param.CityID =Swap16(*(uint16_t*)param);
break;
}
case CarPlateNum:{
memcpy(jt808_term_param_item.set_term_param.CarPlateNum,param,10<param_len?param_len:10);
break;
}
case CarPlateColor:{
jt808_term_param_item.set_term_param.CarPlateColor =((uint8_t*)param)[0];
break;
}
default:{
// TODO: 未知参数
return -1;
break;
}
}
return 0;
}
// 更新位置基本信息
int jt808_updateLocBasicInfo(Loc_basic_info_t *loc_basic_info){
// (void *)loc_basic_info;
return 0;
}
osThreadFunc_t Autoreport_param_ThreadId;
void Autoreport_param_Task(void *arg){
uint32_t count_Sec = 0;// 计数器
nmeaTIME beiJingTime; // 北京时间
while(1){
// TODO: 自动上报参数
// 1. 位置基本信息
GMTconvert(&gps_data.info.utc, &beiJingTime, 8, 1);
// info.lat lon中的格式为[degree][min].[sec/60],使用以下函数转换成[degree].[degree]格式
jt808_term_param_item.big_loc_report.basic_info.latitude = Swap32(nmea_ndeg2degree(gps_data.info.lat) * 1e6);
jt808_term_param_item.big_loc_report.basic_info.longitude = Swap32(nmea_ndeg2degree(gps_data.info.lon) * 1e6);
jt808_term_param_item.big_loc_report.basic_info.altitude = Swap16(gps_data.info.elv);
jt808_term_param_item.big_loc_report.basic_info.speed = Swap16(gps_data.info.speed * 10);
jt808_term_param_item.big_loc_report.basic_info.direction = Swap16(gps_data.info.direction);
jt808_term_param_item.big_loc_report.basic_info.BCDtime[0] =((((beiJingTime.year+1900)%2000%100/10)&0x0F)<<4) | (((beiJingTime.year+1900)%2000%10)&0x0F);
jt808_term_param_item.big_loc_report.basic_info.BCDtime[1] = (((beiJingTime.mon%100/10)&0x0F)<<4) | ((beiJingTime.mon%10)&0x0F);
jt808_term_param_item.big_loc_report.basic_info.BCDtime[2] = (((beiJingTime.day%100/10)&0x0F)<<4) | ((beiJingTime.day%10)&0x0F);
jt808_term_param_item.big_loc_report.basic_info.BCDtime[3] = (((beiJingTime.hour%100/10)&0x0F)<<4) | ((beiJingTime.hour%10)&0x0F);
jt808_term_param_item.big_loc_report.basic_info.BCDtime[4] = (((beiJingTime.min%100/10)&0x0F)<<4) | ((beiJingTime.min%10)&0x0F);
jt808_term_param_item.big_loc_report.basic_info.BCDtime[5] = (((beiJingTime.sec%100/10)&0x0F)<<4) | ((beiJingTime.sec%10)&0x0F);
jt808_term_param_item.big_loc_report.basic_info.status.val32 = 0; // 清除状态信息
jt808_term_param_item.big_loc_report.basic_info.status.acc =0; // 0:未开启1:已开启
jt808_term_param_item.big_loc_report.basic_info.status.positioning = (0 == gps_data.info.sig) ? 0 : 1; // 0:未定位1:已定位
jt808_term_param_item.big_loc_report.basic_info.status.door_lock = 0; // 0:未锁车1:已锁车
jt808_term_param_item.big_loc_report.basic_info.status.operation = 0; // 0:运营状态; 1:停运状态
jt808_term_param_item.big_loc_report.basic_info.status.circuit_cut = 0; // 0:车辆电路正常; 1:车辆电路断开
jt808_term_param_item.big_loc_report.basic_info.status.val32 = Swap32(jt808_term_param_item.big_loc_report.basic_info.status.val32); // 状态信息(转大端)
jt808_term_param_item.big_loc_report.basic_info.alarm_flag.val32 = 0; // 清除报警标志
jt808_term_param_item.big_loc_report.basic_info.alarm_flag.overspeed = 0; // bit_1 超速报警
jt808_term_param_item.big_loc_report.basic_info.alarm_flag.power_low = 0; // bit_7 终端主电源欠压
jt808_term_param_item.big_loc_report.basic_info.alarm_flag.road_deviate = 0; // bit_23 路线偏离报警
jt808_term_param_item.big_loc_report.basic_info.alarm_flag.car_move = 0; // bit_28 车辆非法位移.收到应答后清零
jt808_term_param_item.big_loc_report.basic_info.alarm_flag.val32 = Swap32(jt808_term_param_item.big_loc_report.basic_info.alarm_flag.val32); // 报警标志(转大端)
// jt808_term_param_item.big_loc_report.basic_info.alarm_flag.gnss_fault = 0 == gps_data.info.sig ? 1 : 0; // 0:无故障1:有故障
if(0 == (count_Sec % jt808_term_param_item.set_term_param.HeartBeatInterval)){
if(0 == jt808_term_param_item.big_loc_report.basic_info.status.positioning){ // 未定位时发送心跳包
jt808_pkg_send(ID_Term_HB,0); // 发送心跳包 // 不接收应答
}else{
jt808_pkg_send(ID_LocReport,10000/5); // 发送位置信息上报包
}
}
count_Sec++;
osDelay(1000/5); // 1S
}
}
// 启动自动上报参数
void jt808_Autoreport_param_start(void){
if(Autoreport_param_ThreadId == NULL){
osThreadAttr_t Autoreport_param_task_attr = {
.name = "Autoreport_param_Task",
.stack_size = 1024,
.priority = osPriorityNormal,
};
Autoreport_param_ThreadId = osThreadNew((osThreadFunc_t)Autoreport_param_Task, 0, &Autoreport_param_task_attr);
}else{
osThreadResume(Autoreport_param_ThreadId); //恢复线程
}
}
// 停止自动上报参数
void jt808_Autoreport_param_stop(void){
if(Autoreport_param_ThreadId != NULL){
osThreadSuspend(Autoreport_param_ThreadId); //挂起线程
}
}
// 初始化终端参数
void jt808_set_term_param_init(void){
memset(&jt808_term_param_item,0,sizeof(Term_Param_item_t));
do{ // 设置终端手机号
char cm_iccid[32] = {0};
char get_iccid_ok = 0;
int error_count = 0;
while(error_count <= 20) {
memset(cm_iccid, 0, sizeof(cm_iccid));
get_iccid_ok = 0;
cm_sim_get_iccid(cm_iccid);
// 统计有效字符
for(int i = strlen(cm_iccid) - 1; i >= 8; i--) {
if(cm_iccid[i] >= '0' && cm_iccid[i] <= '9') {
get_iccid_ok++;
}else{
break;
}
}
JT808_DEBUG("get_iccid_ok:%d\n",get_iccid_ok);
if(get_iccid_ok == 12){ // IC CID 获取成功
JT808_DEBUG("iccid:%d,:%s\n",strlen(cm_iccid), cm_iccid);
rawStrToBcd(jt808_term_param_item.phone_BCDnum, cm_iccid+8, 12); // 终端手机号码
break;
}else{
error_count++;
JT808_DEBUG("get iccid failed count:%d\n",error_count);
}
osDelay(1000 / 5); // 根据需求设置延时
}
jt808_term_param_item.msg_flow_num =0;
JT808_DEBUG("phone_BCDnum:");
for(int i=0;i<6;i++){
app_printf("%02X ",jt808_term_param_item.phone_BCDnum[i]);
}
app_printf("\n");
}while(0);
do{// 注册信息初始化
char read_buf[35] = {0};
jt808_term_param_item.big_reg_info.province_id = Swap16(0); // 省域ID
jt808_term_param_item.big_reg_info.city_id = Swap16(0); // 市域ID
memcpy(jt808_term_param_item.big_reg_info.manufacturer_id, "LAT01", 5); // 制造商ID
while(0 != cm_sys_get_sn(read_buf)){
JT808_DEBUG("get sn failed\n");
osDelay(1000/5);
}
JT808_DEBUG("SN:%s\n", read_buf);
memcpy(jt808_term_param_item.big_reg_info.term_model, read_buf, 20); // 终端型号
while(0 != cm_sys_get_imei(read_buf)){
JT808_DEBUG("get imei failed\n");
osDelay(1000/5);
}
JT808_DEBUG("IMEI:%s\n", read_buf);
memcpy(jt808_term_param_item.big_reg_info.term_id, read_buf, 7); // 终端ID
jt808_term_param_item.big_reg_info.car_plate_color = blue_plate; // 车牌颜色
char CarPlateNum[] ="京A12345"; // 车牌号码
memcpy(jt808_term_param_item.big_reg_info.car_plate_num, CarPlateNum, strlen(CarPlateNum)); // 车牌号码
}while(0);
do{// 授权信息初始化
char str_auth[]="auth code error..."; // 授权码
jt808_term_param_item.big_auth_info.str_auth_code = jt808_malloc(strlen(str_auth)+1); // 授权码
if(jt808_term_param_item.big_auth_info.str_auth_code == NULL){
JT808_DEBUG("malloc auth_code failed\r\n");
}
memcpy(jt808_term_param_item.big_auth_info.str_auth_code, str_auth, strlen(str_auth)+1); // 授权码
JT808_DEBUG("auth_code:%d,%s\r\n",strlen(jt808_term_param_item.big_auth_info.str_auth_code), jt808_term_param_item.big_auth_info.str_auth_code);
// jt808_free(jt808_term_param_item.big_auth_info.str_auth_code);
// jt808_term_param_item.big_auth_info.str_auth_code = NULL;
}while(0);
do{// 终端参数初始化
jt808_term_param_item.set_term_param.HeartBeatInterval = 5; // 心跳包间隔(秒)
char ServerAddr[] ="47.99.118.34"; // 车牌号码
uint32_t ServerPort = 5000; // 服务器端口
// char ServerAddr[] ="36.137.226.30"; // 车牌号码
// uint32_t ServerPort = 36204; // 服务器端口
// memset(jt808_term_param_item.set_term_param.MainServerAddr, 0, 50);
memcpy(jt808_term_param_item.set_term_param.MainServerAddr, ServerAddr, strlen(ServerAddr)+1); // 主服务器地址
jt808_term_param_item.set_term_param.ServerPort = ServerPort; // 服务器端口
jt808_term_param_item.set_term_param.DefaultTimeReportInterval = 60; // 默认时间上报间隔(秒)
jt808_term_param_item.set_term_param.InflexionAngle = 0; // 俯仰角(度)
jt808_term_param_item.set_term_param.MaxSpeed = 0; // 最大速度(km/h)
jt808_term_param_item.set_term_param.ProvinceID = 0; // 省域ID
jt808_term_param_item.set_term_param.CityID = 0; // 市域ID
jt808_term_param_item.set_term_param.CarPlateNum[0] = 0; // 车牌号码
jt808_term_param_item.set_term_param.CarPlateColor = 0; // 车牌颜色
}while(0);
do{// 位置信息上报初始化
memset(&jt808_term_param_item.big_loc_report.basic_info,0,sizeof(Loc_basic_info_t));
jt808_term_param_item.big_loc_report.basic_info.status.val32 = 0; // 状态信息
jt808_term_param_item.big_loc_report.basic_info.alarm_flag.val32 = 0; // 报警标志
}while(0);
PrsResult.term_param_item =&jt808_term_param_item;// 全局变量指针指向终端参数项
// JT808_DEBUG("auth_code:%s\r\n",PrsResult.term_param_item->big_auth_info.str_auth_code);
}
// 释放终端参数
void jt808_set_term_param_free(void){
if(jt808_term_param_item.big_auth_info.str_auth_code != NULL){ // 释放授权码
jt808_free(jt808_term_param_item.big_auth_info.str_auth_code);
jt808_term_param_item.big_auth_info.str_auth_code = NULL;
}
if(jt808_term_param_item.big_specific_params.param_id_list != NULL){ // 释放特定参数列表
jt808_free(jt808_term_param_item.big_specific_params.param_id_list);
jt808_term_param_item.big_specific_params.param_id_list = NULL;
}
if(jt808_term_param_item.big_ctrl_info.str_cmd_params != NULL){ // 释放控制命令参数
jt808_free(jt808_term_param_item.big_ctrl_info.str_cmd_params);
jt808_term_param_item.big_ctrl_info.str_cmd_params = NULL;
}
if(jt808_term_param_item.big_upgrade_info.str_upgrade_pkg != NULL){ // 释放残留升级包内存
jt808_free(jt808_term_param_item.big_upgrade_info.str_upgrade_pkg);
jt808_term_param_item.big_upgrade_info.str_upgrade_pkg = NULL;
}
if(jt808_term_param_item.big_upgrade_info.str_ver != NULL){ // 释放升级版本号
jt808_free(jt808_term_param_item.big_upgrade_info.str_ver);
jt808_term_param_item.big_upgrade_info.str_ver = NULL;
}
Loc_addi_info_t *p_addi_info; // 附加信息
Loc_addi_info_t *p_addi_info_next; // 附加信息下一个节点
p_addi_info = jt808_term_param_item.big_loc_report.addi_info;
p_addi_info_next = p_addi_info->next;
while(p_addi_info != NULL){ // 释放附加信息列表
jt808_free(p_addi_info);
p_addi_info = p_addi_info_next;
if(p_addi_info != NULL){
p_addi_info_next = p_addi_info->next;
}
}
PrsResult.term_param_item = NULL;
}

View File

@ -0,0 +1,93 @@
#include "jt808_util.h"
#include "jt808_config.h"
// 双字节大小端转换
uint16_t Swap16(uint16_t val16){
return (((val16 & 0x00FF) << 8) |
((val16 & 0xFF00) >> 8));
}
// 四字节大小端转换
uint32_t Swap32(uint32_t val32){
return (((val32 & 0x000000FF) << 24) |
((val32 & 0x0000FF00) << 8) |
((val32 & 0x00FF0000) >> 8) |
((val32 & 0xFF000000) >> 24));
}
// 异或校验
uint8_t BCC_Check(const uint8_t *src, uint32_t len)
{
uint8_t bcc_check = 0;
for(uint32_t i = 0; i < len; ++i){
bcc_check ^= src[i];
}
return bcc_check;
}
// 十进制转BCD码
uint8_t DecToBcd(uint8_t Dec){
uint8_t temp;
temp = ((Dec / 10) << 4) + (Dec % 10);
return temp;
}
// BCD码转十进制
uint8_t BcdToDec(uint8_t Bcd){
uint8_t temp;
temp = (Bcd >> 4) * 10 + (Bcd & 0x0f);
return temp;
}
// 原始字符串转BCD码 //奇数位时首位BCD码前面补0
uint8_t *rawStrToBcd(uint8_t *bcd, const uint8_t *str, uint16_t str_len){
uint8_t *ptr = bcd;
uint8_t temp;
if (str_len % 2 != 0){
*ptr++ = DecToBcd(*str++ - '0');
}
while (*str){
temp = *str++ - '0';
temp *= 10;
temp += *str++ - '0';
*ptr++ = DecToBcd(temp);
}
return bcd;
}
// BCD转字符串自动去掉bcd码前导零
// bcdlen 为bcd码字节数
uint8_t *BcdToStr(uint8_t *str, const uint8_t *bcd, int bcd_len){
uint8_t *ptr = str;
uint8_t temp;
int cnt = bcd_len;
while (cnt--){
temp = BcdToDec(*bcd);
*ptr++ = temp / 10 + '0';
if(str[0] == '0'){
ptr = str;
}
*ptr++ = temp % 10 + '0';
if(str[0] == '0'){
ptr = str;
}
++bcd;
}
return str;
}
// 原始BCD数据转字符串
// strlen 为原始BCD数据字节数
uint8_t *rawBcdToStr(uint8_t *str, const uint8_t *bcd, int bcd_len){
uint8_t *ptr = str;
uint8_t temp;
int cnt = bcd_len;
while (cnt--)
{
temp = BcdToDec(*bcd);
*ptr++ = temp / 10 + '0';
*ptr++ = temp % 10 + '0';
++bcd;
}
return str;
}

View File

@ -1,74 +0,0 @@
#include "location_report.h"
#include <string.h>
#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<uint32_t>(latitude * 1e6);
// para->location_info.longitude = static_cast<uint32_t>(longitude * 1e6);
// para->location_info.altitude = static_cast<uint16_t>(altitude);
// para->location_info.speed = static_cast<uint16_t>(speed * 10);
// para->location_info.bearing = static_cast<uint16_t>(bearing);
// para->location_info.time.assign(timestamp.begin(), timestamp.end());
// // spdlog::info("[{}] [{}] 更新上报位置信息 ", libjt808::getCurrentFileName(__FILE__), __LINE__);
// }

View File

@ -1,7 +1,7 @@
#include "set_terminal_parameter.h" #include "set_terminal_parameter.h"
#include "terminal_parameter.h" #include "terminal_parameter.h"
#include "client_manager.h" #include "client_manager.h"
#include "jt808_debug.h" #include "jt808_config.h"
unsigned short kParameterSettingCMD[PARA_SETTING_LIMIT] = { unsigned short kParameterSettingCMD[PARA_SETTING_LIMIT] = {
kTerminalHeartBeatInterval, // DWORD, 终端心跳发送间隔(s). kTerminalHeartBeatInterval, // DWORD, 终端心跳发送间隔(s).
@ -93,7 +93,7 @@ void handle_HeartBeatInterval(unsigned char *buf, unsigned char buf_len, struct
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * buf_len);
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
memcpy(u32converter.u8array, p, buf_len); memcpy(u32converter.u8array, p, buf_len);
@ -103,7 +103,7 @@ void handle_HeartBeatInterval(unsigned char *buf, unsigned char buf_len, struct
JT808_DEBUG("handle_HeartBeatInterval ==== %d \r\n", para->parse.terminal_parameters.HeartBeatInterval); JT808_DEBUG("handle_HeartBeatInterval ==== %d \r\n", para->parse.terminal_parameters.HeartBeatInterval);
// FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
free(p); jt808_free(p);
return; return;
} }
@ -114,7 +114,7 @@ void handle_MainServerAddress(unsigned char *buf, unsigned char buf_len, struct
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * (buf_len + 1)); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * (buf_len + 1));
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
// 字符串注意GBK转码 // 字符串注意GBK转码
@ -122,7 +122,7 @@ void handle_MainServerAddress(unsigned char *buf, unsigned char buf_len, struct
memcpy(para->parse.terminal_parameters.MainServerAddress, p, buf_len); memcpy(para->parse.terminal_parameters.MainServerAddress, p, buf_len);
// FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
JT808_DEBUG("handle_MainServerAddress ==== %s \r\n", para->parse.terminal_parameters.MainServerAddress); JT808_DEBUG("handle_MainServerAddress ==== %s \r\n", para->parse.terminal_parameters.MainServerAddress);
free(p); jt808_free(p);
return; return;
} }
@ -136,7 +136,7 @@ void handle_ServerPort(unsigned char *buf, unsigned char buf_len, struct Protoco
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * buf_len);
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
memcpy(u32converter.u8array, p, buf_len); memcpy(u32converter.u8array, p, buf_len);
@ -145,7 +145,7 @@ void handle_ServerPort(unsigned char *buf, unsigned char buf_len, struct Protoco
para->parse.terminal_parameters.ServerPort = serverPort; para->parse.terminal_parameters.ServerPort = serverPort;
// FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
JT808_DEBUG("handle_ServerPort ==== %d \r\n", para->parse.terminal_parameters.ServerPort); JT808_DEBUG("handle_ServerPort ==== %d \r\n", para->parse.terminal_parameters.ServerPort);
free(p); jt808_free(p);
return; return;
} }
@ -158,7 +158,7 @@ void handle_DefaultTimeReportTimeInterval(unsigned char *buf, unsigned char buf_
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * buf_len);
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
memcpy(u32converter.u8array, p, buf_len); memcpy(u32converter.u8array, p, buf_len);
@ -174,7 +174,7 @@ void handle_DefaultTimeReportTimeInterval(unsigned char *buf, unsigned char buf_
para->parse.terminal_parameters.DefaultTimeReportTimeInterval = DefaultTimeReportTimeInterval; para->parse.terminal_parameters.DefaultTimeReportTimeInterval = DefaultTimeReportTimeInterval;
// FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
JT808_DEBUG("handle_DefaultTimeReportTimeInterval ==== %d \r\n", para->parse.terminal_parameters.DefaultTimeReportTimeInterval); JT808_DEBUG("handle_DefaultTimeReportTimeInterval ==== %d \r\n", para->parse.terminal_parameters.DefaultTimeReportTimeInterval);
free(p); jt808_free(p);
return; return;
} }
@ -187,7 +187,7 @@ void handle_CornerPointRetransmissionAngle(unsigned char *buf, unsigned char buf
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * buf_len);
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
memcpy(u32converter.u8array, p, buf_len); memcpy(u32converter.u8array, p, buf_len);
@ -196,7 +196,7 @@ void handle_CornerPointRetransmissionAngle(unsigned char *buf, unsigned char buf
para->parse.terminal_parameters.CornerPointRetransmissionAngle = CornerPointRetransmissionAngle; para->parse.terminal_parameters.CornerPointRetransmissionAngle = CornerPointRetransmissionAngle;
// FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
JT808_DEBUG("handle_DefaultTimeReportTimeInterval ==== %d \r\n", para->parse.terminal_parameters.DefaultTimeReportTimeInterval); JT808_DEBUG("handle_DefaultTimeReportTimeInterval ==== %d \r\n", para->parse.terminal_parameters.DefaultTimeReportTimeInterval);
free(p); jt808_free(p);
return; return;
} }
@ -209,7 +209,7 @@ void handle_MaxSpeed(unsigned char *buf, unsigned char buf_len, struct ProtocolP
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * buf_len);
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
memcpy(u32converter.u8array, p, buf_len); memcpy(u32converter.u8array, p, buf_len);
@ -218,7 +218,7 @@ void handle_MaxSpeed(unsigned char *buf, unsigned char buf_len, struct ProtocolP
para->parse.terminal_parameters.MaxSpeed = MaxSpeed; para->parse.terminal_parameters.MaxSpeed = MaxSpeed;
// FLASH_WriteByte(FLASH_ADDR, (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR, (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
JT808_DEBUG("handle_MaxSpeed ==== %d \r\n", para->parse.terminal_parameters.MaxSpeed); JT808_DEBUG("handle_MaxSpeed ==== %d \r\n", para->parse.terminal_parameters.MaxSpeed);
free(p); jt808_free(p);
return; return;
} }
@ -231,7 +231,7 @@ void handle_ProvinceID(unsigned char *buf, unsigned char buf_len, struct Protoco
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * buf_len);
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
memcpy(u16converter.u8array, p, buf_len); memcpy(u16converter.u8array, p, buf_len);
@ -240,7 +240,7 @@ void handle_ProvinceID(unsigned char *buf, unsigned char buf_len, struct Protoco
para->parse.terminal_parameters.ProvinceID = ProvinceID; para->parse.terminal_parameters.ProvinceID = ProvinceID;
// FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
JT808_DEBUG("handle_ProvinceID ==== %d \r\n", para->parse.terminal_parameters.ProvinceID); JT808_DEBUG("handle_ProvinceID ==== %d \r\n", para->parse.terminal_parameters.ProvinceID);
free(p); jt808_free(p);
return; return;
} }
@ -253,7 +253,7 @@ void handle_CityID(unsigned char *buf, unsigned char buf_len, struct ProtocolPar
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * buf_len);
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
memcpy(u16converter.u8array, p, buf_len); memcpy(u16converter.u8array, p, buf_len);
@ -262,7 +262,7 @@ void handle_CityID(unsigned char *buf, unsigned char buf_len, struct ProtocolPar
para->parse.terminal_parameters.CityID = CityID; para->parse.terminal_parameters.CityID = CityID;
// FLASH_WriteByte(FLASH_ADDR, (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR, (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
JT808_DEBUG("handle_CityID ==== %d \r\n", para->parse.terminal_parameters.CityID); JT808_DEBUG("handle_CityID ==== %d \r\n", para->parse.terminal_parameters.CityID);
free(p); jt808_free(p);
return; return;
} }
@ -274,14 +274,14 @@ void handle_CarPlateNum(unsigned char *buf, unsigned char buf_len, struct Protoc
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len + 1); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * buf_len + 1);
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
memset(para->parse.terminal_parameters.CarPlateNum, 0, sizeof(para->parse.terminal_parameters.CarPlateNum)); memset(para->parse.terminal_parameters.CarPlateNum, 0, sizeof(para->parse.terminal_parameters.CarPlateNum));
memcpy(para->parse.terminal_parameters.CarPlateNum, p, buf_len); memcpy(para->parse.terminal_parameters.CarPlateNum, p, buf_len);
// FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
JT808_DEBUG("handle_CarPlateNum ==== %s \r\n", para->parse.terminal_parameters.CarPlateNum); JT808_DEBUG("handle_CarPlateNum ==== %s \r\n", para->parse.terminal_parameters.CarPlateNum);
free(p); jt808_free(p);
return; return;
} }
@ -292,13 +292,13 @@ void handle_CarPlateColor(unsigned char *buf, unsigned char buf_len, struct Prot
// unsigned char write_buf[FLASH_BUFFER_SIZE] = {0}; // unsigned char write_buf[FLASH_BUFFER_SIZE] = {0};
if ((buf == NULL) || (buf_len == 0)) if ((buf == NULL) || (buf_len == 0))
return; return;
p = (unsigned char *)malloc(sizeof(unsigned char) * buf_len + 1); p = (unsigned char *)jt808_malloc(sizeof(unsigned char) * buf_len + 1);
memcpy(p, buf, buf_len); memcpy(p, buf, buf_len);
para->parse.terminal_parameters.CarPlateColor = *p; para->parse.terminal_parameters.CarPlateColor = *p;
// FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters)); // FLASH_WriteByte(FLASH_ADDR , (uint8_t *) &para->parse.terminal_parameters , sizeof(para->parse.terminal_parameters));
JT808_DEBUG("handle_CarPlateColor ==== 0x%02x \r\n", para->parse.terminal_parameters.CarPlateColor); JT808_DEBUG("handle_CarPlateColor ==== 0x%02x \r\n", para->parse.terminal_parameters.CarPlateColor);
free(p); jt808_free(p);
return; return;
} }

View File

@ -1,6 +1,6 @@
#include "terminal_register.h" #include "terminal_register.h"
#include "string.h" #include "string.h"
#include "jt808_debug.h" #include "jt808_config.h"
struct RegisterInfo registerInfo_; struct RegisterInfo registerInfo_;

View File

@ -1,7 +1,7 @@
#include "util.h" #include "util.h"
#include "protocol_parameter.h" #include "protocol_parameter.h"
#include "client_manager.h" #include "client_manager.h"
#include "jt808_debug.h" #include "jt808_config.h"
union U16ToU8Array u16converter; union U16ToU8Array u16converter;
union U32ToU8Array u32converter; union U32ToU8Array u32converter;

View File

@ -0,0 +1,27 @@
#ifndef __LOCAL_TTS_H__
#define __LOCAL_TTS_H__
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "cm_local_tts.h"
void local_tts_init(void);
// 静音 mute: 0-关闭 1-打开
void local_tts_mute(uint8_t mute);
// 音量设置 volume: 0-100
uint8_t local_tts_volume(uint8_t volume);
// speed: 语速取值范围0-15默认为5
// volume: 音量取值范围0-15默认为5
// mode: 0-自动模式 1-数字模式,2-数值模式
void local_tts_set(int32_t speed, int32_t volume, cm_local_tts_digit_e mode);
// 本地TTS播放
int8_t local_tts_text_play(char *text, uint8_t len, uint32_t timeout);
#endif // __LOCAL_TTS_H__

View File

@ -0,0 +1,6 @@
CUSTOM_MAIN_DIR := custom/local_tts
OC_FILES += $(CUSTOM_MAIN_DIR)/src/local_tts.c
INC += -I'$(CUSTOM_MAIN_DIR)/inc'

View File

@ -0,0 +1,173 @@
#include "stdio.h"
#include "stdlib.h"
#include "cm_fs.h"
#include "cm_mem.h"
#include "cm_sys.h"
#include "cm_gpio.h"
#include "cm_iomux.h"
#include "cm_modem.h"
#include "cm_audio_player.h"
#include "cm_audio_recorder.h"
#include "cm_local_tts.h"
#include "local_tts.h"
#if 1
#include "app_uart.h"
#define DEBUG(fmt, args...) app_printf("[tts]" fmt, ##args)
#else
#define DEBUG(fmt, arg...)
#endif
static osMessageQueueId_t local_tts_play_queue = NULL;
static osSemaphoreId_t local_tts_play_ok_sem = NULL;
/* 离线TTS回调函数 */
static void __local_tts_callback(cm_local_tts_event_e event, void *param)
{
switch(event){
case CM_LOCAL_TTS_EVENT_SYNTH_DATA:{
// cm_local_tts_synth_data_t *data = (cm_local_tts_synth_data_t *)param;
// DEBUG("[%s] SYNTH_DATA [%d] \n", data->user, data->len); //打印log操作较费时
break;
}
case CM_LOCAL_TTS_EVENT_SYNTH_FAIL:
case CM_LOCAL_TTS_EVENT_SYNTH_INTERRUPT:
case CM_LOCAL_TTS_EVENT_SYNTH_FINISH:
break;
case CM_LOCAL_TTS_EVENT_PLAY_FAIL:
DEBUG("[%s] PLAY_FAIL\n", (char *)param);
break;
case CM_LOCAL_TTS_EVENT_PLAY_INTERRUPT:
DEBUG("[[%s] PLAY_INTERRUPT\n", (char *)param);
break;
case CM_LOCAL_TTS_EVENT_PLAY_FINISH:
DEBUG("[%s] PLAY_FINISH\n", (char *)param);
osSemaphoreRelease(local_tts_play_ok_sem); // 释放发送成功应答信号量
break;
default:
break;
}
}
// 静音 mute: 0-关闭 1-打开
void local_tts_mute(uint8_t mute){
cm_gpio_set_level(CM_GPIO_NUM_13, mute? 1 : 0);
}
// 音量设置 volume: 0-100
uint8_t local_tts_volume(uint8_t volume){
uint8_t ret;
if(volume > 100){
volume = 100;
}
cm_audio_play_set_cfg(CM_AUDIO_PLAY_CFG_VOLUME, &volume); //音量设置 0-100
cm_audio_play_get_cfg(CM_AUDIO_PLAY_CFG_VOLUME, &ret);
DEBUG("[AUDIO] volume:%d\n", ret);
return ret;
}
// speed: 语速取值范围0-15默认为5
// volume: 音量取值范围0-15默认为5
// mode: 0-自动模式 1-数字模式,2-数值模式
void local_tts_set(int32_t speed, int32_t volume, cm_local_tts_digit_e mode){
cm_local_tts_deinit();
cm_local_tts_cfg_t tts_cfg = {0};
tts_cfg.speed = speed;
tts_cfg.volume = volume;
tts_cfg.encode = CM_LOCAL_TTS_ENCODE_TYPE_UTF8; // 离线TTS仅支持UTF8格式
tts_cfg.digit = mode;
if(0 == cm_local_tts_init(&tts_cfg)){
DEBUG("tts set:speed %d,volume %d,encode %d,digit %d\n" , tts_cfg.speed, tts_cfg.volume, tts_cfg.encode, tts_cfg.digit);
}else{
DEBUG("tts set error\n");
}
osDelay(100/5); // 等待初始化完成
}
typedef struct{
char *text;
uint8_t len;
}tts_play_queue_t;
// 发送本地TTS播放内容 //timeout=osWaitForever时表示等待播放完成
int8_t local_tts_text_play(char *text, uint8_t len, uint32_t timeout){
tts_play_queue_t tts_play_queue = {0};
local_tts_mute(0); // 取消静音
if(0 == len || len > strlen(text)){
len = strlen(text);
DEBUG("tts play text len > len:%d \n", len);
}
tts_play_queue.text = cm_malloc(len + 1);
if(tts_play_queue.text == NULL){
DEBUG("tts play malloc error\n");
return -1;
}
memcpy(tts_play_queue.text, text, len);
tts_play_queue.text[len] = '\0';
tts_play_queue.len = len;
if(osOK != osMessageQueuePut(local_tts_play_queue, &tts_play_queue, 0, 0)){
DEBUG("tts play queue put error\n");
cm_free(tts_play_queue.text);
return -1;
}
// 等待播放完成
osSemaphoreAcquire(local_tts_play_ok_sem, timeout);
DEBUG("tts play queue put success\n");
return 0;
}
// 异步播放,播放完成后播放下一条 //TODO: 待优化(暂时方案,打断播放)
static osThreadFunc_t local_tts_play_task(void *arg){
tts_play_queue_t tts_play_queue;
while(1){
if(osOK == osMessageQueueGet(local_tts_play_queue, &tts_play_queue, NULL, osWaitForever)){ //
DEBUG("tts play stop\n");
cm_local_tts_play_stop(); // 停止播放
osDelay(200/5); // 等待播放停止
if(tts_play_queue.text == NULL){
DEBUG("tts play text is null\n");
continue;
}
DEBUG("tts play start\n");
cm_local_tts_play(tts_play_queue.text, tts_play_queue.len, __local_tts_callback,"Chinese");
cm_free(tts_play_queue.text);
tts_play_queue.text = NULL;
}
}
return 0;
}
// 初始化
void local_tts_init(void){
cm_gpio_cfg_t cfg = {0};
cfg.direction = CM_GPIO_DIRECTION_OUTPUT;
cfg.pull = CM_GPIO_PULL_UP;
cm_iomux_set_pin_func(CM_IOMUX_PIN_77, CM_IOMUX_FUNC_FUNCTION2);//初始化之前一定要先设置引脚复用
cm_gpio_init(CM_GPIO_NUM_13, &cfg);
local_tts_mute(1); // 关闭静音
local_tts_volume(100); // 设置音量为50
local_tts_set(7, 5, CM_LOCAL_TTS_DIGIT_AUTO); // 设置TTS转换参数
if(local_tts_play_queue == NULL){
local_tts_play_queue = osMessageQueueNew(10, sizeof(tts_play_queue_t), NULL);
}
if(local_tts_play_ok_sem == NULL){
local_tts_play_ok_sem = osSemaphoreNew(1, 0, NULL);
}
osThreadAttr_t local_tts_play_thread_attr = {
.name = "local_tts_play_thread",
.stack_size = 4096 * 4,
.priority = osPriorityNormal
};
osThreadNew((osThreadFunc_t)local_tts_play_task, NULL, &local_tts_play_thread_attr);
}

View File

@ -49,8 +49,8 @@
#endif #endif
#include "cm_mem.h" #include "cm_mem.h"
#define name_malloc(size) cm_malloc(size) #define name_malloc(size) malloc(size)
#define name_free(ptr) cm_free(ptr) #define name_free(ptr) free(ptr)
#endif /* __NMEA_CONFIG_H__ */ #endif /* __NMEA_CONFIG_H__ */

View File

@ -0,0 +1,25 @@
#ifndef __TCP_CLIENT_H__
#define __TCP_CLIENT_H__
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include "string.h"
#include "cm_os.h"
#define TCP_HOST "36.137.226.30" //TCP地址 例"192.168.0.1"
#define TCP_PORT 38840 //TCP端口
// 连接TCP服务器
int tcp_client_connect(const char *host, int port);
// 发送数据到TCP服务器
int tcp_client_send(const uint8_t *buf, uint16_t len);
// 关闭TCP连接
void tcp_client_close(void);
// 初始化TCP客户端
void tcp_client_init(void);
#endif /* __TCP_CLIENT_H__ */

View File

@ -0,0 +1,227 @@
#include "lwip/lwip/netdb.h"
#include "lwip/lwip/sockets.h"
#include "cm_modem.h"
#include "cm_pm.h"
#include "jt808_msg_pkg.h"
#include "jt808_msg_parse.h"
#include "jt808_pkg_transmit.h"
#include "jt808_set_TermParam.h"
#include "tcp_client.h"
#include "app_common.h"
#define TCP_CLIENT_ENABLE 1
#if TCP_CLIENT_ENABLE
#include "app_uart.h"
#define DEBUG(fmt, args...) app_printf("[TCP]" fmt, ##args)
#else
#define DEBUG(fmt, arg...)
#endif
static int tcp_client_sock = -1;
static osThreadId_t tcp_recv_ThreadId = NULL;
static osThreadId_t net_manage_ThreadId = NULL;
osSemaphoreId_t netconn_disconnect_sem = NULL; // 断开连接信号量
// TCP接收线程
static void tcp_recv_task(void){
int ret = 0;
fd_set sets;
struct timeval timeout;
uint8_t buf[128] = {0};
while(1){
FD_ZERO(&sets);
FD_SET(tcp_client_sock, &sets);
timeout.tv_sec = 10;
timeout.tv_usec = 0;
ret = select(tcp_client_sock + 1, &sets, NULL, NULL, &timeout);//监听套接字
if(ret > 0){ // 发生状态变化,可以进行读取、写入或者有异常事件
// DEBUG("tcp_read select ret %d\n", ret);
if(FD_ISSET(tcp_client_sock, &sets)){ // 套接字可读
ret = recv(tcp_client_sock, buf, sizeof(buf), 0);
if(ret > 0){
DEBUG("tcp_read recv:%d\n", ret);
for(int i = 0; i < ret; i++){
app_printf("%02x ", buf[i]);
}
app_printf("\n\n");
// 处理接收到的数据
jt808_pkg_handle(buf, ret);
memset(buf, 0, sizeof(buf));
}else if(ret <= 0){// 连接已断开或发生错误客户端需要执行close操作
DEBUG("tcp_read closed %d\n", errno);
close(tcp_client_sock);
}
}
}else if(ret == 0){// select 等待超时
// TODO
DEBUG("tcp_read_test select timeout %d\n", errno);
}else{// 走到这时当前socket已关闭此时select将一直报错故而挂起线程等待重新连接后再次恢复线程
DEBUG("tcp_recv_task Suspend %d\n", errno);
close(tcp_client_sock);
osSemaphoreRelease(netconn_disconnect_sem); // 发送断开连接信号
osThreadSuspend(tcp_recv_ThreadId);
}
}
}
// TCP连接 // host:服务地址port:服务端口
int tcp_client_connect(const char *host, int port) {
int ret = 0;
tcp_client_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tcp_client_sock == -1){
DEBUG("tcp socket create error\n");
return -1;
}
DEBUG("tcp connect:%s, %d\n", host, port);
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_len = sizeof(server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port); //端口
server_addr.sin_addr.s_addr = inet_addr(host); //服务地址
ret = connect(tcp_client_sock, (const struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret == -1){
DEBUG("tcp connect error\n");
close(tcp_client_sock);
return -1;
}else if (ret == 0){
/* 建立新的线程供select异步读取*/
DEBUG("tcp connect ok\n");
if (tcp_recv_ThreadId == NULL){
osThreadAttr_t tcp_recv_task_attr = {0};
tcp_recv_task_attr.name = "tcp_recv_task";
tcp_recv_task_attr.stack_size = 1024;
tcp_recv_task_attr.priority = osPriorityNormal;
tcp_recv_ThreadId = osThreadNew((osThreadFunc_t)tcp_recv_task, 0, &tcp_recv_task_attr);
}else{
DEBUG("tcp_recv_task Resume %d\n", errno);
osThreadResume(tcp_recv_ThreadId); //恢复线程
}
}
return 0;
}
// TCP发送数据
int tcp_client_send(const uint8_t *buf, uint16_t len){ // 不可加打印
int ret = 0;
ret = send(tcp_client_sock, (char *)buf, len, 0);
if(ret < 0){
DEBUG("tcp send error\n");
// close(tcp_client_sock);
return -1;
}
// DEBUG("tcp send %d bytes\n", ret);
return 0;
}
void tcp_client_close(void){
if(tcp_client_sock != -1){
close(tcp_client_sock);
tcp_client_sock = -1;
}
if(tcp_recv_ThreadId != NULL){
osThreadSuspend(tcp_recv_ThreadId); //挂起线程
// tcp_recv_ThreadId = NULL;
}
}
// 网络管理线程
static void net_manage_task(void *arg){
// osThreadState_t state;
DEBUG("net_manage_task!\r\n");
int ret = 0;
cm_cereg_state_t cereg_state = {0};
uint8_t error_time_out = 0;
while(1){
TCP_DISABLE:
do{// 连接服务器
while(1){ // 等待插入SIM卡并建立网络连接
osDelay(1000/5);
error_time_out++;
if(error_time_out > 15){ // 超时退出
DEBUG("network connect timeout!\n");
cm_pm_reboot();
}
if(0 == cm_modem_get_cpin()){ // 插入SIM卡
DEBUG("sim card ready!\r\n");
}else{
DEBUG("waiting for sim card...\r\n");
}
if(0 ==cm_modem_get_cereg_state(&cereg_state)){ // 获取PS网络注册状态
DEBUG("cereg_state:%d\n",cereg_state.state); // 注册状态
if(cereg_state.state == 1){ // 已注册
DEBUG("network ready\n");
break;
}else{
DEBUG("waiting for network...\n");
}
}else{
DEBUG("cereg_get_state fail!\n\n");
}
// if(cm_modem_get_pdp_state(1) == 1){ // 网络就绪
// app_printf("network ready\n");
// }else{
// app_printf("waiting for network...\n");
// }
}
}while(0 != tcp_client_connect(PrsResult.term_param_item->set_term_param.MainServerAddr , PrsResult.term_param_item->set_term_param.ServerPort)); // 连接到TCP服务器
DEBUG("tcp_client_connect success!\r\n");
// jt808_pkg_send(ID_Term_GenResp,5000/5);
for(uint8_t i = 0; i < 3; i++){ // 发送3次注册、鉴权、参数设置、上报参数
ret =jt808_pkg_send(ID_Term_Reg,8000/5);//注册终端 超时8S
if(0 == ret){
DEBUG("send ID_Term_Reg success!\n");
for(uint8_t i = 0; i < 3; i++){
ret =jt808_pkg_send(ID_Term_Auth,10000/5);//终端鉴权 超时10S
if(0 == ret){
DEBUG("send ID_Term_Auth success!\n");
break;
}else{
DEBUG("send ID_Term_Auth fail:%d!\n",ret);
if(ret == -1){
goto TCP_DISABLE;
}
}
}
break;
}else{
DEBUG("send ID_Term_Reg fail:%d!\n",ret);
if(ret == -1){
goto TCP_DISABLE;
}
}
}
jt808_Autoreport_param_start();//开启自动上报参数设置
led_set_event(EVENT_NETWORK_READY); // 网络连接成功
osSemaphoreAcquire(netconn_disconnect_sem, osWaitForever); // 等待断开连接信号
jt808_Autoreport_param_stop();//停止自动上报参数设置
led_set_event(EVENT_NETWORK_DISCONNECT); // 网络断开连接
}
}
void tcp_client_init(void){
osThreadAttr_t net_manage_task_attr={
.name = "net_manage_task",
.stack_size = 1024,
.priority = osPriorityNormal,
};
DEBUG("tcp_client_init!\r\n");
if(netconn_disconnect_sem == NULL){
netconn_disconnect_sem = osSemaphoreNew(1, 0, NULL);
}
net_manage_ThreadId = osThreadNew((osThreadFunc_t)net_manage_task, 0, &net_manage_task_attr);
}

View File

@ -0,0 +1,6 @@
CUSTOM_MAIN_DIR := custom/tcp_client
OC_FILES += $(CUSTOM_MAIN_DIR)/src/tcp_client.c
INC += -I'$(CUSTOM_MAIN_DIR)/inc'

View File

@ -6,8 +6,16 @@
#include "cm_audio_player.h" #include "cm_audio_player.h"
#include "cm_audio_common.h" #include "cm_audio_common.h"
#define DEBUG_ENABLE 0
#define CM_TTS_FRAME_BUFFER_SIZE (320 * 50 * 10) //支持存放10秒数据可修改 #if DEBUG_ENABLE
#include "app_uart.h"
#define DEBUG(fmt, args...) app_printf("[tts]" fmt, ##args)
#else
#define DEBUG(fmt, arg...)
#endif
#define CM_TTS_FRAME_BUFFER_SIZE (320 * 50 * 60) //支持存放10秒数据可修改
typedef struct { typedef struct {
osThreadId_t TaskHandle; /* TTS播放管理句柄 */ osThreadId_t TaskHandle; /* TTS播放管理句柄 */
@ -39,7 +47,7 @@ static void __cm_tts_play_callback(cm_local_tts_event_e event, void *param)
{ {
cm_tts_play_cfg.user_cb(event, param); cm_tts_play_cfg.user_cb(event, param);
} }
//cm_log_printf(0, "[TTS] [%s] CM_LOCAL_TTS_EVENT_SYNTH_DATA [%d] \n", synth_data->user, synth_data->len); DEBUG("[TTS] [%s] CM_LOCAL_TTS_EVENT_SYNTH_DATA [%d] \n", synth_data->user, synth_data->len);
break; break;
} }
case CM_LOCAL_TTS_EVENT_SYNTH_FAIL: case CM_LOCAL_TTS_EVENT_SYNTH_FAIL:
@ -68,7 +76,7 @@ static void __cm_tts_play_task(void *param)
/* 转码速度大于播放速度,故无需考虑播放速度大于转码速度情况的延迟等待问题 */ /* 转码速度大于播放速度,故无需考虑播放速度大于转码速度情况的延迟等待问题 */
while (index < cm_tts_play_cfg.TtsPcmBufLen && CM_LOCAL_TTS_STATE_WORKING == cm_tts_play_cfg.state) while (index < cm_tts_play_cfg.TtsPcmBufLen && CM_LOCAL_TTS_STATE_WORKING == cm_tts_play_cfg.state)
{ {
//cm_log_printf(0, "%s() __%d__ Length is %d, index is %d", __func__, __LINE__, cm_tts_play_cfg.TtsPcmBufLen, index); DEBUG("%s() __%d__ Length is %d, index is %d", __func__, __LINE__, cm_tts_play_cfg.TtsPcmBufLen, index);
/* 每200ms传10帧PCM数据 */ /* 每200ms传10帧PCM数据 */
if (index + 3200 <= cm_tts_play_cfg.TtsPcmBufLen) if (index + 3200 <= cm_tts_play_cfg.TtsPcmBufLen)
@ -121,7 +129,7 @@ static void __cm_tts_play_task(void *param)
//cm_heap_stats_t stats = {0}; //cm_heap_stats_t stats = {0};
//cm_mem_get_heap_stats(&stats); //cm_mem_get_heap_stats(&stats);
//cm_log_printf(0, "heap total:%d,remain:%d\n",stats.total_size,stats.free); //DEBUG(0, "heap total:%d,remain:%d\n",stats.total_size,stats.free);
} }
} }
@ -147,7 +155,7 @@ int32_t cm_local_tts_play(const char *text, int32_t len, cm_local_tts_callback c
//需要判断当前是否处于播放过程中,处于播放过程中报错 //需要判断当前是否处于播放过程中,处于播放过程中报错
if (CM_LOCAL_TTS_STATE_WORKING == cm_tts_play_cfg.state) if (CM_LOCAL_TTS_STATE_WORKING == cm_tts_play_cfg.state)
{ {
cm_log_printf(0, "%s() __%d__ TTS busy", __func__, __LINE__); DEBUG("%s() __%d__ TTS busy", __func__, __LINE__);
return -1; return -1;
} }
@ -157,7 +165,7 @@ int32_t cm_local_tts_play(const char *text, int32_t len, cm_local_tts_callback c
if (NULL == cm_tts_play_cfg.TtsPcmBuf) if (NULL == cm_tts_play_cfg.TtsPcmBuf)
{ {
cm_log_printf(0, "%s() __%d__ cm_malloc() error", __func__, __LINE__); DEBUG("%s() __%d__ cm_malloc() error", __func__, __LINE__);
return -1; return -1;
} }
} }
@ -165,11 +173,15 @@ int32_t cm_local_tts_play(const char *text, int32_t len, cm_local_tts_callback c
cm_audio_sample_param_t frame = {.sample_format = CM_AUDIO_SAMPLE_FORMAT_16BIT, .rate = CM_AUDIO_SAMPLE_RATE_8000HZ, .num_channels = CM_AUDIO_SOUND_MONO}; cm_audio_sample_param_t frame = {.sample_format = CM_AUDIO_SAMPLE_FORMAT_16BIT, .rate = CM_AUDIO_SAMPLE_RATE_8000HZ, .num_channels = CM_AUDIO_SOUND_MONO};
int32_t ret = cm_audio_player_stream_open(CM_AUDIO_PLAY_FORMAT_PCM, &frame); //从pipe中播放音频开启 int32_t ret = cm_audio_player_stream_open(CM_AUDIO_PLAY_FORMAT_PCM, &frame); //从pipe中播放音频开启
if (-1 == ret) if (-1 == ret){
{ DEBUG("%s() __%d__ cm_audio_player_stream_open0() error, ret is %d", __func__, __LINE__, ret);
cm_log_printf(0, "%s() __%d__ cm_audio_player_stream_open() error, ret is %d", __func__, __LINE__, ret); cm_audio_player_stream_close();
ret = cm_audio_player_stream_open(CM_AUDIO_PLAY_FORMAT_PCM, &frame); //从pipe中播放音频开启
if (-1 == ret){
DEBUG("%s() __%d__ cm_audio_player_stream_open1() error, ret is %d", __func__, __LINE__, ret);
return -1; return -1;
} }
}
if (NULL == cm_tts_play_cfg.SemHandle) if (NULL == cm_tts_play_cfg.SemHandle)
{ {
@ -177,7 +189,7 @@ int32_t cm_local_tts_play(const char *text, int32_t len, cm_local_tts_callback c
if (NULL == cm_tts_play_cfg.SemHandle) if (NULL == cm_tts_play_cfg.SemHandle)
{ {
cm_log_printf(0, "%s() __%d__ osSemaphoreNew() error", __func__, __LINE__); DEBUG("%s() __%d__ osSemaphoreNew() error", __func__, __LINE__);
cm_audio_player_stream_close(); cm_audio_player_stream_close();
return -1; return -1;
} }
@ -195,7 +207,7 @@ int32_t cm_local_tts_play(const char *text, int32_t len, cm_local_tts_callback c
if (NULL == cm_tts_play_cfg.TaskHandle) if (NULL == cm_tts_play_cfg.TaskHandle)
{ {
cm_log_printf(0, "%s() __%d__ osThreadNew() error", __func__, __LINE__); DEBUG("%s() __%d__ osThreadNew() error", __func__, __LINE__);
cm_audio_player_stream_close(); cm_audio_player_stream_close();
return -1; return -1;
} }
@ -225,11 +237,9 @@ int32_t cm_local_tts_play(const char *text, int32_t len, cm_local_tts_callback c
* *
* @details 8M版本ML307A-DSLN ML307A-GSLN ML305A-DS等线TTS功能 * @details 8M版本ML307A-DSLN ML307A-GSLN ML305A-DS等线TTS功能
*/ */
int32_t cm_local_tts_play_stop(void) int32_t cm_local_tts_play_stop(void){
{ if (CM_LOCAL_TTS_STATE_IDLE == cm_tts_play_cfg.state){
if (CM_LOCAL_TTS_STATE_IDLE == cm_tts_play_cfg.state) DEBUG("%s() __%d__ no TTS task", __func__, __LINE__);
{
cm_log_printf(0, "%s() __%d__ no TTS task", __func__, __LINE__);
return -1; return -1;
} }