Friday, June 30, 2017

AC Controller: ESP8266 Telnet Server for logs

Since the start of the project I kept thinking I needed a way to be able to get logs from the system remotely. I originally considered some remote server, maybe use service to push error codes with mqtt, which will allow me easy remote visualization and analysis. I am still considering that option, but as I have already expressed, I hate depending on services provided by thirdparties, so even if I end up taking that path, I decided to add a telnet server to the ESP8266 and send the logs there.

For those not familiar with Telnet, it is just a TCP socket in port 23 where you send ASCII data... super simple... can not get simpler than that... I found this example: doing telnet to serial and pretty much reused that.

This is what I did. At the declarations I added:

  1. WiFiServer telnet(23);
  2. WiFiClient telnetClients;
  3. int disconnectedClient = 1;

  4. #define DEBUG_LOG_LN(x) { Serial.println(x); if(telnetClients) { telnetClients.println(x); } }
  5. #define DEBUG_LOG(x) { Serial.print(x); if(telnetClients) { telnetClients.print(x); } }

Basically for declaring the server (line 1), the client (line 2) and a pair of macros for sending logs to serial only or to serial and telnet if there is a telnet client.

In setup:
  1.   telnet.begin();
  2.   telnet.setNoDelay(true);
  3.   DEBUG_LOG_LN("Telnet server started");  
Start the telnet server (line 1), enable no delay (line 2) which disables the naggle algorithm that would buffer data before pushing it out on the TCP socket.

In loop:
  1.   if (telnet.hasClient()) {
  2.     if (!telnetClients || !telnetClients.connected()) {
  3.       if (telnetClients) {
  4.         telnetClients.stop();
  5.         DEBUG_LOG_LN("Telnet Client Stop");
  6.       }
  7.       telnetClients = telnet.available();
  8.       DEBUG_LOG_LN("New Telnet client");
  9.       telnetClients.flush();  // clear input buffer, else you get strange characters 
  10.       disconnectedClient = 0;
  11.     }
  12.   }
  13.   else {
  14.     if(!telnetClients.connected()) {
  15.       if(disconnectedClient == 0) {
  16.         DEBUG_LOG_LN("Client Not connected");
  17.         telnetClients.stop();
  18.         disconnectedClient = 1;
  19.       }
  20.     }
  21.   }
This will connect to a telnet client if there happens to be one available (lines 1 to 12) and will disconnect the client if the connection gets dropped (lines 14 to 21). With this code, if a client comes in, the current client connection gets dropped (lines 3 to 6).

Lastly, you may notice that I replaced all the Serial.print and Serial.println with DEBUG_LOG and DEBUG_LOG_LN. Those 2 macros are the ones pushing the logs to serial or both to serial and telnet. I will probably extend those in the future to add line number and time.

As with the whole project, the work is being checked in here:

No comments:

Post a Comment