parent
efa0125053
commit
135f835cbc
@ -0,0 +1,318 @@ |
||||
/*
|
||||
ConfigIP.ino, Example for the AutoConnect library. |
||||
Copyright (c) 2019, Hieromon Ikasamo |
||||
https://github.com/Hieromon/AutoConnect
|
||||
This software is released under the MIT License. |
||||
https://opensource.org/licenses/MIT
|
||||
|
||||
This sketch implements an example of enabling a custom web page |
||||
according to the state of an externally equipped switch. The custom |
||||
web page configures and provides a static IP to the ESP module. |
||||
This example needs to equip an external switch circuit that pulls up |
||||
with a resistor (1K to 10K ohms) and then drops it to GND via a push |
||||
switch to connect to any GPIO of the ESP module. |
||||
|
||||
An external switch circuit: |
||||
3.3V |
||||
--+-- |
||||
| |
||||
+-+ |
||||
| | 1K ~ 10K |
||||
+-+ |
||||
| |
||||
+--> D2 |
||||
| |
||||
| O |
||||
--+ |
||||
| O |
||||
| |
||||
--+-- |
||||
GND |
||||
*/ |
||||
|
||||
#if defined(ARDUINO_ARCH_ESP8266) |
||||
#include <ESP8266WiFi.h> |
||||
#include <ESP8266WebServer.h> |
||||
#elif defined(ARDUINO_ARCH_ESP32) |
||||
#include <WiFi.h> |
||||
#include <WebServer.h> |
||||
#endif |
||||
#include <AutoConnect.h> |
||||
#include <EEPROM.h> |
||||
|
||||
static const char AUX_CONFIGIP[] PROGMEM = R"( |
||||
{ |
||||
"title": "Config IP", |
||||
"uri": "/configip", |
||||
"menu": true, |
||||
"element": [ |
||||
{ |
||||
"name": "caption", |
||||
"type": "ACText", |
||||
"value": "<b>Module IP configuration</b>", |
||||
"style": "color:steelblue" |
||||
}, |
||||
{ |
||||
"name": "mac", |
||||
"type": "ACText", |
||||
"format": "MAC: %s" |
||||
}, |
||||
{ |
||||
"name": "staip", |
||||
"type": "ACInput", |
||||
"label": "IP", |
||||
"global": true, |
||||
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" |
||||
}, |
||||
{ |
||||
"name": "gateway", |
||||
"type": "ACInput", |
||||
"label": "Gateway", |
||||
"global": true, |
||||
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" |
||||
}, |
||||
{ |
||||
"name": "netmask", |
||||
"type": "ACInput", |
||||
"label": "Netmask", |
||||
"global": true, |
||||
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" |
||||
}, |
||||
{ |
||||
"name": "dns1", |
||||
"type": "ACInput", |
||||
"label": "DNS", |
||||
"global": true, |
||||
"pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" |
||||
}, |
||||
{ |
||||
"name": "ok", |
||||
"type": "ACSubmit", |
||||
"value": "OK", |
||||
"uri": "/restart" |
||||
}, |
||||
{ |
||||
"name": "cancel", |
||||
"type": "ACSubmit", |
||||
"value": "Cancel", |
||||
"uri": "/_ac" |
||||
} |
||||
] |
||||
} |
||||
)"; |
||||
|
||||
static const char AUX_RESTART[] PROGMEM = R"( |
||||
{ |
||||
"title": "Config IP", |
||||
"uri": "/restart", |
||||
"menu": false, |
||||
"element": [ |
||||
{ |
||||
"name": "caption", |
||||
"type": "ACText", |
||||
"value": "Settings", |
||||
"style": "font-family:Arial;font-weight:bold;text-align:center;margin-bottom:10px;color:steelblue" |
||||
}, |
||||
{ |
||||
"name": "staip", |
||||
"type": "ACText", |
||||
"global": true, |
||||
"format": "IP: %s" |
||||
}, |
||||
{ |
||||
"name": "gateway", |
||||
"type": "ACText", |
||||
"global": true, |
||||
"format": "Gateway: %s" |
||||
}, |
||||
{ |
||||
"name": "netmask", |
||||
"type": "ACText", |
||||
"global": true, |
||||
"format": "Netmask: %s" |
||||
}, |
||||
{ |
||||
"name": "dns1", |
||||
"type": "ACText", |
||||
"global": true, |
||||
"format": "DNS1: %s" |
||||
}, |
||||
{ |
||||
"name": "result", |
||||
"type": "ACText", |
||||
"posterior": "par" |
||||
} |
||||
] |
||||
} |
||||
)"; |
||||
|
||||
AutoConnect portal; |
||||
AutoConnectConfig config; |
||||
AutoConnectAux auxIPConfig; |
||||
AutoConnectAux auxRestart; |
||||
|
||||
// Pin assignment for an external configuration switch
|
||||
uint8_t ConfigPin = D2; |
||||
uint8_t ActiveLevel = LOW; |
||||
|
||||
// EEPROM saving structure
|
||||
typedef union { |
||||
struct { |
||||
uint32_t ip; |
||||
uint32_t gateway; |
||||
uint32_t netmask; |
||||
uint32_t dns1; |
||||
} ipconfig; |
||||
uint8_t ipraw[sizeof(uint32_t) * 4]; |
||||
} IPCONFIG; |
||||
|
||||
// Load IP configuration from EEPROM
|
||||
void loadConfig(IPCONFIG* ipconfig) { |
||||
EEPROM.begin(sizeof(IPCONFIG)); |
||||
int dp = 0; |
||||
for (uint8_t i = 0; i < 4; i++) { |
||||
for (uint8_t c = 0; c < sizeof(uint32_t); c++) |
||||
ipconfig->ipraw[c + i * sizeof(uint32_t)] = EEPROM.read(dp++); |
||||
} |
||||
EEPROM.end(); |
||||
|
||||
// Unset value screening
|
||||
if (ipconfig->ipconfig.ip == 0xffffffffL) |
||||
ipconfig->ipconfig.ip = 0U; |
||||
if (ipconfig->ipconfig.gateway == 0xffffffffL) |
||||
ipconfig->ipconfig.gateway = 0U; |
||||
if (ipconfig->ipconfig.netmask == 0xffffffffL) |
||||
ipconfig->ipconfig.netmask = 0U; |
||||
if (ipconfig->ipconfig.dns1 == 0xffffffffL) |
||||
ipconfig->ipconfig.dns1 = 0U; |
||||
|
||||
Serial.println("IP configuration loaded"); |
||||
Serial.printf("Sta IP :0x%08lx\n", ipconfig->ipconfig.ip); |
||||
Serial.printf("Gateway:0x%08lx\n", ipconfig->ipconfig.gateway); |
||||
Serial.printf("Netmask:0x%08lx\n", ipconfig->ipconfig.netmask); |
||||
Serial.printf("DNS1 :0x%08lx\n", ipconfig->ipconfig.dns1); |
||||
} |
||||
|
||||
// Save current IP configuration to EEPROM
|
||||
void saveConfig(const IPCONFIG* ipconfig) { |
||||
EEPROM.begin(128); |
||||
int dp = 0; |
||||
for (uint8_t i = 0; i < 4; i++) { |
||||
for (uint8_t d = 0; d < sizeof(uint32_t); d++) |
||||
EEPROM.write(dp++, ipconfig->ipraw[d + i * sizeof(uint32_t)]); |
||||
} |
||||
EEPROM.end(); |
||||
delay(100); |
||||
} |
||||
|
||||
// Custom web page handler to set current configuration to the page
|
||||
String getConfig(AutoConnectAux& aux, PageArgument& args) { |
||||
IPCONFIG ipconfig; |
||||
loadConfig(&ipconfig); |
||||
|
||||
// Fetch MAC address
|
||||
String macAddress; |
||||
uint8_t mac[6]; |
||||
WiFi.macAddress(mac); |
||||
for (uint8_t i = 0; i < 6; i++) { |
||||
char buf[3]; |
||||
sprintf(buf, "%02x", mac[i]); |
||||
macAddress += buf; |
||||
if (i < 5) |
||||
macAddress += ':'; |
||||
} |
||||
aux["mac"].value = macAddress; |
||||
|
||||
// Fetch each IP address configuration from EEPROM
|
||||
IPAddress staip = IPAddress(ipconfig.ipconfig.ip); |
||||
IPAddress gateway = IPAddress(ipconfig.ipconfig.gateway); |
||||
IPAddress netmask = IPAddress(ipconfig.ipconfig.netmask); |
||||
IPAddress dns1 = IPAddress(ipconfig.ipconfig.dns1); |
||||
|
||||
// Echo back the IP settings
|
||||
aux["staip"].value = staip.toString(); |
||||
aux["gateway"].value = gateway.toString(); |
||||
aux["netmask"].value = netmask.toString(); |
||||
aux["dns1"].value = dns1.toString(); |
||||
|
||||
return String(); |
||||
} |
||||
|
||||
// Convert IP address from AutoConnectInput string value
|
||||
void getIPAddress(AutoConnectInput& input, uint32_t* ip) { |
||||
IPAddress ipAddress; |
||||
|
||||
if (input.length()) |
||||
ipAddress.fromString(input); |
||||
*ip = (uint32_t)ipAddress; |
||||
} |
||||
|
||||
// Custom web page handler to save the configuration to AutoConnectConfig
|
||||
String setConfig(AutoConnectAux& aux, PageArgument& args) { |
||||
IPCONFIG ipconfig; |
||||
|
||||
// Retrieve each IP address from AutoConnectInput field
|
||||
getIPAddress(aux["staip"].value, &ipconfig.ipconfig.ip); |
||||
getIPAddress(aux["gateway"].value, &ipconfig.ipconfig.gateway); |
||||
getIPAddress(aux["netmask"].value, &ipconfig.ipconfig.netmask); |
||||
getIPAddress(aux["dns1"].value, &ipconfig.ipconfig.dns1); |
||||
|
||||
// Make a result message
|
||||
if (auxIPConfig.isValid()) { |
||||
saveConfig(&ipconfig); |
||||
aux["result"].value = "Reset by AutoConnect menu will restart with the above."; |
||||
} |
||||
else |
||||
aux["result"].value = "Invalid IP address specified."; |
||||
return String(); |
||||
} |
||||
|
||||
// Sense the external switch to enter the configuraton mode
|
||||
bool senseSW(const uint8_t pin, const uint8_t activeLevel) { |
||||
bool sw = digitalRead(pin) == activeLevel; |
||||
if (sw) { |
||||
// Cut-off the chattering noise
|
||||
while (digitalRead(pin) == activeLevel) |
||||
delay(10); |
||||
} |
||||
return sw; |
||||
} |
||||
|
||||
void setup() { |
||||
delay(1000); |
||||
Serial.begin(115200); |
||||
Serial.println(); |
||||
|
||||
// Shift the credentials storage to reserve saving IPCONFIG
|
||||
config.boundaryOffset = sizeof(IPCONFIG); |
||||
|
||||
// Load current IP configuration
|
||||
IPCONFIG ipconfig; |
||||
loadConfig(&ipconfig); |
||||
|
||||
// Configure pre-loaded static IPs
|
||||
config.staip = IPAddress(ipconfig.ipconfig.ip); |
||||
config.staGateway = IPAddress(ipconfig.ipconfig.gateway); |
||||
config.staNetmask = IPAddress(ipconfig.ipconfig.netmask); |
||||
config.dns1 = IPAddress(ipconfig.ipconfig.dns1); |
||||
portal.config(config); |
||||
|
||||
// Sense the configuration button (external switch)
|
||||
pinMode(ConfigPin, INPUT); |
||||
if (senseSW(ConfigPin, ActiveLevel)) { |
||||
Serial.println("IP configuration enable"); |
||||
auxIPConfig.load(AUX_CONFIGIP); |
||||
auxIPConfig.on(getConfig); |
||||
auxRestart.load(AUX_RESTART); |
||||
auxRestart.on(setConfig); |
||||
portal.join({ auxIPConfig, auxRestart }); |
||||
} |
||||
|
||||
portal.begin(); |
||||
} |
||||
|
||||
void loop() { |
||||
// User sketch process is here.
|
||||
|
||||
portal.handleClient(); |
||||
} |
Loading…
Reference in new issue