#include "lwip/opt.h" #include "lwip/sys.h" #include "tcp_server.h" #include #include #include "gd32f30x.h" #include "main.h" #include "lwip/tcp.h" #include "lwip/memp.h" #include "lwip/api.h" #include "sockets.h" #include "log.h" #include "netconf.h" #include "gateway_message.h" #include "gd32_flash.h" #include "stdlib.h" #include "protocol.h" #include "delay.h" #include "sys_mqtt.h" #include "updata.h" uint8_t closeFlag = 0; // DHCP关闭标志位 uint8_t tcp_config = 0; // 存储config标志位 uint8_t ProtocolsModeFlag = 1;// 开启内置协议模式 uint8_t TransparentModeFlag = 0; // 表示用串口透传 将数据原封不动的发给客户端 ip_config load_ip_config = {0}; ip_config *get_ip_config() { return &load_ip_config; } // 解析设备当前的硬件信息(结构体内的数据) void get_device_params(char* device_params) { GATEWAY_PARAMS *get; get= get_gateway_config_params(); DEVICE_PARAMS *current_device=get->device_params; sprintf(device_params, "{\"read_config\":\"success\",\"baudrate\":%d,\"checkBit\":%d,\"commandTopic\":%s,\"dataBit\":%d,\ \"deviceId\": \"%s\",\"host\":\"%s\",\"inboundTime\":%d,\"messageTopic\":\"%s\",\"port\":%d,\"stopBit\":%d,\"deviceList\":[",get->baudrate, get->checkBit,get->commandTopic,get->dataBits,get->deviceId,get->host,get->inboundTime,get->messageTopic,get->port,get->stopBit); while(current_device != NULL) { sprintf(device_params + strlen(device_params),"{\"protocol\":%d,\"bigLittleFormat\":%d,\"deviceId\":\"%s\",\"sensorData\":[", current_device->protocol,current_device->MDBbigLittleFormat,current_device->deviceID); GATEWAY_READ_DLT645_COMMAND *read_dlt645_command = current_device->params->gateway_read_dlt645_command; GATEWAY_READ_MODBUS_COMMAND *read_modbus_command = current_device->params->gateway_read_modbus_command; GATEWAY_WRITE_MODBUS_COMMAND *write_modbus_command = current_device->params->gateway_write_modbus_command; // dlt645 read while(read_dlt645_command != NULL) { sprintf(device_params + strlen(device_params),"{\"identifier645\":%d,\"identifier\":\"%s\",\"deviceID645\":\"%s\"},", read_dlt645_command->Identification,read_dlt645_command->keyword,read_dlt645_command->deviceID645); read_dlt645_command = read_dlt645_command->nextParams; } // modbus read while(read_modbus_command != NULL) { sprintf(device_params + strlen(device_params),"{\"rFunctionCode\":%d,\"registerAddress\":%d,\"slaveAddress\":%d,\"registerByteNum\":%d\"identifier\":\"%s\",\"precise\":%d},", read_modbus_command->functionCode, read_modbus_command->registerAddress,read_modbus_command->slaveAddress, read_modbus_command->registerByteNum,read_modbus_command->keyword,read_modbus_command->decimalPoint); read_modbus_command = read_modbus_command->nextParams; } // modbus write sprintf(device_params + strlen(device_params)-1,"], \"commandData\":[");//sensorData:[ while(write_modbus_command != NULL) { sprintf(device_params + strlen(device_params),"{\"registerAddress\":%d,\"slaveAddress\":%d,\"wFunctionCode\":%d,\"registerByteNum\":%d},", write_modbus_command->registerAddress,write_modbus_command->slaveAddress,write_modbus_command->functionCode,write_modbus_command->registerByteNum); write_modbus_command = write_modbus_command->nextParams; } sprintf(device_params + strlen(device_params)-1,"]}");// commandData:[ current_device = current_device->nextDevice; } sprintf(device_params + strlen(device_params),"]}"); } // 储存上位机发送的config数据,并返回上位机操作结果 void save_config(int client_socket,char* dataBuf) { save_config_params(dataBuf);// 储存到flash 不用判断失败 char* retMsg = pvPortMalloc(32); memset(retMsg, 0, strlen(retMsg)); retMsg = "{\"write_config\":\"success\"}"; send(client_socket, retMsg, strlen(retMsg), 0); vPortFree(retMsg); tcp_config = 1; } // 储存上位机发送的config_add数据,并返回上位机操作结果 void add_config(int client_socket, char* dataBuf) { GATEWAY_PARAMS *get; get= get_gateway_config_params(); DEVICE_PARAMS *device=get->device_params; char* retMsg = pvPortMalloc(32); memset(retMsg, 0, strlen(retMsg)); while(device != NULL)// 一直轮询到当前为NULL { device = device->nextDevice; } addDevice(dataBuf); // 再检查更新后的deviceId是否为NULL if(device == NULL)// error { retMsg = "{\"write_config\":\"error\"}"; send(client_socket, retMsg, strlen(retMsg), 0); } else// success { retMsg = "{\"write_config\":\"success\"}"; send(client_socket, retMsg, strlen(retMsg), 0); } vPortFree(retMsg); } // 设备嗅探 void find_device(int client_socket) { char deviceId[50];// 发送设备名 GATEWAY_PARAMS *get; get= get_gateway_config_params(); if(get->device_params == NULL) { sprintf(deviceId, "{\"find_device\":\"%s\"}", gatewayId); send(client_socket, deviceId, strlen(deviceId), 0); } else { sprintf(deviceId, "{\"find_device\":\"%s\"}", get->deviceId); send(client_socket, deviceId, strlen(deviceId), 0); } memset(deviceId, 0, 50); } // 发送设备当前的config数据 void send_config(int client_socket) { GATEWAY_PARAMS *get; get= get_gateway_config_params(); char* device_params = pvPortMalloc(3 * 1024); memset(device_params,0,3 * 1024); if(get->device_params == NULL) { sprintf(device_params, "{\"read_config\":\"error\"}"); send(client_socket, device_params, strlen(device_params), 0); } else { get_device_params(device_params); send(client_socket, device_params, strlen(device_params), 0); } vPortFree(device_params); } // 解析上位机发送的ip_config数据 void analysis_ip_config(int client_socket, int sockfd,struct sockaddr_in tcpServerSock, char* buf) { // 打开DHCP if (strstr(buf, "\"dhcpMode\":\"open\"") != NULL) { DHCP_open(); char* retMsg = pvPortMalloc(32); retMsg = "{\"ip_config\":\"success\"}"; send(client_socket,retMsg,strlen(retMsg),0); vPortFree(retMsg); } // 关闭DHCP else if (strstr(buf, "\"dhcpMode\":\"close\"") != NULL) { uint8_t prot[6]; // 设置静态IP地址,并关闭DHCP set_ipaddr(buf); // 解析buf内的数据,保存到load_ip_config结构体 parseStringField(buf, "\"ipv4\":\"", (char *)&load_ip_config.host);// eg:192.168.1.100 parseStringField(buf, "\"subnetMask\":\"", (char *)&load_ip_config.subnetMask);// eg:255.255.255.0 parseStringField(buf, "\"defaultGateway\":\"", (char *)&load_ip_config.defaultGateway);// eg:192.168.1.1 parseStringField(buf, "\"udpLogPort\":\"", (char *)&prot); load_ip_config.udpLogPort = atoi((char *)&prot); // 关闭服务端和客户端 lwip_close(sockfd); lwip_close(client_socket); // DHCP关闭标志位置 1 closeFlag = 1; } } // 切换工作模式 void work_mode(char* buf) { /* 用标志位开关data_task任务中,发送数据的方式 */ // 内置协议模式 if(strstr(buf,"protocolsMode") != NULL) { ProtocolsModeFlag = 1;// 开启内置协议模式 TransparentModeFlag = 0; // 关闭透明传输模式 LogPrint(LOG_INFO,__FILE__,__FUNCTION__,__LINE__,"ProtocolsMode"); } // 透明传输模式 if(strstr(buf,"TransparentMode") != NULL) { ProtocolsModeFlag = 0;// 关闭内置协议模式 TransparentModeFlag = 1; // 开启透明传输模式 LogPrint(LOG_INFO,__FILE__,__FUNCTION__,__LINE__,"TransparentModeFlag"); } } #define RECV_BUF_SIZE 3 * 1024 void tcp_server_task(void *pvParameters) { int ret,sockfd; int recv_size; struct sockaddr_in tcpServerSock; struct sockaddr_in client_sock; // 命令集 char* recv_cmd[] = {"\"cmd\":\"write_config\"","\"cmd\":\"write_config_add\"", "\"cmd\":\"read_config\"","\"cmd\":\"find_device\"", "\"cmd\":\"ip_config\"","\"cmd\":\"toggle_work_mode\"", "\"cmd\":\"software_update\"","\"cmd\":\"reboot\"", "\"cmd\":\"error_cmd\""};// cmd:error_cmd 仅为了判断错误的命令 while(dhcp_done!=1) { vTaskDelay(100); } tcpServerSock.sin_family = AF_INET; inet_aton("192.168.0.100",&(tcpServerSock.sin_addr)); // tcpServerSock.sin_addr.s_addr = htonl(IPADDR_ANY); tcpServerSock.sin_port = htons(8080); tcp_server_begin: sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { goto tcp_server_begin; } ret = bind(sockfd, (struct sockaddr *)&tcpServerSock, sizeof(tcpServerSock)); if (ret < 0) { lwip_close(sockfd); sockfd = -1; goto tcp_server_begin; } ret = listen(sockfd, 10); if (ret < 0) { lwip_close(sockfd); sockfd = -1; goto tcp_server_begin; } socklen_t len = sizeof(client_sock); int client_socket = accept(sockfd, (struct sockaddr*)&client_sock,&len); if (client_socket<0) { printf("error"); } LogPrint(LOG_INFO,__FILE__,__FUNCTION__,__LINE__,"PC connect success"); while (1) { vTaskDelay(100); char* dataBuf = pvPortMalloc(RECV_BUF_SIZE);// 存储config数据 最大20K,暂定3K if(dataBuf == NULL) LogPrint(LOG_ERROR,__FILE__,__FUNCTION__,__LINE__,"recv buf malloc fail"); memset(dataBuf,0,strlen(dataBuf)); // 获取上位机发送的数据 recv_size=recv(client_socket,dataBuf,RECV_BUF_SIZE,0); // 插入tcp_config标志位,后续不通过http获取默认配置数据 sprintf(dataBuf + strlen(dataBuf),"tcp_config"); // 接收到消息 // 解析上位机发送的CMD命令 if(recv_size>0) { int j = 0; for(int i = 0; i < sizeof(recv_cmd)/sizeof(recv_cmd[0]); i++) { if(strstr(dataBuf,recv_cmd[i]) != NULL) { i = sizeof(recv_cmd)/sizeof(recv_cmd[0]); } j++; } if (ProtocolsModeFlag) { switch (j) { case WRITE_CONFIG: save_config(client_socket, dataBuf); vPortFree(dataBuf); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "write config"); break; case WRITE_CONFIG_ADD: add_config(client_socket, dataBuf); vPortFree(dataBuf); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "write config add"); break; case READ_CONFIG: send_config(client_socket); vPortFree(dataBuf); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "read config"); break; case FIND_DEVICE: find_device(client_socket); vPortFree(dataBuf); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "find device"); break; case IP_CONFIG: LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "ipconfig"); analysis_ip_config(client_socket, sockfd, tcpServerSock, dataBuf); if (closeFlag == 1) { // 更新新的地址 inet_aton((char*)&load_ip_config.host, &(tcpServerSock.sin_addr)); closeFlag = 0; vPortFree(dataBuf); goto tcp_server_begin; } vPortFree(dataBuf); break; case TOGGLE_MODE: work_mode(dataBuf); vPortFree(dataBuf); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "toggle work mode"); break; case UPDATE: LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "update"); vPortFree(dataBuf); updata_task_creat(client_socket); break; case REBOOT: send(client_socket,"{\"reboot\":\"success\"}", 20, 0); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "reboot"); __set_PRIMASK(1); NVIC_SystemReset(); break; default: send(client_socket,"{\"cmd:error\"}", 15, 0); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "Command error"); } } else { switch (j) { case FIND_DEVICE: find_device(client_socket); vPortFree(dataBuf); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "find device"); break; case IP_CONFIG: LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "ip config"); analysis_ip_config(client_socket, sockfd, tcpServerSock, dataBuf); if (closeFlag == 1) { // 更新新的地址 inet_aton((char*)&load_ip_config.host, &(tcpServerSock.sin_addr)); closeFlag = 0; vPortFree(dataBuf); goto tcp_server_begin; } vPortFree(dataBuf); break; case TOGGLE_MODE: work_mode(dataBuf); vPortFree(dataBuf); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "toggle work mode"); break; case UPDATE: LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "update"); vPortFree(dataBuf); updata_task_creat(client_socket); break; case REBOOT: send(client_socket,"{\"reboot\":\"success\"}", 20, 0); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "reboot"); __set_PRIMASK(1); NVIC_SystemReset(); break; default: send(client_socket,"{\"cmd:error\"}", 15, 0); LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "Command error"); } } } // 没接收到消息 else if(recv_size==0) { lwip_close(client_socket); LOG_PRINT(LOG_ERROR,"PC disconnect,wait reconnect"); client_socket= accept(sockfd, (struct sockaddr*)&client_sock,&len); } vPortFree(dataBuf); } } /*! \brief initialize the tcp_client application \param[in] none \param[out] none \retval none */ void tcp_server_init(void) { xTaskCreate(tcp_server_task, "TCP_SERVER", DEFAULT_THREAD_STACKSIZE, NULL, 1, NULL); }