#include "protocol.h" #include "stdint.h" #include "gateway_message.h" #include "stdlib.h" #include "string.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,protocol_dlt645_07}PROTOCOL_LENGTH; //每个协议的数据包长度 /* ********************************************************************************************************* * 函 数 名: void masterSendNodeString(uint8_t nodeIndex)Index下标从0开始 * 功能说明: 负责取出网关第nodeIndex下的数据组成下发格式的数据,注:此处没有对node是否为NULL进行判断,请确保有该节点的信息 * 形 参:无 * 返 回 值: 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--; } string=malloc(257); memset(string,0,257); //将首字符用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--; } PARAMS_PROTOCOL_COMMAND* currentParams=currentDevice->params; //移动位置到结束位置属性的下一位 while(!nowparamsNum) { currentParams=currentParams->nextParams; nowparamsNum--; } if(currentParams==NULL) { currentDevice=currentDevice->nextDevice; //判断当前还有没有设备没有读取了 if(currentDevice==NULL) //且当前链表无后续设备了则跳出循环 { deviceNum=0; //将结束位置全部归0 paramsNum=0; return -1; } currentParams=currentDevice->params; //有则更新当前指针位置 nowDeviceNum++; nowparamsNum=0; } //最多进行20次循环组成下发数据 int i=0; int len=strlen((char *)&string); do { switch(currentDevice->protocol) { case MODBUS_READ: insertHexData(string,(uint8_t *)protocol_modbus,len,1); //插入modbus长度 len++; insertHexData(string,(uint8_t *)MODBUS_READ,len,1); //插入modbus读指令 len++; insertHexData(string,¤tParams->node_read_modbus_command->dataType,len,1); //插入读取的数据格式 len++; insertHexData(string,¤tParams->node_read_modbus_command->slaveAddress,len,1); //插入modbus从站地址 len++; insertHexData(string,(uint8_t *)¤tParams->node_read_modbus_command->registerAddress,len,2); //插入modbus寄存器地址 len+=2; insertHexData(string,¤tParams->node_read_modbus_command->decimalPoint,len,1); //插入小数点位数 len++; insertHexData(string,¤tParams->node_read_modbus_command->bigLittleFormat,len,1); //插入大小端 len++; break; case MODBUS_WRITE: insertHexData(string,(uint8_t *)protocol_modbus,len,1); //插入modbus长度 len++; insertHexData(string,(uint8_t *)MODBUS_WRITE,len,1); //插入modbus读指令 len++; insertHexData(string,¤tParams->node_write_modbus_command->dataType,len,1); //插入读取的数据格式 len++; insertHexData(string,¤tParams->node_write_modbus_command->slaveAddress,len,1); //插入modbus从站地址 len++; insertHexData(string,(uint8_t *)¤tParams->node_write_modbus_command->registerAddress,len,2); //插入modbus寄存器地址 len+=2; insertHexData(string,0x00,len,1); //插入小数点位数 len++; insertHexData(string,¤tParams->node_write_modbus_command->bigLittleFormat,len,1); //插入大小端 len++; break; case DLT645_07: insertHexData(string,(uint8_t *)protocol_dlt645_07,len,1); //插入dlt645_07数据长度 len++; insertHexData(string,(uint8_t *)¤tParams->node_read_dlt645_command->deviceID645,len,6); //插入dlt645地址域 len+=6; insertHexData(string,(uint8_t *)¤tParams->node_read_dlt645_command->functionCode,len,4); len+=4; break; case DLT645_97: insertHexData(string,(uint8_t *)protocol_dlt645_97,len,1); //插入dlt645_97数据长度 len++; insertHexData(string,(uint8_t *)¤tParams->node_read_dlt645_command->deviceID645,len,6); //插入dlt645_97地址域 len+=6; insertHexData(string,(uint8_t *)¤tParams->node_read_dlt645_command->functionCode,len,2); //插入dlt645_97数据标识 len+=2; default: break; } i++; currentParams=currentParams->nextParams; //判断当前设备有没有属性可读了 if(currentParams==NULL) { currentDevice=currentDevice->nextDevice; //判断当前还有没有设备没有读取了 if(currentDevice==NULL) //且当前链表无后续设备了则跳出循环 { deviceNum=0; //将结束位置全部归0 paramsNum=0; break; } currentParams=currentDevice->params; //有则更新当前指针位置 nowDeviceNum++; nowparamsNum=0; } nowparamsNum++; } while (i==20); //更新结束的位置分为两种情况,一种还在当前设备的属性中轮询此时nowDeviceNum没有改变过,另外一种情况设备内的属性 if(nowDeviceNum==0) { deviceNum=startDeviceNum; paramsNum=startParamsNum+nowparamsNum; } else { deviceNum=startDeviceNum+nowDeviceNum; paramsNum=nowparamsNum; } *size=len; } /* ********************************************************************************************************* * 函 数 名: 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等待解析的字符串数据, * 返 回 值: 无 解析这段数据时要先判断是否为该节点的消息,如果是才进行数据解析工作 ********************************************************************************************************* */ uint8_t SlaveProtocolAnalysis(uint8_t *buff,uint16_t len) { uint16_t NodeAdress=buff[0]<<8 || buff[1]; }