diff --git a/lib/HanConfigAp/src/HanConfigAp.cpp b/lib/HanConfigAp/src/HanConfigAp.cpp index 06a6c0fc..43933e0a 100644 --- a/lib/HanConfigAp/src/HanConfigAp.cpp +++ b/lib/HanConfigAp/src/HanConfigAp.cpp @@ -1,4 +1,6 @@ #include "HanConfigAp.h" +#include "config_html.h" +#include "style_css.h" #if defined(ESP8266) ESP8266WebServer HanConfigAp::server(80); @@ -66,30 +68,34 @@ void HanConfigAp::setup(int accessPointButtonPin, Stream* debugger) /* Setup the DNS server redirecting all the domains to this IP */ dnsServer.setErrorReplyCode(DNSReplyCode::NoError); dnsServer.start(DNS_PORT, "*", WiFi.softAPIP()); - - server.on("/", handleRoot); - server.on("/save", handleSave); - server.begin(); // Web server start - - print("Web server is ready for config at http://"); - print(WiFi.softAPIP()); - println("/"); } } +void HanConfigAp::enableWeb() { + server.on("/", handleRoot); + server.on("/style.css", handleStyle); + server.on("/save", handleSave); + server.begin(); // Web server start + + print("Web server is ready for config at http://"); + if(isActivated) { + print(WiFi.softAPIP()); + } else { + print(WiFi.localIP()); + } + println("/"); +} + bool HanConfigAp::loop() { - if (isActivated) - { + if(isActivated) { //DNS dnsServer.processNextRequest(); - //HTTP - server.handleClient(); - return true; - } - else - { - return false; } + + //HTTP + server.handleClient(); + + return isActivated; } /** Handle root or redirect to captive portal */ @@ -99,11 +105,72 @@ void HanConfigAp::handleRoot() { server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); server.sendHeader("Pragma", "no-cache"); server.sendHeader("Expires", "-1"); - server.setContentLength(CONTENT_LENGTH_UNKNOWN); - String html = String("\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\t
\r\n\r\n\t\t
\r\n\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t

WiFi

\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t
\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t

Meter Type

\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t
\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t

MQTT

\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t
\r\n\t\t
\r\n\t
\r\n\r\n\t\r\n\r\n"); + String html = CONFIG_HTML; + + configuration *config = new configuration(); + config->load(); + + if(config->hasConfig()) { + html.replace("${config.ssid}", config->ssid); + html.replace("${config.ssidPassword}", config->ssidPassword); + switch (config->meterType) { + case 1: + html.replace("${config.meterType0}", ""); + html.replace("${config.meterType1}", "selected"); + html.replace("${config.meterType2}", ""); + html.replace("${config.meterType3}", ""); + break; + case 2: + html.replace("${config.meterType0}", ""); + html.replace("${config.meterType1}", ""); + html.replace("${config.meterType2}", "selected"); + html.replace("${config.meterType3}", ""); + break; + case 3: + html.replace("${config.meterType0}", ""); + html.replace("${config.meterType1}", ""); + html.replace("${config.meterType2}", ""); + html.replace("${config.meterType3}", "selected"); + break; + default: + html.replace("${config.meterType0}", "selected"); + html.replace("${config.meterType1}", ""); + html.replace("${config.meterType2}", ""); + html.replace("${config.meterType3}", ""); + } + html.replace("${config.mqtt}", config->mqtt); + html.replace("${config.mqttPort}", String(config->mqttPort)); + html.replace("${config.mqttClientID}", config->mqttClientID); + html.replace("${config.mqttPublishTopic}", config->mqttPublishTopic); + html.replace("${config.mqttSubscribeTopic}", config->mqttSubscribeTopic); + html.replace("${config.mqttUser}", config->mqttUser); + html.replace("${config.mqttPass}", config->mqttPass); + } else { + html.replace("${config.ssid}", ""); + html.replace("${config.ssidPassword}", ""); + html.replace("${config.meterType0}", "selected"); + html.replace("${config.meterType1}", ""); + html.replace("${config.meterType2}", ""); + html.replace("${config.meterType3}", ""); + html.replace("${config.mqtt}", ""); + html.replace("${config.mqttPort}", "1883"); + html.replace("${config.mqttClientID}", ""); + html.replace("${config.mqttPublishTopic}", ""); + html.replace("${config.mqttSubscribeTopic}", ""); + html.replace("${config.mqttUser}", ""); + html.replace("${config.mqttPass}", ""); + } server.send(200, "text/html", html); } +void HanConfigAp::handleStyle() { + println("Serving /style.css over http..."); + + server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); + server.send(200, "text/html", STYLE_CSS, sizeof(STYLE_CSS)); +} void HanConfigAp::handleSave() { configuration *config = new configuration(); @@ -151,7 +218,7 @@ void HanConfigAp::handleSave() { if (HanConfigAp::debugger) config->print(HanConfigAp::debugger); if (config->save()) { - println("Successfully saved. Will roboot now."); + println("Successfully saved. Will reboot now."); String html = "

Successfully Saved!

Device is restarting now...

"; server.send(200, "text/html", html); #if defined(ESP8266) diff --git a/lib/HanConfigAp/src/HanConfigAp.h b/lib/HanConfigAp/src/HanConfigAp.h index 42eab7c6..d1e01d85 100644 --- a/lib/HanConfigAp/src/HanConfigAp.h +++ b/lib/HanConfigAp/src/HanConfigAp.h @@ -27,6 +27,7 @@ class HanConfigAp { public: void setup(int accessPointButtonPin, Stream* debugger); + void enableWeb(); bool loop(); bool hasConfig(); configuration config; @@ -46,6 +47,7 @@ private: // Web server static void handleRoot(); + static void handleStyle(); static void handleSave(); #if defined(ESP8266) static ESP8266WebServer server; diff --git a/lib/HanConfigAp/src/config_html.h b/lib/HanConfigAp/src/config_html.h new file mode 100644 index 00000000..ff2ea9a7 --- /dev/null +++ b/lib/HanConfigAp/src/config_html.h @@ -0,0 +1,72 @@ +const char CONFIG_HTML[] PROGMEM = R"=="==( + + + + + + + + + AMS2MQTT - configuration + + +
+
+
+
+

WiFi

+
+
+ +
+
+ +
+
+
+
+

Meter Type

+
+
+ +
+
+
+
+

MQTT

+
+
+ + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+ + +)=="=="; diff --git a/lib/HanConfigAp/src/style_css.h b/lib/HanConfigAp/src/style_css.h new file mode 100644 index 00000000..9b28b09c --- /dev/null +++ b/lib/HanConfigAp/src/style_css.h @@ -0,0 +1,135 @@ +const char STYLE_CSS[] PROGMEM = R"=="==( +body,div,input { + font-family: "Roboto", Arial, Lucida Grande; +} +.wrapper { + width: 500px; + position: absolute; + padding: 30px; + background-color: #FFF; + border-radius: 1px; + color: #333; + border-color: rgba(0, 0, 0, 0.03); + box-shadow: 0 2px 2px rgba(0, 0, 0, .24), 0 0 2px rgba(0, 0, 0, .12); + margin-left: 20px; + margin-top: 20px; +} +div { + padding-bottom: 5px; +} +label { + font-family: "Roboto", "Helvetica Neue", sans-serif; + font-size: 14px; + line-height: 16px; + width: 100px; + display: inline-block; +} +input { + font-family: "Roboto", "Helvetica Neue", sans-serif; + font-size: 14px; + line-height: 16px; + bottom: 30px; + border: none; + border-bottom: 1px solid #d4d4d4; + padding: 10px; + background: transparent; + transition: all .25s ease; +} +input[type=number] { + width: 70px; + margin-left: 5px; +} +input:focus { + outline: none; + border-bottom: 1px solid #3f51b5; +} +h2 { + text-align: left; + font-size: 20px; + font-weight: bold; + letter-spacing: 3px; + line-height: 28px; +} +.submit-button { + position: absolute; + text-align: right; + border-radius: 20px; + border-bottom-right-radius: 0; + border-top-right-radius: 0; + background-color: #3f51b5; + color: #FFF; + padding: 12px 25px; + display: inline-block; + font-size: 12px; + font-weight: bold; + letter-spacing: 2px; + right: 0px; + bottom: 10px; + cursor: pointer; + transition: all .25s ease; + box-shadow: 0 2px 2px rgba(0, 0, 0, .24), 0 0 2px rgba(0, 0, 0, .12); + width: 100px; +} +.select-style { + border-top: 10px solid white; + border-bottom: 1px solid #d4d4d4; + color: #ffffff; + cursor: pointer; + display: block; + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 14px; + font-weight: 400; + height: 16px; + line-height: 14px; + min-width: 200px; + padding-bottom: 7px; + padding-left: 0px; + padding-right: 0px; + position: relative; + text-align: left; + width: 80%; + -webkit-box-direction: normal; + overflow: hidden; + background: #ffffff url("data:image/png;base64,R0lGODlhDwAUAIABAAAAAP///yH5BAEAAAEALAAAAAAPABQAAAIXjI+py+0Po5wH2HsXzmw//lHiSJZmUAAAOw==") no-repeat 98% 50%; +} +.disabled-option { + color: #d4d4d4; +} +.select-style select { + padding: 5px 8px; + width: 100%; + border: none; + box-shadow: none; + background: transparent; + background-image: none; + -webkit-appearance: none; +} +.select-style select:focus { + outline: none; + border: none; +} +@media only screen and (max-width: 1000px) { + .wrapper { + width: 80%; + } +} +@media only screen and (max-width: 300px) { + .wrapper { + width: 75%; + } +} +@media only screen and (max-width: 600px) { + .wrapper { + width: 80%; + margin-left: 0px; + margin-top: 0px; + } + .submit-button { + bottom: 0px; + width: 70px; + } + input { + width: 100%; + } +} +)=="=="; diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 79cec03c..b3279749 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -59,10 +59,11 @@ HardwareSerial* debugger = NULL; HanReader hanReader; // the setup function runs once when you press reset or power the board -void setup() -{ - // Uncomment to debug over the same port as used for HAN communication - //debugger = &Serial; +void setup() { + +#if DEBUG_MODE + debugger = &Serial; +#endif if (debugger) { // Setup serial port for debugging @@ -100,6 +101,8 @@ void setup() // Compensate for the known Kaifa bug hanReader.compensateFor09HeaderBug = (ap.config.meterType == 1); } + + ap.enableWeb(); } // the loop function runs over and over again until power down or reset