123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682 |
- #include "parseDeviceMessage.h"
- #include "cJson.h"
- #include "systick.h"
- #include "usart.h"
- #include "string.h"
- #include <math.h>
- #include "mqttRecv.h"
- #include "log.h"
- #include "ec800m.h"
- #include "main.h"
- #define MQTT_SUB_CMD_WRITE 0
- #define MQTT_SUB_CMD_READ 1
- ring_buffer mqttRecv;
- uint8_t protocol;
- void processHTTPjson(cJSON *json);
- char *processStringData(cJSON *data_obj, const char *key);
- int processIntData(cJSON *data_obj, const char *key);
- static void extract_data_from_buffer(const char *buffer, uint32_t *len_ptr, uint16_t *checkCode_ptr);
- //static void extract_data_from_buffer232(const char *buffer, uint32_t *len_ptr, uint16_t *checkCode_ptr);
- static uint16_t checksum(const char *str, uint16_t len);
- // json解析字符串
- char *processStringData(cJSON *data_obj, const char *key)
- {
- cJSON *json_data = cJSON_GetObjectItemCaseSensitive(data_obj, key);
- if (cJSON_IsString(json_data) && (json_data->valuestring != NULL))
- {
- return json_data->valuestring;
- }
- else
- {
- return NULL;
- }
- }
- // json解析int
- int processIntData(cJSON *data_obj, const char *key)
- {
- cJSON *json_data = cJSON_GetObjectItemCaseSensitive(data_obj, key);
- // if (cJSON_IsNumber(json_data) && (json_data->valueint != NULL)) 解决寄存器地址为0问题
- if (cJSON_IsNumber(json_data))
- {
- return json_data->valueint;
- }
- else
- {
- // gateway.data_valid_flag = 0; // 如果任意数据为NULL则此次数据为无效
- return -1;
- }
- }
- /*
- * 函数名:void WaitForUpData(void)
- * 输入参数:无
- * 输出参数:无
- * 返回值:无
- * 函数作用:等待更新本地flash信息
- */
- bool WaitForUpData(char *dmaBuffer)
- {
- if (UART0_RX_STAT > 0)
- {
- UART0_RX_STAT = 0;
- uint32_t len;
- uint16_t checkCode;
- char *temp;
- extract_data_from_buffer(dmaBuffer, &len, &checkCode);
- uint16_t jsonCheck = checksum(dmaBuffer, len);
- if (checkCode == jsonCheck)
- {
- addGatewayParams(dmaBuffer);
- return true;
- }
- else
- {
- return false;
- }
- }
- }
- /*
- * 函数名:static void extract_data_from_buffer(const char* buffer, uint32_t *len_ptr, uint16_t *checkCode_ptr)
- * 输入参数:buffer字符串
- * 输出参数:json有效字符串长度len_ptr,checkCode_ptr校验码指针
- * 返回值:无
- * 函数作用:eg. QFDWL: 621,3e23 从json信息最后端取出这段json的有效长度和校验码
- */
- static void extract_data_from_buffer(const char *buffer, uint32_t *len_ptr, uint16_t *checkCode_ptr)
- {
- char *start = strstr(buffer, "+QFDWL:");
- if (start != NULL)
- {
- start += 8; // 跳过"+QFDWL:"
- uint32_t len = 0;
- sscanf(start, "%u,", &len); // 读取长度
- start = strchr(start, ',') + 1; // 跳过逗号
- uint16_t checkCode = 0;
- sscanf(start, "%hx", &checkCode); // 读取16进制数据
- // 将提取的数据存入形参
- *len_ptr = len;
- *checkCode_ptr = checkCode;
- }
- }
- /*
- * 函数名:void dlt645_read(CONFIG_PARAMS *gateway)
- * 输入参数:设备地址*address 数据标识 readCode
- * 输出参数:无
- * 返回值:无
- * 函数作用:读取645协议内部数据
- 备注:dlt645协议为网上下载,返回值为数据长度
- 现在要加读日期信息YYMMDDhhmm
- 对源代码改动不多的方法是通过返回的数据长度去做判断
- 当数据长度为2、3、4时此时 read_buf数据包内仅含采集到的浮点数数据、 把float值4个字节直接拷贝出即可
- 当数据长度为5时 read_buf数据包为日期数据 其中5个字节分别为YYMMDDhhmm直接拷贝出来
- 当数据长度大于5时 read_buf内既包含浮点数又包含日期时间 其中前4个字节为浮点数数据后五个字节为日期信息
- */
- #if 0
- void dlt645_read(CONFIG_PARAMS *gateway)
- {
- uint8_t read_buf[10];
- for (int i = 0; i < gateway->device_read_data_num; i++)
- {
- gateway->device_read_data[i].rxLen = 0;
-
- memset(read_buf, 0, 10);
- memset(gateway->device_read_data[i].data, 0, 10);
- dlt645_set_addr(&dlt645, gateway->device_read_data[i].deviceID645);
- int8_t rs;
- if(gateway->dataType645==DLT645_2007){
- rs = dlt645_read_data(&dlt645, gateway->device_read_data[i].dataType645, read_buf, DLT645_2007);
- }
- else {
- rs = dlt645_read_data(&dlt645, gateway->device_read_data[i].dataType645, read_buf, DLT645_1997);
- }
- if (rs != -1)
- {
- if (rs <= 4)
- {
- memcpy(gateway->device_read_data[i].data, read_buf, 4);
- gateway->device_read_data[i].rxLen = rs;
- }
- else if (rs == 5)
- {
- memcpy(gateway->device_read_data[i].data, read_buf, 5);
- gateway->device_read_data[i].rxLen = rs;
- }
- else if (rs > 5)
- {
- memcpy(gateway->device_read_data[i].data, read_buf, 9);
- gateway->device_read_data[i].rxLen = rs;
- }
- }
- else
- {
- gateway->device_read_data[i].rxLen = 0;
- }
- task_fwdgt_reload();
- }
-
- }
- #endif
- /*
- * 函数名: void Read_Data(GATEWAY_PARAMS *gateway)
- * 输入参数:gateway网关存储的配置参数
- * 输出参数:网关结构体指针
- * 返回值:无
- * 函数作用:根据存储的设备信息发送modbus信息返回值存储到gateway->device_read_data[i].data中
- * modbusRead读数据只考虑读16位寄存器和32位寄存器这两种情况,但对其返回值进行处理后返回值一律为float型4个字节存储在内部
- dlt645根据其返回长度判断其具体是否挈带了日期数据
- */
- void Read_Data()
- {
- GATEWAY_PARAMS *gateway;
- gateway=get_gateway_config_params();
- DEVICE_PARAMS *currentDevice=gateway->device_params;
- READ_MODBUS_COMMAND *read_modbus_command=NULL;
- READ_DLT645_COMMAND *read_dlt645_command=NULL;
- switch(currentDevice->protocol)
- {
- case DLT645_07:
- case DLT645_97:
- protocol=1;
- read_dlt645_command=currentDevice->params->node_read_dlt645_command;
- break;
- case MODBUS:
- protocol=2;
- read_modbus_command=currentDevice->params->node_read_modbus_command;
- mmodbus_set16bitOrder(currentDevice->MDBbigLittleFormat); //设置大小端
- break;
- }
-
- while(1)//进入轮询
- {
- __START__WHILE:
- delay_1ms(10);
- switch(currentDevice->protocol)
- {
- case DLT645_07:
- case DLT645_97:
- {
- uint8_t read_buf[10];
- memset(read_buf, 0, 10);
- dlt645_set_addr(&dlt645,read_dlt645_command->deviceID645);
- int8_t rs;
- if(currentDevice->protocol==DLT645_97)
- {
- rs = dlt645_read_data(&dlt645, read_dlt645_command->Identification, read_buf, DLT645_1997);
- }
- else if(currentDevice->protocol==DLT645_07)
- {
- rs = dlt645_read_data(&dlt645, read_dlt645_command->Identification, read_buf, DLT645_2007);
- }
- if (rs != -1)
- {
- if (rs <= 4)
- {
- memcpy(read_dlt645_command->data, read_buf, 4);
- read_dlt645_command->rxLen = 4;
- }
- else if (rs == 5)
- {
- memcpy(read_dlt645_command->data, read_buf, 5);
- read_dlt645_command->rxLen = 5;
- }
- else if (rs > 5)
- {
- memcpy(read_dlt645_command->data, read_buf, 9);
- read_dlt645_command->rxLen = 9;
- }
- }
- else
- {
- read_dlt645_command->rxLen = 0;
- }
-
- }
- break;
- case MODBUS:
- {
-
- uint16_t data[read_modbus_command->registerByteNum/2];
- switch(read_modbus_command->functionCode)
- {
- case 0x03://读寄存器
- {
- bool success=mmodbus_readHoldingRegisters16i(read_modbus_command->slaveAddress,
- read_modbus_command->registerAddress,
- read_modbus_command->registerByteNum/2,
- data);
- if(success)
- {
- uint32_t value;
- if(read_modbus_command->registerByteNum==4)
- {
- value = (uint32_t)data[0] << 16 | data[1];
- read_modbus_command->rxLen=4;
- }
- else if(read_modbus_command->registerByteNum==2)
- {
- value = data[0];
- read_modbus_command->rxLen=4;
- }
- if(read_modbus_command->decimalPoint!=0)
- {
- float convertedValue =(float)value/pow(10,read_modbus_command->decimalPoint);
- memcpy(read_modbus_command->value,&convertedValue,4);
- }
- else
- {
- memcpy(read_modbus_command->value,&value,4);
- }
- }
- else
- {
- read_modbus_command->rxLen=0;
- }
- }
- break;
- case 0x01://读线圈
- {
- uint8_t data[2];
- bool success = mmodbus_readCoils(read_modbus_command->slaveAddress,
- read_modbus_command->registerAddress,
- read_modbus_command->registerByteNum/2,
- data);
- if(success)
- {
- read_modbus_command->rxLen=4;
- uint32_t value = (uint32_t)data[0] << 8 | data[1];
- memcpy(read_modbus_command->value,&value,4);
- }
- else
- {
- read_modbus_command->rxLen=0;
- }
-
- }
- break;
- default:
- break;
- }
- }
- break;
- }
- switch(currentDevice->protocol)
- {
- case DLT645_07:
- case DLT645_97:
- read_dlt645_command=read_dlt645_command->nextParams;
- break;
- case MODBUS:
- read_modbus_command=read_modbus_command->nextParams;
- break;
- }
- if((read_dlt645_command==NULL&&protocol==1)||(read_modbus_command==NULL&&protocol==2))
- {
- currentDevice=currentDevice->nextDevice;
- switch(currentDevice->protocol)
- {
- case DLT645_97:
- case DLT645_07:
- protocol=1;
- break;
- case MODBUS:
- protocol=2;
- break;
- }
- if(currentDevice==NULL)
- {
- return;//一直到没有设备时跳出循环
- }
- else
- {
- read_dlt645_command=currentDevice->params->node_read_dlt645_command;
- read_modbus_command=currentDevice->params->node_read_modbus_command;
- }
- }
- task_fwdgt_reload();//喂狗
- goto __START__WHILE;
- }
- }
- /*
- * 函数名:void parseMQTTData(CONFIG_PARAMS *gateway)
- * 输入参数:device存储的各类产品信息
- * 输出参数:无
- * 返回值:无
- * 函数作用:从环形缓冲区中一个个把json信息读出,与存储的gateway内的子设备信息匹配后将对应指令匹配执行并返回相应的值
- * 查询逻辑现在有两套数组read数组和write数组,当接收中断产生时先判断是进行读还是写、之后在查询此网关支持的协议MODBUS还是
- * 645,后根据协议去不同数组查询不同的本地存储信息、组装发送给子设备,然后根据查询的值进行采集上传数据
- */
- void parseMQTTData(GATEWAY_PARAMS *gateway)
- {
- while (UART0_RX_MQTT_SUB_STAT == 1)
- {
- UART0_RX_MQTT_SUB_STAT = 0;
- char payload_out[200];
- memset(payload_out,0,200);
- char mqtt_publish[200];
- char json[128];
- while (MQTT_BUFFER_READ(json))
- {
- LogPrint(LOG_INFO, __func__, __LINE__, "Received JSON: %s", json);
- cJSON *mqtt_sub_json = cJSON_Parse(json);
- if (mqtt_sub_json != NULL)
- {
- uint8_t action1[1];
- uint8_t action;
- strcpy(action1, processStringData(mqtt_sub_json, "action"));
- // 解决字符串为
- if (action1[0] == '0')
- {
- action = 0;
- }
- else if (action1[0] == '1')
- {
- action = 1;
- }
- char identifier[20];
- strcpy(identifier, processStringData(mqtt_sub_json, "identifier"));
- char deviceId[20];
- strcpy(deviceId, processStringData(mqtt_sub_json, "deviceId"));
- uint16_t value = processIntData(mqtt_sub_json, "parameter");
- char messageId[10];
- strcpy(messageId, processStringData(mqtt_sub_json, "messageId"));
-
-
- DEVICE_PARAMS *currentDevice=gateway->device_params;
- WRITE_MODBUS_COMMAND *write_modbus_command=NULL;
- READ_MODBUS_COMMAND *read_modbus_command=NULL;
- READ_DLT645_COMMAND *read_dlt645_command=NULL;
- // 判断其指令过来是读还是写
- if (action == MQTT_SUB_CMD_WRITE)//写指令目前只支持modbus
- {
- while(1)
- {
- if(strcmp((char *)¤tDevice->deviceID,deviceId)!=0)
- {
- currentDevice=currentDevice->nextDevice;
- if(currentDevice==NULL)
- {
- break; //如果找不到所属设备则跳出
- }
- }
- else
- {
- protocol=2;//决定当前使用modbus回调函数还是dlt645
- if(write_modbus_command==NULL)
- {
- write_modbus_command=currentDevice->params->node_write_modbus_command;
- }
- if(strcmp((char*)&write_modbus_command->keyword,identifier)!=0)//寻找设备层内所属属性名称
- {
- write_modbus_command=write_modbus_command->nextParams;
- if(write_modbus_command==NULL)
- {
- break;
- }
- }
- else //找到所属于的属性了
- {
- mmodbus_set16bitOrder(currentDevice->MDBbigLittleFormat);
- if(write_modbus_command->functionCode==0x05)
- {
- bool success = mmodbus_writeCoil(write_modbus_command->slaveAddress,
- write_modbus_command->registerAddress,
- (uint8_t)value);
- // 成功
- if (success)
- {
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d}",
- action1,
- write_modbus_command->keyword,
- currentDevice->deviceID, messageId, success);
- break;
- }
- else
- {
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d}",
- action1,
- write_modbus_command->keyword,
- currentDevice->deviceID, messageId, success);
- break;
- }
- }
- else if(write_modbus_command->functionCode==0x06)
- {
- bool success = mmodbus_writeHoldingRegister16i(write_modbus_command->slaveAddress,
- write_modbus_command->registerAddress,
- (uint16_t)value);
- if (success)
- {
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d}",
- action1,
- write_modbus_command->keyword,
- currentDevice->deviceID, messageId, success);
- break;
- }
- else
- {
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d}",
- action1,
- write_modbus_command->keyword,
- currentDevice->deviceID, messageId, success);
- break;
- }
- }
- }
- }
- }
- }
- // 指令是来读某属性值的
- else if (action == MQTT_SUB_CMD_READ)
- {
- while(1)
- {
- if(strcmp((char *)¤tDevice->deviceID,deviceId)!=0)
- {
- currentDevice=currentDevice->nextDevice;
- if(currentDevice==NULL)
- {
- break; //如果找不到所属设备则跳出
- }
- }
- else //找到了设备
- {
- if(currentDevice->protocol==MODBUS)
- {
- protocol=2;//决定当前使用modbus=2回调函数还是dlt645=1
- if(read_modbus_command==NULL)read_modbus_command=currentDevice->params->node_read_modbus_command;
- if(strcmp((char *)&read_modbus_command->keyword,identifier)!=0)
- {
- read_modbus_command=read_modbus_command->nextParams;
- if(read_modbus_command==NULL)break;
- }
- else//找到了属性
- {
- mmodbus_set16bitOrder(currentDevice->MDBbigLittleFormat);
- if(read_modbus_command->functionCode==0x01)
- {
- uint8_t data[2];
- bool success = mmodbus_readCoils(read_modbus_command->slaveAddress,
- read_modbus_command->registerAddress,
- read_modbus_command->registerByteNum/2,
- data);
- uint8_t value1;
- if (success)
- {
- uint16_t value1 = (uint16_t)data[0] << 8 | data[1];
- if (value1 == 0xFF00)
- {
- value1 = 1;
- }
- else if (value1 == 0x0000)
- {
- value1 = 0;
- }
- // 读线圈成功的json
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d,\"parameter\":%d}",
- action1,
- read_modbus_command->keyword,
- currentDevice->deviceID, messageId, success, value);
- break;
- }
- // 读线圈失败的json
- else
- {
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d}",
- action1,
- read_modbus_command->keyword,
- currentDevice->deviceID, messageId, success);
- break;
- }
- }
- }
- }
- else//dlt645读取指令
- {
- protocol=1;//决定当前使用modbus=2回调函数还是dlt645=1
- float value;
- uint8_t minute, hour, day, month, year;
- uint8_t read_buf[10];
- memset(read_buf, 0, 10);
- if(read_dlt645_command==NULL)read_dlt645_command=currentDevice->params->node_read_dlt645_command;
- dlt645_set_addr(&dlt645, read_dlt645_command->deviceID645);
- int8_t rs ;
- if(currentDevice->protocol==DLT645_07)
- {
- rs = dlt645_read_data(&dlt645, read_dlt645_command->Identification, read_buf, DLT645_2007);
- }else if(currentDevice->protocol==DLT645_97)
- {
- rs = dlt645_read_data(&dlt645, read_dlt645_command->Identification, read_buf, DLT645_1997);
- }
- if (rs != -1)
- {
- if (rs <= 4)
- {
- memcpy(&value, read_buf, 4);
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d,\"value\":%.2f}",
- action1,
- read_dlt645_command->keyword,
- currentDevice->deviceID, messageId, 1, value);
- break;
- }
- else if (rs == 5)
- {
- year = read_buf[4];
- month = read_buf[3];
- day = read_buf[2];
- hour = read_buf[1];
- minute = read_buf[0];
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d,\"value\":\"%02X%02X%02X%02X%02X\"}",
- action1,
- read_dlt645_command->keyword,
- currentDevice->deviceID, messageId, 1, year, month, day, hour, minute);
- break;
- }
- else if (rs > 5)
- {
- memcpy(&value, read_buf, 4);
- year = read_buf[8];
- month = read_buf[7];
- day = read_buf[6];
- hour = read_buf[5];
- minute = read_buf[4];
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d,\"value\":\"%02X%02X%02X%02X%02X%.2f\"}",
- action1,
- read_dlt645_command->keyword,
- currentDevice->deviceID, messageId, 1, year, month, day, hour, minute, value);
- break;
- }
- }
- else
- {
- // dlt645读取失败的json组成
- sprintf((char *)payload_out,
- "{\"action\":\"%s\",\"identifier\":\"%s\",\"deviceId\":\"%s\",\"messageId\":\"%s\",\"state\":%d}",
- action1,
- read_dlt645_command->keyword,
- currentDevice->deviceID, messageId, 0);
- break;
- }
- }
- }
- }
- }
- // 上传对应的响应信息
- sprintf((char *)mqtt_publish, "AT+QMTPUBEX=0,0,0,0,\"%s\",%d\r\n", gateway->messageTopic, strlen(payload_out));
- EC800MSendCmd(mqtt_publish, strlen(mqtt_publish));
- WaitResponse("<", 1000);
- EC800MSendCmd(payload_out, strlen(payload_out));
- WaitResponse(RSP_OK, 1000);
- }
- cJSON_Delete(mqtt_sub_json);
- }
- }
- }
- // 模块下载download校验值
- static uint16_t checksum(const char *str, uint16_t len)
- {
- uint16_t sum = 0;
- uint8_t odd = 0;
- // 如果字符串长度为奇数,则将最后一个字符设置为高8位,低8位设置为0
- if (len % 2 == 1)
- {
- odd = 1;
- len--;
- }
- // 将每两个字符作为一个16位的数值进行异或操作
- for (uint16_t i = 0; i < len; i += 2)
- {
- sum ^= ((uint16_t)str[i] << 8) | (uint16_t)str[i + 1];
- }
- // 如果字符串长度为奇数,则还需要将最后一个字符与0xFF00异或
- if (odd)
- {
- sum ^= (uint16_t)str[len] << 8;
- }
- // 返回校验和
- return sum;
- }
- //比较本次数据和上次数据是否相同如果相同则不进行数据的更新
- int compareWithLastData(char *old_data,const char* new_data,uint8_t dataLen) {
- if (memcmp(new_data, old_data,dataLen) == 0) {
- return 0;
- } else {
- memcpy(old_data,&new_data,dataLen);;
- return 1;
- }
- }
|