Added configuration of GPIO in UI. Added initial setup page in AP mode. Major changes in storing configuration.

This commit is contained in:
Gunnar Skjold
2020-05-03 16:29:38 +02:00
parent 1ea9da22c7
commit 2858123c1b
23 changed files with 1472 additions and 1232 deletions

View File

@@ -1,75 +1,75 @@
#include "AmsConfiguration.h"
String AmsConfiguration::getWifiSsid() {
return wifiSsid;
char* AmsConfiguration::getWifiSsid() {
return config.wifiSsid;
}
void AmsConfiguration::setWifiSsid(String wifiSsid) {
wifiChanged |= this->wifiSsid != wifiSsid;
this->wifiSsid = String(wifiSsid);
void AmsConfiguration::setWifiSsid(const char* wifiSsid) {
wifiChanged |= strcmp(config.wifiSsid, wifiSsid) != 0;
strcpy(config.wifiSsid, wifiSsid);
}
String AmsConfiguration::getWifiPassword() {
return wifiPassword;
char* AmsConfiguration::getWifiPassword() {
return config.wifiPassword;
}
void AmsConfiguration::setWifiPassword(String wifiPassword) {
wifiChanged |= this->wifiPassword != wifiPassword;
this->wifiPassword = String(wifiPassword);
void AmsConfiguration::setWifiPassword(const char* wifiPassword) {
wifiChanged |= strcmp(config.wifiPassword, wifiPassword) != 0;
strcpy(config.wifiPassword, wifiPassword);
}
String AmsConfiguration::getWifiIp() {
return wifiIp;
char* AmsConfiguration::getWifiIp() {
return config.wifiIp;
}
void AmsConfiguration::setWifiIp(String wifiIp) {
wifiChanged |= this->wifiIp != wifiIp;
this->wifiIp = String(wifiIp);
void AmsConfiguration::setWifiIp(const char* wifiIp) {
wifiChanged |= strcmp(config.wifiIp, wifiIp) != 0;
strcpy(config.wifiIp, wifiIp);
}
String AmsConfiguration::getWifiGw() {
return wifiGw;
char* AmsConfiguration::getWifiGw() {
return config.wifiGw;
}
void AmsConfiguration::setWifiGw(String wifiGw) {
wifiChanged |= this->wifiGw != wifiGw;
this->wifiGw = String(wifiGw);
void AmsConfiguration::setWifiGw(const char* wifiGw) {
wifiChanged |= strcmp(config.wifiGw, wifiGw) != 0;
strcpy(config.wifiGw, wifiGw);
}
String AmsConfiguration::getWifiSubnet() {
return wifiSubnet;
char* AmsConfiguration::getWifiSubnet() {
return config.wifiSubnet;
}
void AmsConfiguration::setWifiSubnet(String wifiSubnet) {
wifiChanged |= this->wifiSubnet != wifiSubnet;
this->wifiSubnet = String(wifiSubnet);
void AmsConfiguration::setWifiSubnet(const char* wifiSubnet) {
wifiChanged |= strcmp(config.wifiSubnet, wifiSubnet) != 0;
strcpy(config.wifiSubnet, wifiSubnet);
}
String AmsConfiguration::getWifiDns1() {
return wifiDns1;
char* AmsConfiguration::getWifiDns1() {
return config.wifiDns1;
}
void AmsConfiguration::setWifiDns1(String wifiDns1) {
wifiChanged |= this->wifiDns1 != wifiDns1;
this->wifiDns1 = wifiDns1;
void AmsConfiguration::setWifiDns1(const char* wifiDns1) {
wifiChanged |= strcmp(config.wifiDns1, wifiDns1) != 0;
strcpy(config.wifiDns1, wifiDns1);
}
String AmsConfiguration::getWifiDns2() {
return wifiDns2;
char* AmsConfiguration::getWifiDns2() {
return config.wifiDns2;
}
void AmsConfiguration::setWifiDns2(String wifiDns2) {
wifiChanged |= this->wifiDns2 != wifiDns2;
this->wifiDns2 = wifiDns2;
void AmsConfiguration::setWifiDns2(const char* wifiDns2) {
wifiChanged |= strcmp(config.wifiDns2, wifiDns2) != 0;
strcpy(config.wifiDns2, wifiDns2);
}
String AmsConfiguration::getWifiHostname() {
return wifiHostname;
char* AmsConfiguration::getWifiHostname() {
return config.wifiHostname;
}
void AmsConfiguration::setWifiHostname(String wifiHostname) {
wifiChanged |= this->wifiHostname != wifiHostname;
this->wifiHostname = wifiHostname;
void AmsConfiguration::setWifiHostname(const char* wifiHostname) {
wifiChanged |= strcmp(config.wifiHostname, wifiHostname) != 0;
strcpy(config.wifiHostname, wifiHostname);
}
void AmsConfiguration::clearWifiIp() {
@@ -89,84 +89,84 @@ void AmsConfiguration::ackWifiChange() {
}
String AmsConfiguration::getMqttHost() {
return mqttHost;
char* AmsConfiguration::getMqttHost() {
return config.mqttHost;
}
void AmsConfiguration::setMqttHost(String mqttHost) {
mqttChanged |= this->mqttHost != mqttHost;
this->mqttHost = String(mqttHost);
void AmsConfiguration::setMqttHost(const char* mqttHost) {
mqttChanged |= strcmp(config.mqttHost, mqttHost) != 0;
strcpy(config.mqttHost, mqttHost);
}
int AmsConfiguration::getMqttPort() {
return mqttPort;
uint16_t AmsConfiguration::getMqttPort() {
return config.mqttPort;
}
void AmsConfiguration::setMqttPort(int mqttPort) {
mqttChanged |= this->mqttPort != mqttPort;
this->mqttPort = mqttPort;
void AmsConfiguration::setMqttPort(uint16_t mqttPort) {
mqttChanged |= config.mqttPort != mqttPort;
config.mqttPort = mqttPort;
}
String AmsConfiguration::getMqttClientId() {
return mqttClientId;
char* AmsConfiguration::getMqttClientId() {
return config.mqttClientId;
}
void AmsConfiguration::setMqttClientId(String mqttClientId) {
mqttChanged |= this->mqttClientId != mqttClientId;
this->mqttClientId = String(mqttClientId);
void AmsConfiguration::setMqttClientId(const char* mqttClientId) {
mqttChanged |= strcmp(config.mqttClientId, mqttClientId) != 0;
strcpy(config.mqttClientId, mqttClientId);
}
String AmsConfiguration::getMqttPublishTopic() {
return mqttPublishTopic;
char* AmsConfiguration::getMqttPublishTopic() {
return config.mqttPublishTopic;
}
void AmsConfiguration::setMqttPublishTopic(String mqttPublishTopic) {
mqttChanged |= this->mqttPublishTopic != mqttPublishTopic;
this->mqttPublishTopic = String(mqttPublishTopic);
void AmsConfiguration::setMqttPublishTopic(const char* mqttPublishTopic) {
mqttChanged |= strcmp(config.mqttPublishTopic, mqttPublishTopic) != 0;
strcpy(config.mqttPublishTopic, mqttPublishTopic);
}
String AmsConfiguration::getMqttSubscribeTopic() {
return mqttSubscribeTopic;
char* AmsConfiguration::getMqttSubscribeTopic() {
return config.mqttSubscribeTopic;
}
void AmsConfiguration::setMqttSubscribeTopic(String mqttSubscribeTopic) {
mqttChanged |= this->mqttSubscribeTopic != mqttSubscribeTopic;
this->mqttSubscribeTopic = String(mqttSubscribeTopic);
void AmsConfiguration::setMqttSubscribeTopic(const char* mqttSubscribeTopic) {
mqttChanged |= strcmp(config.mqttSubscribeTopic, mqttSubscribeTopic) != 0;
strcpy(config.mqttSubscribeTopic, mqttSubscribeTopic);
}
String AmsConfiguration::getMqttUser() {
return mqttUser;
char* AmsConfiguration::getMqttUser() {
return config.mqttUser;
}
void AmsConfiguration::setMqttUser(String mqttUser) {
mqttChanged |= this->mqttUser != mqttUser;
this->mqttUser = String(mqttUser);
void AmsConfiguration::setMqttUser(const char* mqttUser) {
mqttChanged |= strcmp(config.mqttUser, mqttUser) != 0;
strcpy(config.mqttUser, mqttUser);
}
String AmsConfiguration::getMqttPassword() {
return mqttPassword;
char* AmsConfiguration::getMqttPassword() {
return config.mqttPassword;
}
void AmsConfiguration::setMqttPassword(String mqttPassword) {
mqttChanged |= this->mqttPassword != mqttPassword;
this->mqttPassword = String(mqttPassword);
void AmsConfiguration::setMqttPassword(const char* mqttPassword) {
mqttChanged |= strcmp(config.mqttPassword, mqttPassword) != 0;
strcpy(config.mqttPassword, mqttPassword);
}
int AmsConfiguration::getMqttPayloadFormat() {
return this->mqttPayloadFormat;
uint8_t AmsConfiguration::getMqttPayloadFormat() {
return config.mqttPayloadFormat;
}
void AmsConfiguration::setMqttPayloadFormat(int mqttPayloadFormat) {
this->mqttPayloadFormat = mqttPayloadFormat;
void AmsConfiguration::setMqttPayloadFormat(uint8_t mqttPayloadFormat) {
config.mqttPayloadFormat = mqttPayloadFormat;
}
bool AmsConfiguration::isMqttSsl() {
return this->mqttSsl;
return config.mqttSsl;
}
void AmsConfiguration::setMqttSsl(bool mqttSsl) {
mqttChanged |= this->mqttSsl != mqttSsl;
this->mqttSsl = mqttSsl;
mqttChanged |= config.mqttSsl != mqttSsl;
config.mqttSsl = mqttSsl;
}
void AmsConfiguration::clearMqtt() {
@@ -193,27 +193,27 @@ void AmsConfiguration::ackMqttChange() {
byte AmsConfiguration::getAuthSecurity() {
return authSecurity;
return config.authSecurity;
}
void AmsConfiguration::setAuthSecurity(byte authSecurity) {
this->authSecurity = authSecurity;
config.authSecurity = authSecurity;
}
String AmsConfiguration::getAuthUser() {
return authUser;
char* AmsConfiguration::getAuthUser() {
return config.authUser;
}
void AmsConfiguration::setAuthUser(String authUser) {
this->authUser = String(authUser);
void AmsConfiguration::setAuthUser(const char* authUser) {
strcpy(config.authUser, authUser);
}
String AmsConfiguration::getAuthPassword() {
return authPassword;
char* AmsConfiguration::getAuthPassword() {
return config.authPassword;
}
void AmsConfiguration::setAuthPassword(String authPassword) {
this->authPassword = String(authPassword);
void AmsConfiguration::setAuthPassword(const char* authPassword) {
strcpy(config.authPassword, authPassword);
}
void AmsConfiguration::clearAuth() {
@@ -222,62 +222,194 @@ void AmsConfiguration::clearAuth() {
setAuthPassword("");
}
int AmsConfiguration::getMeterType() {
return this->meterType;
uint8_t AmsConfiguration::getMeterType() {
return config.meterType;
}
void AmsConfiguration::setMeterType(int meterType) {
this->meterType = meterType;
void AmsConfiguration::setMeterType(uint8_t meterType) {
config.meterType = meterType;
}
int AmsConfiguration::getDistributionSystem() {
return this->distributionSystem;
uint8_t AmsConfiguration::getDistributionSystem() {
return config.distributionSystem;
}
void AmsConfiguration::setDistributionSystem(int distributionSystem) {
this->distributionSystem = distributionSystem;
void AmsConfiguration::setDistributionSystem(uint8_t distributionSystem) {
config.distributionSystem = distributionSystem;
}
int AmsConfiguration::getMainFuse() {
return this->mainFuse;
uint8_t AmsConfiguration::getMainFuse() {
return config.mainFuse;
}
void AmsConfiguration::setMainFuse(int mainFuse) {
this->mainFuse = mainFuse;
void AmsConfiguration::setMainFuse(uint8_t mainFuse) {
config.mainFuse = mainFuse;
}
int AmsConfiguration::getProductionCapacity() {
return this->productionCapacity;
uint8_t AmsConfiguration::getProductionCapacity() {
return config.productionCapacity;
}
void AmsConfiguration::setProductionCapacity(int productionCapacity) {
this->productionCapacity = productionCapacity;
void AmsConfiguration::setProductionCapacity(uint8_t productionCapacity) {
config.productionCapacity = productionCapacity;
}
bool AmsConfiguration::isDebugTelnet() {
return this->debugTelnet;
return config.debugTelnet;
}
void AmsConfiguration::setDebugTelnet(bool debugTelnet) {
this->debugTelnet = debugTelnet;
config.debugTelnet = debugTelnet;
}
bool AmsConfiguration::isDebugSerial() {
return this->debugSerial;
return config.debugSerial;
}
void AmsConfiguration::setDebugSerial(bool debugSerial) {
this->debugSerial = debugSerial;
config.debugSerial = debugSerial;
}
int AmsConfiguration::getDebugLevel() {
return this->debugLevel;
uint8_t AmsConfiguration::getDebugLevel() {
return config.debugLevel;
}
void AmsConfiguration::setDebugLevel(int debugLevel) {
this->debugLevel = debugLevel;
void AmsConfiguration::setDebugLevel(uint8_t debugLevel) {
config.debugLevel = debugLevel;
}
bool AmsConfiguration::pinUsed(uint8_t pin) {
if(pin == 0xFF)
return false;
return
pin == config.hanPin ||
pin == config.apPin ||
pin == config.ledPinRed ||
pin == config.ledPinGreen ||
pin == config.ledPinBlue ||
pin == config.tempSensorPin ||
pin == config.vccPin
;
}
uint8_t AmsConfiguration::getHanPin() {
return config.hanPin;
}
void AmsConfiguration::setHanPin(uint8_t hanPin) {
if(!pinUsed(hanPin)) {
config.hanPin = hanPin;
}
}
uint8_t AmsConfiguration::getApPin() {
return config.apPin;
}
void AmsConfiguration::setApPin(uint8_t apPin) {
if(!pinUsed(apPin)) {
config.apPin = apPin;
if(apPin >= 0)
pinMode(apPin, INPUT_PULLUP);
}
}
uint8_t AmsConfiguration::getLedPin() {
return config.ledPin;
}
void AmsConfiguration::setLedPin(uint8_t ledPin) {
if(!pinUsed(ledPin)) {
config.ledPin = ledPin;
}
}
bool AmsConfiguration::isLedInverted() {
return config.ledInverted;
}
void AmsConfiguration::setLedInverted(bool ledInverted) {
config.ledInverted = ledInverted;
}
uint8_t AmsConfiguration::getLedPinRed() {
return config.ledPinRed;
}
void AmsConfiguration::setLedPinRed(uint8_t ledPinRed) {
if(!pinUsed(ledPinRed)) {
config.ledPinRed = ledPinRed;
}
}
uint8_t AmsConfiguration::getLedPinGreen() {
return config.ledPinGreen;
}
void AmsConfiguration::setLedPinGreen(uint8_t ledPinGreen) {
if(!pinUsed(ledPinGreen)) {
config.ledPinGreen = ledPinGreen;
}
}
uint8_t AmsConfiguration::getLedPinBlue() {
return config.ledPinBlue;
}
void AmsConfiguration::setLedPinBlue(uint8_t ledPinBlue) {
if(!pinUsed(ledPinBlue)) {
config.ledPinBlue = ledPinBlue;
}
}
bool AmsConfiguration::isLedRgbInverted() {
return config.ledRgbInverted;
}
void AmsConfiguration::setLedRgbInverted(bool ledRgbInverted) {
config.ledRgbInverted = ledRgbInverted;
}
uint8_t AmsConfiguration::getTempSensorPin() {
return config.tempSensorPin;
}
void AmsConfiguration::setTempSensorPin(uint8_t tempSensorPin) {
if(!pinUsed(tempSensorPin)) {
config.tempSensorPin = tempSensorPin;
}
}
uint8_t AmsConfiguration::getVccPin() {
return config.vccPin;
}
void AmsConfiguration::setVccPin(uint8_t vccPin) {
if(!pinUsed(vccPin)) {
config.vccPin = vccPin;
}
}
double AmsConfiguration::getVccMultiplier() {
return config.vccMultiplier / 100.0;
}
void AmsConfiguration::setVccMultiplier(double vccMultiplier) {
config.vccMultiplier = max(0.01, min(vccMultiplier, 655.5)) * 100;
}
double AmsConfiguration::getVccBootLimit() {
return config.vccBootLimit / 10;
}
void AmsConfiguration::setVccBootLimit(double vccBootLimit) {
if(vccBootLimit == 0.0)
config.vccBootLimit = 0;
else
config.vccBootLimit = max(2.5, min(vccBootLimit, 3.5)) * 10;
}
bool AmsConfiguration::hasConfig() {
if(configVersion == 0) {
@@ -311,153 +443,25 @@ bool AmsConfiguration::load() {
int cs = EEPROM.read(address);
address++;
switch(cs) {
case 71: // Same as 72
case 72:
success = loadConfig72(address);
break;
case 75:
success = loadConfig75(address);
break;
case 80:
case 80: // v1.1
success = loadConfig80(address);
break;
case 81:
case 81: // v1.2
success = loadConfig81(address);
break;
case 82:
success = loadConfig82(address);
case 82: // v1.3
EEPROM.get(address, config);
success = true;
break;
}
EEPROM.end();
if(config.apPin >= 0)
pinMode(config.apPin, INPUT_PULLUP);
return success;
}
bool AmsConfiguration::loadConfig72(int address) {
char* temp;
address += readString(address, &temp);
setWifiSsid(temp);
address += readString(address, &temp);
setWifiPassword(temp);
byte b;
address += readByte(address, &b);
setMeterType(b);
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("");
}
setMqttPayloadFormat(0);
clearAuth();
setWifiIp("");
setWifiGw("");
setWifiSubnet("");
setMainFuse(0);
setProductionCapacity(0);
setDistributionSystem(0);
ackWifiChange();
setDebugLevel(3); // 3=Info
setDebugTelnet(false);
setDebugSerial(false);
return true;
}
bool AmsConfiguration::loadConfig75(int address) {
char* temp;
address += readString(address, &temp);
setWifiSsid(temp);
address += readString(address, &temp);
setWifiPassword(temp);
byte b;
address += readByte(address, &b);
setMeterType(b);
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("");
}
setMqttPayloadFormat(0);
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);
setMainFuse(i);
address += readByte(address, &b);
setDistributionSystem(b);
setWifiIp("");
setWifiGw("");
setWifiSubnet("");
setProductionCapacity(0);
ackWifiChange();
setDebugLevel(3); // 3=Info
setDebugTelnet(false);
setDebugSerial(false);
return true;
}
bool AmsConfiguration::loadConfig80(int address) {
char* temp;
@@ -504,8 +508,10 @@ bool AmsConfiguration::loadConfig80(int address) {
}
setMqttPayloadFormat(0);
address += readByte(address, &authSecurity);
if (authSecurity > 0) {
byte b;
address += readByte(address, &b);
setAuthSecurity(b);
if (b > 0) {
address += readString(address, &temp);
setAuthUser(temp);
address += readString(address, &temp);
@@ -591,103 +597,10 @@ bool AmsConfiguration::loadConfig81(int address) {
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);
bool debugTelnet = false;
address += readBool(address, &debugTelnet);
setDebugTelnet(debugTelnet);
bool debugSerial = false;
address += readBool(address, &debugSerial);
setDebugSerial(debugSerial);
address += readInt(address, &i);
setDebugLevel(i);
ackWifiChange();
return true;
}
bool AmsConfiguration::loadConfig82(int address) {
char* temp;
address += readString(address, &temp);
setWifiSsid(temp);
address += readString(address, &temp);
setWifiPassword(temp);
bool staticIp = false;
address += readBool(address, &staticIp);
if(staticIp) {
address += readString(address, &temp);
setWifiIp(temp);
address += readString(address, &temp);
setWifiGw(temp);
address += readString(address, &temp);
setWifiSubnet(temp);
address += readString(address, &temp);
setWifiDns1(temp);
address += readString(address, &temp);
setWifiDns2(temp);
}
address += readString(address, &temp);
setWifiHostname(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("");
}
int payloadFormat;
address += readInt(address, &payloadFormat);
setMqttPayloadFormat(payloadFormat);
bool ssl = false;
address += readBool(address, &ssl);
setMqttSsl(ssl);
} else {
clearMqtt();
}
address += readByte(address, &authSecurity);
if (authSecurity > 0) {
byte b;
address += readByte(address, &b);
setAuthSecurity(b);
if (b > 0) {
address += readString(address, &temp);
setAuthUser(temp);
address += readString(address, &temp);
@@ -726,60 +639,11 @@ bool AmsConfiguration::save() {
EEPROM.begin(EEPROM_SIZE);
EEPROM.put(address, EEPROM_CHECK_SUM);
address++;
address += saveString(address, wifiSsid.c_str());
address += saveString(address, wifiPassword.c_str());
if(!wifiIp.isEmpty()) {
address += saveBool(address, true);
address += saveString(address, wifiIp.c_str());
address += saveString(address, wifiGw.c_str());
address += saveString(address, wifiSubnet.c_str());
address += saveString(address, wifiDns1.c_str());
address += saveString(address, wifiDns2.c_str());
} else {
address += saveBool(address, false);
}
address += saveString(address, wifiHostname.c_str());
if(!mqttHost.isEmpty()) {
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.isEmpty()) {
address += saveBool(address, true);
address += saveString(address, mqttUser.c_str());
address += saveString(address, mqttPassword.c_str());
} else {
address += saveBool(address, false);
}
address += saveInt(address, mqttPayloadFormat);
address += saveBool(address, mqttSsl);
} 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);
address += saveBool(address, debugTelnet);
address += saveBool(address, debugSerial);
address += saveInt(address, debugLevel);
EEPROM.put(address, config);
bool success = EEPROM.commit();
EEPROM.end();
configVersion = EEPROM_CHECK_SUM;
return success;
}
@@ -797,21 +661,6 @@ int AmsConfiguration::readString(int pAddress, char* pString[]) {
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);
@@ -819,79 +668,44 @@ int AmsConfiguration::readInt(int address, int *value) {
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(Print* 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());
debugger->printf("WiFi SSID: '%s'\r\n", this->getWifiSsid());
debugger->printf("WiFi Psk: '%s'\r\n", this->getWifiPassword());
if(!getWifiIp().isEmpty()) {
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());
debugger->printf("Primary DNS: %s\r\n", this->getWifiDns1().c_str());
debugger->printf("Secondary DNS: %s\r\n", this->getWifiDns2().c_str());
if(strlen(getWifiIp()) > 0) {
debugger->printf("IP: '%s'\r\n", this->getWifiIp());
debugger->printf("Gateway: '%s'\r\n", this->getWifiGw());
debugger->printf("Subnet: '%s'\r\n", this->getWifiSubnet());
debugger->printf("Primary DNS: '%s'\r\n", this->getWifiDns1());
debugger->printf("Secondary DNS: '%s'\r\n", this->getWifiDns2());
}
debugger->printf("WiFi Host: '%s'\r\n", this->getWifiHostname());
if(!getMqttHost().isEmpty()) {
debugger->printf("mqttHost: %s\r\n", this->getMqttHost().c_str());
if(strlen(getMqttHost()) > 0) {
debugger->printf("mqttHost: '%s'\r\n", this->getMqttHost());
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());
debugger->printf("mqttClientID: '%s'\r\n", this->getMqttClientId());
debugger->printf("mqttPublishTopic: '%s'\r\n", this->getMqttPublishTopic());
debugger->printf("mqttSubscribeTopic: '%s'\r\n", this->getMqttSubscribeTopic());
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());
debugger->printf("mqttUser: '%s'\r\n", this->getMqttUser());
debugger->printf("mqttPass: '%s'\r\n", this->getMqttPassword());
}
debugger->printf("payload format: %i\r\n", this->getMqttPayloadFormat());
}
@@ -899,8 +713,8 @@ void AmsConfiguration::print(Print* debugger)
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("authUser: '%s'\r\n", this->getAuthUser());
debugger->printf("authPass: '%s'\r\n", this->getAuthPassword());
}
debugger->printf("meterType: %i\r\n", this->getMeterType());
@@ -908,5 +722,13 @@ void AmsConfiguration::print(Print* debugger)
debugger->printf("fuseSize: %i\r\n", this->getMainFuse());
debugger->printf("productionCapacity: %i\r\n", this->getProductionCapacity());
debugger->printf("HAN pin: %i\r\n", this->getHanPin());
debugger->printf("LED pin: %i\r\n", this->getLedPin());
debugger->printf("LED red pin: %i\r\n", this->getLedPinRed());
debugger->printf("LED green pin: %i\r\n", this->getLedPinGreen());
debugger->printf("LED blue pin: %i\r\n", this->getLedPinBlue());
debugger->printf("AP pin: %i\r\n", this->getApPin());
debugger->printf("Temperature pin: %i\r\n", this->getTempSensorPin());
debugger->println("-----------------------------------------------");
}

View File

@@ -3,6 +3,50 @@
#include <EEPROM.h>
#include "Arduino.h"
struct ConfigObject {
char wifiSsid[32];
char wifiPassword[64];
char wifiIp[15];
char wifiGw[15];
char wifiSubnet[15];
char wifiDns1[15];
char wifiDns2[15];
char wifiHostname[32];
char mqttHost[128];
uint16_t mqttPort;
char mqttClientId[32];
char mqttPublishTopic[64];
char mqttSubscribeTopic[64];
char mqttUser[64];
char mqttPassword[64];
uint8_t mqttPayloadFormat;
bool mqttSsl;
uint8_t authSecurity;
char authUser[64];
char authPassword[64];
uint8_t meterType;
uint8_t distributionSystem;
uint8_t mainFuse;
uint8_t productionCapacity;
bool debugTelnet;
bool debugSerial;
uint8_t debugLevel;
uint8_t hanPin;
uint8_t apPin;
uint8_t ledPin;
bool ledInverted;
uint8_t ledPinRed;
uint8_t ledPinGreen;
uint8_t ledPinBlue;
bool ledRgbInverted;
uint8_t tempSensorPin;
uint8_t vccPin;
uint16_t vccMultiplier;
uint8_t vccBootLimit;
};
class AmsConfiguration {
public:
bool hasConfig();
@@ -11,43 +55,43 @@ public:
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);
String getWifiDns1();
void setWifiDns1(String wifiDns1);
String getWifiDns2();
void setWifiDns2(String wifiDns1);
String getWifiHostname();
void setWifiHostname(String wifiHostname);
char* getWifiSsid();
void setWifiSsid(const char* wifiSsid);
char* getWifiPassword();
void setWifiPassword(const char* wifiPassword);
char* getWifiIp();
void setWifiIp(const char* wifiIp);
char* getWifiGw();
void setWifiGw(const char* wifiGw);
char* getWifiSubnet();
void setWifiSubnet(const char* wifiSubnet);
char* getWifiDns1();
void setWifiDns1(const char* wifiDns1);
char* getWifiDns2();
void setWifiDns2(const char* wifiDns1);
char* getWifiHostname();
void setWifiHostname(const char* wifiHostname);
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);
int getMqttPayloadFormat();
void setMqttPayloadFormat(int mqttPayloadFormat);
char* getMqttHost();
void setMqttHost(const char* mqttHost);
uint16_t getMqttPort();
void setMqttPort(uint16_t mqttPort);
char* getMqttClientId();
void setMqttClientId(const char* mqttClientId);
char* getMqttPublishTopic();
void setMqttPublishTopic(const char* mqttPublishTopic);
char* getMqttSubscribeTopic();
void setMqttSubscribeTopic(const char* mqttSubscribeTopic);
char* getMqttUser();
void setMqttUser(const char* mqttUser);
char* getMqttPassword();
void setMqttPassword(const char* mqttPassword);
uint8_t getMqttPayloadFormat();
void setMqttPayloadFormat(uint8_t mqttPayloadFormat);
bool isMqttSsl();
void setMqttSsl(bool mqttSsl);
void clearMqtt();
@@ -58,27 +102,56 @@ public:
byte getAuthSecurity();
void setAuthSecurity(byte authSecurity);
String getAuthUser();
void setAuthUser(String authUser);
String getAuthPassword();
void setAuthPassword(String authPassword);
char* getAuthUser();
void setAuthUser(const char* authUser);
char* getAuthPassword();
void setAuthPassword(const char* 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);
uint8_t getMeterType();
void setMeterType(uint8_t meterType);
uint8_t getDistributionSystem();
void setDistributionSystem(uint8_t distributionSystem);
uint8_t getMainFuse();
void setMainFuse(uint8_t mainFuse);
uint8_t getProductionCapacity();
void setProductionCapacity(uint8_t productionCapacity);
bool isDebugTelnet();
void setDebugTelnet(bool debugTelnet);
bool isDebugSerial();
void setDebugSerial(bool debugSerial);
int getDebugLevel();
void setDebugLevel(int debugLevel);
uint8_t getDebugLevel();
void setDebugLevel(uint8_t debugLevel);
bool pinUsed(uint8_t pin);
uint8_t getHanPin();
void setHanPin(uint8_t hanPin);
uint8_t getApPin();
void setApPin(uint8_t apPin);
uint8_t getLedPin();
void setLedPin(uint8_t ledPin);
bool isLedInverted();
void setLedInverted(bool ledInverted);
uint8_t getLedPinRed();
void setLedPinRed(uint8_t ledPinRed);
uint8_t getLedPinGreen();
void setLedPinGreen(uint8_t ledPinGreen);
uint8_t getLedPinBlue();
void setLedPinBlue(uint8_t ledPinBlue);
bool isLedRgbInverted();
void setLedRgbInverted(bool ledRgbInverted);
uint8_t getTempSensorPin();
void setTempSensorPin(uint8_t tempSensorPin);
uint8_t getVccPin();
void setVccPin(uint8_t vccPin);
double getVccMultiplier();
void setVccMultiplier(double vccMultiplier);
double getVccBootLimit();
void setVccBootLimit(double vccBootLimit);
void print(Print* debugger);
@@ -86,57 +159,59 @@ protected:
private:
int configVersion = 0;
ConfigObject config {
"", // SSID
"", // PSK
"", // IP
"", // GW
"", // Subnet
"", // DNS 1
"", // DNS 2
"", // Hostname
"", // MQTT host
1883, // Port
"", // Client ID
"", // Publish topic
"", // Subscribe topic
"", // Username
"", // Password
0, // Format
false, // SSL
0, // Web security
"", // Username
"", // Password
0, // Meter type
0, // Distribution system
0, // Main fuse
0, // Production capacity
false, // Debug telnet
false, // Debug serial
5, // Debug level
0x03, // HAN pin
0xFF, // AP pin
0x02, // LED pin
true, // Inverted
0xFF, // Red
0xFF, // Green
0xFF, // Blue
true, // Inverted
0xFF, // Temp sensor
0xFF, // Vcc
100, // Multiplier
0 // Boot limit
};
bool wifiChanged, mqttChanged;
String wifiSsid;
String wifiPassword;
String wifiIp;
String wifiGw;
String wifiSubnet;
String wifiDns1;
String wifiDns2;
String wifiHostname;
bool wifiChanged = false;
String mqttHost;
int mqttPort = 1883;
String mqttClientId;
String mqttPublishTopic;
String mqttSubscribeTopic;
String mqttUser;
String mqttPassword;
int mqttPayloadFormat = 0;
bool mqttSsl;
bool mqttChanged = false;
byte authSecurity;
String authUser;
String authPassword;
int meterType = 0, distributionSystem = 0, mainFuse = 0, productionCapacity = 0;
bool debugTelnet = false, debugSerial = false;
int debugLevel = 3;
const int EEPROM_SIZE = 512;
const int EEPROM_SIZE = 2048;
const int EEPROM_CHECK_SUM = 82; // Used to check if config is stored. Change if structure changes
const int EEPROM_CONFIG_ADDRESS = 0;
bool loadConfig72(int address);
bool loadConfig75(int address);
bool loadConfig80(int address);
bool loadConfig81(int address);
bool loadConfig82(int address);
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

@@ -5,6 +5,7 @@
#define INVALID_BUTTON_PIN 0xFFFFFFFF
#include <SoftwareSerial.h>
#if defined(ESP8266)
#include <ESP8266WiFi.h>
@@ -17,62 +18,4 @@
#include "Update.h"
#endif
#define RGB_RED 1
#define RGB_GREEN 2
#define RGB_YELLOW 3
#define RGB_ON 1
#define RGB_OFF 0
// Build settings for custom hardware by Roar Fredriksen
#if HW_ROARFRED
#define LED_PIN 2 // The blue on-board LED of the ESP8266 custom AMS board
#define LED_ACTIVE_HIGH 0
#define AP_BUTTON_PIN 0
HardwareSerial *hanSerial = &Serial;
// Build settings for Wemos Lolin D32
#elif defined(ARDUINO_LOLIN_D32)
#define LED_PIN 5
#define LED_ACTIVE_HIGH 0
#define AP_BUTTON_PIN 4
HardwareSerial *hanSerial = &Serial2;
// Build settings for Wemos D1 mini
#elif defined(ARDUINO_ESP8266_WEMOS_D1MINI)
#define LED_PIN D4
#define LED_ACTIVE_HIGH 0
#define AP_BUTTON_PIN D2
#define SOFTWARE_SERIAL 1
#include <SoftwareSerial.h>
SoftwareSerial *hanSerial = new SoftwareSerial(D1);
// Build settings for Adafruit Feather ESP32
#elif defined(ARDUINO_FEATHER_ESP32)
#define LED_PIN LED_BUILTIN
#define LED_ACTIVE_HIGH 1
#define AP_BUTTON_PIN INVALID_BUTTON_PIN
HardwareSerial *hanSerial = &Serial2;
// Default build for ESP32
#elif defined(ESP32)
#define LED_PIN INVALID_BUTTON_PIN
#define LED_ACTIVE_HIGH 1
#define AP_BUTTON_PIN INVALID_BUTTON_PIN
HardwareSerial *hanSerial = &Serial2;
// Default build settings
#else
#define LED_PIN 2
#define LED_ACTIVE_HIGH 0
#define AP_BUTTON_PIN INVALID_BUTTON_PIN
#define SOFTWARE_SERIAL 1
#include <SoftwareSerial.h>
SoftwareSerial *hanSerial = new SoftwareSerial(5);
#endif
#endif

View File

@@ -55,32 +55,92 @@ AmsConfiguration config;
RemoteDebug Debug;
AmsWebServer ws(&Debug);
AmsWebServer ws(&Debug, &hw);
MQTTClient mqtt(512);
HanReader hanReader;
Stream *hanSerial;
int hanSerialPin = 0;
void setup() {
if(config.hasConfig()) {
config.load();
}
#if HW_ROARFRED
if(config.getMeterType() == 3) {
Serial.begin(2400, SERIAL_8N1);
} else {
Serial.begin(2400, SERIAL_8E1);
if(!config.hasConfig() || config.getConfigVersion() < 81) {
debugI("Setting default hostname");
uint16_t chipId;
#if defined(ESP32)
chipId = ESP.getEfuseMac();
#else
chipId = ESP.getChipId();
#endif
config.setWifiHostname((String("ams-") + String(chipId, HEX)).c_str());
}
if(!config.hasConfig() || config.getConfigVersion() < 82) {
config.setVccMultiplier(1.0);
config.setVccBootLimit(0);
#if HW_ROARFRED
config.setHanPin(3);
config.setApPin(0);
config.setLedPin(2);
config.setLedInverted(true);
config.setTempSensorPin(5);
#elif defined(ARDUINO_ESP8266_WEMOS_D1MINI)
config.setHanPin(5);
config.setApPin(4);
config.setLedPin(2);
config.setLedInverted(true);
config.setTempSensorPin(14);
config.setVccMultiplier(1.1);
#elif defined(ARDUINO_LOLIN_D32)
config.setHanPin(16);
config.setLedPin(5);
config.setLedInverted(true);
config.setTempSensorPin(14);
config.setVccPin(35);
config.setVccMultiplier(2.25);
#elif defined(ARDUINO_FEATHER_ESP32)
config.setHanPin(16);
config.setLedPin(2);
config.setTempSensorPin(14);
#elif defined(ESP8266)
config.setHanPin(3);
config.setLedPin(2);
config.setLedInverted(true);
#elif defined(ESP32)
config.setHanPin(16);
config.setLedPin(2);
config.setLedInverted(true);
config.setTempSensorPin(14);
#endif
}
hw.setLed(config.getLedPin(), config.isLedInverted());
hw.setLedRgb(config.getLedPinRed(), config.getLedPinGreen(), config.getLedPinBlue(), config.isLedRgbInverted());
hw.setTempSensorPin(config.getTempSensorPin());
hw.setVccPin(config.getVccPin());
hw.setVccMultiplier(config.getVccMultiplier());
if(config.getHanPin() == 3) {
if(config.getMeterType() == 3) {
Serial.begin(2400, SERIAL_8N1);
} else {
Serial.begin(2400, SERIAL_8E1);
}
} else {
Serial.begin(115200);
}
#else
Serial.begin(115200);
#endif
if(config.hasConfig() && config.isDebugSerial()) {
Debug.setSerialEnabled(config.isDebugSerial());
} else {
#if DEBUG_MODE
Debug.setSerialEnabled(true);
#endif
#if DEBUG_MODE
Debug.setSerialEnabled(true);
#endif
}
double vcc = hw.getVcc();
@@ -90,26 +150,16 @@ void setup() {
debugI("Voltage: %.2fV", vcc);
}
#if SELF_POWERED
if (vcc > 2.5 && vcc < 3.25) { // Only sleep if voltage is realistic and too low
if(Debug.isActive(RemoteDebug::INFO)) {
debugI("Voltage is too low, sleeping");
Serial.flush();
}
ESP.deepSleep(10000000); //Deep sleep to allow output cap to charge up
}
#endif
#if HAS_RGB_LED
// Initialize RGB LED pins
pinMode(LEDPIN_RGB_GREEN, OUTPUT);
pinMode(LEDPIN_RGB_RED, OUTPUT);
#endif
pinMode(LED_PIN, OUTPUT);
pinMode(AP_BUTTON_PIN, INPUT_PULLUP);
led_off();
double vccBootLimit = config.getVccBootLimit();
if(vccBootLimit > 0 && (config.getApPin() == -1 || digitalRead(config.getApPin()) == HIGH)) { // Skip if user is holding AP button while booting (HIGH = button is released)
if (vcc < vccBootLimit) {
if(Debug.isActive(RemoteDebug::INFO)) {
debugI("Voltage is too low, sleeping");
Serial.flush();
}
ESP.deepSleep(10000000); //Deep sleep to allow output cap to charge up
}
}
WiFi.disconnect(true);
WiFi.softAPdisconnect(true);
@@ -178,17 +228,6 @@ void setup() {
}
}
if(!config.hasConfig() || config.getConfigVersion() < 81) {
debugI("Setting default hostname");
uint16_t chipId;
#if defined(ARDUINO_ARCH_ESP32)
chipId = ESP.getEfuseMac();
#else
chipId = ESP.getChipId();
#endif
config.setWifiHostname(String("ams-") + String(chipId, HEX));
}
if(config.hasConfig()) {
if(Debug.isActive(RemoteDebug::INFO)) config.print(&Debug);
WiFi_connect();
@@ -199,49 +238,8 @@ void setup() {
swapWifiMode();
}
#if SOFTWARE_SERIAL
if(Debug.isActive(RemoteDebug::DEBUG)) debugD("HAN has software serial");
if(config.getMeterType() == 3) {
hanSerial->begin(2400, SWSERIAL_8N1);
} else {
hanSerial->begin(2400, SWSERIAL_8E1);
}
#else
if(Debug.isActive(RemoteDebug::DEBUG)) {
debugD("HAN has hardware serial");
Serial.flush();
}
if(config.getMeterType() == 3) {
hanSerial->begin(2400, SERIAL_8N1);
} else {
hanSerial->begin(2400, SERIAL_8E1);
}
#if UART2
hanSerial->swap();
#endif
#endif
hanReader.setup(hanSerial, &Debug);
// Compensate for the known Kaifa bug
hanReader.compensateFor09HeaderBug = (config.getMeterType() == 1);
// Empty buffer before starting
while (hanSerial->available() > 0) {
hanSerial->read();
}
ws.setup(&config, &mqtt);
timeClient.begin();
#if HAS_RGB_LED
//Signal startup by blinking red / green / yellow
rgb_led(RGB_RED, 2);
delay(250);
rgb_led(RGB_GREEN, 2);
delay(250);
rgb_led(RGB_YELLOW, 2);
#endif
}
int buttonTimer = 0;
@@ -254,7 +252,6 @@ bool wifiConnected = false;
unsigned long lastTemperatureRead = 0;
double temperature = -127;
bool even = true;
unsigned long lastRead = 0;
unsigned long lastSuccessfulRead = 0;
@@ -264,8 +261,8 @@ int lastError = 0;
void loop() {
Debug.handle();
unsigned long now = millis();
if(AP_BUTTON_PIN != INVALID_BUTTON_PIN) {
if (digitalRead(AP_BUTTON_PIN) == LOW) {
if(config.getApPin() != INVALID_BUTTON_PIN) {
if (digitalRead(config.getApPin()) == LOW) {
if (buttonActive == false) {
buttonActive = true;
buttonTimer = now;
@@ -300,8 +297,6 @@ void loop() {
// Only do normal stuff if we're not booted as AP
if (WiFi.getMode() != WIFI_AP) {
led_off();
if (WiFi.status() != WL_CONNECTED) {
wifiConnected = false;
Debug.stop();
@@ -313,6 +308,7 @@ void loop() {
Debug.setPassword(config.getAuthPassword());
}
Debug.begin(config.getWifiHostname(), (uint8_t) config.getDebugLevel());
Debug.setSerialEnabled(config.isDebugSerial());
if(!config.isDebugTelnet()) {
Debug.stop();
}
@@ -320,12 +316,12 @@ void loop() {
debugI("Successfully connected to WiFi!");
debugI("IP: %s", WiFi.localIP().toString().c_str());
}
if(!config.getWifiHostname().isEmpty()) {
MDNS.begin(config.getWifiHostname().c_str());
if(strlen(config.getWifiHostname()) > 0) {
MDNS.begin(config.getWifiHostname());
MDNS.addService("http", "tcp", 80);
}
}
if (!config.getMqttHost().isEmpty()) {
if (strlen(config.getMqttHost()) > 0) {
mqtt.loop();
delay(10); // Needed to preserve power. After adding this, the voltage is super smooth on a HAN powered device
if(!mqtt.connected() || config.isMqttChanged()) {
@@ -341,10 +337,13 @@ void loop() {
} else {
dnsServer.processNextRequest();
// Continously flash the LED when AP mode
if (now / 50 % 64 == 0) led_on();
else led_off();
hw.ledBlink(LED_INTERNAL, 1);
}
if(hanSerialPin != config.getHanPin()) {
setupHanPort(config.getHanPin(), config.getMeterType());
}
if(now - lastRead > 100) {
yield();
readHanPort();
@@ -354,24 +353,67 @@ void loop() {
delay(1); // Needed for auto modem sleep
}
void setupHanPort(int pin, int meterType) {
debugI("Setting up HAN on pin %d for meter type %d", pin, meterType);
void led_on()
{
#if LED_ACTIVE_HIGH
digitalWrite(LED_PIN, HIGH);
#else
digitalWrite(LED_PIN, LOW);
#endif
}
HardwareSerial *hwSerial = NULL;
if(pin == 3) {
hwSerial = &Serial;
}
#if defined(ESP32)
if(pin == 9) {
hwSerial = &Serial1;
}
if(pin == 16) {
hwSerial = &Serial2;
}
#endif
if(hwSerial != NULL) {
debugD("Hardware serial");
Serial.flush();
if(meterType == 3) {
hwSerial->begin(2400, SERIAL_8N1);
} else {
hwSerial->begin(2400, SERIAL_8E1);
}
hanSerialPin = pin;
hanSerial = hwSerial;
} else {
debugD("Software serial");
Serial.flush();
SoftwareSerial *swSerial = new SoftwareSerial(pin);
void led_off()
{
#if LED_ACTIVE_HIGH
digitalWrite(LED_PIN, LOW);
#else
digitalWrite(LED_PIN, HIGH);
#endif
if(meterType == 3) {
swSerial->begin(2400, SWSERIAL_8N1);
} else {
swSerial->begin(2400, SWSERIAL_8E1);
}
hanSerialPin = pin;
hanSerial = swSerial;
Serial.begin(115200);
}
hanReader.setup(hanSerial, &Debug);
// Compensate for the known Kaifa bug
hanReader.compensateFor09HeaderBug = (config.getMeterType() == 1);
// Empty buffer before starting
while (hanSerial->available() > 0) {
hanSerial->read();
}
if(config.hasConfig() && config.isDebugSerial()) {
if(WiFi.status() == WL_CONNECTED) {
Debug.begin(config.getWifiHostname(), (uint8_t) config.getDebugLevel());
}
Debug.setSerialEnabled(config.isDebugSerial());
if(!config.isDebugTelnet()) {
Debug.stop();
}
}
}
void errorBlink() {
@@ -382,19 +424,19 @@ void errorBlink() {
switch(lastError) {
case 0:
if(lastErrorBlink - lastSuccessfulRead > 30000) {
rgb_led(1, 2); // If no message received from AMS in 30 sec, blink once
hw.ledBlink(LED_RED, 1); // If no message received from AMS in 30 sec, blink once
return;
}
break;
case 1:
if(!config.getMqttHost().isEmpty() && mqtt.lastError() != 0) {
rgb_led(1, 3); // If MQTT error, blink twice
if(strlen(config.getMqttHost()) > 0 && mqtt.lastError() != 0) {
hw.ledBlink(LED_RED, 2); // If MQTT error, blink twice
return;
}
break;
case 2:
if(WiFi.getMode() != WIFI_AP && WiFi.status() != WL_CONNECTED) {
rgb_led(1, 4); // If WiFi not connected, blink three times
hw.ledBlink(LED_RED, 3); // If WiFi not connected, blink three times
return;
}
break;
@@ -403,7 +445,7 @@ void errorBlink() {
}
void swapWifiMode() {
led_on();
hw.ledOn(LED_INTERNAL);
WiFiMode_t mode = WiFi.getMode();
dnsServer.stop();
WiFi.disconnect(true);
@@ -423,7 +465,7 @@ void swapWifiMode() {
WiFi_connect();
}
delay(500);
led_off();
hw.ledOff(LED_INTERNAL);
}
void mqttMessageReceived(String &topic, String &payload)
@@ -437,6 +479,7 @@ void mqttMessageReceived(String &topic, String &payload)
// Ideas could be to query for values or to initiate OTA firmware update
}
int currentMeterType = 0;
AmsData lastMqttData;
void readHanPort() {
if (hanReader.read()) {
@@ -448,13 +491,16 @@ void readHanPort() {
lastSuccessfulRead = millis();
if(config.getMeterType() > 0) {
rgb_led(RGB_GREEN, 2);
if(config.getLedPinGreen() != 0xFF)
hw.ledBlink(LED_GREEN, 1);
else
hw.ledBlink(LED_INTERNAL, 1);
AmsData data(config.getMeterType(), hanReader);
if(data.getListType() > 0) {
ws.setData(data);
if(!config.getMqttHost().isEmpty() && !config.getMqttPublishTopic().isEmpty()) {
if(strlen(config.getMqttHost()) > 0 && strlen(config.getMqttPublishTopic()) > 0) {
if(config.getMqttPayloadFormat() == 0) {
StaticJsonDocument<512> json;
hanToJson(json, data, hw, temperature);
@@ -469,55 +515,55 @@ void readHanPort() {
serializeJson(json, msg);
mqtt.publish(config.getMqttPublishTopic(), msg.c_str());
} else if(config.getMqttPayloadFormat() == 1 || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/dlms/timestamp", String(data.getPackageTimestamp()));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/dlms/timestamp", String(data.getPackageTimestamp()));
switch(data.getListType()) {
case 3:
// ID and type belongs to List 2, but I see no need to send that every 10s
mqtt.publish(config.getMqttPublishTopic() + "/meter/id", data.getMeterId());
mqtt.publish(config.getMqttPublishTopic() + "/meter/type", data.getMeterType());
mqtt.publish(config.getMqttPublishTopic() + "/meter/clock", String(data.getMeterTimestamp()));
mqtt.publish(config.getMqttPublishTopic() + "/meter/import/reactive/accumulated", String(data.getReactiveImportCounter(), 2));
mqtt.publish(config.getMqttPublishTopic() + "/meter/import/active/accumulated", String(data.getActiveImportCounter(), 2));
mqtt.publish(config.getMqttPublishTopic() + "/meter/export/reactive/accumulated", String(data.getReactiveExportCounter(), 2));
mqtt.publish(config.getMqttPublishTopic() + "/meter/export/active/accumulated", String(data.getActiveExportCounter(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/id", data.getMeterId());
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/type", data.getMeterType());
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/clock", String(data.getMeterTimestamp()));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/import/reactive/accumulated", String(data.getReactiveImportCounter(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/import/active/accumulated", String(data.getActiveImportCounter(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/export/reactive/accumulated", String(data.getReactiveExportCounter(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/export/active/accumulated", String(data.getActiveExportCounter(), 2));
case 2:
// Only send data if changed. ID and Type is sent on the 10s interval only if changed
if(lastMqttData.getMeterId() != data.getMeterId() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/id", data.getMeterId());
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/id", data.getMeterId());
}
if(lastMqttData.getMeterType() != data.getMeterType() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/type", data.getMeterType());
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/type", data.getMeterType());
}
if(lastMqttData.getL1Current() != data.getL1Current() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/l1/current", String(data.getL1Current(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/l1/current", String(data.getL1Current(), 2));
}
if(lastMqttData.getL1Voltage() != data.getL1Voltage() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/l1/voltage", String(data.getL1Voltage(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/l1/voltage", String(data.getL1Voltage(), 2));
}
if(lastMqttData.getL2Current() != data.getL2Current() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/l2/current", String(data.getL2Current(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/l2/current", String(data.getL2Current(), 2));
}
if(lastMqttData.getL2Voltage() != data.getL2Voltage() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/l2/voltage", String(data.getL2Voltage(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/l2/voltage", String(data.getL2Voltage(), 2));
}
if(lastMqttData.getL3Current() != data.getL3Current() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/l3/current", String(data.getL3Current(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/l3/current", String(data.getL3Current(), 2));
}
if(lastMqttData.getL3Voltage() != data.getL3Voltage() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/l3/voltage", String(data.getL3Voltage(), 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/l3/voltage", String(data.getL3Voltage(), 2));
}
if(lastMqttData.getReactiveExportPower() != data.getReactiveExportPower() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/export/reactive", String(data.getReactiveExportPower()));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/export/reactive", String(data.getReactiveExportPower()));
}
if(lastMqttData.getActiveExportPower() != data.getActiveExportPower() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/export/active", String(data.getActiveExportPower()));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/export/active", String(data.getActiveExportPower()));
}
if(lastMqttData.getReactiveImportPower() != data.getReactiveImportPower() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/import/reactive", String(data.getReactiveImportPower()));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/import/reactive", String(data.getReactiveImportPower()));
}
case 1:
if(lastMqttData.getActiveImportPower() != data.getActiveImportPower() || config.getMqttPayloadFormat() == 2) {
mqtt.publish(config.getMqttPublishTopic() + "/meter/import/active", String(data.getActiveImportPower()));
mqtt.publish(String(config.getMqttPublishTopic()) + "/meter/import/active", String(data.getActiveImportPower()));
}
}
}
@@ -565,22 +611,10 @@ void readHanPort() {
// Switch parity if meter is still not detected
if(config.getMeterType() == 0 && millis() - lastSuccessfulRead > 10000) {
lastSuccessfulRead = millis();
if(Debug.isActive(RemoteDebug::DEBUG)) debugD("No data for current setting, switching parity");
debugD("No data for current setting, switching parity");
Serial.flush();
#if SOFTWARE_SERIAL
if(even) {
hanSerial->begin(2400, SWSERIAL_8N1);
} else {
hanSerial->begin(2400, SWSERIAL_8E1);
}
#else
if(even) {
hanSerial->begin(2400, SERIAL_8N1);
} else {
hanSerial->begin(2400, SERIAL_8E1);
}
#endif
even = !even;
if(++currentMeterType == 4) currentMeterType = 1;
setupHanPort(config.getHanPin(), currentMeterType);
}
}
@@ -593,7 +627,7 @@ void WiFi_connect() {
}
lastWifiRetry = millis();
if (Debug.isActive(RemoteDebug::INFO)) debugI("Connecting to WiFi network: %s", config.getWifiSsid().c_str());
if (Debug.isActive(RemoteDebug::INFO)) debugI("Connecting to WiFi network: %s", config.getWifiSsid());
if (WiFi.status() != WL_CONNECTED) {
MDNS.end();
@@ -602,7 +636,7 @@ void WiFi_connect() {
WiFi.enableAP(false);
WiFi.mode(WIFI_STA);
if(!config.getWifiIp().isEmpty()) {
if(strlen(config.getWifiIp()) > 0) {
IPAddress ip, gw, sn(255,255,255,0), dns1, dns2;
ip.fromString(config.getWifiIp());
gw.fromString(config.getWifiGw());
@@ -611,21 +645,21 @@ void WiFi_connect() {
dns2.fromString(config.getWifiDns2());
WiFi.config(ip, gw, sn, dns1, dns2);
}
if(!config.getWifiHostname().isEmpty()) {
if(strlen(config.getWifiHostname()) > 0) {
#if defined(ESP8266)
WiFi.hostname(config.getWifiHostname());
#elif defined(ESP32)
WiFi.setHostname(config.getWifiHostname().c_str());
WiFi.setHostname(config.getWifiHostname());
#endif
}
WiFi.begin(config.getWifiSsid().c_str(), config.getWifiPassword().c_str());
WiFi.begin(config.getWifiSsid(), config.getWifiPassword());
yield();
}
}
unsigned long lastMqttRetry = -10000;
void MQTT_connect() {
if(config.getMqttHost().isEmpty()) {
if(strlen(config.getMqttHost()) == 0) {
if(Debug.isActive(RemoteDebug::WARNING)) debugW("No MQTT config");
return;
}
@@ -635,7 +669,7 @@ void MQTT_connect() {
}
lastMqttRetry = millis();
if(Debug.isActive(RemoteDebug::INFO)) {
debugI("Connecting to MQTT %s:%d", config.getMqttHost().c_str(), config.getMqttPort());
debugI("Connecting to MQTT %s:%d", config.getMqttHost(), config.getMqttPort());
}
mqtt.disconnect();
@@ -680,22 +714,22 @@ void MQTT_connect() {
client = new WiFiClient();
}
mqtt.begin(config.getMqttHost().c_str(), config.getMqttPort(), *client);
mqtt.begin(config.getMqttHost(), config.getMqttPort(), *client);
#if defined(ESP8266)
if(secureClient) secureClient->setX509Time(timeClient.getEpochTime());
#endif
// Connect to a unsecure or secure MQTT server
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 ((strlen(config.getMqttUser()) == 0 && mqtt.connect(config.getMqttClientId())) ||
(strlen(config.getMqttUser()) > 0 && mqtt.connect(config.getMqttClientId(), config.getMqttUser(), config.getMqttPassword()))) {
if (Debug.isActive(RemoteDebug::INFO)) debugI("Successfully connected to MQTT!");
config.ackMqttChange();
// Subscribe to the chosen MQTT topic, if set in configuration
if (!config.getMqttSubscribeTopic().isEmpty()) {
if (strlen(config.getMqttSubscribeTopic()) > 0) {
mqtt.subscribe(config.getMqttSubscribeTopic());
if (Debug.isActive(RemoteDebug::INFO)) debugI(" Subscribing to [%s]\r\n", config.getMqttSubscribeTopic().c_str());
if (Debug.isActive(RemoteDebug::INFO)) debugI(" Subscribing to [%s]\r\n", config.getMqttSubscribeTopic());
}
if(config.getMqttPayloadFormat() == 0) {
@@ -722,7 +756,7 @@ void MQTT_connect() {
void sendMqttData(String data)
{
// Make sure we have configured a publish topic
if (config.getMqttPublishTopic().isEmpty())
if (strlen(config.getMqttPublishTopic()) == 0)
return;
// Build a json with the message in a "data" attribute
@@ -749,63 +783,20 @@ void sendMqttData(String data)
unsigned long lastSystemDataSent = -10000;
void sendSystemStatusToMqtt() {
if (config.getMqttPublishTopic().isEmpty())
if (strlen(config.getMqttPublishTopic()) == 0)
return;
if(millis() - lastSystemDataSent < 10000)
return;
lastSystemDataSent = millis();
mqtt.publish(config.getMqttPublishTopic() + "/id", WiFi.macAddress());
mqtt.publish(config.getMqttPublishTopic() + "/uptime", String((unsigned long) millis64()/1000));
mqtt.publish(String(config.getMqttPublishTopic()) + "/id", WiFi.macAddress());
mqtt.publish(String(config.getMqttPublishTopic()) + "/uptime", String((unsigned long) millis64()/1000));
double vcc = hw.getVcc();
if(vcc > 0) {
mqtt.publish(config.getMqttPublishTopic() + "/vcc", String(vcc, 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/vcc", String(vcc, 2));
}
mqtt.publish(config.getMqttPublishTopic() + "/rssi", String(hw.getWifiRssi()));
mqtt.publish(String(config.getMqttPublishTopic()) + "/rssi", String(hw.getWifiRssi()));
if(temperature != DEVICE_DISCONNECTED_C) {
mqtt.publish(config.getMqttPublishTopic() + "/temperature", String(temperature, 2));
mqtt.publish(String(config.getMqttPublishTopic()) + "/temperature", String(temperature, 2));
}
}
void rgb_led(int color, int mode) {
// Activate red and green LEDs if RGB LED is present (HAS_RGB_LED=1)
// If no RGB LED present (HAS_RGB_LED=0 or not defined), all output goes to ESP onboard LED
// color: 1=red, 2=green, 3=yellow
// mode: 0=OFF, 1=ON, >=2 -> Short blink(s), number of blinks: (mode - 1)
#ifndef HAS_RGB_LED
#define LEDPIN_RGB_RED LED_PIN
#define LEDPIN_RGB_GREEN LED_PIN
#endif
int blinkduration = 50; // milliseconds
switch (mode) {
case RGB_OFF: //OFF
digitalWrite(LEDPIN_RGB_RED, HIGH);
digitalWrite(LEDPIN_RGB_GREEN, HIGH);
break;
case RGB_ON: //ON
switch (color) {
case RGB_RED: //Red
digitalWrite(LEDPIN_RGB_RED, LOW);
digitalWrite(LEDPIN_RGB_GREEN, HIGH);
break;
case RGB_GREEN: //Green
digitalWrite(LEDPIN_RGB_RED, HIGH);
digitalWrite(LEDPIN_RGB_GREEN, LOW);
break;
case RGB_YELLOW: //Yellow
digitalWrite(LEDPIN_RGB_RED, LOW);
digitalWrite(LEDPIN_RGB_GREEN, LOW);
break;
}
break;
default: // Blink
for(int i = 1; i < mode; i++) {
rgb_led(color, RGB_ON);
delay(blinkduration);
rgb_led(color, RGB_OFF);
if(i != mode)
delay(blinkduration);
}
break;
}
}

View File

@@ -1,44 +1,164 @@
#include "HwTools.h"
void HwTools::setTempSensorPin(int tempSensorPin) {
if(tempSensorPin != this->tempSensorPin) {
this->tempSensorInit = false;
if(tempSensor)
delete tempSensor;
if(oneWire)
delete oneWire;
if(tempSensorPin > 0 && tempSensorPin < 40) {
this->tempSensorPin = tempSensorPin;
pinMode(tempSensorPin, INPUT);
} else {
this->tempSensorPin = 0xFF;
}
}
}
void HwTools::setVccPin(int vccPin) {
if(vccPin > 0 && vccPin < 40) {
pinMode(vccPin, INPUT);
this->vccPin = vccPin;
} else {
this->vccPin = 0xFF;
}
}
void HwTools::setVccMultiplier(double vccMultiplier) {
this->vccMultiplier = vccMultiplier;
}
double HwTools::getVcc() {
double volts = 0.0;
#if defined(ARDUINO_ESP8266_WEMOS_D1MINI)
volts = (((double) ESP.getVcc()) / 900.0); // This board has a voltage divider on VCC.
#elif defined(ARDUINO_LOLIN_D32)
volts = (analogRead(GPIO_NUM_35) / 4095.0) * 3.3 * 2.25; // We are actually reading battery voltage here
#elif defined(ESP8266)
volts = ((double) ESP.getVcc()) / 1024.0;
#endif
if(vccPin != 0xFF) {
#if defined(ESP8266)
volts = (analogRead(vccPin) / 1024.0) * 3.3;
#elif defined(ESP32)
volts = (analogRead(vccPin) / 4095.0) * 3.3;
#endif
} else {
#if defined(ESP8266)
volts = ((double) ESP.getVcc()) / 1024.0;
#endif
}
#if defined(ESP_VCC_CALIB_FACTOR)
return volts * ESP_VCC_CALIB_FACTOR;
#else
return volts;
#endif
return volts > 0.0 ? volts * vccMultiplier : 0.0;
}
double HwTools::getTemperature() {
if(tempSensorPin != 0xFF) {
if(!tempSensorInit) {
oneWire = new OneWire(tempSensorPin);
tempSensor = new DallasTemperature(this->oneWire);
tempSensor->begin();
delay(50);
tempSensor->requestTemperatures();
hasTempSensor = tempSensor->getTempCByIndex(0) != DEVICE_DISCONNECTED_C;
tempSensorInit = true;
}
#if defined TEMP_SENSOR_PIN
if(!tempSensorInit) {
tempSensor->begin();
delay(50);
tempSensor->requestTemperatures();
hasTempSensor = tempSensor->getTempCByIndex(0) != DEVICE_DISCONNECTED_C;
tempSensorInit = true;
if(hasTempSensor) {
tempSensor->requestTemperatures();
return tempSensor->getTempCByIndex(0);
} else {
return DEVICE_DISCONNECTED_C;
}
}
if(hasTempSensor) {
tempSensor->requestTemperatures();
return tempSensor->getTempCByIndex(0);
} else {
return DEVICE_DISCONNECTED_C;
}
#endif
return DEVICE_DISCONNECTED_C;
}
int HwTools::getWifiRssi() {
int rssi = WiFi.RSSI();
return isnan(rssi) ? -100.0 : rssi;
}
}
void HwTools::setLed(uint8_t ledPin, bool ledInverted) {
if(ledPin > 0 && ledPin < 40) {
this->ledPin = ledPin;
this->ledInverted = ledInverted;
pinMode(ledPin, OUTPUT);
ledOff(LED_INTERNAL);
} else {
this->ledPin = 0xFF;
}
}
void HwTools::setLedRgb(uint8_t ledPinRed, uint8_t ledPinGreen, uint8_t ledPinBlue, bool ledRgbInverted) {
this->ledRgbInverted = ledRgbInverted;
if(ledPinRed > 0 && ledPinRed < 40) {
this->ledPinRed = ledPinRed;
pinMode(ledPinRed, OUTPUT);
ledOff(LED_RED);
} else {
this->ledPinRed = 0xFF;
}
if(ledPinGreen > 0 && ledPinGreen < 40) {
this->ledPinGreen = ledPinGreen;
pinMode(ledPinGreen, OUTPUT);
ledOff(LED_GREEN);
} else {
this->ledPinGreen = 0xFF;
}
if(ledPinBlue > 0 && ledPinBlue < 40) {
this->ledPinBlue = ledPinBlue;
pinMode(ledPinBlue, OUTPUT);
ledOff(LED_BLUE);
} else {
this->ledPinBlue = 0xFF;
}
}
void HwTools::ledOn(uint8_t color) {
if(color == LED_INTERNAL) {
writeLedPin(color, ledInverted ? LOW : HIGH);
} else {
writeLedPin(color, ledRgbInverted ? LOW : HIGH);
}
}
void HwTools::ledOff(uint8_t color) {
if(color == LED_INTERNAL) {
writeLedPin(color, ledInverted ? HIGH : LOW);
} else {
writeLedPin(color, ledRgbInverted ? HIGH : LOW);
}
}
void HwTools::ledBlink(uint8_t color, uint8_t blink) {
for(int i = 0; i < blink; i++) {
ledOn(color);
delay(50);
ledOff(color);
if(i != blink)
delay(50);
}
}
void HwTools::writeLedPin(uint8_t color, uint8_t state) {
switch(color) {
case LED_INTERNAL:
if(ledPin != 0xFF)
digitalWrite(ledPin, state);
break;
case LED_RED:
if(ledPinRed != 0xFF)
digitalWrite(ledPinRed, state);
break;
case LED_GREEN:
if(ledPinGreen != 0xFF)
digitalWrite(ledPinGreen, state);
break;
case LED_BLUE:
if(ledPinBlue != 0xFF)
digitalWrite(ledPinBlue, state);
break;
case LED_YELLOW:
if(ledPinRed != 0xFF && ledPinGreen != 0xFF) {
digitalWrite(ledPinRed, state);
digitalWrite(ledPinGreen, state);
}
break;
}
}

View File

@@ -12,35 +12,38 @@
#include <DallasTemperature.h>
#include <OneWire.h>
#if HW_ROARFRED
#define TEMP_SENSOR_PIN 5
#elif defined(ARDUINO_LOLIN_D32)
#define TEMP_SENSOR_PIN 14
#elif defined(ARDUINO_ESP8266_WEMOS_D1MINI)
#define TEMP_SENSOR_PIN D5
#else
#define TEMP_SENSOR_PIN 0xFFFFFFFF
#endif
#define LED_INTERNAL 0
#define LED_RED 1
#define LED_GREEN 2
#define LED_BLUE 3
#define LED_YELLOW 4
class HwTools {
public:
void setTempSensorPin(int tempSensorPin);
void setVccPin(int vccPin);
void setVccMultiplier(double vccMultiplier);
double getVcc();
double getTemperature();
int getWifiRssi();
void setLed(uint8_t ledPin, bool ledInverted);
void setLedRgb(uint8_t ledPinRed, uint8_t ledPinGreen, uint8_t ledPinBlue, bool ledRgbInverted);
void ledOn(uint8_t color);
void ledOff(uint8_t color);
void ledBlink(uint8_t color, uint8_t blink);
HwTools() {
#if defined(ARDUINO_LOLIN_D32)
pinMode(GPIO_NUM_35, INPUT);
#endif
oneWire = new OneWire(TEMP_SENSOR_PIN);
tempSensor = new DallasTemperature(this->oneWire);
};
HwTools() {};
private:
uint8_t tempSensorPin = -1;
uint8_t vccPin = -1;
uint8_t ledPin = -1, ledPinRed = -1, ledPinGreen = -1, ledPinBlue = -1;
bool ledInverted, ledRgbInverted;
double vccMultiplier = 1.0;
bool tempSensorInit, hasTempSensor;
OneWire *oneWire;
DallasTemperature *tempSensor;
void writeLedPin(uint8_t color, uint8_t state);
};
#endif

View File

@@ -4,6 +4,7 @@
#include "root/index_html.h"
#include "root/index_js.h"
#include "root/setup_html.h"
#include "root/configmeter_html.h"
#include "root/configwifi_html.h"
#include "root/configmqtt_html.h"
@@ -17,8 +18,9 @@
#include "Base64.h"
AmsWebServer::AmsWebServer(RemoteDebug* Debug) {
AmsWebServer::AmsWebServer(RemoteDebug* Debug, HwTools* hw) {
this->debugger = Debug;
this->hw = hw;
}
void AmsWebServer::setup(AmsConfiguration* config, MQTTClient* mqtt) {
@@ -26,6 +28,7 @@ void AmsWebServer::setup(AmsConfiguration* config, MQTTClient* mqtt) {
this->mqtt = mqtt;
server.on("/", HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on("/", HTTP_POST, std::bind(&AmsWebServer::handleSetup, this));
server.on("/index.js", HTTP_GET, std::bind(&AmsWebServer::indexJs, this));
server.on("/config-meter", HTTP_GET, std::bind(&AmsWebServer::configMeterHtml, this));
server.on("/config-wifi", HTTP_GET, std::bind(&AmsWebServer::configWifiHtml, this));
@@ -38,7 +41,8 @@ void AmsWebServer::setup(AmsConfiguration* config, MQTTClient* mqtt) {
server.on("/save", HTTP_POST, std::bind(&AmsWebServer::handleSave, this));
server.on("/config-system", HTTP_GET, std::bind(&AmsWebServer::configSystemHtml, this));
server.on("/config-system", HTTP_POST, std::bind(&AmsWebServer::uploadPost, this), std::bind(&AmsWebServer::configSystemUpload, this));
server.on("/firmware", HTTP_GET, std::bind(&AmsWebServer::firmwareHtml, this));
server.on("/firmware", HTTP_POST, std::bind(&AmsWebServer::uploadPost, this), std::bind(&AmsWebServer::firmwareUpload, this));
server.on("/restart-wait", HTTP_GET, std::bind(&AmsWebServer::restartWaitHtml, this));
server.on("/is-alive", HTTP_GET, std::bind(&AmsWebServer::isAliveCheck, this));
@@ -110,62 +114,64 @@ bool AmsWebServer::checkSecurity(byte level) {
void AmsWebServer::indexHtml() {
printD("Serving /index.html over http...");
if(!checkSecurity(2))
return;
String html;
if(WiFi.getMode() == WIFI_AP) {
html = String((const __FlashStringHelper*) SETUP_HTML);
html.replace("${version}", VERSION);
} else {
if(!checkSecurity(2))
return;
String html = String((const __FlashStringHelper*) INDEX_HTML);
html.replace("${version}", VERSION);
html = String((const __FlashStringHelper*) INDEX_HTML);
html.replace("${version}", VERSION);
if(WiFi.getMode() != WIFI_AP) {
html.replace("boot.css", BOOTSTRAP_URL);
double u1 = data.getL1Voltage();
double u2 = data.getL2Voltage();
double u3 = data.getL3Voltage();
double i1 = data.getL1Current();
double i2 = data.getL2Current();
double i3 = data.getL3Current();
double tpi = data.getActiveImportCounter();
double tpo = data.getActiveExportCounter();
double tqi = data.getReactiveImportCounter();
double tqo = data.getReactiveExportCounter();
html.replace("${data.P}", String(data.getActiveImportPower()));
html.replace("${data.PO}", String(data.getActiveExportPower()));
html.replace("${display.export}", config->getProductionCapacity() > 0 ? "" : "none");
html.replace("${text.import}", config->getProductionCapacity() > 0 ? "Import" : "Consumption");
html.replace("${data.U1}", u1 > 0 ? String(u1, 1) : "");
html.replace("${data.I1}", u1 > 0 ? String(i1, 1) : "");
html.replace("${display.P1}", u1 > 0 ? "" : "none");
html.replace("${data.U2}", u2 > 0 ? String(u2, 1) : "");
html.replace("${data.I2}", u2 > 0 ? String(i2, 1) : "");
html.replace("${display.P2}", u2 > 0 ? "" : "none");
html.replace("${data.U3}", u3 > 0 ? String(u3, 1) : "");
html.replace("${data.I3}", u3 > 0 ? String(i3, 1) : "");
html.replace("${display.P3}", u3 > 0 ? "" : "none");
html.replace("${data.tPI}", tpi > 0 ? String(tpi, 1) : "");
html.replace("${data.tPO}", tpi > 0 ? String(tpo, 1) : "");
html.replace("${data.tQI}", tpi > 0 ? String(tqi, 1) : "");
html.replace("${data.tQO}", tpi > 0 ? String(tqo, 1) : "");
html.replace("${display.accumulative}", tpi > 0 ? "" : "none");
double vcc = hw->getVcc();
html.replace("${vcc}", vcc > 0 ? String(vcc, 2) : "");
double temp = hw->getTemperature();
html.replace("${temp}", temp > 0 ? String(temp, 1) : "");
html.replace("${display.temp}", temp != DEVICE_DISCONNECTED_C ? "" : "none");
int rssi = hw->getWifiRssi();
html.replace("${wifi.rssi}", vcc > 0 ? String(rssi) : "");
html.replace("${wifi.channel}", WiFi.channel() > 0 ? String(WiFi.channel()) : "");
html.replace("${wifi.ssid}", !WiFi.SSID().isEmpty() ? String(WiFi.SSID()) : "");
}
double u1 = data.getL1Voltage();
double u2 = data.getL2Voltage();
double u3 = data.getL3Voltage();
double i1 = data.getL1Current();
double i2 = data.getL2Current();
double i3 = data.getL3Current();
double tpi = data.getActiveImportCounter();
double tpo = data.getActiveExportCounter();
double tqi = data.getReactiveImportCounter();
double tqo = data.getReactiveExportCounter();
html.replace("${data.P}", String(data.getActiveImportPower()));
html.replace("${data.PO}", String(data.getActiveExportPower()));
html.replace("${display.export}", config->getProductionCapacity() > 0 ? "" : "none");
html.replace("${text.import}", config->getProductionCapacity() > 0 ? "Import" : "Consumption");
html.replace("${data.U1}", u1 > 0 ? String(u1, 1) : "");
html.replace("${data.I1}", u1 > 0 ? String(i1, 1) : "");
html.replace("${display.P1}", u1 > 0 ? "" : "none");
html.replace("${data.U2}", u2 > 0 ? String(u2, 1) : "");
html.replace("${data.I2}", u2 > 0 ? String(i2, 1) : "");
html.replace("${display.P2}", u2 > 0 ? "" : "none");
html.replace("${data.U3}", u3 > 0 ? String(u3, 1) : "");
html.replace("${data.I3}", u3 > 0 ? String(i3, 1) : "");
html.replace("${display.P3}", u3 > 0 ? "" : "none");
html.replace("${data.tPI}", tpi > 0 ? String(tpi, 1) : "");
html.replace("${data.tPO}", tpi > 0 ? String(tpo, 1) : "");
html.replace("${data.tQI}", tpi > 0 ? String(tqi, 1) : "");
html.replace("${data.tQO}", tpi > 0 ? String(tqo, 1) : "");
html.replace("${display.accumulative}", tpi > 0 ? "" : "none");
double vcc = hw.getVcc();
html.replace("${vcc}", vcc > 0 ? String(vcc, 2) : "");
double temp = hw.getTemperature();
html.replace("${temp}", temp > 0 ? String(temp, 1) : "");
html.replace("${display.temp}", temp != DEVICE_DISCONNECTED_C ? "" : "none");
int rssi = hw.getWifiRssi();
html.replace("${wifi.rssi}", vcc > 0 ? String(rssi) : "");
html.replace("${wifi.channel}", WiFi.channel() > 0 ? String(WiFi.channel()) : "");
html.replace("${wifi.ssid}", !WiFi.SSID().isEmpty() ? String(WiFi.SSID()) : "");
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
@@ -190,10 +196,6 @@ void AmsWebServer::configMeterHtml() {
String html = String((const __FlashStringHelper*) CONFIGMETER_HTML);
html.replace("${version}", VERSION);
if(WiFi.getMode() != WIFI_AP) {
html.replace("boot.css", BOOTSTRAP_URL);
}
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
@@ -224,16 +226,12 @@ void AmsWebServer::configWifiHtml() {
String html = String((const __FlashStringHelper*) CONFIGWIFI_HTML);
html.replace("${version}", VERSION);
if(WiFi.getMode() != WIFI_AP) {
html.replace("boot.css", BOOTSTRAP_URL);
}
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.wifiIpType1}", strlen(config->getWifiIp()) > 0 ? "selected" : "");
html.replace("${config.wifiIp}", config->getWifiIp());
html.replace("${config.wifiGw}", config->getWifiGw());
html.replace("${config.wifiSubnet}", config->getWifiSubnet());
@@ -254,14 +252,10 @@ void AmsWebServer::configMqttHtml() {
String html = String((const __FlashStringHelper*) CONFIGMQTT_HTML);
html.replace("${version}", VERSION);
if(WiFi.getMode() != WIFI_AP) {
html.replace("boot.css", BOOTSTRAP_URL);
}
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.mqtt}", strlen(config->getMqttHost()) == 0 ? "" : "checked");
html.replace("${config.mqttHost}", config->getMqttHost());
if(config->getMqttPort() > 0) {
html.replace("${config.mqttPort}", String(config->getMqttPort()));
@@ -311,10 +305,6 @@ void AmsWebServer::configWebHtml() {
String html = String((const __FlashStringHelper*) CONFIGWEB_HTML);
html.replace("${version}", VERSION);
if(WiFi.getMode() != WIFI_AP) {
html.replace("boot.css", BOOTSTRAP_URL);
}
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
@@ -414,10 +404,10 @@ void AmsWebServer::dataJson() {
json["maxPower"] = maxPwr;
json["meterType"] = config->getMeterType();
json["uptime_seconds"] = millis64() / 1000;
double vcc = hw.getVcc();
double vcc = hw->getVcc();
json["vcc"] = serialized(String(vcc, 3));
double temp = hw.getTemperature();
double temp = hw->getTemperature();
json["temp"] = serialized(String(temp, 2));
json.createNestedObject("wifi");
@@ -455,7 +445,7 @@ void AmsWebServer::dataJson() {
json["status"]["han"] = hanStatus;
String wifiStatus;
if(config->getWifiSsid().isEmpty()) {
if(strlen(config->getWifiSsid()) == 0) {
wifiStatus = "secondary";
} else if(rssi > -75) {
wifiStatus = "success";
@@ -467,7 +457,7 @@ void AmsWebServer::dataJson() {
json["status"]["wifi"] = wifiStatus;
String mqttStatus;
if(config->getMqttHost().isEmpty()) {
if(strlen(config->getMqttHost()) == 0) {
mqttStatus = "secondary";
} else if(mqtt->connected()) {
mqttStatus = "success";
@@ -491,6 +481,100 @@ void AmsWebServer::dataJson() {
server.send(200, "application/json", jsonStr);
}
void AmsWebServer::handleSetup() {
if(!server.hasArg("wifiSsid") || server.arg("wifiSsid").isEmpty() || !server.hasArg("wifiPassword") || server.arg("wifiPassword").isEmpty()) {
server.sendHeader("Location", String("/"), true);
server.send (302, "text/plain", "");
} else {
config->setVccMultiplier(1.0);
config->setVccBootLimit(0);
switch(server.arg("board").toInt()) {
case 0: // roarfred
config->setHanPin(3);
config->setApPin(0);
config->setLedPin(2);
config->setLedInverted(true);
config->setTempSensorPin(5);
break;
case 1: // Arnio Kamstrup
config->setHanPin(3);
config->setApPin(0);
config->setLedPin(2);
config->setLedInverted(true);
config->setTempSensorPin(5);
config->setLedPinRed(13);
config->setLedPinGreen(14);
config->setLedRgbInverted(true);
break;
case 2: // spenceme
config->setHanPin(3);
config->setApPin(0);
config->setLedPin(2);
config->setLedInverted(true);
config->setTempSensorPin(5);
config->setVccBootLimit(3.3);
break;
case 101: // D1
config->setHanPin(5);
config->setApPin(4);
config->setLedPin(2);
config->setLedInverted(true);
config->setTempSensorPin(14);
config->setVccMultiplier(1.1);
break;
case 199: // ESP8266
config->setHanPin(3);
config->setLedPin(2);
config->setLedInverted(true);
break;
case 201: // D32
config->setHanPin(16);
config->setApPin(4);
config->setLedPin(5);
config->setLedInverted(true);
config->setTempSensorPin(14);
config->setVccPin(35);
config->setVccMultiplier(2.25);
break;
case 202: // Feather ESP32
config->setHanPin(16);
config->setLedPin(2);
config->setLedInverted(false);
config->setTempSensorPin(14);
break;
case 299: // ESP32
config->setHanPin(16);
config->setLedPin(2);
config->setLedInverted(true);
config->setTempSensorPin(14);
break;
}
config->setMeterType(server.arg("meterType").toInt());
config->setWifiSsid(server.arg("wifiSsid").c_str());
config->setWifiPassword(server.arg("wifiPassword").c_str());
if(server.hasArg("wifiIpType") && server.arg("wifiIpType").toInt() == 1) {
config->setWifiIp(server.arg("wifiIp").c_str());
config->setWifiGw(server.arg("wifiGw").c_str());
config->setWifiSubnet(server.arg("wifiSubnet").c_str());
config->setWifiDns1(server.arg("wifiDns1").c_str());
} else {
config->clearWifiIp();
}
if(server.hasArg("wifiHostname") && !server.arg("wifiHostname").isEmpty()) {
config->setWifiHostname(server.arg("wifiHostname").c_str());
}
if(config->save()) {
performRestart = true;
server.sendHeader("Location","/restart-wait");
server.send(303);
} else {
printE("Error saving configuration");
String html = "<html><body><h1>Error saving configuration!</h1></form>";
server.send(500, "text/html", html);
}
}
}
void AmsWebServer::handleSave() {
String temp;
@@ -502,30 +586,30 @@ void AmsWebServer::handleSave() {
}
if(server.hasArg("wifiConfig") && server.arg("wifiConfig") == "true") {
config->setWifiSsid(server.arg("wifiSsid"));
config->setWifiPassword(server.arg("wifiPassword"));
config->setWifiSsid(server.arg("wifiSsid").c_str());
config->setWifiPassword(server.arg("wifiPassword").c_str());
if(server.hasArg("wifiIpType") && server.arg("wifiIpType").toInt() == 1) {
config->setWifiIp(server.arg("wifiIp"));
config->setWifiGw(server.arg("wifiGw"));
config->setWifiSubnet(server.arg("wifiSubnet"));
config->setWifiDns1(server.arg("wifiDns1"));
config->setWifiDns2(server.arg("wifiDns2"));
config->setWifiIp(server.arg("wifiIp").c_str());
config->setWifiGw(server.arg("wifiGw").c_str());
config->setWifiSubnet(server.arg("wifiSubnet").c_str());
config->setWifiDns1(server.arg("wifiDns1").c_str());
config->setWifiDns2(server.arg("wifiDns2").c_str());
} else {
config->clearWifiIp();
}
config->setWifiHostname(server.arg("wifiHostname"));
config->setWifiHostname(server.arg("wifiHostname").c_str());
}
if(server.hasArg("mqttConfig") && server.arg("mqttConfig") == "true") {
if(server.hasArg("mqtt") && server.arg("mqtt") == "true") {
config->setMqttHost(server.arg("mqttHost"));
config->setMqttHost(server.arg("mqttHost").c_str());
int port = server.arg("mqttPort").toInt();
config->setMqttPort(port == 0 ? 1883 : port);
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->setMqttClientId(server.arg("mqttClientId").c_str());
config->setMqttPublishTopic(server.arg("mqttPublishTopic").c_str());
config->setMqttSubscribeTopic(server.arg("mqttSubscribeTopic").c_str());
config->setMqttUser(server.arg("mqttUser").c_str());
config->setMqttPassword(server.arg("mqttPassword").c_str());
config->setMqttPayloadFormat(server.arg("mqttPayloadFormat").toInt());
config->setMqttSsl(server.arg("mqttSsl") == "true");
} else {
@@ -536,8 +620,8 @@ void AmsWebServer::handleSave() {
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"));
config->setAuthUser(server.arg("authUser").c_str());
config->setAuthPassword(server.arg("authPassword").c_str());
debugger->setPassword(config->getAuthPassword());
} else {
debugger->setPassword("");
@@ -546,6 +630,19 @@ void AmsWebServer::handleSave() {
}
if(server.hasArg("sysConfig") && server.arg("sysConfig") == "true") {
config->setHanPin(server.arg("hanPin").toInt());
config->setLedPin(server.arg("ledPin").toInt());
config->setLedInverted(server.hasArg("ledInverted") && server.arg("ledInverted") == "true");
config->setLedPinRed(server.arg("ledPinRed").toInt());
config->setLedPinGreen(server.arg("ledPinGreen").toInt());
config->setLedPinBlue(server.arg("ledPinBlue").toInt());
config->setLedRgbInverted(server.hasArg("ledRgbInverted") && server.arg("ledRgbInverted") == "true");
config->setApPin(server.arg("apPin").toInt());
config->setTempSensorPin(server.arg("tempSensorPin").toInt());
config->setVccPin(server.arg("vccPin").toInt());
config->setVccMultiplier(server.arg("vccMultiplier").toDouble());
config->setVccBootLimit(server.arg("vccBootLimit").toDouble());
config->setDebugTelnet(server.hasArg("debugTelnet") && server.arg("debugTelnet") == "true");
config->setDebugSerial(server.hasArg("debugSerial") && server.arg("debugSerial") == "true");
config->setDebugLevel(server.arg("debugLevel").toInt());
@@ -575,6 +672,12 @@ void AmsWebServer::handleSave() {
} else {
server.sendHeader("Location", String("/"), true);
server.send (302, "text/plain", "");
hw->setLed(config->getLedPin(), config->isLedInverted());
hw->setLedRgb(config->getLedPinRed(), config->getLedPinGreen(), config->getLedPinBlue(), config->isLedRgbInverted());
hw->setTempSensorPin(config->getTempSensorPin());
hw->setVccPin(config->getVccPin());
hw->setVccMultiplier(config->getVccMultiplier());
}
} else {
printE("Error saving configuration");
@@ -592,9 +695,26 @@ void AmsWebServer::configSystemHtml() {
String html = String((const __FlashStringHelper*) CONFIGSYSTEM_HTML);
html.replace("${version}", VERSION);
if(WiFi.getMode() != WIFI_AP) {
html.replace("boot.css", BOOTSTRAP_URL);
}
#if defined(ESP32)
html.replace("${gpio.max}", "39");
#else
html.replace("${gpio.max}", "16");
#endif
html.replace("${options.han}", getSerialSelectOptions(config->getHanPin()));
html.replace("${config.ledPin}", config->getLedPin() == 0xFF ? "" : String(config->getLedPin()));
html.replace("${config.ledInverted}", String(config->isLedInverted()) ? "checked" : "");
html.replace("${config.ledPinRed}", config->getLedPinRed() == 0xFF ? "" : String(config->getLedPinRed()));
html.replace("${config.ledPinGreen}", config->getLedPinGreen() == 0xFF ? "" : String(config->getLedPinGreen()));
html.replace("${config.ledPinBlue}", config->getLedPinBlue() == 0xFF ? "" : String(config->getLedPinBlue()));
html.replace("${config.ledRgbInverted}", String(config->isLedRgbInverted() ? "checked" : ""));
html.replace("${config.apPin}", config->getApPin() == 0xFF ? "" : String(config->getApPin()));
html.replace("${config.tempSensorPin}", config->getTempSensorPin() == 0xFF ? "" : String(config->getTempSensorPin()));
html.replace("${config.vccPin}", config->getVccPin() == 0xFF ? "" : String(config->getVccPin()));
html.replace("${config.vccMultiplier}", String(config->getVccMultiplier()));
html.replace("${config.vccBootLimit}", String(config->getVccBootLimit()));
html.replace("${config.debugTelnet}", config->isDebugTelnet() ? "checked" : "");
html.replace("${config.debugSerial}", config->isDebugSerial() ? "checked" : "");
@@ -610,6 +730,44 @@ void AmsWebServer::configSystemHtml() {
server.send(200, "text/html", html);
}
String AmsWebServer::getSerialSelectOptions(int selected) {
String gpioOptions;
if(selected == 3) {
gpioOptions += "<option value=\"3\" selected>UART0</option>\n";
} else {
gpioOptions += "<option value=\"3\">UART0</option>\n";
}
#if defined(ESP32)
int numGpio = 24;
int gpios[] = {4,5,6,7,8,10,11,12,13,14,15,17,18,19,21,22,23,25,32,33,34,35,36,39};
if(selected == 9) {
gpioOptions += "<option value=\"9\" selected>UART1</option>\n";
} else {
gpioOptions += "<option value=\"9\">UART1</option>\n";
}
if(selected == 16) {
gpioOptions += "<option value=\"16\" selected>UART2</option>\n";
} else {
gpioOptions += "<option value=\"16\">UART2</option>\n";
}
#elif defined(ESP8266)
int numGpio = 9;
int gpios[] = {4,5,9,10,12,13,14,15,16};
#endif
for(int i = 0; i < numGpio; i++) {
int gpio = gpios[i];
char buffer [16];
sprintf(buffer, "%02u", gpio);
if(gpio == selected) {
gpioOptions += "<option value=\"" + String(gpio) + "\" selected>GPIO" + buffer + "</option>\n";
} else {
gpioOptions += "<option value=\"" + String(gpio) + "\">GPIO" + buffer + "</option>\n";
}
}
return gpioOptions;
}
void AmsWebServer::uploadPost() {
server.send(200);
}
@@ -648,7 +806,13 @@ void AmsWebServer::deleteFile(const char* path) {
}
}
void AmsWebServer::configSystemUpload() {
void AmsWebServer::firmwareHtml() {
printD("Serving /firmware.html over http...");
uploadHtml("CA file", "/firmware", "mqtt");
}
void AmsWebServer::firmwareUpload() {
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START) {
String filename = upload.filename;
@@ -676,7 +840,7 @@ void AmsWebServer::restartWaitHtml() {
if(WiFi.getMode() != WIFI_AP) {
html.replace("boot.css", BOOTSTRAP_URL);
}
if(config->getWifiIp().isEmpty() && WiFi.getMode() != WIFI_AP) {
if(strlen(config->getWifiIp()) == 0 && WiFi.getMode() != WIFI_AP) {
html.replace("${ip}", WiFi.localIP().toString());
} else {
html.replace("${ip}", config->getWifiIp());
@@ -713,10 +877,6 @@ void AmsWebServer::uploadHtml(const char* label, const char* action, const char*
html.replace("${form.action}", action);
html.replace("${version}", VERSION);
if(WiFi.getMode() != WIFI_AP) {
html.replace("boot.css", BOOTSTRAP_URL);
}
html.replace("${menu." + String(menu) + ".class}", "active");
html.replace("${menu.meter.class}", "");
html.replace("${menu.wifi.class}", "");
@@ -737,10 +897,6 @@ void AmsWebServer::deleteHtml(const char* label, const char* action, const char*
html.replace("${form.action}", action);
html.replace("${version}", VERSION);
if(WiFi.getMode() != WIFI_AP) {
html.replace("boot.css", BOOTSTRAP_URL);
}
html.replace("${menu." + String(menu) + ".class}", "active");
html.replace("${menu.meter.class}", "");
html.replace("${menu.wifi.class}", "");
@@ -759,7 +915,6 @@ void AmsWebServer::deleteHtml(const char* label, const char* action, const char*
void AmsWebServer::mqttCa() {
printD("Serving /mqtt-ca.html over http...");
String html;
if(SPIFFS.begin()) {
if(SPIFFS.exists(FILE_MQTT_CA)) {
deleteHtml("CA file", "/mqtt-ca/delete", "mqtt");
@@ -797,7 +952,6 @@ void AmsWebServer::mqttCaDelete() {
void AmsWebServer::mqttCert() {
printD("Serving /mqtt-cert.html over http...");
String html;
if(SPIFFS.begin()) {
if(SPIFFS.exists(FILE_MQTT_CERT)) {
deleteHtml("Certificate", "/mqtt-cert/delete", "mqtt");
@@ -835,7 +989,6 @@ void AmsWebServer::mqttCertDelete() {
void AmsWebServer::mqttKey() {
printD("Serving /mqtt-key.html over http...");
String html;
if(SPIFFS.begin()) {
if(SPIFFS.exists(FILE_MQTT_KEY)) {
deleteHtml("Private key", "/mqtt-key/delete", "mqtt");

View File

@@ -31,7 +31,7 @@
class AmsWebServer {
public:
AmsWebServer(RemoteDebug* Debug);
AmsWebServer(RemoteDebug* Debug, HwTools* hw);
void setup(AmsConfiguration* config, MQTTClient* mqtt);
void loop();
@@ -40,7 +40,7 @@ public:
private:
RemoteDebug* debugger;
int maxPwr = 0;
HwTools hw;
HwTools* hw;
AmsConfiguration* config;
AmsData data;
MQTTClient* mqtt;
@@ -65,10 +65,13 @@ private:
void gaugemeterJs();
void dataJson();
void handleSetup();
void handleSave();
void configSystemHtml();
void configSystemUpload();
String getSerialSelectOptions(int selected);
void firmwareHtml();
void firmwareUpload();
void restartWaitHtml();
void isAliveCheck();