Files
GateWay/Project/GateWay/source/User/Src/Public.c
T

1515 lines
60 KiB
C
Raw Normal View History

2026-04-23 13:56:52 +08:00
#include "main.h"
#include "Public.h"
#include "RS485Task.h"
#include "LoraTask.h"
#include "spiflash.h"
#include "CatOneTask.h"
#include <stdlib.h>
#include "sx127x.h"
2026-04-23 13:56:52 +08:00
const char *ChannelName(Channel_m ch)
{
switch(ch) {
case CH_NULL: return "null";
case CH_DBG: return "dbg";
case CH_RS485_1: return "ch1";
case CH_RS485_2: return "ch2";
case CH_ETH: return "eth";
case CH_LORA: return "lora";
case CH_CAT1: return "cat1";
default: return "?";
}
}
//传感器对应的数据长度
2026-04-23 13:56:52 +08:00
const uint8_t SensorTypeDataLen[] = {
0, //0x0000-保留
30, //0x0001-应力场检测单元
12, //0x0002-渗透压检测单元
14, //0x0003-弹性波导检测单元
10, //0x0004-介电质普检测单元
6, //0x0005-微振动
6, //0x0006-三维连续变形检测单元
3, //0x0007-通讯单元
18, //0x0008-三维应力检测单元
9, //0x0009-激光示踪(主设备)
12, //0x000A-水位计
0, //0x000B-保留
0, //0x000C-保留
14, //0x000D-二维应力场检测单元
9, //0x000E-裂缝检测单元
0, //0x000F-预留
8, //0x0010-姿态检测单元
4, //0x0011-激光位移检测单元
4, //0x0012-表面应力传感器
4, //0x0013-压力传感器
4, //0x0014-微波测距传感器
0, //0x0015-表贴式结冰传感器
0, //0x0016-埋入式结冰传感器
4, //0x0017-单通道钢筋应力传感器
4, //0x0018-单通道锚杆轴力传感器
32, //0x0019-8通道钢筋拉压力传感器
32, //0x001A-8通道锚杆轴力传感器
0, //0x001B-16通道钢筋应力传感器
0, //0x001C-16通道锚杆轴力传感器
0, //0x001D-爆炸冲击传感器
0, //0x001E-随行支架传感器
0, //0x001F-冻融循环传感器
19, //0x0020-位移计
2026-04-23 13:56:52 +08:00
};
/*****************************************************************************************
* 函数名称: CRC_Modbus
* 功能描述: CRC16计算函数
* 参 数: wBase, 多项式
Para,校验数据入口
Data, 校验数据长度入口
* 返 回 值: crc16校验值
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
uint16_t CRC_Modbus(uint16_t wBase, __IO uint8_t *para, uint16_t length)
{
uint16_t crc = 0xffff;
uint16_t index,i;
for(index = 0 ; index < length;index++) {
crc ^= para[index];
for(i = 0; i < 8; i++) {
if(crc & 1) {
crc >>= 1;
crc ^= wBase;
}
else
crc >>= 1;
}
}
return crc;
}
/*****************************************************************************************
* 函数名称: HexToAscii
* 功能描述: HEX转换为ASCII字符串函数
* 参 数: HexData, 16进制数据入口
ASCData,转换后的ASCII数据
sLen, 需要转的16进制数据长度
* 返 回 值: 无
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
void HexToAscii(uint8_t *HexData, char *ASCData, uint8_t sLen)
{
uint8_t temp;
for(int i = 0; i < sLen; i++) {
temp = (HexData[i] >> 4) & 0x0f;
if(temp < 10)
temp += '0';
else
temp = (temp - 10) + 'A';
ASCData[i * 2] = temp;
temp = HexData[i] & 0x0f;
if(temp < 10)
temp += '0';
else
temp = (temp - 10) + 'A';
ASCData[i * 2 + 1] = temp;
}
ASCData[sLen * 2] = 0;
}
/*****************************************************************************************
* 函数名称: AsciiToHex
* 功能描述: AscII字符串转换为16进制数组
* 参 数: ASCData, AscII字符串入口
HexData,转换后的数据
sLen, 需要转的字符串长度
* 返 回 值: 无
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
uint16_t AsciiToHex(char *ASCData, uint8_t *HexData, uint16_t sLen)
2026-04-23 13:56:52 +08:00
{
char chr;
uint8_t HexLen = 0;
if(sLen % 2 == 1)
return 0;
for(int i = 0; i < sLen; i++) {
chr = ASCData[i];
if(chr >= '0' && chr <= '9') {
HexData[HexLen] |= chr - '0';
}
else if(chr >= 'A' && chr <= 'F') {
HexData[HexLen] |= chr - 'A' + 0x0A;
}
else if(chr >= 'a' && chr <= 'f') {
HexData[HexLen] |= chr - 'a' + 0x0A;
}
if(i % 2 == 0) {
HexData[HexLen] <<= 4;
}
else {
HexLen++;
}
}
return HexLen;
}
/*****************************************************************************************
* 函数名称: ReadHistoryData
* 功能描述: 读取历史数据
* 参 数: rData,输入数据
rLen, 输入数据长度
* 返 回 值: 无
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
int ReadHistoryData(LogHeader LogH, uint8_t **Data, int Idx)
{
return ReadLog(LogH, Data, Idx);
}
/*****************************************************************************************
* 函数名称: NetCommOrgData
* 功能描述: 上报数据组织
* 参 数: MegData, 消息队列数据
OutData, 输出数据出口
* 返 回 值: 数据长度
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
int NetCommOrgData(GateWayPara GateWay, uint8_t *MegData, uint8_t *OutData)
{
uint8_t Cmd, *Meg;
uint16_t check;
uint16_t Len;
uint16_t PayloadLen;
PayloadLen = MegData[0] | (MegData[1] << 8);
Cmd = MegData[2];
Meg = &MegData[3];
NetCommFrameHeader NCHeader = (NetCommFrameHeader)OutData;
NCHeader->Header = 0x7A;
memcpy(NCHeader->GWMac, GateWay->ConfigPara.GwMac, 6);
//memcpy(NCHeader->SvrMac, GateWay->SvrMac, 6);
NCHeader->Cmd = Cmd;
NCHeader->BatLevel = GateWay->Battery;
NCHeader->Timestamp = TimeTs();
NCHeader->PacketNum = 1;
NCHeader->PacketIdx = 1;
NCHeader->PayloadLen = PayloadLen;
Len = sizeof(NetCommFrameHeader_t);
memcpy(&OutData[Len], Meg, NCHeader->PayloadLen);
Len += NCHeader->PayloadLen;
check = CRC_Modbus(CRC16_BASE, OutData, Len);
2026-04-23 13:56:52 +08:00
OutData[Len++] = check & 0x00ff;
OutData[Len++] = (check >> 8) & 0x00ff;
return Len;
}
/*****************************************************************************************
* 函数名称: CheckCommUnitReg
* 功能描述: 检查设备是否注册
* 参 数: GateWay,网关句柄
CommUnitMac, 待检查的设备MAC
* 返 回 值: 已注册返回非0,没注册返回-1
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
int CheckCommUnitReg(GateWayPara GateWay, uint8_t *CommUnitMac)
{
for(int i = 0; i < COMMUNIT_NUM_MAX; i++) {
if(memcmp(GateWay->ConfigPara.CommUnitArray[i].Mac[0], CommUnitMac, 6) == 0) {
if(GateWay->ConfigPara.CommUnitArray[i].RegFlag == true)
return i;
}
}
return -1;
}
/*****************************************************************************************
* 函数名称: CheckCommUnitExcl
* 功能描述: 检查设备是否排除
* 参 数: GateWay,网关句柄
CommUnitMac, 待检查的设备MAC
* 返 回 值: 已排除返回非0,没排除返回-1
*****************************************************************************************/
int CheckCommUnitExcl(GateWayPara GateWay, uint8_t *CommUnitMac)
{
for(int i = 0; i < COMMUNIT_NUM_MAX; i++) {//判断是否被排除
if(memcmp(GateWay->ConfigPara.ExclCommUnit[i].ExclMac, CommUnitMac, 6) == 0) {
if(GateWay->ConfigPara.ExclCommUnit[i].ExclFlag == true)
return i;
}
}
return -1;
}
/*****************************************************************************************
* 函数名称: RegPayloadValid
* 功能描述: 注册请求payload合法性校验,拦截频偏串台误解调的乱码帧,避免乱码设备占用注册表
* 参 数: GateWay, 网关句柄
CUHeader, 注册帧头
PayLoad, 注册负载数据
* 返 回 值: 合法返回true, 非法返回false
*****************************************************************************************/
static bool RegPayloadValid(GateWayPara GateWay, CommUnitFrameHeader CUHeader, uint8_t *PayLoad)
{
uint8_t SensorN = PayLoad[0];
int i, j;
bool MacEmpty;
/*空注册无意义*/
if(SensorN == 0) {
return false;
}
/*payload长度必须容纳N个传感器条目(每条目6字节)*/
if(CUHeader->PayloadLen < (uint16_t)(SensorN * 6 + 1)) {
return false;
}
/*通讯单元自身MAC不能为全0/全FF*/
MacEmpty = true;
for(i = 0; i < 6; i++) {
if(CUHeader->DevMac[i] != 0x00 && CUHeader->DevMac[i] != 0xFF) { MacEmpty = false; break; }
}
if(MacEmpty) {
return false;
}
/*注册帧GWMac若非空(全0/全FF视为未填)则必须与本网关匹配*/
MacEmpty = true;
for(i = 0; i < 6; i++) {
if(CUHeader->GWMac[i] != 0x00 && CUHeader->GWMac[i] != 0xFF) { MacEmpty = false; break; }
}
if(!MacEmpty && memcmp(CUHeader->GWMac, GateWay->ConfigPara.GwMac, 6) != 0) {
return false;
}
/*逐传感器: 类型必须在已知类型表内且非保留(数据长度>0), MAC非全0/全FF且不等于网关MAC*/
for(j = 0; j < SensorN; j++) {
uint16_t RegType = PayLoad[(j*6)+1] | (PayLoad[(j*6)+2] << 8);
if(RegType == 0x0000 || RegType >= sizeof(SensorTypeDataLen)/sizeof(SensorTypeDataLen[0])
|| SensorTypeDataLen[RegType] == 0) {
return false;
}
MacEmpty = true;
for(i = 0; i < 6; i++) {
uint8_t mac = PayLoad[(j*6)+1+i];
if(mac != 0x00 && mac != 0xFF) { MacEmpty = false; break; }
}
if(MacEmpty || memcmp(&PayLoad[(j*6)+1], GateWay->ConfigPara.GwMac, 6) == 0) {
return false;
}
}
return true;
}
2026-04-23 13:56:52 +08:00
/*****************************************************************************************
* 函数名称: CommUnitSendCmd
* 功能描述: 网关下发通讯单元指令函数
* 参 数: GateWay, 网关句柄
CommUnitMac,通讯单元MAC地址
Cmd, 命令字
Payload, 下发数据
PayloadLen, 下发数据长度
* 返 回 值: 无
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
void CommUnitCmdSend(GateWayPara GateWay, uint8_t *CommUnitMac, CommUnitCmd_m Cmd, uint8_t *Payload, uint16_t PayloadLen, SendData Send)
{
uint8_t SendBuff[50];
uint8_t SendLen;
if(PayloadLen > 10)
return;
CommUnitFrameHeader CUHeader = (CommUnitFrameHeader)SendBuff;
CUHeader->Header = 0x7B;
memcpy(CUHeader->GWMac, GateWay->ConfigPara.GwMac, 6);
if(CommUnitMac == NULL) {
memset(CUHeader->DevMac, 0x00, 6);
//CUHeader->DevType = 0x0000;
}
else {
int ret = CheckCommUnitReg(GateWay, CommUnitMac);
if(ret < 0 && Cmd != COMM_UNIT_CMD_GET_SIGNAL)
2026-04-23 13:56:52 +08:00
return;
memcpy(CUHeader->DevMac, CommUnitMac, 6);
//CUHeader->DevType = GateWay->ConfigPara.CommUnitArray[ret].CUType;
}
CUHeader->Cmd = Cmd;
CUHeader->PayloadLen = PayloadLen;
SendLen = sizeof(CommUnitFrameHeader_t);
if(PayloadLen > 0) {
memcpy(&SendBuff[SendLen], Payload, PayloadLen);
SendLen += PayloadLen;
}
uint16_t crc16 = CRC_Modbus(CRC16_BASE, SendBuff, SendLen);
2026-04-23 13:56:52 +08:00
SendBuff[SendLen++] = crc16 & 0x00ff;
SendBuff[SendLen++] = (crc16 >> 8) & 0x00ff;
if(Send != NULL) {
Send(SendBuff, SendLen);
}
}
/*****************************************************************************************
* 函数名称: TrySendFullPowerCmd
* 功能描述: 当传感器处于FullPower状态时,直接下发待处理配置命令,无需等待传感器上报
* 参 数: GateWay, 网关参数
CommUnitIdx, 通讯单元索引
* 返 回 值: 无
*****************************************************************************************/
void TrySendFullPowerCmd(GateWayPara GateWay, int CommUnitIdx)
{
if(CommUnitIdx < 0 || CommUnitIdx >= COMMUNIT_NUM_MAX)
return;
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].RegFlag != true)
return;
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CUType != DEV_TYPE_EXT_COMMUNIT)
return;
//使用传感器当前已确认生效的FPO参数判断是否处于全功率时段
uint8_t FPOStart = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CurFPOTimeStart;
uint8_t FPODur = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CurFPOTime;
if(FPODur == 0)
return; //传感器当前未配置全功率时段,不能直接下发,需等待上报回应
struct tm cTime;
TimeGet(&cTime);
int curHour = cTime.tm_hour;
int endHour = FPOStart + FPODur;
bool inFPO = false;
if(FPODur >= 24) {
inFPO = true; //全天全功率
}
else if(endHour > 24) {
//跨天:如 Start=22, Dur=4,则 22~23 和 0~1 为全功率
inFPO = (curHour >= FPOStart || curHour < endHour - 24);
}
else {
//同天:如 Start=8, Dur=10,则 8~17 为全功率
inFPO = (curHour >= FPOStart && curHour < endHour);
}
if(!inFPO)
return;
uint8_t *Mac = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].Mac[0];
uint32_t ctime = TimeTs();
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag == true) {
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag = false;
LPDevConfigPara_t Config;
Config.CollectInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CollectInterval;
Config.ReportInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ReportInterval;
Config.ERInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERInterval;
Config.ERTime = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERTime;
Config.TimeStamp = ctime;
CommUnitCmdSend(GateWay, Mac, COMM_UNIT_CMD_READ, (uint8_t *)&Config, sizeof(LPDevConfigPara_t), Sx1276LoRaSendBuffer);
MAIN_DBG_LOG("FullPower direct send config. Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]);
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ContLaser == true) {
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff == true) {
CommUnitCmdSend(GateWay, Mac, COMM_UNIT_CMD_CONT_LASER, (uint8_t *)&GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff, 1, Sx1276LoRaSendBuffer);
}
MAIN_DBG_LOG("FullPower direct send laser cmd.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CailFlag == true) {
CommUnitCmdSend(GateWay, Mac, COMM_UNIT_CMD_CAIL, 0, 0, Sx1276LoRaSendBuffer);
MAIN_DBG_LOG("FullPower direct send calibrate cmd.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].TimeSyncFlag == true) {
CommUnitCmdSend(GateWay, Mac, COMM_UNIT_CMD_TIME_SYNC, (uint8_t *)&ctime, 4, Sx1276LoRaSendBuffer);
MAIN_DBG_LOG("FullPower direct send time sync cmd.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag == true) {
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag = false;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeConfirmed = false;
uint8_t FPOData[2];
FPOData[0] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeStart;
FPOData[1] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTime;
CommUnitCmdSend(GateWay, Mac, COMM_UNIT_CMD_SET_FPO_TIME, FPOData, 2, Sx1276LoRaSendBuffer);
MAIN_DBG_LOG("FullPower direct send FPO config. Start:%d, Duration:%d\r\n", FPOData[0], FPOData[1]);
}
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
}
2026-04-23 13:56:52 +08:00
/*****************************************************************************************
* 函数名称: CommUintOrgData
* 功能描述: 上传传感器数据函数
* 参 数: CUPara, 通讯单元参数
CUData, 通讯单元数据
sData, 数据入口
* 返 回 值: 数据长度
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
int CommUintOrgData(GateWayPara GateWay, CommUnitPara CUPara, CommUnitData CUData, uint8_t *sData)
{
uint16_t Len = 0;
uint8_t SensorN = 0;
Len = 3;
memcpy(&sData[3], CUPara->Mac[0], 6);
Len += 6;
sData[Len++] = CUPara->CommStatus;
// sData[Len++] = CUPara->BatLevel;
// sData[Len++] = CUPara->SensorN;
// for(int i = 0; i < SENSOR_NUM_MAX; i++) {
// if(CUPara->SensorType[i] != 0x0000) {
// sData[Len++] = CUPara->SensorType[i] & 0x00ff;
// sData[Len++] = (CUPara->SensorType[i] >> 8) & 0x00ff;
// SensorN++;
// }
// if(SensorN >= CUPara->SensorN)
// break;
// }
// SensorN = 0;
for(int i = 0; i < SENSOR_NUM_MAX; i++) {
if(CUPara->SensorType[i] != 0x0000) {
switch(CUPara->SensorType[i]) {
case FORCE_6D:
memcpy(&sData[Len], CUData->Data[i], sizeof(Force6D_T));
Len += sizeof(Force6D_T);
break;
case OSMOTIC_PRESSURE:
break;
case ELASTIC_WAVEGUIDE:
break;
case DIELECTRIC_MASS:
break;
case VIBRATE_SENSOR:
break;
case CONT_DEFOR_3D:
break;
case COMM_UNIT:
break;
case FORCE_3D:
break;
case LASER_TRACING:
memcpy(&sData[Len], CUData->Data[i], sizeof(LaserTracingType_T));
Len += sizeof(LaserTracingType_T);
2026-04-23 13:56:52 +08:00
break;
case WATER_LEVEL:
break;
case _0x000B:
break;
case _0x000C:
break;
case MULTI_PARAMETER_FUSION:
break;
case CRACK_DETECTION:
break;
case _0x000F:
break;
case ATTITUDE_MONITOR:
break;
case LASER_DISPLACE:
break;
case REBAR_STRESS:
break;
case ANCHOR_ROD_STRESS:
break;
case SURFACE_STRESS:
break;
case PRESSURE:
break;
case MICROWAVE_DISPLACE:
break;
case DISPLACEMENT:
memcpy(&sData[Len], CUData->Data[i], sizeof(Displacement_T));
Len += sizeof(Displacement_T);
break;
2026-04-23 13:56:52 +08:00
}
SensorN++;
}
if(SensorN >= CUPara->SensorN)
break;
}
sData[0] = (Len - 3) & 0x00ff;
sData[1] = ((Len - 3) >> 8) & 0x00ff;
sData[2] = NET_COMM_CMD_UPDATE;
return Len;
}
void DebugDisplaySensorData(int SensorIdx, uint16_t SensorType, uint8_t *SensorData)
{
switch(SensorType) {
case SENSOR_TYPE_NULL: {
break;
}
case FORCE_6D: {
Force6D_T Sensor;
memcpy((uint8_t *)&Sensor, SensorData, sizeof(Force6D_T));
MAIN_DBG_LOG("Sensor%d Type %04x: Accx=%d, Accy=%d, Accz=%d, Strain1=%d, Strain2=%d, Strain3=%d, Strain4=%d, Strain5=%d, Strain6=%d\r\n",
SensorIdx, SensorType, Sensor.AccX, Sensor.AccY, Sensor.AccZ,
Sensor.Strain1, Sensor.Strain2, Sensor.Strain3, Sensor.Strain4, Sensor.Strain5, Sensor.Strain6);
break;
}
case OSMOTIC_PRESSURE: {
break;
}
case ELASTIC_WAVEGUIDE:{
break;
}
case DIELECTRIC_MASS:{
break;
}
case VIBRATE_SENSOR:{
break;
}
case CONT_DEFOR_3D:{
break;}
case COMM_UNIT:{
break;
}
case FORCE_3D: {
break;
}
case LASER_TRACING: {
LaserTracingType_T Sensor;
memcpy((uint8_t *)&Sensor, SensorData, sizeof(LaserTracingType_T));
2026-04-23 13:56:52 +08:00
MAIN_DBG_LOG("Sensor%d Type %04x: PitchAngle=%04d, RollAngle=%04d, YawAngle=%04d\r\n",
SensorIdx, SensorType, Sensor.PitchAngle, Sensor.RollAngle, Sensor.YawAngle);
break;
}
case WATER_LEVEL: {
break;
}
case _0x000B: {
break;
}
case _0x000C: {
break;
}
case MULTI_PARAMETER_FUSION: {
break;
}
case CRACK_DETECTION: {
break;
}
case _0x000F: {
break;
}
case ATTITUDE_MONITOR: {
break;
}
case LASER_DISPLACE: {
break;
}
case REBAR_STRESS: {
break;
}
case ANCHOR_ROD_STRESS: {
break;
}
case SURFACE_STRESS: {
break;
}
case PRESSURE: {
break;
}
case MICROWAVE_DISPLACE: {
break;
}
case DISPLACEMENT: {
Displacement_T Sensor;
memcpy((uint8_t *)&Sensor, SensorData, sizeof(Displacement_T));
2026-06-05 11:08:54 +08:00
MAIN_DBG_LOG("Sensor%d Type %04x: PitchAngle=%04d, RollAngle=%04d, YawAngle=%04d, Temp=%06f, Altitude=%06f, Distance=%04d\r\n",
SensorIdx, SensorType, Sensor.PitchAngle, Sensor.RollAngle, Sensor.YawAngle, Sensor.Temp, Sensor.Altitude, Sensor.Distance);
break;
}
2026-04-23 13:56:52 +08:00
default:
break;
}
}
/*****************************************************************************************
* 函数名称: CommUnitAnalyze
* 功能描述: 通讯单元数据解析,使用于LORA和RS485通讯
* 参 数: rData,输入数据
rLen, 输入数据长度
* 返 回 值: 返回接收到的通讯单元序号,错误返回-1
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
int CommUnitAnalyze(GateWayPara GateWay, uint8_t *rData, uint16_t rLen, SendData Response)
{
uint16_t check, crc16;
int CommUnitIdx, ExclCommUnit;
2026-04-23 13:56:52 +08:00
uint16_t PayLoadLen;
uint8_t *PayLoad;
uint8_t *MegData;
uint16_t len;
//uint8_t *Data;
uint16_t CommUintLen;
CommUnitFrameHeader CUHeader = (CommUnitFrameHeader)rData;
PayLoad = &rData[sizeof(CommUnitFrameHeader_t)];
if(CUHeader->Header != 0x7B)
return -1;
check = CRC_Modbus(CRC16_BASE, rData, rLen - 2);
2026-04-23 13:56:52 +08:00
crc16 = rData[rLen - 2] | (rData[rLen - 1] << 8);
if(check != crc16)
return -1;
if((CUHeader->Cmd != COMM_UNIT_CMD_REG && CUHeader->Cmd != COMM_UNIT_CMD_GET_SIGNAL) && (memcmp(GateWay->ConfigPara.GwMac, CUHeader->GWMac, 6) != 0))
2026-04-23 13:56:52 +08:00
return -1;
CommUnitIdx = CheckCommUnitReg(GateWay, CUHeader->DevMac);//判断是否是已注册的设备
2026-04-23 13:56:52 +08:00
if(CommUnitIdx < 0) {
if(CUHeader->Cmd != COMM_UNIT_CMD_REG && CUHeader->Cmd != COMM_UNIT_CMD_GET_SIGNAL){//判断是否是注册请求
2026-04-23 13:56:52 +08:00
return -1;
}
ExclCommUnit = CheckCommUnitExcl(GateWay, CUHeader->DevMac);//判断是否是被排除的设备
if(ExclCommUnit > -1) {
return -1;
}
2026-04-23 13:56:52 +08:00
}
2026-04-23 13:56:52 +08:00
switch(CUHeader->Cmd) {
case COMM_UNIT_CMD_REG:{
if(PayLoad[0] > SENSOR_NUM_MAX) {
return -1;
}
/*串台防护: 校验注册payload合法性, 拦截频偏误解调的乱码帧*/
if(!RegPayloadValid(GateWay, CUHeader, PayLoad)) {
MAIN_DBG_LOG("\r\nReg rejected: invalid payload (cross-band interference?) Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
return -1;
}
2026-04-23 13:56:52 +08:00
// if(CUHeader->PayloadLen < 2)
// return -1;
if(CommUnitIdx >= 0) { //设备存在
2026-04-23 13:56:52 +08:00
MAIN_DBG_LOG("\r\nCommUnit has already been registered! Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
uint8_t ret = 1;
CommUnitPara_t *pCU = &GateWay->ConfigPara.CommUnitArray[CommUnitIdx];
bool ParaChanged = (pCU->CommErrCnt != 0 || pCU->ConfigFlag != true || pCU->CailFlag != false ||
pCU->TimeSyncFlag != false || pCU->ContLaser != false || pCU->LaserOnOff != false ||
pCU->FPOTimeFlag != false || pCU->FPOTimeConfirmed != true);
pCU->CommErrCnt = 0;
pCU->ConfigFlag = true;
pCU->CailFlag = false;
pCU->TimeSyncFlag = false;
pCU->ContLaser = false;
pCU->LaserOnOff = false;
pCU->FPOTimeFlag = false;
pCU->FPOTimeConfirmed = true;
/*先发应答再写Flash:WritePara需擦除2个扇区并写入约7KB参数(耗时百毫秒级),
若先写Flash,应答延迟过大,会超出传感器注册请求后的接收窗口导致其收不到回应;
参数无变化时跳过写入,避免传感器反复重注册时频繁擦写Flash*/
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_REG, &ret, 1, Response);
if(ParaChanged)
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
return CommUnitIdx;
}
2026-04-23 13:56:52 +08:00
for(int i = 0; i < COMMUNIT_NUM_MAX; i++) {
if(GateWay->ConfigPara.CommUnitArray[i].RegFlag == false) {
CommUnitIdx = i;
GateWay->ConfigPara.CommUnitArray[i].RegFlag = true;
GateWay->ConfigPara.CommUnitArray[i].CommStatus = true;
GateWay->ConfigPara.CommUnitArray[i].CailFlag = false;
GateWay->ConfigPara.CommUnitArray[i].TimeSyncFlag = false;
GateWay->ConfigPara.CommUnitArray[i].ContLaser = false;
GateWay->ConfigPara.CommUnitArray[i].LaserOnOff = false;
GateWay->ConfigPara.CommUnitArray[i].CUType = DEV_TYPE_EXT_COMMUNIT;//外置通讯单元
2026-04-23 13:56:52 +08:00
MAIN_DBG_LOG("\r\nCommUnit register succeed!\r\n");
memcpy(GateWay->ConfigPara.CommUnitArray[i].MasterMac, &PayLoad[1], 6);
MAIN_DBG_LOG("Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
GateWay->ConfigPara.CommUnitArray[i].SensorN = PayLoad[0];
MAIN_DBG_LOG("SensorN: %d ", GateWay->ConfigPara.CommUnitArray[i].SensorN);
//memcpy(GateWay->ConfigPara.CommUnitArray[i].SensorType, &PayLoad[1], CUHeader->PayloadLen-1);
MAIN_DBG_LOG("Sensor Type: ");
for(int j = 0; j < GateWay->ConfigPara.CommUnitArray[i].SensorN; j++) {
memcpy(GateWay->ConfigPara.CommUnitArray[i].Mac[j], &PayLoad[(j*6)+1], 6);
GateWay->ConfigPara.CommUnitArray[i].SensorType[j] = PayLoad[(j*6)+1] | (PayLoad[(j*6)+2] << 8);
MAIN_DBG_LOG("0x%04x, ", GateWay->ConfigPara.CommUnitArray[i].SensorType[j]);
}
MAIN_DBG_LOG("\r\n");
GateWay->ConfigPara.CommUnitArray[i].CommErrCnt = 0;
GateWay->ConfigPara.CommUnitArray[i].ConfigFlag = true;
GateWay->ConfigPara.CommUnitArray[i].CollectInterval = LW_DEV_COLLECT_INTERVAL_MAX;
GateWay->ConfigPara.CommUnitArray[i].ReportInterval = LW_DEV_REPORT_INTERVAL_MAX;
GateWay->ConfigPara.CommUnitArray[i].ERInterval = LW_DEV_ER_INTERVAL_MAX;
GateWay->ConfigPara.CommUnitArray[i].ERTime = LW_DEV_ER_TIME_MAX;
GateWay->ConfigPara.CommUnitArray[i].FPOTimeStart = LW_DEV_FPO_TIME_START_DEFAULT;
GateWay->ConfigPara.CommUnitArray[i].FPOTime = LW_DEV_FPO_TIME_DEFAULT;
GateWay->ConfigPara.CommUnitArray[i].CurFPOTimeStart = LW_DEV_FPO_TIME_START_DEFAULT;
GateWay->ConfigPara.CommUnitArray[i].CurFPOTime = LW_DEV_FPO_TIME_DEFAULT;
GateWay->ConfigPara.CommUnitArray[i].FPOTimeFlag = false;
GateWay->ConfigPara.CommUnitArray[i].FPOTimeConfirmed = true;
uint8_t ret = 1;
//先发应答再写Flash,避免WritePara耗时导致应答延迟过大(原因同上)
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_REG, &ret, 1, Response);
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
if(GateWay->MuchRegFlag) { //网关已注册,向服务发送新设备添加指令
2026-04-23 13:56:52 +08:00
PayLoadLen = (GateWay->ConfigPara.CommUnitArray[i].SensorN * 6) + 2;
MegData = rt_malloc(PayLoadLen + 3);
MegData[0] = PayLoadLen & 0x00ff;;
MegData[1] = (PayLoadLen >> 8) & 0x00ff;
MegData[2] = NET_COMM_CMD_ADD_UNIT;
MegData[3] = (GateWay->ConfigPara.CommUnitArray[i].SensorN) & 0x00ff;;
MegData[4] = (GateWay->ConfigPara.CommUnitArray[i].SensorN >> 8) & 0x00ff;
2026-07-14 18:52:51 +08:00
for(uint8_t k = 0; k < GateWay->ConfigPara.CommUnitArray[i].SensorN; k++)
2026-04-23 13:56:52 +08:00
{
2026-07-14 18:52:51 +08:00
memcpy(&MegData[5], GateWay->ConfigPara.CommUnitArray[i].Mac[k], 6);
2026-04-23 13:56:52 +08:00
}
UploadSend(MegData, PayLoadLen+5);
2026-04-23 13:56:52 +08:00
rt_free(MegData);
}
return 0xff;
}
}
MAIN_DBG_LOG("\r\nCommUnit register failed! Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
break;}
case COMM_UNIT_CMD_CAIL:{
if(PayLoad[0] == 0) {
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CailFlag = true;
MAIN_DBG_LOG("CommUnit calibrate failed! Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
}
else if(PayLoad[0] == 1){
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CailFlag = false;
MAIN_DBG_LOG("CommUnit calibrate succeed! Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
}
uint32_t ctime = TimeTs();
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag == true) {
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag = false;
LPDevConfigPara_t Config;
Config.CollectInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CollectInterval;
Config.ReportInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ReportInterval;
Config.ERInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERInterval;
Config.ERTime = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERTime;
Config.TimeStamp = ctime;
MAIN_DBG_LOG("CI:%d, RI:%d, EI:%d, ET:%d\r\n", Config.CollectInterval, Config.ReportInterval, Config.ERInterval, Config.ERTime);
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_READ, (uint8_t *)&Config, sizeof(LPDevConfigPara_t), Response);
2026-04-23 13:56:52 +08:00
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ContLaser == true)
{
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff == true)
{//打开激光
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_CONT_LASER, (uint8_t *)&GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff, 1, Response);
2026-04-23 13:56:52 +08:00
}
MAIN_DBG_LOG("Issue laser control commands.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CailFlag == true)
{
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_CAIL, 0, 0, Response);
2026-04-23 13:56:52 +08:00
MAIN_DBG_LOG("Issue calibration instructions.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].TimeSyncFlag == true)
{
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_TIME_SYNC, (uint8_t *)&ctime, 4, Response);
2026-04-23 13:56:52 +08:00
MAIN_DBG_LOG("Issue a time synchronization command.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag == true)
{
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag = false;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeConfirmed = false;
uint8_t FPOData[2];
FPOData[0] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeStart;
FPOData[1] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTime;
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_SET_FPO_TIME, FPOData, 2, Response);
MAIN_DBG_LOG("Issue FPO time config command. Start:%d, Duration:%d\r\n", FPOData[0], FPOData[1]);
}
2026-04-23 13:56:52 +08:00
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
break;}
2026-04-23 13:56:52 +08:00
case COMM_UNIT_CMD_READ:{
// if(PayLoad[1] > SENSOR_NUM_MAX) {
// return CommUnitIdx;
// }
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CommStatus = true;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].RevNewDataFlag = true;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CommErrCnt = 0;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].BatLevel = PayLoad[0];
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].RSSI = PayLoad[1];
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].Nsr = PayLoad[2];
// memset(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorType, 0x00, sizeof(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorType));
// memcpy(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorType, &PayLoad[2], GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorN * 2);
// len = 0;
// Data = &PayLoad[GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorN * 2 + 2];
// int16_t Rssi;
// int8_t Snr;
// SX1276LoCalcRssiSnr(&Rssi, &Snr);
MAIN_DBG_LOG("\r\nCUMac:%02X-%02X-%02X-%02X-%02X-%02X, Bat: %d%, SN: %d, Rssi:%d, Snr:%d\r\n",
2026-04-23 13:56:52 +08:00
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5],
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].BatLevel,
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorN,
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].RSSI,
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].Nsr);
for(int i = 0; i < GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorN; i++) {
memcpy(GateWay->CUDataArray[CommUnitIdx].Data[i], &PayLoad[0], SensorTypeDataLen[GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorType[i]]);
//显示传感器数据
2026-04-23 13:56:52 +08:00
DebugDisplaySensorData(i, GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorType[i], GateWay->CUDataArray[CommUnitIdx].Data[i]);
len += SensorTypeDataLen[GateWay->ConfigPara.CommUnitArray[CommUnitIdx].SensorType[i]];
}
#ifdef LORA_LOWPOWER
uint32_t ctime = TimeTs();
LPDevConfigPara_t Config;
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CollectInterval > 7200 || GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CollectInterval < 30)
{
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CollectInterval = 300;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag = true;
}
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ReportInterval > 720 || GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ReportInterval < 5)
{
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ReportInterval = 20;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag = true;
}
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERInterval > 5 || GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERInterval < 1)
{
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERInterval = 2;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag = true;
}
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERTime > 120 || GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERTime < 10)
{
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERTime = 20;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag = true;
}
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag == true) {
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag = false;
Config.CollectInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CollectInterval;
Config.ReportInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ReportInterval;
Config.ERInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERInterval;
Config.ERTime = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERTime;
Config.TimeStamp = ctime;
MAIN_DBG_LOG("CI:%d, RI:%d, EI:%d, ET:%d\r\n", Config.CollectInterval, Config.ReportInterval, Config.ERInterval, Config.ERTime);
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_READ, (uint8_t *)&Config, sizeof(LPDevConfigPara_t), Response);
2026-04-23 13:56:52 +08:00
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ContLaser == true)
{
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff == true)
{//打开激光
2026-04-23 13:56:52 +08:00
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_CONT_LASER, (uint8_t *)&GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff, 1, Response);
}
MAIN_DBG_LOG("Issue laser control commands.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CailFlag == true)
{
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_CAIL, 0, 0, Response);
MAIN_DBG_LOG("Issue calibration instructions.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].TimeSyncFlag == true)
{
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_TIME_SYNC, (uint8_t *)&ctime, 4, Response);
MAIN_DBG_LOG("Issue a time synchronization command.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag == true)
{
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag = false;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeConfirmed = false;
uint8_t FPOData[2];
FPOData[0] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeStart;
FPOData[1] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTime;
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_SET_FPO_TIME, FPOData, 2, Response);
MAIN_DBG_LOG("Issue FPO time config command. Start:%d, Duration:%d\r\n", FPOData[0], FPOData[1]);
}
2026-04-23 13:56:52 +08:00
else
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_READ, (uint8_t *)&ctime, 4, Response);
#endif
MegData = rt_malloc(512);
CommUintLen = CommUintOrgData(GateWay, &GateWay->ConfigPara.CommUnitArray[CommUnitIdx], &GateWay->CUDataArray[CommUnitIdx], MegData);
//AddLog(&MegData[2], CommUintLen);
UploadSend(MegData, CommUintLen);
2026-04-23 13:56:52 +08:00
rt_free(MegData);
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
break;}
case COMM_UNIT_CMD_TIME_SYNC:{
if(PayLoad[0] == 0) {
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].TimeSyncFlag = true;
MAIN_DBG_LOG("CommUnit time synchronization failed! Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
}
else if(PayLoad[0] == 1){
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].TimeSyncFlag = false;
MAIN_DBG_LOG("CommUnit time synchronization succeed! Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
}
uint32_t ctime = TimeTs();
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag == true) {
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag = false;
LPDevConfigPara_t Config;
Config.CollectInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CollectInterval;
Config.ReportInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ReportInterval;
Config.ERInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERInterval;
Config.ERTime = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERTime;
Config.TimeStamp = ctime;
MAIN_DBG_LOG("CI:%d, RI:%d, EI:%d, ET:%d\r\n", Config.CollectInterval, Config.ReportInterval, Config.ERInterval, Config.ERTime);
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_READ, (uint8_t *)&Config, sizeof(LPDevConfigPara_t), Response);
2026-04-23 13:56:52 +08:00
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ContLaser == true)
{
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff == true)
{//打开激光
2026-04-23 13:56:52 +08:00
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_CONT_LASER, (uint8_t *)&GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff, 1, Response);
}
MAIN_DBG_LOG("Issue laser control commands.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CailFlag == true)
{
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_CAIL, 0, 0, Response);
MAIN_DBG_LOG("Issue calibration instructions.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].TimeSyncFlag == true)
{
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_TIME_SYNC, (uint8_t *)&ctime, 4, Response);
MAIN_DBG_LOG("Issue a time synchronization command.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag == true)
{
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag = false;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeConfirmed = false;
uint8_t FPOData2[2];
FPOData2[0] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeStart;
FPOData2[1] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTime;
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_SET_FPO_TIME, FPOData2, 2, Response);
MAIN_DBG_LOG("Issue FPO time config command. Start:%d, Duration:%d\r\n", FPOData2[0], FPOData2[1]);
}
2026-04-23 13:56:52 +08:00
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
break;}
case COMM_UNIT_CMD_CONT_LASER:{
if(PayLoad[0] == 0) {
//应答服务器
2026-04-23 13:56:52 +08:00
MegData = rt_malloc(10);
MegData[0] = 7;
MegData[1] = 0;
MegData[2] = NET_COMM_CMD_CONT_LASER;
MegData[3] = CUHeader->DevMac[0];
MegData[4] = CUHeader->DevMac[1];
MegData[5] = CUHeader->DevMac[2];
MegData[6] = CUHeader->DevMac[3];
MegData[7] = CUHeader->DevMac[4];
MegData[8] = CUHeader->DevMac[5];
MegData[9] = PayLoad[0];
UploadSend(MegData, 10);
2026-04-23 13:56:52 +08:00
rt_free(MegData);
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff = false;
2026-04-23 13:56:52 +08:00
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ContLaser = false;
MAIN_DBG_LOG("CommUnit The laser has been turned off! Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
}
else if(PayLoad[0] == 1){
//应答服务器
2026-04-23 13:56:52 +08:00
MegData = rt_malloc(10);
MegData[0] = 7;
MegData[1] = 0;
MegData[2] = NET_COMM_CMD_CONT_LASER;
MegData[3] = CUHeader->DevMac[0];
MegData[4] = CUHeader->DevMac[1];
MegData[5] = CUHeader->DevMac[2];
MegData[6] = CUHeader->DevMac[3];
MegData[7] = CUHeader->DevMac[4];
MegData[8] = CUHeader->DevMac[5];
MegData[9] = PayLoad[0];
UploadSend(MegData, 10);
2026-04-23 13:56:52 +08:00
rt_free(MegData);
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff = true;
2026-04-23 13:56:52 +08:00
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ContLaser = false;
MAIN_DBG_LOG("CommUnit The laser has been activated! Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5]);
}
uint32_t ctime = TimeTs();
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag == true) {
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ConfigFlag = false;
LPDevConfigPara_t Config;
Config.CollectInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CollectInterval;
Config.ReportInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ReportInterval;
Config.ERInterval = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERInterval;
Config.ERTime = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ERTime;
Config.TimeStamp = ctime;
MAIN_DBG_LOG("CI:%d, RI:%d, EI:%d, ET:%d\r\n", Config.CollectInterval, Config.ReportInterval, Config.ERInterval, Config.ERTime);
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_READ, (uint8_t *)&Config, sizeof(LPDevConfigPara_t), Response);
2026-04-23 13:56:52 +08:00
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].ContLaser == true)
{
if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff == true)
{//打开激光
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_CONT_LASER, (uint8_t *)&GateWay->ConfigPara.CommUnitArray[CommUnitIdx].LaserOnOff, 1, Response);
2026-04-23 13:56:52 +08:00
}
MAIN_DBG_LOG("Issue laser control commands.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CailFlag == true)
{
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_CAIL, 0, 0, Response);
MAIN_DBG_LOG("Issue calibration instructions.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].TimeSyncFlag == true)
{
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_TIME_SYNC, (uint8_t *)&ctime, 4, Response);
MAIN_DBG_LOG("Issue a time synchronization command.\r\n");
}
else if(GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag == true)
{
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeFlag = false;
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeConfirmed = false;
uint8_t FPOData3[2];
FPOData3[0] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeStart;
FPOData3[1] = GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTime;
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_SET_FPO_TIME, FPOData3, 2, Response);
MAIN_DBG_LOG("Issue FPO time config command. Start:%d, Duration:%d\r\n", FPOData3[0], FPOData3[1]);
}
2026-04-23 13:56:52 +08:00
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
break;}
case COMM_UNIT_CMD_GET_SIGNAL:{
int16_t Rssi;
int8_t Snr;
uint8_t SignalPayload[2];
SX1276LoCalcRssiSnr(&Rssi, &Snr);
SignalPayload[0] = (uint8_t)Snr;
SignalPayload[1] = (uint8_t)(Rssi & 0xFF);
CommUnitCmdSend(GateWay, CUHeader->DevMac, COMM_UNIT_CMD_GET_SIGNAL, SignalPayload, 2, Response);
MAIN_DBG_LOG("\r\nCUMac:%02X-%02X-%02X-%02X-%02X-%02X, RX(Dev->GW): SNR:%d, RSSI:%d\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5],
Snr, Rssi);
break;}
case COMM_UNIT_CMD_SET_FPO_TIME:{
//传感器回应0x0A命令,携带配置参数
uint8_t FPOResponse = 0;
if(PayLoad[0] <= 23 && PayLoad[1] <= 24) {
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeStart = PayLoad[0];
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTime = PayLoad[1];
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CurFPOTimeStart = PayLoad[0];
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].CurFPOTime = PayLoad[1];
GateWay->ConfigPara.CommUnitArray[CommUnitIdx].FPOTimeConfirmed = true;
FPOResponse = 1;
MAIN_DBG_LOG("FPO time confirmed. Mac:%02X-%02X-%02X-%02X-%02X-%02X, Start:%d, Duration:%d\r\n",
CUHeader->DevMac[0], CUHeader->DevMac[1], CUHeader->DevMac[2], CUHeader->DevMac[3], CUHeader->DevMac[4], CUHeader->DevMac[5],
PayLoad[0], PayLoad[1]);
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
}
else {
MAIN_DBG_LOG("FPO time config invalid. Start:%d, Duration:%d\r\n", PayLoad[0], PayLoad[1]);
}
//回应服务器0x0A命令:DevAddr(6) + Response(1)
MegData = rt_malloc(10);
MegData[0] = 7;
MegData[1] = 0;
MegData[2] = NET_COMM_CMD_FPO_CONFIG;
memcpy(&MegData[3], CUHeader->DevMac, 6);
MegData[9] = FPOResponse;
UploadSend(MegData, 10);
rt_free(MegData);
break;}
2026-04-23 13:56:52 +08:00
default:
break;
}
return CommUnitIdx;
}
/*****************************************************************************************
* 函数名称: _NetRevCallBack
* 功能描述: much、auch接收回调函数
* 参 数: rData,数据输入接口
rLen, 数据长度输入接口
* 返 回 值: 无
2026-04-23 13:56:52 +08:00
*****************************************************************************************/
static int _NetRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen, bool *pRegFlag)
2026-04-23 13:56:52 +08:00
{
uint16_t check,crc16;
uint8_t *Data;
uint8_t *MegData;
uint8_t sLen;
uint8_t CommUintMac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
NetCommFrameHeader NCHeader = (NetCommFrameHeader)rData;
uint16_t FrameLen = sizeof(NetCommFrameHeader_t) + NCHeader->PayloadLen;
if(FrameLen > CAT_ONE_REV_LEN_MAX)
return -1;
if(NCHeader->Header != 0x7A)
return -1;
if(memcmp(NCHeader->GWMac, GateWay->ConfigPara.GwMac, 6) != 0x00)
return -1;
check = CRC_Modbus(CRC16_BASE, rData, FrameLen);
2026-04-23 13:56:52 +08:00
crc16 = rData[FrameLen] | (rData[FrameLen + 1] << 8);
Data = &rData[sizeof(NetCommFrameHeader_t)];
if(check != crc16)
return -1;
uint32_t cTime = TimeTs();
if(abs((int)(NCHeader->Timestamp - cTime)) > 2) {
TimeSync(NCHeader->Timestamp);
GateWay->TimeSyncFlag = true;
SensorCommPara_t SCPara;
SCPara.Cmd = RS485_SENSOR_CMD_TIME_SYNC;
SCPara.SensorAddr = 0x00;
SCPara.SensorType = 0x00;
SCPara.CmdParaLen = 4;
SCPara.CmdPara = (uint8_t *)&NCHeader->Timestamp;
memcpy(&CommUintMac[0], Data, 6);
if(GateWay->ConfigPara.Rs485Ch1.Enable == true) { //内部通讯单元处理
2026-04-23 13:56:52 +08:00
if(GateWay->ConfigPara.Rs485Ch1.CommUnitEnable == true)
CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_TIME_SYNC, (uint8_t *)&NCHeader->Timestamp, 4, GateWay->ConfigPara.Rs485Ch1.RS485Send);
2026-04-23 13:56:52 +08:00
else
RS485CmdSend(GateWay, 1, &SCPara);
}
if(GateWay->ConfigPara.Rs485Ch2.Enable == true) {
if(GateWay->ConfigPara.Rs485Ch2.CommUnitEnable == true)
CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_TIME_SYNC, (uint8_t *)&NCHeader->Timestamp, 4, GateWay->ConfigPara.Rs485Ch2.RS485Send);
2026-04-23 13:56:52 +08:00
else
RS485CmdSend(GateWay, 2, &SCPara);
}
for(int i = 0; i < COMMUNIT_NUM_MAX; i++)//参数遍历
2026-04-23 13:56:52 +08:00
{
if(GateWay->ConfigPara.CommUnitArray[i].RegFlag == true) {
GateWay->ConfigPara.CommUnitArray[i].TimeSyncFlag = true;//校时置位,等待下次此MAC主设备上传数据时下发校准指令(低功耗)
TrySendFullPowerCmd(GateWay, i);
}
2026-04-23 13:56:52 +08:00
}
//校准其他通讯网关
2026-04-23 13:56:52 +08:00
//CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_TIME_SYNC, &rData[14], 4, Sx1276LoRaSendBuffer);
}
switch(NCHeader->Cmd) {
case NET_COMM_CMD_REG:{
if(*Data == 1) { //注册成功
*pRegFlag = true;
2026-04-23 13:56:52 +08:00
memset(GateWay->SvrMac, 0x00, 6);
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
MAIN_DBG_LOG("Gateway %s Registered...\r\n",
pRegFlag == &GateWay->MuchRegFlag ? "Much" : "Auch");
2026-04-23 13:56:52 +08:00
}
else {
*pRegFlag = false;
2026-04-23 13:56:52 +08:00
memset(GateWay->SvrMac, 0x00, 6);
MAIN_DBG_LOG("Gateway %s Register Failed....\r\n",
pRegFlag == &GateWay->MuchRegFlag ? "Much" : "Auch");
2026-04-23 13:56:52 +08:00
}
break;}
case NET_COMM_CMD_CAIL:{
//应答服务器
2026-04-23 13:56:52 +08:00
MegData = rt_malloc(4);
MegData[0] = 1;
MegData[1] = 0;
MegData[2] = NET_COMM_CMD_CAIL;
MegData[3] = 1;
sLen = 4;
UploadSend(MegData, sLen);
2026-04-23 13:56:52 +08:00
rt_free(MegData);
//开始校准
2026-04-23 13:56:52 +08:00
memcpy(&CommUintMac[0], Data, 6);
if(memcmp(CommUintMac, Data, 6) == 0) { //校准所有传感器
2026-04-23 13:56:52 +08:00
SensorCommPara_t SCPara;
SCPara.Cmd = RS485_SENSOR_CMD_CAIL;
SCPara.SensorAddr = 0x00;
//SCPara.SensorType = 0x00;
SCPara.CmdParaLen = 0;
SCPara.CmdPara = NULL;
if(GateWay->ConfigPara.Rs485Ch1.Enable == true) { //内部通讯单元处理
2026-04-23 13:56:52 +08:00
if(GateWay->ConfigPara.Rs485Ch1.CommUnitEnable == true)
RS485CmdSend(GateWay, 1, &SCPara);
else
CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_CAIL, NULL, 0, GateWay->ConfigPara.Rs485Ch1.RS485Send);
}
if(GateWay->ConfigPara.Rs485Ch2.Enable == true) {
if(GateWay->ConfigPara.Rs485Ch2.CommUnitEnable == true)
2026-04-23 13:56:52 +08:00
RS485CmdSend(GateWay, 2, &SCPara);
else
CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_CAIL, NULL, 0, GateWay->ConfigPara.Rs485Ch2.RS485Send);
}
for(int i = 0; i < COMMUNIT_NUM_MAX; i++)//参数遍历
2026-04-23 13:56:52 +08:00
{
if(GateWay->ConfigPara.CommUnitArray[i].RegFlag == true) {
GateWay->ConfigPara.CommUnitArray[i].CailFlag = true;//校准置位,等待下次此MAC主设备上传数据时下发校准指令(低功耗)
TrySendFullPowerCmd(GateWay, i);
}
2026-04-23 13:56:52 +08:00
}
//校准其他通讯网关
2026-04-23 13:56:52 +08:00
//CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_CAIL, NULL, 0, Sx1276LoRaSendBuffer);
MAIN_DBG_LOG("Calibrate all device.\r\n");
}
else {
int ret = CheckCommUnitReg(GateWay, CommUintMac);
if(ret < 0)
return -1;
if(GateWay->ConfigPara.CommUnitArray[ret].CUType != DEV_TYPE_EXT_COMMUNIT)
return -1;
if((GateWay->ConfigPara.CommUnitArray[ret].Mac[0][3] / 0x80) != 1) {//判断是否为通讯单元(主设备)
if(GateWay->ConfigPara.CommUnitArray[ret].Mac[0][2] == 1)//判断通讯类型
2026-04-23 13:56:52 +08:00
{
GateWay->ConfigPara.CommUnitArray[ret].CailFlag = true;//校准置位,等待下次此MAC主设备上传数据时下发校准指令(低功耗)
//CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_CAIL, NULL, 0, Sx1276LoRaSendBuffer);//查询模式
2026-04-23 13:56:52 +08:00
MAIN_DBG_LOG("Calibrate Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CommUintMac[0], CommUintMac[1], CommUintMac[2], CommUintMac[3], CommUintMac[4], CommUintMac[5]);
TrySendFullPowerCmd(GateWay, ret);
2026-04-23 13:56:52 +08:00
}
else if(GateWay->ConfigPara.CommUnitArray[ret].Mac[0][2] == 2)//判断通讯类型
2026-04-23 13:56:52 +08:00
{
if(GateWay->ConfigPara.Rs485Ch1.Enable == true && !GateWay->ConfigPara.Rs485Ch1.CommUnitEnable)
{
CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_CAIL, NULL, 0, GateWay->ConfigPara.Rs485Ch1.RS485Send);
}
else if(GateWay->ConfigPara.Rs485Ch2.Enable == true && !GateWay->ConfigPara.Rs485Ch2.CommUnitEnable)
{
CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_CAIL, NULL, 0, GateWay->ConfigPara.Rs485Ch2.RS485Send);
}
}
}
}
break;}
case NET_COMM_CMD_UPDATE:{
MAIN_DBG_LOG("Received server response.....\r\n");
break;}
case NET_COMM_CMD_READ_GW_INFO: {
MegData = rt_malloc(512);
uint16_t SensorCnt = 0;
sLen = 5;
if(GateWay->ConfigPara.Rs485Ch1.Enable == true) { //内部通讯单元处理
2026-04-23 13:56:52 +08:00
if(GateWay->ConfigPara.Rs485Ch1.CommUnitEnable == true) {
SensorCnt++;
memcpy(&MegData[sLen], GateWay->ConfigPara.Rs485Ch1.CUPara.Para.Mac[0], 6);
2026-04-23 13:56:52 +08:00
sLen += 6;
}
}
if(GateWay->ConfigPara.Rs485Ch2.Enable == true) {
if(GateWay->ConfigPara.Rs485Ch2.CommUnitEnable == true) {
SensorCnt++;
memcpy(&MegData[sLen], GateWay->ConfigPara.Rs485Ch2.CUPara.Para.Mac[0], 6);
2026-04-23 13:56:52 +08:00
sLen += 6;
}
}
for(int i = 0; i < COMMUNIT_NUM_MAX; i++) {
if(GateWay->ConfigPara.CommUnitArray[i].RegFlag) {
for(int j = 0; j < GateWay->ConfigPara.CommUnitArray[i].SensorN; j++)
{
SensorCnt++;
memcpy(&MegData[sLen], GateWay->ConfigPara.CommUnitArray[i].Mac[j], 6);
sLen += 6;
}
}
}
MegData[sLen++] = GateWay->Battery;
MegData[sLen++] = GateWay->UploadInterval & 0x00ff;
MegData[sLen++] = (GateWay->UploadInterval >> 8) & 0x00ff;
MegData[sLen++] = GateWay->HistoryNum & 0x00ff;
MegData[sLen++] = (GateWay->HistoryNum >> 8) & 0x00ff;
MegData[sLen++] = (GateWay->HistoryNum >> 16) & 0x00ff;
MegData[sLen++] = (GateWay->HistoryNum >> 24) & 0x00ff;
MegData[0] = (sLen - 3) & 0x00ff;//数据体长度
MegData[1] = ((sLen - 3) >> 8) & 0x00ff;//数据体长度
MegData[2] = NET_COMM_CMD_READ_GW_INFO;//指令
2026-04-23 13:56:52 +08:00
MegData[3] = SensorCnt&0xFF;
MegData[4] = (SensorCnt >> 8)&0xFF;
UploadSend(MegData, sLen);
2026-04-23 13:56:52 +08:00
rt_free(MegData);
break;
}
case NET_COMM_CMD_GW_PARA_CONFIG:{
//应答服务器
2026-04-23 13:56:52 +08:00
MegData = rt_malloc(4);
MegData[0] = 1;
MegData[1] = 0;
MegData[2] = NET_COMM_CMD_GW_PARA_CONFIG;
MegData[3] = 1;
sLen = 4;
UploadSend(MegData, sLen);
2026-04-23 13:56:52 +08:00
rt_free(MegData);
MAIN_DBG_LOG("AThe server sends down the gateway parameter configuration...\r\n");
break;}
case NET_COMM_CMD_HIS_DATA: {
uint32_t *StartIdx, *EndIdx;
StartIdx = (uint32_t *)Data;
EndIdx = (uint32_t *)&Data[4];
if(*StartIdx > GateWay->HistoryNum)
return -1;
if(*EndIdx == 0) {
*EndIdx = GateWay->HistoryNum;
}
LogHeader_t LogH;
LogH.LogEndAddr = 0;
for(int i = *StartIdx; i < *EndIdx; i++) {
uint8_t *HisData;
int ret = ReadHistoryData(&LogH, &HisData, i);
if(HisData != NULL) {
MegData = rt_malloc(ret + 15);
MegData[0] = ret - 1 + 4;
MegData[1] = NET_COMM_CMD_HIS_DATA;
memcpy(&MegData[2], (uint8_t *)&LogH.LogIdx, 4);
sLen = 6;
memcpy(&MegData[sLen], HisData, 6);
sLen += 6;
memcpy(&MegData[sLen], &HisData[7], ret - 7);
sLen += ret - 7;
UploadSend(MegData, sLen);
2026-04-23 13:56:52 +08:00
rt_free(MegData);
rt_free(HisData);
rt_thread_delay(10);
}
else {
continue;
}
}
break;}
2026-04-23 13:56:52 +08:00
case NET_COMM_CMD_ADD_UNIT:{
if(*Data == 1) { //录入成功
2026-04-23 13:56:52 +08:00
MAIN_DBG_LOG("Adding CommUnit succeeded...\r\n");
}
else {
MAIN_DBG_LOG("Adding CommUnit Failed...\r\n");
}
break;}
case NET_COMM_CMD_LP_DEV_CONFIG: {
//13字节:DevAddr(6) + CollectInterval(2) + ReportInterval(2) + ERInterval(1) + ERTime(1)
2026-04-23 13:56:52 +08:00
SvrDownLPDevConfigPara_t *LPDevConfig;
LPDevConfig = (SvrDownLPDevConfigPara_t *)Data;
int ret = memcmp(CommUintMac, LPDevConfig->CommDevAddr, 6);
if(ret == 0) {
for(int i = 0; i < COMMUNIT_NUM_MAX; i++) {
if(GateWay->ConfigPara.CommUnitArray[i].RegFlag) {
GateWay->ConfigPara.CommUnitArray[i].CollectInterval = LPDevConfig->CollectInterval;
GateWay->ConfigPara.CommUnitArray[i].ReportInterval = LPDevConfig->ReportInterval;
GateWay->ConfigPara.CommUnitArray[i].ERInterval = LPDevConfig->ERInterval;
GateWay->ConfigPara.CommUnitArray[i].ERTime = LPDevConfig->ERTime;
GateWay->ConfigPara.CommUnitArray[i].ConfigFlag = true;
TrySendFullPowerCmd(GateWay, i);
2026-04-23 13:56:52 +08:00
}
}
MAIN_DBG_LOG("Configure all the parameters of the main devices.\r\n");
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
}
else {
memcpy(&CommUintMac[0], Data, 6);
int ret = CheckCommUnitReg(GateWay, CommUintMac);
if(ret < 0)
return -1;
GateWay->ConfigPara.CommUnitArray[ret].CollectInterval = LPDevConfig->CollectInterval;
GateWay->ConfigPara.CommUnitArray[ret].ReportInterval = LPDevConfig->ReportInterval;
GateWay->ConfigPara.CommUnitArray[ret].ERInterval = LPDevConfig->ERInterval;
GateWay->ConfigPara.CommUnitArray[ret].ERTime = LPDevConfig->ERTime;
GateWay->ConfigPara.CommUnitArray[ret].ConfigFlag = true;
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
MAIN_DBG_LOG("Main equipment parameter configuration. Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CommUintMac[0], CommUintMac[1], CommUintMac[2], CommUintMac[3], CommUintMac[4], CommUintMac[5]);
TrySendFullPowerCmd(GateWay, ret);
2026-04-23 13:56:52 +08:00
}
//应答服务器
2026-04-23 13:56:52 +08:00
MegData = rt_malloc(4);
MegData[0] = 1;
MegData[1] = 0;
MegData[2] = NET_COMM_CMD_LP_DEV_CONFIG;
MegData[3] = 1;
sLen = 4;
UploadSend(MegData, sLen);
2026-04-23 13:56:52 +08:00
rt_free(MegData);
break;}
case NET_COMM_CMD_FPO_CONFIG: {
//8字节:DevAddr(6) + FPOTimeStart(1) + FPOTime(1),全功率时间配置
SvrDownFPOConfigPara_t *FPOConfig;
FPOConfig = (SvrDownFPOConfigPara_t *)Data;
memcpy(&CommUintMac[0], Data, 6);
int ret = CheckCommUnitReg(GateWay, CommUintMac);
if(ret < 0)
return -1;
GateWay->ConfigPara.CommUnitArray[ret].FPOTimeStart = FPOConfig->FPOTimeStart;
GateWay->ConfigPara.CommUnitArray[ret].FPOTime = FPOConfig->FPOTime;
GateWay->ConfigPara.CommUnitArray[ret].FPOTimeFlag = true;
GateWay->ConfigPara.CommUnitArray[ret].FPOTimeConfirmed = false;
WritePara((uint8_t *)&GateWay->ConfigPara, sizeof(GWConfigPara_t));
MAIN_DBG_LOG("FPO time config. Mac:%02X-%02X-%02X-%02X-%02X-%02X, Start:%d, Duration:%d\r\n",
CommUintMac[0], CommUintMac[1], CommUintMac[2], CommUintMac[3], CommUintMac[4], CommUintMac[5],
FPOConfig->FPOTimeStart, FPOConfig->FPOTime);
TrySendFullPowerCmd(GateWay, ret);
break;}
case NET_COMM_CMD_ALARM:{
MAIN_DBG_LOG("Received server response.....\r\n");
break;}
2026-04-23 13:56:52 +08:00
case NET_COMM_CMD_CONT_LASER:{
memcpy(&CommUintMac[0], Data, 6);
int ret = CheckCommUnitReg(GateWay, CommUintMac);
if(ret < 0)
return -1;
if(GateWay->ConfigPara.CommUnitArray[ret].CUType != DEV_TYPE_EXT_COMMUNIT)
return -1;
if((GateWay->ConfigPara.CommUnitArray[ret].Mac[0][3] / 0x80) != 1) {//判断是否为通讯单元(主设备)
if(GateWay->ConfigPara.CommUnitArray[ret].Mac[0][2] == 1)//判断通讯类型
2026-04-23 13:56:52 +08:00
{
GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff = Data[6];//服务器下发打开或者关闭激光
2026-04-23 13:56:52 +08:00
if(GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff == true)
{
GateWay->ConfigPara.CommUnitArray[ret].ContLaser = true;//控制激光,等待下次此MAC主设备上传数据时下发打开激光指令(低功耗)
2026-04-23 13:56:52 +08:00
MAIN_DBG_LOG("Waiting for the laser response. Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CommUintMac[0], CommUintMac[1], CommUintMac[2], CommUintMac[3], CommUintMac[4], CommUintMac[5]);
TrySendFullPowerCmd(GateWay, ret);
2026-04-23 13:56:52 +08:00
}
else if(GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff == false)
{//直接发送
2026-04-23 13:56:52 +08:00
MAIN_DBG_LOG("Waiting for the laser response. Mac:%02X-%02X-%02X-%02X-%02X-%02X\r\n",
CommUintMac[0], CommUintMac[1], CommUintMac[2], CommUintMac[3], CommUintMac[4], CommUintMac[5]);
GateWay->ConfigPara.CommUnitArray[ret].ContLaser = false;
CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_CONT_LASER, (uint8_t *)&GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff, 1, Sx1276LoRaSendBuffer);//查询模式
2026-04-23 13:56:52 +08:00
}
}
else if(GateWay->ConfigPara.CommUnitArray[ret].Mac[0][2] == 2)//判断通讯类型
2026-04-23 13:56:52 +08:00
{
if(GateWay->ConfigPara.Rs485Ch1.Enable == true && !GateWay->ConfigPara.Rs485Ch1.CommUnitEnable)
{
GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff = Data[6];//服务器下发打开或者关闭激光
2026-04-23 13:56:52 +08:00
if(GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff == true)
{
GateWay->ConfigPara.CommUnitArray[ret].ContLaser = true;//控制激光,等待下次此MAC主设备上传数据时下发打开激光指令(低功耗)
2026-04-23 13:56:52 +08:00
}
else if(GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff == false)
{
CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_CONT_LASER, &Data[6], 1, GateWay->ConfigPara.Rs485Ch1.RS485Send);
}
}
else if(GateWay->ConfigPara.Rs485Ch2.Enable == true && !GateWay->ConfigPara.Rs485Ch2.CommUnitEnable)
{
GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff = Data[6];//服务器下发打开或者关闭激光
2026-04-23 13:56:52 +08:00
if(GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff == true)
{
GateWay->ConfigPara.CommUnitArray[ret].ContLaser = true;//控制激光,等待下次此MAC主设备上传数据时下发打开激光指令(低功耗)
2026-04-23 13:56:52 +08:00
}
else if(GateWay->ConfigPara.CommUnitArray[ret].LaserOnOff == false)
{
CommUnitCmdSend(GateWay, CommUintMac, COMM_UNIT_CMD_CONT_LASER, &Data[6], 1, GateWay->ConfigPara.Rs485Ch2.RS485Send);
}
}
}
}
break;}
default:
break;
}
return 0;
}
int MuchRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen)
{
return _NetRevCallBack(GateWay, rData, rLen, &GateWay->MuchRegFlag);
}
int AuchRevCallBack(GateWayPara GateWay, uint8_t *rData, uint16_t rLen)
{
return _NetRevCallBack(GateWay, rData, rLen, &GateWay->AuchRegFlag);
}