In my previous post, ESP8266/Arduino IDE: Further TCP Exploration, I was up to the point of using an Echo server to test TCP, and was sending commands to myself (the ESP8266) via the echo server to control the LED.
Since I have the overall idea fleshed out pretty well on the ESP8266, it’s time to implement a real server.
Expanding the Protocol
In the prior post, I had worked out a simplistic protocol that will allow a client to tell the server what needs to be done. As I started to implement a real server I realized there were a few more things to add.
Previously, I was using an Echo server, so I was transmitting on the echo port of 7. Now that I’m creating my own server, I need to decide on a port. I am going to use the telnet port of 23, and I’m doing that because I’m going to use telnet to test the server. Using the telnet port makes it a little easier to test. I can easily change the port later to something more appropriate.
When the server accepts a client connection, it will transmit “ready<cr><lf>” to the client so the client knows it can send a command.
Previously, any error generated a response of just “error”. Now, if the error is a timeout, I will return “timeout<cr><lf>”. A program is not going to normally encounter this condition (it will xmit a command as soon as it received “ready”), but if a human types too slow, it will be obvious what happened.
Program Highlights
This program is very straight-forward. It implements the server class, waits for a connection, then waits for a command and processes it. Once done it terminates the client and goes back to waiting. Since it is built on prior tested code, there is very little new here.
Here is the code:
#include <ESP8266WiFi.h> const int ledPin = 0; WiFiServer server(23); // --------------------------------------------------------------------------- char * getstr( WiFiClient c, char * s, int maxlen ) { const unsigned long timeout = 30UL * 1000UL; int i = 0; unsigned long timer = millis() + timeout; strcpy(s, ""); while (true) { while (!c.available()) { if (millis() > timer) { // don't allow session to remain open too long strcpy(s, ""); return s; } delay(10UL); } // while s[i] = c.read(); if (s[i] == '\n') { s[i] = '\0'; break; // while } else if (s[i] == '\r') ; // do nothing additional on return character - it will be overwritten by next char else { if (i == maxlen) { // if user's input exceeds buffer, stop reading Serial.println("buffer overflow"); s[maxlen-1] = '\0'; return s; } else i = i + 1; } } // while return s; } // getstr // --------------------------------------------------------------------------- void setup() { char pass[] = "1234"; char ssid[] = "AP101"; char s[100]; int status; Serial.begin(9600); pinMode(ledPin, OUTPUT); Serial.print("Trying to connect to "); Serial.println(ssid); // attempt to connect to Wifi network: status = WiFi.begin(ssid, pass); status = WiFi.waitForConnectResult(); if (status != WL_CONNECTED) { Serial.println("Connection Failed"); while (true) {} } Serial.println("Connected. IP Addr: "); Serial.println(WiFi.localIP()); server.begin(); } // setup // --------------------------------------------------------------------------- void loop() { int k; char s[100]; WiFiClient client; while (true) { client = server.available(); // you only get to do this once, so do test after assignment if (client) { // is there a connection? Serial.println("Client Connected"); client.println("ready"); getstr(client, s, sizeof(s)); Serial.print("cmd received: "); Serial.println(s); if (strlen(s) == 0) { client.println("timeout"); } else if (strcmp("on", s) == 0) { digitalWrite(ledPin, HIGH); client.println("ok"); } else if (strcmp("off", s) == 0) { digitalWrite(ledPin, LOW); client.println("ok"); } else { client.println("error"); } client.stop(); Serial.println("Client disconnected."); } // server.available delay(10UL); } // outerblock while }
Testing With Telnet
In the continual dumbing down of Windows, Microsoft stopped installing Telnet in Windows 7 (it is now an optional feature), and, further, completely disabled its access from the command line (can’t say if this is true for Windows 8 because I am boycotting it).
You can track down how to install telnet on Google. Since I specified the default telnet port of 23 in the server, you don’t have to run telnet from the command line which is the only way to override the port.
If you have have putty or don’t want to install Microsoft’s telnet, you can install/use putty, and it allows you to specify the port should you need it.
Once you have telnet working, you just telnet to the ESP8266, type “on” and the LED will light:
ready on ok Connection to host lost.
To verify proper operation, I typed the commands “on” and “off”. Then “bogus” to generate an error. I also typed in really long text to verify the buffer doesn’t overflow and just let it sit until it timed out. Looks like the server is working as I wish.
Next up is to access the server from a program I write on my PC.
Pingback: Using Lazarus / Free Pascal to Communicate with ESP8266 | Big Dan the Blogging Man