mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-04-05 05:50:56 +00:00
Implemented new user interface and prepared for live view
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
#include "HanConfigAp.h"
|
||||
#include "config_html.h"
|
||||
#include "style_css.h"
|
||||
|
||||
#include "index_html.h"
|
||||
#include "configuration_html.h"
|
||||
#include "bootstrap_css.h"
|
||||
#include "application_css.h"
|
||||
#include "jquery_js.h"
|
||||
#include "gaugemeter_js.h"
|
||||
#include "index_js.h"
|
||||
|
||||
#include "Base64.h"
|
||||
|
||||
@@ -74,9 +80,16 @@ void HanConfigAp::setup(int accessPointButtonPin, Stream* debugger)
|
||||
}
|
||||
|
||||
void HanConfigAp::enableWeb() {
|
||||
server.on("/", handleRoot);
|
||||
server.on("/style.css", handleStyle);
|
||||
server.on("/", indexHtml);
|
||||
server.on("/configuration", configurationHtml);
|
||||
server.on("/css/bootstrap.css", bootstrapCss);
|
||||
server.on("/css/application.css", applicationCss);
|
||||
server.on("/js/jquery.js", jqueryJs);
|
||||
server.on("/js/gaugemeter.js", gaugemeterJs);
|
||||
server.on("/js/index.js", indexJs);
|
||||
|
||||
server.on("/save", handleSave);
|
||||
|
||||
server.begin(); // Web server start
|
||||
|
||||
print("Web server is ready for config at http://");
|
||||
@@ -100,113 +113,6 @@ bool HanConfigAp::loop() {
|
||||
return isActivated;
|
||||
}
|
||||
|
||||
/** Handle root or redirect to captive portal */
|
||||
void HanConfigAp::handleRoot() {
|
||||
println("Serving / over http...");
|
||||
|
||||
configuration *config = new configuration();
|
||||
config->load();
|
||||
|
||||
String html = CONFIG_HTML;
|
||||
|
||||
if(config->hasConfig()) {
|
||||
bool access = !config->isAuth();
|
||||
if(config->isAuth() && server.hasHeader("Authorization")) {
|
||||
String expectedAuth = String(config->authUser) + ":" + String(config->authPass);
|
||||
|
||||
String providedPwd = server.header("Authorization");
|
||||
providedPwd.replace("Basic ", "");
|
||||
char inputString[providedPwd.length()];
|
||||
providedPwd.toCharArray(inputString, providedPwd.length()+1);
|
||||
|
||||
int inputStringLength = sizeof(inputString);
|
||||
int decodedLength = Base64.decodedLength(inputString, inputStringLength);
|
||||
char decodedString[decodedLength];
|
||||
Base64.decode(decodedString, inputString, inputStringLength);
|
||||
print("Received auth: ");
|
||||
println(decodedString);
|
||||
access = String(decodedString).equals(expectedAuth);
|
||||
}
|
||||
|
||||
if(!access) {
|
||||
server.sendHeader("WWW-Authenticate", "Basic realm=\"Secure Area\"");
|
||||
server.send(401, "text/html", "");
|
||||
} else {
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
|
||||
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);
|
||||
html.replace("${config.authUser}", config->authUser);
|
||||
html.replace("${config.authPass}", config->authPass);
|
||||
}
|
||||
|
||||
} else {
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
|
||||
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}", "");
|
||||
html.replace("${config.authUser}", "");
|
||||
html.replace("${config.authPass}", "");
|
||||
}
|
||||
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();
|
||||
|
||||
@@ -248,6 +154,8 @@ void HanConfigAp::handleSave() {
|
||||
config->mqttPass = new char[temp.length() + 1];
|
||||
temp.toCharArray(config->mqttPass, temp.length() + 1, 0);
|
||||
|
||||
config->authSecurity = (byte)server.arg("authSecurity").toInt();
|
||||
|
||||
temp = server.arg("authUser");
|
||||
config->authUser = new char[temp.length() + 1];
|
||||
temp.toCharArray(config->authUser, temp.length() + 1, 0);
|
||||
@@ -256,14 +164,18 @@ void HanConfigAp::handleSave() {
|
||||
config->authPass = new char[temp.length() + 1];
|
||||
temp.toCharArray(config->authPass, temp.length() + 1, 0);
|
||||
|
||||
config->fuseSize = (int)server.arg("fuseSize").toInt();
|
||||
|
||||
println("Saving configuration now...");
|
||||
|
||||
if (HanConfigAp::debugger) config->print(HanConfigAp::debugger);
|
||||
if (config->save())
|
||||
{
|
||||
println("Successfully saved. Will reboot now.");
|
||||
String html = "<html><body><h1>Successfully Saved!</h1><h3>Device is restarting now...</h3></form>";
|
||||
String html = "<html><body><h1>Successfully Saved!</h1><h3>Device is restarting now...</h3><a href=\"/\">Go to index</a></form>";
|
||||
server.send(200, "text/html", html);
|
||||
yield();
|
||||
delay(1000);
|
||||
#if defined(ESP8266)
|
||||
ESP.reset();
|
||||
#elif defined(ESP32)
|
||||
@@ -278,6 +190,153 @@ void HanConfigAp::handleSave() {
|
||||
}
|
||||
}
|
||||
|
||||
void HanConfigAp::indexHtml() {
|
||||
println("Serving /index.html 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", INDEX_HTML, sizeof(INDEX_HTML)-1);
|
||||
|
||||
}
|
||||
|
||||
void HanConfigAp::configurationHtml() {
|
||||
println("Serving /configuration.html over http...");
|
||||
|
||||
configuration *config = new configuration();
|
||||
config->load();
|
||||
|
||||
bool access = !config->hasConfig() || config->authSecurity == 0;
|
||||
if(config->authSecurity > 0 && server.hasHeader("Authorization")) {
|
||||
String expectedAuth = String(config->authUser) + ":" + String(config->authPass);
|
||||
|
||||
String providedPwd = server.header("Authorization");
|
||||
providedPwd.replace("Basic ", "");
|
||||
char inputString[providedPwd.length()];
|
||||
providedPwd.toCharArray(inputString, providedPwd.length()+1);
|
||||
|
||||
int inputStringLength = sizeof(inputString);
|
||||
int decodedLength = Base64.decodedLength(inputString, inputStringLength);
|
||||
char decodedString[decodedLength];
|
||||
Base64.decode(decodedString, inputString, inputStringLength);
|
||||
print("Received auth: ");
|
||||
println(decodedString);
|
||||
access = String(decodedString).equals(expectedAuth);
|
||||
}
|
||||
|
||||
if(!access) {
|
||||
server.sendHeader("WWW-Authenticate", "Basic realm=\"Secure Area\"");
|
||||
server.send(401, "text/html", "");
|
||||
return;
|
||||
}
|
||||
String html = CONFIGURATION_HTML;
|
||||
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
|
||||
if(config->hasConfig()) {
|
||||
html.replace("${config.ssid}", config->ssid);
|
||||
html.replace("${config.ssidPassword}", config->ssidPassword);
|
||||
html.replace("${config.meterType}", String(config->fuseSize));
|
||||
for(int i = 0; i<3; i++) {
|
||||
html.replace("${config.meterType" + String(i) + "}", config->meterType == i ? "selected" : "");
|
||||
}
|
||||
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);
|
||||
html.replace("${config.authUser}", config->authUser);
|
||||
html.replace("${config.authSecurity}", String(config->authSecurity));
|
||||
for(int i = 0; i<2; i++) {
|
||||
html.replace("${config.authSecurity" + String(i) + "}", config->authSecurity == i ? "selected" : "");
|
||||
}
|
||||
html.replace("${config.authPass}", config->authPass);
|
||||
html.replace("${config.fuseSize}", String(config->fuseSize));
|
||||
for(int i = 0; i<63; i++) {
|
||||
html.replace("${config.fuseSize" + String(i) + "}", config->fuseSize == i ? "selected" : "");
|
||||
}
|
||||
} else {
|
||||
html.replace("${config.ssid}", "");
|
||||
html.replace("${config.ssidPassword}", "");
|
||||
html.replace("${config.meterType}", "");
|
||||
for(int i = 0; i<3; i++) {
|
||||
html.replace("${config.meterType" + String(i) + "}", i == 0 ? "selected" : "");
|
||||
}
|
||||
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}", "");
|
||||
html.replace("${config.authSecurity}", "");
|
||||
for(int i = 0; i<2; i++) {
|
||||
html.replace("${config.authSecurity" + String(i) + "}", i == 0 ? "selected" : "");
|
||||
}
|
||||
html.replace("${config.authUser}", "");
|
||||
html.replace("${config.authPass}", "");
|
||||
html.replace("${config.fuseSize}", "");
|
||||
for(int i = 0; i<63; i++) {
|
||||
html.replace("${config.fuseSize" + String(i) + "}", i == 0 ? "selected" : "");
|
||||
}
|
||||
}
|
||||
server.send(200, "text/html", html);
|
||||
}
|
||||
|
||||
void HanConfigAp::bootstrapCss() {
|
||||
println("Serving /bootstrap.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", BOOTSTRAP_CSS, sizeof(BOOTSTRAP_CSS)-1);
|
||||
|
||||
}
|
||||
|
||||
void HanConfigAp::applicationCss() {
|
||||
println("Serving /application.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", APPLICATION_CSS, sizeof(APPLICATION_CSS)-1);
|
||||
|
||||
}
|
||||
|
||||
void HanConfigAp::jqueryJs() {
|
||||
println("Serving /jquery.js 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", JQUERY_JS, sizeof(JQUERY_JS)-1);
|
||||
|
||||
}
|
||||
|
||||
void HanConfigAp::gaugemeterJs() {
|
||||
println("Serving /gaugemeter.js 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", GAUEGMETER_JS, sizeof(GAUEGMETER_JS)-1);
|
||||
|
||||
}
|
||||
|
||||
void HanConfigAp::indexJs() {
|
||||
println("Serving /index.js 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", INDEX_JS, sizeof(INDEX_JS)-1);
|
||||
|
||||
}
|
||||
|
||||
size_t HanConfigAp::print(const char* text)
|
||||
{
|
||||
if (debugger) debugger->print(text);
|
||||
|
||||
@@ -46,9 +46,16 @@ private:
|
||||
static size_t println(const Printable& data);
|
||||
|
||||
// Web server
|
||||
static void handleRoot();
|
||||
static void handleStyle();
|
||||
static void indexHtml();
|
||||
static void configurationHtml();
|
||||
static void bootstrapCss();
|
||||
static void applicationCss();
|
||||
static void jqueryJs();
|
||||
static void gaugemeterJs();
|
||||
static void indexJs();
|
||||
|
||||
static void handleSave();
|
||||
|
||||
#if defined(ESP8266)
|
||||
static ESP8266WebServer server;
|
||||
#elif defined(ESP32) // ARDUINO_ARCH_ESP32
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const char APPLICATION_CSS[] PROGMEM = R"=="==(
|
||||
.bg-purple {
|
||||
background-color: var(--purple);
|
||||
}
|
||||
@@ -42,3 +43,4 @@
|
||||
font-weight: 200;
|
||||
opacity: .8;
|
||||
}
|
||||
)=="==";
|
||||
File diff suppressed because one or more lines are too long
@@ -1,85 +0,0 @@
|
||||
const char CONFIG_HTML[] PROGMEM = R"=="==(
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||
|
||||
<title>AMS2MQTT - configuration</title>
|
||||
</head>
|
||||
<body>
|
||||
<form method='post' action='/save'>
|
||||
<div class="wrapper">
|
||||
<div class="inner-wrapper">
|
||||
<div>
|
||||
<h2>WiFi</h2>
|
||||
</div>
|
||||
<div>
|
||||
<input type='text' name='ssid' value="${config.ssid}" placeholder="SSID">
|
||||
</div>
|
||||
<div>
|
||||
<input type='password' name='ssidPassword' value="${config.ssidPassword}" placeholder="Password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="inner-wrapper">
|
||||
<div>
|
||||
<h2>Meter Type</h2>
|
||||
</div>
|
||||
<div class="select-style">
|
||||
<select name="meterType">
|
||||
<option value="0" ${config.meterType0} disabled class="disabled-option"> SELECT TYPE </option>
|
||||
<option value="1" ${config.meterType1}>Kaifa</option>
|
||||
<option value="2" ${config.meterType2}>Aidon</option>
|
||||
<option value="3" ${config.meterType3}>Kamstrup</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inner-wrapper">
|
||||
<div>
|
||||
<h2>MQTT</h2>
|
||||
</div>
|
||||
<div>
|
||||
<label>Server & port:</label>
|
||||
<input type='text' name='mqtt' value="${config.mqtt}" placeholder="server">
|
||||
<input type='number' name='mqttPort' value="${config.mqttPort}" placeholder="port">
|
||||
</div>
|
||||
<div>
|
||||
<label>Client ID:</label>
|
||||
<input type='text' name='mqttClientID' value="${config.mqttClientID}" placeholder="client id">
|
||||
</div>
|
||||
<div>
|
||||
<label>Publish topic: </label>
|
||||
<input type='text' name='mqttPublishTopic' value="${config.mqttPublishTopic}" placeholder="topic">
|
||||
</div>
|
||||
<div>
|
||||
<label>Username:</label>
|
||||
<input type='text' name='mqttUser' value="${config.mqttUser}" placeholder="Blank for insecure">
|
||||
</div>
|
||||
<div>
|
||||
<label>Password:</label>
|
||||
<input type='password' name='mqttPass' value="${config.mqttPass}" placeholder="Blank for insecure">
|
||||
</div>
|
||||
<div>
|
||||
<input class="submit-button" type='submit' value='save'>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inner-wrapper">
|
||||
<div>
|
||||
<h2>Webserver</h2>
|
||||
</div>
|
||||
<div>
|
||||
<label>Username:</label>
|
||||
<input type='text' name='authUser' value="${config.authUser}" placeholder="Blank for insecure">
|
||||
</div>
|
||||
<div>
|
||||
<label>Password:</label>
|
||||
<input type='password' name='authPass' value="${config.authPass}" placeholder="Blank for insecure">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<body>
|
||||
</html>
|
||||
)=="==";
|
||||
@@ -39,12 +39,14 @@ bool configuration::save()
|
||||
address += saveBool(address, false);
|
||||
|
||||
|
||||
address += saveBool(address, isAuth());
|
||||
if (isAuth()) {
|
||||
address += saveByte(address, authSecurity);
|
||||
if (authSecurity > 0) {
|
||||
address += saveString(address, authUser);
|
||||
address += saveString(address, authPass);
|
||||
}
|
||||
|
||||
address += saveInt(address, fuseSize);
|
||||
|
||||
bool success = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
|
||||
@@ -67,8 +69,10 @@ bool configuration::load()
|
||||
mqttUser = 0;
|
||||
mqttPass = 0;
|
||||
mqttPort = 1883;
|
||||
authSecurity = 0;
|
||||
authUser = 0;
|
||||
authPass = 0;
|
||||
fuseSize = 0;
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
int cs = EEPROM.read(address);
|
||||
@@ -102,17 +106,17 @@ bool configuration::load()
|
||||
success = true;
|
||||
}
|
||||
if(cs >= 72) {
|
||||
bool auth = false;
|
||||
address += readBool(address, &auth);
|
||||
if (auth) {
|
||||
address += readByte(address, &authSecurity);
|
||||
if (authSecurity > 0) {
|
||||
address += readString(address, &authUser);
|
||||
address += readString(address, &authPass);
|
||||
} else {
|
||||
authUser = 0;
|
||||
authPass = 0;
|
||||
}
|
||||
|
||||
success = true;
|
||||
}
|
||||
if(cs >= 73) {
|
||||
address += readInt(address, &fuseSize);
|
||||
}
|
||||
EEPROM.end();
|
||||
return success;
|
||||
@@ -123,10 +127,6 @@ bool configuration::isSecure()
|
||||
return (mqttUser != 0) && (String(mqttUser).length() > 0);
|
||||
}
|
||||
|
||||
bool configuration::isAuth() {
|
||||
return (authUser != 0) && (String(authUser).length() > 0);
|
||||
}
|
||||
|
||||
int configuration::readInt(int address, int *value)
|
||||
{
|
||||
int lower = EEPROM.read(address);
|
||||
@@ -190,11 +190,13 @@ void configuration::print(Stream* debugger)
|
||||
debugger->printf("mqttPass: %s\r\n", this->mqttPass);
|
||||
}
|
||||
|
||||
if (this->isAuth()) {
|
||||
if (this->authSecurity > 0) {
|
||||
debugger->printf("WEB AUTH:\r\n");
|
||||
debugger->printf("authSecurity: %i\r\n", this->authSecurity);
|
||||
debugger->printf("authUser: %s\r\n", this->authUser);
|
||||
debugger->printf("authPass: %s\r\n", this->authPass);
|
||||
}
|
||||
debugger->printf("fuseSize: %i\r\n", this->fuseSize);
|
||||
|
||||
debugger->println("-----------------------------------------------");
|
||||
}
|
||||
|
||||
@@ -25,12 +25,14 @@ public:
|
||||
char* mqttPass;
|
||||
byte meterType;
|
||||
|
||||
byte authSecurity;
|
||||
char* authUser;
|
||||
char* authPass;
|
||||
|
||||
int fuseSize;
|
||||
|
||||
bool hasConfig();
|
||||
bool isSecure();
|
||||
bool isAuth();
|
||||
bool save();
|
||||
bool load();
|
||||
|
||||
@@ -39,7 +41,7 @@ protected:
|
||||
|
||||
private:
|
||||
const int EEPROM_SIZE = 512;
|
||||
const byte EEPROM_CHECK_SUM = 72; // Used to check if config is stored. Change if structure changes
|
||||
const byte EEPROM_CHECK_SUM = 73; // Used to check if config is stored. Change if structure changes
|
||||
const int EEPROM_CONFIG_ADDRESS = 0;
|
||||
|
||||
int saveString(int pAddress, char* pString);
|
||||
|
||||
147
lib/HanConfigAp/src/configuration_html.h
Normal file
147
lib/HanConfigAp/src/configuration_html.h
Normal file
@@ -0,0 +1,147 @@
|
||||
const char CONFIGURATION_HTML[] PROGMEM = R"=="==(
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>AMS reader - configuration</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="stylesheet" type="text/css" href="/css/bootstrap.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/css/application.css"/>
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
<main role="main" class="container">
|
||||
<div class="d-flex align-items-center p-3 my-2 text-white-50 bg-purple rounded shadow">
|
||||
<div class="lh-100">
|
||||
<h6 class="mb-0 text-white lh-100">AMS reader - configuration</h6>
|
||||
<small>v1.0.0</small>
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" action="/save">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="my-2 p-3 bg-white rounded shadow">
|
||||
<h6 class="border-bottom border-gray pb-2 mb-4">WiFi</h6>
|
||||
<div class="row form-group">
|
||||
<label class="col-3">SSID</label>
|
||||
<div class="col-9">
|
||||
<input type="text" class="form-control" name="ssid" value="${config.ssid}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-3">Password</label>
|
||||
<div class="col-9">
|
||||
<input type="password" class="form-control" name="ssidPassword" value="${config.ssidPassword}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-3 p-3 bg-white rounded shadow">
|
||||
<h6 class="border-bottom border-gray pb-2 mb-4">AMS meter</h6>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Meter type</label>
|
||||
<div class="col-8">
|
||||
<select class="form-control" name="meterType">
|
||||
<option value="0" ${config.meterType0} disabled></option>
|
||||
<option value="1" ${config.meterType1}>Kaifa</option>
|
||||
<option value="2" ${config.meterType2}>Aidon</option>
|
||||
<option value="3" ${config.meterType3}>Kamstrup</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Main fuse</label>
|
||||
<div class="col-8">
|
||||
<select class="form-control" name="fuseSize">
|
||||
<option value="" ${config.fuseSize0}></option>
|
||||
<option value="25" ${config.fuseSize25}>25A</option>
|
||||
<option value="32" ${config.fuseSize32}>32A</option>
|
||||
<option value="40" ${config.fuseSize40}>40A</option>
|
||||
<option value="50" ${config.fuseSize50}>50A</option>
|
||||
<option value="63" ${config.fuseSize63}>63A</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="my-2 p-3 bg-white rounded shadow">
|
||||
<h6 class="border-bottom border-gray pb-2 mb-4">MQTT</h6>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Hostname</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control" name="mqtt" value="${config.mqtt}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Port</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control" name="mqttPort" value="${config.mqttPort}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Client ID</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control" name="mqttClientID" value="${config.mqttClientID}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Topic</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control" name="mqttPublishTopic" value="${config.mqttPublishTopic}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Username</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control" name="mqttUser" value="${config.mqttUser}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Password</label>
|
||||
<div class="col-8">
|
||||
<input type="password" class="form-control" name="mqttPass" value="${config.mqttPass}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="my-2 p-3 bg-white rounded shadow">
|
||||
<h6 class="border-bottom border-gray pb-2 mb-4">Web server</h6>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Security</label>
|
||||
<div class="col-8">
|
||||
<select class="form-control" name="authSecurity">
|
||||
<option value="0" ${config.authSecurity0}>None</option>
|
||||
<option value="1" ${config.authSecurity1}>Only configuration</option>
|
||||
<option value="2" ${config.authSecurity2}>Everything</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Username</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control" name="authUser" value="${config.authUser}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Password</label>
|
||||
<div class="col-8">
|
||||
<input type="password" class="form-control" name="authPass" value="${config.authPass}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row form-group">
|
||||
<div class="col-6">
|
||||
<a href="/" class="btn btn-outline-secondary">Back</a>
|
||||
</div>
|
||||
<div class="col-6 text-right">
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
)=="==";
|
||||
@@ -1,4 +1,4 @@
|
||||
;
|
||||
const char GAUEGMETER_JS[] PROGMEM = R"=="==(
|
||||
/*
|
||||
* AshAlom Gauge Meter. Version 2.0.0
|
||||
* Copyright AshAlom.com All rights reserved.
|
||||
@@ -274,3 +274,4 @@
|
||||
};
|
||||
}
|
||||
(jQuery);
|
||||
)=="==";
|
||||
@@ -1,13 +1,14 @@
|
||||
const char INDEX_HTML[] PROGMEM = R"=="==(
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>AMS reader - configuration</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/css/bootstrap.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/css/application.css"/>
|
||||
<script src="/js/jquery.min.js"></script>
|
||||
<script src="/js/GaugeMeter.js"></script>
|
||||
<script src="/js/jquery.js"></script>
|
||||
<script src="/js/gaugemeter.js"></script>
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
<main role="main" class="container">
|
||||
@@ -63,10 +64,11 @@
|
||||
<a href="https://github.com/gskjold/AmsToMqttBridge/releases" class="btn btn-outline-secondary">Release notes</a>
|
||||
</div>
|
||||
<div class="col-6 text-right">
|
||||
<a href="/configuration.html" class="btn btn-primary">Configuration</a>
|
||||
<a href="/configuration" class="btn btn-primary">Configuration</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="/js/meter.js"></script>
|
||||
<script src="/js/index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
)=="==";
|
||||
@@ -1,3 +1,4 @@
|
||||
const char INDEX_JS[] PROGMEM = R"=="==(
|
||||
$(function() {
|
||||
$(".GaugeMeter").gaugeMeter();
|
||||
|
||||
@@ -9,3 +10,4 @@ $(function() {
|
||||
console.log(el);
|
||||
});
|
||||
});
|
||||
)=="==";
|
||||
File diff suppressed because one or more lines are too long
@@ -1,135 +0,0 @@
|
||||
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%;
|
||||
}
|
||||
}
|
||||
)=="==";
|
||||
@@ -9,5 +9,6 @@ lib_deps = ${common.lib_deps}
|
||||
build_flags =
|
||||
-D HAS_DALLAS_TEMP_SENSOR=0
|
||||
-D IS_CUSTOM_AMS_BOARD=0
|
||||
-D DEBUG_MODE=1
|
||||
monitor_speed = 2400
|
||||
monitor_flags = --parity E
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>AMS reader - configuration</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/css/application.css"/>
|
||||
</head>
|
||||
<body class="bg-light">
|
||||
<main role="main" class="container">
|
||||
<div class="d-flex align-items-center p-3 my-2 text-white-50 bg-purple rounded shadow">
|
||||
<div class="lh-100">
|
||||
<h6 class="mb-0 text-white lh-100">AMS reader - configuration</h6>
|
||||
<small>v1.0.0</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="my-2 p-3 bg-white rounded shadow">
|
||||
<h6 class="border-bottom border-gray pb-2 mb-4">WiFi</h6>
|
||||
<div class="row form-group">
|
||||
<label class="col-3">SSID</label>
|
||||
<div class="col-9">
|
||||
<input type="text" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-3">Password</label>
|
||||
<div class="col-9">
|
||||
<input type="password" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-3 p-3 bg-white rounded shadow">
|
||||
<h6 class="border-bottom border-gray pb-2 mb-4">AMS meter</h6>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Meter type</label>
|
||||
<div class="col-8">
|
||||
<select class="form-control">
|
||||
<option value=""></option>
|
||||
<option value="1">Kaifa</option>
|
||||
<option value="2">Aidon</option>
|
||||
<option value="3">Kamstrup</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Fuse size</label>
|
||||
<div class="col-8">
|
||||
<select class="form-control">
|
||||
<option value=""></option>
|
||||
<option value="25">25A</option>
|
||||
<option value="32">32A</option>
|
||||
<option value="40">40A</option>
|
||||
<option value="50">50A</option>
|
||||
<option value="63">63A</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="my-2 p-3 bg-white rounded shadow">
|
||||
<h6 class="border-bottom border-gray pb-2 mb-4">MQTT</h6>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Hostname</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Port</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Client ID</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Topic</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Username</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Password</label>
|
||||
<div class="col-8">
|
||||
<input type="password" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="my-2 p-3 bg-white rounded shadow">
|
||||
<h6 class="border-bottom border-gray pb-2 mb-4">Web server</h6>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Security</label>
|
||||
<div class="col-8">
|
||||
<select class="form-control">
|
||||
<option value="0">None</option>
|
||||
<option value="1">Only configuration</option>
|
||||
<option value="2">Everything</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Username</label>
|
||||
<div class="col-8">
|
||||
<input type="text" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-group">
|
||||
<label class="col-4">Password</label>
|
||||
<div class="col-8">
|
||||
<input type="password" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row form-group">
|
||||
<div class="col-6">
|
||||
<a href="/" class="btn btn-outline-secondary">Back</a>
|
||||
</div>
|
||||
<div class="col-6 text-right">
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user