Here is how to embed a simple NodeMCU client server for remote control.
My goal is to embed the NodeMCU (ESP-12) module in an antenna (or any other thing) to be remote controlled over my home network. At the simplest level, I want to use a computer or phone to connect to the NodeMCU, send it commands, and receive data back. This will use a basic client-server model. My computer or phone will be the “client”; the remote thing with the NodeMCU will be the “server”. In the case of my antenna, the NodeMCU will be a control computer to move the antenna using servo motors, switch relays and tune the antenna.
As a proof of concept, I wrote the short program (below) in Arduino C++ and flashed it onto the NodeMCU. When the ESP-12 starts, it connects to my LAN at a known IP address and port number. It then listens for a client to connect. When a client connects and sends some data, the NodeMCU does something with the data, and sends an acknowledgement “OK” back to the client. Pretty basic, but it demonstrates how to develop a simple NodeMCU Client Server remote control system.
In the picture above, the RealTerm screen is a serial port connection to monitor the ESP-12 activity. The other window, Socket Test, is a TCP/IP client on my computer. The picture demonstrates what happens when the Socket Test (client) connects to the NodeMCU (server) and exchanges data.
Simple NodeMCU Client Server Source Code
Programming the NodeMCU with the ESP8266 Arduino Core requires some learning, particularly about the provided ESP8266WiFi library. Since none of the examples show such a simple client-server arrangement for remote control, I had to figure it out. Here is the code.
All you need to do is write a more meaningful routine to Process Client Data and you will have a basic, but complete, remote control system. That’s what I will be doing next.
/* First test program with the Arduino Core and NodeMCU. I wanted to make sure that I could run a server on the NodeMCU which would receive data from a remote socket. Assumes that Serial is open while this is running. Assumes that only one remote socket would try to connect to the server. - John 2016 10 16 */ #include <WiFiServer.h> #include <WiFiClient.h> #include <ESP8266WiFi.h> #define WIFI_BUFFER_SIZE 128 const char* ssid = "xxxxxxx"; const char* password = "xxxxxxxxx"; WiFiServer server(4000); WiFiClient client; int status = WL_IDLE_STATUS; boolean ClientConnected = false; boolean LastClientConnected = false; char wifiBuffer[WIFI_BUFFER_SIZE]; void setup() { /* Open serial port for debugging only. */ Serial.begin(115200); delay(100); /* Log NodeMCU on to LAN. Provide IP Address over Serial port */ WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(250); } Serial.print("WiFi Connected at "); Serial.println(WiFi.localIP()); /* Start Server */ server.begin(); delay(1000); Serial.println("Server Ready"); } void loop() { /* Check whether or not a client is connected once each loop */ SetClientConnected(CheckClientConnection()); if (ClientConnected && GetClientData()) { ProcessClientData(); } delay(10); } void SetClientConnected(boolean flag) { /* Only process this routine when the ClientConnected state has actually changed. Otherwise, return immediately. */ if (flag != LastClientConnected) { ClientConnected = flag; LastClientConnected = ClientConnected; if (ClientConnected) { Serial.println("Client Connected"); } else { Serial.println("Client Disconnected"); } } } boolean CheckClientConnection() { /* If we have a running WiFiClient and there is a remote connection, just confirm the connection*/ if (client && client.connected()) { return true; } /* If we have a running WiFiClient but the remote has disconnected, disable WiFiClient and report no connection */ if (client && !client.connected()) { client.stop(); return false; } /* At this point we are ready for a new remote connection. Create the WiFiClient and confirn the connection */ if (server.hasClient()) { if ((!client) || (!client.connected())) { if (client) client.stop(); client = server.available(); return true; } } } boolean GetClientData() { /* If the remote connection has sent data, read the data and put it into the WiFiBuffer. Tell the main loop that data is available for processing. Otherwise, return immediately and report that no data is available. */ if (client.available()) { String c = client.readStringUntil('\r'); client.flush(); c.toCharArray(wifiBuffer, WIFI_BUFFER_SIZE); return true; } else { return false; } } void ProcessClientData(void) { /* This is a trivial routine to process data from remote socket. It simply repeats the data to the Serial port, and sends an "OK" confirmation back to the remote socket. */ Serial.print("Client Data Received: "); Serial.println(wifiBuffer); if (client) { client.println("OK"); } }