diff --git a/lib/AmsConfiguration/include/AmsConfiguration.h b/lib/AmsConfiguration/include/AmsConfiguration.h index 1980378f..531118fe 100644 --- a/lib/AmsConfiguration/include/AmsConfiguration.h +++ b/lib/AmsConfiguration/include/AmsConfiguration.h @@ -34,8 +34,8 @@ struct SystemConfig { bool vendorConfigured; bool userConfigured; uint8_t dataCollectionConsent; // 0 = unknown, 1 = accepted, 2 = declined - char country[2]; -}; // 6 + char country[3]; +}; // 7 struct WiFiConfig91 { char ssid[32]; diff --git a/lib/AmsConfiguration/include/hexutils.h b/lib/AmsConfiguration/include/hexutils.h index c5fa278c..28e2c93d 100644 --- a/lib/AmsConfiguration/include/hexutils.h +++ b/lib/AmsConfiguration/include/hexutils.h @@ -7,5 +7,6 @@ String toHex(uint8_t* in); String toHex(uint8_t* in, uint16_t size); void fromHex(uint8_t *out, String in, uint16_t size); +void stripNonAscii(uint8_t* in, uint16_t size); #endif \ No newline at end of file diff --git a/lib/AmsConfiguration/src/AmsConfiguration.cpp b/lib/AmsConfiguration/src/AmsConfiguration.cpp index 9001342f..3cbbf751 100644 --- a/lib/AmsConfiguration/src/AmsConfiguration.cpp +++ b/lib/AmsConfiguration/src/AmsConfiguration.cpp @@ -1,4 +1,5 @@ #include "AmsConfiguration.h" +#include "hexutils.h" bool AmsConfiguration::getSystemConfig(SystemConfig& config) { EEPROM.begin(EEPROM_SIZE); @@ -19,6 +20,7 @@ bool AmsConfiguration::getSystemConfig(SystemConfig& config) { bool AmsConfiguration::setSystemConfig(SystemConfig& config) { EEPROM.begin(EEPROM_SIZE); + stripNonAscii((uint8_t*) config.country, 2); EEPROM.put(CONFIG_SYSTEM_START, config); bool ret = EEPROM.commit(); EEPROM.end(); @@ -59,6 +61,16 @@ bool AmsConfiguration::setWiFiConfig(WiFiConfig& config) { } else { wifiChanged = true; } + + stripNonAscii((uint8_t*) config.ssid, 32); + stripNonAscii((uint8_t*) config.psk, 64); + stripNonAscii((uint8_t*) config.ip, 16); + stripNonAscii((uint8_t*) config.gateway, 16); + stripNonAscii((uint8_t*) config.subnet, 16); + stripNonAscii((uint8_t*) config.dns1, 16); + stripNonAscii((uint8_t*) config.dns2, 16); + stripNonAscii((uint8_t*) config.hostname, 32); + EEPROM.begin(EEPROM_SIZE); EEPROM.put(CONFIG_WIFI_START, config); bool ret = EEPROM.commit(); @@ -127,6 +139,14 @@ bool AmsConfiguration::setMqttConfig(MqttConfig& config) { } else { mqttChanged = true; } + + stripNonAscii((uint8_t*) config.host, 128); + stripNonAscii((uint8_t*) config.clientId, 32); + stripNonAscii((uint8_t*) config.publishTopic, 64); + stripNonAscii((uint8_t*) config.subscribeTopic, 64); + stripNonAscii((uint8_t*) config.username, 128); + stripNonAscii((uint8_t*) config.password, 256); + EEPROM.begin(EEPROM_SIZE); EEPROM.put(CONFIG_MQTT_START, config); bool ret = EEPROM.commit(); @@ -171,6 +191,10 @@ bool AmsConfiguration::getWebConfig(WebConfig& config) { } bool AmsConfiguration::setWebConfig(WebConfig& config) { + + stripNonAscii((uint8_t*) config.username, 64); + stripNonAscii((uint8_t*) config.password, 64); + EEPROM.begin(EEPROM_SIZE); EEPROM.put(CONFIG_WEB_START, config); bool ret = EEPROM.commit(); @@ -221,8 +245,8 @@ void AmsConfiguration::clearMeter(MeterConfig& config) { config.baud = 0; config.parity = 0; config.invert = false; - config.distributionSystem = 0; - config.mainFuse = 0; + config.distributionSystem = 2; + config.mainFuse = 40; config.productionCapacity = 0; memset(config.encryptionKey, 0, 16); memset(config.authenticationKey, 0, 16); @@ -445,6 +469,10 @@ bool AmsConfiguration::setNtpConfig(NtpConfig& config) { } else { ntpChanged = true; } + + stripNonAscii((uint8_t*) config.server, 64); + stripNonAscii((uint8_t*) config.timezone, 32); + EEPROM.begin(EEPROM_SIZE); EEPROM.put(CONFIG_NTP_START, config); bool ret = EEPROM.commit(); @@ -492,6 +520,11 @@ bool AmsConfiguration::setEntsoeConfig(EntsoeConfig& config) { } else { entsoeChanged = true; } + + stripNonAscii((uint8_t*) config.token, 37); + stripNonAscii((uint8_t*) config.area, 17); + stripNonAscii((uint8_t*) config.currency, 4); + EEPROM.begin(EEPROM_SIZE); EEPROM.put(CONFIG_ENTSOE_START, config); bool ret = EEPROM.commit(); diff --git a/lib/AmsConfiguration/src/hexutils.cpp b/lib/AmsConfiguration/src/hexutils.cpp index 230cedc4..54f95412 100644 --- a/lib/AmsConfiguration/src/hexutils.cpp +++ b/lib/AmsConfiguration/src/hexutils.cpp @@ -20,4 +20,17 @@ void fromHex(uint8_t *out, String in, uint16_t size) { for(int i = 0; i < size*2; i += 2) { out[i/2] = strtol(in.substring(i, i+2).c_str(), 0, 16); } +} + +void stripNonAscii(uint8_t* in, uint16_t size) { + for(uint16_t i = 0; i < size; i++) { + if(in[i] == 0) { // Clear the rest with null-terminator + memset(in+i, 0, size-i); + break; + } + if(in[i] < 32 || in[i] > 126) { + memset(in+i, ' ', 1); + } + } + memset(in+size-1, 0, 1); // Make sure the last character is null-terminator } \ No newline at end of file diff --git a/lib/ClassicUi/src/AmsWebServer.cpp b/lib/ClassicUi/src/AmsWebServer.cpp index f7dc3159..cdb778fe 100644 --- a/lib/ClassicUi/src/AmsWebServer.cpp +++ b/lib/ClassicUi/src/AmsWebServer.cpp @@ -1835,7 +1835,7 @@ void AmsWebServer::restartWaitHtml() { performRestart = false; } else if(performUpgrade) { WiFiClient client; - String url = customFirmwareUrl.isEmpty() || !customFirmwareUrl.startsWith(F("http")) ? F("http://ams2mqtt.rewiredinvent.no/hub/firmware/update") : customFirmwareUrl; + String url = customFirmwareUrl.isEmpty() || !customFirmwareUrl.startsWith(F("http")) ? F("http://hub.amsleser.no/hub/firmware/update") : customFirmwareUrl; #if defined(ESP8266) String chipType = F("esp8266"); #elif defined(CONFIG_IDF_TARGET_ESP32S2) diff --git a/lib/EntsoePriceApi/src/EntsoeApi.cpp b/lib/EntsoePriceApi/src/EntsoeApi.cpp index 2d64ae5a..3b6dc474 100644 --- a/lib/EntsoePriceApi/src/EntsoeApi.cpp +++ b/lib/EntsoePriceApi/src/EntsoeApi.cpp @@ -308,7 +308,7 @@ PricesContainer* EntsoeApi::fetchPrices(time_t t) { } else if(hub) { String data; snprintf(buf, BufferSize, "%s/%s/%d/%d/%d?currency=%s", - "http://ams2mqtt.rewiredinvent.no/hub/price", + "http://hub.amsleser.no/hub/price", config->area, tm.Year+1970, tm.Month, diff --git a/lib/HomeAssistantMqttHandler/include/HomeAssistantMqttHandler.h b/lib/HomeAssistantMqttHandler/include/HomeAssistantMqttHandler.h index 05675eee..878efa4a 100644 --- a/lib/HomeAssistantMqttHandler/include/HomeAssistantMqttHandler.h +++ b/lib/HomeAssistantMqttHandler/include/HomeAssistantMqttHandler.h @@ -31,6 +31,5 @@ private: String clientId; String topic; HwTools* hw; - uint8_t sequence = 0, listType = 0; }; #endif diff --git a/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp b/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp index 2629b65f..02ec96b8 100644 --- a/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp +++ b/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp @@ -16,7 +16,6 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En if(topic.isEmpty() || !mqtt->connected()) return false; - listType = data->getListType(); // for discovery stuff in publishSystem() if(data->getListType() >= 3) { // publish energy counts snprintf_P(json, BufferSize, HA2_JSON, data->getActiveImportCounter(), @@ -192,6 +191,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { } char ts1hr[24]; + memset(ts1hr, 0, 24); if(min1hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min1hrIdx); //Serial.printf("1hr: %d %lu\n", min1hrIdx, ts); @@ -200,6 +200,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } char ts3hr[24]; + memset(ts3hr, 0, 24); if(min3hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min3hrIdx); //Serial.printf("3hr: %d %lu\n", min3hrIdx, ts); @@ -208,6 +209,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } char ts6hr[24]; + memset(ts6hr, 0, 24); if(min6hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min6hrIdx); //Serial.printf("6hr: %d %lu\n", min6hrIdx, ts); @@ -240,23 +242,19 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) { } bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) { - if(topic.isEmpty() || !mqtt->connected()){ - sequence = 0; + if(topic.isEmpty() || !mqtt->connected()) return false; - } - if(sequence % 3 == 0){ - snprintf_P(json, BufferSize, JSONSYS_JSON, - WiFi.macAddress().c_str(), - clientId.c_str(), - (uint32_t) (millis64()/1000), - hw->getVcc(), - hw->getWifiRssi(), - hw->getTemperature(), - VERSION - ); - mqtt->publish(topic + "/state", json); - } + snprintf_P(json, BufferSize, JSONSYS_JSON, + WiFi.macAddress().c_str(), + clientId.c_str(), + (uint32_t) (millis64()/1000), + hw->getVcc(), + hw->getWifiRssi(), + hw->getTemperature(), + VERSION + ); + mqtt->publish(topic + "/state", json); if(!autodiscoverInit) { #if defined(ESP8266) @@ -315,6 +313,5 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, Energ autodiscoverInit = true; } - if(listType>0) sequence++; return true; } diff --git a/lib/JsonMqttHandler/include/JsonMqttHandler.h b/lib/JsonMqttHandler/include/JsonMqttHandler.h index db3e12bc..63032e36 100644 --- a/lib/JsonMqttHandler/include/JsonMqttHandler.h +++ b/lib/JsonMqttHandler/include/JsonMqttHandler.h @@ -19,6 +19,5 @@ private: String clientId; String topic; HwTools* hw; - bool init = false; }; #endif diff --git a/lib/JsonMqttHandler/src/JsonMqttHandler.cpp b/lib/JsonMqttHandler/src/JsonMqttHandler.cpp index 273a331e..8aea11cf 100644 --- a/lib/JsonMqttHandler/src/JsonMqttHandler.cpp +++ b/lib/JsonMqttHandler/src/JsonMqttHandler.cpp @@ -231,6 +231,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) { } char ts1hr[24]; + memset(ts1hr, 0, 24); if(min1hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min1hrIdx); //Serial.printf("1hr: %d %lu\n", min1hrIdx, ts); @@ -239,6 +240,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) { sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } char ts3hr[24]; + memset(ts3hr, 0, 24); if(min3hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min3hrIdx); //Serial.printf("3hr: %d %lu\n", min3hrIdx, ts); @@ -247,6 +249,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) { sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour); } char ts6hr[24]; + memset(ts6hr, 0, 24); if(min6hrIdx > -1) { time_t ts = now + (SECS_PER_HOUR * min6hrIdx); //Serial.printf("6hr: %d %lu\n", min6hrIdx, ts); @@ -279,7 +282,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) { } bool JsonMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounting* ea) { - if(init || topic.isEmpty() || !mqtt->connected()) + if(topic.isEmpty() || !mqtt->connected()) return false; snprintf_P(json, BufferSize, JSONSYS_JSON, @@ -291,6 +294,5 @@ bool JsonMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, EnergyAccounti hw->getTemperature(), VERSION ); - init = mqtt->publish(topic, json); - return init; + return mqtt->publish(topic, json); } diff --git a/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte b/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte index 367aca08..29bc503d 100644 --- a/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte +++ b/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte @@ -260,9 +260,8 @@
Voltage
diff --git a/lib/SvelteUi/app/src/lib/Helpers.js b/lib/SvelteUi/app/src/lib/Helpers.js index f1a21569..e9580d05 100644 --- a/lib/SvelteUi/app/src/lib/Helpers.js +++ b/lib/SvelteUi/app/src/lib/Helpers.js @@ -1,15 +1,10 @@ export let monthnames = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; -export function voltcol(pct) { - if(pct > 85) return '#d90000'; - else if(pct > 75) return'#e32100'; - else if(pct > 70) return '#ffb800'; - else if(pct > 65) return '#dcd800'; - else if(pct > 35) return '#32d900'; - else if(pct > 25) return '#dcd800'; - else if(pct > 20) return '#ffb800'; - else if(pct > 15) return'#e32100'; - else return '#d90000'; +export function voltcol(volt) { + if(volt > 218 && volt < 242) return '#32d900'; + if(volt > 212 && volt < 248) return '#b1d900'; + if(volt > 208 && volt < 252) return '#ffb800'; + return '#d90000'; }; export function ampcol(pct) { diff --git a/lib/SvelteUi/app/src/lib/VoltPlot.svelte b/lib/SvelteUi/app/src/lib/VoltPlot.svelte index 14ce6a01..265f2829 100644 --- a/lib/SvelteUi/app/src/lib/VoltPlot.svelte +++ b/lib/SvelteUi/app/src/lib/VoltPlot.svelte @@ -19,7 +19,7 @@ points.push({ label: u1 ? u1.toFixed(0) + 'V' : '-', value: u1 ? u1 : 0, - color: voltcol(u1 ? (u1-min)/(max-min)*100 : 0) + color: voltcol(u1 ? u1 : 0) }); } if(u2 > 0) { @@ -27,7 +27,7 @@ points.push({ label: u2 ? u2.toFixed(0) + 'V' : '-', value: u2 ? u2 : 0, - color: voltcol(u2 ? (u2-min)/(max-min)*100 : 0) + color: voltcol(u2 ? u2 : 0) }); } if(u3 > 0) { @@ -35,7 +35,7 @@ points.push({ label: u3 ? u3.toFixed(0) + 'V' : '-', value: u3 ? u3 : 0, - color: voltcol(u3 ? (u3-min)/(max-min)*100 : 0) + color: voltcol(u3 ? u3 : 0) }); } config = { diff --git a/lib/SvelteUi/json/firmware.html b/lib/SvelteUi/json/firmware.html index 2e3e6555..7594c521 100644 --- a/lib/SvelteUi/json/firmware.html +++ b/lib/SvelteUi/json/firmware.html @@ -1,11 +1,29 @@ -
- File: - -
- or

-
- URL: - -
+ +
+ Firmware install +
+ File: + +
+ or

+
+ URL: + +
+
+
+ Configuration upload +
+ File: + +
+
+
+ Factory reset +
+ +
+
+ \ No newline at end of file diff --git a/lib/SvelteUi/src/AmsWebServer.cpp b/lib/SvelteUi/src/AmsWebServer.cpp index 2b211d4b..42c6eea3 100644 --- a/lib/SvelteUi/src/AmsWebServer.cpp +++ b/lib/SvelteUi/src/AmsWebServer.cpp @@ -240,7 +240,7 @@ void AmsWebServer::sysinfoJson() { UiConfig ui; config->getUiConfig(ui); - snprintf_P(buf, BufferSize, SYSINFO_JSON, + int size = snprintf_P(buf, BufferSize, SYSINFO_JSON, VERSION, #if defined(CONFIG_IDF_TARGET_ESP32S2) "esp32s2", @@ -288,6 +288,8 @@ void AmsWebServer::sysinfoJson() { webConfig.security ); + stripNonAscii((uint8_t*) buf, size+1); + server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); @@ -981,7 +983,7 @@ void AmsWebServer::handleSave() { switch(boardType) { case 2: // spenceme config->clearGpio(*gpioConfig); - gpioConfig->vccBootLimit = 33; + gpioConfig->vccBootLimit = 32; gpioConfig->hanPin = 3; gpioConfig->apPin = 0; gpioConfig->ledPin = 2; @@ -1435,7 +1437,7 @@ void AmsWebServer::upgrade() { customFirmwareUrl = server.arg(F("url")); } - String url = customFirmwareUrl.isEmpty() || !customFirmwareUrl.startsWith(F("http")) ? F("http://ams2mqtt.rewiredinvent.no/hub/firmware/update") : customFirmwareUrl; + String url = customFirmwareUrl.isEmpty() || !customFirmwareUrl.startsWith(F("http")) ? F("http://hub.amsleser.no/hub/firmware/update") : customFirmwareUrl; if(server.hasArg(F("version"))) { url += "/" + server.arg(F("version")); diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index c5f13d15..782d1fc1 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -216,7 +216,7 @@ void setup() { debugI("Voltage: %.2fV", vcc); } - float vccBootLimit = gpioConfig.vccBootLimit == 0 ? 0 : gpioConfig.vccBootLimit / 10.0; + float vccBootLimit = gpioConfig.vccBootLimit == 0 ? 0 : min(3.29, gpioConfig.vccBootLimit / 10.0); // Make sure it is never above 3.3v if(vccBootLimit > 2.5 && vccBootLimit < 3.3 && (gpioConfig.apPin == 0xFF || digitalRead(gpioConfig.apPin) == HIGH)) { // Skip if user is holding AP button while booting (HIGH = button is released) if (vcc < vccBootLimit) { if(Debug.isActive(RemoteDebug::INFO)) { @@ -585,7 +585,7 @@ void loop() { } debugD("Used %ld ms to update temperature", millis()-start); } - if(now - lastSysupdate > 10000) { + if(now - lastSysupdate > 60000) { if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) { mqttHandler->publishSystem(&hw, eapi, &ea); } @@ -1447,7 +1447,7 @@ void MQTT_connect() { if (strlen(mqttConfig.subscribeTopic) > 0) { mqtt->onMessage(mqttMessageReceived); mqtt->subscribe(String(mqttConfig.subscribeTopic) + "/#"); - debugI(" Subscribing to [%s]\r\n", mqttConfig.subscribeTopic); + debugI(" Subscribing to [%s]\n", mqttConfig.subscribeTopic); } } else { if (Debug.isActive(RemoteDebug::ERROR)) {