Finalized new configuration menu and moved AP button trigger from setup to loop

This commit is contained in:
Gunnar Skjold
2020-02-14 19:49:25 +01:00
parent 75f3c8c592
commit 517a40b0a6
19 changed files with 1124 additions and 1057 deletions

467
src/AmsConfiguration.cpp Normal file
View File

@@ -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<length; i++)
{
buffer[i] = EEPROM.read(pAddress + address++);
}
*pString = buffer;
return address;
}
int AmsConfiguration::saveString(int pAddress, const char* pString) {
int address = 0;
int length = pString ? strlen(pString) + 1 : 0;
EEPROM.put(pAddress + address, length);
address++;
for (int i = 0; i < length; i++)
{
EEPROM.put(pAddress + address, pString[i]);
address++;
}
return address;
}
int AmsConfiguration::readInt(int address, int *value) {
int lower = EEPROM.read(address);
int higher = EEPROM.read(address + 1);
*value = lower + (higher << 8);
return 2;
}
int AmsConfiguration::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 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 <class T> 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 <class T> 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("-----------------------------------------------");
}

106
src/AmsConfiguration.h Normal file
View File

@@ -0,0 +1,106 @@
#ifndef _AMSCONFIGURATION_h
#define _AMSCONFIGURATION_h
#include <EEPROM.h>
#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 <class T> int writeAnything(int ee, const T& value);
template <class T> int readAnything(int ee, T& value);
};
#endif

View File

@@ -1,5 +1,7 @@
#define WIFI_CONNECTION_TIMEOUT 30000;
#define INVALID_BUTTON_PIN 0xFFFFFFFF
#if defined(ESP8266)
#include <ESP8266WiFi.h>

View File

@@ -6,14 +6,15 @@
#if defined(ESP8266)
ADC_MODE(ADC_VCC);
#endif
#endif
#include "AmsToMqttBridge.h"
#include <ArduinoJson.h>
#include <MQTT.h>
#include <DNSServer.h>
#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);

View File

@@ -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<unsigned long>();
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 = "<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 (config->save()) {
println("Successfully saved.");
if(config->isWifiChanged()) {
String html = "<html><body><h1>Successfully Saved!</h1><a href=\"/\">Go to index</a></form>";
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 = "<html><body><h1>Error saving configuration!</h1></form>";
server.send(500, "text/html", html);

View File

@@ -3,7 +3,7 @@
#include <ArduinoJson.h>
#include <MQTT.h>
#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();