#include "gd32f10x.h" #include "usart.h" #include "device_message.h" #include "PC.h" #include "parseDeviceMessage.h" #include "ec800m.h" #include "string.h" #include "mmodbus.h" #include "otaEvent.h" #define Top 0xEE //自定义协议帧起始符号 #define END 0xBB //自定义协议帧结束 #define READ_ID 0x01 // 读取设备id、固件版本号 #define READ_GATEWAY_MESSAGE 0x02 // 读取网关设备信息 #define READ_GATEWAY_JSON_CONFIG 0x03 // 读取JSON配置 #define WIRTE_GATEWAY_JSON_CONFIG 0x04 // 写入JSON配置 #define OTA_EVENT 0x05 // 进入程序更新 #define SET_GATEWAY_PLATFORM 0x06 // 设置物联网平台 bool WaitField(char *expectStr, int timeout); void readGatewayConfig(void); //读取设备系列DTU/LORA等等 void readGatewayMessage(void); //读取sim卡相关信息 void readSIMCARD(void); void read_json_config(); void write_json_config(char *json); void ec800m_4G_Data_read(uint8_t *str,uint16_t len); volatile int RxState; usart2_data_buf_t RxPacket; volatile uint32_t json_buf_num;//串口232配置数据长度 /* 此中断处理逻辑较为复杂 总共有两条线路 1、自定义协议的线路 对于自定义协议当其接收到了开始位之后、进入功能判断对其具体功能做出具体的响应、 其中又分为两种情况: (1)查询某一属性值、其长度并不会超过5、在接收完毕后即可进行状态归位操作 (2)写入操作、其在后续会跟一些不定长的数据包、无法判断其具体长度。所以要在空闲中断中进行状态 归位操作。 2、OTA升级的线路 对于OTA升级的操作、其上位机要先导要传一段自定义协议的数据将状态转化为升级状态、之后等待 从机回应进入等待升级状态、直到最后一个数据包结束标志抵达后才进行状态清零。或者超时之后进行了状态 归位操作。 */ void USART2_IRQHandler(void) { char *writeJSON=NULL; if (RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE)) // 接收寄存器不空 { uint8_t Serial_RxData; Serial_RxData = usart_data_receive(USART2); if (ota_data.ota_flag==0&&RxState==OTA_EVENT) { RxState=0;//ota更新中断后状态归位 } if (RxState == 0) // 等待包头 { if (Serial_RxData == Top) // 获取到包头则切换到识别功能模式 { RxState = 1; RxPacket.data_cnt = 0; RxPacket.data[RxPacket.data_cnt] = Serial_RxData; } } else if (RxState == 1) // 接收数据 { RxPacket.data_cnt++; RxPacket.data[RxPacket.data_cnt] = Serial_RxData; if (RxPacket.data_cnt >= 3) // 接收完数据 { RxState = 2; // 前导数据位已经接收完毕、转化状态接收尾部数据 } } else if (RxState == 2) // 等待包尾 { if (Serial_RxData == END) // 进入了结束位 { if (RxPacket.data[1] == WIRTE_GATEWAY_JSON_CONFIG) // 当为写入json数据后进入状态3、将对应数据放到usart0_buf中 { RxState = 3; writeJSON=malloc(40*1024); json_buf_num = 0; } else if (RxPacket.data[1] == OTA_EVENT) // 进入了OTA事件此时的状态会处于接收程序状态、一直等待OTA的结束标志位 { RxState = 4; ota_data.data_cnt=0; memset(ota_data.data,0,133);//清空数据 ota_data.ota_flag=1; } else // 其他情况则将状态归位 { RxState = 0; } } } else if (RxState == 3) // 接收到json信息进入进行处理 { writeJSON[json_buf_num++]=Serial_RxData; } else if (RxState == 4) //进入OTA升级路线 { ota_data.data[ota_data.data_cnt] = Serial_RxData; ota_data.data_cnt++; } // 清除中断标志 usart_interrupt_flag_clear(USART2, USART_INT_FLAG_RBNE); } if ((RxPacket.data_cnt > 0) && RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE)) { // 进入空闲中断后通过功能位进行判断其具体作用,并给予相应响应 if (RxPacket.data[0] == Top) { switch (RxPacket.data[1]) { case READ_ID: // readGatewayMessage(); break; case READ_GATEWAY_MESSAGE: // readSIMCARD(); break; case READ_GATEWAY_JSON_CONFIG: // read_json_config(); break; case WIRTE_GATEWAY_JSON_CONFIG: // write_json_config(writeJSON); break; case SET_GATEWAY_PLATFORM: break; default: break; } } // 此时不在ota升级的分支时,防止其他错误指令造成的数据状态不归位情况 if (ota_data.ota_flag == 0) { RxState = 0; } else if(ota_data.ota_flag==1) { ota_data.done=1; } usart_data_receive(USART2); } } /* * 函数名:void readGatewayMessage() * 输入参数:无 * 输出参数:无 * 返回值:无 * 函数作用:读取gateway内部配置信息 */ void readGatewayMessage(void) { GATEWAY_PARAMS *gateway; gateway = get_gateway_config_params(); uint8_t *gatewayMessageData=malloc(100); memset(gatewayMessageData,0,100); gatewayMessageData[0]=Top; gatewayMessageData[1]=READ_ID; uint8_t deviceIdLen=strlen((char *)&gateway->deviceId); uint8_t versionLen=strlen((char *)&gateway->version); memcpy(gatewayMessageData+2,gateway->deviceId,deviceIdLen); gatewayMessageData[deviceIdLen+2]=0x3B; memcpy(gatewayMessageData+2+1+deviceIdLen,gateway->version,versionLen); uint16_t CRC16=mmodbus_crc16(gatewayMessageData+1,strlen((char *)&gatewayMessageData)-1); gatewayMessageData[deviceIdLen+2+1+versionLen+1] = (uint8_t) (CRC16 & 0x00FF); gatewayMessageData[deviceIdLen+2+1+versionLen] = (uint8_t) ((CRC16 & 0xFF00)>>8); gatewayMessageData[deviceIdLen+2+1+versionLen+2]=END; gatewayMessageData[deviceIdLen+2+1+versionLen+2+1]='\0'; gd_com_232_send(gatewayMessageData,strlen((char* )&gatewayMessageData)); free(gatewayMessageData); } /* * 函数名:void readSIMCARD() * 输入参数:无 * 输出参数:无 * 返回值:无 * 函数作用:读出sim卡的相关配置 */ void readSIMCARD() { GATEWAY_PARAMS *gateway; gateway = get_gateway_config_params(); char *gatewayConfigData=malloc(1024); memset(gatewayConfigData,0,1024); uint8_t Operators[16]; int Networkstatu; uint8_t SIMCard=0; //状态0 正常 状态1异常 uint8_t ICCID[20]; uint8_t IMMIE[15]; uint8_t Networktyp; //0 GSM 2 UTRAN 3 GSM W/EGPRS 4 UTRAN W/HSDPA 5 UTRAN W/HSUPA 6 UTRAN W/HSDPA and HSUPA 7 E-UTRAN 8 UTRAN HSPA+ uint8_t Signal_strength; //信号强度 //查询运营商 EC800MSendCmd(CMD_SERVICE_Operatortyp, strlen(CMD_SERVICE_Operatortyp)); if(WaitField("+COPS: 0,0,",100)) //+COPS:0,0,"%s"为运营商,+COPS:0为无sim卡 { sscanf((char *)&UART0_RX_BUF, "AT+COPS?\r\r\n+COPS: 0,0,\"%[^\"]\",%s", Operators, &Networktyp); } else { strcpy((char *)&Operators,""); //未读取到sim卡信息 Networktyp=NULL; } Clear_DMA_Buffer(); //查询注册状态 EC800MSendCmd(CMD_SERVICE_Networktyp,strlen(CMD_SERVICE_Networktyp)); WaitField("OK",100); char* status_str=strstr((char *)&UART0_RX_BUF, "+CREG:"); if(status_str != NULL) //不为NULL则为有信号 { sscanf(status_str, "+CREG: %*d,%d", &Networkstatu); //原先0未注册 1注册,取反后1未注册0注册 } //查询sim卡iccid EC800MSendCmd(CMD_SERVICE_SIMcardICCID,strlen(CMD_SERVICE_SIMcardICCID)); WaitField("OK",100); char* ICCID_str=strstr((char *)&UART0_RX_BUF,"+QCCID:"); if(ICCID_str != NULL) { sscanf(ICCID_str,"+QCCID: %s",ICCID); //查询信号强度 EC800MSendCmd(CMD_SERVICE_Signalstrength,strlen(CMD_SERVICE_Signalstrength)); WaitField("OK",100); int rssi; sscanf((char *)&UART0_RX_BUF,"AT+CSQ\r\r\n+CSQ: %d",&rssi); Signal_strength=(int)(((float)rssi/31)*100); //算出来的百分比不准确log函数的斜率不断降低,此方法算出来的斜线的信号强度,实际信号为log函数,后续修正 Clear_DMA_Buffer(); } else //为没有sim卡状态 { memset(ICCID,0,20); //此时无ICCID Signal_strength=0; //无sim卡直接让其等于0 SIMCard=0; //然后sim状态抛异常 } Clear_DMA_Buffer(); //查询IMMIE号 EC800MSendCmd(CMD_SERVICE_IMEInumber,strlen(CMD_SERVICE_IMEInumber)); WaitField("OK",100); sscanf((char *)&UART0_RX_BUF,"AT+GSN\r\r\n%s",IMMIE); Clear_DMA_Buffer(); //查询结束,开始组装json gatewayConfigData[0]=Top; gatewayConfigData[1]=READ_GATEWAY_MESSAGE; sprintf(gatewayConfigData+2, "{\"UniqueId\":\"%s\",\"Equipmentname\":\"%s\",\"Equipmenttype\":\"%s\",\"Workmode\":\"%s\",\"baudrate\":%d,\"dataBit\":%d,\"stopBit\":%d,\"checkBit\":%d,\"Operatortype\":\"%s\",\"Networktype\":\"%c\",\"Networkstatus\":\"%d\",\"SIMcardstatus\":\"%d\",\"SIMcardICCID\":\"%s\",\"IMEInumber\":\"%s\",\"Signalstrength\":\"%d\"}", gateway->deviceId,"4G_DTU",gateway->gateName,gateway->gatewayMode,gateway->baudrate,gateway->dataBits,gateway->stopBit,gateway->checkBit, Operators,Networktyp,Networkstatu,SIMCard,ICCID,IMMIE,Signal_strength); uint16_t CRC16=mmodbus_crc16(gatewayConfigData+1,strlen(gatewayConfigData)-1); gatewayConfigData[strlen(gatewayConfigData)+1] = (uint8_t) (CRC16 & 0x00FF); gatewayConfigData[strlen(gatewayConfigData)] = (uint8_t) ((CRC16 & 0xFF00)>>8); gatewayConfigData[strlen(gatewayConfigData)]=END; gd_com_232_send(gatewayConfigData,strlen(gatewayConfigData)); free(gatewayConfigData); } #if 0 /* * 函数名:void readSIMCARD() * 输入参数:无 * 输出参数:无 * 返回值:无 * 函数作用:读取内部json配置 */ void read_json_config() { char *json_config=malloc(11*1024);//暂时最大空间只能解析10K数据 memset(json_config,0,11*1024); GATEWAY_PARAMS *gateway; gateway = get_gateway_config_params(); //帧头 json_config[0]=Top; json_config[1]=READ_GATEWAY_JSON_CONFIG; //数据包json最外层 sprintf(json_config+2,"{\"host\":\"%s\",\"port\":%d,\"messageTopic\":\"%s\",\"commandTopic\":\"%s\",\"baudrate\":%d,\"dataBit\":%d,\"stopBit\":%d,\"checkBit\":%d,\"flowControl\":%d,\"deviceId\":\"%s\",\"dataSource\":%d,\"version645\":%d,\"inboundTime\":%d,\"pollTime\":%d,", gateway->host, gateway->port, gateway->messageTopic, gateway->commandTopic, gateway->baudrate, gateway->dataBits, gateway->stopBit, gateway->checkBit, 0, gateway->deviceId, gateway->dataSource, gateway->dataType645, gateway->inboundTime, gateway->pollTime); //读指令头部 sprintf(json_config+strlen(json_config),"\"sensorData\":["); //读指令数据包 for (int i = 0; i < gateway->device_read_data_num; i++) { if (gateway->dataSource == MODBUS) { sprintf(json_config+strlen(json_config),"{\"rFunctionCode\":%d,\"registerAddress\":%d,\"slaveAddress\":%d,\"registerByteNum\":%d,\"identifier\":\"%s\",\"deviceId\":\"%s\",\"precise\":%d,\"bigLittleFormat\":%d},", gateway->device_read_data[i].mdbFunctionCode, gateway->device_read_data[i].mdbRegister, gateway->device_read_data[i].mdbSlave, gateway->device_read_data[i].registerLength, gateway->device_read_data[i].keyword, gateway->device_read_data[i].deviceId, gateway->device_read_data[i].decimalPoint, gateway->device_read_data[i].bigLittleFormat); } else if(gateway->dataSource == DLT645) { sprintf(json_config+strlen(json_config), "{\"identifier\":\"%s\",\"deviceID645\":\"%02x%02x%02x%02x%02x%02x\",\"identifier645\":%d,\"deviceId\":\"%s\"},", gateway->device_read_data[i].keyword, gateway->device_read_data[i].deviceID645[0], gateway->device_read_data[i].deviceID645[1], gateway->device_read_data[i].deviceID645[2], gateway->device_read_data[i].deviceID645[3], gateway->device_read_data[i].deviceID645[4], gateway->device_read_data[i].deviceID645[5], gateway->device_read_data[i].dataType645, gateway->device_read_data[i].deviceId); } } //特殊处理数据包括号最后一个逗号,清空 memset(json_config+strlen(json_config)-1,0,1); //读指令数据包尾部以及写指令数据包头部 sprintf(json_config+strlen(json_config),"],\"commandData\":["); //写数据包内容 写数据包目前只有MODBUS含有 for (int i = 0; i < gateway->device_write_data_num; i++) { sprintf(json_config+strlen(json_config),"{\"deviceId\":\"%s\",\"identifier\":\"%s\",\"registerAddress\":%d,\"slaveAddress\":%d,\"wFunctionCode\":%d,\"registerByteNum\":%d,\"bigLittleFormat\":%d},", gateway->device_write_data[i].deviceId, gateway->device_write_data[i].keyword, gateway->device_write_data[i].mdbRegister, gateway->device_write_data[i].mdbSlave, gateway->device_write_data[i].mdbFunctionCode, gateway->device_write_data[i].registerLength, gateway->device_write_data[i].bigLittleFormat); } //特殊处理数据包括号最后一个逗号,清空 memset(json_config+strlen(json_config)-1,0,1); //写数据包结尾以及json结尾 sprintf(json_config+strlen(json_config),"]}"); //CRC校验 uint16_t CRC16=mmodbus_crc16(json_config+1,strlen(json_config)-1); json_config[strlen(json_config)+1] = (uint8_t) (CRC16 & 0x00FF); json_config[strlen(json_config)] = (uint8_t) ((CRC16 & 0xFF00)>>8); //帧尾 json_config[strlen(json_config)]=END; gd_com_232_send(json_config,strlen(json_config)); free(json_config); } /* * 函数名:void write_json_config() * 输入参数:无 * 输出参数:无 * 返回值:无 * 函数作用:读取内部json配置 */ void write_json_config(char *json) { UART0_RX_STAT=0x01; //复用代码 bool success=WaitForUpData(json); int8_t resp[10]; memset(resp,0,10); resp[0]=Top; resp[1]=WIRTE_GATEWAY_JSON_CONFIG; resp[2]=success; uint16_t CRC16=mmodbus_crc16(resp+1,strlen(resp)-1); resp[strlen(resp)+1] = (uint8_t) (CRC16 & 0x00FF); resp[strlen(resp)] = (uint8_t) ((CRC16 & 0xFF00)>>8); resp[strlen(resp)]=END; gd_com_232_send(resp,strlen(resp)); //配置完成重启设备 NVIC_SystemReset(); } /* * 函数名:void ec800m_4G_Data_read(uint8_t *str,uint16_t len) * 输入参数:无 * 输出参数:str读到的首地址,len读到的数据总长 * 返回值:无 * 函数作用:读取gateway内部配置信息 */ void ec800m_4G_Data_read(uint8_t *str,uint16_t len) { EC800MSendCmd(CMD_SERVICE_Operatortyp, strlen(CMD_SERVICE_Operatortyp)); WaitField("+COPS:",100); } #endif /* * 函数名:bool WaitField(char *expectStr, int timeout) * 输入参数:expectStr 需要匹配的关键字 timeout超时时间 * 输出参数:true flase * 返回值:无 * 函数作用:从UART0_RX_BUF缓冲区中匹配有无对应关键字有关键字则返回true无返回false且不会清掉里面的数据 */ bool WaitField(char *expectStr, int timeout) { bool timeoutFlag = false; if (timeout >= 0) { timeoutFlag = true; } while (1) { delay_1ms(50); if (UART0_RX_STAT > 0) { UART0_RX_STAT = 0; char *p=strstr((char *)&UART0_RX_BUF, expectStr); if (p) { return true; } } timeout -= 50; if (timeoutFlag == true && timeout <= 0) { return false; } }; }