The following code enables multiple Esp to be controlled( for now simple led on/off on PIn14) through simple mesh technique...I would like some feedback and if some users could try it and see where i am going wrong or not.
I have tested this code on 3 esps and each esp can be controlled from any one in the group.
The concept is that the wherever you are located, if you have even one node near you, you can may control any other node even if the wifi is not in range(through multiple other esps in the middle).
I am using a transaction id that should be randomly generated every time a request is made to each node.
The transmission may take a little time, but the message gets through!
Much appreciate any comments!
//Logical Steps:
//Go to AP MODE and Wait for signal
//
//if id is same as own id then transmit else
//
//SAVE signal and ID and Transact id And Restart to search mode
//
//check if ID is avalable,if true then save SSID to EEPROM,else search and save wifi with no Transact ID in last 4 digits too EEPROM, if no wifi found, skip to AP mode
//
//restart to connect mode
//
//Connect to saved Wifi and Send IR and ID and Transact ID
//
//Go back to AP mode and add transact ID to AP
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
extern "C" {
#include "user_interface.h"
}
int SetupMode = 0; //0-AP,1-Search,2-Wifi
const char* host = "192.168.4.1";
ESP8266WebServer server(80);
char trans[8]; //TransactId
char buf2[8]; //EspID
char buf3[1]; //State
char buf4[15]; //AP to connect to
char buf1[4];
const char WiFiAPPSK[] = "12345678";
const int EEPROM_MIN_ADDR = 0;
const int EEPROM_MAX_ADDR = 511;
boolean eeprom_is_addr_ok(int addr) {
return ((addr >= EEPROM_MIN_ADDR) && (addr <= EEPROM_MAX_ADDR));
}
boolean eeprom_write_bytes(int startAddr, const byte* array, int numBytes) {
// counter
int i;
if (!eeprom_is_addr_ok(startAddr) || !eeprom_is_addr_ok(startAddr + numBytes)) {
return false;
}
for (i = 0; i < numBytes; i++) {
EEPROM.write(startAddr + i, array[i]);
}
EEPROM.commit();
return true;
}
boolean eeprom_write_string(int addr, const char* string) {
int numBytes; // actual number of bytes to be written
//write the string contents plus the string terminator byte (0x00)
numBytes = strlen(string) + 1;
return eeprom_write_bytes(addr, (const byte*)string, numBytes);
}
boolean eeprom_read_string(int addr, char* buffer, int bufSize) {
byte ch; // byte read from eeprom
int bytesRead; // number of bytes read so far
if (!eeprom_is_addr_ok(addr)) {
return false;
}
if (bufSize == 0) {
return false;
}
if (bufSize == 1) {
buffer[0] = 0;
return true;
}
bytesRead = 0; // initialize byte counter
ch = EEPROM.read(addr + bytesRead); // read next byte from eeprom
buffer[bytesRead] = ch; // store it into the user buffer
bytesRead++; // increment byte counter
while ( (ch != 0x00) && (bytesRead < bufSize) && ((addr + bytesRead) <= EEPROM_MAX_ADDR) ) {
ch = EEPROM.read(addr + bytesRead);
buffer[bytesRead] = ch; // store it into the user buffer
bytesRead++;
}
if ((ch != 0x00) && (bytesRead >= 1)) {
buffer[bytesRead - 1] = 0;
}
return true;
}
void handleRoot() {
if(server.args()==3){
String TransactID = server.arg(0);
String EspID = server.arg(1);
String State = server.arg(2);
Serial.println("Got Values:");
Serial.println("TID: "+TransactID);
Serial.println("EspID: "+EspID);
Serial.println("State: "+State);
if(EspID==String(ESP.getChipId())){
EEPROM.write(50,State.toInt());
EEPROM.commit();
digitalWrite(14,State.toInt());
server.send(200, "text/html", "Thats me!, Changed State to "+ State);
}else{
TransactID.toCharArray(trans, 4); //convert string to char array
eeprom_write_string(2, trans);
EspID.toCharArray(buf2, 9); //convert string to char array
eeprom_write_string(7, buf2);
State.toCharArray(buf3, 2); //convert string to char array
eeprom_write_string(16, buf3);
EEPROM.write(0,1);
EEPROM.commit();
server.send(200, "text/html", "Signal Passed On");
system_restart();
}
}else{
server.send(200, "text/html", "Welcome to the MESH");
}
}
void setup() {
Serial.begin(115200);
Serial.println();
EEPROM.begin(512);
pinMode(14,OUTPUT);
SetupMode=EEPROM.read(0);
digitalWrite(14,EEPROM.read(50));
if (SetupMode>2){
SetupMode=0;
}
delay(500);
eeprom_read_string(16, trans, 2);
eeprom_read_string(7, buf2, 9);
eeprom_read_string(16, buf3, 2);
eeprom_read_string(201, buf4, 16);
eeprom_read_string(2, buf1, 4);
Serial.println("Setup Mode: "+String(SetupMode));
Serial.println("Transaction ID: "+String(buf1));
Serial.println("ESP ID: "+String(buf2));
Serial.println("State: "+String(buf3));
Serial.println("WifiSSID: "+String(buf4));
if (SetupMode==0){
//Enter AP mode
WiFi.mode(WIFI_AP);
String AP_NameString = "VIS"+String(ESP.getChipId())+String(buf1);
char AP_NameChar[AP_NameString.length() + 1];
memset(AP_NameChar, 0, AP_NameString.length() + 1);
for (int i=0; i<AP_NameString.length(); i++)
AP_NameChar[i] = AP_NameString.charAt(i);
WiFi.softAP(AP_NameChar, WiFiAPPSK);
server.on("/SendIR", handleRoot);
server.begin();
Serial.println("BRAODCAST SSID: ");
Serial.println(AP_NameString);
}else if(SetupMode==1){
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.println("scan start");
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0){
Serial.println("no networks found");
SetupMode=0;
} else
{
Serial.print(n);
Serial.println(" networks found");
//VIS111111110000
for (int i = 0; i < n; ++i)
{
if(String(WiFi.SSID(i)).substring(0,3)=="VIS"){
if(String(WiFi.SSID(i)).substring(3,11)==String(buf2)){
Serial.println("Found Target: "+ String(WiFi.SSID(i)));
String(WiFi.SSID(i)).toCharArray(buf4, 15);
delay(500);
eeprom_write_string(201, buf4);
EEPROM.write(0,2);
EEPROM.commit();
system_restart();
return;
}
if(String(WiFi.SSID(i)).substring(11,15)!=String(buf1)){
Serial.println("Next Available Target: "+ String(WiFi.SSID(i)));
String(WiFi.SSID(i)).toCharArray(buf4, 15);
delay(500);
eeprom_write_string(201, buf4);
EEPROM.write(0,2);
EEPROM.commit();
system_restart();
return;
}
}
}
Serial.println("No device Available...Going back to AP mode");
EEPROM.write(0,0);
EEPROM.commit();
system_restart();
}
}else if(SetupMode==2){
WiFi.mode(WIFI_STA);
WiFi.disconnect();
Serial.print("Reading WifiAP: ");
Serial.println(buf4);
WiFi.begin(buf4,WiFiAPPSK);
Serial.print("Connecting");
int check_count = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(200);
Serial.print(".");
check_count++;
if(check_count>15){
Serial.println("Connection Timeout...Going back to AP mode");
EEPROM.write(0,0);
EEPROM.commit();
system_restart();
}
}
Serial.println("WiFi connected");
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("Connection failed...Going back to AP Mode");
EEPROM.write(0,0);
EEPROM.commit();
system_restart();
}
String url = "/SendIR?tid="+String(buf1)+"&esp="+String(buf2)+"&state="+String(buf3);
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
Serial.println("Response: " + line);
}
Serial.println();
Serial.println("closing connection");
Serial.println("Send Succesful...Will wait for 5s and then Go back to AP Mode");
EEPROM.write(0,0);
EEPROM.commit();
delay(5000);
system_restart();
}
}
void loop() {
server.handleClient();
}