ShipCentralControl/Anjiehui7_DTU/User/uart_dtu.c

2513 lines
71 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

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

/*
*********************************************************************************************************
* 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);
}
}
}