/* ********************************************************************************************************* * IAR Development Kits * on the * * M451 * * Filename : uart_dtu.c * Version : V1.00 * Programmer(s) : Qian Xianghong ********************************************************************************************************* */ #include "includes.h" #include "cJSON.h" // 初始唤醒次数(快速发送) #define INITIAL_TRAN_COUNT 6 // 绝对值 #define abs(x) ((x) < 0 ? -(x) : (x)) // GPS上报数据的时间戳,年基数为2010 #define GPS_BASE_YEAR 2010 // Boot-loader地址(在线升级以后重启运行) #define LDROM_BASE 0x100000ul // 1M // GPRS串口接收的循环缓冲 #define DTU_TASKM_DATA_COUNT 200 loopbuff_t DTU_TaskM; uint8_t DTU_TaskM_Data[sizeof(uint8_t) * (DTU_TASKM_DATA_COUNT + 1)] = {0}; // GPS开启计时 volatile uint32_t DTU_gpsTime = 0; // 强制上传数据 volatile uint8_t DTU_dataConn = 0; // 强制连接维护平台 volatile uint8_t DTU_ldmsConn = 0; // 维护平台连接计时 volatile uint32_t DTU_ldmsTime = 0; // 最近一条上传数据的采集时间 volatile uint32_t DTU_dataTime = 0; // 串口超时定时器 const uint16_t DTU_tmrQPendLong = 120; // 120s const uint16_t DTU_tmrQPendShort = 5; // 5s const uint16_t DTU_tmrQPendSpec = 40; // 40s // 发送成功时间 volatile uint32_t DTU_succTime = 0; // DTU上电标志 uint8_t DTU_hasPowered = 0; uint8_t DTU_imeiRead = 0; uint8_t DTU_simCard = 0; uint8_t DTU_simReg = 0; uint8_t DTU_gprsReg = 0; uint8_t DTU_isATMode = 0; uint8_t DTU_gprsAttached = 0; uint8_t DTU_linkEstablished = 0; uint8_t DTU_sslConfig = 0; uint8_t DTU_mqttConfig = 0; uint8_t DTU_ipFetched = 0; char DTU_APN[20] = ""; uint8_t DTU_isRMCFormat = 0; uint8_t DTU_fail_count = 0; uint8_t DTU_shutdown_count = 0; // 是否需要检查并重启GPS uint8_t DTU_needCheckGPS = 0; void DTU_CheckGPS(); // GPRS拨号 uint32_t Sim808_GPRSDial(); // 从服务器获取当前时间 void DTU_setOffsetSecondsFromServer(); // 这个缓冲区比较大,不放在stack里面 #define DTU_GPSDATA_SIZE 120 char DTU_gpsData[2][DTU_GPSDATA_SIZE] = {0}; // 扩展内存 #define DTU_RECVBUFF_SIZE 200 char DTU_recvBuff[DTU_RECVBUFF_SIZE] = {0}; // 扩展内存 // 一次请求升级包数据大小 #define UPGRADE_DATA_LEN 1024 // DTU_Task任务和服务器之间的收发缓冲 #define TASK_SENDBUFF_SIZE 800 uint8_t Task_sendBuff[TASK_SENDBUFF_SIZE] = {0}; // 扩展内存 #if UPGRADE_DATA_LEN >= SFLASH_ERASE_SIZE #define TASK_RECVBUFF_SIZE (UPGRADE_DATA_LEN + 32) #else #define TASK_RECVBUFF_SIZE (SFLASH_ERASE_SIZE) #endif uint8_t Task_recvBuff[TASK_RECVBUFF_SIZE] = {0}; // 扩展内存 // 信号量,用于通知执行任务 volatile uint8_t DTU_semGPS = 0; volatile uint8_t DTU_semGPRS = 0; volatile uint8_t DTU_semSync = 0; // **************** 上传GPS调试信息 ******************** // GPS闪断次数:取值为0~599循环计数 uint16_t GPS_BOD_COUNT = 0; // ***************************************************** // 用于发送到服务器的数据结构 // 和蓝牙的相应命令一致 #pragma pack(push, 1) typedef struct { uint16_t mark; unsigned ver : 7; unsigned trans : 1; unsigned reserved: 8; uint16_t len; union { uint16_t cmd; struct { uint8_t err; uint8_t cmd_L; }; }; } bluetooth_recv_t; typedef bluetooth_recv_t bluetooth_send_t; typedef struct { unsigned staEPress3 : 2; unsigned staETempr1 : 2; unsigned staETempr2 : 2; unsigned staETempr3 : 2; unsigned staDiff : 2; unsigned staPress : 2; unsigned staEPress1 : 2; unsigned staEPress2 : 2; } bluetooth_sensor_t; typedef struct { unsigned maskStamp : 1; unsigned maskEPress1 : 1; unsigned maskEPress2 : 1; unsigned maskEPress3 : 1; unsigned : 1; unsigned maskLowPower : 1; unsigned maskAbnormal : 1; unsigned maskCharging : 1; unsigned maskRssi : 1; unsigned maskGPS : 1; unsigned maskETempr1 : 1; unsigned maskETempr2 : 1; unsigned maskETempr3 : 1; unsigned maskBattery : 1; unsigned maskFlow : 1; unsigned maskLeak : 1; } bluetooth_mask_t; typedef union { struct { unsigned sec : 6; unsigned min : 6; unsigned hour_L : 4; unsigned hour_H : 1; unsigned day : 5; unsigned mon : 4; unsigned year : 6; }; uint32_t tm; } bluetooth_timestamp_t; typedef union { unsigned long long ll; struct { unsigned long l; unsigned long h; }; } longlong_mask_t; typedef struct { union { struct { unsigned sateCount : 5; // gps可见卫星数量 unsigned posState : 1; // gps定位状态 (0-GPS未定位,1-GPS已定位) unsigned carState : 1; // 车辆是否启动 (0-车辆未启动,1-车辆已启动) unsigned carEvent : 1; // 车辆启动或停止事件(0-启动状态未改变,1-启动状态已改变) }; uint8_t state; }; bluetooth_timestamp_t time; // 时间戳 int32_t latitude; int32_t longitude; uint16_t speed; } gps_data_t; typedef struct // size = 158 { uint32_t sample_time; // 采集时间:自启动以来经过的秒数 data_dtu_t dtuData; // size = 36 data_sample_t sampleData; // size = 118 } gprs_data_t; // 双向通讯的数据结构 typedef struct // size = 120 { uint16_t serverVer; // 服务器参数版本号 uint8_t type; // 储罐类型 uint32_t diameter; // 内径 uint32_t len; // 圆柱体长度 uint32_t lenExtra; // 直边封头长度 uint32_t reserved_1[3]; uint8_t source; // 液源 uint32_t density; // 各液源的比重(kg/m3) uint16_t fullPct; // 满液位百分比 uint16_t priPct; // 关键液位百分比 uint16_t orderPct; // 订货液位百分比 uint16_t emptyPct; // 空液位百分比 uint32_t planMount; // 每日计划用量 uint32_t predictMount; // 每日预测用量 uint16_t warnVolt; // 电压报警低点: 10mV uint16_t warnVoltH; // 电压报警高点: 10mV uint16_t warnPress; // 压力报警低点: KPa uint16_t warnPressH; // 压力报警高点: KPa uint32_t intervalTrans; // 数据上报周期 uint32_t intervalSample; // 数据采集周期 uint32_t intervalGPSTrans; // 位置上报周期 uint32_t intervalGPS; // 位置采集周期 union { struct { char gpsServer[20]; // 远传服务器 (只上传,不修改) int16_t gpsPort; // 远传端口 (只上传,不修改) char pwd1[6]; // 储罐参数修改密码 }; struct { char gprsServer[26]; // praxair:修改数据服务器地址 int16_t gprsPort; // praxair: 修改数据服务器端口 }; }; uint32_t options; // 参数开关 union { uint8_t reserved_2[12]; struct { uint16_t floorLevel; // praxair: 液量报警下限 uint16_t span; // praxair: 液量变化报警门限 uint16_t spanPeriod; // praxair: 液量变化报警时间 unsigned floorLevelAssigned : 1; // praxair: 参数中floorLevel是否有效 unsigned spanAssigned : 1; // praxair: 参数中span是否有效 unsigned spanPeriodAssigned : 1; // praxair: 参数中spanPeriod是否有效 unsigned intervalTransAssigned : 1; // praxair: 参数中intervalTrans是否有效 unsigned gprsServerAssigned : 1; // praxair: 参数中数据服务器地址是否有效 unsigned gprsPortAssigned : 1; // praxair: 参数中数据服务器端口是否有效 unsigned : 2; }; }; uint32_t ts; // 参数时间戳 } param_data_t; // 升级进度信息(存放在FRAM中,可断点续传) typedef struct { uint16_t check; // 标志,固定为0x55AA uint32_t ver; // 固件版本 int32_t fileSize; // 固件总字节数 uint16_t fileCrc; // 固件总的crc int32_t offset; // 本次固件偏移量 int32_t len; // 本次数据长度 uint16_t crc; // 本记录的crc } upgrade_info_t; // 升级包接收记录 typedef struct { uint32_t ver; // 固件版本 int32_t fileSize; // 固件总字节数 uint16_t fileCrc; // 固件总的crc int32_t offset; // 本次固件偏移量 int32_t len; // 本次数据长度 uint8_t data[UPGRADE_DATA_LEN]; // 本次数据 uint16_t crc; // 本次数据的crc } upgrade_frame_t; // 升级文件头 typedef struct // size=12 { unsigned short check; // 数据有效标志, 0x55AA表示有效 unsigned upgrade_request : 1; // 升级请求标志,0-无升级,1-有升级 unsigned upgrade_result : 3; // 升级失败标志,0-成功,1-失败,其余保留 unsigned encrypt_flag : 2; // 加密标志, 0-无加密,其余保留 unsigned compress_flag : 2; // 压缩标志, 0-无压缩,1-有压缩,其余保留 unsigned rerseved1 : 8; // 保留,必须为0xFF unsigned long upgrade_length; // 升级文件长度 unsigned rerseved2 : 8; // 保留,必须为0xFF unsigned rerseved3 : 8; // 保留,必须为0xFF unsigned short crc; // 对前面内容的crc校验 } TUpgradeHeader; // 阿里云密钥记录 typedef struct // size=76 { unsigned short check; // 数据有效标志, 0x55AA表示有效 uint8_t PSN[6]; // 获取密钥所用的PSN(如果PSN改变需重新获取) char product[12]; // 产品代码 char device[21]; // 默认为cPSN char secret[33]; // 设备密钥 unsigned short crc; // 对前面内容的crc校验 } TAliyunSecret; #define ALIYUN_SECRET_SIZE (66) #pragma pack(pop) // 阿里云密钥 TAliyunSecret aliyunSecret = {0}; // 升级包记录 upgrade_info_t upInfo = {0}; // GPS循环缓冲记录 loopbuff_t gpsBuff = {0}; // 存放GPRS记录的循环缓冲 loopbuff_t gprsBuff = {0}; loopbuff_t bd_gprsBuff = {0}; // GPRS记录读写缓冲 gprs_data_t gprsRWBuf; void pack_param_DO23_data(param_data_t *param) { memset(param, 0, sizeof(param_data_t)); param->serverVer = htons(dcBuff.configBottle.serverVer); param->type = dcBuff.configBottle.type; param->diameter = htonl(dcBuff.configBottle.diameter); param->len = htonl(dcBuff.configBottle.len); param->lenExtra = htonl(dcBuff.configBottle.lenExtra); param->source = dcBuff.configBottle.source; param->density = htonl(Config_GetDensity(dcBuff.configBottle.source) * 1000); param->fullPct = htons(dcBuff.configBottle.fullPct); param->priPct = htons(dcBuff.configBottle.priPct); param->orderPct = htons(dcBuff.configBottle.orderPct); param->emptyPct = htons(dcBuff.configBottle.emptyPct); param->planMount = htonl(dcBuff.configBottle.planMount); param->predictMount = htonl(dcBuff.configBottle.predictMount); param->warnVolt = htons(dcBuff.configBottle.warnVolt); param->warnVoltH = htons(dcBuff.configBottle.warnVoltH); param->warnPress = htons(dcBuff.configBottle.warnPress); param->warnPressH = htons(dcBuff.configBottle.warnPressH); param->intervalTrans = htonl(dcBuff.configData.intervalTrans); param->intervalSample = htonl(dcBuff.configData.intervalSample); param->intervalGPSTrans = htonl(dcBuff.configData.intervalGPSTrans); param->intervalGPS = htonl(dcBuff.configData.intervalGPS); if(dcBuff.configBottle.serverVer != 3) { strcpy(param->gpsServer, dcBuff.configData.gpsServer); param->gpsPort = htons(dcBuff.configData.gpsPort); strcpy(param->pwd1, dcBuff.configDisplay.pwd1); } param->options = dcBuff.configBottle.options; if(dcBuff.configBottle.dispMode == DISP_MODE_ALL) param->options |= 0x0003ul; else param->options &= ~0x0003ul; param->options = htonl(param->options); param->ts = htonl(dcBuff.configBottle.ts); // praxair memset(param->reserved_2, 0, sizeof(param->reserved_2)); if(dcBuff.configBottle.serverVer == 3) { param->floorLevel = htons(dcBuff.configBottle.floorLevel); param->floorLevelAssigned = 1; param->span = htons(dcBuff.configBottle.span); param->spanAssigned = 1; param->spanPeriod = htons(dcBuff.configBottle.spanPeriod); param->spanPeriodAssigned = 1; param->intervalTransAssigned = 1; strcpy(param->gprsServer, dcBuff.configData.server); param->gprsServerAssigned = 1; param->gprsPort = htons(dcBuff.configData.port); param->gprsPortAssigned = 1; } } void parse_param_D021_data(param_data_t *param) { int serverVer = ntohs(param->serverVer); dcBuff.configBottle.serverVer = serverVer; if(serverVer == 3) // praxair { if(param->floorLevelAssigned) dcBuff.configBottle.floorLevel = ntohs(param->floorLevel); if(param->spanAssigned) dcBuff.configBottle.span = ntohs(param->span); if(param->spanPeriodAssigned) dcBuff.configBottle.spanPeriod = ntohs(param->spanPeriod); if(param->intervalTransAssigned) dcBuff.configData.intervalTrans = ntohl(param->intervalTrans); if(param->gprsServerAssigned) { strcpy(dcBuff.configData.server, param->gprsServer); strcpy(dcBuff.configData.upgServer, param->gprsServer); strcpy(dcBuff.configData.gpsServer, param->gprsServer); } if(param->gprsPortAssigned) { dcBuff.configData.port = ntohs(param->gprsPort); dcBuff.configData.upgPort = dcBuff.configData.port + 1; dcBuff.configData.gpsPort = dcBuff.configData.port + 2; } } else { dcBuff.configBottle.type = param->type; dcBuff.configBottle.diameter = ntohl(param->diameter); dcBuff.configBottle.len = ntohl(param->len); dcBuff.configBottle.lenExtra = ntohl(param->lenExtra); dcBuff.configBottle.source = param->source; Config_SetDensity(dcBuff.configBottle.source, ntohl(param->density) / 1000.0); dcBuff.configBottle.fullPct = ntohs(param->fullPct); dcBuff.configBottle.priPct = ntohs(param->priPct); dcBuff.configBottle.orderPct = ntohs(param->orderPct); dcBuff.configBottle.emptyPct = ntohs(param->emptyPct); dcBuff.configBottle.planMount = ntohl(param->planMount); dcBuff.configBottle.predictMount = ntohl(param->predictMount); dcBuff.configBottle.warnVolt = ntohs(param->warnVolt); dcBuff.configBottle.warnVoltH = ntohs(param->warnVoltH); dcBuff.configBottle.warnPress = ntohs(param->warnPress); dcBuff.configBottle.warnPressH = ntohs(param->warnPressH); dcBuff.configData.intervalTrans = ntohl(param->intervalTrans); dcBuff.configData.intervalSample = ntohl(param->intervalSample); // 以下参数只做上传,不做修改 // dcBuff.configData.intervalGPSTrans = ntohl(param->intervalGPSTrans); // dcBuff.configData.intervalGPS = ntohl(param->intervalGPS); // strcpy(dcBuff.configData.gpsServer, param->gpsServer); // dcBuff.configData.gpsPort = ntohs(param->gpsPort); // strcpy(dcBuff.configDisplay.pwd1, param->pwd1); dcBuff.configBottle.options = ntohl(param->options); if(dcBuff.configBottle.options & 0x0003ul) dcBuff.configBottle.dispMode = DISP_MODE_ALL; else dcBuff.configBottle.dispMode = DISP_MODE_DPRESS; dcBuff.configBottle.ts = ntohl(param->ts); } } // 是否GPS定位 volatile uint8_t GPS_Locate = 1; volatile uint8_t GPS_Located = 0; volatile uint32_t GPS_waitTick = 0; volatile uint8_t GPS_Waiting = 0; // GPS定位超时 const uint8_t DTU_tmrLocate = 90; // GPS发送数据 volatile uint32_t GPS_tranTick = 0; // 保存上次数据的时间 bluetooth_timestamp_t GPS_LastTime = {0}; // 是否发送GPRS数据 uint8_t GPRS_Send_Task = 0; uint32_t GPRS_Send_Time = 0; // 是否保存GPRS数据 uint8_t GPRS_Save_Task = 0; uint32_t GPRS_Save_Time = 0; // 计算两个经纬度之间的距离 const double EARTH_RADIUS = 6378.137; double rad(double d) { return d * PI / 180.0; } double GetDistance(int32_t lat1, int32_t lng1, int32_t lat2, int32_t lng2) { double radLat1 = rad(lat1 * 0.000001); double radLat2 = rad(lat2 * 0.000001); double a = radLat1 - radLat2; double b = rad(lng1 * 0.000001) - rad(lng2 * 0.000001); double s = 2 * asin(sqrt(pow(sin(a / 2), 2) + cos(radLat1) * cos(radLat2) * pow(sin(b / 2), 2))); s = s * EARTH_RADIUS; return s; } // 比较新数据的时间,是否晚于老数据的时间 int32_t GPS_IsLateThan(bluetooth_timestamp_t *pNewTime, bluetooth_timestamp_t *pOldTime) { uint8_t newHour = (pNewTime->hour_H << 4) | pNewTime->hour_L; uint8_t oldHour = (pOldTime->hour_H << 4) | pOldTime->hour_L; if(pNewTime->year > pOldTime->year) return TRUE; if(pNewTime->year < pOldTime->year) return FALSE; if(pNewTime->mon > pOldTime->mon) return TRUE; if(pNewTime->mon < pOldTime->mon) return FALSE; if(pNewTime->day > pOldTime->day) return TRUE; if(pNewTime->day < pOldTime->day) return FALSE; if(newHour > oldHour) return TRUE; if(newHour < oldHour) return FALSE; if(pNewTime->min > pOldTime->min) return TRUE; if(pNewTime->min < pOldTime->min) return FALSE; return pNewTime->sec > pOldTime->sec; } // 计算两个时间间隔的秒数 uint32_t GPS_CalcInterval(bluetooth_timestamp_t *pNewTime, bluetooth_timestamp_t *pOldTime) { // 计算从OldYear以来的秒数 uint32_t newSeconds = Calc_SecondsFromYear(GPS_BASE_YEAR + pOldTime->year, pNewTime->year + GPS_BASE_YEAR, pNewTime->mon, pNewTime->day, (pNewTime->hour_H << 4) | pNewTime->hour_L, pNewTime->min, pNewTime->sec); uint32_t oldSeconds = Calc_SecondsFromYear(GPS_BASE_YEAR + pOldTime->year, pOldTime->year + GPS_BASE_YEAR, pOldTime->mon, pOldTime->day, (pOldTime->hour_H << 4) | pOldTime->hour_L, pOldTime->min, pOldTime->sec); return newSeconds - oldSeconds; } // 将一个数据加入队列 void GPS_PutToQueue(gps_data_t *gps) { uint16_t nextPtr; // 如果要添加数据的时间大于上一条数据的时间 if(GPS_LastTime.year == 0 || GPS_IsLateThan(&gps->time, &GPS_LastTime)) { // 移动写指针 nextPtr = LoopBuff_GetNextPtr(&gpsBuff, gpsBuff.info.wtPtr); // 如果队列已满 if(nextPtr == gpsBuff.info.rdPtr) { // 移动读指针(丢弃第一条数据) gpsBuff.info.rdPtr = LoopBuff_GetNextPtr(&gpsBuff, gpsBuff.info.rdPtr); } // 将新数据加到最后 FRAM_BufferWrite(LoopBuff_GetDataPos(&gpsBuff, gpsBuff.info.wtPtr), (uint8_t *) gps, sizeof(gps_data_t)); gpsBuff.info.wtPtr = nextPtr; // 保存到铁电 FRAM_SaveInfo(gpsBuff.info_base, (uint8_t *) &gpsBuff.info, sizeof(gpsBuff.info)); GPS_LastTime = gps->time; } } // 将一个数据加入队列 void GPRS_PutToQueue(loopbuff_t *lpBuff, data_dtu_t *dtuData, data_sample_t *sampleData) { uint16_t nextPtr; S_RTC_TIME_DATA_T sRTC; gprs_data_t *gprs; // 移动写指针 nextPtr = LoopBuff_GetNextPtr(lpBuff, lpBuff->info.wtPtr); // 如果队列已满 if(nextPtr == lpBuff->info.rdPtr) { // 移动读指针(丢弃第一条数据) lpBuff->info.rdPtr = LoopBuff_GetNextPtr(lpBuff, lpBuff->info.rdPtr); } // 将新数据加到最后 gprs = &gprsRWBuf; // 获取当前时间 RTC_GetDateAndTime(&sRTC); // 计算自上次gps定位以来的时间 gprs->sample_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); gprs->dtuData = *dtuData; gprs->sampleData = *sampleData; FRAM_BufferWrite(LoopBuff_GetDataPos(lpBuff, lpBuff->info.wtPtr), (uint8_t *) gprs, sizeof(gprs_data_t)); lpBuff->info.wtPtr = nextPtr; } // 将前面几条数据移出队列 void GPS_MoveFromQueue(uint8_t count) { LoopBuff_RemoveItems(&gpsBuff, count); // 保存到铁电 FRAM_SaveInfo(gpsBuff.info_base, (uint8_t *) &gpsBuff.info, sizeof(gpsBuff.info)); } // 查找队列前面的数据, 找出时间间隔相同的一组,最多max_count条 // 本函数在调用的地方加锁,因为这个函数返回以后接着要取数据 uint8_t GPS_LookData(uint8_t max_count, uint16_t *interval, uint8_t *done) { uint8_t count = 0; uint8_t i; uint16_t gps_count = 0, nextPtr; gps_data_t gps0, gps1; *interval = 0; *done = 1; if(max_count < 1) return 0; // 获取未发送记录条数 gps_count = LoopBuff_GetCount(&gpsBuff); if(gps_count < 2) return gps_count; count = 2; FRAM_BufferRead(LoopBuff_GetDataPos(&gpsBuff, gpsBuff.info.rdPtr), (uint8_t *) &gps0, sizeof(gps_data_t)); nextPtr = LoopBuff_GetNextPtr(&gpsBuff, gpsBuff.info.rdPtr); FRAM_BufferRead(LoopBuff_GetDataPos(&gpsBuff, nextPtr), (uint8_t *) &gps1, sizeof(gps_data_t)); *interval = GPS_CalcInterval(&gps1.time, &gps0.time); for(i = 2; count < max_count && i < gps_count; i++) { // 如果后面的时间间隔不一样 gps0 = gps1; nextPtr = LoopBuff_GetNextPtr(&gpsBuff, nextPtr); FRAM_BufferRead(LoopBuff_GetDataPos(&gpsBuff, nextPtr), (uint8_t *) &gps1, sizeof(gps_data_t)); if(GPS_CalcInterval(&gps1.time, &gps0.time) != *interval) break; count++; } if(i < gps_count) *done = 0; return count; } // 将采集数据中的传感器状态转换为蓝牙协议中的状态 static uint8_t Bluetooth_ConvertStat(sensor_status_t *pStat) { if(pStat->notConnect) return 3; if(pStat->overFlow) return 1; if(pStat->underFlow) return 2; return 0; } // GPS uart void UART1_IRQHandler(void) { uint8_t u8DTU; if(UART_GET_INT_FLAG(UART1, UART_ISR_RDA_IS_Msk) || UART_GET_INT_FLAG(UART1, UART_ISR_RTO_IS_Msk)) /* Rx Ready or Time-out INT*/ { // do { u8DTU = UART1->RBR; // printf("%c", u8DTU); // 直接处理 DTU_Task0(u8DTU); } //while(UART_IS_RX_READY(UART1)); } if(UART_GET_INT_FLAG(UART1, UART_ISR_BUF_ERR_IS_Msk)) /* Buffer Error INT */ { UART_ClearIntFlag(UART1, UART_ISR_BUF_ERR_IS_Msk); } if(UART_GET_INT_FLAG(UART1, UART_ISR_RLS_IS_Msk)) /* RLS INT */ { UART_ClearIntFlag(UART1, UART_ISR_RLS_IS_Msk); } } // GSM uart void SC1_IRQHandler(void) { uint8_t u8DTU; if(SCUART_GET_INT_FLAG(SC1, SC_ISR_RDA_IS_Msk) || SCUART_GET_INT_FLAG(SC1, SC_ISR_RTMR_IS_Msk)) /* Rx Ready or Time-out INT*/ { SCUART_CLR_INT_FLAG(SC1, SC_ISR_RDA_IS_Msk | SC_ISR_RTMR_IS_Msk); //do { u8DTU = SC1->RBR; // if(u8DTU == '\n') // printf("\\n\n"); // else if(u8DTU == '\r') // printf("\\r"); // else // printf("%c", u8DTU); // 加入缓冲 LoopBuff_PutItem(&DTU_TaskM, &u8DTU); }// while(SCUART_IS_RX_READY(SC1)); } if(SCUART_GET_INT_FLAG(SC1, SC_ISR_TERR_IS_Msk)) { SCUART_CLR_INT_FLAG(SC1, SC_ISR_TERR_IS_Msk); } } void DTU_Init() { /* 配置GSM端口 */ /* Select SC UART module clock source as HXT and UART module clock divider as 1 */ CLK_SetModuleClock(SC1_MODULE, CLK_CLKSEL2_SC_S_HXT, CLK_SC1_CLK_DIVIDER(1)); /*---------------------------------------------------------------------------------------------------------*/ /* Init I/O Multi-function */ /*---------------------------------------------------------------------------------------------------------*/ /* Set PC.0 and PC.1 pin for SC UART mode */ SYS->PC_L_MFP &= ~(SYS_PC_L_MFP_PC0_MFP_Msk | SYS_PC_L_MFP_PC1_MFP_Msk); SYS->PC_L_MFP |= (SYS_PC_L_MFP_PC0_MFP_SC1_CLK | SYS_PC_L_MFP_PC1_MFP_SC1_DAT); /* Enable SC UART module clock */ CLK_EnableModuleClock(SC1_MODULE); /* 配置GPS端口: GPS和Debug共用一个串口,GPS用到输入,DEBUG用到输出 */ } void DTU_Open() { // 分配扩展内存 // DTU_gpsData[0] = (char *) SRAM_Alloc(DTU_GPSDATA_SIZE); // DTU_gpsData[1] = (char *) SRAM_Alloc(DTU_GPSDATA_SIZE); // DTU_recvBuff = (char *) SRAM_Alloc(DTU_RECVBUFF_SIZE); // Task_sendBuff = (uint8_t *) SRAM_Alloc(TASK_SENDBUFF_SIZE); // Task_recvBuff = (uint8_t *) SRAM_Alloc(TASK_RECVBUFF_SIZE); LoopBuff_Create(&gpsBuff, sizeof(gps_data_t), FRAM_GPS_DATA_COUNT, FRAM_GPS_INFO_BASE, FRAM_GPS_DATA_BASE); LoopBuff_Create(&gprsBuff, sizeof(gprs_data_t), FRAM_GPRS_DATA_COUNT, FRAM_GPRS_INFO_BASE, FRAM_GPRS_DATA_BASE); LoopBuff_Create(&bd_gprsBuff, sizeof(gprs_data_t), FRAM_BD_GPRS_DATA_COUNT, FRAM_GPRS_BD_INFO_BASE, FRAM_GPRS_BD_DATA_BASE); LoopBuff_Create(&DTU_TaskM, sizeof(uint8_t), DTU_TASKM_DATA_COUNT, 0, (uint32_t) DTU_TaskM_Data); /*---------------------------------------------------------------------------------------------------------*/ /* Init UART */ /*---------------------------------------------------------------------------------------------------------*/ /* 打开GSM端口 */ SYS_ResetModule(SC1_RST); /* Configure UART0 and set UART0 baud rate */ SCUART_Open(SC1, 115200); /* 打开GPS端口: GPS和Debug共用一个串口,GPS用到输入,DEBUG用到输出 */ /* Enable RDA\RLS\Time-out Interrupt */ SCUART_ENABLE_INT(SC1, (SC_IER_RDA_IE_Msk)); // | SC_IER_RTMR_IE_Msk));// | SC_IER_TERR_IE_Msk)); UART_ENABLE_INT(UART1, (UART_IER_RDA_IE_Msk | UART_IER_BUF_ERR_IE_Msk | UART_IER_RLS_IE_Msk)); // | UART_IER_RTO_IE_Msk)); /* Enable SC1 interrupt */ NVIC_SetPriority(SC1_IRQn, 1); NVIC_EnableIRQ(SC1_IRQn); NVIC_SetPriority(UART1_IRQn, 1); NVIC_EnableIRQ(UART1_IRQn); } // 清空无效数据 static void DTU_ClearQueue() { uint8_t timeOut; uint32_t timeOutTick; do { timeOut = 1; timeOutTick = GetDelayTick(500); while(!IsTickOut(timeOutTick)) { if(LoopBuff_GetCount(&DTU_TaskM)) { timeOut = 0; break; } } LoopBuff_Clear(&DTU_TaskM); } while(!timeOut); } // 等待DTU命令的返回,检查期待的结果字符串 uint32_t DTU_ParseResult(char *checkPattern, char *checkErrPattern, char *resultBuff, uint16_t waitSeconds) { uint8_t done = 0, timeOut; uint32_t timeOutTick; uint8_t u8DTU; uint16_t count, idx = 0; uint32_t ret = FALSE; uint8_t strLen = strlen(checkPattern); uint8_t errLen = strlen(checkErrPattern); memset(DTU_recvBuff, 0, DTU_RECVBUFF_SIZE); // 检测返回信息 do { timeOut = 1; timeOutTick = GetDelayTick(waitSeconds * 1000); while(!IsTickOut(timeOutTick)) { // 喂狗 if(!Wakeup_Sleeping) WDT_RESET_COUNTER(); if(LoopBuff_GetCount(&DTU_TaskM)) { timeOut = 0; break; } } if(!timeOut) { count = LoopBuff_GetCount(&DTU_TaskM); while(count--) { // 取数据 memmove(&u8DTU, LoopBuff_GetDataPtr(&DTU_TaskM, DTU_TaskM.info.rdPtr), 1); LoopBuff_RemoveItems(&DTU_TaskM, 1); // if(u8DTU == '\n') // printf("\\n"); // else if(u8DTU == '\r') // printf("\\r"); // else // printf("%c", u8DTU); // 如果是检测发送的提示符(>),直接返回成功 if(strcmp(checkPattern, ">") == 0 && u8DTU == '>') { strcpy(resultBuff, ">"); ret = TRUE; done = 1; break; } // 换行符 if(u8DTU == '\n') { // 丢掉\n前面的\r if(idx > 0 && DTU_recvBuff[idx - 1] == '\r') DTU_recvBuff[--idx] = 0; // 先检查字符串(电话号码没有特征字符串) if((strLen > 0 && strstr(DTU_recvBuff, checkPattern)) || (strLen == 0 && idx > 0)) { DTU_recvBuff[idx] = 0; strcpy(resultBuff, DTU_recvBuff); ret = TRUE; done = 1; break; } // 检查返回错误的字符串 if(errLen > 0 && strstr(DTU_recvBuff, checkErrPattern)) { DTU_recvBuff[idx] = 0; strcpy(resultBuff, DTU_recvBuff); ret = FALSE; done = 1; break; } // 没有所要的字符串,清空 memset(DTU_recvBuff, 0, DTU_RECVBUFF_SIZE); idx = 0; continue; } if(idx < DTU_RECVBUFF_SIZE) DTU_recvBuff[idx++] = u8DTU; } } } while(!done && !timeOut); return ret; } // 执行命令,等待结果 uint32_t DTU_ExecuteCmd(char *cmd, char *checkPattern, char *checkErrPattern, char *resultBuff, uint16_t waitSeconds) { uint32_t ret = FALSE; // 检查并及时打开GPS电源 if(DTU_needCheckGPS) DTU_CheckGPS(); if(DTU_hasPowered) { // 唤醒 // SCUART_Write(SC1, (uint8_t *) "AT\r", 3); // delay_ms(5); printf("\n=> %s\n", cmd); // 清空数据 DTU_ClearQueue(); // 发送命令, 并附加回车换行符 SCUART_Write(SC1, (uint8_t *) cmd, strlen(cmd)); SCUART_Write(SC1, (uint8_t *) "\r", 1); // 等待结果 ret = DTU_ParseResult(checkPattern, checkErrPattern, resultBuff, waitSeconds); } return ret; } // 等待服务器端返回(至少len个字节,最多size个字节),直到收完或超时 // 返回值为实际收到的数据长度 uint16_t DTU_WaitResponse(uint8_t ssl, uint16_t len, uint8_t *buff, uint16_t size, uint16_t waitSeconds) { uint8_t timeOut; uint32_t timeOutTick; uint8_t u8DTU, phase; uint16_t i, count, data_count; uint16_t preidx, idx; char cntbuff[40], prebuff[40], *p, *p1; // 等待返回数据 idx = 0; memset(prebuff, 0, sizeof(prebuff)); preidx = 0; phase = 0; do { timeOut = 1; timeOutTick = GetDelayTick(idx == 0 ? waitSeconds * 1000 : 1000); while(!IsTickOut(timeOutTick)) { // 喂狗 if(!Wakeup_Sleeping) WDT_RESET_COUNTER(); if(LoopBuff_GetCount(&DTU_TaskM)) { timeOut = 0; break; } } if(!timeOut) { count = LoopBuff_GetCount(&DTU_TaskM); while(count--) { // 取数据 memmove(&u8DTU, LoopBuff_GetDataPtr(&DTU_TaskM, DTU_TaskM.info.rdPtr), 1); LoopBuff_RemoveItems(&DTU_TaskM, 1); // if(u8DTU == '\n') // printf("\\n"); // else if(u8DTU == '\r') // printf("\\r"); // else if(isprint(u8DTU)) // printf("%c", u8DTU); // else // printf("[%02X]", u8DTU); if(phase == 0) { // 接收URC消息错误 if(preidx >= sizeof(prebuff) - 1) return 0; prebuff[preidx++] = u8DTU; if(u8DTU == '\n') { if(!ssl) p = strstr(prebuff, "+QIURC: \"recv\",0,"); else p = strstr(prebuff, "+QSSLURC: \"recv\",1,"); if(p) // 获取数据长度 { p += (ssl ? 19 : 17); p1 = strstr(p, "\r\n"); // 接收URC消息错误 if(!p1 || p1 >= p + sizeof(cntbuff)) return 0; memset(cntbuff, 0, sizeof(cntbuff)); strncpy(cntbuff, p, p1 - p); data_count = atoi(cntbuff); phase = 1; } else { memset(prebuff, 0, sizeof(prebuff)); preidx = 0; } } } else if(idx < size) { if(data_count--) buff[idx++] = u8DTU; if(data_count == 0) { memset(prebuff, 0, sizeof(prebuff)); preidx = 0; phase = 0; } } } } } while(idx < size && !timeOut); if(!ssl) { printf("\nresponse from server (%d bytes):\n", idx); for(i = 0; i < idx && i < 128; i++) printf("%02X ", buff[i]); if(idx > 128) printf("..."); printf("\n"); } if(idx < len) strcpy(dcBuff.powerInfo.gprsFailCode, "RECV"); else { // 不清除错误代码(始终保留最近一次的错误代码) // strcpy(dcBuff.powerInfo.gprsFailCode, ""); } return idx; } // 模块DEACT uint8_t DTU_Shutdown() { uint8_t ret = 0; char buff[40]; // 设置标志 DTU_imeiRead = 0; DTU_simCard = 0; DTU_simReg = 0; DTU_gprsReg = 0; DTU_gprsAttached = 0; DTU_linkEstablished = 0; DTU_sslConfig = 0; DTU_mqttConfig = 0; DTU_ipFetched = 0; DTU_fail_count = 0; dcBuff.dtuData.connected = 0; DTU_shutdown_count++; if(DTU_ExecuteCmd("AT+QIDEACT=1", "OK", "ERROR", buff, DTU_tmrQPendSpec)) { strcpy(DTU_APN, ""); printf("\nDTU shutdown.\n"); ret = 1; } else printf("\nDTU shutdown failed.\n"); return ret; } // 发送数据, 等待服务器返回 uint32_t DTU_SendAndRecv(uint8_t ssl, uint8_t *data, uint16_t len, uint16_t *recvLen, uint8_t *recvBuff, uint16_t recvSize) { char cmd[40], buff[40]; int8_t try_count = 2; uint32_t ret = TRUE; uint16_t rlen = *recvLen; uint16_t totalLen = 0, rslen; S_RTC_TIME_DATA_T sRTC; // 唤醒 // SCUART_Write(SC1, (uint8_t *) "AT\r", 3); // delay_ms(5); // 清空数据 DTU_ClearQueue(); // EC20一次最多只能发送1460字节 while(totalLen < len) { if(len - totalLen > 1460) rslen = 1460; else rslen = len - totalLen; // 发送命令, 并附加回车换行符 if(!ssl) sprintf(cmd, "AT+QISEND=0,%d", rslen); else sprintf(cmd, "AT+QSSLSEND=1,%d", rslen); do { ret = FALSE; SCUART_Write(SC1, (uint8_t *) cmd, strlen(cmd)); SCUART_Write(SC1, (uint8_t *) "\r", 1); if(DTU_ParseResult(">", "", buff, DTU_tmrQPendShort)) { delay_ms(10); SCUART_Write(SC1, data + totalLen, rslen); ret = DTU_ParseResult("SEND OK", "SEND FAIL", buff, DTU_tmrQPendSpec); } if(ret) { totalLen += rslen; break; } delay_ms(200); } while(--try_count > 0); if(!ret) { strcpy(dcBuff.powerInfo.gprsFailCode, "SEND"); break; } } if(ret && rlen > 0) { do { rslen = DTU_WaitResponse(ssl, rlen, recvBuff, recvSize, DTU_tmrQPendSpec); memmove(recvLen, &rslen, 2); ret = (rslen >= rlen); if(ret) break; delay_ms(200); } while(--try_count > 0); } if(ret) { DTU_fail_count = 0; DTU_shutdown_count = 0; printf("\nSend %d bytes ok\n", len); // 记录发送成功的时间 RTC_GetDateAndTime(&sRTC); DTU_succTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); return TRUE; } printf("\nSend failed\n"); // 如果2次失败,模块关机/关电 if(++DTU_fail_count >= 2) { if(DTU_shutdown_count >= 1 || !DTU_Shutdown()) DTU_PowerOff(); } return FALSE; } // 打开GPS功能 uint32_t DTU_EnableGPS() { char cmd[50], buff[50]; uint8_t try_count = 2; static uint8_t first = 1; // 禁止重启GPS DTU_needCheckGPS = 0; if(!IS_VCC_GPS_ON()) { VCC_GPS_ON(); delay_ms(2500); } // DTU_ExecuteCmd("AT+QGPSDEL=3", "OK", "ERROR", buff, DTU_tmrQPendShort); // DTU_ExecuteCmd("AT+QGPSXTRA=0", "OK", "ERROR", buff, DTU_tmrQPendShort); // return FALSE; #if 0 // 检查QGPSXTRA if(!DTU_ExecuteCmd("AT+QGPSXTRA?", "+QGPSXTRA: 1", "+QGPSXTRA: 0", buff, DTU_tmrQPendShort)) { // 如果没有, 则设置并重启 if(DTU_ExecuteCmd("AT+QGPSXTRA=1", "OK", "ERROR", buff, DTU_tmrQPendShort)) { DTU_PowerOff(); delay_ms(200); NVIC_SystemReset(); } } // 检查QGPSXTRADATA if(DTU_ExecuteCmd("AT+QGPSXTRADATA?", "+QGPSXTRADATA: ", "ERROR", buff, DTU_tmrQPendShort) && strstr(buff, "+QGPSXTRADATA: 0,")) { // 先删除内存文件 DTU_ExecuteCmd("AT+QFDEL=\"RAM:xtra2.bin\"", "OK", "ERROR", buff, DTU_tmrQPendShort); // 下载XTRADATA if(Sim808_GPRSDial() && DTU_ExecuteCmd("AT+QHTTPCFG=\"contextid\",1", "OK", "ERROR", buff, DTU_tmrQPendShort) && DTU_ExecuteCmd("AT+QHTTPCFG=\"responseheader\",0", "OK", "ERROR", buff, DTU_tmrQPendShort) && DTU_ExecuteCmd("AT+QHTTPURL=40,10", "CONNECT", "ERROR", buff, DTU_tmrQPendShort) ) { strcpy(cmd, "http://xtrapath1.izatcloud.net/xtra2.bin"); SCUART_Write(SC1, (uint8_t *) cmd, strlen(cmd)); if(DTU_ParseResult("OK", "ERROR", buff, DTU_tmrQPendShort) && DTU_ExecuteCmd("AT+QHTTPGET=80", "+QHTTPGET: 0,", "ERROR", buff, DTU_tmrQPendSpec) && DTU_ExecuteCmd("AT+QHTTPREADFILE=\"RAM:xtra2.bin\",80", "+QHTTPREADFILE: 0", "ERROR", buff, DTU_tmrQPendSpec) && DTU_ExecuteCmd("AT+QLTS=2", "+QLTS: ", "ERROR", buff, DTU_tmrQPendShort) // Get UTC time ) { // 获取时间 memset(cmd, 0, sizeof(cmd)); strncpy(cmd, strstr(buff, "+QLTS: \"") + 8, 19); // 注入时间、XTRADATA sprintf(buff, "AT+QGPSXTRATIME=0,\"%s\",1,1,3500", cmd); // Inject UTC time strcpy(cmd, buff); if(DTU_ExecuteCmd(cmd, "OK", "ERROR", buff, DTU_tmrQPendShort) && DTU_ExecuteCmd("AT+QGPSXTRADATA=\"RAM:xtra2.bin\"", "OK", "ERROR", buff, DTU_tmrQPendShort) ) { printf("\nGPS XTRADATA Injected.\n"); } } } } #endif while(try_count--) { delay_ms(200); // 先停止GPS定位 if(DTU_ExecuteCmd("AT+QGPSEND", "OK", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nGPS disabled.\n"); delay_ms(200); } // 查询当前输出端口是否为uartdebug if(first || !DTU_ExecuteCmd("AT+QGPSCFG=\"outport\"", "+QGPSCFG:", "ERROR", buff, DTU_tmrQPendShort) || strstr(buff, "uartdebug") == 0) { // 设置当前输出端口为uartdebug if(!DTU_ExecuteCmd("AT+QGPSCFG=\"outport\",\"uartdebug\"", "OK", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nSet GPS outport failed.\n"); continue; } first = 0; } if(DTU_ExecuteCmd("AT+QGPS=1,255,50,0,4", "OK", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nGPS enabled.\n"); // 允许重启GPS DTU_needCheckGPS = 1; return TRUE; } } printf("\nGPS enable failed.\n"); // 允许重启GPS DTU_needCheckGPS = 1; return FALSE; } // 模块上电,等1秒钟才能发送命令 void DTU_PowerOn() { char buff[40]; S_RTC_TIME_DATA_T sRTC; uint8_t try_count = 2; if(!DTU_hasPowered) { printf("\nDTU power on ...\n"); delay_ms(200); VCC_GSM_ON(); // delay_ms(10000); DTU_ParseResult("RDY", "", buff, DTU_tmrQPendShort * 3); // 获取当前时间 RTC_GetDateAndTime(&sRTC); // 重设自上次gps定位以来的时间 DTU_gpsTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); // 设置标志 DTU_hasPowered = 1; // 关闭命令回显 while(try_count--) { if(DTU_ExecuteCmd("ATE0", "OK", "", buff, DTU_tmrQPendShort)) { printf("\nDTU echo off.\n"); break; } printf("\nDTU echo off failed.\n"); delay_ms(2000); } // 版本 if(DTU_ExecuteCmd("ATI", "Revision: ", "", buff, DTU_tmrQPendShort)) printf("\n%s\n", buff); if(GPS_Waiting || dcBuff.configDisplay.op_SEND_GPS_DATA) { if(try_count > 0) delay_ms(2000); // 在这里主动打开GPS DTU_EnableGPS(); } } } // 关闭GPS功能 void DTU_DisableGPS() { char buff[50]; if(IS_VCC_GPS_ON()) { VCC_GPS_OFF(); if(DTU_ExecuteCmd("AT+QGPSEND", "OK", "ERROR", buff, DTU_tmrQPendShort)) printf("\nGPS disabled.\n"); else printf("\nGPS disable failed.\n"); } } // 模块关电 void DTU_PowerOff() { char buff[40]; // 禁止重启GPS DTU_needCheckGPS = 0; if(DTU_hasPowered) { // 关闭GPS DTU_DisableGPS(); if(DTU_ExecuteCmd("AT+QPOWD=1", "POWERED DOWN", "", buff, DTU_tmrQPendShort * 2)) printf("\nGPRS disconnected.\n"); else printf("\nGPRS disconnect failed.\n"); // 设置标志 DTU_hasPowered = 0; DTU_imeiRead = 0; DTU_simCard = 0; DTU_simReg = 0; DTU_gprsReg = 0; DTU_isATMode = 0; DTU_gprsAttached = 0; DTU_linkEstablished = 0; DTU_sslConfig = 0; DTU_mqttConfig = 0; DTU_ipFetched = 0; strcpy(DTU_APN, ""); DTU_isRMCFormat = 0; DTU_fail_count = 0; dcBuff.dtuData.connected = 0; DTU_shutdown_count = 0; printf("\nDTU power off ...\n"); VCC_GSM_OFF(); } } // 读取IMEI号码(测试4G模块是否正常) uint32_t DTU_ReadIMEI() { char buff[40]; uint8_t try_count = 2; if(DTU_imeiRead) return TRUE; while(try_count--) { if(DTU_ExecuteCmd("AT+GSN", "", "ERROR", buff, DTU_tmrQPendShort)) { if(strlen(buff) == 15) { DTU_imeiRead = 1; printf("\nThe IMEI is: %s\n", buff); return TRUE; } } delay_ms(200); } printf("\nRead IMEI failed.\n"); return FALSE; } // 检查sim card uint32_t DTU_CheckSimCard() { char buff[40]; uint8_t try_count = 4; if(DTU_simCard) return TRUE; while(try_count--) { if(DTU_ExecuteCmd("AT+CPIN?","+CPIN:", "", buff, DTU_tmrQPendShort) && strstr(buff, "+CPIN: READY")) { DTU_simCard = 1; printf("\nSim card ready.\n"); return TRUE; } delay_ms(200); } DTU_simReg = 0; DTU_gprsReg = 0; DTU_gprsAttached = 0; DTU_linkEstablished = 0; DTU_sslConfig = 0; DTU_mqttConfig = 0; DTU_ipFetched = 0; printf("\nSim card not ready.\n"); return FALSE; } // 检查GPRS附着情况:最多等40秒 uint32_t DTU_CheckGprs() { char buff[40]; uint32_t check_time; S_RTC_TIME_DATA_T sRTC; if(DTU_gprsAttached) return TRUE; // 获取当前时间 RTC_GetDateAndTime(&sRTC); check_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); DTU_ExecuteCmd("AT+CGATT=1", "OK", "ERROR", buff, DTU_tmrQPendLong); do { if(DTU_ExecuteCmd("AT+CGATT?", "+CGATT: 1", "+CGATT: 0", buff, DTU_tmrQPendShort)) { DTU_gprsAttached = 1; printf("\nGprs attached.\n"); return TRUE; } delay_ms(1000); RTC_GetDateAndTime(&sRTC); } while(Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) < check_time + 120); DTU_gprsAttached = 0; DTU_linkEstablished = 0; DTU_sslConfig = 0; DTU_mqttConfig = 0; DTU_ipFetched = 0; printf("\nGprs not attached.\n"); // 如果1次失败,模块关机/关电 if(++DTU_fail_count >= 1) { if(DTU_shutdown_count >= 1 || !DTU_Shutdown()) DTU_PowerOff(); } return FALSE; } char *DTU_DecideAPN() { if(strncmp(dcBuff.powerInfo.simNumber, "898604", 6) == 0) return "CMIOT"; if(strncmp(dcBuff.powerInfo.simNumber, "898607", 6) == 0) return "CMIOT"; if(strncmp(dcBuff.powerInfo.simNumber, "898602", 6) == 0) return "CMIOT"; if(strncmp(dcBuff.powerInfo.simNumber, "898600", 6) == 0) return "CMIOT"; if(strncmp(dcBuff.powerInfo.simNumber, "898608", 6) == 0) return "CMIOT"; if(strcmp(dcBuff.configDisplay.APN, "CMNET") == 0) return "CMIOT"; return dcBuff.configDisplay.APN; } // 设置APN uint32_t DTU_SetAPN(char *APN) { char cmd[50], buff[40]; uint8_t try_count = 2; if(strcmp(DTU_APN, APN) == 0) return TRUE; while(try_count--) { sprintf(cmd, "AT+QICSGP=1,1,\"%s\",\"\",\"\"", APN); if(DTU_ExecuteCmd(cmd, "OK", "ERROR", buff, DTU_tmrQPendShort)) { strcpy(DTU_APN, APN); printf("\nSet APN to \"%s\".\n", APN); return TRUE; } delay_ms(200); } printf("\nSet APN failed.\n"); return FALSE; } // 建立无线链路 uint32_t DTU_EstablishLink() { char buff[40]; uint8_t try_count = 2; if(DTU_linkEstablished) return TRUE; while(try_count--) { if(DTU_ExecuteCmd("AT+QIACT=1", "OK", "ERROR", buff, DTU_tmrQPendLong)) { DTU_linkEstablished = 1; printf("\nGprs link established\n"); // DTU_ExecuteCmd("AT+QIDNSCFG=1", "OK", "ERROR", buff, DTU_tmrQPendShort); return TRUE; } delay_ms(200); } DTU_ipFetched = 0; printf("\nGprs link not established.\n"); // 如果2次失败,模块关机/关电 if(++DTU_fail_count >= 1) { if(DTU_shutdown_count >= 1 || !DTU_Shutdown()) DTU_PowerOff(); } return FALSE; } uint32_t DTU_ConfigSSL() { char cmd[40], buff[40]; if(DTU_sslConfig) return TRUE; // 检查、上传CA证书 while(!DTU_ExecuteCmd("AT+QFLST=\"RAM:ca_cert.pem\"", "+QFLST: \"RAM:ca_cert.pem\"", "ERROR", buff, DTU_tmrQPendShort)) { sprintf(cmd, "AT+QFUPL=\"RAM:ca_cert.pem\",%d", strlen(ca_cert)); if(DTU_ExecuteCmd(cmd, "CONNECT", "ERROR", buff, DTU_tmrQPendShort)) { SCUART_Write(SC1, (uint8_t *) ca_cert, strlen(ca_cert)); if(DTU_ParseResult("+QFUPL:", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nca_cert.pem uploaded\n"); break; } } printf("\nca_cert.pem upload failed\n"); return FALSE; } // 检查、上传CLIENT证书 while(!DTU_ExecuteCmd("AT+QFLST=\"RAM:client_cert.pem\"", "+QFLST: \"RAM:client_cert.pem\"", "ERROR", buff, DTU_tmrQPendShort)) { sprintf(cmd, "AT+QFUPL=\"RAM:client_cert.pem\",%d", strlen(client_cert)); if(DTU_ExecuteCmd(cmd, "CONNECT", "ERROR", buff, DTU_tmrQPendShort)) { SCUART_Write(SC1, (uint8_t *) client_cert, strlen(client_cert)); if(DTU_ParseResult("+QFUPL:", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nclient_cert.pem uploaded\n"); break; } } printf("\nclient_cert.pem upload failed\n"); return FALSE; } // 检查、上传CLIENT密钥 while(!DTU_ExecuteCmd("AT+QFLST=\"RAM:client_key.pem\"", "+QFLST: \"RAM:client_key.pem\"", "ERROR", buff, DTU_tmrQPendShort)) { sprintf(cmd, "AT+QFUPL=\"RAM:client_key.pem\",%d", strlen(client_key)); if(DTU_ExecuteCmd(cmd, "CONNECT", "ERROR", buff, DTU_tmrQPendShort)) { SCUART_Write(SC1, (uint8_t *) client_key, strlen(client_key)); if(DTU_ParseResult("+QFUPL:", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nclient_key.pem uploaded\n"); break; } } printf("\nclient_key.pem upload failed\n"); return FALSE; } if(!DTU_ExecuteCmd("AT+QSSLCFG=\"ignorelocaltime\",1,1", "OK", "ERROR", buff, DTU_tmrQPendShort)) return FALSE; if(!DTU_ExecuteCmd("AT+QSSLCFG=\"sslversion\",1,4", "OK", "ERROR", buff, DTU_tmrQPendShort)) return FALSE; if(!DTU_ExecuteCmd("AT+QSSLCFG=\"ciphersuite\",1,0xFFFF", "OK", "ERROR", buff, DTU_tmrQPendShort)) return FALSE; if(!DTU_ExecuteCmd("AT+QSSLCFG=\"seclevel\",1,2", "OK", "ERROR", buff, DTU_tmrQPendShort)) return FALSE; if(!DTU_ExecuteCmd("AT+QSSLCFG=\"cacert\",1,\"RAM:ca_cert.pem\"", "OK", "ERROR", buff, DTU_tmrQPendShort)) return FALSE; if(!DTU_ExecuteCmd("AT+QSSLCFG=\"clientcert\",1,\"RAM:client_cert.pem\"", "OK", "ERROR", buff, DTU_tmrQPendShort)) return FALSE; if(!DTU_ExecuteCmd("AT+QSSLCFG=\"clientkey\",1,\"RAM:client_key.pem\"", "OK", "ERROR", buff, DTU_tmrQPendShort)) return FALSE; DTU_sslConfig = 1; return TRUE; } uint32_t DTU_ConfigMQTT() { char cmd[100], buff[40], psn[14]; if(DTU_mqttConfig) return TRUE; sprintf(psn, "20%02d%02d%02d%02d%03d", dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], dcBuff.configBottle.PSN[2], dcBuff.configBottle.PSN[3], (dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5]); // 每次重连服务器,需要重新订阅topic if(!DTU_ExecuteCmd("AT+QMTCFG=\"session\",0,1", "OK", "ERROR", buff, DTU_tmrQPendShort)) return FALSE; // URC只报长度,不报内容 if(!DTU_ExecuteCmd("AT+QMTCFG=\"recv/mode\",0,1,1", "OK", "ERROR", buff, DTU_tmrQPendShort)) return FALSE; // 阿里云授权码 // sprintf(cmd, "AT+QMTCFG=\"aliauth\",0,\"%s\",\"%s\",\"%s\"", // aliyunSecret.product, aliyunSecret.device, aliyunSecret.secret); // if(!DTU_ExecuteCmd(cmd, "OK", "ERROR", buff, DTU_tmrQPendShort)) // return FALSE; DTU_mqttConfig = 1; return TRUE; } // 获取基站定位经纬度 uint32_t DTU_GetCellLocPosition() { char buff[40]; uint8_t try_count = 2; char *p, *p1 = NULL; // 查询当前multi PDNs是否enabled(默认enabled) // if(!DTU_ExecuteCmd("AT+QCFG=\"PDP/DuplicateChk\"", "+QCFG: \"pdp/duplicatechk\"", "ERROR", buff, DTU_tmrQPendShort) // || strstr(buff, ",1") == 0) // { // // 设置当前multi PDNs为enabled // if(!DTU_ExecuteCmd("AT+QCFG=\"PDP/DuplicateChk\",1", "OK", "ERROR", buff, DTU_tmrQPendShort)) // { // printf("\nSet multi PDNs failed.\n"); // return FALSE; // } // } // // 查询当前contextid是否为1(默认为1) // if(!DTU_ExecuteCmd("AT+QLOCCFG=\"contextid\"", "+QLOCCFG: \"contextid\"", "ERROR", buff, DTU_tmrQPendShort) // || strstr(buff, ",1") == 0) // { // // 设置当前contextid为1 // if(!DTU_ExecuteCmd("AT+QLOCCFG=\"contextid\",1", "OK", "ERROR", buff, DTU_tmrQPendShort)) // { // printf("\nSet Cell-Loc contextid failed.\n"); // return FALSE; // } // } // 设置token(默认为空) if(!DTU_ExecuteCmd("AT+QLOCCFG=\"token\"", "+QLOCCFG: \"token\"", "ERROR", buff, DTU_tmrQPendShort) || strstr(buff, "exist") == 0) { if(!DTU_ExecuteCmd("AT+QLOCCFG=\"token\",\"u3S224CX18r4O045\"", "OK", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nSet Cell-Loc token failed.\n"); return FALSE; } } // 查询当前基站定位服务器是否为www.queclocator.com:80 if(!DTU_ExecuteCmd("AT+QLOCCFG=\"server\"", "+QLOCCFG: \"server\"", "ERROR", buff, DTU_tmrQPendShort) || strstr(buff, "www.queclocator.com:80") == 0) { // 设置当前基站定位服务器为www.queclocator.com:80 if(!DTU_ExecuteCmd("AT+QLOCCFG=\"server\",\"www.queclocator.com:80\"", "OK", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nSet Cell-Loc server failed.\n"); return FALSE; } } while(try_count--) { if(DTU_ExecuteCmd("AT+QCELLLOC", "+QCELLLOC: ", "ERROR", buff, DTU_tmrQPendSpec)) { p = strstr(buff, "+QCELLLOC: "); if(p) { p += 11; p1 = strstr(p, ","); if(p1) { dcBuff.dtuData.posState = 1; // 基站定位成功 *p1 = 0; dcBuff.dtuData.longitude = atof(p) * 1000000; p = p1 + 1; dcBuff.dtuData.latitude = atof(p) * 1000000; printf("\nLatitude:\t%10.6f\n", dcBuff.dtuData.latitude * 0.000001); printf("Longitude:\t%10.6f\n", dcBuff.dtuData.longitude * 0.000001); return TRUE; } } } // 有可能是原来的token不对,重新设一次 if(!DTU_ExecuteCmd("AT+QLOCCFG=\"token\",\"u3S224CX18r4O045\"", "OK", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nSet Cell-Loc token failed.\n"); return FALSE; } delay_ms(200); } printf("\nGet Cell-Loc position failed.\n"); return FALSE; } // 设置普通(AT命令,非透传)模式 // !!! 此命令在4G模块无效 !!! uint32_t DTU_SetATMode() { char buff[40]; uint8_t try_count = 2; if(DTU_isATMode) return TRUE; while(try_count--) { if(DTU_ExecuteCmd("AT+QIMODE=0","OK", "ERROR", buff, DTU_tmrQPendShort)) { DTU_isATMode = 1; printf("\nSet to AT cmd mode.\n"); return TRUE; } delay_ms(200); } printf("\nSet AT mode failed.\n"); return FALSE; } // 获得本机IP地址 uint32_t DTU_FetchIP() { char buff[40]; uint8_t try_count = 2; if(DTU_ipFetched) return TRUE; while(try_count--) { if(DTU_ExecuteCmd("AT+QIACT?", "+QIACT: 1,1", "+QIACT: 1,0", buff, DTU_tmrQPendShort)) { DTU_ipFetched = 1; printf("\nLocal ip is: %s\n", buff + 14); return TRUE; } delay_ms(200); } printf("\nFetch ip failed.\n"); return FALSE; } // 设置服务器格式为DNS // !!! 此命令在4G模块无效 !!! uint32_t DTU_SetDNSIP() { char buff[40]; uint8_t try_count = 2; while(try_count--) { if(DTU_ExecuteCmd("AT+QIDNSIP=1", "OK", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nSet remote server to domain name.\n"); return TRUE; } delay_ms(200); } printf("\nSet remote server to domain name failed.\n"); return FALSE; } // 连接服务器:Direct push mode uint32_t DTU_Connect(uint8_t ssl, char *server, short port) { char cmd[80], buff[40]; uint32_t ret = FALSE; uint8_t try_count = 1; while(try_count--) { if(!ssl) { sprintf(cmd, "AT+QIOPEN=1,0,\"TCP\",\"%s\",%d,0,1", server, port); if(!DTU_ExecuteCmd(cmd, "+QIOPEN: 0,", "ERROR", buff, DTU_tmrQPendSpec)) break; if(strstr(buff, "+QIOPEN: 0,0")) { ret = TRUE; break; } } else { sprintf(cmd, "AT+QSSLOPEN=1,1,1,\"%s\",%d,1", server, port); if(!DTU_ExecuteCmd(cmd, "+QSSLOPEN: 1,", "ERROR", buff, DTU_tmrQPendSpec)) break; if(strstr(buff, "+QSSLOPEN: 1,0")) { ret = TRUE; break; } } delay_ms(200); } if(ret) { dcBuff.dtuData.connected = 1; printf("\nConnect to %s: %d\n", server, port); return TRUE; } dcBuff.dtuData.connected = 0; printf("\nCan not connect to %s: %d\n", server, port); // 如果2次失败,模块关机/关电 if(++DTU_fail_count >= 2) { if(DTU_shutdown_count >= 1 || !DTU_Shutdown()) DTU_PowerOff(); } return FALSE; } // 关闭连接 uint32_t DTU_Close(uint8_t ssl) { char buff[40]; uint8_t try_count = 2; uint8_t ret; if(!dcBuff.dtuData.connected) return TRUE; dcBuff.dtuData.connected = 0; while(try_count--) { // 可能返回OK,也可能返回错误(如连接已关闭,或被服务器主动关闭),都视为关闭成功 if(!ssl) ret = DTU_ExecuteCmd("AT+QICLOSE=0", "OK", "ERROR", buff, DTU_tmrQPendSpec); else ret = DTU_ExecuteCmd("AT+QSSLCLOSE=1", "OK", "ERROR", buff, DTU_tmrQPendSpec); if(ret) { printf("\nConnection closed.\n"); return TRUE; } delay_ms(200); } printf("\nConnection close failed.\n"); return FALSE; } // 读取sim卡电话号码 uint32_t DTU_ReadPhoneNo() { char buff[40]; uint8_t try_count = 2; if(strlen(dcBuff.powerInfo.simNumber)) return TRUE; while(try_count--) { if(DTU_ExecuteCmd("AT+QCCID", "+QCCID: ", "ERROR", buff, DTU_tmrQPendShort)) { strcpy(dcBuff.powerInfo.simNumber, buff + 8); printf("\nThe phone no is: %s\n", dcBuff.powerInfo.simNumber); return TRUE; } delay_ms(200); } printf("\nRead phone no failed.\n"); return FALSE; } // 读取信号强度 uint32_t DTU_ReadRssi(uint8_t *rssi) { char buff[40]; uint8_t try_count = 6; char *pCSQ, *pCommon; uint8_t csq; *rssi = 0; while(try_count--) { if(DTU_ExecuteCmd("AT+CSQ", "+CSQ:", "ERROR", buff, DTU_tmrQPendShort)) { pCSQ = strstr(buff, "+CSQ: "); pCommon = strstr(buff, ","); if(pCommon) *pCommon = 0; // 将0~31的强度值转换为百分比 csq = atoi(pCSQ + 6); printf("\nThe CSQ is: %d\n", csq); if(csq != 99 && csq != 199) { if(csq < 100) { if(csq <= 31) *rssi = csq * 100 / 31; } else { if(csq <= 191) *rssi = csq - 100 + 9; } if(*rssi > 100) *rssi = 100; printf("\nThe rssi is: %d\n", *rssi); return TRUE; } } delay_ms(500); } printf("\nRead rssi failed.\n"); return FALSE; } // 读取入网标志 uint32_t DTU_ReadRegistry(uint8_t *reg) { char buff[40]; char *pReg; uint32_t check_time; uint16_t DTU_regTime = 60; uint8_t rssi = 0; S_RTC_TIME_DATA_T sRTC; if(DTU_simReg) { *reg = 1; return TRUE; } DTU_ReadRssi(&rssi); if(rssi >= 50) DTU_regTime = 150; // 获取当前时间 RTC_GetDateAndTime(&sRTC); check_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); *reg = 0; do { if(DTU_ExecuteCmd("AT+CREG?", "+CREG:", "ERROR", buff, DTU_tmrQPendShort)) { pReg = strstr(buff, ","); if(pReg) { *reg = *(pReg + 1) - '0'; if(*reg == 0) break; } //printf("\n%s\n", buff); if(*reg == 1 || *reg == 5) { printf("\nRegistry status: %d.\n", *reg); *reg = 1; DTU_simReg = 1; return TRUE; } } delay_ms(1000); RTC_GetDateAndTime(&sRTC); } while(Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) < check_time + DTU_regTime); printf("\nRegistry status: %d.\n", *reg); // 如果2次失败,模块关机/关电 if(++DTU_fail_count >= 2) { if(DTU_shutdown_count >= 1 || !DTU_Shutdown()) DTU_PowerOff(); } else { DTU_gprsReg = 0; DTU_gprsAttached = 0; DTU_linkEstablished = 0; DTU_sslConfig = 0; DTU_mqttConfig = 0; DTU_ipFetched = 0; } return FALSE; } // 读取GPRS入网标志 uint32_t DTU_ReadGPRSRegistry(uint8_t *reg) { char buff[40]; char *pReg; uint32_t check_time; S_RTC_TIME_DATA_T sRTC; if(DTU_gprsReg) { *reg = 1; return TRUE; } // 获取当前时间 RTC_GetDateAndTime(&sRTC); check_time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); *reg = 0; do { if(DTU_ExecuteCmd("AT+CGREG?", "+CGREG:", "", buff, DTU_tmrQPendShort)) { pReg = strstr(buff, ","); if(pReg) { *reg = *(pReg + 1) - '0'; if(*reg == 0) break; } if(*reg == 1 || *reg == 5) { printf("\nGPRS registry status: %d.\n", *reg); *reg = 1; DTU_gprsReg = 1; return TRUE; } } delay_ms(1000); RTC_GetDateAndTime(&sRTC); } while(Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) < check_time + 60); printf("\nGPRS registry status: %d.\n", *reg); return FALSE; } // 处理时差函数 void GPS_ProcessTimeLag(date_time_t *sysTime, int8_t timeLag) { // 处理时差:正时差 if(timeLag > 0) { sysTime->hour += timeLag; if(sysTime->hour >= 24) { sysTime->hour %= 24; if(sysTime->day < get_month_days(sysTime->year + 2000, sysTime->month)) sysTime->day++; else { sysTime->day = 1; if(sysTime->month < 12) sysTime->month++; else { sysTime->month = 1; sysTime->year++; } } } } // 处理时差:负时差 else if(timeLag < 0) { // hour是无符号数 if(sysTime->hour >= (-timeLag)) sysTime->hour += timeLag; else { sysTime->hour += (24 + timeLag); if(sysTime->day > 1) sysTime->day--; else { if(sysTime->month > 1) { sysTime->month--; sysTime->day = get_month_days(sysTime->year + 2000, sysTime->month); } else { sysTime->month = 12; sysTime->day = 31; sysTime->year--; } } } } } // 读取GPRS网络信息信息 uint32_t Sim808_ReadGPRS() { uint8_t val; printf("\nRead RSSI data ....\n"); DTU_PowerOn(); if(!DTU_ReadIMEI()) { strcpy(dcBuff.powerInfo.gprsFailCode, "EC20"); return FALSE; } if(!DTU_CheckSimCard()) { strcpy(dcBuff.powerInfo.gprsFailCode, "SIM"); return FALSE; } DTU_ReadPhoneNo(); if(!DTU_SetAPN(DTU_DecideAPN())) { strcpy(dcBuff.powerInfo.gprsFailCode, "APN"); return FALSE; } if(!DTU_ReadRegistry(&val)) { strcpy(dcBuff.powerInfo.gprsFailCode, "REG"); return FALSE; } dcBuff.dtuData.networked = (val == 1 ? 1 : 0); if(DTU_ReadRssi(&val)) dcBuff.dtuData.rssi = val; return TRUE; } void DTU_setOffsetSeconds() { char buff[40], *p; S_RTC_TIME_DATA_T sRTC; uint32_t totalSeconds1, totalSeconds2; int8_t zz; if(DTU_ExecuteCmd("AT+QLTS=2", "+QLTS: ", "ERROR", buff, DTU_tmrQPendShort)) // Get UTC time { // 获取当前时间 RTC_GetDateAndTime(&sRTC); totalSeconds1 = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); // UTC日期 p = strstr(buff, "+QLTS: \"") + 8; printf("\n%s\n", p); // 4位年份 p[4] = 0; sRTC.u32Year = atoi(p); p += 5; // 2位月份 p[2] = 0; sRTC.u32Month = atoi(p); p += 3; // 2位日期 p[2] = 0; sRTC.u32Day = atoi(p); p += 3; // 2位小时 p[2] = 0; sRTC.u32Hour = atoi(p); p += 3; // 2位分钟 p[2] = 0; sRTC.u32Minute = atoi(p); p += 3; // 2位秒 sRTC.u32Second = (*p - '0') * 10 + (*(p + 1) - '0'); p += 2; // 3位时差(按1/4小时, 带符号) p[3] = 0; zz = atoi(p); totalSeconds2 = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); // 将UTC时间转换为GMT时间(时差为0) totalSeconds2 -= zz * 900; // 将GMT时间转换为UTC时间(按配置的时差) totalSeconds2 += dcBuff.configData.timeLag * 3600; if(RTC_offsetSeconds == 0) RTC_offsetSeconds = totalSeconds2 - totalSeconds1; } } // GPRS拨号 uint32_t Sim808_GPRSDial() { uint8_t reg; printf("\nGPRS Dialing ....\n"); DTU_PowerOn(); if(!DTU_ReadIMEI()) { strcpy(dcBuff.powerInfo.gprsFailCode, "EC20"); return FALSE; } if(!DTU_CheckSimCard()) { strcpy(dcBuff.powerInfo.gprsFailCode, "SIM"); return FALSE; } if(!DTU_SetAPN(DTU_DecideAPN())) { strcpy(dcBuff.powerInfo.gprsFailCode, "APN"); return FALSE; } if(!DTU_ReadRegistry(®)) { strcpy(dcBuff.powerInfo.gprsFailCode, "REG"); return FALSE; } DTU_ReadGPRSRegistry(®); // if(!DTU_CheckGprs()) // { // strcpy(dcBuff.powerInfo.gprsFailCode, "GPRS"); // return FALSE; // } // if(!DTU_SetATMode()) // { // strcpy(dcBuff.powerInfo.gprsFailCode, "AT"); // return FALSE; // } if(!DTU_EstablishLink()) { strcpy(dcBuff.powerInfo.gprsFailCode, "ACT"); return FALSE; } // 修正时间基准(可显示绝对时间) if(RTC_offsetSeconds == 0) DTU_setOffsetSeconds(); if(RTC_offsetSeconds == 0) DTU_setOffsetSecondsFromServer(); return TRUE; } uint32_t Sim808_Connect(uint8_t ssl, char *server, int port) { if(!Sim808_GPRSDial()) return FALSE; // if(!DTU_FetchIP()) // { // strcpy(dcBuff.powerInfo.gprsFailCode, "IP"); // return FALSE; // } // if(!DTU_SetDNSIP()) // { // strcpy(dcBuff.powerInfo.gprsFailCode, "DNS"); // return FALSE; // } if(ssl && !DTU_ConfigSSL()) { strcpy(dcBuff.powerInfo.gprsFailCode, "SSL"); return FALSE; } printf("\nConnect to server....\n"); if(!DTU_Connect(ssl, server, port)) { strcpy(dcBuff.powerInfo.gprsFailCode, "CONN"); return FALSE; } return TRUE; } // 获取基站定位经纬度 uint32_t Sim808_GetCellLocPosition() { if(!Sim808_GPRSDial()) return FALSE; printf("\nGet Cell-Loc position....\n"); // 获取基站定位经纬度 return DTU_GetCellLocPosition(); } uint32_t Sim808_SendAndRecv(uint8_t ssl, uint8_t *data, uint16_t len, uint16_t *recvLen, uint8_t *recvBuff, uint16_t recvSize) { return DTU_SendAndRecv(ssl, data, len, recvLen, recvBuff, recvSize); } // EC20一次最多只能发送1500字节 uint32_t DTU_MqttPublish(uint8_t *data, uint16_t len) { static uint16_t msgid = 1; char cmd[100], buff[40], psn[14]; int8_t try_count = 2; S_RTC_TIME_DATA_T sRTC; sprintf(psn, "20%02d%02d%02d%02d%03d", dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], dcBuff.configBottle.PSN[2], dcBuff.configBottle.PSN[3], (dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5]); while(try_count--) { // 唤醒 // SCUART_Write(SC1, (uint8_t *) "AT\r", 3); // delay_ms(5); // 清空数据 DTU_ClearQueue(); // 发送命令, 并附加回车换行符 // sprintf(cmd, "AT+QMTPUBEX=0,%d,1,0,\"/sys/%s/%s/thing/model/up_raw\",%d", // msgid, aliyunSecret.product, aliyunSecret.device, len); sprintf(cmd, "AT+QMTPUBEX=0,%d,1,0,\"rockcar/guanshuche02\",%d", msgid, len); printf("\n%s\n", cmd); SCUART_Write(SC1, (uint8_t *) cmd, strlen(cmd)); SCUART_Write(SC1, (uint8_t *) "\r", 1); if(DTU_ParseResult(">", "ERROR", buff, DTU_tmrQPendShort)) { delay_ms(10); SCUART_Write(SC1, data, len); if(DTU_ParseResult("+QMTPUBEX: ", "ERROR", buff, DTU_tmrQPendSpec)) { sprintf(cmd, "+QMTPUBEX: 0,%d,0", msgid); if(strstr(buff, cmd)) { DTU_fail_count = 0; DTU_shutdown_count = 0; printf("\nSend %d bytes ok\n", len); msgid++; if(msgid == 0) msgid++; // 记录发送成功的时间 RTC_GetDateAndTime(&sRTC); DTU_succTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); return TRUE; } } } strcpy(dcBuff.powerInfo.gprsFailCode, "SEND"); delay_ms(200); } printf("\nSend failed\n"); // 如果2次失败,模块关机/关电 if(++DTU_fail_count >= 2) { if(DTU_shutdown_count >= 1 || !DTU_Shutdown()) DTU_PowerOff(); } return FALSE; } uint32_t Sim808_MqttPublish(uint8_t *data, uint16_t len) { return DTU_MqttPublish(data, len); } // 关闭连接 uint32_t MQTT_Close() { char buff[40]; uint8_t try_count = 2; if(!dcBuff.dtuData.connected) return TRUE; dcBuff.dtuData.connected = 0; while(try_count--) { // 可能返回OK,也可能返回错误(如连接已关闭,或被服务器主动关闭),都视为关闭成功 if(DTU_ExecuteCmd("AT+QMTDISC=0","+QMTDISC: 0,0", "ERROR", buff, DTU_tmrQPendShort)) { printf("\nConnection closed.\n"); return TRUE; } delay_ms(200); } printf("\nConnection close failed.\n"); return FALSE; } // 连接服务器:MQTT uint32_t DTU_MqttConnect(const char *server, int port) { char cmd[80], buff[40]; uint8_t try_count = 1; while(try_count--) { sprintf(cmd, "AT+QMTOPEN=0,\"%s\",%d", server, port); if(DTU_ExecuteCmd(cmd, "+QMTOPEN: 0,0", "ERROR", buff, DTU_tmrQPendSpec) && DTU_ExecuteCmd("AT+QMTCONN=0,\"oilH2\",\"agfTc766c\"","+QMTCONN: 0,0,0", "ERROR", buff, DTU_tmrQPendShort)) { dcBuff.dtuData.connected = 1; printf("\nConnect to %s:%d\n", server, port); return TRUE; } delay_ms(200); } dcBuff.dtuData.connected = 0; printf("\nCan not connect to %s:%d\n", server, port); // 如果2次失败,模块关机/关电 if(++DTU_fail_count >= 2) { if(DTU_shutdown_count >= 1 || !DTU_Shutdown()) DTU_PowerOff(); } return FALSE; } uint32_t Sim808_MqttConnect(const char *server, int port) { if(!Sim808_GPRSDial()) return FALSE; // if(!DTU_FetchIP()) // { // strcpy(dcBuff.powerInfo.gprsFailCode, "IP"); // return FALSE; // } // if(!DTU_SetDNSIP()) // { // strcpy(dcBuff.powerInfo.gprsFailCode, "DNS"); // return FALSE; // } if(!DTU_ConfigMQTT()) { strcpy(dcBuff.powerInfo.gprsFailCode, "MQTT"); return FALSE; } printf("\nConnect to MQTT-Server....\n"); if(!DTU_MqttConnect(server, port)) { strcpy(dcBuff.powerInfo.gprsFailCode, "CONN"); return FALSE; } return TRUE; } // ASCII重组 void ASCII2Hex(char hchar, char lchar, uint8_t* hex) { uint8_t h = 0, l = 0; if(hchar >= '0' && hchar <= '9') { h = hchar - '0'; } else if(hchar >= 'A' && hchar <= 'F') { h = hchar - 'A' + 10; } else if(hchar >= 'a' && hchar <= 'f') { h = hchar - 'a' + 10; } if(lchar >= '0' && lchar <= '9') { l = lchar - '0'; } else if(lchar >= 'A' && lchar <= 'F') { l = lchar - 'A' + 10; } else if(lchar >= 'a' && lchar <= 'f') { l = lchar - 'a' + 10; } *hex = (h << 4) | l; } uint8_t check_sum(char *message) { int16_t i, len = strlen(message); uint8_t cs0, cs1 = 0; if(len < 4 || message[0] != '$' || message[len - 3] != '*') return 0; for(i = 1; i < len - 3; i++) { cs1 ^= message[i]; } ASCII2Hex(message[len - 2], message[len - 1], &cs0); if(cs1 == cs0) return 1; printf("\nCheck sum error: %s<>%02X", message, cs1); return 0; } uint32_t parse_vtg(char *message, data_dtu_t *sample) { char *p = message, *pe = p + strlen(message), *p1 = NULL; char buff[20]; // $GNVTG,293.56,T,,M,1.13,N,2.10,K,A*28 // 运动角度 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // T=真北参照系 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // 运动角度 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // M=磁北参照系 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // 水平运动速度(节) p = strstr(p, ","); if(!p || ++p >= pe) return 0; // N=节 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // 水平运动速度(千米) p = strstr(p, ","); if(!p || ++p >= pe) return 0; p1 = strstr(p, ","); if(!p1) return 0; memset(buff, 0, sizeof(buff)); strncpy(buff, p, p1 - p); sample->speed = atof(buff); return 1; } uint32_t parse_gga(char *message, data_dtu_t *sample) { char *p = message, *pe = p + strlen(message), *p1 = NULL; char buff[20]; // $GNGGA,014600.000,3029.3359,N,10357.9168,E,1,4,4.16,200.1,M,-32.0,M,,*6B if(!check_sum(message)) return 0; // UTC 时间 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // 纬度 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // N/S p = strstr(p, ","); if(!p || ++p >= pe) return 0; // 经度 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // E/W p = strstr(p, ","); if(!p || ++p >= pe) return 0; // GPS状态 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // 正在使用的卫星数 p = strstr(p, ","); if(!p || ++p >= pe) return 0; p1 = strstr(p, ","); if(!p1) return 0; memset(buff, 0, sizeof(buff)); strncpy(buff, p, p1 - p); sample->sateCount = atoi(buff); return 1; } uint32_t parse_rmc(char *message, data_dtu_t *sample) { char *p = message, *pe = p + strlen(message), *p1 = NULL; char buff[20]; uint16_t deg; float fen; // $GNRMC,014600.000,A,3029.3359,N,10357.9168,E,1.13,293.56,070417,,,A*7C if(!check_sum(message)) return 0; // UTC时间 p = strstr(p, ","); if(!p || ++p >= pe) return 0; p1 = strstr(p, ","); if(!p1 || p1 < p + 6) return 0; // 2位小时 memset(buff, 0, sizeof(buff)); strncpy(buff, p, 2); p += 2; sample->sysTime.hour = atoi(buff); // 2位分钟 memset(buff, 0, sizeof(buff)); strncpy(buff, p, 2); p += 2; sample->sysTime.minute = atoi(buff); // 2位秒 memset(buff, 0, sizeof(buff)); strncpy(buff, p, 2); p += 2; sample->sysTime.second = atoi(buff); if(sample->sysTime.hour > 23 || sample->sysTime.minute > 59 || sample->sysTime.second > 59) return 0; // 定位状态 p = strstr(p, ","); if(!p || ++p >= pe) return 0; sample->posState = (*p == 'A'); // 纬度 p = strstr(p, ","); if(!p || ++p >= pe) return 0; p1 = strstr(p, ","); if(!p1 || p1 < p + 11) return 0; memset(buff, 0, sizeof(buff)); strncpy(buff, p, 2); deg = atoi(buff); p += 2; strncpy(buff, p, 9); fen = atof(buff); if(deg > 90 || fen >= 60 || (deg == 90 && fen > 0)) return 0; sample->latitude = (deg + fen / 60) * 1000000ul; // N/S p = strstr(p, ","); if(!p || ++p >= pe) return 0; if(*p == 'S') sample->latitude = -sample->latitude; // 经度 p = strstr(p, ","); if(!p || ++p >= pe) return 0; p1 = strstr(p, ","); if(!p1 || p1 < p + 12) return 0; memset(buff, 0, sizeof(buff)); strncpy(buff, p, 3); deg = atoi(buff); p += 3; strncpy(buff, p, 9); fen = atof(buff); if(deg > 180 || fen >= 60 || (deg == 180 && fen > 0)) return 0; sample->longitude = (deg + fen / 60) * 1000000ul; // E/W p = strstr(p, ","); if(!p || ++p >= pe) return 0; if(*p == 'W') sample->longitude = -sample->longitude; // 速度(节) p = strstr(p, ","); if(!p || ++p >= pe) return 0; p1 = strstr(p, ","); if(!p1) return 0; memset(buff, 0, sizeof(buff)); strncpy(buff, p, p1 - p); sample->speed = atof(buff) * 1.852; // 方位角 p = strstr(p, ","); if(!p || ++p >= pe) return 0; // UTC日期 p = strstr(p, ","); if(!p || ++p >= pe) return 0; p1 = strstr(p, ","); if(!p1 || p1 < p + 6) return 0; // 2位日期 memset(buff, 0, sizeof(buff)); strncpy(buff, p, 2); p += 2; sample->sysTime.day = atoi(buff); // 2位月份 memset(buff, 0, sizeof(buff)); strncpy(buff, p, 2); p += 2; sample->sysTime.month = atoi(buff); // 2位年份 memset(buff, 0, sizeof(buff)); strncpy(buff, p, 2); p += 2; sample->sysTime.year = atoi(buff); if(sample->sysTime.month < 1 || sample->sysTime.month > 12 || sample->sysTime.day < 1 || sample->sysTime.day > 31) return 0; // 处理时差 GPS_ProcessTimeLag(&sample->sysTime, dcBuff.configData.timeLag); return 1; } uint8_t parse_frame(uint8_t *bufIdx, char *message, data_dtu_t *sample) { uint8_t ret = 0; S_RTC_TIME_DATA_T sRTC; if(strncmp(message, "$GPGGA", 6) == 0) { // printf("\n%s\n", message); *bufIdx = 1 - *bufIdx; } else if(strncmp(message, "$GPRMC", 6) == 0) { printf("\n%s\n", message); // 获取当前时间 RTC_GetDateAndTime(&sRTC); // 记录GPS上次数据时间 DTU_gpsTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); parse_gga(DTU_gpsData[1 - *bufIdx], sample); ret = parse_rmc(message, sample); if(!ret) sample->posState = 0; } return ret; } // 任务主体:采集GPS数据 void DTU_Task0(uint8_t c) { static uint16_t RdIdx = 0; static uint8_t bufIdx = 0; static data_dtu_t sample = {0}; static int32_t last_latitude, last_longitude; static uint8_t gps_flag = 0, motion_count = 0, motionless_count = 0; static uint32_t last_time = 0; gps_data_t gpsData; uint32_t time; if(c == '$' || RdIdx >= DTU_GPSDATA_SIZE) RdIdx = 0; if(RdIdx == 0 && c != '$') return; if(c != '\r' && c != '\n') DTU_gpsData[bufIdx][RdIdx++] = c; else { // 收到完整的一行 DTU_gpsData[bufIdx][RdIdx] = 0; RdIdx = 0; // 解析一行数据 if(parse_frame(&bufIdx, DTU_gpsData[bufIdx], &sample)) { if(sample.sateCount > 0) printf("sateCount:\t%d\n", sample.sateCount); if(sample.posState) { time = Calc_SecondsFromYear(INITIAL_YEAR, sample.sysTime.year + 2000, sample.sysTime.month, sample.sysTime.day, sample.sysTime.hour, sample.sysTime.minute, sample.sysTime.second); // 修正时间基准(可显示绝对时间) //if(RTC_offsetSeconds == 0 && time >= DTU_gpsTime) if(time >= DTU_gpsTime) // 每次成功定位都修正时间 RTC_offsetSeconds = time - DTU_gpsTime; if(!dcBuff.configDisplay.op_CELL_LOCATION || sample.sateCount >= 4) { if(time >= last_time + dcBuff.configData.intervalGPS) { last_time = time; // 如果没有硬件加速度计,则用软件方式判断 if(dcBuff.configDisplay.op_SEND_GPS_DATA && Accelero_ID != ACCELERO_ID) { if(sample.speed <= 3) { motion_count = 0; if(Motion_Status == 1 && ++motionless_count >= 3) { Motion_Status = 0; printf("\nSoft Motion status = 0\n"); } } else { motionless_count = 0; if(Motion_Status == 0 && ++motion_count >= 3) { Motion_Status = 1; printf("\nSoft Motion status = 1\n"); } } } printf("Latitude:\t%10.6f\n", sample.latitude * 0.000001); printf("Longitude:\t%10.6f\n", sample.longitude * 0.000001); printf("Speed:\t\t%d km/h\n", sample.speed); printf("GPS time:\t%d-%02d-%02d %02d:%02d:%02d\n", sample.sysTime.year + 2000, sample.sysTime.month, sample.sysTime.day, sample.sysTime.hour, sample.sysTime.minute, sample.sysTime.second); // 计算和上次定位之间的距离,或者判断运动状态 if(dcBuff.configDisplay.op_SEND_GPS_DATA && gps_flag == 1 && ( !Motion_Status // || (sample.speed < 5 && GetDistance(last_latitude, last_longitude, sample.latitude, sample.longitude) < 10) )) { printf("\nCalibrate to last position\n"); sample.latitude = last_latitude; sample.longitude = last_longitude; } else { gps_flag = 1; last_latitude = sample.latitude; last_longitude = sample.longitude; } // 写入全局缓冲 dcBuff.dtuData.posState = sample.posState; dcBuff.dtuData.sateCount = sample.sateCount; dcBuff.dtuData.latitude = sample.latitude; dcBuff.dtuData.longitude = sample.longitude; dcBuff.dtuData.speed = sample.speed; dcBuff.dtuData.sysTime = sample.sysTime; if(dcBuff.configDisplay.op_SEND_GPS_DATA) { // 加入GPS数据队列,待发送 if(sample.sateCount > 31) gpsData.sateCount = 31; else gpsData.sateCount = sample.sateCount; gpsData.posState = sample.posState; gpsData.carState = VCC_POWER_STATUS() ? 1: 0; gpsData.carEvent = bat_CurrentEvent; bat_CurrentEvent = 0; gpsData.time.year = sample.sysTime.year + 2000 - GPS_BASE_YEAR; gpsData.time.mon = sample.sysTime.month; gpsData.time.day = sample.sysTime.day; gpsData.time.hour_H = sample.sysTime.hour >> 4; gpsData.time.hour_L = sample.sysTime.hour & 0x0F; gpsData.time.min = sample.sysTime.minute; gpsData.time.sec = sample.sysTime.second; gpsData.latitude = sample.latitude; gpsData.longitude = sample.longitude; gpsData.speed = sample.speed; GPS_PutToQueue(&gpsData); } else { GPS_Located = 1; // 停止超时定时器 GPS_Waiting = 0; } } } } // 清除数据 memset(&sample, 0, sizeof(sample)); } } } uint8_t pack_gprs_send_data(gprs_data_t *pGprs, uint32_t totalSeconds) { uint8_t i, j; bluetooth_sensor_t *pSensor; bluetooth_mask_t *pMask; uint32_t relativeTime; S_RTC_TIME_DATA_T sRTC; uint16_t crc; // 打包上报数据(按modbus从机响应的格式) memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = 0; // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); printf("\nSend PSN: 20%02d%02d%02d%02d%03d\n", Task_sendBuff[i], Task_sendBuff[i + 1], Task_sendBuff[i + 2], Task_sendBuff[i+3], (Task_sendBuff[i + 4] << 8) | Task_sendBuff[i + 5]); i += 6; // 功能码 Task_sendBuff[i++] = 0x10; // 数据长度:先预设为0,最后再修改,位置为Task_sendBuff[7] Task_sendBuff[i++] = 0; // 当前差压值 i +=2 ; // 容积百分比 i += 2; // 当前容积 i += 4; // 重量 i += 4; // 高度:mmWC i += 2; // 压力 Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.pressure)); i += 2; #if 0 // 温度 Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.batTempr); #else // 用温度表示自启动以来的时间分钟数,32767分钟 Int2ByteS(Task_sendBuff, i, htons((totalSeconds % 1966080ul) / 60)); #endif i += 2; // 液源 if(dcBuff.configBottle.source >= SOURCE_LNG && dcBuff.configBottle.source <= SOURCE_POPO) Task_sendBuff[i] = dcBuff.configBottle.source; i++; // 储罐类型 if(dcBuff.configBottle.type == BOTTLE_TYPE_STAND) Task_sendBuff[i] = 0; else if(dcBuff.configBottle.type == BOTTLE_TYPE_LYING) Task_sendBuff[i] = 1; else if(dcBuff.configBottle.type == BOTTLE_TYPE_SPHERICAL) Task_sendBuff[i] = 2; i++; // 故障码 pSensor = (bluetooth_sensor_t *) (Task_sendBuff + i); pSensor->staDiff = Bluetooth_ConvertStat(&pGprs->sampleData.staDPress); pSensor->staPress = Bluetooth_ConvertStat(&pGprs->sampleData.staPress); pSensor->staEPress1 = Bluetooth_ConvertStat(&pGprs->sampleData.staExtPress[0]); pSensor->staEPress2 = Bluetooth_ConvertStat(&pGprs->sampleData.staExtPress[1]); pSensor->staEPress3 = Bluetooth_ConvertStat(&pGprs->sampleData.staExtPress[2]); pSensor->staETempr1 = Bluetooth_ConvertStat(&pGprs->sampleData.staExtTempr[0]); pSensor->staETempr2 = Bluetooth_ConvertStat(&pGprs->sampleData.staExtTempr[1]); pSensor->staETempr3 = Bluetooth_ConvertStat(&pGprs->sampleData.staExtTempr[2]); i += 2; // 传感器状态 pMask = (bluetooth_mask_t *) (Task_sendBuff + i); memset(pMask, 0xFF, 2); pMask->maskFlow = 0; pMask->maskLowPower = pGprs->dtuData.batLow; pMask->maskAbnormal = 0; pMask->maskCharging = pGprs->sampleData.charging; i += 2; // 版本号 Task_sendBuff[i++] = dcBuff.powerInfo.protocolVer.minor; // rssi Task_sendBuff[i++] = pGprs->dtuData.rssi; if(pMask->maskGPS) { // 经度 Int2ByteL(Task_sendBuff, i, htonl(pGprs->dtuData.longitude)); i += 4; // 纬度 Int2ByteL(Task_sendBuff, i, htonl(pGprs->dtuData.latitude)); i += 4; } // 扩展温度 if(pMask->maskETempr1) { Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.extTempr[0])); i += 2; } if(pMask->maskETempr2) { Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.extTempr[1])); i += 2; } if(pMask->maskETempr3) { #if 0 // 扩展温度3 Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.extTempr[2])); #else // 用扩展温度3表示硬件配置 Int2ByteS(Task_sendBuff, i, htons(dcBuff.powerInfo.hardVer.major)); #endif i += 2; } // 电池信息 if(pMask->maskBattery) { // 电量百分比 Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.batPct)); i += 2; // 电池内部温度 Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.batTempr)); i += 2; // 电池当前电压 Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.batVoltage / 10)); i += 2; // 电池容量 Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.batMaxCapa)); i += 2; // 电池当前容量 Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.batCapa)); i += 2; #if 0 // 充电电流,电流的符号表示充放电状态 Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.batCurrent)); #else // 用电流的绝对值表示复位原因 // 1-POR, 2-PIN, 4-WDT, 8-LVR, 16-BOD, 32-SYS, 128-CPU, 256-CPULK Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.batCurrent > 0 ? SYS_RSTSTS : -SYS_RSTSTS)); #endif i += 2; // 光照强度 Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.sunLevel)); i += 2; } // 流量计 if(pMask->maskFlow) { // 天信MODBUS /A1 通信协议 (BCD码) // 标况体积总量 i += 6; // 标况流量 i += 4; // 工况流量 i += 4; // 温度 i += 4; // 压力 i += 4; } // 泄露报警 if(pMask->maskLeak) { // 类型 Task_sendBuff[i++] = pGprs->sampleData.leak.typeLeak; // 状态、报警浓度 if(pGprs->sampleData.leak.staLeak == LEAK_STATUS_FAULT || pGprs->sampleData.leak.staLeak == LEAK_STATUS_COMM_FAULT) Task_sendBuff[i] = 0x80; else Task_sendBuff[i] = (pGprs->sampleData.leak.concentrations & 0x7F); i++; } if(pMask->maskStamp) { if(dcBuff.powerInfo.protocolVer.minor == 107) { // 获取当前时间 RTC_GetDateAndTime(&sRTC); // 计算自上次gps定位以来的时间 relativeTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) - pGprs->sample_time; Int2ByteL(Task_sendBuff, i, htonl(relativeTime)); } // 时间 i += 4; // 年月日 i += 4; } // 扩展压力 if(pMask->maskEPress1) { Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.extPressure[0])); i += 2; } if(pMask->maskEPress2) { Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.extPressure[1])); i += 2; } if(pMask->maskEPress3) { #if 0 // 扩展压力3 Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.extPressure[2])); #else // 上传GPS调试信息: 闪断次数*100+卫星数 // 如2105表示闪断21次,卫星数5颗 Int2ByteS(Task_sendBuff, i, htons(GPS_BOD_COUNT * 100 + pGprs->dtuData.sateCount)); printf("\nGPS_DEBUG_VAL: %d\n", ntohs(Byte2IntS(Task_sendBuff, i))); #endif i += 2; } printf("\ndcBuff.powerInfo.hardVer.major = %d, dcBuff.powerInfo.softVer.minor = %d\n", dcBuff.powerInfo.hardVer.major, dcBuff.powerInfo.softVer.minor); // 硬件版本 //Task_sendBuff[i++] = ((dcBuff.powerInfo.hardVer.minor / 10) << 4) + dcBuff.powerInfo.hardVer.minor % 10; Task_sendBuff[i++] = dcBuff.powerInfo.hardVer.minor; // 软件版本 //Task_sendBuff[i++] = ((dcBuff.powerInfo.softVer.minor / 10) << 4) + dcBuff.powerInfo.softVer.minor % 10;; Task_sendBuff[i++] = dcBuff.powerInfo.softVer.minor; // 真空传感器1 if(pGprs->sampleData.vacuum[0].staVacuum == VACUUM_STATUS_FAULT || pGprs->sampleData.vacuum[0].staVacuum == VACUUM_STATUS_COMM_FAULT) Int2ByteS(Task_sendBuff, i, htons(0)); else Int2ByteS(Task_sendBuff, i, htons(1)); i += 2; // 使用年限 Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.vacuum[0].lifeVacuum)); i += 2; // 真空度 Int2ByteL(Task_sendBuff, i, htonl(pGprs->sampleData.vacuum[0].vacuum * 100)); i += 4; // 漏放气速率 Int2ByteL(Task_sendBuff, i, htonl(pGprs->sampleData.vacuum[0].rateVacuum * 100)); i += 4; // 真空传感器2 Int2ByteS(Task_sendBuff, i, htons(0)); i += 2; // 使用年限 i += 2; // 真空度 i += 4; // 漏放气速率 i += 4; // 气瓶容量 Int2ByteL(Task_sendBuff, i, htonl(pGprs->sampleData.volumeTotal)); i += 4; // 储罐封头直边长 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.lenExtra)); i += 2; // 储罐筒长度 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.len)); i += 4; // 储罐直径 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.diameter)); i += 4; // 自动发送频率 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.intervalTrans / 60)); i += 2; // 自动发送短信频率(实际发送采集频率) Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.intervalSample / 60)); i += 2; // 修改数据长度 Task_sendBuff[7] = i - 8; // 校验码 crc = MODBUS_RTU_CRC16((uint8_t *) Task_sendBuff, i); Int2ByteS(Task_sendBuff, i, htons(crc)); i += 2; // 结束符 Task_sendBuff[i++] = 0x0d; Task_sendBuff[i++] = 0x0a; return i; } uint8_t pack_furui_send_data(gprs_data_t *pGprs, uint32_t *relativeTime) { uint8_t i; uint32_t uVal32; S_RTC_TIME_DATA_T sRTC; uint16_t crc; // 打包上报数据(按modbus从机响应的格式) memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = 0; // 起始符 Task_sendBuff[i++] = 0x4C; // 总长度:先预设为0,最后再修改,位置为Task_sendBuff[1] Task_sendBuff[i++] = 0; // 协议版本 Task_sendBuff[i++] = 1; // 硬件版本 Task_sendBuff[i++] = dcBuff.powerInfo.hardVer.minor; // 软件版本 Task_sendBuff[i++] = dcBuff.powerInfo.softVer.minor; // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); printf("\nSend PSN: 20%02d%02d%02d%02d%03d\n", Task_sendBuff[i], Task_sendBuff[i + 1], Task_sendBuff[i + 2], Task_sendBuff[i+3], (Task_sendBuff[i + 4] << 8) | Task_sendBuff[i + 5]); i += 6; // 时间戳 RTC_GetDateAndTime(&sRTC); *relativeTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) - pGprs->sample_time; Int2ByteL(Task_sendBuff, i, htonl(*relativeTime)); i += 4; // 传感器状态 uVal32 = 0xFFFFFFFFul; // 连接状态 // if(!pGprs->sampleData.staDPress.notConnect) // uVal32 &= ~(1ul << 0); if(!pGprs->sampleData.staPress.notConnect) uVal32 &= ~(1ul << 1); if(!pGprs->sampleData.staExtPress[0].notConnect) uVal32 &= ~(1ul << 2); if(!pGprs->sampleData.staExtTempr[0].notConnect) uVal32 &= ~(1ul << 3); if(!pGprs->sampleData.staExtTempr[1].notConnect) uVal32 &= ~(1ul << 4); if(!(pGprs->sampleData.vacuum[0].staVacuum == VACUUM_STATUS_COMM_FAULT)) uVal32 &= ~(1ul << 5); if(1) // 流量计 uVal32 &= ~(1ul << 6); if(!(pGprs->sampleData.leak.staLeak == LEAK_STATUS_COMM_FAULT)) uVal32 &= ~(1ul << 7); // 故障状态 if(!(pGprs->sampleData.staDPress.overFlow || pGprs->sampleData.staDPress.underFlow)) uVal32 &= ~(1ul << 8); if(!(pGprs->sampleData.staPress.overFlow || pGprs->sampleData.staPress.underFlow)) uVal32 &= ~(1ul << 9); if(!(pGprs->sampleData.staExtPress[0].overFlow || pGprs->sampleData.staExtPress[0].underFlow)) uVal32 &= ~(1ul << 10); if(!(pGprs->sampleData.staExtTempr[0].overFlow || pGprs->sampleData.staExtTempr[0].underFlow)) uVal32 &= ~(1ul << 11); if(!(pGprs->sampleData.staExtTempr[1].overFlow || pGprs->sampleData.staExtTempr[1].underFlow)) uVal32 &= ~(1ul << 12); if(!(pGprs->sampleData.vacuum[0].staVacuum == VACUUM_STATUS_FAULT)) uVal32 &= ~(1ul << 13); if(1) // 流量计 uVal32 &= ~(1ul << 14); if(!(pGprs->sampleData.leak.staLeak == LEAK_STATUS_FAULT)) uVal32 &= ~(1ul << 15); Int2ByteL(Task_sendBuff, i, htonl(uVal32)); i += 4; // 当前差压值:mmWC i +=2 ; // 容积百分比 i += 2; // 当前容积 i += 4; // 重量 i += 4; // 气瓶容量 Int2ByteL(Task_sendBuff, i, htonl(pGprs->sampleData.volumeTotal)); i += 4; // 压力1 Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.pressure)); i += 2; // 压力2 Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.extPressure[0])); i += 2; // 温度1 Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.extTempr[0])); i += 2; // 温度2 Int2ByteS(Task_sendBuff, i, htons(pGprs->sampleData.extTempr[1])); i += 2; // 真空度 Int2ByteS(Task_sendBuff, i, htons((uint16_t) (pGprs->sampleData.vacuum[0].vacuum * 100))); i += 2; // 真空计温度 Int2ByteS(Task_sendBuff, i, htons((int16_t) pGprs->sampleData.vacuum[0].tempr)); i += 2; // 天信MODBUS /A1 通信协议 (BCD码) // 标况体积总量 memmove(Task_sendBuff + i, pGprs->sampleData.flow.nM3, 6); i += 6; // 标况流量 memmove(Task_sendBuff + i, pGprs->sampleData.flow.nM3_h, 4); i += 4; // 工况流量 memmove(Task_sendBuff + i, pGprs->sampleData.flow.M3_h, 4); i += 4; // 流量计温度 memmove(Task_sendBuff + i, pGprs->sampleData.flow.tempr, 4); i += 4; // 流量计压力 memmove(Task_sendBuff + i, pGprs->sampleData.flow.pressure, 4); i += 4; // 泄露状态 Task_sendBuff[i++] = (pGprs->sampleData.leak.staLeak == LEAK_STATUS_A2_ALARM ? 1 : 0); // 经度 Int2ByteL(Task_sendBuff, i, htonl(pGprs->dtuData.longitude)); i += 4; // 纬度 Int2ByteL(Task_sendBuff, i, htonl(pGprs->dtuData.latitude)); i += 4; // rssi Task_sendBuff[i++] = pGprs->dtuData.rssi; // 电量百分比 Task_sendBuff[i++] = pGprs->dtuData.batPct; // 电池当前电压 Int2ByteS(Task_sendBuff, i, htons(pGprs->dtuData.batVoltage / 10)); i += 2; // 供电状态 Task_sendBuff[i++] = (pGprs->dtuData.batCurrent < 0 ? -1 : 1); // 液源 if(dcBuff.configBottle.source >= SOURCE_LNG && dcBuff.configBottle.source <= SOURCE_POPO) Task_sendBuff[i] = dcBuff.configBottle.source; i++; // 密度 Int2ByteS(Task_sendBuff, i, htons(Config_GetDensity(dcBuff.configBottle.source) * 1000)); i += 2; // 储罐类型 if(dcBuff.configBottle.type == BOTTLE_TYPE_STAND) Task_sendBuff[i] = 0; else if(dcBuff.configBottle.type == BOTTLE_TYPE_LYING) Task_sendBuff[i] = 1; else if(dcBuff.configBottle.type == BOTTLE_TYPE_SPHERICAL) Task_sendBuff[i] = 2; i++; // 储罐直径 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.diameter)); i += 4; // 储罐筒长度 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.len + dcBuff.configBottle.lenExtra * 2)); i += 4; // 采集周期 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configData.intervalSample)); i += 4; // 发送周期 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configData.intervalTrans)); i += 4; // 满液位百分比 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.fullPct)); i += 2; // 关键液位百分比 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.priPct)); i += 2; // 订货位百分比 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.orderPct)); i += 2; // 空液位百分比 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.emptyPct)); i += 2; // 压力报警上限 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnPressH)); i += 2; // 压力报警下限 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnPress)); i += 2; // 温度报警上限 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnTemprH)); i += 2; // 温度报警下限 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnTempr)); i += 2; // 真空度报警上限 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnVacuumH)); i += 2; // 显示控制 Task_sendBuff[i++] = dcBuff.configBottle.dispMode; // 修改数据长度 Task_sendBuff[1] = i - 1 + 2; // 校验码 crc = MODBUS_RTU_CRC16(Task_sendBuff + 1, i - 1); Int2ByteS(Task_sendBuff, i, htons(crc)); i += 2; // 结束符 Task_sendBuff[i++] = 0x53; return i; } uint8_t parse_furui_recv_data(uint8_t PSN[6], uint32_t relativeTime, uint16_t recvLen) { uint8_t i, j, len, protocol; uint32_t mask, uVal32; uint16_t uVal16; int16_t val16; uint8_t saveConfig = 0; i = 0; // 检查起始符、结束符 if(Task_recvBuff[i++] != 0x4C || Task_recvBuff[recvLen - 1] != 0x53) return 0; // 检查数据长度和CRC len = Task_recvBuff[i++]; if(len != recvLen - 2 || MODBUS_RTU_CRC16(Task_recvBuff + 1, len) != 0) return 0; // 检查协议版本 protocol = Task_recvBuff[i++]; if(protocol != 1) return 0; // 检查PSN if(memcmp(Task_recvBuff + i, PSN, 6) != 0) return 0; i += 6; // 检查时间戳 if(ntohl(Byte2IntL(Task_recvBuff, i)) != relativeTime) return 0; i += 4; // 参数更新标志 mask = ntohl(Byte2IntL(Task_recvBuff, i)); i += 4; j = 0; // 介质 if(mask & (1ul << (j++))) { printf("modify source\r\n"); if(dcBuff.configBottle.source != Task_recvBuff[i]) { dcBuff.configBottle.source = Task_recvBuff[i]; saveConfig = 1; } } i++; // 密度 if(mask & (1ul << (j++))) { printf("modify density\r\n"); uVal16 = ntohs(Byte2IntS(Task_recvBuff, i)); if(Config_GetDensity(dcBuff.configBottle.source) * 1000 != uVal16) { Config_SetDensity(dcBuff.configBottle.source, uVal16 / 1000.0); saveConfig = 1; } } i += 2; // 储罐类型 if(mask & (1ul << (j++))) { printf("modify type\r\n"); if(dcBuff.configBottle.type != Task_recvBuff[i]) { dcBuff.configBottle.type = Task_recvBuff[i]; saveConfig = 1; } } i++; // 储罐直径 if(mask & (1ul << (j++))) { printf("modify diameter\r\n"); uVal32 = ntohl(Byte2IntL(Task_recvBuff, i)); if(dcBuff.configBottle.diameter != uVal32) { dcBuff.configBottle.diameter = uVal32; saveConfig = 1; } } i += 4; // 储罐筒长度 if(mask & (1ul << (j++))) { printf("modify len\r\n"); uVal32 = ntohl(Byte2IntL(Task_recvBuff, i)); if(dcBuff.configBottle.lenExtra != 0 || dcBuff.configBottle.len != uVal32) { dcBuff.configBottle.lenExtra = 0; dcBuff.configBottle.len = uVal32; saveConfig = 1; } } i += 4; // 采集周期 if(mask & (1ul << (j++))) { printf("modify intervalSample\r\n"); uVal32 = ntohl(Byte2IntL(Task_recvBuff, i)); if(dcBuff.configData.intervalSample != uVal32) { dcBuff.configData.intervalSample = uVal32; saveConfig = 1; } } i += 4; // 发送周期 if(mask & (1ul << (j++))) { printf("modify intervalTrans\r\n"); uVal32 = ntohl(Byte2IntL(Task_recvBuff, i)); if(dcBuff.configData.intervalTrans != uVal32) { dcBuff.configData.intervalTrans = uVal32; saveConfig = 1; } } i += 4; // 满液位百分比 if(mask & (1ul << (j++))) { printf("modify fullPct\r\n"); uVal16= ntohs(Byte2IntS(Task_recvBuff, i)); if(dcBuff.configBottle.fullPct != uVal16) { dcBuff.configBottle.fullPct = uVal16; saveConfig = 1; } } i += 2; // 关键液位百分比 if(mask & (1ul << (j++))) { printf("modify priPct\r\n"); uVal16= ntohs(Byte2IntS(Task_recvBuff, i)); if(dcBuff.configBottle.priPct != uVal16) { dcBuff.configBottle.priPct = uVal16; saveConfig = 1; } } i += 2; // 订货位百分比 if(mask & (1ul << (j++))) { printf("modify orderPct\r\n"); uVal16= ntohs(Byte2IntS(Task_recvBuff, i)); if(dcBuff.configBottle.orderPct != uVal16) { dcBuff.configBottle.orderPct = uVal16; saveConfig = 1; } } i += 2; // 空液位百分比 if(mask & (1ul << (j++))) { printf("modify emptyPct\r\n"); uVal16= ntohs(Byte2IntS(Task_recvBuff, i)); if(dcBuff.configBottle.emptyPct != uVal16) { dcBuff.configBottle.emptyPct = uVal16; saveConfig = 1; } } i += 2; // 压力报警上限 if(mask & (1ul << (j++))) { printf("modify warnPressH\r\n"); uVal16= ntohs(Byte2IntS(Task_recvBuff, i)); if(dcBuff.configBottle.warnPressH != uVal16) { dcBuff.configBottle.warnPressH = uVal16; saveConfig = 1; } } i += 2; // 压力报警下限 if(mask & (1ul << (j++))) { printf("modify warnPress\r\n"); uVal16= ntohs(Byte2IntS(Task_recvBuff, i)); if(dcBuff.configBottle.warnPress != uVal16) { dcBuff.configBottle.warnPress = uVal16; saveConfig = 1; } } i += 2; // 温度报警上限 if(mask & (1ul << (j++))) { printf("modify warnTemprH\r\n"); uVal16= ntohs(Byte2IntS(Task_recvBuff, i)); memmove(&val16, &uVal16, 2); if(dcBuff.configBottle.warnTemprH != val16) { dcBuff.configBottle.warnTemprH = val16; saveConfig = 1; } } i += 2; // 温度报警下限 if(mask & (1ul << (j++))) { printf("modify warnTempr\r\n"); uVal16= ntohs(Byte2IntS(Task_recvBuff, i)); memmove(&val16, &uVal16, 2); if(dcBuff.configBottle.warnTempr != val16) { dcBuff.configBottle.warnTempr = val16; saveConfig = 1; } } i += 2; // 真空度报警上限 if(mask & (1ul << (j++))) { printf("modify warnVacuumH\r\n"); uVal16= ntohs(Byte2IntS(Task_recvBuff, i)); if(dcBuff.configBottle.warnVacuumH != uVal16) { dcBuff.configBottle.warnVacuumH = uVal16; saveConfig = 1; } } i += 2; // 显示控制 if(mask & (1ul << (j++))) { printf("modify dispMode\r\n"); if(dcBuff.configBottle.dispMode != Task_recvBuff[i]) { dcBuff.configBottle.dispMode = Task_recvBuff[i]; saveConfig = 1; } } i++; // 保存参数 if(saveConfig) Config_SaveConfig(); return 1; } //////////////////////////////////////////////////////////////////////////////////////// uint8_t pack_rf_send_data(gprs_data_t *pGprs, uint32_t totalSeconds) { uint8_t i; rf_sensor_t *pSensor; S_RTC_TIME_DATA_T sRTC; // 打包上报数据(按modbus从机响应的格式) memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = 0; // PSN printf("\nRf PSN: 20%02d%02d%02d%02d%03d\n", dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], dcBuff.configBottle.PSN[2], dcBuff.configBottle.PSN[3], (dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5]); // 差压测量:差压值 *100(KPa),称重测量:容积百分比*100,电容测量:液位高度(mm) i += 2; // 压力 Int2ByteS(Task_sendBuff, i, pGprs->sampleData.pressure); i += 2; // 温度 Int2ByteS(Task_sendBuff, i, pGprs->sampleData.extTempr[0]); i += 2; // 液源/贮罐类型/故障码/测量方式 pSensor = (rf_sensor_t *) (Task_sendBuff + i); pSensor->staDiff = Bluetooth_ConvertStat(&pGprs->sampleData.staDPress); pSensor->staPress = Bluetooth_ConvertStat(&pGprs->sampleData.staPress); pSensor->staETempr1 = Bluetooth_ConvertStat(&pGprs->sampleData.staExtTempr[0]); pSensor->charging = pGprs->sampleData.charging; pSensor->bat_low = pGprs->dtuData.batLow; pSensor->measure_type = MEASURE_DPRESS; pSensor->bottle_type = dcBuff.configBottle.type; pSensor->L_source = dcBuff.configBottle.source; i += 2; // 密度 Int2ByteS(Task_sendBuff, i, Config_GetDensity(dcBuff.configBottle.source) * 1000); i += 2; // 经度 Int2ByteL(Task_sendBuff, i, pGprs->dtuData.longitude); i += 4; // 纬度 Int2ByteL(Task_sendBuff, i, pGprs->dtuData.latitude); i += 4; // 电池当前电压 Int2ByteS(Task_sendBuff, i, pGprs->dtuData.batVoltage / 10); i += 2; // 电量百分比 Task_sendBuff[i++] = pGprs->dtuData.batPct; #if 0 // 充电电流,电流的符号表示充放电状态 if(pGprs->dtuData.batCurrent < -128) Task_sendBuff[i] = -128; else if(pGprs->dtuData.batCurrent > 127) Task_sendBuff[i] = 127; else Task_sendBuff[i] = pGprs->dtuData.batCurrent; #else // 用电流的绝对值表示复位原因 // 1-POR, 2-PIN, 4-WDT, 8-LVR, 16-BOD, 32-SYS Task_sendBuff[i] = SYS_RSTSTS & 0x7F; if(pGprs->dtuData.batCurrent < 0) Task_sendBuff[i] = -Task_sendBuff[i]; #endif i++; // 获取当前时间 RTC_GetDateAndTime(&sRTC); Int2ByteL(Task_sendBuff, i, Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) - pGprs->sample_time); i += 4; printf("\ndcBuff.powerInfo.hardVer.major = %d, dcBuff.powerInfo.softVer.minor = %d\n", dcBuff.powerInfo.hardVer.major, dcBuff.powerInfo.softVer.minor); // 硬件版本 Task_sendBuff[i++] = dcBuff.powerInfo.hardVer.minor; // 软件版本 Task_sendBuff[i++] = dcBuff.powerInfo.softVer.minor; // 储罐筒长度 Int2ByteL(Task_sendBuff, i, dcBuff.configBottle.len + dcBuff.configBottle.lenExtra * 2); i += 4; // 储罐直径 Int2ByteL(Task_sendBuff, i, dcBuff.configBottle.diameter); i += 4; // 充装比 Task_sendBuff[i++] = dcBuff.configBottle.chargePct; return i; } //////////////////////////////////////////////////////////////////////////////////////// uint8_t pack_bd_send_data(gprs_data_t *pGprs, uint32_t totalSeconds) { uint8_t i; rf_sensor_t *pSensor; S_RTC_TIME_DATA_T sRTC; // 打包上报数据(按modbus从机响应的格式) memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = 0; // PSN printf("\nBD PSN: 20%02d%02d%02d%02d%03d\n", dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], dcBuff.configBottle.PSN[2], dcBuff.configBottle.PSN[3], (dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5]); // 差压 i += 2; // 容积百分比 i += 2; // 当前容积 i += 4; // 重量 i += 4; // 压力 Int2ByteS(Task_sendBuff, i, pGprs->sampleData.pressure); i += 2; // 温度-扩展温度1 Int2ByteS(Task_sendBuff, i, pGprs->sampleData.extTempr[0]); i += 2; // 温度-调试信息:标识北斗短信 Int2ByteS(Task_sendBuff, i, 2); i += 2; // 液源/贮罐类型/故障码/测量方式 pSensor = (rf_sensor_t *) (Task_sendBuff + i); pSensor->staDiff = Bluetooth_ConvertStat(&pGprs->sampleData.staDPress); pSensor->staPress = Bluetooth_ConvertStat(&pGprs->sampleData.staPress); pSensor->staETempr1 = Bluetooth_ConvertStat(&pGprs->sampleData.staExtTempr[0]); pSensor->charging = pGprs->sampleData.charging; pSensor->bat_low = pGprs->dtuData.batLow; pSensor->measure_type = MEASURE_DPRESS; pSensor->bottle_type = dcBuff.configBottle.type; pSensor->L_source = dcBuff.configBottle.source; i += 2; // 经度 Int2ByteL(Task_sendBuff, i, pGprs->dtuData.longitude); i += 4; // 纬度 Int2ByteL(Task_sendBuff, i, pGprs->dtuData.latitude); i += 4; // 电池当前电压 Int2ByteS(Task_sendBuff, i, pGprs->dtuData.batVoltage / 10); i += 2; // 电量百分比 Task_sendBuff[i++] = pGprs->dtuData.batPct; #if 0 // 充电电流,电流的符号表示充放电状态 if(pGprs->dtuData.batCurrent < -128) Task_sendBuff[i] = -128; else if(pGprs->dtuData.batCurrent > 127) Task_sendBuff[i] = 127; else Task_sendBuff[i] = pGprs->dtuData.batCurrent; #else // 用电流的绝对值表示复位原因 // 1-POR, 2-PIN, 4-WDT, 8-LVR, 16-BOD, 32-SYS Task_sendBuff[i] = SYS_RSTSTS & 0x7F; if(pGprs->dtuData.batCurrent < 0) Task_sendBuff[i] = -Task_sendBuff[i]; #endif i++; // 获取当前时间 RTC_GetDateAndTime(&sRTC); Int2ByteL(Task_sendBuff, i, Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second) - pGprs->sample_time); i += 4; printf("\ndcBuff.powerInfo.hardVer.major = %d, dcBuff.powerInfo.softVer.minor = %d\n", dcBuff.powerInfo.hardVer.major, dcBuff.powerInfo.softVer.minor); // 硬件版本 Task_sendBuff[i++] = dcBuff.powerInfo.hardVer.minor; // 软件版本 Task_sendBuff[i++] = dcBuff.powerInfo.softVer.minor; // 气瓶容量 Int2ByteL(Task_sendBuff, i, pGprs->sampleData.volumeTotal); i += 4; // 储罐筒长度 Int2ByteL(Task_sendBuff, i, dcBuff.configBottle.len + dcBuff.configBottle.lenExtra * 2); i += 4; // 储罐直径 Int2ByteL(Task_sendBuff, i, dcBuff.configBottle.diameter); i += 4; return i; } /// ????????? static void *my_malloc(size_t size) { void *ptr = malloc(200 * 5); // ??????? if (ptr == NULL) { fprintf(stderr, "Memory allocation failed\n"); } return ptr; } // ????????? static void my_free(void *ptr) { free(ptr); } uint16_t pack_json_send_data(gprs_data_t *pGprs, uint32_t totalSeconds) { uint16_t len = 0; char Json_data[500],utc[21]; S_RTC_TIME_DATA_T sRTC; Wakeup_CalcUTCTime(pGprs->sample_time + RTC_offsetSeconds, &sRTC); sprintf(utc, "%04d-%02d-%02dT%02d:%02d:%02d", sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); // len = sprintf(Json_data,"{\ // \"PSN\":20%02d%02d%02d%02d%03d,\ // \"RTC\":%s,\ // \"hardVer\":%d,\ // \"softVer\":%d,\ // \"batVoltage\":%d,\ // \"batPct\":%d,\ // \"latitude\":%d,\ // \"longitude\":%d,\ // \"rssi\":%d,\ // \"simNumber\":%s,\ // \"type\":%d,\ // \"diameter\":%d,\ // \"len\":%d,\ // \"source\":%d,\ // \"Theoretical_v\":%d,\ // \"Pressure\":%.2f,\ // \"volume\":%d,\ // \"warnPressH\":%.2f,\ // \"warnPressL\":%.2f,\ // \"fullPct\":%.2f,\ // \"emptyPct\":%.2f,\ // \"adExtTempr0\":%d,\ // \"adExtTempr1\":%d,\ // \"intervalSample\":%d,\ // \"intervalTrans\":%d}", // dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], // dcBuff.configBottle.PSN[2], dcBuff.configBottle.PSN[3], // (dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5], // utc, // dcBuff.powerInfo.hardVer.minor, // dcBuff.powerInfo.softVer.minor, // dcBuff.dtuData.batVoltage, // dcBuff.dtuData.batPct, // dcBuff.dtuData.latitude, // dcBuff.dtuData.longitude, // dcBuff.dtuData.rssi, // dcBuff.powerInfo.simNumber, // dcBuff.configBottle.type, // dcBuff.configBottle.diameter, // dcBuff.configBottle.len, // dcBuff.configBottle.source, // Theoretical_Param.v, // (float)dcBuff.sampleData.pressure * 0.01f, // dcBuff.sampleData.volume, // dcBuff.configBottle.warnPressH * 0.01f, // dcBuff.configBottle.warnPress * 0.01f, // dcBuff.configBottle.fullPct * 0.01f, // dcBuff.configBottle.emptyPct * 0.01f, // dcBuff.sampleData.extTempr[0], // dcBuff.sampleData.extTempr[1], // dcBuff.configData.intervalSample, // dcBuff.configData.intervalTrans); len = sprintf(Json_data,"{\ \"PSN\":\"20%02d%02d%02d%02d%03d\",\ \"RTC\":\"%s\",\ \"batPct\":%d,\ \"latitude\":%d,\ \"longitude\":%d,\ \"rssi\":%d,\ \"type\":%d,\ \"source\":%d,\ \"Theoretical_v\":%d,\ \"Pressure\":%.2f,\ \"volume\":%d,\ \"warnPressH\":%.2f,\ \"warnPressL\":%.2f,\ \"adExtTempr\":%d,\ \"intervalSample\":%d,\ \"intervalTrans\":%d}", dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1], dcBuff.configBottle.PSN[2], dcBuff.configBottle.PSN[3], (dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5], utc, dcBuff.dtuData.batPct, dcBuff.dtuData.latitude, dcBuff.dtuData.longitude, dcBuff.dtuData.rssi, dcBuff.configBottle.type, dcBuff.configBottle.source, Theoretical_Param.v, (float)dcBuff.sampleData.pressure * 0.01f, dcBuff.sampleData.volume, dcBuff.configBottle.warnPressH * 0.01f, dcBuff.configBottle.warnPress * 0.01f, dcBuff.sampleData.extTempr[0], dcBuff.configData.intervalSample, dcBuff.configData.intervalTrans); //len=strlen(Json_data); for(int i=0; isample_time + RTC_offsetSeconds, &sRTC); // sprintf(utc, "%04d-%02d-%02dT%02d:%02d:%02d", sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, // sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); // 1. ?????? JSON ?? cJSON *root = cJSON_CreateObject(); if (root == NULL) { printf("Error: Failed to create JSON object.\n"); return 1; } printf("\n111\n"); // 2. ? JSON ??????? cJSON_AddStringToObject(root, "psn", psn); //cJSON_AddStringToObject(root, "utc", utc); cJSON_AddNumberToObject(root, "hardVer", dcBuff.powerInfo.hardVer.minor); cJSON_AddNumberToObject(root, "softVer", dcBuff.powerInfo.softVer.minor); // cJSON_AddNumberToObject(root, "totalSeconds", totalSeconds); cJSON_AddNumberToObject(root, "batVoltage", dcBuff.dtuData.batVoltage); cJSON_AddNumberToObject(root, "batPct", dcBuff.dtuData.batPct); cJSON_AddNumberToObject(root, "latitude", dcBuff.dtuData.latitude); cJSON_AddNumberToObject(root, "longitude", dcBuff.dtuData.longitude); // sprintf(utc, "%04d-%02d-%02dT%02d:%02d:%02d", dcBuff.dtuData.sysTime.year, dcBuff.dtuData.sysTime.month, dcBuff.dtuData.sysTime.day, // dcBuff.dtuData.sysTime.hour, dcBuff.dtuData.sysTime.minute, dcBuff.dtuData.sysTime.second); // cJSON_AddStringToObject(root, "pos_utc", utc); //// cJSON_AddNumberToObject(root, "sateCount", dcBuff.dtuData.sateCount);// 卫星数量 // // // sprintf(utc, "%04d-%02d-%02dT%02d:%02d:%02d", sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, // sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); // cJSON_AddStringToObject(root, "data_utc", utc);// 数据时间 // ////////////////////// // cJSON_AddNumberToObject(root, "rssi", dcBuff.dtuData.rssi);// 信号强度 // cJSON_AddStringToObject(root, "simNumber", dcBuff.powerInfo.simNumber);// // // //len= strlen(json_str); // printf("\n222\n"); // cJSON_AddNumberToObject(root, "type", dcBuff.configBottle.type);// 储罐类型 // cJSON_AddNumberToObject(root, "diameter", dcBuff.configBottle.diameter); //len= strlen(json_str); // cJSON_AddNumberToObject(root, "len", dcBuff.configBottle.len); //len= strlen(json_str); //cJSON_AddNumberToObject(root, "v", Theoretical_Param.v); //cJSON_AddNumberToObject(root, "chargePct", dcBuff.configBottle.chargePct); printf("\n333\n"); //cJSON_AddNumberToObject(root, "source", dcBuff.configBottle.source); //len= strlen(json_str); //cJSON_AddStringToObject(root, "server", dcBuff.configData.server); //cJSON_AddNumberToObject(root, "port", dcBuff.configData.port); printf("\n444\n"); cJSON_AddNumberToObject(root, "intervalTrans", dcBuff.configData.intervalTrans); cJSON_AddNumberToObject(root, "intervalSample", dcBuff.configData.intervalSample); cJSON_AddNumberToObject(root, "warnPress", dcBuff.configBottle.warnPress); cJSON_AddNumberToObject(root, "warnPressH", dcBuff.configBottle.warnPressH); cJSON_AddNumberToObject(root, "fullPct", dcBuff.configBottle.fullPct); //printf("\n455\n"); cJSON_AddNumberToObject(root, "priPct", dcBuff.configBottle.priPct); cJSON_AddNumberToObject(root, "orderPct", dcBuff.configBottle.orderPct); cJSON_AddNumberToObject(root, "emptyPct", dcBuff.configBottle.emptyPct); cJSON_AddNumberToObject(root, "warnVolt", dcBuff.configBottle.warnVolt); cJSON_AddNumberToObject(root, "warnVoltH", dcBuff.configBottle.warnVoltH); cJSON_AddNumberToObject(root, "planMount", dcBuff.configBottle.planMount); cJSON_AddNumberToObject(root, "predictMount", dcBuff.configBottle.predictMount); cJSON_AddNumberToObject(root, "floorLevel", dcBuff.configBottle.floorLevel); cJSON_AddNumberToObject(root, "span", dcBuff.configBottle.span); //cJSON_AddNumberToObject(root, "spanPeriod", dcBuff.configBottle.spanPeriod); // cJSON_AddNumberToObject(root, "adDPress", dcBuff.sampleData.adDPress); // cJSON_AddNumberToObject(root, "adPress", dcBuff.sampleData.adPress); // cJSON_AddNumberToObject(root, "adExtTempr", dcBuff.sampleData.adExtTempr[0]); // // cJSON_AddNumberToObject(root, "utc", utc); // cJSON_AddBoolToObject(root, "is_awesome", 1); // 1=true, 0=false // // 3. ??????? JSON ?? // cJSON *features = cJSON_CreateObject(); // cJSON_AddStringToObject(features, "language", "C/C++"); // cJSON_AddNumberToObject(features, "speed", 100); // cJSON_AddItemToObject(root, "features", features); // // 4. ?????? // cJSON *tags = cJSON_CreateArray(); // cJSON_AddItemToArray(tags, cJSON_CreateString("AI")); // cJSON_AddItemToArray(tags, cJSON_CreateString("JSON")); // cJSON_AddItemToArray(tags, cJSON_CreateString("Parser")); // cJSON_AddItemToObject(root, "tags", tags); // 5. ? JSON ???????(?????) // uint16_t len = sprintf((char*)Task_sendBuff,json_str); char *json_str = cJSON_Print(root); len= strlen(json_str); for(int i=0; imark = CONFIG_MARK_LS; pSend->ver = htons(dcBuff.powerInfo.protocolVer.major); pSend->trans = 0; pSend->len = htons(len - sizeof(bluetooth_send_t) + 2); pSend->cmd = htons(cmd); crc = MODBUS_RTU_CRC16((uint8_t *) Task_sendBuff, len); Int2ByteS(Task_sendBuff, len, htons(crc)); return len + 2; } uint16_t pack_ldms_info_data(uint32_t dataTime, uint32_t totalSeconds) { uint16_t i = 0; S_RTC_TIME_DATA_T sRTC; bluetooth_timestamp_t t; memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); // 头信息(最后再填内容) i += sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; Task_sendBuff[i++] = dcBuff.powerInfo.hardVer.major; Task_sendBuff[i++] = dcBuff.powerInfo.hardVer.minor; Task_sendBuff[i++] = dcBuff.powerInfo.softVer.major; Task_sendBuff[i++] = dcBuff.powerInfo.softVer.minor; // 软件日期:yyyymmdd Int2ByteL(Task_sendBuff, i, htonl((2000 + dcBuff.powerInfo.softDate.year) * 10000 + dcBuff.powerInfo.softDate.month * 100 + dcBuff.powerInfo.softDate.day)); i += 4; // Report format Task_sendBuff[i++] = dcBuff.powerInfo.protocolVer.major; Task_sendBuff[i++] = dcBuff.powerInfo.protocolVer.minor; // Config format Task_sendBuff[i++] = dcBuff.configBottle.header.ver.major; Task_sendBuff[i++] = dcBuff.configBottle.header.ver.minor; // 运行时间:分钟 Int2ByteL(Task_sendBuff, i, htonl(totalSeconds / 60)); i += 4; Int2ByteS(Task_sendBuff, i, htons(SYS_RSTSTS)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.dtuData.batCurrent)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.dtuData.batVoltage / 10)); i += 2; Task_sendBuff[i++] = dcBuff.dtuData.batPct; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.dtuData.batCapa)); i += 4; if(bat_veryLow) Task_sendBuff[i] = 2; else if(dcBuff.dtuData.batLow) Task_sendBuff[i] = 1; else Task_sendBuff[i] = 0; i++; if(dcBuff.dtuData.posState) Int2ByteL(Task_sendBuff, i, htonl(dcBuff.dtuData.latitude)); i += 4; if(dcBuff.dtuData.posState) Int2ByteL(Task_sendBuff, i, htonl(dcBuff.dtuData.longitude)); i += 4; // 定位时间 if(dcBuff.dtuData.posState) { t.year = dcBuff.dtuData.sysTime.year + 2000 - 2010; t.mon = dcBuff.dtuData.sysTime.month; t.day = dcBuff.dtuData.sysTime.day; t.hour_H = dcBuff.dtuData.sysTime.hour >> 4; t.hour_L = dcBuff.dtuData.sysTime.hour & 0x0F; t.min = dcBuff.dtuData.sysTime.minute; t.sec = dcBuff.dtuData.sysTime.second; Int2ByteL(Task_sendBuff, i, htonl(t.tm)); } i += 4; // 卫星数量 Task_sendBuff[i++] = dcBuff.dtuData.sateCount; // 数据时间 Wakeup_CalcUTCTime(dataTime + RTC_offsetSeconds, &sRTC); t.year = sRTC.u32Year - 2010; t.mon = sRTC.u32Month; t.day = sRTC.u32Day; t.hour_H = sRTC.u32Hour >> 4; t.hour_L = sRTC.u32Hour & 0x0F; t.min = sRTC.u32Minute; t.sec = sRTC.u32Second; Int2ByteL(Task_sendBuff, i, htonl(t.tm)); i += 4; // 信号强度 Task_sendBuff[i++] = dcBuff.dtuData.rssi; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.powerInfo.gprsSuccCount)); i += 4; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.powerInfo.gprsSendCount - dcBuff.powerInfo.gprsSuccCount)); i += 4; if(dcBuff.powerInfo.gprsSendCount > 0) Task_sendBuff[i] = dcBuff.powerInfo.gprsSuccCount * 100 / dcBuff.powerInfo.gprsSendCount; i++; memmove(Task_sendBuff + i, dcBuff.powerInfo.gprsFailCode, strlen(dcBuff.powerInfo.gprsFailCode)); i += 6; memmove(Task_sendBuff + i, dcBuff.powerInfo.simNumber, strlen(dcBuff.powerInfo.simNumber)); i += 24; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.powerInfo.bdNumber)); i += 4; // 储罐类型 Task_sendBuff[i++] = dcBuff.configBottle.type; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.diameter)); i += 4; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.len)); i += 4; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.lenExtra)); i += 4; Int2ByteL(Task_sendBuff, i, htonl(Theoretical_Param.v)); i += 4; Task_sendBuff[i++] = dcBuff.configBottle.chargePct; Task_sendBuff[i++] = dcBuff.configBottle.source; Int2ByteS(Task_sendBuff, i, htons(Config_GetDensity(dcBuff.configBottle.source) * 1000)); i += 2; Task_sendBuff[i++] = dcBuff.configBottle.dispMode; Task_sendBuff[i++] = dcBuff.configDisplay.L_Unit; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.serverVer)); i += 2; memmove(Task_sendBuff + i, dcBuff.configData.server, strlen(dcBuff.configData.server)); i += 26; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.port)); i += 2; memmove(Task_sendBuff + i, dcBuff.configData.gpsServer, strlen(dcBuff.configData.gpsServer)); i += 26; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.gpsPort)); i += 2; memmove(Task_sendBuff + i, dcBuff.configData.upgServer, strlen(dcBuff.configData.upgServer)); i += 26; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.upgPort)); i += 2; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configData.intervalTrans)); i += 4; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configData.intervalSample)); i += 4; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.intervalGPSTrans)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configData.intervalGPS)); i += 2; Task_sendBuff[i++] = dcBuff.configData.timeLag; strcpy((char *) Task_sendBuff + i, DTU_DecideAPN()); i += 20; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configDisplay.bdCommander)); i += 4; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnPress)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnPressH)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.fullPct)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.priPct)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.orderPct)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.emptyPct)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnVolt)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnVoltH)); i += 2; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.planMount)); i += 4; Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.predictMount)); i += 4; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.floorLevel)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.span)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.spanPeriod)); i += 2; // 测量方式 Task_sendBuff[i++] = MEASURE_DPRESS; Task_sendBuff[i++] = 0; Task_sendBuff[i++] = dcBuff.configDisplay.op_USE_PT100_SENSOR ? 0 : 1; // 差压传感器参数 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorDPress.lowRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorDPress.highRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorDPress.zeroValue)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorDPress.fullValue)); i += 2; // 电容传感器参数 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorCap.baseC)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorCap.refC)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorCap.c1ADC)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorCap.c2ADC)); i += 2; Int2ByteS(Task_sendBuff, i, htons(CAP_K_C1)); i += 2; Int2ByteS(Task_sendBuff, i, htons(CAP_K_C2)); i += 2; // 称重传感器参数 // Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configSensor.sensorWeight.lowRange)); Int2ByteL(Task_sendBuff, i, htonl(dcBuff.sampleData.adDPress)); i += 4; // Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configSensor.sensorWeight.highRange)); Int2ByteL(Task_sendBuff, i, htonl(dcBuff.sampleData.adPress)); i += 4; // Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configSensor.sensorWeight.zeroValue)); Int2ByteL(Task_sendBuff, i, htonl(dcBuff.sampleData.adExtTempr[0])); i += 4; // Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configSensor.sensorWeight.fullValue)); Int2ByteL(Task_sendBuff, i, htonl(dcBuff.sampleData.adExtTempr[1])); i += 4; // 压力传感器参数 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPress.lowRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPress.highRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPress.zeroValue)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPress.fullValue)); i += 2; // 扩展压力传感器1参数 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorEPress[0].lowRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorEPress[0].highRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorEPress[0].zeroValue)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorEPress[0].fullValue)); i += 2; if(dcBuff.configDisplay.op_USE_PT100_SENSOR) { // 扩展温度传感器1参数 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[0].calibrateT)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[0].calibrateR)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[0].zeroValue)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[0].fullValue)); i += 2; // 扩展温度传感器2参数 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[1].calibrateT)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[1].calibrateR)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[1].zeroValue)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorPTempr[1].fullValue)); i += 2; } else { // 扩展温度传感器1参数 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorMTempr[0].lowRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorMTempr[0].highRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorMTempr[0].zeroValue)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorMTempr[0].fullValue)); i += 2; // 扩展温度传感器2参数 Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorMTempr[1].lowRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorMTempr[1].highRange)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorMTempr[1].zeroValue)); i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configSensor.sensorMTempr[1].fullValue)); i += 2; } // 填写固定字段 return fill_biDir_fixFields(0xD035, i); } #define D036_PARAM_SIZE (240) uint8_t parse_param_D036_data(uint8_t *param, uint8_t *reset) { longlong_mask_t mask; uint16_t i = 0, shift = 0; // 参数有效标志位(用一个无符号长整数表示, 共63项可选配置(bit 0~62), 最高位(bit 63)代表复位命令) // 网络字节序: 12 34 56 78 90 ab cd ef // h = 0x78563412, l = 0xefcdab90 (网络字节序) // h = 0x12345678, l = 0x90abcdef (本机字节序) // mask = 0x1234567890abcdef mask.h = ntohl(Byte2IntL(param, i)); i += 4; mask.l = ntohl(Byte2IntL(param, i)); i += 4; printf("\nmask = %016llX\n", mask.ll); // 储罐类型 if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.type = param[i]; i++; // 直径 if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.diameter = ntohl(Byte2IntL(param, i)); i += 4; // 长度 if(mask.ll & (1ull << (shift++))) { dcBuff.configBottle.len = ntohl(Byte2IntL(param, i)); dcBuff.configBottle.lenExtra = 0; } i += 4; // 充装比 if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.chargePct = param[i]; i++; // 介质 if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.source = param[i]; i++; // 密度 if(mask.ll & (1ull << (shift++))) Config_SetDensity(dcBuff.configBottle.source, ntohs(Byte2IntS(param, i)) / 1000.0); i += 2; // 显示模式 if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.dispMode = param[i]; i++; // 显示单位 if(mask.ll & (1ull << (shift++))) dcBuff.configDisplay.L_Unit = param[i]; i++; // 服务器版本 if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.serverVer = ntohs(Byte2IntS(param, i)); i += 2; // 远传服务器 if(mask.ll & (1ull << (shift++))) strcpy(dcBuff.configData.server, (char *) param + i); i += 26; // 远传端口 if(mask.ll & (1ull << (shift++))) dcBuff.configData.port = ntohs(Byte2IntS(param, i)); i += 2; // 远传服务器 if(mask.ll & (1ull << (shift++))) strcpy(dcBuff.configData.gpsServer, (char *) param + i); i += 26; // 远传端口 if(mask.ll & (1ull << (shift++))) dcBuff.configData.gpsPort = ntohs(Byte2IntS(param, i)); i += 2; // 远传服务器 if(mask.ll & (1ull << (shift++))) strcpy(dcBuff.configData.upgServer, (char *) param + i); i += 26; // 远传端口 if(mask.ll & (1ull << (shift++))) dcBuff.configData.upgPort = ntohs(Byte2IntS(param, i)); i += 2; // 发送频率 if(mask.ll & (1ull << (shift++))) dcBuff.configData.intervalTrans = ntohl(Byte2IntL(param, i)); i += 4; // 采集频率 if(mask.ll & (1ull << (shift++))) dcBuff.configData.intervalSample = ntohl(Byte2IntL(param, i)); i += 4; // 发送频率 if(mask.ll & (1ull << (shift++))) dcBuff.configData.intervalGPSTrans = ntohs(Byte2IntS(param, i)); i += 2; // 采集频率 if(mask.ll & (1ull << (shift++))) dcBuff.configData.intervalGPS = ntohs(Byte2IntS(param, i)); i += 2; // 时差 if(mask.ll & (1ull << (shift++))) dcBuff.configData.timeLag = param[i]; i++; // APN if(mask.ll & (1ull << (shift++))) strcpy(dcBuff.configDisplay.APN, (char *) param + i); i += 20; // 北斗指挥机卡号 if(mask.ll & (1ull << (shift++))) dcBuff.configDisplay.bdCommander = ntohl(Byte2IntL(param, i)); i += 4; // 压力报警点低: KPa if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.warnPress = ntohs(Byte2IntS(param, i)); i += 2; // 压力报警点高: KPa if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.warnPressH = ntohs(Byte2IntS(param, i)); i += 2; // 满液位报警点: 0.01% if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.fullPct = ntohs(Byte2IntS(param, i)); i += 2; // 关键液位报警点: 0.01% if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.priPct = ntohs(Byte2IntS(param, i)); i += 2; // 订货液位报警点: 0.01% if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.orderPct = ntohs(Byte2IntS(param, i)); i += 2; // 空液位报警点: 0.01% if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.emptyPct = ntohs(Byte2IntS(param, i)); i += 2; // 电压报警低点: mV if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.warnVolt = ntohs(Byte2IntS(param, i)); i += 2; // 电压报警高点: mV if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.warnVoltH = ntohs(Byte2IntS(param, i)); i += 2; // 每日计划用量: L if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.planMount = ntohl(Byte2IntL(param, i)); i += 4; // 每日预测用量: L if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.predictMount = ntohl(Byte2IntL(param, i)); i += 4; // TTS-空液位报警点: 0.01% if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.floorLevel = ntohs(Byte2IntS(param, i)); i += 2; // TTS-变化量报警点: 0.01% if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.span = ntohs(Byte2IntS(param, i)); i += 2; // TTS-变化量检测时间: 秒 if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.spanPeriod = ntohs(Byte2IntS(param, i)); i += 2; // 差压传感器量程: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorDPress.lowRange = ntohs(Byte2IntS(param, i)); i += 2; // 差压传感器量程: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorDPress.highRange = ntohs(Byte2IntS(param, i)); i += 2; // 差压传感器标定: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorDPress.zeroValue = ntohs(Byte2IntS(param, i)); i += 2; // 差压传感器标定: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorDPress.fullValue = ntohs(Byte2IntS(param, i)); i += 2; // 电容传感器量程: 底电容 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorCap.baseC = ntohs(Byte2IntS(param, i)); i += 2; // 电容传感器量程: 增长电容 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorCap.refC = ntohs(Byte2IntS(param, i)); i += 2; // 电容传感器标定: C1ADC if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorCap.c1ADC = ntohs(Byte2IntS(param, i)); i += 2; // 电容传感器标定: C2ADC if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorCap.c2ADC = ntohs(Byte2IntS(param, i)); i += 2; // 称重传感器量程: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorWeight.lowRange = ntohl(Byte2IntL(param, i)); i += 4; // 称重传感器量程: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorWeight.highRange = ntohl(Byte2IntL(param, i)); i += 4; // 称重传感器标定: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorWeight.zeroValue = ntohl(Byte2IntL(param, i)); i += 4; // 称重传感器标定: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorWeight.fullValue = ntohl(Byte2IntL(param, i)); i += 4; // 压力传感器1量程: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPress.lowRange = ntohs(Byte2IntS(param, i)); i += 2; // 压力传感器1量程: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPress.highRange = ntohs(Byte2IntS(param, i)); i += 2; // 压力传感器1标定: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPress.zeroValue = ntohs(Byte2IntS(param, i)); i += 2; // 压力传感器1标定: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPress.fullValue = ntohs(Byte2IntS(param, i)); i += 2; // 压力传感器2量程: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorEPress[0].lowRange = ntohs(Byte2IntS(param, i)); i += 2; // 压力传感器2量程: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorEPress[0].highRange = ntohs(Byte2IntS(param, i)); i += 2; // 压力传感器2标定: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorEPress[0].zeroValue = ntohs(Byte2IntS(param, i)); i += 2; // 压力传感器2标定: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorEPress[0].fullValue = ntohs(Byte2IntS(param, i)); i += 2; if(dcBuff.configDisplay.op_USE_PT100_SENSOR) { // 温度传感器1量程: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPTempr[0].calibrateT = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器1量程: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPTempr[0].calibrateR = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器1标定: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPTempr[0].zeroValue = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器1标定: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPTempr[0].fullValue = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器2量程: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPTempr[1].calibrateT = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器2量程: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPTempr[1].calibrateR = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器2标定: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPTempr[1].zeroValue = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器2标定: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorPTempr[1].fullValue = ntohs(Byte2IntS(param, i)); i += 2; } else { // 温度传感器1量程: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorMTempr[0].lowRange = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器1量程: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorMTempr[0].highRange = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器1标定: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorMTempr[0].zeroValue = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器1标定: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorMTempr[0].fullValue = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器2量程: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorMTempr[1].lowRange = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器2量程: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorMTempr[1].highRange = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器2标定: 低 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorMTempr[1].zeroValue = ntohs(Byte2IntS(param, i)); i += 2; // 温度传感器2标定: 高 if(mask.ll & (1ull << (shift++))) dcBuff.configSensor.sensorMTempr[1].fullValue = ntohs(Byte2IntS(param, i)); i += 2; } *reset = ((mask.ll & (1ull << shift)) != 0); return ((mask.ll & ~(1ull << shift)) != 0); } #define D038_CONFIG_SIZE (74) uint8_t parse_config_D038_data(uint8_t *param) { uint16_t i = 0; // 服务器版本 dcBuff.configBottle.serverVer = ntohs(Byte2IntS(param, i)); i += 2; // 远传服务器 strcpy(dcBuff.configData.server, (char *) param + i); i += 26; // 远传端口 dcBuff.configData.port = ntohs(Byte2IntS(param, i)); i += 2; // 远传服务器 strcpy(dcBuff.configData.gpsServer, (char *) param + i); i += 26; // 远传端口 dcBuff.configData.gpsPort = ntohs(Byte2IntS(param, i)); i += 2; // 发送频率 dcBuff.configData.intervalTrans = ntohl(Byte2IntL(param, i)); i += 4; // 采集频率 dcBuff.configData.intervalSample = ntohl(Byte2IntL(param, i)); i += 4; // 硬件版本 dcBuff.configDisplay.op_HARDWARE_VER_MAJOR = param[i++]; // 只显示毫米水柱 dcBuff.configDisplay.op_DISP_MMWC_ONLY = param[i++]; // 罐箱版本 dcBuff.configDisplay.op_BOX_VER = param[i++]; // 基站定位 dcBuff.configDisplay.op_CELL_LOCATION = param[i++]; // 发送轨迹 dcBuff.configDisplay.op_SEND_GPS_DATA = param[i++]; // 通信方式 dcBuff.configDisplay.op_SERVER_PROTOCOL = param[i++]; // URL索引 dcBuff.configDisplay.op_SERVER_INDEX = param[i++]; // 单向通信 dcBuff.configDisplay.op_UNIDIR_COMM = param[i++]; return 1; } // 从服务器获取时间 void DTU_setOffsetSecondsFromServer() { bluetooth_send_t *pRecv = (bluetooth_send_t *) Task_recvBuff; S_RTC_TIME_DATA_T sRTC; uint32_t totalSeconds1, totalSeconds2; int16_t zz; uint16_t i, recvLen; // 从服务器获取当前时间 printf("\nGet time from server ...\n"); // 连接升级服务器 if(DTU_Connect(0, dcBuff.configData.upgServer, dcBuff.configData.upgPort)) { memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // 填写固定字段 i = fill_biDir_fixFields(0xD03B, i); // 发送i个字节到服务器,至少接收10个字节 recvLen = sizeof(bluetooth_recv_t) + 2; if(DTU_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { if(recvLen >= sizeof(bluetooth_recv_t) + 2 && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0) { if(recvLen >= sizeof(bluetooth_recv_t) + 11 && pRecv->cmd == ntohs(0x003B) && MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + 11) == 0) { // 获取当前时间 RTC_GetDateAndTime(&sRTC); totalSeconds1 = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); // UTC日期 i = sizeof(bluetooth_recv_t); // 年 sRTC.u32Year = ntohs(Byte2IntS(Task_recvBuff, i)); i += 2; // 月 sRTC.u32Month = Task_recvBuff[i++]; // 日 sRTC.u32Day = Task_recvBuff[i++]; // 时 sRTC.u32Hour = Task_recvBuff[i++]; // 分 sRTC.u32Minute = Task_recvBuff[i++]; // 秒 sRTC.u32Second = Task_recvBuff[i++]; // 时差(按1/4小时, 带符号) recvLen = ntohs(Byte2IntS(Task_recvBuff, i)); memmove(&zz, &recvLen, 2); printf("\n%04d-%02d-%02d %02d:%02d:%02d %d\n", sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second, zz); totalSeconds2 = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); // 将UTC时间转换为GMT时间(时差为0) totalSeconds2 -= zz * 900; // 将GMT时间转换为UTC时间(按配置的时差) totalSeconds2 += dcBuff.configData.timeLag * 3600; if(RTC_offsetSeconds == 0) RTC_offsetSeconds = totalSeconds2 - totalSeconds1; } } } // 关闭和服务器的连接 DTU_Close(0); } } //////////////////////////////////////////////////////////////////////////////////////// void DTU_CheckGPS() { uint32_t time; S_RTC_TIME_DATA_T sRTC; if(DTU_hasPowered) { // 获取当前时间 RTC_GetDateAndTime(&sRTC); // 计算自上次gps定位以来的时间 time = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); if(!Wakeup_Sleeping && time > DTU_gpsTime + 30 && (GPS_Waiting || dcBuff.configDisplay.op_SEND_GPS_DATA)) { // 如果是第一次,或者曾经有输出了,则闪断计数 if(GPS_BOD_COUNT == 599) GPS_BOD_COUNT = 0; else GPS_BOD_COUNT++; printf("\nGPS_BOD_COUNT: %d\n", GPS_BOD_COUNT); printf("\n*** Restart GPS module ***\n"); DTU_EnableGPS(); DTU_gpsTime = time; } } } // 任务主体:发送运行数据和GPS数据,读取网络信号强度等 void DTU_Task(void *p_arg) { bluetooth_send_t *pSend = (bluetooth_send_t *) Task_sendBuff; bluetooth_send_t *pRecv = (bluetooth_send_t *) Task_recvBuff; uint16_t crc; uint16_t i, j, k; uint8_t gpsCount, gpsDone; uint16_t gpsInterval; uint32_t totalSeconds; uint32_t relativeTime; S_RTC_TIME_DATA_T sRTC; gprs_data_t *pGprs; uint8_t try_count; uint16_t recvLen; uint8_t upgrade; uint8_t ackUpgrade; uint8_t downloadParam; uint8_t ackParam; uint8_t downloadConfig; uint8_t ackConfig; uint8_t reset = 0; param_data_t *pParam; TUpgradeHeader upHeader; upgrade_frame_t *pFrame; gps_data_t gps; uint16_t nextPtr; uint8_t write_count; uint8_t rf_fail_count = 0; uint8_t semSync, semGPRS, semGPS; uint32_t tick; // 从FRAM读取阿里云密钥信息 FRAM_LoadInfo(FRAM_ALIYUN_SECRET_BASE, (uint8_t *) &aliyunSecret, sizeof(aliyunSecret)); // 从FRAM读取GPS信息 FRAM_LoadInfo(gpsBuff.info_base, (uint8_t *) &gpsBuff.info, sizeof(gpsBuff.info)); if(gpsBuff.info.rdPtr > gpsBuff.maxItemCount || gpsBuff.info.wtPtr > gpsBuff.maxItemCount) memset(&gpsBuff.info, 0, sizeof(gpsBuff.info)); // 清除数据 memset(&dcBuff.dtuData, 0, sizeof(dcBuff.dtuData)); // 读取其它板子的配置数据 // 启动定时器 GPS_tranTick = GetDelayTick(dcBuff.configData.intervalGPSTrans * 1000); if(dcBuff.configDisplay.op_BOX_VER) { // 检查是否有BD模块 BD_PowerOn(); BD_PowerOff(); // 检查是否有RF模块 RF_PowerOn(); RF_PowerOff(); } // 上电运行一次任务 DTU_semSync = 1; DTU_semGPRS = 1; DTU_semGPS = 1; while(1) { // 喂狗 if(!Wakeup_Sleeping) WDT_RESET_COUNTER(); // 读取信号量 semSync = DTU_semSync; DTU_semSync = 0; semGPRS = DTU_semGPRS; DTU_semGPRS = 0; semGPS = DTU_semGPS; DTU_semGPS = 0; // 获取当前时间 RTC_GetDateAndTime(&sRTC); // 计算自上次gps定位以来的时间 totalSeconds = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day, sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second); // 刚开始运行的时候,回退到刚启动的时间(忽略系统初始化时间) if(totalSeconds < 10) totalSeconds = 0; // 默认不保存、不发送 GPRS_Send_Task = 0; GPRS_Save_Task = 0; //pack_json_send_data(pGprs, totalSeconds); // 是否强制上传 if(DTU_dataConn) { DTU_dataConn = 0; GPRS_Send_Task = 1; } // 是否强制定位 if(GPS_Locate) { GPS_Locate = 0; // 强制定位:保存和发送 GPRS_Send_Task = 1; GPRS_Save_Task = 1; // 设置超时定时器 GPS_waitTick = GetDelayTick(DTU_tmrLocate * 1000); GPS_Waiting = 1; } // GPS发送周期:检查电池电量 if(semGPS || semSync) { delay_ms(200); // 先清除信号量 GPRS_semSampled = 0; // 采集数据 if(!Sample_Busy()) NVIC_SetPendingIRQ(TMR1_IRQn); tick = GetDelayTick(3000); while(!GPRS_semSampled && !IsTickOut(tick)) { } // 根据电量设置工作模式 Wakeup_SetWorkMode(); } // 检测唤醒同步信号 if(semGPRS || semSync) { if(dcBuff.sampleData.warnning) { printf("\n*** dcBuff.sampleData.warnning = 1 ***\n"); GPRS_Send_Task = 1; dcBuff.sampleData.warnning = 0; } // 判断是否发送周期 // 如果发送时间到了,或者队列中的数据够了,则发送数据(为了工程测试方便,刚开始几次按照不大于5分钟的频率发送) if(dcBuff.configDisplay.op_SEND_GPS_DATA) { // 发送间隔最小值 if(totalSeconds + 3 >= GPRS_Send_Time + (dcBuff.configData.intervalTrans > 300 ? 300 : dcBuff.configData.intervalTrans)) GPRS_Send_Task = 1; } else { if(((SYS_RSTSTS & 0x13) && !(SYS_RSTSTS & 0x04) && // 上电或手动复位, 非看门狗复位 totalSeconds < INITIAL_TRAN_COUNT * (dcBuff.configData.intervalSample > 300 ? 300 : dcBuff.configData.intervalSample)) || totalSeconds + 3 >= GPRS_Send_Time + dcBuff.configData.intervalTrans // || LoopBuff_GetCount(&gprsBuff) >= dcBuff.configData.intervalTrans / dcBuff.configData.intervalSample - 1 ) ////// if(LoopBuff_GetCount(&gprsBuff) >= 11) { // 发送间隔最小值 if(totalSeconds + 3 >= GPRS_Send_Time + (dcBuff.configData.intervalTrans > 300 ? 300 : dcBuff.configData.intervalTrans)) GPRS_Send_Task = 1; } // else if(Config_CheckUpdate(&dcBuff)) // { // GPRS_Send_Task = 1; // } } // 判断是否保存周期 if(GPRS_Send_Task || totalSeconds + 3 >= GPRS_Save_Time + dcBuff.configData.intervalSample) GPRS_Save_Task = 1; if(GPRS_Send_Task && ((dcBuff.configDisplay.op_BOX_VER && (Motion_Detected || Motion_Status)) || (dcBuff.configDisplay.op_SEND_GPS_DATA && Wakeup_GetWorkMode() == WORK_MODE_NORMAL))) { GPS_Located = 0; // 设置超时定时器 GPS_waitTick = GetDelayTick(DTU_tmrLocate * 1000); GPS_Waiting = 1; } } // 运行数据发送周期:检测信号强度 if(semGPRS || semSync) { if(Wakeup_GetWorkMode() == WORK_MODE_NORMAL && GPRS_Send_Task) { delay_ms(200); // 打开DTU(开始定位) dcBuff.dtuData.networked = 0; if(RF_initStatus) { // 打开射频模块 RF_PowerOn(); // 检查中继器是否存在 rf_check_gateway(); // 关闭射频模块 RF_PowerOff(); } if(!rf_has_gateway() || GPS_Waiting || dcBuff.configDisplay.op_SEND_GPS_DATA) { DTU_PowerOn(); // 重新开始定位计时,保证足够定位时间 GPS_waitTick = GetDelayTick(DTU_tmrLocate * 1000); // 采集信号强度和注册信息 Sim808_ReadGPRS(); printf("\ndcBuff.dtuData.networked: %d\n", dcBuff.dtuData.networked); // 如果有GPRS但是信号很弱 if(rf_has_gateway() && dcBuff.dtuData.rssi < 30) dcBuff.dtuData.networked = 0; if(!dcBuff.dtuData.networked) dcBuff.dtuData.rssi = 0; } } // 每小时保存1条数据 if(Wakeup_GetWorkMode() == WORK_MODE_NORMAL && GPRS_Save_Task) { if(GPRS_Send_Task) { // GPRS拨号和GPS定位同时进行,以节省时间 if(dcBuff.dtuData.networked) Sim808_GPRSDial(); // 如果不发送轨迹数据,则等待定位完成再发送运行数据 while(!dcBuff.configDisplay.op_SEND_GPS_DATA && Wakeup_GetWorkMode() == WORK_MODE_NORMAL && GPS_Waiting) { // 喂狗 if(!Wakeup_Sleeping) WDT_RESET_COUNTER(); delay_ms(200); } if(!dcBuff.configDisplay.op_SEND_GPS_DATA) { // 关闭GPS DTU_DisableGPS(); } // 获取基站定位数据 if(GPRS_Send_Task && !GPS_Locate && !GPS_Located) { if(dcBuff.configDisplay.op_CELL_LOCATION) Sim808_GetCellLocPosition(); } // 本次定位结束 GPS_Located = 1; // 下次有运动才定位(罐箱) Motion_Detected = 0; // 先清除信号量 GPRS_semSampled = 0; // 采集数据 if(!Sample_Busy()) NVIC_SetPendingIRQ(TMR1_IRQn); tick = GetDelayTick(3000); while(!GPRS_semSampled && !IsTickOut(tick)) { } // 记录本次发送的时间 GPRS_Send_Time = totalSeconds; } // 加入队列,待发送 printf("\nPut gprs data to queue...\n"); GPRS_PutToQueue(&gprsBuff, &dcBuff.dtuData, &dcBuff.sampleData); // 每条记录,北斗发送2次 if(BD_initStatus) { GPRS_PutToQueue(&bd_gprsBuff, &dcBuff.dtuData, &dcBuff.sampleData); GPRS_PutToQueue(&bd_gprsBuff, &dcBuff.dtuData, &dcBuff.sampleData); } // 记录本次保存的时间 GPRS_Save_Time = totalSeconds; } } // 用北斗发送数据 if(BD_initStatus && (semGPRS || semSync)) { // 每采集1条就发送1条 if(LoopBuff_GetCount(&bd_gprsBuff) > 0) { if(Wakeup_GetWorkMode() == WORK_MODE_NORMAL) { // 打开北斗模块 BD_PowerOn(); if(BD_initStatus) { FRAM_BufferRead(LoopBuff_GetDataPos(&bd_gprsBuff, bd_gprsBuff.info.rdPtr), (uint8_t *) &gprsRWBuf, sizeof(gprs_data_t)); pGprs = &gprsRWBuf; // 打包上报数据(按北斗精简报文的格式) i = pack_bd_send_data(pGprs, totalSeconds); bd_rf_app_send_data(i, Task_sendBuff); delay_ms(200); } // 关闭北斗模块 BD_PowerOff(); } // 不管是否发送成功,都移除记录(因为1分钟发送一次,没有重发机制) LoopBuff_RemoveItems(&bd_gprsBuff, 1); } } // 优先用射频发送数据 if(rf_has_gateway() && (semGPRS || semSync)) { if(Wakeup_GetWorkMode() == WORK_MODE_NORMAL && GPRS_Send_Task) { // 关闭GPRS DTU_PowerOff(); // 打开射频模块 RF_PowerOn(); k = LoopBuff_GetCount(&gprsBuff); while(k--) { FRAM_BufferRead(LoopBuff_GetDataPos(&gprsBuff, gprsBuff.info.rdPtr), (uint8_t *) &gprsRWBuf, sizeof(gprs_data_t)); pGprs = &gprsRWBuf; // 打包上报数据(按RF精简报文的格式) i = pack_rf_send_data(pGprs, totalSeconds); try_count = 3; while(try_count--) { j = rf_app_send_data(i, Task_sendBuff); if(j == 1) { rf_fail_count = 0; LoopBuff_RemoveItems(&gprsBuff, 1); break; } } if(j == 0) { rf_fail_count++; if(rf_fail_count >= 3) { // 清除网关信息 rf_fail_count = 0; rf_clear_gateway(); } // 下次再来 break; } } // 关闭射频模块 RF_PowerOff(); } } // 如果没有卡,或者没有注册进网络,采集以后休眠 if(!dcBuff.dtuData.networked) { // 检查是否进入掉电模式 Wakeup_Powerdown(); continue; } // 检测发送采集数据的信号 if(semGPRS || semSync) { if(Wakeup_GetWorkMode() == WORK_MODE_NORMAL && GPRS_Send_Task) { // 是否下载参数:数据服务器 downloadParam = 0; ackParam = 0; dcBuff.configDisplay.op_SERVER_PROTOCOL = SERVER_PROTOCOL_MQTT; dcBuff.configDisplay.op_SERVER_INDEX = 2; dcBuff.configData.port=1883; if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_HTTPS) { try_count = 2; while((try_count--) && LoopBuff_GetCount(&gprsBuff) > 0) { // 第一条记录,连接就开始计数 if(LoopBuff_GetCount(&gprsBuff) > 0) dcBuff.powerInfo.gprsSendCount++; if(Sim808_Connect(1, dcBuff.configData.server, dcBuff.configData.port)) { nextPtr = gprsBuff.info.rdPtr; for(k = 0; k < LoopBuff_GetCount(&gprsBuff); k++) { if(k > 0) // 第一条发送计数在连接之前 dcBuff.powerInfo.gprsSendCount++; FRAM_BufferRead(LoopBuff_GetDataPos(&gprsBuff, nextPtr), (uint8_t *) &gprsRWBuf, sizeof(gprs_data_t)); pGprs = &gprsRWBuf; nextPtr = LoopBuff_GetNextPtr(&gprsBuff, nextPtr); // 打包上报数据(按modbus从机响应的格式) i = pack_json_send_data(pGprs, totalSeconds); sprintf((char *) Task_sendBuff, http_header_fmt, SERVER_URLs[dcBuff.configDisplay.op_SERVER_INDEX], dcBuff.configData.server, i); printf("\n\n%s%s\n", Task_sendBuff, JSON_data()); recvLen = 0; // 发送HTTP头,完了直接返回,不等结果 if(!Sim808_SendAndRecv(1, Task_sendBuff, strlen((char *) Task_sendBuff), &recvLen, Task_recvBuff, sizeof(Task_recvBuff))) break; recvLen = 15; // 发送数据,完了等结果 if(!Sim808_SendAndRecv(1, (uint8_t *) JSON_data(), i, &recvLen, Task_recvBuff, sizeof(Task_recvBuff))) break; if(!strstr((char *) Task_recvBuff, "HTTP/1.1 200 OK")) { strcpy(dcBuff.powerInfo.gprsFailCode, "HTTP"); break; } dcBuff.powerInfo.gprsSuccCount++; // 最近一条上传数据的采集时间 DTU_dataTime = pGprs->sample_time; } // 移除已成功发送的数据 if(k > 0) LoopBuff_RemoveItems(&gprsBuff, k); // 关闭和服务器的连接 DTU_Close(1); } } } else if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_MQTT) { // 检查阿里云密钥是否有效,如无效则下载 // try_count = 2; // while((try_count--) && // (aliyunSecret.check != 0x55AA || memcmp(aliyunSecret.PSN, dcBuff.configBottle.PSN, 6) != 0)) // { // // 连接升级服务器 // if(Sim808_Connect(0, dcBuff.configData.upgServer, dcBuff.configData.upgPort)) // { // printf("\nDownload aliyun secret ...\n"); // memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); // // i = sizeof(bluetooth_send_t); // // // PSN // memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); // i += 6; // // // 填写固定字段 // i = fill_biDir_fixFields(0xD037, i); // // // 发送i个字节到服务器,至少接收10个字节 // // 如果失败,下次再发送 // recvLen = sizeof(bluetooth_recv_t) + 2; // if(Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) // { // if(recvLen >= sizeof(bluetooth_recv_t) + 2 // && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0) // { // if(recvLen >= sizeof(bluetooth_recv_t) + ALIYUN_SECRET_SIZE + 2 // && pRecv->cmd == ntohs(0x0037) // && MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + ALIYUN_SECRET_SIZE + 2) == 0) // { // // 保存参数 // memmove(aliyunSecret.PSN, dcBuff.configBottle.PSN, 6); // strcpy(aliyunSecret.product, (char *) Task_recvBuff + sizeof(bluetooth_recv_t)); // strcpy(aliyunSecret.device, (char *) Task_recvBuff + sizeof(bluetooth_recv_t) + sizeof(aliyunSecret.product)); // strcpy(aliyunSecret.secret, (char *) Task_recvBuff + sizeof(bluetooth_recv_t) + sizeof(aliyunSecret.product) + sizeof(aliyunSecret.device)); // FRAM_SaveInfo(FRAM_ALIYUN_SECRET_BASE, (uint8_t *) &aliyunSecret, sizeof(aliyunSecret)); // } // } // } //\ // // 关闭和服务器的连接 // DTU_Close(0); // } // } try_count = 2; while((try_count--) && /*aliyunSecret.check == 0x55AA && memcmp(aliyunSecret.PSN, dcBuff.configBottle.PSN, 6) == 0 && */LoopBuff_GetCount(&gprsBuff) > 0) { // 第一条记录,连接就开始计数 if(LoopBuff_GetCount(&gprsBuff) > 0) dcBuff.powerInfo.gprsSendCount++; if(Sim808_MqttConnect(SERVER_URLs[dcBuff.configDisplay.op_SERVER_INDEX], dcBuff.configData.port)) { nextPtr = gprsBuff.info.rdPtr; for(k = 0; k < LoopBuff_GetCount(&gprsBuff); k++) { if(k > 0) // 第一条发送计数在连接之前 dcBuff.powerInfo.gprsSendCount++; FRAM_BufferRead(LoopBuff_GetDataPos(&gprsBuff, nextPtr), (uint8_t *) &gprsRWBuf, sizeof(gprs_data_t)); pGprs = &gprsRWBuf; nextPtr = LoopBuff_GetNextPtr(&gprsBuff, nextPtr); // 打包上报数据(按modbus从机响应的格式) //i = pack_gprs_send_data(pGprs, totalSeconds); i = pack_json_send_data(pGprs, totalSeconds); if(!Sim808_MqttPublish(Task_sendBuff, i)) break; dcBuff.powerInfo.gprsSuccCount++; // 最近一条上传数据的采集时间 DTU_dataTime = pGprs->sample_time; } // 移除已成功发送的数据 if(k > 0) LoopBuff_RemoveItems(&gprsBuff, k); // 关闭和服务器的连接 MQTT_Close(); } } } else if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_TCP) { try_count = 2; while((try_count--) && (LoopBuff_GetCount(&gprsBuff) > 0 // || Config_CheckUpdate(&dcBuff) || downloadParam || ackParam)) { // 第一条记录,连接就开始计数 if(LoopBuff_GetCount(&gprsBuff) > 0) dcBuff.powerInfo.gprsSendCount++; if(Sim808_Connect(0, dcBuff.configData.server, dcBuff.configData.port)) { // 普莱克斯、林德、宝钢的不再上传 if(dcBuff.configBottle.serverVer != 3 && dcBuff.configBottle.serverVer != 4 && dcBuff.configBottle.serverVer != 5 && !dcBuff.configDisplay.op_UNIDIR_COMM && Config_CheckUpdate(&dcBuff)) { printf("\nUpload parameters ...\n"); memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 参数时间戳 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.ts)); i += 4; // 打包参数 pParam = (param_data_t *) (Task_sendBuff + i); pack_param_DO23_data(pParam); i += sizeof(param_data_t); // 填写固定字段 i = fill_biDir_fixFields(0xD023, i); // 发送i个字节到服务器,至少接收10个字节 // 如果失败,下次再发送 recvLen = sizeof(bluetooth_recv_t) + 2; if(Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { if(recvLen >= sizeof(bluetooth_recv_t) + 2 && pRecv->cmd == ntohs(0x0023) && MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + 2) == 0) { // 清除更新标志,保存参数 dcBuff.configBottle.updateFlag = 0; Config_SaveConfig(); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_BOTTLE_CONFIG, &display_modifi); } } else { // 关闭和服务器的连接 DTU_Close(0); // 重连 continue; } } nextPtr = gprsBuff.info.rdPtr; for(k = 0; k < LoopBuff_GetCount(&gprsBuff); k++) { if(k > 0) // 第一条发送计数在连接之前 dcBuff.powerInfo.gprsSendCount++; FRAM_BufferRead(LoopBuff_GetDataPos(&gprsBuff, nextPtr), (uint8_t *) &gprsRWBuf, sizeof(gprs_data_t)); pGprs = &gprsRWBuf; nextPtr = LoopBuff_GetNextPtr(&gprsBuff, nextPtr); // 打包上报数据(按modbus从机响应的格式) i = pack_gprs_send_data(pGprs, totalSeconds); recvLen = 2; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) break; dcBuff.powerInfo.gprsSuccCount++; // 最近一条上传数据的采集时间 DTU_dataTime = pGprs->sample_time; // 从GPRS切换到RF,需要重新搜索网关 rf_fail_count = 0; rf_clear_gateway(); if(!dcBuff.configDisplay.op_UNIDIR_COMM) { if(recvLen >= 2 && Task_recvBuff[0] == 0xFF && Task_recvBuff[1] == 0x0F) { // 普莱克斯、林德的不再下载 if(dcBuff.configBottle.serverVer != 3 && dcBuff.configBottle.serverVer != 4) downloadParam = 1; } } } // 移除已成功发送的数据 if(k > 0) LoopBuff_RemoveItems(&gprsBuff, k); // 下载参数 if(downloadParam) { printf("\nDownload parameters ...\n"); memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 宝钢版本:用D036替代D021, 因为服务器端没有完整的参数信息,只能修改个别参数 if(dcBuff.configBottle.serverVer == 5) { // 填写固定字段 i = fill_biDir_fixFields(0xD036, i); } else { // 参数时间戳 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.ts)); i += 4; // 填写固定字段 i = fill_biDir_fixFields(0xD021, i); } // 发送i个字节到服务器,至少接收10个字节 recvLen = sizeof(bluetooth_recv_t) + 2; if(Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { if(recvLen >= sizeof(bluetooth_recv_t) + 2 && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0) { downloadParam = 0; if(recvLen >= sizeof(bluetooth_recv_t) + sizeof(param_data_t) + 2 && pRecv->cmd == ntohs(0x0021) && MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + sizeof(param_data_t) + 2) == 0) { // 解析参数 pParam = (param_data_t *) (Task_recvBuff + sizeof(bluetooth_recv_t)); parse_param_D021_data(pParam); // 清除更新标志, dcBuff.configBottle.updateFlag = 0; } else if(recvLen >= sizeof(bluetooth_recv_t) + D036_PARAM_SIZE + 2 && pRecv->cmd == ntohs(0x0036) && MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + D036_PARAM_SIZE + 2) == 0) { // 保存参数 parse_param_D036_data(Task_recvBuff + sizeof(bluetooth_recv_t), &reset); } // 保存参数 Config_SaveConfig(); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_BOTTLE_CONFIG, &display_modifi); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_SENSOR_CONFIG, &display_modifi); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_DATA_CONFIG, &display_modifi); ackParam = 1; } } else { // 关闭和服务器的连接 DTU_Close(0); // 重连 continue; } } // 确认参数 if(ackParam) { printf("\nConfirm download parameters ...\n"); // 发送确认 memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 参数时间戳 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.ts)); i += 4; // 填写固定字段 i = fill_biDir_fixFields(0xD022, i); // 发送i个字节到服务器,至少接收10个字节 // 如果失败,下次再发送 recvLen = sizeof(bluetooth_recv_t) + 2; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { // 关闭和服务器的连接 DTU_Close(0); // 重连 continue; } ackParam = 0; } // 关闭和服务器的连接 DTU_Close(0); } } } else if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_FURUI) { try_count = 2; while((try_count--) && LoopBuff_GetCount(&gprsBuff) > 0) { // 第一条记录,连接就开始计数 if(LoopBuff_GetCount(&gprsBuff) > 0) dcBuff.powerInfo.gprsSendCount++; if(Sim808_Connect(0, dcBuff.configData.server, dcBuff.configData.port)) { nextPtr = gprsBuff.info.rdPtr; for(k = 0; k < LoopBuff_GetCount(&gprsBuff); k++) { if(k > 0) // 第一条发送计数在连接之前 dcBuff.powerInfo.gprsSendCount++; FRAM_BufferRead(LoopBuff_GetDataPos(&gprsBuff, nextPtr), (uint8_t *) &gprsRWBuf, sizeof(gprs_data_t)); pGprs = &gprsRWBuf; nextPtr = LoopBuff_GetNextPtr(&gprsBuff, nextPtr); // 打包上报数据(按modbus从机响应的格式) i = pack_furui_send_data(pGprs, &relativeTime); printf("\nSend %d bytes to server:\n", i); for(j = 0; j < i; j++) printf("%02X ", Task_sendBuff[j]); printf("\n"); recvLen = 6; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) break; if(!parse_furui_recv_data(dcBuff.configBottle.PSN, relativeTime, recvLen)) break; dcBuff.powerInfo.gprsSuccCount++; // 最近一条上传数据的采集时间 DTU_dataTime = pGprs->sample_time; // 从GPRS切换到RF,需要重新搜索网关 rf_fail_count = 0; rf_clear_gateway(); } // 移除已成功发送的数据 if(k > 0) LoopBuff_RemoveItems(&gprsBuff, k); // 关闭和服务器的连接 DTU_Close(0); } } } // 是否连接维护平台:每隔12小时一次(普莱克斯、林德的每次连接) if(dcBuff.configBottle.serverVer == 3 || dcBuff.configBottle.serverVer == 4 || (!dcBuff.configDisplay.op_UNIDIR_COMM && (totalSeconds < INITIAL_TRAN_COUNT * (dcBuff.configData.intervalSample > 300 ? 300 : dcBuff.configData.intervalSample) || totalSeconds + 3 >= DTU_ldmsTime + 43200 || DTU_ldmsConn))) { // 清除强制连接维护平台标志 DTU_ldmsConn = 0; // 保存连接维护平台时间(刚复位时连续上传6次,但只保存第一次) if(totalSeconds >= 3600) DTU_ldmsTime = totalSeconds; // 是否升级或下载参数:维护平台 upgrade = 0; ackUpgrade = 0; downloadParam = 0; ackParam = 0; downloadConfig = 0; ackConfig = 0; reset = 0; k = 1; // 发送1条诊断信息 try_count = 2; while((try_count--) && (k || upgrade || ackUpgrade || downloadParam || ackParam || downloadConfig || ackConfig)) { // 连接升级服务器 if(Sim808_Connect(0, dcBuff.configData.upgServer, dcBuff.configData.upgPort)) { if(k) { // 发送诊断信息,至少接收12个字节 i = pack_ldms_info_data(DTU_dataTime, totalSeconds); recvLen = sizeof(bluetooth_recv_t) + 2 + 2; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { // 关闭和服务器的连接 DTU_Close(0); // 重连 continue; } if(recvLen >= sizeof(bluetooth_recv_t) + 2 + 2 && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0 && pRecv->cmd == ntohs(0x0035)) { upgrade = Task_recvBuff[sizeof(bluetooth_recv_t)]; downloadParam = Task_recvBuff[sizeof(bluetooth_recv_t) + 1]; downloadConfig = Task_recvBuff[sizeof(bluetooth_recv_t) + 2]; k--; // 发送成功 } } // 下载参数 if(downloadParam) { printf("\nDownload parameters ...\n"); memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 填写固定字段 i = fill_biDir_fixFields(0xD036, i); // 发送i个字节到服务器,至少接收10个字节 recvLen = sizeof(bluetooth_recv_t) + 2; if(Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { if(recvLen >= sizeof(bluetooth_recv_t) + 2 && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0) { downloadParam = 0; if(recvLen >= sizeof(bluetooth_recv_t) + D036_PARAM_SIZE + 2 && pRecv->cmd == ntohs(0x0036) && MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + D036_PARAM_SIZE + 2) == 0) { // 保存参数 if(parse_param_D036_data(Task_recvBuff + sizeof(bluetooth_recv_t), &reset)) { // 保存参数 Config_SaveConfig(); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_BOTTLE_CONFIG, &display_modifi); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_SENSOR_CONFIG, &display_modifi); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_DATA_CONFIG, &display_modifi); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_DISPLAY_CONFIG, &display_modifi); } ackParam = 1; } } } else { // 关闭和服务器的连接 DTU_Close(0); // 重连 continue; } } // 确认参数 if(ackParam) { printf("\nConfirm download parameters ...\n"); // 发送确认 memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 参数时间戳 Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.ts)); i += 4; // 填写固定字段 i = fill_biDir_fixFields(0xD022, i); // 发送i个字节到服务器,至少接收10个字节 // 如果失败,下次再发送 recvLen = sizeof(bluetooth_recv_t) + 2; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { // 关闭和服务器的连接 DTU_Close(0); // 重连 continue; } ackParam = 0; } // 下载配置 if(downloadConfig) { printf("\nDownload configuration ...\n"); memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 填写固定字段 i = fill_biDir_fixFields(0xD038, i); // 发送i个字节到服务器,至少接收10个字节 recvLen = sizeof(bluetooth_recv_t) + 2; if(Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { if(recvLen >= sizeof(bluetooth_recv_t) + 2 && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0) { downloadConfig = 0; if(recvLen >= sizeof(bluetooth_recv_t) + D038_CONFIG_SIZE + 2 && pRecv->cmd == ntohs(0x0038) && MODBUS_RTU_CRC16(Task_recvBuff, sizeof(bluetooth_recv_t) + D038_CONFIG_SIZE + 2) == 0) { // 保存参数 if(parse_config_D038_data(Task_recvBuff + sizeof(bluetooth_recv_t))) { // 保存参数 Config_SaveConfig(); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_BOTTLE_CONFIG, &display_modifi); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_SENSOR_CONFIG, &display_modifi); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_DATA_CONFIG, &display_modifi); // Can_Write(CONFIG_BOARD_SAMPLE,CAN_DC_DISPLAY_CONFIG, &display_modifi); } ackConfig = 1; } } } else { // 关闭和服务器的连接 DTU_Close(0); // 重连 continue; } } // 确认配置 if(ackConfig) { printf("\nConfirm download configuration ...\n"); // 发送确认 memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 填写固定字段 i = fill_biDir_fixFields(0xD039, i); // 发送i个字节到服务器,至少接收10个字节 // 如果失败,下次再发送 recvLen = sizeof(bluetooth_recv_t) + 2; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { // 关闭和服务器的连接 DTU_Close(0); // 重连 continue; } ackConfig = 0; // 配置改变,需要复位 reset = 1; } // 升级 if(upgrade) { printf("\nUpgrade software ...\n"); // 从FRAM读取初始进度 FRAM_LoadInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)); if(upInfo.fileSize == 0) { // 从头开始升级 memset(&upInfo, 0, sizeof(upInfo)); // 保存到铁电 for(write_count = 0; write_count < 2; write_count++) { FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)); if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo))) break; printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo)); delay_ms(200); } } // 下载数据 while(upInfo.fileSize == 0 || upInfo.offset < upInfo.fileSize) { memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 当前固件号 Int2ByteL(Task_sendBuff, i, htonl(upInfo.ver)); i += 4; // 文件偏移量 Int2ByteL(Task_sendBuff, i, htonl(upInfo.offset)); i += 4; // 请求数据长度 Int2ByteL(Task_sendBuff, i, htonl(UPGRADE_DATA_LEN)); i += 4; // 填写固定字段 i = fill_biDir_fixFields(0xD0E0, i); // 发送i个字节到服务器,至少接收10个字节 // 如果失败,下次再升级 recvLen = sizeof(bluetooth_recv_t) + 2; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) break; if(recvLen >= sizeof(bluetooth_recv_t) + 2 && MODBUS_RTU_CRC16(Task_recvBuff, recvLen) == 0) { if(pRecv->cmd == ntohs(0x00E0)) { pFrame = (upgrade_frame_t *) (Task_recvBuff + sizeof(bluetooth_recv_t)); if(MODBUS_RTU_CRC16(pFrame->data, ntohl(pFrame->len) + 2) == 0) { // 升级内容下载成功,允许继续升级 try_count = 2; // 如果升级包有变化 if(upInfo.fileSize > 0 && (upInfo.fileSize != ntohl(pFrame->fileSize) || upInfo.fileCrc != pFrame->fileCrc || upInfo.offset > ntohl(pFrame->fileSize) || upInfo.ver != ntohl(pFrame->ver))) { // 从头开始升级 memset(&upInfo, 0, sizeof(upInfo)); // 保存到铁电 for(write_count = 0; write_count < 2; write_count++) { FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)); if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo))) break; printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo)); delay_ms(200); } continue; } // 保存下载信息 // 如果只是网络通信失败,会断点续传 upInfo.ver = ntohl(pFrame->ver); upInfo.fileSize = ntohl(pFrame->fileSize); upInfo.offset = ntohl(pFrame->offset); upInfo.len = ntohl(pFrame->len); upInfo.fileCrc = pFrame->fileCrc; printf("\nfileSize = %d, offset = %d, len = %d\n", upInfo.fileSize, upInfo.offset, upInfo.len); // 如果是第一个包,先将升级请求改为0,以免意外重启导致boot-loader解压 // 待全部下载完以后,再改为1 if(upInfo.offset == 0) ((TUpgradeHeader *) pFrame->data)->upgrade_request = 0; #if UPGRADE_DATA_LEN >= SFLASH_ERASE_SIZE // 直接写入flash for(write_count = 0; write_count < 2; write_count++) { SFlash_BufferWrite(SFLASH_UPGRADE_BASE + upInfo.offset, pFrame->data, upInfo.len); if(SFlash_BufferVerify(SFLASH_UPGRADE_BASE + upInfo.offset, pFrame->data, upInfo.len)) break; printf("**** Verify SFlash failed at: 0x%08X, %d bytes\n", SFLASH_UPGRADE_BASE + upInfo.offset, upInfo.len); delay_ms(200); } upInfo.offset += upInfo.len; #else // 为了减少flash的多次擦写,又节约收发缓冲 // 先把数据拷到flash页缓冲 for(write_count = 0; write_count < 2; write_count++) { FRAM_BufferWrite(FRAM_UPGRADE_DATA_BASE + upInfo.offset % SFLASH_ERASE_SIZE, pFrame->data, upInfo.len); if(FRAM_BufferVerify(FRAM_UPGRADE_DATA_BASE + upInfo.offset % SFLASH_ERASE_SIZE, pFrame->data, upInfo.len)) break; printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_DATA_BASE + upInfo.offset % SFLASH_ERASE_SIZE, upInfo.len); delay_ms(200); } upInfo.offset += upInfo.len; // 够一页了,或者下载完了就从铁电写入flash if(upInfo.offset % SFLASH_ERASE_SIZE == 0) { FRAM_BufferRead(FRAM_UPGRADE_DATA_BASE, Task_recvBuff, SFLASH_ERASE_SIZE); for(write_count = 0; write_count < 2; write_count++) { SFlash_BufferWrite(SFLASH_UPGRADE_BASE + (upInfo.offset - SFLASH_ERASE_SIZE), Task_recvBuff, SFLASH_ERASE_SIZE); if(SFlash_BufferVerify(SFLASH_UPGRADE_BASE + (upInfo.offset - SFLASH_ERASE_SIZE), Task_recvBuff, SFLASH_ERASE_SIZE)) break; printf("**** Verify SFlash failed at: 0x%08X, %d bytes\n", SFLASH_UPGRADE_BASE + (upInfo.offset - SFLASH_ERASE_SIZE), SFLASH_ERASE_SIZE); delay_ms(200); } } else if(upInfo.offset == upInfo.fileSize) { FRAM_BufferRead(FRAM_UPGRADE_DATA_BASE, Task_recvBuff, upInfo.offset % SFLASH_ERASE_SIZE); for(write_count = 0; write_count < 2; write_count++) { SFlash_BufferWrite(SFLASH_UPGRADE_BASE + (upInfo.offset - upInfo.offset % SFLASH_ERASE_SIZE), Task_recvBuff, upInfo.offset % SFLASH_ERASE_SIZE); if(SFlash_BufferVerify(SFLASH_UPGRADE_BASE + (upInfo.offset - upInfo.offset % SFLASH_ERASE_SIZE), Task_recvBuff, upInfo.offset % SFLASH_ERASE_SIZE)) break; printf("**** Verify SFlash failed at: 0x%08X, %d bytes\n", SFLASH_UPGRADE_BASE + (upInfo.offset - upInfo.offset % SFLASH_ERASE_SIZE), upInfo.offset % SFLASH_ERASE_SIZE); delay_ms(200); } } #endif for(write_count = 0; write_count < 2; write_count++) { // 保存到铁电 FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)); if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo))) break; printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo)); delay_ms(200); } } } else // 命令返回错误 { // 取消本次升级 upInfo.fileSize = 0; // 保存到铁电 for(write_count = 0; write_count < 2; write_count++) { FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)); if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo))) break; printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo)); delay_ms(200); } upgrade = 0; break; } } } if(upInfo.fileSize > 0 && upInfo.offset == upInfo.fileSize) { SFlash_BufferRead(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader)); // 将升级请求改为1 upHeader.upgrade_request = 1; if(upHeader.check == 0x55AA && do_crc_16(0, (uint8_t *) &upHeader, sizeof(upHeader)) == 0 && do_sflash_crc(SFLASH_UPGRADE_BASE + sizeof(upHeader), upHeader.upgrade_length) == 0) { // 校验通过 printf("\nUpgrade package confirm passed\n"); // 发送确认 ackUpgrade = 1; } else { // 校验未通过 printf("\n****** Upgrade package confirm failed\n"); // 从头开始 upInfo.fileSize = 0; // 保存到铁电 for(write_count = 0; write_count < 2; write_count++) { FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)); if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo))) break; printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo)); delay_ms(200); } } } else { // 关闭和服务器的连接 DTU_Close(0); // 继续 continue; } } // 确认升级成功 if(ackUpgrade) { printf("\nConfirm upgrade software ...\n"); // 发送确认 memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 当前固件号 Int2ByteL(Task_sendBuff, i, htonl(upInfo.ver)); i += 4; // 固件的CRC16 Int2ByteS(Task_sendBuff, i, upInfo.fileCrc); i += 2; // 填写固定字段 i = fill_biDir_fixFields(0xD0E1, i); // 发送i个字节到服务器,至少接收10个字节 // 如果失败,下次再发送 recvLen = sizeof(bluetooth_recv_t) + 2; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { // 关闭和服务器的连接 DTU_Close(0); // 重连 continue; } if(recvLen == sizeof(bluetooth_recv_t) + 2 && pRecv->cmd == ntohs(0x00E1)) { // 将升级请求改为1 SFlash_BufferRead(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader)); upHeader.upgrade_request = 1; for(write_count = 0; write_count < 2; write_count++) { SFlash_BufferWrite(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader)); if(SFlash_BufferVerify(SFLASH_UPGRADE_BASE, (uint8_t *) &upHeader, sizeof(upHeader))) break; printf("**** Verify SFlash failed at: 0x%08X, %d bytes\n", SFLASH_UPGRADE_BASE, sizeof(upHeader)); delay_ms(200); } // 下次再升级从头开始 upInfo.fileSize = 0; // 保存到铁电 for(write_count = 0; write_count < 2; write_count++) { FRAM_SaveInfo(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo)); if(FRAM_BufferVerify(FRAM_UPGRADE_INFO_BASE, (uint8_t *) &upInfo, sizeof(upInfo))) break; printf("**** Verify FRAM failed at: 0x%08X, %d bytes\n", FRAM_UPGRADE_INFO_BASE, sizeof(upInfo)); delay_ms(200); } // 关闭和服务器的连接 DTU_Close(0); // 关闭DTU电源 VCC_GSM_OFF(); delay_ms(200); // 将LDROM映射到地址0x0 // FMC_Open(); // FMC_SetVectorPageAddr(LDROM_BASE); // FMC_Close(); // 复位以后执行Bootloader,将升级包解压 WDT_Close(); // 先关看门狗,免得bootloader复位 NVIC_SystemReset(); } } // 关闭和服务器的连接 DTU_Close(0); // 确认参数以后才执行复位命令(避免反复复位) if(reset && !ackParam) { VCC_GSM_OFF(); delay_ms(200); NVIC_SystemReset(); } } } } } // 刚处理完,清除等待的信号。等下一个周期再执行 DTU_semGPRS = 0; } // 检测发送GPS定位信号 if(semGPS || semSync) { if(Wakeup_GetWorkMode() == WORK_MODE_NORMAL) { if(dcBuff.configDisplay.op_SEND_GPS_DATA && Sim808_Connect(0, dcBuff.configData.gpsServer, dcBuff.configData.gpsPort)) { // 如果有待发送数据 do { // 根据发送缓冲区的大小,决定一次最多发几条数据 // 每条记录占12个字节,另外有24个字节的固定字段,比如头信息、PSN、crc等 // 如果没有合法的记录,发送一条空记录 gpsCount = GPS_LookData((TASK_SENDBUFF_SIZE - 24) / 12, &gpsInterval, &gpsDone); if(gpsCount > 0) { nextPtr = gpsBuff.info.rdPtr; FRAM_BufferRead(LoopBuff_GetDataPos(&gpsBuff, nextPtr), (uint8_t *) &gps, sizeof(gps_data_t)); } memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 坐标个数 if(gpsCount > 0) Int2ByteS(Task_sendBuff, i, htons(gpsCount)); else Int2ByteS(Task_sendBuff, i, htons(1)); i += 2; // 起始时间戳 if(gpsCount > 0) Int2ByteL(Task_sendBuff, i, htonl(gps.time.tm)); i += 4; // 时间戳增量 if(gpsCount > 0) Int2ByteS(Task_sendBuff, i, htons(gpsInterval)); i += 2; for(j = 0; j < (gpsCount ? gpsCount : 1); j++) { // 状态 if(gpsCount > 0) Task_sendBuff[i] = gps.state; else { // 车辆是否启动(根据充电状态决定) if(VCC_POWER_STATUS()) Task_sendBuff[i] |= (1 << 6); // 车辆启动状态是否改变) Task_sendBuff[i] |= (bat_CurrentEvent << 7); bat_CurrentEvent = 0; } i++; // 保留 i++; // 经度 if(gpsCount > 0) Int2ByteL(Task_sendBuff, i, htonl(gps.longitude)); i += 4; // 纬度 if(gpsCount > 0) Int2ByteL(Task_sendBuff, i, htonl(gps.latitude)); i += 4; // 速度 if(gpsCount > 0) Int2ByteS(Task_sendBuff, i, htons(gps.speed * 100)); i += 2; nextPtr = LoopBuff_GetNextPtr(&gpsBuff, nextPtr); FRAM_BufferRead(LoopBuff_GetDataPos(&gpsBuff, nextPtr), (uint8_t *) &gps, sizeof(gps_data_t)); } // 填写固定字段 i = fill_biDir_fixFields(0xD010, i); // 发送i个字节到服务器,至少接收10个字节 // 如果失败,下次再发送 recvLen = sizeof(bluetooth_recv_t) + 2; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) break; if(gpsCount > 0) { // 将这几条记录移除 GPS_MoveFromQueue(gpsCount); if(gpsDone) { GPS_Located = 1; // 停止超时定时器 GPS_Waiting = 0; } } } while(!gpsDone); } // 无论如何,关闭和服务器的连接 DTU_Close(0); // 刚处理完,清除等待的信号。等下一个周期再执行 DTU_semGPS = 0; } } if(semSync) { // 刚处理完,清除等待的信号。等下一个周期再执行 DTU_semSync = 0; } // 检查是否进入掉电模式 Wakeup_Powerdown(); } }