When designing the software system architecture of the simple programmable controller, I have the following main considerations:
(1) need to support TCP server as well as TCP client multiplexed concurrently, TCP server has three cases of connection, the browser downloads the built-in web page and the communication after that, for the communication connection of the third-party software, for the connection of Modbus-TCP protocol;
The TCP client is used to connect to the TCP server on the cloud server to realize remote access. Considering the resource situation of ESP8266, the concurrency is designed according to the specification that the TCP server supports four TCP client connection while one TCP client connects to the cloud server;
(2) It is necessary to control the flow of up to 5-way TCP/IP data communication and allocate enough time slices for PLC-related task scheduling to ensure reliable scheduling of PLC functions and real-time response;
3) The main tasks are the LWIP task and the main task, the priority of the LWIP task is lower than that of the main task, and at the same time ensure that the main task does not have a long time-consuming or blocking task, and the main task is scheduled in 10ms tick, and it actively enters the blocking state after the execution of the main task, releasing the CPU for scheduling other tasks;
Combining these, I designed the nearby software architecture;
When TCP server or TCP client receives data, the task of LWIP executes the callback function for data reception;
In the callback function, the program just stores the received data into the receive buffer, but does not process the data;
There are five receive buffer, each used for five concurrent connections; when deposited into these buffer, the TCP packet unpacking and sticky packet situation is handled at the same time, HTTP protocol data is unpacked through the end of the \r\n\r\n characters;
When new data is received, the task of LWIP wakes up the main task to process it by signaling Semaphore.
Each time the main task detect status of these 5 buffers, and if there is received data, it processes the relevant data and generates a response back to the sender;
In order to ensure that all 5 connections have the same chance to be processed, the main task takes turns to prioritize the state of these 5 caches.
For example, if the scheduler determines the cache for connection 0 first, then the next scheduler determines the cache for connection 1.
This can be achieved with a simple code;
signed short http_get_recvs(U32 *msg, U32 *addr, U16 *port){
U8 i;
signed short res = -1;
for(i = 0; i< TCPSERVER_CLIENT_NUM; i++)
{
if(tcpclient_curquery_client >= TCPSERVER_CLIENT_NUM){
tcpclient_curquery_client = 0;
}
if(tcpclient_info[tcpclient_curquery_client].used == TRUE){
if(tcpclient_info[tcpclient_curquery_client].received){
*msg = (U32)tcpclient_info[tcpclient_curquery_client].recvbuff;
*addr = tcpclient_info[tcpclient_curquery_client].ipaddr;
*port = tcpclient_info[tcpclient_curquery_client].port;
res = (signed short)tcpclient_curquery_client;
break;
}
}
tcpclient_curquery_client++;
}
return(res);
}