1. Use OTA to update the sketch as needed.
2. Act as station which will transmit/receive UDP packets from other ESP on the WLAN.
3. Act as a webserver, that when logged into it's website will show the UDP responses from the other ESP.
I have developed a series of smart switches based on the ESP-01. They communicate with each other using UDP packets. However, I would like to now develop a sketch to monitor their status to make sure they are online and functioning properly.
In short, what I would like to do is to log into a "controller" ESP which serves up a webpage which automatically updates with the status of each "switch" ESP. I think I want to do this, also using UDP, by having the controller send a packet to each switch and then serve response to the webpage. (I am open to learning about smarter ways to do this.)
Ultimately, using OTA, I will adjust the code to add additional target IP addresses as I add more switches to my house. (Again, unless there is a smarter way to do this.)
In the sketch, I would define the total number of switches, then the IP address for each switch. Then using a for statement, go through a series of send/receive packets to collect the status and serve it to the webpage.
(In reality, what I am trying to do is probably not that much different than the Tardis example I've seen, I just don't understand it well enough to make the adaptation.)
In order to do this, I was thinking about declaring my variables like this:
//Define UDP server variables
unsigned int udpPort = 4500; // used by udp.begin()command (it is udpPort converted for use)
char pktBuf[25]; //buffer for UDP packets
//variables for processing Switches
int count = 3; // number of IP addresses to ping
char IP1[16] = "192.168.0.2";
char IP2[16] = "192.168.0.13";
char IP3[16] = "192.168.0.45";
where I could adjust count up or down, then add additional IP# variables.
Then in the loop() is was going to try to do something like this:
for (int x = 0; x<count; x++) {
IPAddress targetIP;
targetIP.fromString(IP(x));
Udp.beginPacket(targetIP, udpPort);
Udp.write("survey");
Udp.endPacket();
delay(10);
//Receive incoming Udp packet and parse information
int pktSize = Udp.parsePacket();
if (pktSize) {
// Serial.print(Udp.remoteIP());
// Serial.print(":");
// Serial.println(Udp.remotePort());
Udp.read(pktBuf, pktSize);
}
String packetbuffer (pktBuf);
packetbuffer(x) = (packetbuffer);
for (int i = 0; i<pktSize; i++){
pktBuf[i] = (char) 0;
}
Udp.flush();
delay(500);
}
In this case, the variable IP would be appended with x such that each time the for statement ran, it would change the variable name to... IP1, IP2, IP3, etc.
Obviously, this isn't correct and does not work. I'm looking for suggestion about how to do this... or something which will function in this way.
Then I would serve up the results to the webpage like this:
// Serve up the webpage with responses
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html; charset=UTF-8");
client.println("");
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head>");
client.println("<title>Lights Manager</title>");
client.println("</head>");
client.println("<body>");
client.println("<a href=\"/\">Refresh Status</a>");
client.println("</br></br>");
for (int x = 0; x<count; x++) {
client.println(packetbuffer(x) "</br/");
}
client.println("</br>");
client.println("</br>");
client.println("</body>");
client.println("</html>");
}
Again, here packetbuffer(x) would change each time the for statement ran, ultimately serving up all of the udp packetbuffer responses. (Although, assuming this method is even possible, I'm not sure how to declare multiple instances of packetbuffer(x) variable.
Here is my complete code. It is a total disaster of cut and paste examples I've mashed together to try to demonstrate what I am hoping to accomplish. It contains elements of:
1. an OTA example
2. a webserver example
3. a wifi.udp example
It is a total mess!
I know this is a BIG ask, so I appreciate any help I can be given. Thanks.
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ESP8266WebServer.h>
#include <ArduinoOTA.h>
const char* ssid = "..........";
const char* password = "..........";
WiFiServer WebServer(80);
WiFiClient client;
WiFiUDP Udp;
//Define UDP server variables
unsigned int udpPort = 4500; // used by udp.begin()command (it is udpPort converted for use)
char pktBuf[25]; //buffer for UDP packets
//variables for processing Switches
int count = 3; // number of IP addresses to ping
char IP1[16] = "192.168.0.2";
char IP2[16] = "192.168.0.13";
char IP3[16] = "192.168.0.45";
void setup() {
Serial.begin(115200);
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
// Port defaults to 8266
ArduinoOTA.setPort(8266);
// Hostname defaults to esp8266-[ChipID]
ArduinoOTA.setHostname("Light Manager");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
WebServer.begin();
Udp.begin(udpPort);
}
void loop() {
ArduinoOTA.handle();
client = WebServer.available();
if (!client) {//restart loop
return;
}
// Wait until the user sends some data
Serial.println("New User");
while (!client.available()) {
delay(1);
}
// Read the first line of the request
String request = client.readStringUntil('\r\n');
Serial.println(request);
client.flush();
// Process the request:
if (request.indexOf("/survey") != -1) {
for (int x = 0; x<count; x++) {
IPAddress targetIP;
targetIP.fromString(IP(x));
Udp.beginPacket(targetIP, udpPort);
Udp.write("survey");
Udp.endPacket();
delay(10);
//Receive incoming Udp packet and parse information
int pktSize = Udp.parsePacket();
if (pktSize) {
// Serial.print(Udp.remoteIP());
// Serial.print(":");
// Serial.println(Udp.remotePort());
Udp.read(pktBuf, pktSize);
}
String packetbuffer (pktBuf);
packetbuffer(x) = (packetbuffer);
for (int i = 0; i<pktSize; i++){
pktBuf[i] = (char) 0;
}
Udp.flush();
delay(500);
}
// Serve up the webpage with responses
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html; charset=UTF-8");
client.println("");
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head>");
client.println("<title>Lights Manager</title>");
client.println("</head>");
client.println("<body>");
client.println("<a href=\"/\">Refresh Status</a>");
client.println("</br></br>");
for (int x = 0; x<count; x++) {
client.println(packetbuffer(x) "</br/");
}
client.println("</br>");
client.println("</br>");
client.println("</body>");
client.println("</html>");
}
}