123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579 |
- #include "protocol.h"
- #include "stdint.h"
- #include "stdlib.h"
- #include "string.h"
- #include "node_message.h"
- #include "sys_mqtt.h"
- /*****************************protocol主要为主网关与子节点通讯的协议使用**********************************/
- /*****************************其主要作用主网关给子节点轮询发送数据的编码**********************************/
- /*****************************子节点解析该主网关发送的数据 **********************************/
- /*****************************子节点回应对应的响应 **********************************/
- /*****************************子节点回应对应的响应的解析 **********************************/
- static volatile int deviceNum = 0; // 记录轮询读取设备的结束位置
- static volatile int paramsNum = 0; // 记录轮询读取属性的结束位置
- static volatile int startDeviceNum = 0; // 记录轮询读取设备的开始位置
- static volatile int startParamsNum = 0; // 记录轮询读取设备属性的开始位置
- void insertHexData(uint8_t *String, const uint8_t *hexData, uint8_t insertIndex, uint8_t length);
- enum
- {
- protocol_dlt645_97 = 0x08,
- protocol_modbus_read,
- protocol_dlt645_07
- } PROTOCOL_LENGTH; // 每个协议的数据包长度用于最开始区分不同协议
- // 枚举采集数据的存储个数
- enum
- {
- typeInt = 1,
- typeFloat,
- typeDouble
- } DATAType;
- // 枚举MODBUS协议具体功能
- enum
- {
- READ_COIL = 0x01,
- WRITE_COIL = 0x05,
- WRITE_COILS = 0x0F,
- READ_REGISTER = 0x03,
- WRITE_REFISTER = 0x06,
- WRITE_REGISTERS = 0x10
- } MODBUS_COMMAND;
- // 大小端
- typedef enum
- {
- MModBus_16bitOrder_AB = 1, // 大端
- MModBus_16bitOrder_BA,
- } MModBus_16bitOrder_t;
- /*
- *********************************************************************************************************
- * 函 数 名: void masterSendNodeString(uint8_t nodeIndex)Index下标从0开始
- * 功能说明: 负责取出网关第nodeIndex下的数据组成下发格式的数据,注:此处没有对node是否为NULL进行判断,请确保有该节点的信息
- * 形 参:nodeIndex第几个节点数据、string所总成的传递的字符串、size组成的字符串大小
- * 返 回 值: 0:该节点下已经没有属性需要在去读出了,1:该节点下还拥有其他属性等待读出。
- 注:其一次性只能传输20条属性的值若超出其范围还有数据则要多次组成发送
- 逻辑:每次调用该函数都会总成一条string,属性足够的时候会组成一条具有20个属性的指令,并记录结束的设备链表位置,属性链表位置,下次再调用从结束位置再开始,到最后可能就组成不了20个属性的string了,此时将开始的设备num,属性都归位
- 且也要记录每次开始的设备位置和属性位置,方便接收应答信号的解析
- *********************************************************************************************************
- */
- int masterSendNodeString(uint8_t nodeIndex, uint8_t *string, uint16_t *size)
- {
- startDeviceNum = deviceNum; // 起始位置等于上次结束的位置
- startParamsNum = paramsNum; // 起始位置等于上次结束的位置
- int nowDeviceNum = deviceNum;
- int nowparamsNum = paramsNum;
- GATEWAY_PARAMS *gateway;
- gateway = get_gateway_config_params();
- // 将当前的节点指针指到需要读取的节点位置
- NODE_PARAMS *currentNode = gateway->node_params;
- while (nodeIndex)
- {
- currentNode = currentNode->nextNode;
- nodeIndex--;
- }
- memset(string, 0, 256); // 清除上一次数据
- // 将首字符用nodeAdress
- string[0] = currentNode->node_address[0];
- string[1] = currentNode->node_address[1];
- // 找到当前的设备结束位置
- DEVICE_PARAMS *currentDevice = currentNode->device_params;
- while (nowDeviceNum)
- {
- currentDevice = currentDevice->nextDevice;
- nowDeviceNum--;
- }
- // 移动位置到结束位置属性的下一位
- NODE_READ_MODBUS_COMMAND *currentModbusParams = currentDevice->params->node_read_modbus_command;
- NODE_READ_DLT645_COMMAND *currentDlt645Params = currentDevice->params->node_read_dlt645_command;
- switch (currentDevice->protocol)
- {
- case MODBUS:
- while (nowparamsNum)
- {
- currentModbusParams = currentModbusParams->nextParams;
- nowparamsNum--;
- }
- break;
- case DLT645_07:
- case DLT645_97:
- while (nowparamsNum)
- {
- currentDlt645Params = currentDlt645Params->nextParams;
- nowparamsNum--;
- }
- break;
- default:
- break;
- }
- // 最多进行20次循环组成下发数据
- int i = 0;
- int len;
- len = strlen(string);
- do
- {
- switch (currentDevice->protocol)
- {
- case MODBUS_READ:
- {
- uint8_t protocolHexData = protocol_modbus_read;
- insertHexData(string, &protocolHexData, len, 1); // 插入modbus长度
- len++;
- insertHexData(string, ¤tModbusParams->functionCode, len, 1); // 插入读取功能码
- len++;
- insertHexData(string, ¤tDevice->MDBdataType, len, 1); // 插入读取的数据格式
- len++;
- insertHexData(string, ¤tModbusParams->slaveAddress, len, 1); // 插入modbus从站地址
- len++;
- insertHexData(string, (uint8_t *)¤tModbusParams->registerAddress, len, 2); // 插入modbus寄存器地址
- len += 2;
- insertHexData(string, ¤tModbusParams->decimalPoint, len, 1); // 插入小数点位数
- len++;
- insertHexData(string, ¤tDevice->MDBbigLittleFormat, len, 1); // 插入大小端
- len++;
- // 属性读取完毕,移位到下一个属性
- i++;
- currentModbusParams = currentModbusParams->nextParams;
- if (currentModbusParams == NULL)
- {
- currentDevice = currentDevice->nextDevice;
- if (currentModbusParams == NULL)
- {
- deviceNum = 0; // 将结束位置全部归0
- paramsNum = 0;
- *size = len;
- return 1;
- }
- currentModbusParams = currentDevice->params->node_read_modbus_command;
- nowDeviceNum++;
- nowparamsNum = 0;
- }
- break;
- }
- case DLT645_07:
- {
- uint8_t protocolHexData = protocol_dlt645_07;
- insertHexData(string, &protocolHexData, len, 1); // 插入dlt645_07数据长度
- len++;
- insertHexData(string, (uint8_t *)¤tDlt645Params->deviceID645, len, 6); // 插入dlt645地址域
- len += 6;
- insertHexData(string, (uint8_t *)¤tDlt645Params->Identification, len, 4);
- len += 4;
- // 属性读取完毕,移位到下一个属性
- i++;
- currentDlt645Params = currentDlt645Params->nextParams;
- if (currentDlt645Params == NULL)
- {
- currentDevice = currentDevice->nextDevice;
- if (currentDevice == NULL)
- {
- deviceNum = 0; // 将结束位置全部归0
- paramsNum = 0;
- *size = len;
- return 1;
- }
- currentDlt645Params = currentDevice->params->node_read_dlt645_command;
- nowDeviceNum++;
- nowparamsNum = 0;
- }
- break;
- }
- case DLT645_97:
- {
- uint8_t protocolHexData = protocol_dlt645_97;
- insertHexData(string, &protocolHexData, len, 1); // 插入dlt645_97数据长度
- len++;
- insertHexData(string, (uint8_t *)¤tDlt645Params->deviceID645, len, 6); // 插入dlt645_97地址域
- len += 6;
- insertHexData(string, (uint8_t *)¤tDlt645Params->Identification, len, 2); // 插入dlt645_97数据标识
- len += 2;
- // 属性读取完毕,移位到下一个属性
- i++;
- currentDlt645Params = currentDlt645Params->nextParams;
- if (currentDlt645Params == NULL)
- {
- currentDevice = currentDevice->nextDevice;
- if (currentDlt645Params == NULL)
- {
- deviceNum = 0; // 将结束位置全部归0
- paramsNum = 0;
- *size = len;
- return 1;
- }
- currentDlt645Params = currentDevice->params->node_read_dlt645_command; // 还有属性则更新位置
- nowDeviceNum++;
- nowparamsNum = 0;
- }
- break;
- }
- default:
- goto end_while;
- }
- nowparamsNum++;
- } while (i != 20);
- end_while:
- // 更新结束的位置分为两种情况,一种还在当前设备的属性中轮询此时nowDeviceNum没有改变过,另外一种情况设备内的属性
- if (nowDeviceNum == 0)
- {
- deviceNum = startDeviceNum;
- paramsNum = startParamsNum + nowparamsNum;
- }
- else
- {
- deviceNum = startDeviceNum + nowDeviceNum;
- paramsNum = nowparamsNum - 1;
- }
- *size = len;
- return 0;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: void insertHexData(uint8_t *originalString,const uint8_t *hexData,int position)
- * 形 参:uint8_t *String需要插入的字符串,hexData插入的hex数据,insertIndex插入的下标位置,length插入的数据长度
- * 返 回 值: 无
- 注:插入的数据以被插入的字符串都可能包含0x00不要使用strlen
- *********************************************************************************************************
- */
- void insertHexData(uint8_t *String, const uint8_t *hexData, uint8_t insertIndex, uint8_t length)
- {
- memcpy(String + insertIndex, hexData, length);
- }
- /*
- *********************************************************************************************************
- * 函 数 名: uint8_t SlaveProtocolAnalysis(uint8_t *buff,uint16_t len)
- * 形 参:uint8_t *buff等待解析的字符串数据,
- * 返 回 值: 0:不是该节点的消息,数据没有进行任何处理。1:为该节点信息,接收到要进行的相应的切换工作
- 解析这段数据时要先判断是否为该节点的消息,stuct B *p=malloc(sizeof(struct B);
- *********************************************************************************************************
- */
- uint16_t LocalAddress=0x1F6E;
- uint8_t SlaveProtocolAnalysis(uint8_t *buff, uint16_t len)
- {
- NODE_DEVICE_PARAMS *node_receive_params;
- free_all_node_params();
- node_receive_params = get_node_receive_params();
- uint16_t slaveAdress = buff[0] << 8 | buff[1];
- int protocol_location = 2; // 起始的协议所处位置
- uint8_t i = 0;
- while (1)
- {
- if (slaveAdress == LocalAddress) // 判断此消息是否为该节点的消息,如果不是则跳出
- {
- switch (buff[protocol_location]) // 读取接收到的数据属于什么协议
- {
- case protocol_modbus_read:
- protocol_location++;
- node_receive_params->params[i].protcol = MODBUS_READ;
- node_receive_params->params[i].dlt645_params = NULL;
- node_receive_params->params[i].modbus_read = malloc(sizeof(NODE_MODBUS_READ));
- node_receive_params->params[i].modbus_write = NULL;
- node_receive_params->params[i].modbus_read->functionCode = buff[protocol_location + 1]; // 读出functionCode
- node_receive_params->params[i].modbus_read->dataType = buff[protocol_location + 2]; // 读出数据格式
- node_receive_params->params[i].modbus_read->slaveAddress = buff[protocol_location + 3]; // 读出从站地址
- node_receive_params->params[i].modbus_read->registerAddress = buff[protocol_location + 5] << 8 || buff[protocol_location + 4]; // 读出寄存器地址
- node_receive_params->params[i].modbus_read->registerLength = buff[protocol_location + 7] << 8 || buff[protocol_location + 6]; // 读出要读的寄存器长度
- node_receive_params->params[i].modbus_read->precision = buff[protocol_location + 8]; // 读出小数点精度
- node_receive_params->params[i].modbus_read->bigLittleFormat = buff[protocol_location + 9]; // 读出数据大小端格式
- protocol_location += protocol_modbus_read;
- break;
- case protocol_dlt645_07:
- protocol_location++;
- node_receive_params->params[i].protcol = DLT645_07;
- node_receive_params->params[i].dlt645_params = malloc(sizeof(NODE_DLT645_PARAMS));
- node_receive_params->params[i].modbus_read = NULL;
- node_receive_params->params[i].modbus_write = NULL;
- memcpy(node_receive_params->params[i].dlt645_params->deviceType645, buff + protocol_location, 6);
- memcpy((uint8_t *)&node_receive_params->params[i].dlt645_params->dataType645, buff + protocol_location + 6, 4);
- protocol_location += protocol_dlt645_07;
- break;
- case protocol_dlt645_97:
- protocol_location++;
- node_receive_params->params[i].protcol = DLT645_97;
- node_receive_params->params[i].dlt645_params = malloc(sizeof(NODE_DLT645_PARAMS));
- node_receive_params->params[i].modbus_read = NULL;
- node_receive_params->params[i].modbus_write = NULL;
- memcpy(node_receive_params->params[i].dlt645_params->deviceType645, buff + protocol_location, 6);
- memcpy((uint8_t *)&node_receive_params->params[i].dlt645_params->dataType645, buff + protocol_location + 6, 2);
- protocol_location += protocol_dlt645_97;
- break;
- default: // 解析没满20个属性
- return 1;
- }
- }
- else
- {
- node_receive_params->Index = i; // 记录本次有多少数据传输过来了
- return 0;
- }
- i++;
- if (protocol_location > len) // 判断数据解析是否越界了,越界则跳转出
- {
- return 1;
- }
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: nodeSendReadValue(uint8_t *string)
- * 形 参:组成node回传数据,传输数据为
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void nodeSendReaddValue(uint8_t *string,uint16_t *size)
- {
- NODE_DEVICE_PARAMS *node_receive_params;
- node_receive_params = get_node_receive_params();
- int i = 0;
- int len=0;
- //先加载node的地址node地址暂时本地写死后续加载
- string[len]= LocalAddress>>8;
- string[len+1]=LocalAddress;
- len+=2;
-
- while (i != 20)
- {
- switch (node_receive_params->params[i].protcol)
- {
- case DLT645_07:
- case DLT645_97:
- if (node_receive_params->params[i].dlt645_params->rxLen <= 4)
- {
- string[len] = 0x04;
- len++;
- memcpy(&string[len], node_receive_params->params[i].dlt645_params->value, 4);
- len += 4;
- }
- else if (node_receive_params->params[i].dlt645_params->rxLen == 5)
- {
- string[len] = 0x05;
- len++;
- memcpy(&string[len], node_receive_params->params[i].dlt645_params->value, 5);
- len += 5;
- }
- else if (node_receive_params->params[i].dlt645_params->rxLen == 9)
- {
- string[len] = 0x09;
- len++;
- memcpy(&string[len], node_receive_params->params[i].dlt645_params->value, 9);
- len += 9;
- }
- else
- {
- string[len] = 0x00;
- len++;
- }
- break;
- case MODBUS:
- if (node_receive_params->params[i].modbus_read->rxLen == 4)
- {
- string[len] = 0x04;
- len++;
- memcpy(&string[len], node_receive_params->params[i].dlt645_params->value, 4);
- len += 4;
- }
- else
- {
- string[len] = 0x00;
- len++;
- }
- break;
- default:
- *size=len;
- return;
- }
- i++;
- }
- *size=len;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: GatewayProtocolAnalysis(uint8_t *string)
- * 形 参:将节点应答信息依次解析为json数据
- * 返 回 值: 0未读到json数据,1读到了json数据
- *********************************************************************************************************
- */
- int GatewayProtocolAnalysis(uint8_t *string, uint16_t len)
- {
- // 读取上次循环最终停止位置
- int nowDeviceNum = startDeviceNum;
- int nowparamsNum = startParamsNum;
- GATEWAY_PARAMS *gateway;
- gateway = get_gateway_config_params();
- uint16_t nodeId = string[0] << 8 | string[1];
- // 将当前的节点指针指到需要读取的节点位置
- NODE_PARAMS *currentNode = gateway->node_params;
- uint16_t currentNodeId = currentNode->node_address[0] << 8 | currentNode->node_address[1];
- while (currentNodeId != nodeId)
- {
- currentNode = currentNode->nextNode;
- if (currentNode == NULL)
- {
- // 没有找到对应该节点信息不是给本机
-
- return 0;
- }
- currentNodeId = currentNode->node_address[0] << 8 | currentNode->node_address[1];
- }
- // 找到该节点进行轮询
- DEVICE_PARAMS *currentDevice = currentNode->device_params;
- while (nowDeviceNum)
- {
- currentDevice = currentDevice->nextDevice;
- nowDeviceNum--;
- }
- // 移动位置到开始属性
- NODE_READ_MODBUS_COMMAND *currentModbusParams = currentDevice->params->node_read_modbus_command;
- NODE_READ_DLT645_COMMAND *currentDlt645Params = currentDevice->params->node_read_dlt645_command;
- switch (currentDevice->protocol)
- {
- case MODBUS:
- while (nowparamsNum)
- {
- currentModbusParams = currentModbusParams->nextParams;
- nowparamsNum--;
- }
- break;
- case DLT645_07:
- case DLT645_97:
- while (nowparamsNum)
- {
- currentDlt645Params = currentDlt645Params->nextParams;
- nowparamsNum--;
- }
- break;
- default:
- break;
- }
- memset(pubJsonString,0,jsonMaxSize);
-
- sprintf(pubJsonString, "{\"data\":[");
- int index = 2; // 子节点地址
- while (index <len)
- {
- switch (currentDevice->protocol)
- {
- case MODBUS:
- // modbus协议
- switch (*(string + index))
- {
- case 0x00:
- // 没有数据
- index++;
- break;
- case 0x04:
- if (currentDevice->MDBdataType == 0x01 && currentModbusParams->decimalPoint == 0x00) // modbus底层存储的数据类型 1INT 2float
- {
- uint32_t data;
- data = string[index + 1] + (string[index + 2] >> 8) + (string[index + 3] >> 16) + (string[index + 4] >> 24);
- sprintf(pubJsonString + strlen(pubJsonString), "{\"deviceId\":\"%s\",\"%s\":%d},", currentDevice->deviceID, currentModbusParams->keyword, data);
- }
- else // 如果是int且有小数点,或者底层就是float按照float来计算
- {
- float value;
- memcpy(&value,string+index+1,4);
- sprintf(pubJsonString + strlen(pubJsonString), "{\"deviceId\":\"%s\",\"%s\":%.2f},", currentDevice->deviceID,currentModbusParams->keyword,value);
- }
- index += 4;
- break;
- default:
- break;
- }
- currentModbusParams = currentModbusParams->nextParams;
- if (currentModbusParams == NULL)
- {
- currentDevice = currentDevice->nextDevice;
- if(currentDevice->protocol==MODBUS)
- {
- currentModbusParams=currentModbusParams->nextParams;
- }
- else
- {
- currentDlt645Params=currentDlt645Params->nextParams;
- }
- }
- break;
- case DLT645_07:
- case DLT645_97:
- switch (*(string + index))
- {
- case 0x00:
- index++;
- break;
- case 0x04:
- {
- index++;
- float value;
- memcpy(&value,string+index,sizeof(float));
- sprintf(pubJsonString + strlen(pubJsonString), "{\"deviceId\":\"%s\",\"%s\": %.2f},", currentDevice->deviceID, currentDlt645Params->keyword,value);
- index += 4;
- }
- break;
- case 0x05:
- {
- index++;
- //%02依次为年月日时分
- sprintf(pubJsonString + strlen(pubJsonString), "{\"deviceId\":\"%s\",\"%s\": \"%02X%02X%02X%02X%02X\"},",
- currentDevice->deviceID, currentDlt645Params->keyword, string[index + 4], string[index + 3], string[index + 2], string[index + 1], string[index]);
- index += 5;
- }
- break;
- case 9:
- {
- index++;
- float value;
- memcpy(&value, &string[index], 4);
- sprintf(pubJsonString + strlen(pubJsonString), "{\"deviceId\":\"%s\",\"%s\":\"%02X%02X%02X%02X%02X%.2f\"},",
- currentDevice->deviceID, currentDlt645Params->keyword, string[index + 8], string[index + 7], string[index + 6], string[index + 5], string[index + 4], value);
- index+=9;
- }
- break;
- default:
- break;
- }
- //移动到下个属性
- switch (currentDevice->protocol)
- {
- case DLT645_97:
- case DLT645_07:
- currentDlt645Params = currentDlt645Params->nextParams;
- if (currentDlt645Params == NULL)
- {
- currentDevice = currentDevice->nextDevice;
- currentDlt645Params=currentDevice->params->node_read_dlt645_command;
- }
- break;
- case MODBUS:
- currentModbusParams=currentModbusParams->nextParams;
- if(currentModbusParams==NULL)
- {
- currentDevice=currentDevice->nextDevice;
- currentDlt645Params=currentDevice->params->node_read_dlt645_command;
- }
- break;
- }
- break;
- default:
- break;
- }
- }
- if(strlen(pubJsonString)<10)
- {
- return 0;
- }
- sprintf(pubJsonString+strlen(pubJsonString)-1,"]}");
- //组装完成json数据开始向mqtt邮箱发送完成标识
- int msg = MBOX_USER_PUBLISHQOS2;
- if(mqtt_connectFlag==1) OSMboxPost(mqtt_sendMseeageMbox, &msg);
- return 1;
- }
|