Skip to content

feature request / example code request: website by esp32 server, plus remote control also of esp8266 clients #4110

@dsyleixa

Description

@dsyleixa

feature request / example code request for noobs:
code for a website by esp32 with buttons, connect with an extra remote esp8266 client and contol remote pins.
Problems:

  • no example code in this repo available how to connect an esp8266 to an esp32 web-or wifiserver over a website,
  • different source codes for esp8266 (!!)-server(!!) and esp8266 clients to connect to each other work fine, but cannot be ported to work with an esp32 server.

e.g., to start from:
https://lastminuteengineers.com/creating-esp32-web-server-arduino-ide/
now with 1st button still for esp32 LED_BUILTIN (that part of course works already)
but 2nd button instead for remote esp8266 client LED_BUILTIN

what I tried (but failed):
problem:
both programs run, but esp8266 client can never connect to esp32 server/website.
So a working example for all noobs in this repo would be highly appreciated.
If already exists somewhere: a link would be appreciated.

ESP32 Server:

// Create A Simple ESP32 Web Server In Arduino IDE
// https://lastminuteengineers.com/creating-esp32-web-server-arduino-ide/

#include <WiFi.h>
#include <WiFiClient.h>
#include <ESPmDNS.h>
#include <ArduinoOTA.h>
#include <WebServer.h>
//#include <WiFiServer.h>

String version = "0.03a";

/*Put your SSID & Password*/
const char* ssid = "WLAN";  // Enter SSID here
const char* password = "18658";  //Enter Password here

char www_username[64] = "admin";
char www_password[64] = "esp32";

IPAddress   this_ip(192, 168, 2, 202);       // <<< static local IP of this ESP-webserver
IPAddress   gateway(192, 168, 2, 1);         // <<< LAN Gateway IP
IPAddress   subnet(255, 255, 255, 0);        // <<< LAN Subnet Mask

#define wwwport 8008
#define wifiport 8081  // Port für die esp clients
WebServer  webserver(wwwport);  // www website: website http port 
WebServer  server(wifiport);     // client comm: router wifi port  

// allows you to set the realm of authentication Default:"Login Required"
const char* www_realm = "Custom Auth Realm";
// the Content of the HTML response in case of Unautherized Access Default:empty
String authFailResponse = "Authentication Failed";

uint8_t LED1pin = LED_BUILTIN;
bool LED1status = LOW;

uint8_t LED2pin = 12;
bool LED2status = LOW; // c4out1

volatile int8_t  c4out1=0, C4OUT2=0, C4OUT3=0; // Client4; actual output pin states; stop=0, fwd=1, rev=-1;


//----------------------------------------------------------
void handleNotFound() {
 
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += webserver.uri();
  message += "\nMethod: ";
  message += (webserver.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += webserver.args();
  message += "\n";

  for (uint8_t i = 0; i < webserver.args(); i++) {
    message += " " + webserver.argName(i) + ": " + webserver.arg(i) + "\n";
  }

  webserver.send(404, "text/plain", message);
 
}


//----------------------------------------------------------
void setup() {
  Serial.begin(115200);
  delay(1000);
  
  pinMode(LED1pin, OUTPUT);
  pinMode(LED2pin, OUTPUT);

  Serial.println("Connecting to ");
  Serial.println(ssid);

  //connect to your local wi-fi network
  WiFi.begin(ssid, password);
  WiFi.config(this_ip, gateway, subnet);   // static IP  

  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());


  ArduinoOTA.begin();
  webserver.on("/", []() {
    if (!webserver.authenticate(www_username, www_password))
      //Basic Auth Method with Custom realm and Failure Response
      //return webserver.requestAuthentication(BASIC_AUTH, www_realm, authFailResponse);
      //Digest Auth Method with realm="Login Required" and empty Failure Response
      //return webserver.requestAuthentication(DIGEST_AUTH);
      //Digest Auth Method with Custom realm and empty Failure Response
      //return webserver.requestAuthentication(DIGEST_AUTH, www_realm);
      //Digest Auth Method with Custom realm and Failure Response
    {
      return webserver.requestAuthentication(DIGEST_AUTH, www_realm, authFailResponse);
    }
    handle_OnConnect();
  });
  
 /*
  webserver.on("/inline", []() {
    webserver.send(200, "text/plain", "this works as well");
  });
 */ 
 
  webserver.on("/led1on", handle_led1on);
  webserver.on("/led1off", handle_led1off);  
  webserver.on("/led2on", handle_led2on);
  webserver.on("/led2off", handle_led2off);  
  webserver.onNotFound(handle_NotFound);
  webserver.begin();  
  Serial.println("HTTP webserver started");

  server.on("/client/client1/", handleClientIOs);
  server.on("/client/client4/", handleClientIOs);
  server.begin();
  Serial.println("ESP server started");
}


//----------------------------------------------------------
void loop() {
  ArduinoOTA.handle();
  
  webserver.handleClient();
  if(LED1status)
  {digitalWrite(LED1pin, HIGH);}
  else
  {digitalWrite(LED1pin, LOW);}

  // LED2 jetzt nicht mehr lokal, sondern auf remote ESP8266 
  /*
  if(LED2status)
  {digitalWrite(LED2pin, HIGH);}
  else
  {digitalWrite(LED2pin, LOW);}
  */

  handleClientIOs();
  delay(1000);
}


//----------------------------------------------------------
void handle_OnConnect() {
  LED1status = LOW;
  LED2status = LOW;
  Serial.println("GPIO13 Status: OFF | GPIO12 Status: OFF");
  webserver.send(200, "text/html", SendHTML(LED1status,LED2status)); 
}

//----------------------------------------------------------
void handle_led1on() {
  LED1status = HIGH;
  Serial.println("GPIO13 Status: ON");
  webserver.send(200, "text/html", SendHTML(true,LED2status)); 
}

void handle_led1off() {
  LED1status = LOW;
  Serial.println("GPIO13 Status: OFF");
  webserver.send(200, "text/html", SendHTML(false,LED2status)); 
}

//----------------------------------------------------------
void handle_led2on() {
  LED2status = HIGH;
  c4out1 = HIGH;
  Serial.println("clientIO Status: ON");
  handleClientIOs();
  webserver.send(200, "text/html", SendHTML(LED1status,true)); 
}

void handle_led2off() {
  LED2status = LOW;
  c4out1 = LOW;
  Serial.println("clientIO Status: OFF");
  handleClientIOs();
  webserver.send(200, "text/html", SendHTML(LED1status,false)); 
}

//----------------------------------------------------------
void handle_NotFound(){
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += webserver.uri();
  message += "\nMethod: ";
  message += (webserver.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += webserver.args();
  message += "\n";

  for (uint8_t i = 0; i < webserver.args(); i++) {
    message += " " + webserver.argName(i) + ": " + webserver.arg(i) + "\n";
  }

  webserver.send(404, "text/plain", message);  
  //webserver.send(404, "text/plain", "Not found");
}

//----------------------------------------------------------
String SendHTML(uint8_t led1stat,uint8_t led2stat){
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>LED Control</title>\n";
  ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; /*text-align: center*/;}\n";   // text-align
  ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
  //ptr +=".button {display: block;width: 80px;background-color: #3498db;border: none;        color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";

  ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
  ptr +="</style>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<h1>ESP32 Web Server</h1>\n";
  ptr +="<h3>Using Station(STA) Mode</h3>\n";
  
  ptr +="<h1><p>version=" + version + "</p></h1><br>\n";

  ptr+="<p>";
  if(led1stat) {ptr +="LED1 Status:  ON_ ";}  
  else         {ptr +=" LED1 Status: OFF ";}  

  ptr += ("<a href=\" /led1on\"\"> <button style=\"height:70px;width:140px\" > ON  </button></a>  ");
  ptr += ("<a href=\" /led1off\"\"> <button style=\"height:70px;width:140px\" >  OFF  </button></a> ");
  ptr+="</p>";

  ptr+="<br><br><p>";
  if(led2stat) {ptr +="LED2 Status:  ON_ ";}  
  else         {ptr +=" LED2 Status: OFF ";}   
  ptr += ("<a href=\" /led2on\"\"> <button style=\"height:70px;width:140px\" > ON  </button></a>  ");
  ptr += ("<a href=\" /led2off\"\"> <button style=\"height:70px;width:140px\" >  OFF  </button></a> ");
  ptr+="</p>";
  
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

//----------------------------------------------------------------------------

void handleClientIOs() {    
  
  //printUrlArg(); //fuer Debug Zwecke
  
  double ftmp; 
  String msgtok;
   
  //Werte auch bei Url-Aufruf zurückgeben

  String message="***";
  
  message += "&c4out1="+(String)c4out1 ;   
  message += "&LED2status="+(String)LED2status ; // alias
  message += ";###";
  Serial.println(message);
  server.send(200, "text/plain", message);
}

ESP8288 remote Client:

/*  ESP8266 NodeMCU
    ESP8266WiFi Client für Remote Sensor Werte
    Client 4, Port 8081, wifi server .202
    Arduino IDE 1.8.9
*/

char * clientname = "Client 4"; //
char * ver = "4.014-";

//----------------------------------------------------------------------------
#include <Wire.h>

#define ESPSDA   D2   // GPIO4 
#define ESPSCL   D1   // GPIO5 

//----------------------------------------------------------------------------
// IO pins
//----------------------------------------------------------------------------
#define PIN_OUT0        D6
#define PIN_OUT1        LED_BUILTIN
#define PIN_OUT2        D8


//----------------------------------------------------------------------------
// OLED SSD1306

#include <ESP_SSD1306.h>    // Modification of Adafruit_SSD1306 for ESP8266 compatibility
#include <Adafruit_GFX.h>   // Needs a little change in original Adafruit library (See README.txt file)
#include <Fonts/FreeMono9pt7b.h>
#include <Fonts/FreeMono8pt7b.h>

ESP_SSD1306    display(-1);


//----------------------------------------------------------------------------
// outputs + signals

int16_t  c4out0=0,
         c4out1=0,
         c4out2=0;

int32_t  timeoutcnt;

//----------------------------------------------------------------------------
#include <ESP8266WiFi.h>

/*Put your SSID & Password*/
const char* ssid = "WLAN";  // Enter SSID here
const char* password = "18658";  //Enter Password here


const char* hostIP   = "192.168.2.202"; // Server der die temperatur empfangen soll
const int   wifiPort = 8081;  // Port für die esp clients
const char* script   = "/client/client4/"; // URL/Verzeichnis das wir gewaehlt haben


//----------------------------------------------------------------------------
const int  MAXLEN = 1024;
const int  TOKLEN = 64;

int16_t  strstrpos(char * haystack,  char * needle)   // find 1st occurance of substr in str
{
   char *p = strstr(haystack, needle);
   if (p) return p - haystack;
   return -1;   // Not found = -1.
}


//-------------------------------------------------------
char * cstringarg( char* haystack, char* vname, char* sarg ) {
  int i = 0, pos = -1;
  unsigned char  ch = 0xff;
  const char*  kini = "&";       // start of varname: '&'
  const char*  kin2 = "?";       // start of varname: '?'
  const char*  kequ = "=";       // end of varname, start of argument: '='
  char  needle[TOKLEN] = "";     // complete pattern:  &varname=abc1234

  strcpy(sarg, "");
  strcpy(needle, kini);
  strcat(needle, vname);
  strcat(needle, kequ);
  pos = strstrpos(haystack, needle);
  if (pos == -1) {
    needle[0] = kin2[0];
    pos = strstrpos(haystack, needle);
    if (pos == -1) return sarg;
  }
  pos = pos + strlen(vname) + 2; // start of value = kini+vname+kequ
  while ( (ch != '&') && (ch != '\0') ) {
    ch = haystack[pos + i];
    if ( (ch == '&') || (ch == ';') || (ch == '\0') || (ch == '\n') 
         || (ch == ' ') // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< for login!
         || (i + pos >= strlen(haystack)) || (i > TOKLEN - 1) ) {
      sarg[i] = '\0';
      return sarg;
    }
    if ( (ch != '&') ) {
      sarg[i] = ch;
      i++;
    }
  }
  return sarg;
}




//----------------------------------------------------------------------------

char * dashboard(int mode) {
   // OLED
}


//----------------------------------------------------------------------------
// SETUP
//----------------------------------------------------------------------------

void setup() {

   Serial.begin(115200);
   delay(10);

   pinMode( PIN_OUT0, OUTPUT);
   pinMode( PIN_OUT1, OUTPUT);
   pinMode( PIN_OUT2, OUTPUT);
   pinMode( LED_BUILTIN, OUTPUT);  // alias

   // i2c + OLED
   //Wire.begin(ESPSDA,ESPSCL); // SDA, SCL
   Wire.begin(); // default
   delay(1);

   display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
   display.setRotation(2);

   display.setFont();
   display.setTextSize(1);
   display.setTextColor(WHITE);
   display.clearDisplay();
   display.setCursor( 0, 0);  display.print("OLED TEST OK");
   display.display();

   // WiFi start
   Serial.println();
   Serial.println();
   Serial.print("Verbinde mich mit Netz: ");
   Serial.println(ssid);

   WiFi.begin(ssid, password);

   while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
   }

   Serial.println("");
   Serial.println("WiFi Verbindung aufgebaut");
   Serial.print("Eigene IP des ESP-Moduls: ");
   Serial.println(WiFi.localIP() );

   display.setCursor(0,15);  display.print("WiFi Verbindung aufgebaut");
   display.display();
   delay(500); // debug
}


//----------------------------------------------------------------------------
// LOOP
//----------------------------------------------------------------------------

// Bei deepSleep wird die loop Schleife eigentlich nur einmal durchlaufen

void loop() {

   static float ftmp;
   static unsigned long tms=0;
   static unsigned long dtms=0;
   unsigned long timeout;

   if(timeoutcnt>60*30) { // > 30min timeout
      Serial.println("\n timeout => restart \n");
      display.print("timeout => restart");
      ESP.restart();
   }

   WiFiClient client;
   delay(10);

   //---------------------------------------
   // msg string
   String vals = "";  // for sensor values

   //---------------------------------------
   // connect to ESP8266 webserver
   int versuche=1;
   int IOres=0;

   do
   {
      Serial.print("Verbindungsaufbau zu Server ");
      Serial.println(hostIP);

      IOres =client.connect(hostIP, wifiPort);
      if (!IOres) {
         versuche++;
         timeoutcnt++;
         dashboard(1);

         Serial.println("Verbindungsaufbau nicht moeglich!!!");
         if (versuche>10) {
            Serial.println("Klappt nicht, versuche es spaeter noch mal!");
            client.stop();
            delay(1000);
         }
      }
      delay(1000);
   } while (IOres!=1);

   //---------------------------------------
   // msg string to server

   String url = script; //Url wird zusammengebaut: script = "/client/client4/";
   url += "?pw=";
   url += password;

   url += vals;

   Serial.print("Folgende URL wird aufgerufen: ");
   Serial.println((String)hostIP + "?pw="+"*****"+vals);

   client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                "hostIP: " + hostIP + "\r\n" +
                "Connection: close\r\n\r\n");


   timeout= millis();
   while ( !client.available() )  {
      timeoutcnt+=1;
      if( (millis()-timeout < 20000)) {
         Serial.print("Timeout svr count: "); Serial.println( timeoutcnt );
         Serial.println("Rueckmeldung von Server verzoegert, ich warte noch...");
         //client.stop();

         delay(1000);
      }
      else {
         Serial.println("\nAbbruch, keine Rueckantwort vom Server!\n");
         break;
      }
   }

   timeout=millis();
   String msgline;

   Serial.println("Rueckgabe vom Server:\n");
   if(client.available()) {
      timeoutcnt=0;
      while(client.available()) {
         msgline = client.readStringUntil('\r');
         //Serial.print("msgline="); Serial.println(msgline);
      }
      String Sargval="";
      char carg[TOKLEN], ctok[TOKLEN], cmsg[MAXLEN];
      Sargval="";
      msgline.toCharArray(cmsg, MAXLEN-1);
      Serial.println();
      Serial.print("cmsg="); Serial.println(cmsg);

      c4out0=0; // default
      c4out1=0;
      c4out2=0;
      if(cmsg!="") {
         cstringarg(cmsg, "c4out0", carg);  // alert pin (D6) switch on/off
         Sargval=(String)carg;
         if(Sargval!="") {
            c4out0=Sargval.toInt();
         }

         cstringarg(cmsg, "c4out1", carg);  // switch on/off
         Sargval=(String)carg;
         if(Sargval!="") {
            c4out1=Sargval.toInt();
         }

         cstringarg(cmsg, "c4out2", carg);  // switch on/off
         Sargval=(String)carg;
         if(Sargval!="") {
            c4out2=Sargval.toInt();
         }
      }

      // debug
      Serial.println( (String)"c4out0=" + (String)c4out0 + " <<<<<<<<<<<<" );
      Serial.println( (String)"c4out1=" + (String)c4out1 + " <<<<<<<<<<<<" );
      Serial.println( (String)"c4out2=" + (String)c4out2 + " " );

      if(c4out0==0) digitalWrite(PIN_OUT0, LOW); else digitalWrite(PIN_OUT0, HIGH);
      if(c4out1==0) digitalWrite(PIN_OUT1, LOW); else digitalWrite(PIN_OUT1, HIGH);
      if(c4out2==0) digitalWrite(PIN_OUT2, LOW); else digitalWrite(PIN_OUT2, HIGH);

   }  // if(client.available())
   client.flush();
   client.stop();

   Serial.println("\nPausiere jetzt ... \n");
   delay(3000);
}

(PS, additionally also reading esp8266 client remote values would be highly appreciated)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions