/* ********************************************************************************************************* * IAR Development Kits * on the * * M451 * * Filename : uart_dtu.c * Version : V1.00 * Programmer(s) : Qian Xianghong ********************************************************************************************************* */ #include "includes.h" #include "drv_dtu.h" #include "drv_gps.h" // 运动状态(默认为1,万一加速度计有问题) volatile uint8_t Motion_Status = 1; // 初始唤醒次数(快速发送) #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}; // 最近一条上传数据的采集时间 volatile uint32_t DTU_dataTime = 0; // 发送成功时间 volatile uint32_t DTU_succTime = 0; // 这个缓冲区比较大,不放在stack里面 char DTU_gpsData[2][DTU_GPSDATA_SIZE] = {0}; // 扩展内存 char DTU_recvBuff[DTU_RECVBUFF_SIZE] = {0}; // 扩展内存 // 一次请求升级包数据大小 #define UPGRADE_DATA_LEN 1024 // DTU_Task任务和服务器之间的收发缓冲 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}; // 扩展内存 // 信号量,用于通知执行任务 SemaphoreHandle_t DTU_semUpgrade = NULL; // 用于发送到服务器的数据结构 // 和蓝牙的相应命令一致 #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; // 升级进度信息(存放在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; #pragma pack(pop) // 升级包记录 upgrade_info_t upInfo = {0}; // 下载储罐档案记录 upgrade_info_t boxesInfo = {0}; // 储罐档案缓冲区 char boxesBuff[16384 + 1] = {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; } // 将采集数据中的传感器状态转换为蓝牙协议中的状态 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 GPS_IRQHandler(USART_Handle *huart) { uint8_t u8DTU = (uint8_t) huart->Instance->DR; // printf("%c", u8DTU); // 直接处理 DTU_Task0(u8DTU); } // GSM uart void GPRS_IRQHandler(USART_Handle *huart) { uint8_t u8DTU = (uint8_t) huart->Instance->DR; if(DTU_uartPrint) { // if(u8DTU == '\n') // printf("\\n\n"); // else if(u8DTU == '\r') // printf("\\r"); // else printf("%c", u8DTU); } // 加入缓冲 LoopBuff_PutItem(&DTU_TaskM, &u8DTU); } 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(&DTU_TaskM, sizeof(uint8_t), DTU_TASKM_DATA_COUNT, 0, (uint32_t) DTU_TaskM_Data); // 创建信号量 DTU_semUpgrade = xSemaphoreCreateBinary(); huart1.RxISR = GPRS_IRQHandler; huart6.RxISR = GPS_IRQHandler; SET_BIT(USART1->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); LL_USART_Enable(USART1); /* 打开GPS端口: GPS和Debug共用一个串口,GPS用到输入,DEBUG用到输出 */ SET_BIT(USART6->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); } // 任务主体:采集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; static uint32_t last_gpsTime = 0; 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) { RTC_offsetSeconds = time - DTU_gpsTime; // 关联铁电和SFlash的一致性 CheckFramSFlashValid(DTU_gpsTime); } // 修正时间基准(可显示绝对时间) if(time >= DTU_gpsTime) // 每次成功定位都修正时间 RTC_offsetSeconds = time - DTU_gpsTime; if(sample.sateCount >= 4) { if(time >= last_time + dcBuff.configData.intervalGPS) { last_time = time; // 没有硬件加速度计,用软件方式判断 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(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; // 每30秒保存一次定位信息,重启有效 if(time >= last_gpsTime + 30) { last_gpsTime = time; Ext_GPS.sysTime = dcBuff.dtuData.sysTime; Ext_GPS.longitude = dcBuff.dtuData.longitude; Ext_GPS.latitude = dcBuff.dtuData.latitude; Ext_GPS.speed = dcBuff.dtuData.speed; Ext_GPS.sateCount = dcBuff.dtuData.sateCount; Ext_GPS.posState = dcBuff.dtuData.posState; FRAM_SaveInfo(FRAM_GPS_INFO_BASE, (uint8_t *) &Ext_GPS, sizeof(ext_gps_t)); } } } } // 清除数据 memset(&sample, 0, sizeof(sample)); } } } uint8_t pack_gprs_tran_data(ext_data_t *pGprs, uint8_t is4G) { uint16_t i, j; bluetooth_sensor_t *pSensor; bluetooth_mask_t *pMask; uint16_t crc; rf_app_data_t *pData = (rf_app_data_t *) pGprs->payload; static data_sample_t sample; // TODO: 将精简数据转换成上传数据 cacl_gprs_tran_data(pGprs, &sample); // 打包上报数据(按modbus从机响应的格式) memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = 0; // PSN memmove(Task_sendBuff + i, pGprs->oriPSN, 6); i += 6; // 功能码 Task_sendBuff[i++] = 0x10; // 数据长度:先预设为0,最后再修改,位置为Task_sendBuff[7] Task_sendBuff[i++] = 0; // 当前差压值 *(uint16_t *) (Task_sendBuff + i) = htons(sample.diff); i +=2 ; // 容积百分比 *(uint16_t *) (Task_sendBuff + i) = htons(sample.volumePct); i += 2; // 当前容积 *(uint32_t *) (Task_sendBuff + i) = htonl(sample.volume); i += 4; // 重量 *(uint32_t *) (Task_sendBuff + i) = htonl(sample.weight); i += 4; if(pData->Sensor.measure_type == 0) // 差压 { // 高度:mmWC *(uint16_t *) (Task_sendBuff + i) = htons((uint16_t) (sample.diff * 101.9716213)); } else if(pData->Sensor.measure_type == 2) // 电容 { // 高度:mm *(uint16_t *) (Task_sendBuff + i) = htons((uint16_t) (sample.height)); } i += 2; // 压力 *(uint16_t *) (Task_sendBuff + i) = htons(pData->press); i += 2; // 温度-调试信息 *(int16_t *) (Task_sendBuff + i) = htons(is4G ? 3 : 1); // 1-标识为LoRa转发,2-标志为北斗上传,3-标志为4G转发 i += 2; // 液源 if(pData->Sensor.L_source <= SOURCE_POPO) Task_sendBuff[i] = pData->Sensor.L_source; i++; // 储罐类型 if(pData->Sensor.bottle_type == BOTTLE_TYPE_STAND) Task_sendBuff[i] = 0; else if(pData->Sensor.bottle_type == BOTTLE_TYPE_LYING) Task_sendBuff[i] = 1; else if(pData->Sensor.bottle_type == BOTTLE_TYPE_SPHERICAL) Task_sendBuff[i] = 2; i++; // 故障码 pSensor = (bluetooth_sensor_t *) (Task_sendBuff + i); pSensor->staDiff = pData->Sensor.staDiff; pSensor->staPress = pData->Sensor.staPress; pSensor->staEPress1 = 3; pSensor->staEPress2 = 3; pSensor->staEPress3 = 3; pSensor->staETempr1 = pData->Sensor.staETempr1; pSensor->staETempr2 = 3; pSensor->staETempr3 = 3; i += 2; // 传感器状态 pMask = (bluetooth_mask_t *) (Task_sendBuff + i); memset(pMask, 0xFF, 2); pMask->maskFlow = 0; pMask->maskLowPower = pData->Sensor.bat_low; pMask->maskAbnormal = 0; pMask->maskCharging = pData->Sensor.charging; i += 2; // 版本号 Task_sendBuff[i++] = dcBuff.powerInfo.protocolVer.minor; // rssi Task_sendBuff[i++] = 0; if(pMask->maskGPS) { // 经度 *(int32_t *) (Task_sendBuff + i) = htonl(pData->longitude); i += 4; // 纬度 *(int32_t *) (Task_sendBuff + i) = htonl(pData->latitude); i += 4; } // 扩展温度 if(pMask->maskETempr1) { *(uint16_t *) (Task_sendBuff + i) = htons(pData->tempr); i += 2; } if(pMask->maskETempr2) { i += 2; } if(pMask->maskETempr3) { i += 2; } // 电池信息 if(pMask->maskBattery) { // 电量百分比 *(uint16_t *) (Task_sendBuff + i) = htons(pData->batPct); i += 2; // 电池内部温度 i += 2; // 电池当前电压 *(int16_t *) (Task_sendBuff + i) = htons(pData->voltage); i += 2; // 电池容量 i += 2; // 电池当前容量 i += 2; // 充电电流,电流的符号表示充放电状态 *(int16_t *) (Task_sendBuff + i) = htons(pData->batCurrent); i += 2; // 光照强度 i += 2; } // 流量计 if(pMask->maskFlow) { // 天信MODBUS /A1 通信协议 (BCD码) // 标况体积总量 i += 6; // 标况流量 i += 4; // 工况流量 i += 4; // 温度 i += 4; // 压力 i += 4; } // 泄露报警 if(pMask->maskLeak) { // 类型 Task_sendBuff[i++] = LEAK_TYPE_SWITCH | LEAK_TYPE_CURRENT | LEAK_TYPE_MODBUS; // 状态、报警浓度 Task_sendBuff[i++] = 0x80; } if(pMask->maskStamp) { if(dcBuff.powerInfo.protocolVer.minor == 107) { *(uint32_t *) (Task_sendBuff + i) = htonl(pData->relative_time + (RTC_offsetSeconds + rf_get_seconds() - pGprs->recvTime)); } // 时间 i += 4; // 年月日 i += 4; } // 扩展压力 if(pMask->maskEPress1) { i += 2; } if(pMask->maskEPress2) { i += 2; } if(pMask->maskEPress3) { i += 2; } // 硬件版本 // Task_sendBuff[i++] = ((pData->hardVer / 10) << 4) + pData->hardVer % 10; Task_sendBuff[i++] = pData->hardVer; // 软件版本 // Task_sendBuff[i++] = ((pData->softVer / 10) << 4) + pData->softVer % 10;; Task_sendBuff[i++] = pData->softVer; // 真空传感器 for(j = 0; j < 2; j++) { // 状态 *(uint16_t *) (Task_sendBuff + i) = htons(0); i += 2; // 使用年限 i += 2; // 真空度 i += 4; // 漏放气速率 i += 4; } // 气瓶容量 *(uint32_t *) (Task_sendBuff + i) = htonl(Theoretical_Param.v); i += 4; // 储罐封头直边长 *(uint16_t *) (Task_sendBuff + i) = htons(0); i += 2; // 储罐筒长度 *(uint32_t *) (Task_sendBuff + i) = htonl(pData->L); i += 4; // 储罐直径 *(uint32_t *) (Task_sendBuff + i) = htonl(pData->d); i += 4; // 自动发送频率 i += 2; // 自动发送短信频率 i += 2; // 修改数据长度 Task_sendBuff[7] = i - 8; // 校验码 crc = MODBUS_RTU_CRC16((uint8_t *) Task_sendBuff, i); *(uint16_t *)(Task_sendBuff + i) = htons(crc); i += 2; // 结束符 Task_sendBuff[i++] = 0x0d; Task_sendBuff[i++] = 0x0a; return i; } uint8_t pack_modbus_tran_data(ext_data_t *pGprs) { uint16_t i, j; bluetooth_sensor_t *pSensor; bluetooth_mask_t *pMask; uint16_t crc; rf_app_data_t *pData = (rf_app_data_t *) pGprs->payload; static data_sample_t sample; // TODO: 将精简数据转换成上传数据 cacl_gprs_tran_data(pGprs, &sample); // 打包上报数据(按modbus从机响应的格式) memset(Modbus_sendBuff, 0, TASK_SENDBUFF_SIZE); i = 0; // PSN memmove(Modbus_sendBuff + i, pGprs->oriPSN, 6); i += 6; // 功能码 Modbus_sendBuff[i++] = 0x10; // 数据长度:先预设为0,最后再修改,位置为Modbus_sendBuff[7] Modbus_sendBuff[i++] = 0; // 当前差压值 *(uint16_t *) (Modbus_sendBuff + i) = htons(sample.diff); i +=2 ; // 容积百分比 *(uint16_t *) (Modbus_sendBuff + i) = htons(sample.volumePct / 100); i += 2; // 当前容积 *(uint32_t *) (Modbus_sendBuff + i) = htonl(sample.volume); i += 4; // 重量 *(uint32_t *) (Modbus_sendBuff + i) = htonl(sample.weight); i += 4; if(pData->Sensor.measure_type == 0) // 差压 { // 高度:mmWC *(uint16_t *) (Modbus_sendBuff + i) = htons((uint16_t) (sample.diff * 101.9716213)); } else if(pData->Sensor.measure_type == 2) // 电容 { // 高度:mm *(uint16_t *) (Modbus_sendBuff + i) = htons((uint16_t) (sample.height)); } i += 2; // 压力 *(uint16_t *) (Modbus_sendBuff + i) = htons(pData->press); i += 2; // 温度-调试信息 *(int16_t *) (Modbus_sendBuff + i) = 1; // 1-标识为LoRa转发,2-标志为北斗上传,3-标志为4G转发 i += 2; // 液源 if(pData->Sensor.L_source <= SOURCE_POPO) Modbus_sendBuff[i] = pData->Sensor.L_source; i++; // 储罐类型 if(pData->Sensor.bottle_type == BOTTLE_TYPE_STAND) Modbus_sendBuff[i] = 0; else if(pData->Sensor.bottle_type == BOTTLE_TYPE_LYING) Modbus_sendBuff[i] = 1; else if(pData->Sensor.bottle_type == BOTTLE_TYPE_SPHERICAL) Modbus_sendBuff[i] = 2; i++; // 故障码 pSensor = (bluetooth_sensor_t *) (Modbus_sendBuff + i); pSensor->staDiff = pData->Sensor.staDiff; pSensor->staPress = pData->Sensor.staPress; pSensor->staEPress1 = 3; pSensor->staEPress2 = 3; pSensor->staEPress3 = 3; pSensor->staETempr1 = pData->Sensor.staETempr1; pSensor->staETempr2 = 3; pSensor->staETempr3 = 3; i += 2; // 传感器状态 pMask = (bluetooth_mask_t *) (Modbus_sendBuff + i); memset(pMask, 0xFF, 2); pMask->maskFlow = 0; pMask->maskLowPower = pData->Sensor.bat_low; pMask->maskAbnormal = 0; pMask->maskCharging = pData->Sensor.charging; i += 2; // 版本号 Modbus_sendBuff[i++] = dcBuff.powerInfo.protocolVer.minor; // rssi Modbus_sendBuff[i++] = 0; if(pMask->maskGPS) { // 经度 *(int32_t *) (Modbus_sendBuff + i) = htonl(pData->longitude); i += 4; // 纬度 *(int32_t *) (Modbus_sendBuff + i) = htonl(pData->latitude); i += 4; } // 扩展温度 if(pMask->maskETempr1) { *(uint16_t *) (Modbus_sendBuff + i) = htons(pData->tempr); i += 2; } if(pMask->maskETempr2) { i += 2; } if(pMask->maskETempr3) { i += 2; } // 电池信息 if(pMask->maskBattery) { // 电量百分比 *(uint16_t *) (Modbus_sendBuff + i) = htons(pData->batPct); i += 2; // 电池内部温度 i += 2; // 电池当前电压 *(int16_t *) (Modbus_sendBuff + i) = htons(pData->voltage); i += 2; // 电池容量 i += 2; // 电池当前容量 i += 2; // 充电电流,电流的符号表示充放电状态 *(int16_t *) (Modbus_sendBuff + i) = htons(pData->batCurrent); i += 2; // 光照强度 i += 2; } // 流量计 if(pMask->maskFlow) { // 天信MODBUS /A1 通信协议 (BCD码) // 标况体积总量 i += 6; // 标况流量 i += 4; // 工况流量 i += 4; // 温度 i += 4; // 压力 i += 4; } // 泄露报警 if(pMask->maskLeak) { // 类型 Modbus_sendBuff[i++] = LEAK_TYPE_SWITCH | LEAK_TYPE_CURRENT | LEAK_TYPE_MODBUS; // 状态、报警浓度 Modbus_sendBuff[i++] = 0x80; } if(pMask->maskStamp) { if(dcBuff.powerInfo.protocolVer.minor == 107) { *(uint32_t *) (Modbus_sendBuff + i) = htonl(pData->relative_time + (RTC_offsetSeconds + rf_get_seconds() - pGprs->recvTime)); } // 时间 i += 4; // 年月日 i += 4; } // 扩展压力 if(pMask->maskEPress1) { i += 2; } if(pMask->maskEPress2) { i += 2; } if(pMask->maskEPress3) { i += 2; } // 硬件版本 // Modbus_sendBuff[i++] = ((pData->hardVer / 10) << 4) + pData->hardVer % 10; Modbus_sendBuff[i++] = pData->hardVer; // 软件版本 // Modbus_sendBuff[i++] = ((pData->softVer / 10) << 4) + pData->softVer % 10;; Modbus_sendBuff[i++] = pData->softVer; // 真空传感器 for(j = 0; j < 2; j++) { // 状态 *(uint16_t *) (Modbus_sendBuff + i) = htons(0); i += 2; // 使用年限 i += 2; // 真空度 i += 4; // 漏放气速率 i += 4; } // 气瓶容量 *(uint32_t *) (Modbus_sendBuff + i) = htonl(Theoretical_Param.v); i += 4; // 储罐封头直边长 *(uint16_t *) (Modbus_sendBuff + i) = htons(0); i += 2; // 储罐筒长度 *(uint32_t *) (Modbus_sendBuff + i) = htonl(pData->L); i += 4; // 储罐直径 *(uint32_t *) (Modbus_sendBuff + i) = htonl(pData->d); i += 4; // 自动发送频率 i += 2; // 自动发送短信频率 i += 2; // 修改数据长度 Modbus_sendBuff[7] = i - 8; // 校验码 crc = MODBUS_RTU_CRC16((uint8_t *) Modbus_sendBuff, i); *(uint16_t *)(Modbus_sendBuff + i) = htons(crc); i += 2; // 结束符 Modbus_sendBuff[i++] = 0x0d; Modbus_sendBuff[i++] = 0x0a; return i; } //////////////////////////////////////////////////////////////////////////////////////// // 填写双向通讯的固定字段 uint16_t fill_biDir_fixFields(uint16_t cmd, uint16_t len) { bluetooth_send_t *pSend = (bluetooth_send_t *) Task_sendBuff; uint16_t crc; pSend->mark = 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; 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 && dcBuff.dtuData.sysTime.year) { 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; // if(dcBuff.configDisplay.L_Unit == UNIT_KPA) // Task_sendBuff[i] = 0; // else if(dcBuff.configDisplay.L_Unit == UNIT_KG) // Task_sendBuff[i] = 1; // else if(dcBuff.configDisplay.L_Unit == UNIT_L) // Task_sendBuff[i] = 2; // else if(dcBuff.configDisplay.L_Unit == UNIT_MMH2O) // Task_sendBuff[i] = 4; // else // Task_sendBuff[i] = 3; i++; 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)); Int2ByteL(Task_sendBuff, i, htonl(dcBuff.configBottle.offlineSeconds)); 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.warnTempr)); // span i += 2; Int2ByteS(Task_sendBuff, i, htons(dcBuff.configBottle.warnTemprH)); // spanPeriod i += 2; // 测量方式 // Task_sendBuff[i] = dcBuff.configDisplay.op_USE_CAPACITY_SENSOR ? 2 : dcBuff.configBottle.measureType; i++; // Task_sendBuff[i] = 0; i++; // Task_sendBuff[i] = dcBuff.configDisplay.op_USE_PT100_SENSOR ? 0 : 1; i++; // 差压传感器参数 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; // 扩展温度传感器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; // 填写固定字段 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]; dcBuff.configBottle.options &= ~0x0003ul; if(dcBuff.configBottle.dispMode == DISP_MODE_ALL) dcBuff.configBottle.options |= 0x0003ul; else if(dcBuff.configBottle.dispMode == DISP_MODE_L) dcBuff.configBottle.options |= 0x0001ul; else if(dcBuff.configBottle.dispMode == DISP_MODE_KG) dcBuff.configBottle.options |= 0x0002ul; } i++; // 显示单位 if(mask.ll & (1ull << (shift++))) { if(param[i] == 0) dcBuff.configDisplay.L_Unit = UNIT_KPA; else if(param[i] == 1) dcBuff.configDisplay.L_Unit = UNIT_KG; else if(param[i] == 2) dcBuff.configDisplay.L_Unit = UNIT_L; else if(param[i] == 4) dcBuff.configDisplay.L_Unit = UNIT_MMH2O; else dcBuff.configDisplay.L_Unit = UNIT_PCT; } 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)); dcBuff.configBottle.offlineSeconds = 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.warnTempr = ntohs(Byte2IntS(param, i)); // span i += 2; // TTS-变化量检测时间: 秒 if(mask.ll & (1ull << (shift++))) dcBuff.configBottle.warnTemprH = ntohs(Byte2IntS(param, i)); // spanPeriod 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; // 温度传感器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; *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]; i++; // 只显示毫米水柱 // dcBuff.configDisplay.op_DISP_MMWC_ONLY = param[i]; i++; // 罐箱版本 // dcBuff.configDisplay.op_BOX_VER = param[i]; i++; // 基站定位 // dcBuff.configDisplay.op_CELL_LOCATION = param[i]; i++; // 发送轨迹 // dcBuff.configDisplay.op_SEND_GPS_DATA = param[i]; i++; // 通信方式 // dcBuff.configDisplay.op_SERVER_PROTOCOL = param[i]; i++; // URL索引 // dcBuff.configDisplay.op_SERVER_INDEX = param[i]; i++; // 单向通信 // dcBuff.configDisplay.op_UNIDIR_COMM = param[i]; 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; // 关联铁电和SFlash的一致性 CheckFramSFlashValid(totalSeconds1); } } } } // 关闭和服务器的连接 DTU_Close(0); } } //////////////////////////////////////////////////////////////////////////////////////// // 任务主体:发送运行数据和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 i, j, k; uint32_t totalSeconds; S_RTC_TIME_DATA_T sRTC; uint8_t try_count; uint16_t recvLen; uint8_t upgrade; uint8_t ackUpgrade; uint8_t downloadParam; uint8_t ackParam; uint8_t downloadOptions; uint8_t ackOptions; uint8_t downloadBoxes; uint8_t ackBoxes; uint8_t downloadConfig; uint8_t ackConfig; uint8_t reset = 0; TUpgradeHeader upHeader; upgrade_frame_t *pFrame; int32_t nextPtr; uint8_t write_count; uint32_t rssiTick = 0; uint8_t tranLocked = 0; // 清除数据 memset(&dcBuff.dtuData, 0, sizeof(dcBuff.dtuData)); // 从铁电读取最近一次GPS定位信息,并检查是否合法 if(FRAM_LoadInfo(FRAM_GPS_INFO_BASE, (uint8_t *) &Ext_GPS, sizeof(ext_gps_t))) { dcBuff.dtuData.sysTime = Ext_GPS.sysTime; dcBuff.dtuData.longitude = Ext_GPS.longitude; dcBuff.dtuData.latitude = Ext_GPS.latitude; dcBuff.dtuData.speed = Ext_GPS.speed; dcBuff.dtuData.sateCount = Ext_GPS.sateCount; dcBuff.dtuData.posState = Ext_GPS.posState; } // 触发固件升级任务:开机执行一次 xSemaphoreGive(DTU_semUpgrade); while(1) { // 获取当前时间 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; // 每30秒刷新一下4G信号 if(IsTickOut(rssiTick)) { rssiTick = GetDelayTick(30000); DTU_PowerOn(); // 采集信号强度和注册信息 Sim808_ReadGPRS(); // GPRS拨号和GPS定位同时进行,以节省时间 if(dcBuff.dtuData.networked) Sim808_GPRSDial(); } // 连接成功,对发送加锁 if(!dcBuff.dtuData.connected && Sim808_Connect(0, dcBuff.configData.server, dcBuff.configData.port) && !tranLocked) { xSemaphoreTake(RF_TranLock, portMAX_DELAY); tranLocked = 1; } if(!dcBuff.dtuData.connected && tranLocked) { // 4G连接失败,释放锁让网口有机会发送 xSemaphoreGive(RF_TranLock); tranLocked = 0; } // 掉电有效,如果未获取到UTC时间,不转发 if(RTC_offsetSeconds > 0 && dcBuff.dtuData.connected && LoopBuff_GetCount(&RF_TranM) > 0) { nextPtr = RF_TranM.info.rdPtr; for(k = 0; k < LoopBuff_GetCount(&RF_TranM); k++) { dcBuff.powerInfo.gprsSendCount++; if(!SFlash_LoadInfo(LoopBuff_GetDataPos(&RF_TranM, nextPtr), (uint8_t *) &Ext_Data_Rec1, sizeof(ext_data_t))) { nextPtr = LoopBuff_GetNextPtr(&RF_TranM, nextPtr); continue; // 不发送,算失败1次 } nextPtr = LoopBuff_GetNextPtr(&RF_TranM, nextPtr); // 打包上报数据(按modbus从机响应的格式) i = pack_gprs_tran_data(&Ext_Data_Rec1, 1); recvLen = 2; if(!Sim808_SendAndRecv(0, Task_sendBuff, i, &recvLen, Task_recvBuff, TASK_RECVBUFF_SIZE)) { if(tranLocked) { // 4G发送失败,释放锁让网口有机会发送 xSemaphoreGive(RF_TranLock); tranLocked = 0; } // 关闭和服务器的连接 DTU_Close(0); break; } // 成功发送数据的时间: 取当前时间 DTU_dataTime = totalSeconds; dcBuff.powerInfo.gprsSuccCount++; } // 移除已成功发送的数据 if(k > 0) { LoopBuff_RemoveItems(&RF_TranM, k); // 保存到铁电 FRAM_SaveInfo(RF_TranM.info_base, (uint8_t *) &RF_TranM.info, sizeof(RF_TranM.info)); } } // 是否连接维护平台:每隔12小时一次(普莱克斯、林德的每次连接) if(xSemaphoreTake(DTU_semUpgrade, 0) == pdTRUE) { // 关闭和服务器的连接 DTU_Close(0); // 是否升级或下载参数:维护平台 upgrade = 0; ackUpgrade = 0; downloadParam = 0; ackParam = 0; downloadOptions = 0; ackOptions = 0; downloadBoxes = 0; ackBoxes = 0; downloadConfig = 0; ackConfig = 0; reset = 0; k = 1; // 发送1条诊断信息 try_count = 2; while((try_count--) && (k || upgrade || ackUpgrade || downloadParam || ackParam || downloadOptions || ackOptions || downloadBoxes || ackBoxes || 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]; if(recvLen >= sizeof(bluetooth_recv_t) + 3 + 2) downloadConfig = Task_recvBuff[sizeof(bluetooth_recv_t) + 2]; if(recvLen >= sizeof(bluetooth_recv_t) + 4 + 2) downloadOptions = Task_recvBuff[sizeof(bluetooth_recv_t) + 3]; if(recvLen >= sizeof(bluetooth_recv_t) + 5 + 2) downloadBoxes = Task_recvBuff[sizeof(bluetooth_recv_t) + 4]; 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(downloadOptions) { } // 确认配置选项 if(ackOptions) { } // 下载罐箱档案 if(downloadBoxes) { printf("\nDownload boxes ...\n"); if(boxesInfo.fileSize == 0) { // 从头开始下载 memset(&boxesInfo, 0, sizeof(boxesInfo)); } // 下载数据 while(boxesInfo.fileSize == 0 || boxesInfo.offset < boxesInfo.fileSize) { memset(Task_sendBuff, 0, TASK_SENDBUFF_SIZE); i = sizeof(bluetooth_send_t); // PSN memmove(Task_sendBuff + i, dcBuff.configBottle.PSN, 6); i += 6; // 当前版本号 i += 4; // 文件偏移量 Int2ByteL(Task_sendBuff, i, htonl(boxesInfo.offset)); i += 4; // 请求数据长度 Int2ByteL(Task_sendBuff, i, htonl(UPGRADE_DATA_LEN)); i += 4; // 填写固定字段 i = fill_biDir_fixFields(0xD0E2, 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(0x00E2)) { 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(boxesInfo.fileSize > 0 && (boxesInfo.fileSize != ntohl(pFrame->fileSize) || boxesInfo.fileCrc != pFrame->fileCrc || boxesInfo.offset > ntohl(pFrame->fileSize))) { // 从头开始升级 memset(&boxesInfo, 0, sizeof(boxesInfo)); continue; } // 保存下载信息 // 如果只是网络通信失败,会断点续传 boxesInfo.fileSize = ntohl(pFrame->fileSize); boxesInfo.offset = ntohl(pFrame->offset); boxesInfo.len = ntohl(pFrame->len); boxesInfo.fileCrc = pFrame->fileCrc; printf("\nfileSize = %d, offset = %d, len = %d\n", boxesInfo.fileSize, boxesInfo.offset, boxesInfo.len); // 要留1个字节用于添加结束符 if(boxesInfo.offset + boxesInfo.len < sizeof(boxesBuff)) { memmove(boxesBuff + boxesInfo.offset, pFrame->data, boxesInfo.len); boxesInfo.offset += boxesInfo.len; } else { // 取消本次下载 boxesInfo.fileSize = 0; downloadBoxes = 0; break; } } } else // 命令返回错误 { // 取消本次下载 boxesInfo.fileSize = 0; downloadBoxes = 0; break; } } } if(boxesInfo.fileSize > 0 && boxesInfo.offset == boxesInfo.fileSize) { if(do_crc_16(0, (uint8_t *) boxesBuff, boxesInfo.fileSize) == boxesInfo.fileCrc) { // 校验通过 printf("\nBoxes confirm passed\n"); downloadBoxes = 0; // 发送确认 ackBoxes = 1; } else { // 校验未通过 printf("\n****** Boxes confirm failed\n"); // 从头开始 boxesInfo.fileSize = 0; } } else { // 关闭和服务器的连接 DTU_Close(0); // 继续 continue; } } // 确认罐箱档案 if(ackBoxes) { printf("\nConfirm boxes ...\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(boxesInfo.ver)); i += 4; // 档案的CRC16 Int2ByteS(Task_sendBuff, i, boxesInfo.fileCrc); i += 2; // 填写固定字段 i = fill_biDir_fixFields(0xD0E3, 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(0x00E3)) { ackBoxes = 0; // 更新储罐档案 boxesBuff[boxesInfo.fileSize] = 0; Ext_Update_Boxes(boxesBuff); // 下次再升级从头开始 boxesInfo.fileSize = 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(); } } } // 刚处理完,清除等待的信号。等下一个周期再执行(如果有报警必须立即上传) xSemaphoreTake(DTU_semUpgrade, 0); } } }