From 4972b980ba5c403c1382e514d641c11a1c518a01 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Fri, 6 Jan 2023 14:34:07 +0100 Subject: [PATCH] Changes for v2.2 --- .../include/AmsConfiguration.h | 20 +- lib/AmsConfiguration/src/AmsConfiguration.cpp | 45 +++- lib/AmsDataStorage/include/AmsDataStorage.h | 33 ++- lib/AmsDataStorage/src/AmsDataStorage.cpp | 205 ++++++++++++++++-- .../include/HomeAssistantStatic.h | 16 +- .../src/HomeAssistantMqttHandler.cpp | 3 + lib/RawMqttHandler/src/RawMqttHandler.cpp | 2 + lib/SvelteUi/app/src/app.postcss | 3 +- lib/SvelteUi/app/src/lib/BarChart.svelte | 9 +- .../app/src/lib/ConfigurationPanel.svelte | 38 +++- .../app/src/lib/ConsentComponent.svelte | 2 +- .../app/src/lib/FileUploadComponent.svelte | 2 +- lib/SvelteUi/app/src/lib/SetupPanel.svelte | 2 +- lib/SvelteUi/app/src/lib/StatusPage.svelte | 6 +- lib/SvelteUi/app/src/lib/VendorPanel.svelte | 2 +- lib/SvelteUi/app/vite.config.js | 14 +- lib/SvelteUi/json/conf_domoticz.json | 7 + lib/SvelteUi/json/conf_gpio.json | 2 +- lib/SvelteUi/json/firmware.html | 2 +- lib/SvelteUi/src/AmsWebServer.cpp | 29 ++- src/AmsToMqttBridge.ino | 81 +++++-- 21 files changed, 426 insertions(+), 97 deletions(-) create mode 100644 lib/SvelteUi/json/conf_domoticz.json diff --git a/lib/AmsConfiguration/include/AmsConfiguration.h b/lib/AmsConfiguration/include/AmsConfiguration.h index cbbcb8f2..c66885ac 100644 --- a/lib/AmsConfiguration/include/AmsConfiguration.h +++ b/lib/AmsConfiguration/include/AmsConfiguration.h @@ -4,7 +4,7 @@ #include "Arduino.h" #define EEPROM_SIZE 1024*3 -#define EEPROM_CHECK_SUM 100 // Used to check if config is stored. Change if structure changes +#define EEPROM_CHECK_SUM 101 // Used to check if config is stored. Change if structure changes #define EEPROM_CLEARED_INDICATOR 0xFC #define EEPROM_CONFIG_ADDRESS 0 #define EEPROM_TEMP_CONFIG_ADDRESS 2048 @@ -95,6 +95,23 @@ struct WebConfig { }; // 129 struct MeterConfig { + uint32_t baud; + uint8_t parity; + bool invert; + uint8_t distributionSystem; + uint16_t mainFuse; + uint16_t productionCapacity; + uint8_t encryptionKey[16]; + uint8_t authenticationKey[16]; + uint32_t wattageMultiplier; + uint32_t voltageMultiplier; + uint32_t amperageMultiplier; + uint32_t accumulatedMultiplier; + uint8_t source; + uint8_t parser; +}; // 52 + +struct MeterConfig100 { uint32_t baud; uint8_t parity; bool invert; @@ -302,6 +319,7 @@ private: bool relocateConfig94(); // 2.1.0 bool relocateConfig95(); // 2.1.4 bool relocateConfig96(); // 2.1.14 + bool relocateConfig100(); // 2.2-dev void saveToFs(); bool loadFromFs(uint8_t version); diff --git a/lib/AmsConfiguration/src/AmsConfiguration.cpp b/lib/AmsConfiguration/src/AmsConfiguration.cpp index 50b07ea1..f88f7ea1 100644 --- a/lib/AmsConfiguration/src/AmsConfiguration.cpp +++ b/lib/AmsConfiguration/src/AmsConfiguration.cpp @@ -230,6 +230,8 @@ void AmsConfiguration::clearMeter(MeterConfig& config) { config.voltageMultiplier = 0; config.amperageMultiplier = 0; config.accumulatedMultiplier = 0; + config.source = 1; // Serial + config.parser = 0; // Auto } bool AmsConfiguration::isMeterChanged() { @@ -694,6 +696,14 @@ bool AmsConfiguration::hasConfig() { configVersion = 0; return false; } + case 100: + configVersion = -1; // Prevent loop + if(relocateConfig100()) { + configVersion = 101; + } else { + configVersion = 0; + return false; + } case EEPROM_CHECK_SUM: return true; default: @@ -848,9 +858,13 @@ bool AmsConfiguration::relocateConfig96() { SystemConfig sys; EEPROM.get(CONFIG_SYSTEM_START, sys); - #if defined(ESP8266) MeterConfig meter; EEPROM.get(CONFIG_METER_START, meter); + meter.source = 1; // Serial + meter.parser = 0; // Auto + EEPROM.put(CONFIG_METER_START, meter); + + #if defined(ESP8266) GpioConfig gpio; EEPROM.get(CONFIG_GPIO_START, gpio); @@ -912,6 +926,35 @@ bool AmsConfiguration::relocateConfig96() { return ret; } +bool AmsConfiguration::relocateConfig100() { + EEPROM.begin(EEPROM_SIZE); + + MeterConfig100 meter100; + EEPROM.get(CONFIG_METER_START, meter100); + MeterConfig meter; + meter.baud = meter100.baud; + meter.parity = meter100.parity; + meter.invert = meter100.invert; + meter.distributionSystem = meter100.distributionSystem; + meter.mainFuse = meter100.mainFuse; + meter.productionCapacity = meter100.productionCapacity; + memcpy(meter.encryptionKey, meter100.encryptionKey, 16); + memcpy(meter.authenticationKey, meter100.authenticationKey, 16); + meter.wattageMultiplier = meter100.wattageMultiplier; + meter.voltageMultiplier = meter100.voltageMultiplier; + meter.amperageMultiplier = meter100.amperageMultiplier; + meter.accumulatedMultiplier = meter100.accumulatedMultiplier; + meter.source = meter100.source; + meter.parser = meter100.parser; + + EEPROM.put(CONFIG_METER_START, meter); + + EEPROM.put(EEPROM_CONFIG_ADDRESS, 101); + bool ret = EEPROM.commit(); + EEPROM.end(); + return ret; +} + bool AmsConfiguration::save() { EEPROM.begin(EEPROM_SIZE); EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM); diff --git a/lib/AmsDataStorage/include/AmsDataStorage.h b/lib/AmsDataStorage/include/AmsDataStorage.h index f542bc99..46e1bdb9 100644 --- a/lib/AmsDataStorage/include/AmsDataStorage.h +++ b/lib/AmsDataStorage/include/AmsDataStorage.h @@ -12,7 +12,8 @@ struct DayDataPoints { uint32_t activeImport; uint32_t activeExport; uint16_t hExport[24]; -}; // 112 bytes + uint8_t accuracy; +}; // 113 bytes struct MonthDataPoints { uint8_t version; @@ -21,17 +22,18 @@ struct MonthDataPoints { uint32_t activeImport; uint32_t activeExport; uint16_t dExport[31]; -}; // 141 bytes + uint8_t accuracy; +}; // 142 bytes class AmsDataStorage { public: AmsDataStorage(RemoteDebug*); void setTimezone(Timezone*); bool update(AmsData*); - int32_t getHourImport(uint8_t); - int32_t getHourExport(uint8_t); - int32_t getDayImport(uint8_t); - int32_t getDayExport(uint8_t); + uint32_t getHourImport(uint8_t); + uint32_t getHourExport(uint8_t); + uint32_t getDayImport(uint8_t); + uint32_t getDayExport(uint8_t); bool load(); bool save(); @@ -40,6 +42,11 @@ public: MonthDataPoints getMonthData(); bool setMonthData(MonthDataPoints&); + uint8_t getDayAccuracy(); + void setDayAccuracy(uint8_t); + uint8_t getMonthAccuracy(); + void setMonthAccuracy(uint8_t); + bool isHappy(); bool isDayHappy(); bool isMonthHappy(); @@ -50,19 +57,21 @@ private: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10 }; MonthDataPoints month = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10 }; RemoteDebug* debugger; - void setHourImport(uint8_t, int32_t); - void setHourExport(uint8_t, int32_t); - void setDayImport(uint8_t, int32_t); - void setDayExport(uint8_t, int32_t); + void setHourImport(uint8_t, uint32_t); + void setHourExport(uint8_t, uint32_t); + void setDayImport(uint8_t, uint32_t); + void setDayExport(uint8_t, uint32_t); }; #endif diff --git a/lib/AmsDataStorage/src/AmsDataStorage.cpp b/lib/AmsDataStorage/src/AmsDataStorage.cpp index 5031f2e1..66c012e4 100644 --- a/lib/AmsDataStorage/src/AmsDataStorage.cpp +++ b/lib/AmsDataStorage/src/AmsDataStorage.cpp @@ -5,8 +5,10 @@ #include "version.h" AmsDataStorage::AmsDataStorage(RemoteDebug* debugger) { - day.version = 4; - month.version = 5; + day.version = 5; + day.accuracy = 1; + month.version = 6; + month.accuracy = 1; this->debugger = debugger; } @@ -237,44 +239,160 @@ bool AmsDataStorage::update(AmsData* data) { return ret; } -void AmsDataStorage::setHourImport(uint8_t hour, int32_t val) { +void AmsDataStorage::setHourImport(uint8_t hour, uint32_t val) { if(hour < 0 || hour > 24) return; - day.hImport[hour] = val / 10; + + uint8_t accuracy = day.accuracy; + uint32_t update = val / pow(10, accuracy); + while(update > UINT16_MAX) { + accuracy++; + update = val / pow(10, accuracy); + } + + if(accuracy != day.accuracy) { + setDayAccuracy(accuracy); + } + + day.hImport[hour] = update; + + uint32_t max = 0; + for(uint8_t i = 0; i < 24; i++) { + if(day.hImport[i] > max) + max = day.hImport[i]; + if(day.hExport[i] > max) + max = day.hExport[i]; + } + + while(max < UINT16_MAX/10 && accuracy > 0) { + accuracy--; + max = max*10; + } + + if(accuracy != day.accuracy) { + setDayAccuracy(accuracy); + } } -int32_t AmsDataStorage::getHourImport(uint8_t hour) { +uint32_t AmsDataStorage::getHourImport(uint8_t hour) { if(hour < 0 || hour > 24) return 0; - return day.hImport[hour] * 10; + return day.hImport[hour] * pow(10, day.accuracy); } -void AmsDataStorage::setHourExport(uint8_t hour, int32_t val) { +void AmsDataStorage::setHourExport(uint8_t hour, uint32_t val) { if(hour < 0 || hour > 24) return; - day.hExport[hour] = val / 10; + + uint8_t accuracy = day.accuracy; + uint32_t update = val / pow(10, accuracy); + while(update > UINT16_MAX) { + accuracy++; + update = val / pow(10, accuracy); + } + + if(accuracy != day.accuracy) { + setDayAccuracy(accuracy); + } + + day.hExport[hour] = update; + + uint32_t max = 0; + for(uint8_t i = 0; i < 24; i++) { + if(day.hImport[i] > max) + max = day.hImport[i]; + if(day.hExport[i] > max) + max = day.hExport[i]; + } + + while(max < UINT16_MAX/10 && accuracy > 0) { + accuracy--; + max = max*10; + } + + if(accuracy != day.accuracy) { + setDayAccuracy(accuracy); + } } -int32_t AmsDataStorage::getHourExport(uint8_t hour) { +uint32_t AmsDataStorage::getHourExport(uint8_t hour) { if(hour < 0 || hour > 24) return 0; - return day.hExport[hour] * 10; + return day.hExport[hour] * pow(10, day.accuracy); } -void AmsDataStorage::setDayImport(uint8_t day, int32_t val) { +void AmsDataStorage::setDayImport(uint8_t day, uint32_t val) { if(day < 1 || day > 31) return; - month.dImport[day-1] = val / 10; + + uint8_t accuracy = month.accuracy; + uint32_t update = val / pow(10, accuracy); + while(update > UINT16_MAX) { + accuracy++; + update = val / pow(10, accuracy); + } + + if(accuracy != month.accuracy) { + setMonthAccuracy(accuracy); + } + + month.dImport[day-1] = update; + + uint32_t max = 0; + for(uint8_t i = 0; i < 31; i++) { + if(month.dImport[i] > max) + max = month.dImport[i]; + if(month.dExport[i] > max) + max = month.dExport[i]; + } + + while(max < UINT16_MAX/10 && accuracy > 0) { + accuracy--; + max = max*10; + } + + if(accuracy != month.accuracy) { + setMonthAccuracy(accuracy); + } } -int32_t AmsDataStorage::getDayImport(uint8_t day) { +uint32_t AmsDataStorage::getDayImport(uint8_t day) { if(day < 1 || day > 31) return 0; - return (month.dImport[day-1] * 10); + return (month.dImport[day-1] * pow(10, month.accuracy)); } -void AmsDataStorage::setDayExport(uint8_t day, int32_t val) { +void AmsDataStorage::setDayExport(uint8_t day, uint32_t val) { if(day < 1 || day > 31) return; - month.dExport[day-1] = val / 10; + + uint8_t accuracy = month.accuracy; + uint32_t update = val / pow(10, accuracy); + while(update > UINT16_MAX) { + accuracy++; + update = val / pow(10, accuracy); + } + + if(accuracy != month.accuracy) { + setMonthAccuracy(accuracy); + } + + month.dExport[day-1] = update; + + uint32_t max = 0; + for(uint8_t i = 0; i < 31; i++) { + if(month.dImport[i] > max) + max = month.dImport[i]; + if(month.dExport[i] > max) + max = month.dExport[i]; + } + + while(max < UINT16_MAX/10 && accuracy > 0) { + accuracy--; + max = max*10; + } + + if(accuracy != month.accuracy) { + setMonthAccuracy(accuracy); + } } -int32_t AmsDataStorage::getDayExport(uint8_t day) { +uint32_t AmsDataStorage::getDayExport(uint8_t day) { if(day < 1 || day > 31) return 0; - return (month.dExport[day-1] * 10); + return (month.dExport[day-1] * pow(10, month.accuracy)); } bool AmsDataStorage::load() { @@ -348,31 +466,74 @@ MonthDataPoints AmsDataStorage::getMonthData() { } bool AmsDataStorage::setDayData(DayDataPoints& day) { - if(day.version == 4) { + if(day.version == 5) { this->day = day; return true; + } else if(day.version == 4) { + this->day = day; + this->day.accuracy = 1; + this->day.version = 5; + return true; } else if(day.version == 3) { this->day = day; for(uint8_t i = 0; i < 24; i++) this->day.hExport[i] = 0; - this->day.version = 4; + this->day.accuracy = 1; + this->day.version = 5; return true; } return false; } bool AmsDataStorage::setMonthData(MonthDataPoints& month) { - if(month.version == 5) { + if(month.version == 6) { this->month = month; return true; + } else if(month.version == 5) { + this->month = month; + this->month.accuracy = 1; + this->month.version = 6; + return true; } else if(month.version == 4) { this->month = month; for(uint8_t i = 0; i < 31; i++) this->month.dExport[i] = 0; - this->month.version = 5; + this->month.accuracy = 1; + this->month.version = 6; return true; } return false; } +uint8_t AmsDataStorage::getDayAccuracy() { + return day.accuracy; +} + +void AmsDataStorage::setDayAccuracy(uint8_t accuracy) { + if(day.accuracy != accuracy) { + uint16_t multiplier = pow(10, day.accuracy)/pow(10, accuracy); + for(uint8_t i = 0; i < 24; i++) { + day.hImport[i] = day.hImport[i] * multiplier; + day.hExport[i] = day.hExport[i] * multiplier; + } + day.accuracy = accuracy; + } +} + +uint8_t AmsDataStorage::getMonthAccuracy() { + return month.accuracy; +} + +void AmsDataStorage::setMonthAccuracy(uint8_t accuracy) { + if(month.accuracy != accuracy) { + uint16_t multiplier = pow(10, month.accuracy)/pow(10, accuracy); + for(uint8_t i = 0; i < 31; i++) { + month.dImport[i] = month.dImport[i] * multiplier; + month.dExport[i] = month.dExport[i] * multiplier; + } + month.accuracy = accuracy; + } + month.accuracy = accuracy; +} + bool AmsDataStorage::isHappy() { return isDayHappy() && isMonthHappy(); } diff --git a/lib/HomeAssistantMqttHandler/include/HomeAssistantStatic.h b/lib/HomeAssistantMqttHandler/include/HomeAssistantStatic.h index 8f781d6f..baf495d5 100644 --- a/lib/HomeAssistantMqttHandler/include/HomeAssistantStatic.h +++ b/lib/HomeAssistantMqttHandler/include/HomeAssistantStatic.h @@ -22,12 +22,12 @@ HomeAssistantSensor HA_SENSORS[HA_SENSOR_COUNT] PROGMEM = { {"L1 active import", "/power", "P1", "W", "power", "\"measurement\""}, {"L2 active import", "/power", "P2", "W", "power", "\"measurement\""}, {"L3 active import", "/power", "P3", "W", "power", "\"measurement\""}, - {"Reactive import", "/power", "Q", "VAr", "reactive_power", "\"measurement\""}, + {"Reactive import", "/power", "Q", "var", "reactive_power", "\"measurement\""}, {"Active export", "/power", "PO", "W", "power", "\"measurement\""}, {"L1 active export", "/power", "PO1", "W", "power", "\"measurement\""}, {"L2 active export", "/power", "PO2", "W", "power", "\"measurement\""}, {"L3 active export", "/power", "PO3", "W", "power", "\"measurement\""}, - {"Reactive export", "/power", "QO", "VAr", "reactive_power", "\"measurement\""}, + {"Reactive export", "/power", "QO", "var", "reactive_power", "\"measurement\""}, {"L1 current", "/power", "I1", "A", "current", "\"measurement\""}, {"L2 current", "/power", "I2", "A", "current", "\"measurement\""}, {"L3 current", "/power", "I3", "A", "current", "\"measurement\""}, @@ -36,12 +36,12 @@ HomeAssistantSensor HA_SENSORS[HA_SENSOR_COUNT] PROGMEM = { {"L3 voltage", "/power", "U3", "V", "voltage", "\"measurement\""}, {"Accumulated active import", "/energy", "tPI", "kWh", "energy", "\"total_increasing\""}, {"Accumulated active export", "/energy", "tPO", "kWh", "energy", "\"total_increasing\""}, - {"Accumulated reactive import","/energy", "tQI", "kVArh","energy", "\"total_increasing\""}, - {"Accumulated reactive export","/energy", "tQO", "kVArh","energy", "\"total_increasing\""}, - {"Power factor", "/power", "PF", "", "power_factor", "\"measurement\""}, - {"L1 power factor", "/power", "PF1", "", "power_factor", "\"measurement\""}, - {"L2 power factor", "/power", "PF2", "", "power_factor", "\"measurement\""}, - {"L3 power factor", "/power", "PF3", "", "power_factor", "\"measurement\""}, + {"Accumulated reactive import","/energy", "tQI", "kvarh","energy", "\"total_increasing\""}, + {"Accumulated reactive export","/energy", "tQO", "kvarh","energy", "\"total_increasing\""}, + {"Power factor", "/power", "PF", "%", "power_factor", "\"measurement\""}, + {"L1 power factor", "/power", "PF1", "%", "power_factor", "\"measurement\""}, + {"L2 power factor", "/power", "PF2", "%", "power_factor", "\"measurement\""}, + {"L3 power factor", "/power", "PF3", "%", "power_factor", "\"measurement\""}, {"Price current hour", "/prices", "prices['0']", "", "monetary", ""}, {"Price next hour", "/prices", "prices['1']", "", "monetary", ""}, {"Price in two hour", "/prices", "prices['2']", "", "monetary", ""}, diff --git a/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp b/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp index 71253a6c..17066021 100644 --- a/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp +++ b/lib/HomeAssistantMqttHandler/src/HomeAssistantMqttHandler.cpp @@ -286,6 +286,9 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, Energ if(peaks >= peakCount) continue; peaks++; } + if(strncmp(sensor.path, "temp", 4) == 0) { + if(hw->getTemperature() < 0) continue; + } snprintf_P(json, BufferSize, HADISCOVER_JSON, sensor.name, topic.c_str(), sensor.topic, diff --git a/lib/RawMqttHandler/src/RawMqttHandler.cpp b/lib/RawMqttHandler/src/RawMqttHandler.cpp index 1767e3d9..ee8ae40c 100644 --- a/lib/RawMqttHandler/src/RawMqttHandler.cpp +++ b/lib/RawMqttHandler/src/RawMqttHandler.cpp @@ -92,6 +92,7 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState, EnergyAccountin } mqtt->publish(topic + "/realtime/import/hour", String(ea->getUseThisHour(), 3)); mqtt->publish(topic + "/realtime/import/day", String(ea->getUseToday(), 2)); + mqtt->publish(topic + "/realtime/import/month", String(ea->getUseThisMonth(), 1)); uint8_t peakCount = ea->getConfig()->hours; if(peakCount > 5) peakCount = 5; for(uint8_t i = 1; i <= peakCount; i++) { @@ -101,6 +102,7 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState, EnergyAccountin mqtt->publish(topic + "/realtime/import/monthmax", String(ea->getMonthMax(), 3), true, 0); mqtt->publish(topic + "/realtime/export/hour", String(ea->getProducedThisHour(), 3)); mqtt->publish(topic + "/realtime/export/day", String(ea->getProducedToday(), 2)); + mqtt->publish(topic + "/realtime/export/month", String(ea->getProducedThisMonth(), 1)); return true; } diff --git a/lib/SvelteUi/app/src/app.postcss b/lib/SvelteUi/app/src/app.postcss index a3e3dcf9..dace2220 100644 --- a/lib/SvelteUi/app/src/app.postcss +++ b/lib/SvelteUi/app/src/app.postcss @@ -63,7 +63,7 @@ } .pl-ov { position: absolute; - top: 28%; + top: 27%; left: 25%; width: 50%; text-align: center; @@ -76,6 +76,7 @@ color: grey; } .pl-sub { + padding-top: 10px; font-size: 1.0rem; } .pl-snt { diff --git a/lib/SvelteUi/app/src/lib/BarChart.svelte b/lib/SvelteUi/app/src/lib/BarChart.svelte index 8713a153..b6532b5a 100644 --- a/lib/SvelteUi/app/src/lib/BarChart.svelte +++ b/lib/SvelteUi/app/src/lib/BarChart.svelte @@ -19,8 +19,13 @@ return (i*barWidth)+config.padding.left; }; yScale = function(i) { - if(i > config.y.max) return heightAvailable; - let ret = heightAvailable-config.padding.bottom-((i-config.y.min)*yPerUnit); + let ret = 0; + if(i > config.y.max) + ret = config.padding.bottom; + else if(i < config.y.min) + ret = heightAvailable-config.padding.bottom; + else + ret = heightAvailable-config.padding.bottom-((i-config.y.min)*yPerUnit); return ret > heightAvailable || ret < 0.0 ? 0.0 : ret; }; }; diff --git a/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte b/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte index 01a83724..a64f2afb 100644 --- a/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte +++ b/lib/SvelteUi/app/src/lib/ConfigurationPanel.svelte @@ -31,6 +31,13 @@ h: '', p: 1883, u: '', a: '', b: '', s: { e: false, c: false, r: true, k: false } }, + o: { + e: '', + c: '', + u1: '', + u2: '', + u3: '' + }, t: { t: [0,0,0,0,0,0,0,0,0,0], h: 1 }, @@ -120,7 +127,7 @@ } -
+
General @@ -257,14 +264,14 @@
Main fuse
Production
@@ -457,6 +464,31 @@
+ {#if configuration.q.m == 3} +
+ Domoticz + + +
+
+ Electricity IDX
+ +
+
+ Current IDX
+ +
+
+
+ Voltage IDX: L1, L2 & L3 +
+ + + +
+
+
+ {/if} {#if configuration.p.r.startsWith("10YNO") || configuration.p.r == '10Y1001A1001A48H'}
Tariff thresholds diff --git a/lib/SvelteUi/app/src/lib/ConsentComponent.svelte b/lib/SvelteUi/app/src/lib/ConsentComponent.svelte index 8bfa9007..3e8568d3 100644 --- a/lib/SvelteUi/app/src/lib/ConsentComponent.svelte +++ b/lib/SvelteUi/app/src/lib/ConsentComponent.svelte @@ -34,7 +34,7 @@
- +
Various permissions we need to do stuff:
diff --git a/lib/SvelteUi/app/src/lib/FileUploadComponent.svelte b/lib/SvelteUi/app/src/lib/FileUploadComponent.svelte index eee6c877..a47fbf24 100644 --- a/lib/SvelteUi/app/src/lib/FileUploadComponent.svelte +++ b/lib/SvelteUi/app/src/lib/FileUploadComponent.svelte @@ -11,7 +11,7 @@
Upload {title}

Select a suitable file and click upload

- uploading=true}> + uploading=true} autocomplete="off">
diff --git a/lib/SvelteUi/app/src/lib/SetupPanel.svelte b/lib/SvelteUi/app/src/lib/SetupPanel.svelte index 16984e66..250c7706 100644 --- a/lib/SvelteUi/app/src/lib/SetupPanel.svelte +++ b/lib/SvelteUi/app/src/lib/SetupPanel.svelte @@ -69,7 +69,7 @@
- + Setup
diff --git a/lib/SvelteUi/app/src/lib/StatusPage.svelte b/lib/SvelteUi/app/src/lib/StatusPage.svelte index 6091a676..02ea016d 100644 --- a/lib/SvelteUi/app/src/lib/StatusPage.svelte +++ b/lib/SvelteUi/app/src/lib/StatusPage.svelte @@ -135,7 +135,7 @@ {/if} {#if sysinfo.security == 0 || data.a}
- firmwareUploading=true}> + firmwareUploading=true} autocomplete="off"> {#if firmwareFiles.length == 0} @@ -150,7 +150,7 @@ {#if sysinfo.security == 0 || data.a}
Configuration - +
@@ -167,7 +167,7 @@ {/if} -
configUploading=true}> + configUploading=true} autocomplete="off"> {#if configFiles.length == 0} diff --git a/lib/SvelteUi/app/src/lib/VendorPanel.svelte b/lib/SvelteUi/app/src/lib/VendorPanel.svelte index 8740f27c..032927a5 100644 --- a/lib/SvelteUi/app/src/lib/VendorPanel.svelte +++ b/lib/SvelteUi/app/src/lib/VendorPanel.svelte @@ -35,7 +35,7 @@
- + Initial configuration
diff --git a/lib/SvelteUi/app/vite.config.js b/lib/SvelteUi/app/vite.config.js index 9bcb4a69..295482b8 100644 --- a/lib/SvelteUi/app/vite.config.js +++ b/lib/SvelteUi/app/vite.config.js @@ -17,14 +17,14 @@ export default defineConfig({ plugins: [svelte()], server: { proxy: { - "/data.json": "http://192.168.233.229", - "/energyprice.json": "http://192.168.233.229", - "/dayplot.json": "http://192.168.233.229", - "/monthplot.json": "http://192.168.233.229", - "/temperature.json": "http://192.168.233.229", - "/sysinfo.json": "http://192.168.233.229", + "/data.json": "https://ams2mqtt.no23.cc", + "/energyprice.json": "https://ams2mqtt.no23.cc", + "/dayplot.json": "https://ams2mqtt.no23.cc", + "/monthplot.json": "https://ams2mqtt.no23.cc", + "/temperature.json": "https://ams2mqtt.no23.cc", + "/sysinfo.json": "https://ams2mqtt.no23.cc", "/configuration.json": "http://192.168.233.229", - "/tariff.json": "http://192.168.233.229", + "/tariff.json": "https://ams2mqtt.no23.cc", "/save": "http://192.168.233.229", "/reboot": "http://192.168.233.229", "/configfile": "http://192.168.233.229", diff --git a/lib/SvelteUi/json/conf_domoticz.json b/lib/SvelteUi/json/conf_domoticz.json new file mode 100644 index 00000000..3c11d996 --- /dev/null +++ b/lib/SvelteUi/json/conf_domoticz.json @@ -0,0 +1,7 @@ +"o": { + "e" : %d, + "c" : %d, + "u1" : %d, + "u2" : %d, + "u3" : %d +} diff --git a/lib/SvelteUi/json/conf_gpio.json b/lib/SvelteUi/json/conf_gpio.json index 4cea40be..c887d2f3 100644 --- a/lib/SvelteUi/json/conf_gpio.json +++ b/lib/SvelteUi/json/conf_gpio.json @@ -25,4 +25,4 @@ }, "b": %.1f } -} +}, diff --git a/lib/SvelteUi/json/firmware.html b/lib/SvelteUi/json/firmware.html index b4e32ece..da27f421 100644 --- a/lib/SvelteUi/json/firmware.html +++ b/lib/SvelteUi/json/firmware.html @@ -1,5 +1,5 @@ - + diff --git a/lib/SvelteUi/src/AmsWebServer.cpp b/lib/SvelteUi/src/AmsWebServer.cpp index 8631a640..1577cf09 100644 --- a/lib/SvelteUi/src/AmsWebServer.cpp +++ b/lib/SvelteUi/src/AmsWebServer.cpp @@ -25,6 +25,7 @@ #include "html/conf_thresholds_json.h" #include "html/conf_debug_json.h" #include "html/conf_gpio_json.h" +#include "html/conf_domoticz_json.h" #include "html/firmware_html.h" #include "version.h" @@ -727,6 +728,8 @@ void AmsWebServer::configurationJson() { config->getEntsoeConfig(entsoe); DebugConfig debugConfig; config->getDebugConfig(debugConfig); + DomoticzConfig domo; + config->getDomoticzConfig(domo); bool qsc = false; bool qsr = false; @@ -854,6 +857,14 @@ void AmsWebServer::configurationJson() { gpioConfig->vccBootLimit / 10.0 ); server.sendContent(buf); + snprintf_P(buf, BufferSize, CONF_DOMOTICZ_JSON, + domo.elidx, + domo.cl1idx, + domo.vl1idx, + domo.vl2idx, + domo.vl3idx + ); + server.sendContent(buf); server.sendContent("}"); } @@ -1141,14 +1152,14 @@ void AmsWebServer::handleSave() { config->setMqttConfig(mqtt); } - if(server.hasArg(F("dc")) && server.arg(F("dc")) == F("true")) { + if(server.hasArg(F("o")) && server.arg(F("o")) == F("true")) { if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf(PSTR("Received Domoticz config")); DomoticzConfig domo { - static_cast(server.arg(F("elidx")).toInt()), - static_cast(server.arg(F("vl1idx")).toInt()), - static_cast(server.arg(F("vl2idx")).toInt()), - static_cast(server.arg(F("vl3idx")).toInt()), - static_cast(server.arg(F("cl1idx")).toInt()) + static_cast(server.arg(F("oe")).toInt()), + static_cast(server.arg(F("ou1")).toInt()), + static_cast(server.arg(F("ou2")).toInt()), + static_cast(server.arg(F("ou3")).toInt()), + static_cast(server.arg(F("oc")).toInt()) }; config->setDomoticzConfig(domo); } @@ -1830,10 +1841,11 @@ void AmsWebServer::configFileDownload() { if(ds != NULL) { DayDataPoints day = ds->getDayData(); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dayplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"), + server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dayplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"), day.version, (int32_t) day.lastMeterReadTime, day.activeImport, + day.accuracy, ds->getHourImport(0), ds->getHourImport(1), ds->getHourImport(2), @@ -1892,10 +1904,11 @@ void AmsWebServer::configFileDownload() { } MonthDataPoints month = ds->getMonthData(); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("monthplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"), + server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("monthplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"), month.version, (int32_t) month.lastMeterReadTime, month.activeImport, + month.accuracy, ds->getDayImport(1), ds->getDayImport(2), ds->getDayImport(3), diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index f2255c36..266abd7d 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -1724,20 +1724,38 @@ void configFileParse() { eac.hours = String(pch).toInt(); } else if(strncmp_P(buf, PSTR("dayplot "), 8) == 0) { int i = 0; - DayDataPoints day = { 4 }; // Use a version we know the multiplier of the data points + DayDataPoints day = { 0 }; char * pch = strtok (buf+8," "); while (pch != NULL) { int64_t val = String(pch).toInt(); - if(i == 1) { - day.lastMeterReadTime = val; - } else if(i == 2) { - day.activeImport = val; - } else if(i > 2 && i < 27) { - day.hImport[i-3] = val / 10; - } else if(i == 27) { - day.activeExport = val; - } else if(i > 27 && i < 52) { - day.hExport[i-28] = val / 10; + if(day.version < 5) { + if(i == 0) { + day.version = val; + } else if(i == 1) { + day.lastMeterReadTime = val; + } else if(i == 2) { + day.activeImport = val; + } else if(i > 2 && i < 27) { + day.hImport[i-3] = val / 10; + } else if(i == 27) { + day.activeExport = val; + } else if(i > 27 && i < 52) { + day.hExport[i-28] = val / 10; + } + } else { + if(i == 1) { + day.lastMeterReadTime = val; + } else if(i == 2) { + day.activeImport = val; + } else if(i == 3) { + day.accuracy = val; + } else if(i > 3 && i < 28) { + day.hImport[i-4] = val / pow(10, day.accuracy); + } else if(i == 28) { + day.activeExport = val; + } else if(i > 28 && i < 53) { + day.hExport[i-29] = val / pow(10, day.accuracy); + } } pch = strtok (NULL, " "); @@ -1747,22 +1765,39 @@ void configFileParse() { sDs = true; } else if(strncmp_P(buf, PSTR("monthplot "), 10) == 0) { int i = 0; - MonthDataPoints month = { 5 }; // Use a version we know the multiplier of the data points + MonthDataPoints month = { 0 }; char * pch = strtok (buf+10," "); while (pch != NULL) { int64_t val = String(pch).toInt(); - if(i == 1) { - month.lastMeterReadTime = val; - } else if(i == 2) { - month.activeImport = val; - } else if(i > 2 && i < 34) { - month.dImport[i-3] = val / 10; - } else if(i == 34) { - month.activeExport = val; - } else if(i > 34 && i < 66) { - month.dExport[i-35] = val / 10; + if(month.version < 6) { + if(i == 0) { + month.version = val; + } else if(i == 1) { + month.lastMeterReadTime = val; + } else if(i == 2) { + month.activeImport = val; + } else if(i > 2 && i < 34) { + month.dImport[i-3] = val / 10; + } else if(i == 34) { + month.activeExport = val; + } else if(i > 34 && i < 66) { + month.dExport[i-35] = val / 10; + } + } else { + if(i == 1) { + month.lastMeterReadTime = val; + } else if(i == 2) { + month.activeImport = val; + } else if(i == 3) { + month.accuracy = val; + } else if(i > 3 && i < 35) { + month.dImport[i-4] = val / pow(10, month.accuracy); + } else if(i == 35) { + month.activeExport = val; + } else if(i > 35 && i < 67) { + month.dExport[i-36] = val / pow(10, month.accuracy); + } } - pch = strtok (NULL, " "); i++; }