ESP8266 / ESP32 stand alone webserver, cloud MQTT

Scenario:
I have to build a timer relay for the solar system of a friend of mine.

  • If the voltage exceeds a certain ammount then start timer.
    when times expires then write GPIO high.
  • If the voltage falls short of a certain ammount then start timer.
    when times expires then write GPIO low.

for learning purpouses I was wondering how difficult it was to add:

  • local webserver with pushbutton at my frineds house (behind NAT)
  • preferaby https if possible, if memory allows …
  • integrate it to my HA over cloud / tunnel …

webserver (example):

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp32-esp8266-web-server-outputs-momentary-switch/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/

#ifdef ESP32
  #include <WiFi.h>
  #include <AsyncTCP.h>
#else
  #include <ESP8266WiFi.h>
  #include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>

// REPLACE WITH YOUR NETWORK CREDENTIALS
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

const int output = 2;

// HTML web page
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
  <head>
    <title>ESP Pushbutton Web Server</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
      body { font-family: Arial; text-align: center; margin:0px auto; padding-top: 30px;}
      .button {
        padding: 10px 20px;
        font-size: 24px;
        text-align: center;
        outline: none;
        color: #fff;
        background-color: #2f4468;
        border: none;
        border-radius: 5px;
        box-shadow: 0 6px #999;
        cursor: pointer;
        -webkit-touch-callout: none;
        -webkit-user-select: none;
        -khtml-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
        -webkit-tap-highlight-color: rgba(0,0,0,0);
      }  
      .button:hover {background-color: #1f2e45}
      .button:active {
        background-color: #1f2e45;
        box-shadow: 0 4px #666;
        transform: translateY(2px);
      }
    </style>
  </head>
  <body>
    <h1>ESP Pushbutton Web Server</h1>
    <button class="button" onmousedown="toggleCheckbox('on');" ontouchstart="toggleCheckbox('on');" onmouseup="toggleCheckbox('off');" ontouchend="toggleCheckbox('off');">LED PUSHBUTTON</button>
   <script>
   function toggleCheckbox(x) {
     var xhr = new XMLHttpRequest();
     xhr.open("GET", "/" + x, true);
     xhr.send();
   }
  </script>
  </body>
</html>)rawliteral";

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

AsyncWebServer server(80);

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("WiFi Failed!");
    return;
  }
  Serial.println();
  Serial.print("ESP IP Address: http://");
  Serial.println(WiFi.localIP());
  
  pinMode(output, OUTPUT);
  digitalWrite(output, LOW);
  
  // Send web page to client
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", index_html);
  });

  // Receive an HTTP GET request
  server.on("/on", HTTP_GET, [] (AsyncWebServerRequest *request) {
    digitalWrite(output, HIGH);
    request->send(200, "text/plain", "ok");
  });

  // Receive an HTTP GET request
  server.on("/off", HTTP_GET, [] (AsyncWebServerRequest *request) {
    digitalWrite(output, LOW);
    request->send(200, "text/plain", "ok");
  });
  
  server.onNotFound(notFound);
  server.begin();
}

void loop() {
 
}

and here and example for the relays:

# https://forum.arduino.cc/t/triggering-relays-with-a-voltage-sensor/1082239/7
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
// Define analog input
#define ANALOG_IN_PIN01 A0
#define ANALOG_IN_PIN02 A3

// Define output pins
#define Relay01 5
#define Relay02 6
#define Relay03 7
#define Relay04 8
#define Relay05 9
#define Relay06 10
#define Relay07 11
#define Relay08 12
 
// Floats for ADC voltage & Input voltage
float adc_voltage01 = 0.0;
float adc_voltage02 = 0.0;
float in_voltage01 = 0.0;
float in_voltage02 = 0.0;
 
// Floats for resistor values in divider (in ohms)
float R1 = 30000.0;
float R2 = 7500.0;
 
// Float for Reference Voltage
float ref_voltage = 5.0;
 
// Integer for ADC value
int adc_value01 = 0;
int adc_value02 = 0;

void setup()
{
  // Setup Serial Monitor
  Serial.begin(9600);
  Serial.println("DC Voltage Test");
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))
  {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }
  display.clearDisplay();
 
  // Define digital pins as OUTPUT
  pinMode(Relay01, OUTPUT);
  pinMode(Relay02, OUTPUT);
  pinMode(Relay03, OUTPUT);
  pinMode(Relay04, OUTPUT);
  pinMode(Relay05, OUTPUT);
  pinMode(Relay06, OUTPUT);
  pinMode(Relay07, OUTPUT);
  pinMode(Relay08, OUTPUT);
 
}
 
void loop() {
  // Read the Analog Input
  adc_value01 = analogRead(ANALOG_IN_PIN01);
  adc_value02 = analogRead(ANALOG_IN_PIN02);
  
  // Determine voltage at ADC input
  adc_voltage01 = (adc_value01 * ref_voltage) / 1024.0;
  adc_voltage02 = (adc_value02 * ref_voltage) / 1024.0;
 
  // Calculate voltage at divider input
  in_voltage01 = adc_voltage01 / (R2 / (R1 + R2)) ;
  in_voltage02 = adc_voltage02 / (R2 / (R1 + R2)) ;

  //Activate Relays based on input voltage
  if (in_voltage01 > 0.5 && in_voltage01 < 2){
    digitalWrite(Relay01, LOW);
  }    
  else{    
    digitalWrite(Relay01, HIGH);
  } 
  if (in_voltage01 > 3 && in_voltage01 < 4.5){
    digitalWrite(Relay02, LOW);
  }
  else{
    digitalWrite(Relay02, HIGH);  
  }
  if (in_voltage01 > 5.5 && in_voltage01 < 8){
    digitalWrite(Relay03, LOW);
  }          
  else{
    digitalWrite(Relay03, HIGH);
  }
  if (in_voltage01 > 9){     
    digitalWrite(Relay04, LOW);
  }
  else{
    digitalWrite(Relay04, HIGH);
  }
     if (in_voltage02 > 0.5 && in_voltage02 < 2){
    digitalWrite(Relay05, LOW);
  }    
  else{    
    digitalWrite(Relay05, HIGH);
  } 
  if (in_voltage02 > 3 && in_voltage02 < 4.5){
    digitalWrite(Relay06, LOW);
  }
  else{
    digitalWrite(Relay06, HIGH);  
  }
  if (in_voltage02 > 5.5 && in_voltage02 < 8){
    digitalWrite(Relay07, LOW);
  }          
  else{
    digitalWrite(Relay07, HIGH);
  }
  if (in_voltage02 > 9){     
    digitalWrite(Relay08, LOW);
  }
  else{
    digitalWrite(Relay08, HIGH);
  }  
               
   // Print results to Serial Monitor to 1 decimal place
  Serial.print("Input Voltage = ");
  Serial.println(in_voltage01, 1);
  
  //Display static text on OLED display
  display.setCursor(2, 2);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.println("Input Voltage 1");

  display.setCursor(2, 33);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.println("Input Voltage 2");

  //Display voltage readings on OLED display
  display.setCursor(50, 13);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.print(in_voltage01, 1);
  display.println(" V");
  
  display.setCursor(50, 44); 
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.print(in_voltage02, 1);
  display.println(" V");  
  
  display.display();
  delay(500);
  display.clearDisplay();
 
}

questions:

  • would a esp8266 also work?
  • how to do MQTT over cloud, best options?
  • are there any better code examples out there than mine?

Is this Home Assistant related?

woud you like to help?

Does Tasmota fit the bill?
ESPHome?

I am working currently with esphome.
Is this not the location to ask for configuration help here for esphome devices?

You have identified a number of issues that need to be addressed:
Hardware (yes, a ESP8266 will most likely suffice, but an ESP32 only costs a few cents more and offers added capacity should you wish to add functionality later)
Getting voltage values from the solar system - real time or delayed - direct or via cloud.
Software to glue it all together.
Remote access (networking, Dynamic DNS, routing)
Integration into HomeAssistant
Deciding where to put your decision logic and control - local or remote.

Warning: Asking AI will get you lots of outdated slop - home automation is one of the best examples of how misfunctional it can be. Best read actual up to date documentation and experiment, and understand what you are doing AND WHY.

You have given fairly generic examples in your question, getting bogged down in a lot of detail before you have outlined your bigger picture requirements.

Each of these portions is a challenge in its own. Others have done it. Following the documentation will get you there.

Are you going to be reading and switching very low voltages under 12 volts, or mains power? Your approach should be vastly different if you are switching solar batteries with kilowatts of power compared to a few square inch solar panel powering a single 16550 cell.

Get a plan. Define your requirements carefully. Bite off little chunks, get them working well, and then tie them in together. The detail you have given is not enough to give you specific directions to go in.

A good project to work together with your friend.

Ignore grumpy… If you put in some effort, show you are progressing, document your pitfalls, don’t take shortcuts with AI slop, quote your code in the forum so it is formatted properly, then we will probably jump in and offer suggestions.

Good luck.