I need help with a webserver project...



  • I need the clock... :( I have that same error every 5 / 7 minutes, it restarts and works for a few minutes again and so on...
    Maybe I can do some test without the clock to see if it is the cause of the problem...



  • @crazyhorse80 Maybe show the whole code you're running now?



  • @rop Here's what my full code looks like at the moment:

    #include <M5Stack.h>
    #include <ezTime.h>
    #include <M5ez.h>
    
    #include <WiFi.h>
    #include <WiFiClient.h>
    #include <WebServer.h>
    #include <ESPmDNS.h>
    
    #include "images.h"
    
    #define MAIN_DECLARED
    
    WebServer rDserver(1980);
    
    byte   remYear = 0;           // Current PVControl server Year
    byte   remMonth = 0;          // Current PVControl server Month
    byte   remDay = 0;            // Current PVControl server Day
    byte   remHour = 0;           // Current PVControl server Hour
    byte   remMinute = 0;         // Current PVControl server Minute
    float  GenE = 0;              // Last Generated Energy
    float  UseE = 0;              // Last Consumed Energy
    float  TtGE = 0;              // Last to the Grid Energy
    float  FtGE = 0;              // Last from the Grid Energy
    int    GenP = 0;              // Last Generated Power
    int    UseP = 0;              // Last Consumed Power
    int    NetP = 0;              // Last Net Power
    
    void setup() {
      #include <themes/default.h>
      #include <themes/dark.h>
      ezt::setDebug(NONE);
      ez.begin();
      if (ez.wifi.indexForSSID("xxx") == -1) {
        ez.wifi.add("xxx", "xxx");
        ez.wifi.writeFlash();
      }
    
      MDNS.begin("remdisplay1");
    
      rDserver.on("/", handleRoot);
      rDserver.onNotFound(handleNotFound);
      rDserver.begin();
      
      dacWrite(25,0); // Speaker mute
    
      ez.addEvent(serveClients, 3000);
    
      ezMenu mainmenu("remDisplay");
      //  mainmenu.txtSmall();
      mainmenu.addItem("PVControl", remDisplay);
      mainmenu.addItem("Settings", mainmenu_image);
      //  mainmenu.addItem("Updates via https", mainmenu_ota);
      mainmenu.upOnFirst("last|up");
      mainmenu.downOnLast("first|down");
      mainmenu.run();
    }
    
    void loop() {
      
    }
    
    uint16_t serveClients() {
      rDserver.handleClient();
      return 50;
    }
    
    void handleRoot() {
      for (uint8_t i = 0; i < rDserver.headers(); i++) { //debug only
        Serial.print(" ");
        Serial.print(rDserver.headerName(i));
        Serial.print(": ");
        Serial.println(rDserver.header(i));
      }
      for (uint8_t i = 0; i < rDserver.args(); i++) { //debug only
        Serial.print(" ");
        Serial.print(rDserver.argName(i));
        Serial.print(": ");
        Serial.println(rDserver.arg(i));
      }
    
      if(rDserver.args() == 7) {
          if((rDserver.argName(0) != "r") || (rDserver.argName(1) != "da")
            || (rDserver.argName(2) != "ti") || (rDserver.argName(3) != "v1")
              || (rDserver.argName(4) != "v2") || (rDserver.argName(5) != "v3")
                || (rDserver.argName(6) != "v4")) {
            rDserver.send(400, "text/plain", " Bad Request");
            return;
          }
          else {
            rDserver.send(200, "text/plain", " OK");
    
            remYear = atoi(rDserver.arg(1).substring(0,3).c_str());
            remMonth = atoi(rDserver.arg(1).substring(4,5).c_str());
            remDay = atoi(rDserver.arg(1).substring(6,7).c_str());
            remHour = atoi(rDserver.arg(2).substring(0,1).c_str());
            remMinute = atoi(rDserver.arg(2).substring(2,3).c_str());
            GenE = atoi(rDserver.arg(3).c_str());
            GenP = atoi(rDserver.arg(4).c_str());
            UseE = atoi(rDserver.arg(5).c_str());
            UseP = atoi(rDserver.arg(6).c_str());
            NetP = GenP - UseP;    // Last Net Power
            remDisplay();
          }
      }
      else {
        rDserver.send(400, "text/plain", " Bad Request");
        return;
      }
    }
    
    void handleNotFound() {
      String message = "File Not Found\n\n";
      message += "URI: ";
      message += rDserver.uri();
      message += "\nMethod: ";
      message += (rDserver.method() == HTTP_GET) ? "GET" : "POST";
      message += "\nArguments: ";
      message += rDserver.args();
      message += "\n";
      for (uint8_t i = 0; i < rDserver.args(); i++) {
        message += " " + rDserver.argName(i) + ": " + rDserver.arg(i) + "\n";
      }
      rDserver.send(404, "text/plain", message);
    }
    
    void mainmenu_image() {
      ezMenu images;
      images.imgBackground(TFT_BLACK);
      images.imgFromTop(40);
      images.imgCaptionColor(TFT_WHITE);
      images.addItem(sysinfo_jpg, "System Information", sysInfo);
      images.addItem(wifi_jpg, "Built-in wifi & other settings", ez.settings.menu);
      images.addItem(wifi_jpg, "WiFi Settings", ez.wifi.menu);
      images.addItem(about_jpg, "About remDisplay", about);
      images.addItem(sleep_jpg, "Power Off", powerOff);
      images.addItem(return_jpg, "Back");
      images.run();
    }
    
    void powerOff() {
      m5.powerOFF();
    }
    
    void about() {
      ez.msgBox("About remDisplay", "");
    }
    
    String exit_buttonrD = "Exit";
    
    void remDisplay() {
      remDisplayPage1();
      while (true) {
        String btn = ez.buttons.poll();
        if (btn == "up") remDisplayPage1();
        if (btn == "down") remDisplayPage2();
        if (btn == "Exit") break;
      }
    }
    
    void remDisplayPage1() {
      const byte tab = 120;
      ez.screen.clear();
      ez.header.show("PVControl  (1/2)");
      ez.buttons.show("#" + exit_buttonrD + "#down");
      ez.canvas.font(&FreeSans9pt7b);
      ez.canvas.lmargin(10);
      ez.canvas.println("");
      ez.canvas.print("Produzione:");
      ez.canvas.x(tab);ez.canvas.print(GenP); ez.canvas.println(" W");
      ez.canvas.x(tab); ez.canvas.print(GenE / 1000); ez.canvas.println(" kWh");
      ez.canvas.print("Consumo:");
      ez.canvas.x(tab); ez.canvas.print(UseP); ez.canvas.println(" W");
      ez.canvas.x(tab); ez.canvas.print(UseE / 1000); ez.canvas.println(" kWh");
      ez.canvas.print("Immissione:");
      ez.canvas.x(tab);
      if(NetP > 0)
        ez.canvas.print(NetP);
      else
        ez.canvas.print("0");
      ez.canvas.println(" W");
      ez.canvas.x(tab); ez.canvas.println(" kWh");
      ez.canvas.print("Prelievo:");
      ez.canvas.x(tab);
      if(NetP < 0)
        ez.canvas.print(abs(NetP));
      else
        ez.canvas.print("0");
      ez.canvas.println(" W");
      ez.canvas.x(tab); ez.canvas.println(" kWh");
    }
    
    void remDisplayPage2() {
      const byte tab = 140;
      ez.screen.clear();
      ez.header.show("PVControl  (2/2)");
      ez.buttons.show("up#" + exit_buttonrD + "#");
      ez.canvas.font(&FreeSans9pt7b);
      ez.canvas.lmargin(10);
      ez.canvas.println("");
      ez.canvas.print("Free RAM:");  ez.canvas.x(tab);  ez.canvas.println(String((long)ESP.getFreeHeap()) + " bytes");
      ez.canvas.print("Min. free seen:");  ez.canvas.x(tab); ez.canvas.println(String((long)esp_get_minimum_free_heap_size()) + " bytes");
    }
    

    It's only a part of what I want to achieve and here I'll try to explain what my project should do when it'll be complete:
    every minute my M5Stack will receive from another Arduino board an HTTP GET request with data and it stores them in global variables and eventually does some operation with them;
    it should have a multi-page view to show data received and stored in variables (one displays data in numeric form, another will display them in graphs, another one will only change screen background color and make some noise based on data received, and maybe some more);
    it also should have access to the menus to change wi-fi and screen preferences and some more options related to my program (sound volume, default page to display on startup and so on).
    I'd also like to have some more widgets:
    one will have to show me if data received is older than one minute (it means I've lost connection with the Arduino board);
    another one will have to show the current energy billing band based on what time and day of week it is.
    The problem with M5ez, and ESP32 in general, is that I've no clue of where to put my code: do I have to do all in loop() function? Or should I register various functions with ez.addEvent()? Or should I do it some other way? I'm a bit confused... Can you show me a proof of concept application using M5ez (even if not related to my needs, so I could understand how it works)?



  • @crazyhorse80I need help with a webserver project... 中说:

    It's only a part of what I want to achieve and here I'll try to explain what my project should do when it'll be complete:

    • every minute my M5Stack will receive from another Arduino board an HTTP GET request with data and it stores them in global variables and eventually does some operation with them;
    • it should have a multi-page view to show data received and stored in variables (one displays data in numeric form, another will display them in graphs, another one will only change screen background color and make some noise based on data received, and maybe some more);
    • it also should have access to the menus to change wi-fi and screen preferences and some more options related to my program (sound volume, default page to display on startup and so on).
      I'd also like to have some more widgets:
    • one will have to show me if data received is older than one minute (it means I've lost connection with the Arduino board);
      another one will have to show the current energy billing band based on what time and day of week it is.

    The problem with M5ez, and ESP32 in general, is that I've no clue of where to put my code: do I have to do all in loop() function? Or should I register various functions with ez.addEvent()? Or should I do it some other way? I'm a bit confused... Can you show me a proof of concept application using M5ez (even if not related to my needs, so I could understand how it works)?

    Zooming out and looking at your propject:

    • Have you considered using mqtt ? I'm no expert, but it seems built for jobs that involve getting values from A to B, figuring out if the sending side is still there, etc etc. All sorts of Arduino libraries for sending and receiving end.

    • How to switch between functionality that runs concurrently is always an issue, and there are often more ways to accomplish the same thing. So don't worry too much if it seems hard now. It gets easier to wrap one's head around the program flow with experience, and it sucks in the beginning.

    Specifically for this project:

    • To make widgets, after reading the user manual it's probably best to study the clock-related code in M5ez.cpp to see how it does its widget things.

    • All web handling is done by the webserver code which you have placed in M5ez's main loop with ez.addEvent. The difference between placing code there and placing it in your sketch's loop() function is that loop() is not called when M5ez is waiting for input (like in menus, msgBox, etc etc).

    • There is a way to add your own items to the M5ez settings menu. It's in the manual, but again: also look at how it's done inside M5ez.cpp, for example with the clock code.

     

    Good luck!



  • Thanks for your help, I'll try to follow your directions in the following days.