OTA with ESP32 as AP

rsappia
Posts: 3
Joined: Wed Jul 31, 2019 8:32 pm

OTA with ESP32 as AP

Postby rsappia » Wed Jul 31, 2019 8:48 pm

Hi there, I am having the following use case scenario:

The ESP32 is placed within a case that cannot be easily opened. Therefore, in case I need to update its firmware, OTA is a must. The second point, the ESP32 will be working without a Wifi network in reach. I thought it would be possible to setup the OTA code to set the ESP32 as AP so it can provide its own wifi net and I could just upload my bin file without needing nothing else than a laptop and the ESP32..
I managed to configure the ESP32 as AP, I can access its webpage but when I try to upload the file, I got always the message that the page hasnt been found ("serverIndex/Update Not found").

I have used the code shown here: https://randomnerdtutorials.com/esp32- ... ogramming/
and replaced the first part where the wifi is started to be set as AP.

  1.  /* OTAWebUpdater.ino Example from ArduinoOTA Library
  2.  * Rui Santos
  3.  * Complete Project Details https://randomnerdtutorials.com
  4.  */
  5.  
  6. #include <WiFi.h>
  7. #include <WiFiClient.h>
  8. #include <WebServer.h>
  9. #include <ESPmDNS.h>
  10. #include <Update.h>
  11.  
  12. const char* host = "esp32";
  13. const char* ssid = "REPLACE_WITH_YOUR_SSID";
  14. const char* password = "REPLACE_WITH_YOUR_PASSWORD";
  15.  
  16. WebServer server(80);
  17.  
  18. /*
  19.  * Login page
  20.  */
  21. const char* loginIndex =
  22.  "<form name='loginForm'>"
  23.     "<table width='20%' bgcolor='A09F9F' align='center'>"
  24.         "<tr>"
  25.             "<td colspan=2>"
  26.                 "<center><font size=4><b>ESP32 Login Page</b></font></center>"
  27.                 "<br>"
  28.             "</td>"
  29.             "<br>"
  30.             "<br>"
  31.         "</tr>"
  32.         "<td>Username:</td>"
  33.         "<td><input type='text' size=25 name='userid'><br></td>"
  34.         "</tr>"
  35.         "<br>"
  36.         "<br>"
  37.         "<tr>"
  38.             "<td>Password:</td>"
  39.             "<td><input type='Password' size=25 name='pwd'><br></td>"
  40.             "<br>"
  41.             "<br>"
  42.         "</tr>"
  43.         "<tr>"
  44.             "<td><input type='submit' onclick='check(this.form)' value='Login'></td>"
  45.         "</tr>"
  46.     "</table>"
  47. "</form>"
  48. "<script>"
  49.     "function check(form)"
  50.     "{"
  51.     "if(form.userid.value=='admin' && form.pwd.value=='admin')"
  52.     "{"
  53.     "window.open('/serverIndex')"
  54.     "}"
  55.     "else"
  56.     "{"
  57.     " alert('Error Password or Username')/*displays error message*/"
  58.     "}"
  59.     "}"
  60. "</script>";
  61.  
  62. /*
  63.  * Server Index Page
  64.  */
  65.  
  66. const char* serverIndex =
  67. "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
  68. "<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
  69.    "<input type='file' name='update'>"
  70.         "<input type='submit' value='Update'>"
  71.     "</form>"
  72.  "<div id='prg'>progress: 0%</div>"
  73.  "<script>"
  74.   "$('form').submit(function(e){"
  75.   "e.preventDefault();"
  76.   "var form = $('#upload_form')[0];"
  77.   "var data = new FormData(form);"
  78.   " $.ajax({"
  79.   "url: '/update',"
  80.   "type: 'POST',"
  81.   "data: data,"
  82.   "contentType: false,"
  83.   "processData:false,"
  84.   "xhr: function() {"
  85.   "var xhr = new window.XMLHttpRequest();"
  86.   "xhr.upload.addEventListener('progress', function(evt) {"
  87.   "if (evt.lengthComputable) {"
  88.   "var per = evt.loaded / evt.total;"
  89.   "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
  90.   "}"
  91.   "}, false);"
  92.   "return xhr;"
  93.   "},"
  94.   "success:function(d, s) {"
  95.   "console.log('success!')"
  96.  "},"
  97.  "error: function (a, b, c) {"
  98.  "}"
  99.  "});"
  100.  "});"
  101.  "</script>";
  102.  
  103. /*
  104.  * setup function
  105.  */
  106. void setup(void) {
  107.   Serial.begin(115200);
  108.  
  109.   // Connect to WiFi network
  110.   //WiFi.begin(ssid, password);
  111.  WiFi.softAP(ssid, password);
  112.   Serial.println("");
  113.  
  114.   IPAddress IP = WiFi.softAPIP();
  115.   Serial.print("AP IP address: ");
  116.   Serial.println(IP);
  117.  
  118.   /*use mdns for host name resolution*/
  119.   if (!MDNS.begin(host)) { //http://esp32.local
  120.     Serial.println("Error setting up MDNS responder!");
  121.     while (1) {
  122.       delay(1000);
  123.     }
  124.   }
  125.   Serial.println("mDNS responder started");
  126.   /*return index page which is stored in serverIndex */
  127.   server.on("/", HTTP_GET, []() {
  128.     server.sendHeader("Connection", "close");
  129.     server.send(200, "text/html", loginIndex);
  130.   });
  131.   server.on("/serverIndex", HTTP_GET, []() {
  132.     server.sendHeader("Connection", "close");
  133.     server.send(200, "text/html", serverIndex);
  134.   });
  135.   /*handling uploading firmware file */
  136.   server.on("/update", HTTP_POST, []() {
  137.     server.sendHeader("Connection", "close");
  138.     server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
  139.     ESP.restart();
  140.   }, []() {
  141.     HTTPUpload& upload = server.upload();
  142.     if (upload.status == UPLOAD_FILE_START) {
  143.       Serial.printf("Update: %s\n", upload.filename.c_str());
  144.       if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
  145.         Update.printError(Serial);
  146.       }
  147.     } else if (upload.status == UPLOAD_FILE_WRITE) {
  148.       /* flashing firmware to ESP*/
  149.       if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
  150.         Update.printError(Serial);
  151.       }
  152.     } else if (upload.status == UPLOAD_FILE_END) {
  153.       if (Update.end(true)) { //true to set the size to the current progress
  154.         Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
  155.       } else {
  156.         Update.printError(Serial);
  157.       }
  158.     }
  159.   });
  160.   server.begin();
  161. }
  162.  
  163. void loop(void) {
  164.   server.handleClient();
  165.   delay(1);
  166. }

Is there any hint you could provide me? may be a working example?

Thanks in advance!

ESP_Sprite
Posts: 9764
Joined: Thu Nov 26, 2015 4:08 am

Re: OTA with ESP32 as AP

Postby ESP_Sprite » Thu Aug 01, 2019 2:53 am

Well, if anything, you seem to be checking on "/update", with a lower-case u.

rsappia
Posts: 3
Joined: Wed Jul 31, 2019 8:32 pm

Re: OTA with ESP32 as AP

Postby rsappia » Thu Aug 01, 2019 3:59 am

ESP_Sprite wrote:
Thu Aug 01, 2019 2:53 am
Well, if anything, you seem to be checking on "/update", with a lower-case u.
Hi, thanks for answering. If you mean this from my comment, it was just illustrative, I didn't copy paste the error msg (:

boarchuz
Posts: 606
Joined: Tue Aug 21, 2018 5:28 am

Re: OTA with ESP32 as AP

Postby boarchuz » Thu Aug 01, 2019 2:29 pm

Do you mean that it's trying to upload to "http://x.x.x.x/serverIndex/update" (rather than "http://x.x.x.x/update")?
You'll have to figure out how to stop it going to the relative uri instead. Try removing the trailing / from your url (ie. go to "http://x.x.x.x/serverIndex" rather than "http://x.x.x.x/serverIndex/") or remove it from the ajax url (ie. "/update" -> "update").

machiel
Posts: 4
Joined: Wed Oct 09, 2019 1:29 pm

Re: OTA with ESP32 as AP

Postby machiel » Wed Oct 09, 2019 1:55 pm

I struggled with the same issue, need for an OTA firmware update functionality without registration to an existing WiFi network. And therefore, make use of the Access point configuration in the ESP.

Downsize of this setup is the lack of internet access. It’s not possible to make use of external web sources. In this case, the HTML has a reference to an external jquery (https://ajax.googleapis.com/ajax/libs/j ... ery.min.js) internet source that is not available with an Access Point configuration.
Therefore, I extended the code with an embedded jQuery 3.2.1 file. To keep is simple and not making the example unnecessarily large and complicated, I didn’t make use of spiff or an asynchronous webserver. For better performance and larger projects, I recommend ESPAsyncWebServer.


URL: https://www.dropbox.com/s/w3jvjdgs5o8wd ... P.ino?dl=0

Code: Select all

/* OTAWebUpdater.ino Example from ArduinoOTA Library
 * Rui Santos
 * Complete Project Details https://randomnerdtutorials.com
 * 20191009 Update: M.Mastenbroek - Added embedded jquery
 */
 
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>

const char* sw_version = "20191009";
const char* host = "esp32";
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";


/*	jquery.min.js version 3.2.1

	size of original js file:  85 KB
	size in this source file: 148 KB
	size on ESP:               30 KB
 
 */
#define jquery_min_js_v3_2_1_gz_len 30178
PROGMEM const char jquery_min_js_v3_2_1_gz[]  = {
0x1f,0x8b,   .................... 0x01,0x00
};

WebServer server(80);
 
/*
 * Login page
 */
const char* loginIndex =
 "<form name='loginForm'>"
    "<table width='20%' bgcolor='A09F9F' align='center'>"
        "<tr>"
            "<td colspan=2>"
                "<center><font size=4><b>ESP32 Login Page</b></font></center>"
                "<br>"
            "</td>"
            "<br>"
            "<br>"
        "</tr>"
        "<td>Username:</td>"
        "<td><input type='text' size=25 name='userid'><br></td>"
        "</tr>"
        "<br>"
        "<br>"
        "<tr>"
            "<td>Password:</td>"
            "<td><input type='Password' size=25 name='pwd'><br></td>"
            "<br>"
            "<br>"
        "</tr>"
        "<tr>"
            "<td><input type='submit' onclick='check(this.form)' value='Login'></td>"
        "</tr>"
    "</table>"
"</form>"
"<script>"
    "function check(form)"
    "{"
    "if(form.userid.value=='admin' && form.pwd.value=='admin')"
    "{"
    "window.open('/serverIndex')"
    "}"
    "else"
    "{"
    " alert('Error Password or Username')/*displays error message*/"
    "}"
    "}"
"</script>";
 
/*
 * Server Index Page
 */
 
const char* serverIndex =
"<script src='/jquery.min.js'></script>"
"Because the lack of an asynchronous webserver in this Arduino sketch like 'ESPAsyncWebServer', <br/>"
"both file 'serverIndex' and 'jquery.min.js' can't be read from the webserver at the same time. <br/><br/>"
"Your web browser probably requests those two files simultaneously and therefore <br/>"
"the javascript file failed to load. By a refresh of this page, the browser cash has already <br/>"
"load 'serverIndex' file, the web browser will do a second attempt to only read the javascript file. <br/>"
"This second attempt, with an idle webserver, will be processed.<br/><br/>"
"Long story short, press F5 (refresh web browser) before uploading your firmware. <br/><br/>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
   "<input type='file' name='update'>"
        "<input type='submit' value='Update'>"
    "</form>"
 "<div id='prg'>progress: 0%</div>"
 "<script>"
  "$('form').submit(function(e){"
  "e.preventDefault();"
  "var form = $('#upload_form')[0];"
  "var data = new FormData(form);"
  " $.ajax({"
  "url: '/update',"
  "type: 'POST',"
  "data: data,"
  "contentType: false,"
  "processData:false,"
  "xhr: function() {"
  "var xhr = new window.XMLHttpRequest();"
  "xhr.upload.addEventListener('progress', function(evt) {"
  "if (evt.lengthComputable) {"
  "var per = evt.loaded / evt.total;"
  "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
  "}"
  "}, false);"
  "return xhr;"
  "},"
  "success:function(d, s) {"
  "console.log('success!')"
 "},"
 "error: function (a, b, c) {"
 "}"
 "});"
 "});"
 "</script>";

// Callback for the embedded jquery.min.js page
void onJavaScript(void) {
    Serial.println("onJavaScript(void)");
		server.setContentLength(jquery_min_js_v3_2_1_gz_len);
		server.sendHeader(F("Content-Encoding"), F("gzip"));
    server.send_P(200, "text/javascript", jquery_min_js_v3_2_1_gz, jquery_min_js_v3_2_1_gz_len);
}

/*
 * setup function
 */
void setup(void) {
  Serial.begin(115200);
 
  // Connect to WiFi network
  //WiFi.begin(ssid, password);
  WiFi.softAP(ssid, password);
  Serial.println();
  Serial.print("software version: ");
  Serial.println(sw_version);
  Serial.print("host: ");
  Serial.println(host);
  Serial.print("ssid: ");
  Serial.println(ssid);
  Serial.print("password: ");
  Serial.println(password);
  IPAddress IP = WiFi.softAPIP();
  Serial.print("url: http://");
  Serial.print(IP);
  Serial.println("/ (user: admin, pswd: admin)");
 
  /*use mdns for host name resolution*/
  if (!MDNS.begin(host)) { //http://esp32.local
    Serial.println("Error setting up MDNS responder!");
    while (1) {
      delay(1000);
    }
  }
  Serial.println("mDNS responder started");

  /*return javascript jquery */
  server.on("/jquery.min.js", HTTP_GET, onJavaScript);
  /*return index page which is stored in serverIndex */
  server.on("/", HTTP_GET, []() {
    Serial.println("server.on(/)");
    server.sendHeader("Connection", "close");
    server.send(200, "text/html", loginIndex);
  });
  server.on("/serverIndex", HTTP_GET, []() {
    Serial.println("server.on(/serverIndex)");
    server.sendHeader("Connection", "close");
    server.send(200, "text/html", serverIndex);
  });
  /*handling uploading firmware file */
  server.on("/update", HTTP_POST, []() {
    Serial.println("server.on(/update)");
    server.sendHeader("Connection", "close");
    server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
    ESP.restart();
  }, []() {
    HTTPUpload& upload = server.upload();
    if (upload.status == UPLOAD_FILE_START) {
      Serial.printf("Update: %s\n", upload.filename.c_str());
      if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
        Update.printError(Serial);
      }
    } else if (upload.status == UPLOAD_FILE_WRITE) {
      /* flashing firmware to ESP*/
      if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
        Update.printError(Serial);
      }
    } else if (upload.status == UPLOAD_FILE_END) {
      if (Update.end(true)) { //true to set the size to the current progress
        Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
      } else {
        Update.printError(Serial);
      }
    }
  });
  server.begin();
}
 
void loop(void) {
  server.handleClient();
  delay(1);
}

TomWS1
Posts: 21
Joined: Wed May 01, 2019 2:50 pm

Re: OTA with ESP32 as AP

Postby TomWS1 » Thu Oct 10, 2019 11:56 am

@machiel, nice contribution! I've wondered how to include jquery into an embedded webserver. Thanks for showing us a way.

machiel
Posts: 4
Joined: Wed Oct 09, 2019 1:29 pm

Re: OTA with ESP32 as AP

Postby machiel » Thu Oct 10, 2019 1:14 pm

For the record, In the code I published, jQuery is already included / embedded. You only have do download the code by clicking on the DropBox link. The code I paste in the form is incomplete, because I reached the max size ☹. Therefore I removed the binary part of the code.

Code: Select all

#define jquery_min_js_v3_2_1_gz_len 30178
PROGMEM const char jquery_min_js_v3_2_1_gz[]  = {
0x1f,0x8b,   .................... 0x01,0x00
};
Nevertheless, if you mean how to make an embedded file yourself. My suggestion is to read this post. I used this information myself to create this webserver.

https://tinkerman.cat/post/embed-your-w ... are-image/

Beastlord
Posts: 1
Joined: Thu Feb 04, 2021 5:21 pm

Re: OTA with ESP32 as AP

Postby Beastlord » Thu Feb 04, 2021 5:26 pm

Wow great Job :shock: :shock: :shock:

Florencio.Canche
Posts: 1
Joined: Sat Jan 08, 2022 8:05 am

Re: OTA with ESP32 as AP

Postby Florencio.Canche » Sat Jan 08, 2022 8:15 am

#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>


const char *ssid = "ESP32-AP-WebServer";
const char* password = "12345678";

const char* PARAM_INPUT_1 = "state"; //guarda el estado en PARAM_INPUT

const int output = 2;// salida en la pata 2 y esta esta pata unida al led azul del esp32
const int buttonPin = 4; //boton pulsador normalmente abierto que cuando se pushea se conecta a positivo y el esp32 lee una señal de entrada

// Variables will change:
int buttonState=LOW; // the current reading from the input pin


// Create AsyncWebServer object on port 80

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);// crea un servidor asíncrono El término asíncrono se refiere al concepto de que más de una cosa ocurre al mismo tiempo, o múltiples cosas relacionadas ocurren sin esperar a que la previa se haya completado
AsyncWebSocket ws("/ws");// para procesar las solicitudes de servicio de red.
//Index.html es la página por defecto dentro de los directorios de los servidores de los sitios webs que se carga siempre que se solicita un dominio., index sería la página principal o el home de nuestra web
// PROGMEM es una manera de guardar una pagina web en el programa de arduino y volverlo a llamar sin causar que se congele el esp32. PROGMEM guarda y sirve de nuevo paginss web
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<head>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
h1 {
font-size: 1.8rem;
color: white;
}
h2{
font-size: 1.5rem;
font-weight: bold;
color: #143642;
}
.topnav {
overflow: hidden;
background-color: #143642;
}
body {
margin: 0;
}
.content {
padding: 30px;
max-width: 600px;
margin: 0 auto;
}
.card {
background-color: #F8F7F9;;
box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);
padding-top:10px;
padding-bottom:20px;
}
.button {
padding: 15px 50px;
font-size: 24px;
text-align: center;
outline: none;
color: #fff;
background-color: #0f8b8d;
border: none;
border-radius: 5px;
-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: #0f8b8d}*/
.button:active {
background-color: #0f8b8d;
box-shadow: 2 2px #CDCDCD;
transform: translateY(2px);
}
.state {
font-size: 1.5rem;
color:#8c8c8c;
font-weight: bold;
}
</style>
<title>florencio </title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 2.0rem;}
p {font-size: 3.0rem;}
body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
.switch {position: relative; display: inline-block; width: 120px; height: 68px}
.switch input {display: none}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
input:checked+.slider {background-color: #2196F3}
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
</style>
</head>
<body>
<h2>esp32 modo acces point</h2>
%BUTTONPLACEHOLDER%
<script>
// creamos una variable llamada BUTTONPLACEHOLDER para los botones on the web server. esto cambiara el codigo HTML para los botones.como usamos switches fisicos los cuales tam bien haran cambios en los botones segun el estado de la salida
function toggleCheckbox(element) {
var xhr = new XMLHttpRequest();
// si se ha pulsado la caja del boton= if(element.checked)
if(element.checked){ xhr.open("GET", "/haslo?state=1", true); } //obten el estado que esta almacenado en haslo EL state=1 es decir PARAM_INPUT_1=1
else { xhr.open("GET", "/haslo?state=0", true); }
xhr.send();
}

setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var inputChecked;
var outputStateM;
if( this.responseText == 1){
inputChecked = true;
outputStateM = "On";
}
else {
inputChecked = false;
outputStateM = "Off";
}
document.getElementById("output").checked = inputChecked;
document.getElementById("outputState").innerHTML = outputStateM;
}
};
xhttp.open("GET", "/state", true); // obten de la ruta state, si es true
xhttp.send();
}, 1000 ) ;
</script>
</body>
</html>
)rawliteral";

// cambia los placeholder con la seccion de boton en la pagina web
String processor(const String& var){
//Serial.println(var);
if(var == "BUTTONPLACEHOLDER"){
String buttons ="";
String outputStateValue = outputState();
buttons+= "<h4>output- GPIO 2 - State <span id=\"outputState\"></span></h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"output\" " + outputStateValue + "><span class=\"slider\"></span></label>";
return buttons;
}
return String();
}

String outputState(){
if(digitalRead(output)){
return "checked";
}
else {
return "";
}
return "";
}

void setup(){
// Serial port for debugging purposes
Serial.begin(115200);

pinMode(output, OUTPUT);
digitalWrite(output, LOW);
pinMode(buttonPin, INPUT_PULLDOWN); // esto significa que la pata esta en estado usando la resitencia interna e inicialmente esta en estado bajo esa pata Y al conectarce a positivo se registra una entrada
//conectando al punto de acceso
WiFi.softAP(ssid, password);
delay(1000);
Serial.println(WiFi.softAPIP());
Serial.print("IP address: ");

// RUTA para la entrada a la pagina de elegantOTA
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor); // CON ESTA LINEA MANDAMOS AL index_html., LA CUAL ES LA PAGINA DE INICIO DE elegantOTA
});

// con esto le indicamos a ESP32 que es lo que el boton virtual en la pagina web indica OSEA que el ESP32 prenda o apague el relay., la ruta se llama "haslo"
server.on("/haslo", HTTP_GET, [] (AsyncWebServerRequest *request) { // con esta linea le decimos que envie mensaje en la variable inputMessage
String inputMessage;
String inputParam;

if (request->hasParam(PARAM_INPUT_1)) { // GET input1 value on <ESP_IP>/haslo?state=<inputMessage> recuerda que: PARAM_INPUT_1 = "state";
inputMessage = request->getParam(PARAM_INPUT_1)->value(); //guarda en inputMessage
inputParam = PARAM_INPUT_1;
digitalWrite(output, inputMessage.toInt());

}
else {
inputMessage = "No message sent";
inputParam = "none";
}
Serial.println(inputMessage);
request->send(200, "text/plain", "OK");
});

// Start ElegantOTA

AsyncElegantOTA.begin(&server);
server.begin();
//Ahora manejaremos la declaración de rutas, que es donde podemos controlar los métodos permitidos por HTTP.
server.on("/state", HTTP_GET, [] (AsyncWebServerRequest *request) { // CON la ruta "/state" LE DECIMOS A LA PAGINA WEB que actualice los botones cuando fisicamente activamos el switch
request->send(200, "text/plain", String(digitalRead(output)).c_str());
});
}

void loop() {

if (digitalRead(buttonPin) == HIGH && buttonState == LOW) { //digitalRead() – lee el valor del pin fisico correspondiente en este caso si esta en low entonces ejecuta activa el relay (RelayPin1, HIGH);
digitalWrite(output, HIGH);
buttonState = HIGH;

}

if (digitalRead(buttonPin) == LOW && buttonState == HIGH) {
digitalWrite(output, LOW);
buttonState = LOW;
}
}

italocjs
Posts: 11
Joined: Thu Mar 10, 2022 6:15 pm

Re: OTA with ESP32 as AP

Postby italocjs » Thu Mar 10, 2022 6:21 pm

I've added a sample code for anyone trying to make it work, and get the serverIndex or similar errors caused by the jquery.min.js. -> https://github.com/italocjs/ESP32_OTA_APMODE

Who is online

Users browsing this forum: Baidu [Spider], Bing [Bot] and 78 guests