#include "gprs.h" #include "string.h" #include "AiderProtocol.h" #include "API-Platform.h" #include "rtc.h" #include "NB-IOT.h" #include "TEA.h" #include "gsdk_api.h" #include "gsdk_sdk.h" #include "gsdk_ril.h" #include "gsdk_ril_cmds.h" #include "bsp_ds2782.h" #include "flash.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////// /* 1、由于数据帧中存在回车换行符,因此通过3G模块AT命令上传数据的长度有待确认。 2、关于一帧上传数据的数据采集方式有两种方案,分别是: 一、数据采集时间在两次数据上传时间之间平均分配,此时需要采集一次数据进行休眠,同时将采集到的数据存入外部存储区, 并用外存或者备份寄存器记录数据采集次数。 二、数据采集间隔远小于数据上传时间间隔,定时唤醒,唤醒之后立即采集数据,N组数据采集完成之后立即上传到服务器, 上传完成,并完成其他相关处理后,再次进入待机模式。 目前默认采用方案二 */ ///////////////////////////////////////////////////////////////////////////////////////////////////////////// extern struct DeviceSet DeviceConfig; //配置信息结构体 extern struct BusinessData businessData; extern struct DataFrame dataFrame; extern uint8_t DeviceID[6]; extern uint16_t NodeAddr; extern uint8_t RouteControl; extern char IMEI_Code[32]; //有效15位结束位0 extern char ICCID_Code[32]; //有效20位结束位0 extern uint8_t SIMCard_Type; extern uint8_t signalValue[6]; extern uint8_t Flash_Write_Flag[9]; extern double GASData; extern uint16_t ACR; /******************************************************************************* * Function Name : XX * Description : XX * Input : None * Output : None * Return : None *******************************************************************************/ uint16_t StartupRequest(uint8_t* pSendBuff, uint8_t Optype) { struct SpecialDataFrame StartupSend; struct SpecialDataFrame* pDataFrame = &StartupSend; char* pChar = NULL; uint16_t CrcData = 0; uint8_t i, g = 0, NB_ReTry=0; uint8_t Offset = 0; //发送缓存地址偏移变量 uint8_t ValidLength = 0; //有效数据长度,指1个Tag空间中实际存储有效数据的长度。 uint8_t LengthKey = 0; //数据净荷部分长度字段指示的数值 const uint8_t PreLength = 16; //帧前缀长度,指从帧前导码到OID序列(或者Tag序列)的数据长度,包括帧前导码,而不包括OID序列(或者Tag序列) const uint8_t CoreLength = 12; //关键信息长度,指数据净荷部分长度字段指示的数值,去除Tag序列后剩余数据的长度 uint16_t Send_Flag = 0; uint8_t TEA_Data[MAX_SEND_DATA]; //加密以后数据长度为8的倍数,加密前长度除以8向上取整后乘以8 uint16_t TEA_Data_Len; printf("\r\n**********StartupRequest**********\r\n"); pChar = (char*)pDataFrame; memset(pChar, 0x00, sizeof(struct SpecialDataFrame)); //初始化结构体 StartupSend.Preamble = 0xA3; StartupSend.Version = 0x20; for(g = 0; g < 6; g++) { StartupSend.DeviceID[g] = DeviceID[g]; } StartupSend.RouteFlag = RouteControl; //通讯方式 StartupSend.NodeAddr = ntohs(NodeAddr); //调整为网络序,即高字节在前,低字节在后 switch (Optype) { case 12 : StartupSend.PDU_Type = (12 << 8) + (1 << 7) + 0x1C; //SetResponse break; case 8 : StartupSend.PDU_Type = (8 << 8) + (1 << 7) + 0x1C; //StartupRequest break; default: StartupSend.PDU_Type = (4 << 8) + (1 << 7) + 0x1C; //默认为TrapRequest printf("\r\nOptype:%d\r\n", Optype); //测试使用, 设备类型相关 break; } StartupSend.PDU_Type = ntohs(StartupSend.PDU_Type); //调整为网络序,即高字节在前,低字节在后 StartupSend.Seq = 0x01; LengthKey = CoreLength; if(Optype == 8) { StartupSend.TagList[0].OID_Command = ntohl(CARRIER_CODE); //设备类型相关 StartupSend.TagList[0].Width = 35; memcpy(StartupSend.TagList[0].Value,IMEI_Code + 7,15); memcpy(StartupSend.TagList[0].Value+15,ICCID_Code,20); printf("CARRIER_CODE:%s",StartupSend.TagList[0].Value); StartupSend.Length = LengthKey + StartupSend.TagList[0].Width + 6; } else if(Optype == 12) { StartupSend.TagList[0].OID_Command = ntohl(DEF_NR); //重传次数 StartupSend.TagList[0].Width = 1; StartupSend.TagList[0].Value[0] = DeviceConfig.RetryNum; StartupSend.Length = LengthKey + StartupSend.TagList[0].Width + 6; StartupSend.TagList[1].OID_Command = ntohl(CLT1_ITRL1); StartupSend.TagList[1].Width = 2; StartupSend.TagList[1].Value[0] = DeviceConfig.CollectPeriod >> 8; //数据采集间隔,高字节在前 StartupSend.TagList[1].Value[1] = DeviceConfig.CollectPeriod & 0xff; //数据采集间隔,低字节在后 StartupSend.Length = StartupSend.Length + StartupSend.TagList[1].Width + 6; StartupSend.TagList[2].OID_Command = ntohl(UPLOAD_CYCLE); StartupSend.TagList[2].Width = 2; StartupSend.TagList[2].Value[0] = DeviceConfig.UploadCycle >> 8; //数据上报周期,高字节在前 StartupSend.TagList[2].Value[1] = DeviceConfig.UploadCycle & 0xff; //数据上报周期,低字节在后 StartupSend.Length = StartupSend.Length + StartupSend.TagList[1].Width + 6; } StartupSend.Length = ntohs(StartupSend.Length); //计算长度字段 memcpy(pSendBuff, &StartupSend.Preamble, 1); memcpy(pSendBuff+1, &StartupSend.Version, 1); memcpy(pSendBuff+2, &StartupSend.Length, 2); memcpy(pSendBuff+4, &StartupSend.DeviceID, 6); memcpy(pSendBuff+10, &StartupSend.RouteFlag, 1); memcpy(pSendBuff+11, &StartupSend.NodeAddr, 2); memcpy(pSendBuff+13, &StartupSend.PDU_Type, 2); memcpy(pSendBuff+15, &StartupSend.Seq, 1); // memcpy(pSendBuff, pChar, PreLength); //复制Tag之前的数据到发送Buff Offset = PreLength; //指针偏移地址 if(Optype == 8) { pChar = (char*) & (StartupSend.TagList[0].OID_Command); ValidLength = StartupSend.TagList[0].Width + 6; //计算1个数据Tag实际占用的字节空间 StartupSend.TagList[0].Width = ntohs(StartupSend.TagList[0].Width); //调整为网络序,即高字节在前,低字节在后 memcpy((pSendBuff + Offset), pChar, ValidLength); //复制每一个数据Tag到发送Buff Offset = Offset + ValidLength; } else if(Optype == 12) { for(i = 0; i < 3; i++) { pChar = (char*) & (StartupSend.TagList[i].OID_Command); //Tag ValidLength = StartupSend.TagList[i].Width + 6; //计算1个Tag实际占用的字节空间 StartupSend.TagList[i].Width = ntohs(StartupSend.TagList[i].Width); //调整为网络序,即高字节在前,低字节在后 memcpy((pSendBuff + Offset), pChar, ValidLength); //复制Tag数据到发送Buff Offset = Offset + ValidLength; } } for(g = 0; g < Offset; g++) { printf("%.2x ", pSendBuff[g]); //测试使用 } printf("\r\n*********pSendBuff!***********\r\n"); //payload 加密 memcpy(TEA_Data, (char*)(pSendBuff + PreLength), (Offset - PreLength)); TEA_Data_Len = Tea_Encrypt(TEA_Data, (Offset - PreLength)); memcpy((pSendBuff + PreLength), TEA_Data, TEA_Data_Len); //复制加密之后的payload数据到发送Buff Offset = PreLength + TEA_Data_Len; CrcData = CRC16(pSendBuff, Offset ); // Update the CRC value StartupSend.CrcCode = CrcData; pSendBuff[Offset++] = CrcData >> 8; //CRC高字节在前 pSendBuff[Offset++] = CrcData & 0xff; //CRC低字节在后 for(g = 0; g < Offset; g++) { printf("%.2x ", pSendBuff[g]); //测试使用 } /////////////////////////////////////////////////////////////////////////////////////////////////////////// for(NB_ReTry=0; NB_ReTry<1; NB_ReTry++) { printf("\r\n*********NB Start!***********\r\n"); printf("\r\n***************发送次数:%d***************\r\n",g); if(SIMCard_Type == 1) //电信NB,发送到IOT平台 { Send_Flag =SendMessage_NB_T(pSendBuff, Offset); } else if(SIMCard_Type == 0) //移动、联通NB,直接发送到后台服务器 { Send_Flag =SendMessage_NB_MU(pSendBuff, Offset); } else { printf("\r\n ===========SIM卡异常,无法发数!===========!!\r\n"); } if(Send_Flag == 0x099C) { printf("\r\nReceive StartupResponse success!\r\n"); //测试使用 break; } } printf("\r\n----Length:%d----\r\n", Offset); //测试使用 for(g = 0; g < Offset; g++) { printf("%.2x ", pSendBuff[g]); //测试使用 } return Send_Flag; } /******************************************************************************* * Function Name : XX * Description : XX * Input : None * Output : None * Return : None *******************************************************************************/ uint16_t TrapRequest(uint8_t* pSendBuff, uint8_t Optype) { struct SpecialDataFrame TrapSend; struct SpecialDataFrame* pDataFrame = &TrapSend; char* pChar = NULL; uint16_t CrcData = 0; uint8_t i,g = 0; uint8_t Offset = 0; //发送缓存地址偏移变量 uint8_t ValidLength = 0; //有效数据长度,指1个Tag空间中实际存储有效数据的长度。 uint8_t LengthKey = 0; //数据净荷部分长度字段指示的数值 const uint8_t PreLength = 16; //帧前缀长度,指从帧前导码到OID序列(或者Tag序列)的数据长度,包括帧前导码,而不包括OID序列(或者Tag序列) const uint8_t CoreLength = 12; //关键信息长度,指数据净荷部分长度字段指示的数值,去除Tag序列后剩余数据的长度 uint16_t Send_Flag = 0; uint8_t TEA_Data[MAX_SEND_DATA]; //加密以后数据长度为8的倍数,加密前长度除以8向上取整后乘以8 uint16_t TEA_Data_Len; uint8_t count = 0; printf("\r\n**********TrapRequest**********\r\n"); pChar = (char*)pDataFrame; memset(pChar, 0x00, sizeof(struct SpecialDataFrame)); //初始化结构体 TrapSend.Preamble = 0xA3; TrapSend.Version = 0x20; for(g = 0; g < 6; g++) { TrapSend.DeviceID[g] = DeviceID[g]; } TrapSend.RouteFlag = RouteControl; //通讯方式 TrapSend.NodeAddr = ntohs(NodeAddr); //调整为网络序,即高字节在前,低字节在后 switch (Optype) { case 2 : TrapSend.PDU_Type = (2 << 8) + (1 << 7) + 0x1C; //GetResponse break; default: TrapSend.PDU_Type = (4 << 8) + (1 << 7) + 0x1C; //默认为TrapRequest printf("\r\nOptype:%d\r\n", Optype); //测试使用, 设备类型相关 break; } TrapSend.PDU_Type = ntohs(TrapSend.PDU_Type); //调整为网络序,即高字节在前,低字节在后 TrapSend.Seq = 0x01; LengthKey = CoreLength; if(ACR > 17000) ACR = 17000; DeviceConfig.BatteryCapacity = ACR/170; //电池电量 TrapSend.BattEnergy.OID_Command = ntohl(DEVICE_QTY); //调整为网络序,即高字节在前,低字节在后 TrapSend.BattEnergy.Width = 1; // TrapSend.BattEnergy.Value[0] = DeviceConfig.BatteryCapacity; //数据上传时的电池剩余电量 LengthKey = LengthKey + 6 + TrapSend.BattEnergy.Width; TrapSend.SysTime.OID_Command = ntohl(SYSTERM_DATA); //调整为网络序,即高字节在前,低字节在后 TrapSend.SysTime.Width = 3; // TrapSend.SysTime.Value[0] = businessData.StartTime[0]; //消息内容日期,非当前日期,年 TrapSend.SysTime.Value[1] = businessData.StartTime[1]; //消息内容日期,非当前日期,月 TrapSend.SysTime.Value[2] = businessData.StartTime[2]; //消息内容日期,非当前日期,日 LengthKey = LengthKey + 6 + TrapSend.SysTime.Width; while (1) { if (count > 10) { break; } vTaskDelay(500 / portTICK_PERIOD_MS); count++; } // vTaskDelay(500); printf("\r\n--------Module_ME3616_menginfo_Check-----------\r\n"); Module_ME3616_menginfo_Check(); TrapSend.TagList[0].OID_Command= ntohl(NB_PCI); //调整为网络序,即高字节在前,低字节在后 TrapSend.TagList[0].Width =2; TrapSend.TagList[0].Value[0] = signalValue[0]; //数据上传时的NB主小区物理小区PCI号高字节 TrapSend.TagList[0].Value[1] = signalValue[1]; //数据上传时的NB主小区物理小区PCI号低字节 TrapSend.Tag_Count++; LengthKey = LengthKey + 6 + TrapSend.TagList[0].Width; TrapSend.TagList[1].OID_Command= ntohl(NB_RSRP); //调整为网络序,即高字节在前,低字节在后 TrapSend.TagList[1].Width =2; TrapSend.TagList[1].Value[0] = signalValue[2]; //数据上传时的NB主小区RSRP值高字节 TrapSend.TagList[1].Value[1] = signalValue[3]; //数据上传时的NB主小区RSRP值低字节 TrapSend.Tag_Count++; LengthKey = LengthKey + 6 + TrapSend.TagList[1].Width; TrapSend.TagList[2].OID_Command= ntohl(NB_SNR); //调整为网络序,即高字节在前,低字节在后 TrapSend.TagList[2].Width =2; TrapSend.TagList[2].Value[0] = signalValue[4]; //数据上传时的NB主小区lart SNR值高字节 TrapSend.TagList[2].Value[1] = signalValue[5]; //数据上传时的NB主小区lart SNR值低字节 TrapSend.Tag_Count++; LengthKey = LengthKey + 6 + TrapSend.TagList[2].Width; TrapSend.TagList[3].OID_Command= ntohl(SENSOR_STATE); //调整为网络序,即高字节在前,低字节在后 TrapSend.TagList[3].Width =1; if(GASData > 245) { TrapSend.TagList[3].Value[0] = 1; //燃气传感器采集失败 }else if(GASData > 235) { TrapSend.TagList[3].Value[0] = 2; //燃气传感器数据异常 }else { TrapSend.TagList[3].Value[0] = 0; //燃气传感器工作正常 } TrapSend.Tag_Count++; LengthKey = LengthKey + 6 + TrapSend.TagList[2].Width; for(i = 4, TrapSend.Tag_Count = 4, TrapSend.Length = LengthKey ; i < businessData.DataCount+4; i++) //对每一个数据Tag赋值 { if(i == 4) //第一组数据TAG填入OID和LENGTH { TrapSend.TagList[i].OID_Command = (DeviceConfig.CollectPeriod << 11) + (businessData.StartTime[3] * 60 + businessData.StartTime[4]) + (0xC5 << 24); printf("\r\n----TrapSend.TagList[i].OID_Data1:%lx----\r\n", TrapSend.TagList[i].OID_Command); //测试使用 TrapSend.TagList[i].OID_Command = ntohl(TrapSend.TagList[i].OID_Command); //调整为网络序,即高字节在前,低字节在? printf("\r\n----TrapSend.TagList[i].OID_Command:%lx----\r\n", TrapSend.TagList[i].OID_Command); //测试使用? TrapSend.TagList[i].Width = 4 * businessData.DataCount; TrapSend.Length = TrapSend.Length + 10; } else { TrapSend.Length = TrapSend.Length + 4; } TrapSend.TagList[i].LevelData.Value[0] = businessData.CollectData[i-4][0]; //采集到的数据 TrapSend.TagList[i].LevelData.Value[1] = businessData.CollectData[i-4][1]; //采集到的数据 TrapSend.TagList[i].LevelData.Value[2] = businessData.CollectData[i-4][2]; //采集到的数据 TrapSend.TagList[i].LevelData.Value[3] = businessData.CollectData[i-4][3]; //采集到的数据 TrapSend.Tag_Count++ ; //对数据Tag进行计数,不包括采集日期Tag } ///////////////////////////////////////////////////////////////////////////////////////////// TrapSend.Length = ntohs(TrapSend.Length); //计算长度字段 memcpy(pSendBuff, &TrapSend.Preamble, 1); memcpy(pSendBuff+1, &TrapSend.Version, 1); memcpy(pSendBuff+2, &TrapSend.Length, 2); memcpy(pSendBuff+4, &TrapSend.DeviceID, 6); memcpy(pSendBuff+10, &TrapSend.RouteFlag, 1); memcpy(pSendBuff+11, &TrapSend.NodeAddr, 2); memcpy(pSendBuff+13, &TrapSend.PDU_Type, 2); memcpy(pSendBuff+15, &TrapSend.Seq, 1); // memcpy(pSendBuff, pChar, PreLength); //复制Tag之前的数据到发送Buff Offset = PreLength; //指针偏移地址 pChar = (char*) & (TrapSend.BattEnergy.OID_Command); //电池电量Tag ValidLength = TrapSend.BattEnergy.Width + 6; //计算1个Tag实际占用的字节空间 TrapSend.BattEnergy.Width = ntohs(TrapSend.BattEnergy.Width); //调整为网络序,即高字节在前,低字节在后 memcpy((pSendBuff + Offset), pChar, ValidLength); //复制电池电量Tag数据到发送Buff Offset = Offset + ValidLength; pChar = (char*) & (TrapSend.SysTime.OID_Command); //系统日期Tag ValidLength = TrapSend.SysTime.Width + 6; //计算1个Tag实际占用的字节空间 TrapSend.SysTime.Width = ntohs(TrapSend.SysTime.Width); //调整为网络序,即高字节在前,低字节在后 memcpy((pSendBuff + Offset), pChar, ValidLength); //复制系统时间Tag数据到发送Buff Offset = Offset + ValidLength; for(i = 0; i < 4; i++) { pChar = (char*) & (TrapSend.TagList[i].OID_Command); //信号强度Tag ValidLength = TrapSend.TagList[i].Width + 6; //计算1个Tag实际占用的字节空间 TrapSend.TagList[i].Width = ntohs(TrapSend.TagList[i].Width); //调整为网络序,即高字节在前,低字节在后 memcpy((pSendBuff + Offset), pChar, ValidLength); //复制信号强度Tag数据到发送Buff Offset = Offset + ValidLength; } for(i = 4; i < TrapSend.Tag_Count; i++) // { if(i == 4) //第一组数据TAG填入OID和LENGTH { pChar = (char*) & (TrapSend.TagList[4].OID_Command); ValidLength = 6; //计算1个Tag实际占用的字节空间 TrapSend.TagList[4].Width = ntohs(TrapSend.TagList[4].Width); //调整为网络序,即高字节在前,低字节在后 memcpy((pSendBuff + Offset), pChar, ValidLength); //复制每一个数据Tag到发送Buff Offset = Offset + ValidLength; } pChar = (char*) & (TrapSend.TagList[i].LevelData); ValidLength = 4; //计算1个Tag实际占用的字节空间 memcpy((pSendBuff + Offset), pChar, ValidLength); //复制每一个数据Tag到发送Buff Offset = Offset + ValidLength; } for(g = 0; g < Offset; g++) { printf("%.2x ", pSendBuff[g]); //测试使用 } //payload 加密 memcpy(TEA_Data, (char*)(pSendBuff + PreLength), (Offset - PreLength)); TEA_Data_Len = Tea_Encrypt(TEA_Data, (Offset - PreLength)); memcpy((pSendBuff + PreLength), TEA_Data, TEA_Data_Len); //复制加密之后的payload数据到发送Buff Offset = PreLength + TEA_Data_Len; CrcData = CRC16(pSendBuff, Offset); // Update the CRC value TrapSend.CrcCode = CrcData; pSendBuff[Offset++] = CrcData >> 8; //CRC高字节在前 pSendBuff[Offset++] = CrcData & 0xff; //CRC低字节在后 /////////////////////////////////////////////////////////////////////////////////////////////////////////// printf("\r\n*********NB Start!***********\r\n"); if(SIMCard_Type == 1) //电信NB,发送到IOT平台 { Send_Flag =SendMessage_NB_T(pSendBuff, Offset); } else if(SIMCard_Type == 0) //移动、联通NB,直接发送到后台服务器 { Send_Flag =SendMessage_NB_MU(pSendBuff, Offset); } else { printf("\r\n ===========SIM卡异常,无法发数!===========!!\r\n"); } if(Send_Flag == 0x039C) { printf("\r\nReceive SetRequest success!\r\n"); //测试使用 if(Flash_Write_Flag[0] == 1) { Module_Flash_Write(RetryNum_ADDR - FLASH_TEST_BASE, &(DeviceConfig.RetryNum), 1); } if(Flash_Write_Flag[1] == 1) { Module_Flash_Write( CollectTime_ADDR - FLASH_TEST_BASE, (uint8_t*) & (DeviceConfig.CollectTime), 2); } if(Flash_Write_Flag[2] == 1) { Module_Flash_Write(CollectPeriod_ADDR - FLASH_TEST_BASE, (uint8_t*) & (DeviceConfig.CollectPeriod), 2); } if(Flash_Write_Flag[3] == 1) { Module_Flash_Write(CollectNum_ADDR - FLASH_TEST_BASE, (uint8_t*) & (DeviceConfig.CollectNum), 2); } if(Flash_Write_Flag[4] == 1) { Module_Flash_Write(UploadCycle_ADDR - FLASH_TEST_BASE, (uint8_t*) & (DeviceConfig.UploadCycle), 2); } if(Flash_Write_Flag[5] == 1) { Module_Flash_Write(MountHeight_ADDR - FLASH_TEST_BASE, DeviceConfig.MountHeight.Data_Hex, 4); } if(Flash_Write_Flag[6] == 1) { Module_Flash_Write(AlarmValue_ADDR - FLASH_TEST_BASE, DeviceConfig.AlarmValue.Data_Hex, 4); } if(Flash_Write_Flag[7] == 1) { Module_Flash_Write(ServerIP_ADDR - FLASH_TEST_BASE, (uint8_t*) & (DeviceConfig.ServerIP), sizeof(DeviceConfig.ServerIP)); } if(Flash_Write_Flag[8] == 1) { Module_Flash_Write(ServerPort_ADDR - FLASH_TEST_BASE, (uint8_t*) & (DeviceConfig.ServerPort), 2); } businessData.DataCount = 0; Module_Flash_Write(CollectedDateCount_ADDR - FLASH_TEST_BASE, &(businessData.DataCount), 1); if(dataFrame.Tag_Count > 1) { businessData.ParameterReply = 1; Module_Flash_Write(ParameterReply_ADDR - FLASH_TEST_BASE, &(businessData.ParameterReply), 1); } } else { Module_Flash_Write(HistoryDateCount_ADDR - FLASH_TEST_BASE, &Offset, 1); Module_Flash_Write(HistoryDate_ADDR - FLASH_TEST_BASE, pSendBuff, Offset); businessData.SendCount = 1; Module_Flash_Write(SendCount_ADDR - FLASH_TEST_BASE, &(businessData.SendCount), 1); } printf("\r\n----Length:%d----\r\n", Offset); //测试使用 for(g = 0; g < Offset; g++) { printf("%.2x ", pSendBuff[g]); //测试使用 } return Send_Flag; }