diff --git a/lib/HanConfigAp/library.properties b/lib/HanConfigAp/library.properties deleted file mode 100644 index 6fa3db03..00000000 --- a/lib/HanConfigAp/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=HanConfigAp -version=1.0.0 -author=roarfred -maintainer=roarfred -sentence=HAN Configuraiton accesspoint -paragraph=HAN Configuraiton accesspoint -category=Sensors -url=https://github.com/roarfred/AmsToMqttBridge -architectures=* diff --git a/lib/HanConfigAp/src/Base64.cpp b/lib/HanConfigAp/src/Base64.cpp deleted file mode 100644 index 5cf68987..00000000 --- a/lib/HanConfigAp/src/Base64.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* -Copyright (C) 2016 Arturo Guadalupi. All right reserved. - -This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -*/ - -#include "Base64.h" -#include -#if (defined(__AVR__)) -#include -#else -#include -#endif -const char PROGMEM _Base64AlphabetTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -int Base64Class::encode(char *output, char *input, int inputLength) { - int i = 0, j = 0; - int encodedLength = 0; - unsigned char A3[3]; - unsigned char A4[4]; - - while(inputLength--) { - A3[i++] = *(input++); - if(i == 3) { - fromA3ToA4(A4, A3); - - for(i = 0; i < 4; i++) { - output[encodedLength++] = pgm_read_byte(&_Base64AlphabetTable[A4[i]]); - } - - i = 0; - } - } - - if(i) { - for(j = i; j < 3; j++) { - A3[j] = '\0'; - } - - fromA3ToA4(A4, A3); - - for(j = 0; j < i + 1; j++) { - output[encodedLength++] = pgm_read_byte(&_Base64AlphabetTable[A4[j]]); - } - - while((i++ < 3)) { - output[encodedLength++] = '='; - } - } - output[encodedLength] = '\0'; - return encodedLength; -} - -int Base64Class::decode(char * output, char * input, int inputLength) { - int i = 0, j = 0; - int decodedLength = 0; - unsigned char A3[3]; - unsigned char A4[4]; - - - while (inputLength--) { - if(*input == '=') { - break; - } - - A4[i++] = *(input++); - if (i == 4) { - for (i = 0; i <4; i++) { - A4[i] = lookupTable(A4[i]); - } - - fromA4ToA3(A3,A4); - - for (i = 0; i < 3; i++) { - output[decodedLength++] = A3[i]; - } - i = 0; - } - } - - if (i) { - for (j = i; j < 4; j++) { - A4[j] = '\0'; - } - - for (j = 0; j <4; j++) { - A4[j] = lookupTable(A4[j]); - } - - fromA4ToA3(A3,A4); - - for (j = 0; j < i - 1; j++) { - output[decodedLength++] = A3[j]; - } - } - output[decodedLength] = '\0'; - return decodedLength; -} - -int Base64Class::encodedLength(int plainLength) { - int n = plainLength; - return (n + 2 - ((n + 2) % 3)) / 3 * 4; -} - -int Base64Class::decodedLength(char * input, int inputLength) { - int i = 0; - int numEq = 0; - for(i = inputLength - 1; input[i] == '='; i--) { - numEq++; - } - - return ((6 * inputLength) / 8) - numEq; -} - -//Private utility functions -inline void Base64Class::fromA3ToA4(unsigned char * A4, unsigned char * A3) { - A4[0] = (A3[0] & 0xfc) >> 2; - A4[1] = ((A3[0] & 0x03) << 4) + ((A3[1] & 0xf0) >> 4); - A4[2] = ((A3[1] & 0x0f) << 2) + ((A3[2] & 0xc0) >> 6); - A4[3] = (A3[2] & 0x3f); -} - -inline void Base64Class::fromA4ToA3(unsigned char * A3, unsigned char * A4) { - A3[0] = (A4[0] << 2) + ((A4[1] & 0x30) >> 4); - A3[1] = ((A4[1] & 0xf) << 4) + ((A4[2] & 0x3c) >> 2); - A3[2] = ((A4[2] & 0x3) << 6) + A4[3]; -} - -inline unsigned char Base64Class::lookupTable(char c) { - if(c >='A' && c <='Z') return c - 'A'; - if(c >='a' && c <='z') return c - 71; - if(c >='0' && c <='9') return c + 4; - if(c == '+') return 62; - if(c == '/') return 63; - return -1; -} - -Base64Class Base64; diff --git a/lib/HanConfigAp/src/Base64.h b/lib/HanConfigAp/src/Base64.h deleted file mode 100644 index 7330225e..00000000 --- a/lib/HanConfigAp/src/Base64.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright (C) 2016 Arturo Guadalupi. All right reserved. - -This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -*/ - -#ifndef _BASE64_H -#define _BASE64_H - -class Base64Class{ - public: - int encode(char *output, char *input, int inputLength); - int decode(char * output, char * input, int inputLength); - int encodedLength(int plainLength); - int decodedLength(char * input, int inputLength); - - private: - inline void fromA3ToA4(unsigned char * A4, unsigned char * A3); - inline void fromA4ToA3(unsigned char * A3, unsigned char * A4); - inline unsigned char lookupTable(char c); -}; -extern Base64Class Base64; - -#endif // _BASE64_H diff --git a/lib/HanConfigAp/src/HanConfigAp.cpp b/lib/HanConfigAp/src/HanConfigAp.cpp deleted file mode 100644 index edc8e0bf..00000000 --- a/lib/HanConfigAp/src/HanConfigAp.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "HanConfigAp.h" - -Stream* HanConfigAp::debugger; - -bool HanConfigAp::hasConfig() { - return config->hasConfig(); -} - -void HanConfigAp::setup(int accessPointButtonPin, configuration* config, Stream* debugger) -{ - this->debugger = debugger; - this->config = config; - - // Test if we're missing configuration - if (!config->hasConfig()) - { - print("No config. We're booting as AP. Look for SSID "); - println(this->AP_SSID); - isActivated = true; - } - else - { - // Load the configuration - if (this->debugger) config->print(this->debugger); - - if (accessPointButtonPin != INVALID_BUTTON_PIN) - { - // Assign pin for boot as AP - pinMode(accessPointButtonPin, INPUT_PULLUP); - - // Test if we're holding down the AP pin, over 1 second - int time = millis() + 1000; - print("Press the AP button now to boot as access point"); - while (millis() < time) - { - print("."); - if (digitalRead(accessPointButtonPin) == LOW) - { - print("AP button was pressed. Booting as access point now. Look for SSID "); - println(this->AP_SSID); - isActivated = true; - break; - } - delay(100); - } - println(""); - } - } - - if (isActivated) - { - // Setup AP - WiFi.disconnect(true); - WiFi.softAPdisconnect(true); - WiFi.mode(WIFI_OFF); - delay(2000); - - WiFi.mode(WIFI_AP); - WiFi.softAP(AP_SSID); - - /* Setup the DNS server redirecting all the domains to this IP */ - dnsServer.setErrorReplyCode(DNSReplyCode::NoError); - dnsServer.start(DNS_PORT, "*", WiFi.softAPIP()); - } -} - -bool HanConfigAp::loop() { - if(isActivated) { - //DNS - dnsServer.processNextRequest(); - } - - return isActivated; -} - -size_t HanConfigAp::print(const char* text) -{ - if (debugger) debugger->print(text); -} -size_t HanConfigAp::println(const char* text) -{ - if (debugger) debugger->println(text); -} -size_t HanConfigAp::print(const Printable& data) -{ - if (debugger) debugger->print(data); -} -size_t HanConfigAp::println(const Printable& data) -{ - if (debugger) debugger->println(data); -} diff --git a/lib/HanConfigAp/src/HanConfigAp.h b/lib/HanConfigAp/src/HanConfigAp.h deleted file mode 100644 index 401b8656..00000000 --- a/lib/HanConfigAp/src/HanConfigAp.h +++ /dev/null @@ -1,50 +0,0 @@ -// ap.h - -#ifndef _ACCESSPOINT_h -#define _ACCESSPOINT_h - -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - -#if defined(ESP8266) - #include -#elif defined(ESP32) // ARDUINO_ARCH_ESP32 - #include -#else - #warning "Unsupported board type" -#endif - -#include -#include "configuration.h" - -#define INVALID_BUTTON_PIN 0xFFFFFFFF - -class HanConfigAp { -public: - void setup(int accessPointButtonPin, configuration* config, Stream* debugger); - bool loop(); - bool hasConfig(); - bool isActivated = false; - -private: - const char* AP_SSID = "AMS2MQTT"; - - configuration* config; - - // DNS server - const byte DNS_PORT = 53; - DNSServer dnsServer; - - static size_t print(const char* text); - static size_t println(const char* text); - static size_t print(const Printable& data); - static size_t println(const Printable& data); - - static Stream* debugger; -}; - -#endif - diff --git a/lib/HanConfigAp/src/configuration.cpp b/lib/HanConfigAp/src/configuration.cpp deleted file mode 100644 index 34715e63..00000000 --- a/lib/HanConfigAp/src/configuration.cpp +++ /dev/null @@ -1,260 +0,0 @@ -// -// -// - -#include "configuration.h" - -bool configuration::hasConfig() -{ - bool hasConfig = false; - EEPROM.begin(EEPROM_SIZE); - hasConfig = EEPROM.read(EEPROM_CONFIG_ADDRESS) == EEPROM_CHECK_SUM; - EEPROM.end(); - return hasConfig; -} - -bool configuration::save() -{ - int address = EEPROM_CONFIG_ADDRESS; - - EEPROM.begin(EEPROM_SIZE); - EEPROM.put(address, EEPROM_CHECK_SUM); - address++; - - address += saveString(address, ssid); - address += saveString(address, ssidPassword); - address += saveByte(address, meterType); - - - if(mqttHost) { - address += saveBool(address, true); - address += saveString(address, mqttHost); - address += saveInt(address, mqttPort); - address += saveString(address, mqttClientID); - address += saveString(address, mqttPublishTopic); - address += saveString(address, mqttSubscribeTopic); - } else { - address += saveBool(address, false); - } - - if (isSecure()) { - address += saveBool(address, true); - address += saveString(address, mqttUser); - address += saveString(address, mqttPass); - } - else - address += saveBool(address, false); - - - address += saveByte(address, authSecurity); - if (authSecurity > 0) { - address += saveString(address, authUser); - address += saveString(address, authPass); - } - - address += saveInt(address, fuseSize); - address += saveInt(address, distSys); - - bool success = EEPROM.commit(); - EEPROM.end(); - - return success; -} - - -bool configuration::load() -{ - int address = EEPROM_CONFIG_ADDRESS; - bool success = false; - - ssid = 0; - ssidPassword = 0; - mqttHost = 0; - mqttClientID = 0; - mqttPublishTopic = 0; - mqttSubscribeTopic = 0; - mqttUser = 0; - mqttPass = 0; - authUser = 0; - authPass = 0; - - EEPROM.begin(EEPROM_SIZE); - int cs = EEPROM.read(address); - if (cs == EEPROM_CHECK_SUM) - { - address++; - - address += readString(address, &ssid); - address += readString(address, &ssidPassword); - address += readByte(address, &meterType); - - bool mqtt = false; - address += readBool(address, &mqtt); - if(mqtt) { - address += readString(address, &mqttHost); - address += readInt(address, &mqttPort); - address += readString(address, &mqttClientID); - address += readString(address, &mqttPublishTopic); - address += readString(address, &mqttSubscribeTopic); - } - - bool secure = false; - address += readBool(address, &secure); - if (secure) - { - address += readString(address, &mqttUser); - address += readString(address, &mqttPass); - } - else - { - mqttUser = 0; - mqttPass = 0; - } - - address += readByte(address, &authSecurity); - if (authSecurity > 0) { - address += readString(address, &authUser); - address += readString(address, &authPass); - } else { - authUser = 0; - authPass = 0; - } - - address += readInt(address, &fuseSize); - address += readByte(address, &distSys); - - success = true; - } - EEPROM.end(); - return success; -} - -bool configuration::isSecure() -{ - return (mqttUser != 0) && (String(mqttUser).length() > 0); -} - -int configuration::readInt(int address, int *value) -{ - int lower = EEPROM.read(address); - int higher = EEPROM.read(address + 1); - *value = lower + (higher << 8); - return 2; -} -int configuration::saveInt(int address, int value) -{ - byte lowByte = value & 0xFF; - byte highByte = ((value >> 8) & 0xFF); - - EEPROM.write(address, lowByte); - EEPROM.write(address + 1, highByte); - - return 2; -} - -int configuration::readBool(int address, bool *value) -{ - byte y = EEPROM.read(address); - *value = (bool)y; - return 1; -} - -int configuration::saveBool(int address, bool value) -{ - byte y = (byte)value; - EEPROM.write(address, y); - return 1; -} - -int configuration::readByte(int address, byte *value) -{ - *value = EEPROM.read(address); - return 1; -} - -int configuration::saveByte(int address, byte value) -{ - EEPROM.write(address, value); - return 1; -} -void configuration::print(Stream* debugger) -{ - debugger->println("Configuration:"); - debugger->println("-----------------------------------------------"); - debugger->printf("ssid: %s\r\n", this->ssid); - debugger->printf("ssidPassword: %s\r\n", this->ssidPassword); - debugger->printf("meterType: %i\r\n", this->meterType); - if(this->mqttHost) { - debugger->printf("mqttHost: %s\r\n", this->mqttHost); - debugger->printf("mqttPort: %i\r\n", this->mqttPort); - debugger->printf("mqttClientID: %s\r\n", this->mqttClientID); - debugger->printf("mqttPublishTopic: %s\r\n", this->mqttPublishTopic); - debugger->printf("mqttSubscribeTopic: %s\r\n", this->mqttSubscribeTopic); - } - - if (this->isSecure()) - { - debugger->printf("SECURE MQTT CONNECTION:\r\n"); - debugger->printf("mqttUser: %s\r\n", this->mqttUser); - debugger->printf("mqttPass: %s\r\n", this->mqttPass); - } - - 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->printf("distSys: %i\r\n", this->distSys); - - debugger->println("-----------------------------------------------"); -} - -template int configuration::writeAnything(int ee, const T& value) -{ - const byte* p = (const byte*)(const void*)&value; - unsigned int i; - for (i = 0; i < sizeof(value); i++) - EEPROM.write(ee++, *p++); - return i; -} - -template int configuration::readAnything(int ee, T& value) -{ - byte* p = (byte*)(void*)&value; - unsigned int i; - for (i = 0; i < sizeof(value); i++) - *p++ = EEPROM.read(ee++); - return i; -} - -int configuration::readString(int pAddress, char* pString[]) -{ - int address = 0; - byte length = EEPROM.read(pAddress + address); - address++; - - char* buffer = new char[length]; - for (int i = 0; i - - -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - -class configuration { -public: - char* ssid; - char* ssidPassword; - char* mqttHost; - int mqttPort = 1883; - char* mqttClientID; - char* mqttPublishTopic; - char* mqttSubscribeTopic; - char* mqttUser; - char* mqttPass; - byte meterType; - - byte authSecurity; - char* authUser; - char* authPass; - - int fuseSize; - byte distSys; - - bool hasConfig(); - bool isSecure(); - bool save(); - bool load(); - - void print(Stream* debugger); -protected: - -private: - const int EEPROM_SIZE = 512; - const byte EEPROM_CHECK_SUM = 75; // Used to check if config is stored. Change if structure changes - const int EEPROM_CONFIG_ADDRESS = 0; - - int saveString(int pAddress, char* pString); - int readString(int pAddress, char* pString[]); - int saveInt(int pAddress, int pValue); - int readInt(int pAddress, int *pValue); - int saveBool(int pAddress, bool pValue); - int readBool(int pAddress, bool *pValue); - int saveByte(int pAddress, byte pValue); - int readByte(int pAddress, byte *pValue); - - - template int writeAnything(int ee, const T& value); - template int readAnything(int ee, T& value); -}; - -#endif - diff --git a/platformio.ini b/platformio.ini index 326212b3..70b94fff 100755 --- a/platformio.ini +++ b/platformio.ini @@ -4,7 +4,7 @@ extra_configs = platformio-user.ini [common] framework = arduino -lib_deps = HanConfigAp@1.0.0, HanReader@1.0.0, HanToJson@1.0.0, ArduinoJson@^6.0.0, MQTT@^2.4.0, DallasTemperature@^3.8.0, EspSoftwareSerial@^6.7.1 +lib_deps = HanReader@1.0.0, HanToJson@1.0.0, ArduinoJson@^6.0.0, MQTT@^2.4.0, DallasTemperature@^3.8.0, EspSoftwareSerial@^6.7.1 [env:hw1esp12e] platform = espressif8266 diff --git a/src/AmsConfiguration.cpp b/src/AmsConfiguration.cpp new file mode 100644 index 00000000..f72b874f --- /dev/null +++ b/src/AmsConfiguration.cpp @@ -0,0 +1,467 @@ +#include "AmsConfiguration.h" + +String AmsConfiguration::getWifiSsid() { + return wifiSsid; +} + +void AmsConfiguration::setWifiSsid(String wifiSsid) { + wifiChanged |= this->wifiSsid != wifiSsid; + this->wifiSsid = String(wifiSsid); +} + +String AmsConfiguration::getWifiPassword() { + return wifiPassword; +} + +void AmsConfiguration::setWifiPassword(String wifiPassword) { + wifiChanged |= this->wifiPassword != wifiPassword; + this->wifiPassword = String(wifiPassword); +} + +String AmsConfiguration::getWifiIp() { + return wifiIp; +} + +void AmsConfiguration::setWifiIp(String wifiIp) { + wifiChanged |= this->wifiIp != wifiIp; + this->wifiIp = String(wifiIp); +} + +String AmsConfiguration::getWifiGw() { + return wifiGw; +} + +void AmsConfiguration::setWifiGw(String wifiGw) { + wifiChanged |= this->wifiGw != wifiGw; + this->wifiGw = String(wifiGw); +} + +String AmsConfiguration::getWifiSubnet() { + return wifiSubnet; +} + +void AmsConfiguration::setWifiSubnet(String wifiSubnet) { + wifiChanged |= this->wifiSubnet != wifiSubnet; + this->wifiSubnet = String(wifiSubnet); +} + +void AmsConfiguration::clearWifiIp() { + setWifiIp(""); + setWifiGw(""); + setWifiSubnet(""); +} + +bool AmsConfiguration::isWifiChanged() { + return wifiChanged; +} + +void AmsConfiguration::ackWifiChange() { + wifiChanged = false; +} + + +String AmsConfiguration::getMqttHost() { + return mqttHost; +} + +void AmsConfiguration::setMqttHost(String mqttHost) { + mqttChanged |= this->mqttHost != mqttHost; + this->mqttHost = String(mqttHost); +} + +int AmsConfiguration::getMqttPort() { + return mqttPort; +} + +void AmsConfiguration::setMqttPort(int mqttPort) { + mqttChanged |= this->mqttPort != mqttPort; + this->mqttPort = mqttPort; +} + +String AmsConfiguration::getMqttClientId() { + return mqttClientId; +} + +void AmsConfiguration::setMqttClientId(String mqttClientId) { + mqttChanged |= this->mqttClientId != mqttClientId; + this->mqttClientId = String(mqttClientId); +} + +String AmsConfiguration::getMqttPublishTopic() { + return mqttPublishTopic; +} + +void AmsConfiguration::setMqttPublishTopic(String mqttPublishTopic) { + mqttChanged |= this->mqttPublishTopic != mqttPublishTopic; + this->mqttPublishTopic = String(mqttPublishTopic); +} + +String AmsConfiguration::getMqttSubscribeTopic() { + return mqttSubscribeTopic; +} + +void AmsConfiguration::setMqttSubscribeTopic(String mqttSubscribeTopic) { + mqttChanged |= this->mqttSubscribeTopic != mqttSubscribeTopic; + this->mqttSubscribeTopic = String(mqttSubscribeTopic); +} + +String AmsConfiguration::getMqttUser() { + return mqttUser; +} + +void AmsConfiguration::setMqttUser(String mqttUser) { + mqttChanged |= this->mqttUser != mqttUser; + this->mqttUser = String(mqttUser); +} + +String AmsConfiguration::getMqttPassword() { + return mqttPassword; +} + +void AmsConfiguration::setMqttPassword(String mqttPassword) { + mqttChanged |= this->mqttPassword != mqttPassword; + this->mqttPassword = String(mqttPassword); +} + +void AmsConfiguration::clearMqtt() { + setMqttHost(""); + setMqttPort(1883); + setMqttClientId(""); + setMqttPublishTopic(""); + setMqttSubscribeTopic(""); + setMqttUser(""); + setMqttPassword(""); +} + +bool AmsConfiguration::isMqttChanged() { + return mqttChanged; +} + +void AmsConfiguration::ackMqttChange() { + mqttChanged = false; +} + + +byte AmsConfiguration::getAuthSecurity() { + return authSecurity; +} + +void AmsConfiguration::setAuthSecurity(byte authSecurity) { + this->authSecurity = authSecurity; +} + +String AmsConfiguration::getAuthUser() { + return authUser; +} + +void AmsConfiguration::setAuthUser(String authUser) { + this->authUser = String(authUser); +} + +String AmsConfiguration::getAuthPassword() { + return authPassword; +} + +void AmsConfiguration::setAuthPassword(String authPassword) { + this->authPassword = String(authPassword); +} + +void AmsConfiguration::clearAuth() { + setAuthSecurity(0); + setAuthUser(""); + setAuthPassword(""); +} + +int AmsConfiguration::getMeterType() { + return this->meterType; +} + +void AmsConfiguration::setMeterType(int meterType) { + this->meterType = meterType; +} + +int AmsConfiguration::getDistributionSystem() { + return this->distributionSystem; +} + +void AmsConfiguration::setDistributionSystem(int distributionSystem) { + this->distributionSystem = distributionSystem; +} + +int AmsConfiguration::getMainFuse() { + return this->mainFuse; +} + +void AmsConfiguration::setMainFuse(int mainFuse) { + this->mainFuse = mainFuse; +} + +int AmsConfiguration::getProductionCapacity() { + return this->productionCapacity; +} + +void AmsConfiguration::setProductionCapacity(int productionCapacity) { + this->productionCapacity = productionCapacity; +} + + +bool AmsConfiguration::hasConfig() +{ + bool hasConfig = false; + EEPROM.begin(EEPROM_SIZE); + hasConfig = EEPROM.read(EEPROM_CONFIG_ADDRESS) == EEPROM_CHECK_SUM; + EEPROM.end(); + return hasConfig; +} + +bool AmsConfiguration::load() { + int address = EEPROM_CONFIG_ADDRESS; + bool success = false; + + EEPROM.begin(EEPROM_SIZE); + int cs = EEPROM.read(address); + if (cs == EEPROM_CHECK_SUM) + { + char* temp; + address++; + + address += readString(address, &temp); + setWifiSsid(temp); + address += readString(address, &temp); + setWifiPassword(temp); + address += readString(address, &temp); + setWifiIp(temp); + address += readString(address, &temp); + setWifiGw(temp); + address += readString(address, &temp); + setWifiSubnet(temp); + + bool mqtt = false; + address += readBool(address, &mqtt); + if(mqtt) { + address += readString(address, &temp); + setMqttHost(temp); + int port; + address += readInt(address, &port); + setMqttPort(port); + address += readString(address, &temp); + setMqttClientId(temp); + address += readString(address, &temp); + setMqttPublishTopic(temp); + address += readString(address, &temp); + setMqttSubscribeTopic(temp); + + bool secure = false; + address += readBool(address, &secure); + if (secure) + { + address += readString(address, &temp); + setMqttUser(temp); + address += readString(address, &temp); + setMqttPassword(temp); + } else { + setMqttUser(""); + setMqttPassword(""); + } + } else { + clearMqtt(); + } + + address += readByte(address, &authSecurity); + if (authSecurity > 0) { + address += readString(address, &temp); + setAuthUser(temp); + address += readString(address, &temp); + setAuthPassword(temp); + } else { + clearAuth(); + } + + int i; + address += readInt(address, &i); + setMeterType(i); + address += readInt(address, &i); + setDistributionSystem(i); + address += readInt(address, &i); + setMainFuse(i); + address += readInt(address, &i); + setProductionCapacity(i); + + ackWifiChange(); + + success = true; + } + return success; +} + +bool AmsConfiguration::save() { + int address = EEPROM_CONFIG_ADDRESS; + + EEPROM.begin(EEPROM_SIZE); + EEPROM.put(address, EEPROM_CHECK_SUM); + address++; + + address += saveString(address, wifiSsid.c_str()); + address += saveString(address, wifiPassword.c_str()); + address += saveString(address, wifiIp.c_str()); + address += saveString(address, wifiGw.c_str()); + address += saveString(address, wifiSubnet.c_str()); + if(mqttHost) { + address += saveBool(address, true); + address += saveString(address, mqttHost.c_str()); + address += saveInt(address, mqttPort); + address += saveString(address, mqttClientId.c_str()); + address += saveString(address, mqttPublishTopic.c_str()); + address += saveString(address, mqttSubscribeTopic.c_str()); + if (mqttUser) { + address += saveBool(address, true); + address += saveString(address, mqttUser.c_str()); + address += saveString(address, mqttPassword.c_str()); + } else { + address += saveBool(address, false); + } + } else { + address += saveBool(address, false); + } + + address += saveByte(address, authSecurity); + if (authSecurity > 0) { + address += saveString(address, authUser.c_str()); + address += saveString(address, authPassword.c_str()); + } + + address += saveInt(address, meterType); + address += saveInt(address, distributionSystem); + address += saveInt(address, mainFuse); + address += saveInt(address, productionCapacity); + + bool success = EEPROM.commit(); + EEPROM.end(); + + return success; +} + +int AmsConfiguration::readString(int pAddress, char* pString[]) { + int address = 0; + byte length = EEPROM.read(pAddress + address); + address++; + + char* buffer = new char[length]; + for (int i = 0; i> 8) & 0xFF); + + EEPROM.write(address, lowByte); + EEPROM.write(address + 1, highByte); + + return 2; +} + +int AmsConfiguration::readBool(int address, bool *value) { + byte y = EEPROM.read(address); + *value = (bool)y; + return 1; +} + +int AmsConfiguration::saveBool(int address, bool value) { + byte y = (byte)value; + EEPROM.write(address, y); + return 1; +} + +int AmsConfiguration::readByte(int address, byte *value) { + *value = EEPROM.read(address); + return 1; +} + +int AmsConfiguration::saveByte(int address, byte value) { + EEPROM.write(address, value); + return 1; +} + +template int AmsConfiguration::writeAnything(int ee, const T& value) { + const byte* p = (const byte*)(const void*)&value; + unsigned int i; + for (i = 0; i < sizeof(value); i++) + EEPROM.write(ee++, *p++); + return i; +} + +template int AmsConfiguration::readAnything(int ee, T& value) { + byte* p = (byte*)(void*)&value; + unsigned int i; + for (i = 0; i < sizeof(value); i++) + *p++ = EEPROM.read(ee++); + return i; +} + +void AmsConfiguration::print(Stream* debugger) +{ + debugger->println("Configuration:"); + debugger->println("-----------------------------------------------"); + debugger->printf("WiFi SSID: %s\r\n", this->getWifiSsid().c_str()); + debugger->printf("WiFi Psk: %s\r\n", this->getWifiPassword().c_str()); + + if(getWifiIp()) { + debugger->printf("IP: %s\r\n", this->getWifiIp().c_str()); + debugger->printf("Gateway: %s\r\n", this->getWifiGw().c_str()); + debugger->printf("Subnet: %s\r\n", this->getWifiSubnet().c_str()); + } + + if(getMqttHost()) { + debugger->printf("mqttHost: %s\r\n", this->getMqttHost().c_str()); + debugger->printf("mqttPort: %i\r\n", this->getMqttPort()); + debugger->printf("mqttClientID: %s\r\n", this->getMqttClientId().c_str()); + debugger->printf("mqttPublishTopic: %s\r\n", this->getMqttPublishTopic().c_str()); + debugger->printf("mqttSubscribeTopic: %s\r\n", this->getMqttSubscribeTopic().c_str()); + if (this->getMqttUser()) { + debugger->printf("SECURE MQTT CONNECTION:\r\n"); + debugger->printf("mqttUser: %s\r\n", this->getMqttUser().c_str()); + debugger->printf("mqttPass: %s\r\n", this->getMqttPassword().c_str()); + } + } + + if (this->getAuthSecurity()) { + debugger->printf("WEB AUTH:\r\n"); + debugger->printf("authSecurity: %i\r\n", this->getAuthSecurity()); + debugger->printf("authUser: %s\r\n", this->getAuthUser().c_str()); + debugger->printf("authPass: %s\r\n", this->getAuthPassword().c_str()); + } + + debugger->printf("meterType: %i\r\n", this->getMeterType()); + debugger->printf("distSys: %i\r\n", this->getDistributionSystem()); + debugger->printf("fuseSize: %i\r\n", this->getMainFuse()); + debugger->printf("productionCapacity: %i\r\n", this->getProductionCapacity()); + + debugger->println("-----------------------------------------------"); +} diff --git a/src/AmsConfiguration.h b/src/AmsConfiguration.h new file mode 100644 index 00000000..3c17b1e6 --- /dev/null +++ b/src/AmsConfiguration.h @@ -0,0 +1,106 @@ +#ifndef _AMSCONFIGURATION_h +#define _AMSCONFIGURATION_h +#include +#include "Arduino.h" + +class AmsConfiguration { +public: + bool hasConfig(); + bool load(); + bool save(); + + String getWifiSsid(); + void setWifiSsid(String wifiSsid); + String getWifiPassword(); + void setWifiPassword(String wifiPassword); + String getWifiIp(); + void setWifiIp(String wifiIp); + String getWifiGw(); + void setWifiGw(String wifiGw); + String getWifiSubnet(); + void setWifiSubnet(String wifiSubnet); + void clearWifiIp(); + + bool isWifiChanged(); + void ackWifiChange(); + + String getMqttHost(); + void setMqttHost(String mqttHost); + int getMqttPort(); + void setMqttPort(int mqttPort); + String getMqttClientId(); + void setMqttClientId(String mqttClientId); + String getMqttPublishTopic(); + void setMqttPublishTopic(String mqttPublishTopic); + String getMqttSubscribeTopic(); + void setMqttSubscribeTopic(String mqttSubscribeTopic); + String getMqttUser(); + void setMqttUser(String mqttUser); + String getMqttPassword(); + void setMqttPassword(String mqttPassword); + void clearMqtt(); + + bool isMqttChanged(); + void ackMqttChange(); + + byte getAuthSecurity(); + void setAuthSecurity(byte authSecurity); + String getAuthUser(); + void setAuthUser(String authUser); + String getAuthPassword(); + void setAuthPassword(String authPassword); + void clearAuth(); + + int getMeterType(); + void setMeterType(int meterType); + int getDistributionSystem(); + void setDistributionSystem(int distributionSystem); + int getMainFuse(); + void setMainFuse(int mainFuse); + int getProductionCapacity(); + void setProductionCapacity(int productionCapacity); + + void print(Stream* debugger); + +protected: + +private: + String wifiSsid; + String wifiPassword; + String wifiIp; + String wifiGw; + String wifiSubnet; + bool wifiChanged; + + String mqttHost; + int mqttPort; + String mqttClientId; + String mqttPublishTopic; + String mqttSubscribeTopic; + String mqttUser; + String mqttPassword; + bool mqttChanged; + + byte authSecurity; + String authUser; + String authPassword; + + int meterType, distributionSystem, mainFuse, productionCapacity; + + const int EEPROM_SIZE = 512; + const byte EEPROM_CHECK_SUM = 80; // Used to check if config is stored. Change if structure changes + const int EEPROM_CONFIG_ADDRESS = 0; + + int saveString(int pAddress, const char* pString); + int readString(int pAddress, char* pString[]); + int saveInt(int pAddress, int pValue); + int readInt(int pAddress, int *pValue); + int saveBool(int pAddress, bool pValue); + int readBool(int pAddress, bool *pValue); + int saveByte(int pAddress, byte pValue); + int readByte(int pAddress, byte *pValue); + + template int writeAnything(int ee, const T& value); + template int readAnything(int ee, T& value); +}; +#endif diff --git a/src/AmsToMqttBridge.h b/src/AmsToMqttBridge.h index 0b984c9f..8245abeb 100644 --- a/src/AmsToMqttBridge.h +++ b/src/AmsToMqttBridge.h @@ -1,5 +1,7 @@ #define WIFI_CONNECTION_TIMEOUT 30000; +#define INVALID_BUTTON_PIN 0xFFFFFFFF + #if defined(ESP8266) #include diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index 4396bff9..92ae320f 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -6,14 +6,15 @@ #if defined(ESP8266) ADC_MODE(ADC_VCC); -#endif +#endif #include "AmsToMqttBridge.h" #include #include +#include #include "web/AmsWebServer.h" -#include "HanConfigAp.h" +#include "AmsConfiguration.h" #include "HanReader.h" #include "HanToJson.h" @@ -21,11 +22,10 @@ ADC_MODE(ADC_VCC); #include "Kaifa.h" #include "Kamstrup.h" -// Configuration -configuration config; +DNSServer dnsServer; -// Object used to boot as Access Point -HanConfigAp ap; +// Configuration +AmsConfiguration config; // Web server AmsWebServer ws; @@ -51,7 +51,7 @@ void setup() { #if SOFTWARE_SERIAL debugger->begin(115200, SERIAL_8N1); #else - if(config.meterType == 3) { + if(config.getMeterType() == 3) { hanSerial->begin(2400, SERIAL_8N1); } else { hanSerial->begin(2400, SERIAL_8E1); @@ -84,27 +84,31 @@ void setup() { // Flash the LED, to indicate we can boot as AP now pinMode(LED_PIN, OUTPUT); - led_on(); + pinMode(AP_BUTTON_PIN, INPUT_PULLUP); - delay(1000); + WiFi.disconnect(true); + WiFi.softAPdisconnect(true); + WiFi.mode(WIFI_OFF); - // Initialize the AP - ap.setup(AP_BUTTON_PIN, &config, debugger); - - led_off(); - - if (!ap.isActivated) { - setupWiFi(); + if(config.hasConfig()) { + if(debugger) config.print(debugger); + client = new WiFiClient(); + } else { + if(debugger) { + debugger->println("No configuration, booting AP"); + } + swapWifiMode(); } #if defined SOFTWARE_SERIAL - if(config.meterType == 3) { + if(config.getMeterType() == 3) { hanSerial->begin(2400, SWSERIAL_8N1); } else { hanSerial->begin(2400, SWSERIAL_8E1); } +#elif defined DEBUG_MODE #else - if(config.meterType == 3) { + if(config.getMeterType() == 3) { hanSerial->begin(2400, SERIAL_8N1); } else { hanSerial->begin(2400, SERIAL_8E1); @@ -113,20 +117,44 @@ void setup() { hanSerial->swap(); #endif #endif - while (!&hanSerial); - hanReader.setup(hanSerial, debugger); + hanReader.setup(hanSerial, 0); // Compensate for the known Kaifa bug - hanReader.compensateFor09HeaderBug = (config.meterType == 1); + hanReader.compensateFor09HeaderBug = (config.getMeterType() == 1); ws.setup(&config, debugger, &mqtt); } -// the loop function runs over and over again until power down or reset +int buttonTimer = 0; +bool buttonActive = false; +unsigned long longPressTime = 5000; +bool longPressActive = false; + void loop() { + if (digitalRead(AP_BUTTON_PIN) == LOW) { + if (buttonActive == false) { + buttonActive = true; + buttonTimer = millis(); + } + + if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) { + longPressActive = true; + swapWifiMode(); + } + } else { + if (buttonActive == true) { + if (longPressActive == true) { + longPressActive = false; + } else { + // Single press action + } + buttonActive = false; + } + } + // Only do normal stuff if we're not booted as AP - if (!ap.loop()) { + if (WiFi.getMode() != WIFI_AP) { // Turn off the LED led_off(); @@ -134,15 +162,19 @@ void loop() { if (WiFi.status() != WL_CONNECTED) { WiFi_connect(); } else { - if (config.mqttHost) { + if (!config.getMqttHost().isEmpty()) { mqtt.loop(); yield(); - if(!mqtt.connected()) { + if(!mqtt.connected() || config.isMqttChanged()) { MQTT_connect(); } + } else if(mqtt.connected()) { + mqtt.disconnect(); + yield(); } } } else { + dnsServer.processNextRequest(); // Continously flash the LED when AP mode if (millis() / 50 % 64 == 0) led_on(); else led_off(); @@ -157,6 +189,7 @@ void loop() { } readHanPort(); ws.loop(); + delay(1); // Needed for auto modem sleep } @@ -179,25 +212,28 @@ void led_off() #endif } +void swapWifiMode() { + led_on(); + WiFiMode_t mode = WiFi.getMode(); + dnsServer.stop(); + WiFi.disconnect(true); + WiFi.softAPdisconnect(true); + WiFi.mode(WIFI_OFF); + yield(); -void setupWiFi() -{ - // Turn off AP - WiFi.enableAP(false); + if (mode != WIFI_AP) { + if(debugger) debugger->println("Swapping to AP mode"); + WiFi.softAP("AMS2MQTT"); + WiFi.mode(WIFI_AP); - // Connect to WiFi - WiFi.mode(WIFI_STA); - WiFi.begin(config.ssid, config.ssidPassword); - - // Wait for WiFi connection - if (debugger) debugger->print("\nWaiting for WiFi to connect..."); - while (WiFi.status() != WL_CONNECTED) { - if (debugger) debugger->print("."); - delay(500); + dnsServer.setErrorReplyCode(DNSReplyCode::NoError); + dnsServer.start(53, "*", WiFi.softAPIP()); + } else { + if(debugger) debugger->println("Swapping to STA mode"); + WiFi_connect(); } - if (debugger) debugger->println(" connected"); - - client = new WiFiClient(); + delay(500); + led_off(); } void mqttMessageReceived(String &topic, String &payload) @@ -221,7 +257,7 @@ void readHanPort() { if (hanReader.read()) { lastSuccessfulRead = millis(); - if(config.meterType > 0) { + if(config.getMeterType() > 0) { // Flash LED on, this shows us that data is received led_on(); @@ -254,9 +290,9 @@ void readHanPort() { data["temp"] = tempSensor.getTempCByIndex(0); #endif - hanToJson(data, config.meterType, hanReader); + hanToJson(data, config.getMeterType(), hanReader); - if(config.mqttHost != 0 && strlen(config.mqttHost) != 0 && config.mqttPublishTopic != 0 && strlen(config.mqttPublishTopic) != 0) { + if(!config.getMqttHost().isEmpty() && !config.getMqttPublishTopic().isEmpty()) { // Write the json to the debug port if (debugger) { debugger->print("Sending data to MQTT: "); @@ -268,7 +304,7 @@ void readHanPort() { String msg; serializeJson(json, msg); - mqtt.publish(config.mqttPublishTopic, msg.c_str()); + mqtt.publish(config.getMqttPublishTopic(), msg.c_str()); mqtt.loop(); } ws.setJson(json); @@ -292,26 +328,27 @@ void readHanPort() { if(!list.isEmpty()) { list.toLowerCase(); if(list.startsWith("kfm")) { - config.meterType = 1; + config.setMeterType(1); if(debugger) debugger->println("Detected Kaifa meter"); break; } else if(list.startsWith("aidon")) { - config.meterType = 2; + config.setMeterType(2); if(debugger) debugger->println("Detected Aidon meter"); break; } else if(list.startsWith("kamstrup")) { - config.meterType = 3; + config.setMeterType(3); if(debugger) debugger->println("Detected Kamstrup meter"); break; } } } - hanReader.compensateFor09HeaderBug = (config.meterType == 1); + hanReader.compensateFor09HeaderBug = (config.getMeterType() == 1); } } - if(config.meterType == 0 && millis() - lastSuccessfulRead > 10000) { + if(config.getMeterType() == 0 && millis() - lastSuccessfulRead > 10000) { lastSuccessfulRead = millis(); + if(debugger) debugger->println("No data for current setting, switching parity"); #if defined SOFTWARE_SERIAL if(even) { hanSerial->begin(2400, SWSERIAL_8N1); @@ -329,59 +366,45 @@ void readHanPort() { } } +unsigned long wifiTimeout = WIFI_CONNECTION_TIMEOUT; +unsigned long lastWifiRetry = -WIFI_CONNECTION_TIMEOUT; void WiFi_connect() { - // Connect to WiFi access point. + if(millis() - lastWifiRetry < wifiTimeout) { + delay(50); + return; + } + lastWifiRetry = millis(); + if (debugger) { debugger->println(); debugger->println(); debugger->print("Connecting to WiFi network "); - debugger->println(config.ssid); + debugger->println(config.getWifiSsid()); } - if (WiFi.status() != WL_CONNECTED) - { - // Make one first attempt at connect, this seems to considerably speed up the first connection + if (WiFi.status() != WL_CONNECTED) { WiFi.disconnect(); - WiFi.begin(config.ssid, config.ssidPassword); - delay(1000); - } - - // Wait for the WiFi connection to complete - long vTimeout = millis() + WIFI_CONNECTION_TIMEOUT; - while (WiFi.status() != WL_CONNECTED) { - delay(50); - if (debugger) debugger->print("."); - - // If we timed out, disconnect and try again - if (vTimeout < millis()) - { - if (debugger) - { - debugger->print("Timout during connect. WiFi status is: "); - debugger->println(WiFi.status()); - } - WiFi.disconnect(); - WiFi.begin(config.ssid, config.ssidPassword); - vTimeout = millis() + WIFI_CONNECTION_TIMEOUT; - } yield(); - } - if (debugger) { - debugger->println(); - debugger->println("WiFi connected"); - debugger->println("IP address: "); - debugger->println(WiFi.localIP()); + WiFi.enableAP(false); + WiFi.mode(WIFI_STA); + WiFi.setOutputPower(0); + if(!config.getWifiIp().isEmpty()) { + IPAddress ip, gw, sn(255,255,255,0); + ip.fromString(config.getWifiIp()); + gw.fromString(config.getWifiGw()); + sn.fromString(config.getWifiSubnet()); + WiFi.config(ip, gw, sn); + } + WiFi.begin(config.getWifiSsid().c_str(), config.getWifiPassword().c_str()); + yield(); } } -// Function to connect and reconnect as necessary to the MQTT server. -// Should be called in the loop function and it will take care if connecting. - unsigned long lastMqttRetry = -10000; void MQTT_connect() { - if(!config.mqttHost) { + if(config.getMqttHost().isEmpty()) { if(debugger) debugger->println("No MQTT config"); return; } @@ -392,25 +415,27 @@ void MQTT_connect() { lastMqttRetry = millis(); if(debugger) { debugger->print("Connecting to MQTT: "); - debugger->print(config.mqttHost); + debugger->print(config.getMqttHost()); debugger->print(", port: "); - debugger->print(config.mqttPort); + debugger->print(config.getMqttPort()); debugger->println(); } mqtt.disconnect(); + yield(); - mqtt.begin(config.mqttHost, config.mqttPort, *client); + mqtt.begin(config.getMqttHost().c_str(), config.getMqttPort(), *client); // Connect to a unsecure or secure MQTT server - if ((config.mqttUser == 0 && mqtt.connect(config.mqttClientID)) || - (config.mqttUser != 0 && mqtt.connect(config.mqttClientID, config.mqttUser, config.mqttPass))) { + if ((config.getMqttUser().isEmpty() && mqtt.connect(config.getMqttClientId().c_str())) || + (!config.getMqttUser().isEmpty() && mqtt.connect(config.getMqttClientId().c_str(), config.getMqttUser().c_str(), config.getMqttPassword().c_str()))) { if (debugger) debugger->println("\nSuccessfully connected to MQTT!"); + config.ackMqttChange(); // Subscribe to the chosen MQTT topic, if set in configuration - if (config.mqttSubscribeTopic != 0 && strlen(config.mqttSubscribeTopic) > 0) { - mqtt.subscribe(config.mqttSubscribeTopic); - if (debugger) debugger->printf(" Subscribing to [%s]\r\n", config.mqttSubscribeTopic); + if (!config.getMqttSubscribeTopic().isEmpty()) { + mqtt.subscribe(config.getMqttSubscribeTopic()); + if (debugger) debugger->printf(" Subscribing to [%s]\r\n", config.getMqttSubscribeTopic().c_str()); } sendMqttData("Connected!"); @@ -427,7 +452,7 @@ void MQTT_connect() { void sendMqttData(String data) { // Make sure we have configured a publish topic - if (config.mqttPublishTopic == 0 || strlen(config.mqttPublishTopic) == 0) + if (config.getMqttPublishTopic().isEmpty()) return; // Build a json with the message in a "data" attribute @@ -438,13 +463,16 @@ void sendMqttData(String data) #if defined(ESP8266) json["vcc"] = ((double) ESP.getVcc()) / 1000; #endif + float rssi = WiFi.RSSI(); + rssi = isnan(rssi) ? -100.0 : rssi; + json["rssi"] = rssi; // Stringify the json String msg; serializeJson(json, msg); // Send the json over MQTT - mqtt.publish(config.mqttPublishTopic, msg.c_str()); + mqtt.publish(config.getMqttPublishTopic(), msg.c_str()); if (debugger) debugger->print("sendMqttData: "); if (debugger) debugger->println(data); diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index fcd5c17c..f5dd4648 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -2,7 +2,10 @@ #include "version.h" #include "root/index_html.h" -#include "root/configuration_html.h" +#include "root/configmeter_html.h" +#include "root/configwifi_html.h" +#include "root/configmqtt_html.h" +#include "root/configweb_html.h" #include "root/boot_css.h" #include "root/gaugemeter_js.h" @@ -14,13 +17,16 @@ ESP8266WebServer server(80); WebServer server(80); #endif -void AmsWebServer::setup(configuration* config, Stream* debugger, MQTTClient* mqtt) { +void AmsWebServer::setup(AmsConfiguration* config, Stream* debugger, MQTTClient* mqtt) { this->config = config; this->debugger = debugger; this->mqtt = mqtt; server.on("/", std::bind(&AmsWebServer::indexHtml, this)); - server.on("/configuration", std::bind(&AmsWebServer::configurationHtml, this)); + server.on("/config/meter", std::bind(&AmsWebServer::configMeterHtml, this)); + server.on("/config/wifi", std::bind(&AmsWebServer::configWifiHtml, this)); + server.on("/config/mqtt", std::bind(&AmsWebServer::configMqttHtml, this)); + server.on("/config/web", std::bind(&AmsWebServer::configWebHtml, this)); server.on("/boot.css", std::bind(&AmsWebServer::bootCss, this)); server.on("/gaugemeter.js", std::bind(&AmsWebServer::gaugemeterJs, this)); server.on("/data.json", std::bind(&AmsWebServer::dataJson, this)); @@ -28,14 +34,6 @@ void AmsWebServer::setup(configuration* config, Stream* debugger, MQTTClient* mq server.on("/save", std::bind(&AmsWebServer::handleSave, this)); server.begin(); // Web server start - - print("Web server is ready for config at http://"); - if(WiFi.getMode() == WIFI_AP) { - print(WiFi.softAPIP()); - } else { - print(WiFi.localIP()); - } - println("/"); } void AmsWebServer::loop() { @@ -60,12 +58,12 @@ void AmsWebServer::setJson(StaticJsonDocument<1024> json) { } } - if(maxPwr == 0 && config->hasConfig() && config->fuseSize > 0 && config->distSys > 0) { - int volt = config->distSys == 2 ? 400 : 230; + if(maxPwr == 0 && config->hasConfig() && config->getMainFuse() > 0 && config->getDistributionSystem() > 0) { + int volt = config->getDistributionSystem() == 2 ? 400 : 230; if(u2 > 0) { - maxPwr = config->fuseSize * sqrt(3) * volt; + maxPwr = config->getMainFuse() * sqrt(3) * volt; } else { - maxPwr = config->fuseSize * 230; + maxPwr = config->getMainFuse() * 230; } } @@ -100,10 +98,10 @@ void AmsWebServer::setJson(StaticJsonDocument<1024> json) { } bool AmsWebServer::checkSecurity(byte level) { - bool access = WiFi.getMode() == WIFI_AP || !config->hasConfig() || config->authSecurity < level; - if(!access && config->authSecurity >= level && server.hasHeader("Authorization")) { + bool access = WiFi.getMode() == WIFI_AP || !config->hasConfig() || config->getAuthSecurity() < level; + if(!access && config->getAuthSecurity() >= level && server.hasHeader("Authorization")) { println(" forcing web security"); - String expectedAuth = String(config->authUser) + ":" + String(config->authPass); + String expectedAuth = String(config->getAuthUser()) + ":" + String(config->getAuthPassword()); String providedPwd = server.header("Authorization"); providedPwd.replace("Basic ", ""); @@ -173,46 +171,99 @@ void AmsWebServer::indexHtml() { server.send(200, "text/html", html); } -void AmsWebServer::configurationHtml() { - println("Serving /configuration.html over http..."); +void AmsWebServer::configMeterHtml() { + println("Serving /config/meter.html over http..."); if(!checkSecurity(1)) return; - String html = String((const __FlashStringHelper*) CONFIGURATION_HTML); + String html = String((const __FlashStringHelper*) CONFIGMETER_HTML); html.replace("${version}", VERSION); 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); - html.replace("${config.meterType}", String(config->fuseSize)); + html.replace("${config.meterType}", String(config->getMainFuse())); for(int i = 0; i<4; i++) { - html.replace("${config.meterType" + String(i) + "}", config->meterType == i ? "selected" : ""); + html.replace("${config.meterType" + String(i) + "}", config->getMeterType() == i ? "selected" : ""); } - html.replace("${config.mqtt}", config->mqttHost == 0 ? "" : "checked"); - html.replace("${config.mqttHost}", config->mqttHost); - 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)); + html.replace("${config.distributionSystem}", String(config->getDistributionSystem())); for(int i = 0; i<3; i++) { - html.replace("${config.authSecurity" + String(i) + "}", config->authSecurity == i ? "selected" : ""); + html.replace("${config.distributionSystem" + String(i) + "}", config->getDistributionSystem() == i ? "selected" : ""); } - html.replace("${config.authPass}", config->authPass); - html.replace("${config.fuseSize}", String(config->fuseSize)); + html.replace("${config.mainFuse}", String(config->getMainFuse())); for(int i = 0; i<64; i++) { - html.replace("${config.fuseSize" + String(i) + "}", config->fuseSize == i ? "selected" : ""); + html.replace("${config.mainFuse" + String(i) + "}", config->getMainFuse() == i ? "selected" : ""); } + html.replace("${config.productionCapacity}", String(config->getProductionCapacity())); + server.send(200, "text/html", html); +} + +void AmsWebServer::configWifiHtml() { + println("Serving /config/wifi.html over http..."); + + if(!checkSecurity(1)) + return; + + String html = String((const __FlashStringHelper*) CONFIGWIFI_HTML); + html.replace("${version}", VERSION); + + server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server.sendHeader("Pragma", "no-cache"); + + html.replace("${config.wifiSsid}", config->getWifiSsid()); + html.replace("${config.wifiPassword}", config->getWifiPassword()); + html.replace("${config.wifiIpType1}", config->getWifiIp().isEmpty() ? "" : "selected"); + html.replace("${config.wifiIp}", config->getWifiIp()); + html.replace("${config.wifiGw}", config->getWifiGw()); + html.replace("${config.wifiSubnet}", config->getWifiSubnet()); + + server.send(200, "text/html", html); +} + +void AmsWebServer::configMqttHtml() { + println("Serving /config/mqtt.html over http..."); + + if(!checkSecurity(1)) + return; + + String html = String((const __FlashStringHelper*) CONFIGMQTT_HTML); + html.replace("${version}", VERSION); + + server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server.sendHeader("Pragma", "no-cache"); + + html.replace("${config.mqtt}", config->getMqttHost() == 0 ? "" : "checked"); + html.replace("${config.mqttHost}", config->getMqttHost()); + html.replace("${config.mqttPort}", String(config->getMqttPort())); + html.replace("${config.mqttClientId}", config->getMqttClientId()); + html.replace("${config.mqttPublishTopic}", config->getMqttPublishTopic()); + html.replace("${config.mqttSubscribeTopic}", config->getMqttSubscribeTopic()); + html.replace("${config.mqttUser}", config->getMqttUser()); + html.replace("${config.mqttPassword}", config->getMqttPassword()); + + server.send(200, "text/html", html); +} + +void AmsWebServer::configWebHtml() { + println("Serving /config/web.html over http..."); + + if(!checkSecurity(1)) + return; + + String html = String((const __FlashStringHelper*) CONFIGWEB_HTML); + html.replace("${version}", VERSION); + + server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + server.sendHeader("Pragma", "no-cache"); + + html.replace("${config.authSecurity}", String(config->getAuthSecurity())); for(int i = 0; i<3; i++) { - html.replace("${config.distSys" + String(i) + "}", config->distSys == i ? "selected" : ""); + html.replace("${config.authSecurity" + String(i) + "}", config->getAuthSecurity() == i ? "selected" : ""); } + html.replace("${config.authUser}", config->getAuthUser()); + html.replace("${config.authPassword}", config->getAuthPassword()); + server.send(200, "text/html", html); } @@ -268,7 +319,7 @@ void AmsWebServer::dataJson() { unsigned long now = millis(); json["id"] = WiFi.macAddress(); json["maxPower"] = maxPwr; - json["meterType"] = config->meterType; + json["meterType"] = config->getMeterType(); json["currentMillis"] = now; double vcc = 0; @@ -300,7 +351,7 @@ void AmsWebServer::dataJson() { unsigned long lastHan = json.isNull() ? 0 : json["up"].as(); String hanStatus; - if(config->meterType == 0) { + if(config->getMeterType() == 0) { hanStatus = "secondary"; } else if(now - lastHan < 15000) { hanStatus = "success"; @@ -312,7 +363,7 @@ void AmsWebServer::dataJson() { json["status"]["han"] = hanStatus; String wifiStatus; - if(!config->ssid) { + if(config->getWifiSsid().isEmpty()) { wifiStatus = "secondary"; } else if(rssi > -75) { wifiStatus = "success"; @@ -324,7 +375,7 @@ void AmsWebServer::dataJson() { json["status"]["wifi"] = wifiStatus; String mqttStatus; - if(!config->mqttHost) { + if(config->getMqttHost().isEmpty()) { mqttStatus = "secondary"; } else if(mqtt->connected()) { mqttStatus = "success"; @@ -349,84 +400,72 @@ void AmsWebServer::dataJson() { void AmsWebServer::handleSave() { String temp; - temp = server.arg("ssid"); - config->ssid = new char[temp.length() + 1]; - temp.toCharArray(config->ssid, temp.length() + 1, 0); - - temp = server.arg("ssidPassword"); - config->ssidPassword = new char[temp.length() + 1]; - temp.toCharArray(config->ssidPassword, temp.length() + 1, 0); - - config->meterType = (byte)server.arg("meterType").toInt(); - - if(server.hasArg("mqtt") && server.arg("mqtt") == "true") { - println("MQTT enabled"); - temp = server.arg("mqttHost"); - config->mqttHost = new char[temp.length() + 1]; - temp.toCharArray(config->mqttHost, temp.length() + 1, 0); - - config->mqttPort = (int)server.arg("mqttPort").toInt(); - - temp = server.arg("mqttClientID"); - config->mqttClientID = new char[temp.length() + 1]; - temp.toCharArray(config->mqttClientID, temp.length() + 1, 0); - - temp = server.arg("mqttPublishTopic"); - config->mqttPublishTopic = new char[temp.length() + 1]; - temp.toCharArray(config->mqttPublishTopic, temp.length() + 1, 0); - - temp = server.arg("mqttSubscribeTopic"); - config->mqttSubscribeTopic = new char[temp.length() + 1]; - temp.toCharArray(config->mqttSubscribeTopic, temp.length() + 1, 0); - - temp = server.arg("mqttUser"); - config->mqttUser = new char[temp.length() + 1]; - temp.toCharArray(config->mqttUser, temp.length() + 1, 0); - - temp = server.arg("mqttPass"); - config->mqttPass = new char[temp.length() + 1]; - temp.toCharArray(config->mqttPass, temp.length() + 1, 0); - } else { - println("MQTT disabled"); - config->mqttHost = NULL; - config->mqttUser = NULL; - config->mqttPass = NULL; + if(server.hasArg("meterConfig") && server.arg("meterConfig") == "true") { + config->setMeterType(server.arg("meterType").toInt()); + config->setDistributionSystem(server.arg("distributionSystem").toInt()); + config->setMainFuse(server.arg("mainFuse").toInt()); + config->setProductionCapacity(server.arg("productionCapacity").toInt()); } - config->authSecurity = (byte)server.arg("authSecurity").toInt(); - - if(config->authSecurity > 0) { - temp = server.arg("authUser"); - config->authUser = new char[temp.length() + 1]; - temp.toCharArray(config->authUser, temp.length() + 1, 0); - - temp = server.arg("authPass"); - config->authPass = new char[temp.length() + 1]; - temp.toCharArray(config->authPass, temp.length() + 1, 0); + if(server.hasArg("wifiConfig") && server.arg("wifiConfig") == "true") { + config->setWifiSsid(server.arg("wifiSsid")); + config->setWifiPassword(server.arg("wifiPassword")); + if(server.hasArg("wifiIpType") && server.arg("wifiIpType").toInt() == 1) { + config->setWifiIp(server.arg("wifiIp")); + config->setWifiGw(server.arg("wifiGw")); + config->setWifiSubnet(server.arg("wifiSubnet")); + } else { + config->clearWifiIp(); + } } - config->fuseSize = (int)server.arg("fuseSize").toInt(); + if(server.hasArg("mqttConfig") && server.arg("mqttConfig") == "true") { + if(server.hasArg("mqtt") && server.arg("mqtt") == "true") { + config->setMqttHost(server.arg("mqttHost")); + config->setMqttPort(server.arg("mqttPort").toInt()); + config->setMqttClientId(server.arg("mqttClientId")); + config->setMqttPublishTopic(server.arg("mqttPublishTopic")); + config->setMqttSubscribeTopic(server.arg("mqttSubscribeTopic")); + config->setMqttUser(server.arg("mqttUser")); + config->setMqttPassword(server.arg("mqttPassword")); + config->setAuthUser(server.arg("authUser")); + config->setAuthPassword(server.arg("authPassword")); + } else { + config->clearMqtt(); + } + } - config->distSys = (byte)server.arg("distSys").toInt(); + if(server.hasArg("authConfig") && server.arg("authConfig") == "true") { + config->setAuthSecurity((byte)server.arg("authSecurity").toInt()); + if(config->getAuthSecurity() > 0) { + config->setAuthUser(server.arg("authUser")); + config->setAuthPassword(server.arg("authPassword")); + } else { + config->clearAuth(); + } + } println("Saving configuration now..."); if (debugger) config->print(debugger); - if (config->save()) - { - println("Successfully saved. Will reboot now."); - String html = "

Successfully Saved!

Device is restarting now...

Go to index"; - server.send(200, "text/html", html); - yield(); - delay(1000); + if (config->save()) { + println("Successfully saved."); + if(config->isWifiChanged()) { + String html = "

Successfully Saved!

Go to index"; + server.send(200, "text/html", html); + yield(); + println("Wifi config changed, rebooting"); + delay(1000); #if defined(ESP8266) - ESP.reset(); + ESP.reset(); #elif defined(ESP32) - ESP.restart(); + ESP.restart(); #endif - } - else - { + } else { + server.sendHeader("Location", String("/"), true); + server.send ( 302, "text/plain", ""); + } + } else { println("Error saving configuration"); String html = "

Error saving configuration!

"; server.send(500, "text/html", html); diff --git a/src/web/AmsWebServer.h b/src/web/AmsWebServer.h index 0dc060e8..3e89aefb 100644 --- a/src/web/AmsWebServer.h +++ b/src/web/AmsWebServer.h @@ -3,7 +3,7 @@ #include #include -#include "configuration.h" +#include "AmsConfiguration.h" #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" @@ -23,12 +23,12 @@ class AmsWebServer { public: - void setup(configuration* config, Stream* debugger, MQTTClient* mqtt); + void setup(AmsConfiguration* config, Stream* debugger, MQTTClient* mqtt); void loop(); void setJson(StaticJsonDocument<1024> json); private: - configuration* config; + AmsConfiguration* config; Stream* debugger; MQTTClient* mqtt; StaticJsonDocument<1024> json; @@ -45,7 +45,10 @@ private: bool checkSecurity(byte level); void indexHtml(); - void configurationHtml(); + void configMeterHtml(); + void configWifiHtml(); + void configMqttHtml(); + void configWebHtml(); void bootCss(); void gaugemeterJs(); void dataJson(); diff --git a/web/configmeter.html b/web/configmeter.html index 4982ee45..2a10fe58 100644 --- a/web/configmeter.html +++ b/web/configmeter.html @@ -46,6 +46,7 @@
+
@@ -63,10 +64,10 @@
- + + +
@@ -75,23 +76,23 @@
- + + + + + + +
- +
- -
kW
+ +
kWp
diff --git a/web/configmqtt.html b/web/configmqtt.html new file mode 100644 index 00000000..87f3d8b7 --- /dev/null +++ b/web/configmqtt.html @@ -0,0 +1,129 @@ + + + + + AMS reader - WiFi configuration + + + + + + + +
+ + + +
+
+
+
+ +
+ +
+
+
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+
+
+
+ Back +
+
+ +
+
+ +
+ + + diff --git a/web/configuration.html b/web/configuration.html deleted file mode 100644 index d0faab58..00000000 --- a/web/configuration.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - AMS reader - configuration - - - - - - - -
-
-
-
AMS reader - configuration
- ${version} -
-
-
-
-
-
-
WiFi
-
- -
- -
-
-
- -
- -
-
-
-
-
AMS meter
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
-
-
-
MQTT
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
-
-
-
Web server
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
-
-
-
-
- Back -
-
- -
-
-
-
- - - diff --git a/web/configweb.html b/web/configweb.html new file mode 100644 index 00000000..eb2099a9 --- /dev/null +++ b/web/configweb.html @@ -0,0 +1,105 @@ + + + + + AMS reader - Meter configuration + + + + + + + +
+ +
+ +
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+ Back +
+
+ +
+
+
+
+ + + diff --git a/web/configwifi.html b/web/configwifi.html index 11ecb169..23a5dab6 100644 --- a/web/configwifi.html +++ b/web/configwifi.html @@ -6,6 +6,7 @@ +