Page 1 of 1

Websocket reconnect after sleep mode

Posted: Fri Feb 25, 2022 7:24 pm
by Stumpy_L
I'm working on a greenhouse monitor, currently I have a BME280 module connected to a ESP32 Dev board, this unit will be battery powered. In the house I have another ESP32 Dev board with a 3.5" TFT display. I connect both to my house WiFi router.

I have the monitor connect to the internet to get NTP time as well as I can send the BME values to ThinkSpeak. In order to keep that connection I used a websocket to also send the values to the base unit. This is my first websocket project, I found a good tutorial with the codes on YouTube, where else? The monitor is set as the server and the base the client. Although I would think that the base should be the server so I could have multiple monitors, clients, sending values to the base but that's another conversation.

Using the examples, I have gotten it all to work fine with one problem. To save battery life I put the monitor to sleep, so I lose the websocket connection. I have seen online people suggest heartbeats and adding java script to reconnect, that's beyond my knowledge, I have not done any Java script.

I came up with a crude and not very efficient way to reconnect. The monitor goes to sleep for 5 minutes, will be longer when I get this working, I wake it up for 1 minute. In the base's loop function I added a timer to keep trying to reconnect every 30 seconds. That works although after an hour or so the base gets hung up, again not the best way to do this. It does show me that is what I need to do, detect that I am no longer connected then try to reconnect.

Looking at the code below at the beginning of the loop function is my timer, I have commented out the if statement I was trying different parameters in websocket libraries, I'm also not very good at determining what I can use in the libraries.

So that's the question, what is the best way to reconnect to the server after it has gone to sleep and then woke back up?

Thanks for all comments and suggestions
John
  1.  
  2. // Changed controller to ESP32
  3. // Added websocket client
  4.  
  5. #include <SPI.h>
  6. #include <TFT_eSPI.h> // Hardware-specific library
  7. #include <WebServer.h>
  8. #include <WebSocketsClient.h>
  9. #include <ArduinoJson.h>
  10.  
  11. TFT_eSPI tft = TFT_eSPI();       // Invoke custom library
  12.  
  13. //==== Defining Variables
  14.  
  15. unsigned char text;
  16. //char text[6] = "";
  17. String inTemp, inHum, outTemp = "", outHum;
  18. extern uint8_t SmallFont[];
  19. extern uint8_t BigFont[];
  20. extern uint8_t SevenSegNumFont[];
  21.  
  22. int x, y;
  23.  
  24. int currentPage = 0; //, selectedUnit;
  25. int selectedUnit = 0;
  26.  
  27. char grnHouseTemp[20] = " "; // Greenhouse Temperature number
  28. char grnHouseHum[20] = " "; // Greenhouse Humidity number
  29. long int start_time = millis();
  30. long int read_time = 4800; // time between reading Greenhouse data
  31. int grnHouseRead = 0; // bit that system is reading Greenhouse status
  32. float  grnHouse_Temp = 0; // Greenhouse temp
  33. float  grnHouse_Hum = 0; // Greenhouse humdity
  34. float  grnHouse_Press = 0; // Greenhouse pressure
  35. boolean newData = false;
  36.  
  37.     // temporary array for use when parsing
  38. const byte numChars = 64;
  39. char receivedChars[numChars];
  40. char tempChars[numChars];  
  41.  
  42.   // For Greenhouse
  43. char temp_str1[25];
  44. char humd_str1[25];
  45. char prss_str1[25];
  46. char Hour_strl[25];
  47. char Min_strl[25];
  48. char Batt_strl[25];
  49.  
  50. // Incoming data
  51. struct incomingData {
  52.  float In_Temp;
  53.  float In_Prss;
  54.  float In_Humd;
  55.  int   In_Hour;
  56.  int   In_Min;
  57.  float Batt_Lvl;
  58. }myincomingDataStructure;
  59.  
  60. // data from Greenhouse
  61. struct dataStruct1 {
  62.  float H1_Temp;
  63.  float H1_Prss;
  64.  float H1_Humd;
  65.  float H1_Batt;
  66. }myDataStructure1;
  67.  
  68. long int touchTime = 0; // time sceen was last touched
  69. long int scrnSavTime = 60000; // Screen saver display time
  70. int scrnSavOn = 0; //In screen saver mode
  71. const int backLite = 53;
  72.  
  73. // WiFi
  74. const char* ssid = "my_ssid"; // Wifi SSID
  75. const char* password = "my_password"; //Wi-FI Password
  76. WebSocketsClient webSocket; // websocket client class instance
  77. StaticJsonDocument<120> doc; // Allocate a static JSON document
  78. long int socket_Time = millis();
  79. long int socket_Delay = 30000;
  80.  
  81. const String pin_stat = doc["PIN_Status"]; // String variable tha holds LED status
  82. float Gh1_t = 1.1; // Float variable that holds temperature
  83. float Gh1_h = 2.2; // Float variable that holds Humidity
  84. float Gh1_p = 3.3; // Float variable that holds Pressure
  85. float Gh1_b = 4.4; // Float variable that holds Battery Voltage
  86. int Gh1_hr = 5; // integer for current hour
  87. int Gh1_mn = 6; // integer for current minute
  88.  
  89. void setup() {
  90.   Serial.begin(115200);
  91.  // Serial.println("Start Setup");
  92.  
  93. // TFT setup
  94.  
  95.   tft.init();
  96.   tft.fillScreen(TFT_BLACK); //clears screen, sets to Black
  97.   tft.setRotation(1);  // rotates screen 180' for landscape mode
  98.  
  99.   currentPage = 0; // Indicates that we are at Home Screen
  100.   selectedUnit = 0; // Indicates the selected unit for the first example, cms or inches
  101.  
  102.    // Draw intial screen
  103.      drawHomeScreen();
  104.    //drawGreenhouse1();  // Draws the Greenhouse 1 Status screen
  105.    
  106.   touchTime = millis(); // start touch time
  107.  
  108.  // Connect to local WiFi
  109.   WiFi.begin(ssid, password);
  110.   Serial.begin(115200);
  111.   while (WiFi.status() != WL_CONNECTED) {
  112.     Serial.print(".");
  113.     delay(500);
  114.   }
  115.   Serial.println();
  116.   Serial.print("IP Address: ");
  117.   Serial.println(WiFi.localIP()); // Print local IP address
  118.  
  119.   //address, port, and URL path
  120.   webSocket.begin("192.168.1.175", 81, "/");
  121.   // webSocket event handler
  122.   webSocket.onEvent(webSocketEvent);
  123.   // if connection failed retry every 5s
  124.   webSocket.setReconnectInterval(5000);
  125.  
  126. } // end void setup
  127.  
  128.  
  129. void loop() {
  130.  
  131. if(millis() > socket_Time + socket_Delay){
  132. //if(!connectFailedCb()){  
  133.    //address, port, and URL path
  134.   webSocket.begin("192.168.1.175", 81, "/");
  135.   // webSocket event handler
  136.   webSocket.onEvent(webSocketEvent);
  137.   // if connection failed retry every 5s
  138.   webSocket.setReconnectInterval(5000);
  139.  
  140.   socket_Time = millis();
  141. } // end if(millis() > socket_Time + socket_Delay)
  142.    webSocket.loop(); // Keep the socket alive
  143.  
  144.   // To get raw touch screen coordinates
  145.  /*
  146.       uint16_t x, y;
  147.       tft.getTouchRaw(&x, &y);
  148.       Serial.printf("x: %i     ", x);
  149.       Serial.printf("y: %i     ", y);
  150.       Serial.printf("z: %i \n", tft.getTouchRawZ());
  151.       delay(250);
  152. */
  153.  
  154.    display_cntrl(); // display screen controls
  155.  
  156.  
  157. } // end void loop
  158.  
  159.  
  160. // drawHomeScreen - Menu page
  161.  
  162.  // drawHomeScreen() {
  163. void drawHomeScreen() {
  164.   // Draws Home Screen
  165.    tft.fillScreen(TFT_BLACK); //clears screen, sets to Black
  166.  
  167. // Prints the title on the screen
  168.   tft.setCursor(80, 70);
  169.   tft.setTextColor(TFT_WHITE);
  170.   tft.setTextSize(3);
  171.   tft.print("Greenhouse Monitor");
  172.  
  173.   // Draws the red line under the title
  174.   tft.drawFastHLine(60, 100, 350, TFT_RED);
  175.  
  176.  
  177.   // Button - Greenhouse page
  178.  
  179.   tft.fillRoundRect(140, 150, 210, 40, 25, TFT_BLUE);
  180.   tft.drawRoundRect(140, 150, 210, 40, 25, TFT_WHITE);
  181.   tft.setCursor(170, 160);
  182.   tft.setTextColor(TFT_WHITE);
  183.   tft.setTextSize(2);
  184.   tft.print("Greenhouse");
  185.  
  186.  } // end void drawHomeScreen
  187.  
  188. void drawGreenhouse1() {
  189.   // Draws Report Setup screen
  190.   yield();
  191. //  Serial.println("In drawGreenhouse1");
  192.   // Sets the background color of the screen to black
  193.   tft.fillScreen(TFT_BLACK);
  194.  
  195.  // Back to Home button
  196.  
  197.   tft.fillRoundRect(30, 20, 50, 30, 10, TFT_BLUE);
  198.   tft.drawRoundRect(30, 20, 50, 30, 10, TFT_WHITE);
  199.   tft.setCursor(40, 27);
  200.   tft.setTextColor(TFT_WHITE);
  201.   tft.setTextSize(2);
  202.   tft.print("<-");
  203.  
  204.   tft.setCursor(100, 30);
  205.   tft.setTextColor(TFT_WHITE);
  206.   tft.setTextSize(1);
  207.   tft.print("Back to Main Menu");
  208.  
  209.   // Prints the title on the screen
  210.   tft.setCursor(80, 70);
  211.   tft.setTextColor(TFT_WHITE);
  212.   tft.setTextSize(3);
  213.   tft.print("Greenhouse Status");
  214.  
  215.   // Draws the red line under the title
  216.   tft.drawFastHLine(90, 100, 320, TFT_RED);
  217.  
  218.  // Label - Temperature
  219.  
  220.   tft.fillRect(20, 120, 90, 40, TFT_CYAN);
  221.   tft.drawRect(20, 120, 90, 40, TFT_WHITE);
  222.  // tft.fillRect(0, 0, 90, 40, TFT_CYAN);
  223.  // tft.drawRect(5, 3, 90, 40, TFT_WHITE);
  224.   tft.setCursor(32, 130);
  225.   tft.setTextColor(TFT_BLACK);
  226.   tft.setTextSize(2);
  227.   tft.print("Temp = ");
  228.   //tft.drawCentreString("Temp = ",120, 70, 4);
  229.  
  230.  // Label Humidity #
  231.  
  232.   tft.fillRect(20, 190, 90, 40, TFT_CYAN);
  233.   tft.drawRect(20, 190, 90, 40, TFT_WHITE);
  234.   tft.setCursor(35, 200);
  235.   tft.setTextColor(TFT_BLACK);
  236.   tft.setTextSize(2);
  237.   tft.print("Hum = ");
  238.  
  239.  // Label Pressure
  240.  
  241.   tft.fillRect(240, 120, 100, 40, TFT_CYAN);
  242.   tft.drawRect(240, 120, 100, 40, TFT_WHITE);
  243.   tft.setCursor(250, 130);
  244.   tft.setTextColor(TFT_BLACK);
  245.   tft.setTextSize(2);
  246.   tft.print("Press = ");
  247.  
  248.   // Label Update Time
  249.  
  250.   tft.fillRect(240, 190, 100, 40, TFT_CYAN);
  251.   tft.drawRect(240, 190, 100, 40, TFT_WHITE);
  252.   tft.setCursor(250, 200);
  253.   tft.setTextColor(TFT_BLACK);
  254.   tft.setTextSize(2);
  255.   tft.print("Time = ");
  256.  
  257.   // Label Battery Level
  258.  
  259.   tft.fillRect(20, 260, 135, 40, TFT_CYAN);
  260.   tft.drawRect(20, 260, 135, 40, TFT_WHITE);
  261.   tft.setCursor(35, 270);
  262.   tft.setTextColor(TFT_BLACK);
  263.   tft.setTextSize(2);
  264.   tft.print("Battery = ");
  265.  
  266. } // end of drawGreenhouse1
  267.  
  268. void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
  269.   //Serial.println("webSocketEvent");
  270.  
  271.   if (type == WStype_TEXT)
  272.   {
  273.     DeserializationError error = deserializeJson(doc, payload); // deserialize incoming Json String
  274.     if (error) { // Print erro msg if incomig String is not JSON formated
  275.       Serial.print(F("deserializeJson() failed: "));
  276.       Serial.println(error.c_str());
  277.       return;
  278.     }
  279.    
  280.     const float t = doc["Temp"]; // Float variable that holds temperature
  281.     Gh1_t = t;
  282.     const float h = doc["Hum"]; // Float variable that holds Humidity
  283.     Gh1_h = h;
  284.     const float p = doc["Press"]; // Float variable that holds pressure
  285.     Gh1_p = p;
  286.     const float b = doc["Batt"]; // Float variable that holds battery voltage
  287.     Gh1_b = b;
  288.     const int hr = doc["Hour"]; // Float variable that holds current hour
  289.     Gh1_hr = hr;
  290.     const int mn = doc["Min"]; // Float variable that holds current minute
  291.     Gh1_mn = mn;
  292.    
  293.     // Print the received data for debugging
  294.     //Serial.print(String(pin_stat));
  295.     //Serial.print(String(t));
  296.     //Serial.println(String(h));
  297.     // Send acknowledgement
  298.     // webSocket.sendTXT("OK");
  299.        
  300.   //  Serial.print("LED = ");
  301.   //  Serial.print("\t");
  302.   //  Serial.print(pin_stat);
  303.   //  Serial.print("\t");
  304.    
  305.     Serial.print("Temp = ");
  306.     Serial.print(t);
  307.     Serial.print("\t");
  308.  
  309.     Serial.print("Pressure = ");
  310.     Serial.print(p);
  311.     Serial.print("\t");
  312.    
  313.     Serial.print("Humidity = ");
  314.     Serial.println(h);
  315.  
  316.     Serial.print("Time = ");
  317.     Serial.print(hr);
  318.     Serial.print(":");
  319.     Serial.print(mn);
  320.     Serial.print("\t");
  321.  
  322.     Serial.print("Battery = ");
  323.     Serial.println(b);
  324.  
  325.     Serial.println();
  326.    
  327.   } // end if (type == WStype_TEXT)
  328. } // end void webSocketEvent
  329.