Compare commits

..

12 Commits

Author SHA1 Message Date
Gunnar Skjold
de19de2129 Fixed incorrect change in previous commit 2023-02-01 19:00:50 +01:00
Gunnar Skjold
1719263de0 Fixed config migration issue from v2.1 2023-02-01 18:46:22 +01:00
Gunnar Skjold
e70b872c98 Removed v2.0 config loading 2023-02-01 18:46:06 +01:00
Gunnar Skjold
b7d28238ab Extended cache for js and css 2023-01-31 17:16:18 +01:00
Gunnar Skjold
6c9a8b0692 Label fix 2023-01-31 17:04:46 +01:00
Gunnar Skjold
9f3dba3aab Fixed reconnect after setup 2023-01-30 20:58:08 +01:00
Gunnar Skjold
e4e4ad4107 Fixed autodetect 2023-01-30 18:32:17 +01:00
Gunnar Skjold
e8fb9570bb Chasing a reboot bug... 2023-01-30 16:52:12 +01:00
Gunnar Skjold
bc42099962 Fixing some bug reports 2023-01-30 16:07:08 +01:00
Gunnar Skjold
be71cbe609 Some changes after bug reports 2023-01-30 12:02:23 +01:00
Gunnar Skjold
0d6df03c94 Fixed reboot loop, changed temperature sensor behaviour and changed some debugging 2023-01-29 22:45:35 +01:00
Gunnar Skjold
d777040c0a Fixed loading error from previous version energy accounting 2023-01-29 17:04:04 +01:00
18 changed files with 234 additions and 262 deletions

View File

@@ -22,10 +22,6 @@
#define CONFIG_NTP_START 872 #define CONFIG_NTP_START 872
#define CONFIG_MQTT_START 1004 #define CONFIG_MQTT_START 1004
#define CONFIG_MQTT_START_86 224
#define CONFIG_METER_START_87 784
#define CONFIG_ENTSOE_START_90 286
#define CONFIG_WIFI_START_91 16
#define CONFIG_METER_START_93 224 #define CONFIG_METER_START_93 224
@@ -37,18 +33,6 @@ struct SystemConfig {
char country[3]; char country[3];
}; // 7 }; // 7
struct WiFiConfig91 {
char ssid[32];
char psk[64];
char ip[15];
char gateway[15];
char subnet[15];
char dns1[15];
char dns2[15];
char hostname[32];
bool mdns;
}; // 204
struct WiFiConfig { struct WiFiConfig {
char ssid[32]; char ssid[32];
char psk[64]; char psk[64];
@@ -65,18 +49,6 @@ struct WiFiConfig {
bool autoreboot; bool autoreboot;
}; // 213 }; // 213
struct MqttConfig86 {
char host[128];
uint16_t port;
char clientId[32];
char publishTopic[64];
char subscribeTopic[64];
char username[64];
char password[64];
uint8_t payloadFormat;
bool ssl;
}; // 420
struct MqttConfig { struct MqttConfig {
char host[128]; char host[128];
uint16_t port; uint16_t port;
@@ -110,7 +82,7 @@ struct MeterConfig {
uint32_t accumulatedMultiplier; uint32_t accumulatedMultiplier;
uint8_t source; uint8_t source;
uint8_t parser; uint8_t parser;
}; // 52 }; // 61
struct MeterConfig100 { struct MeterConfig100 {
uint32_t baud; uint32_t baud;
@@ -127,7 +99,7 @@ struct MeterConfig100 {
uint32_t accumulatedMultiplier; uint32_t accumulatedMultiplier;
uint8_t source; uint8_t source;
uint8_t parser; uint8_t parser;
}; // 50 }; // 59
struct MeterConfig95 { struct MeterConfig95 {
uint32_t baud; uint32_t baud;
@@ -146,16 +118,6 @@ struct MeterConfig95 {
uint8_t parser; uint8_t parser;
}; // 50 }; // 50
struct MeterConfig87 {
uint8_t type;
uint8_t distributionSystem;
uint8_t mainFuse;
uint8_t productionCapacity;
uint8_t encryptionKey[16];
uint8_t authenticationKey[16];
bool substituteMissing;
}; // 37
struct DebugConfig { struct DebugConfig {
bool telnet; bool telnet;
bool serial; bool serial;
@@ -331,9 +293,6 @@ private:
uint8_t tempSensorCount = 0; uint8_t tempSensorCount = 0;
TempSensorConfig** tempSensors = NULL; TempSensorConfig** tempSensors = NULL;
bool relocateConfig90(); // 2.0.0
bool relocateConfig91(); // 2.0.2
bool relocateConfig92(); // 2.0.3
bool relocateConfig93(); // 2.1.0 bool relocateConfig93(); // 2.1.0
bool relocateConfig94(); // 2.1.0 bool relocateConfig94(); // 2.1.0
bool relocateConfig95(); // 2.1.4 bool relocateConfig95(); // 2.1.4

View File

@@ -358,8 +358,9 @@ bool AmsConfiguration::pinUsed(uint8_t pin, GpioConfig& config) {
} }
bool AmsConfiguration::getGpioConfig(GpioConfig& config) { bool AmsConfiguration::getGpioConfig(GpioConfig& config) {
if(hasConfig()) { EEPROM.begin(EEPROM_SIZE);
EEPROM.begin(EEPROM_SIZE); uint8_t configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
if(configVersion == EEPROM_CHECK_SUM || configVersion == EEPROM_CLEARED_INDICATOR) {
EEPROM.get(CONFIG_GPIO_START, config); EEPROM.get(CONFIG_GPIO_START, config);
EEPROM.end(); EEPROM.end();
return true; return true;
@@ -505,6 +506,7 @@ bool AmsConfiguration::getEntsoeConfig(EntsoeConfig& config) {
} }
return true; return true;
} else { } else {
clearEntsoe(config);
return false; return false;
} }
} }
@@ -560,6 +562,7 @@ bool AmsConfiguration::getEnergyAccountingConfig(EnergyAccountingConfig& config)
if(config.hours > 5) config.hours = 5; if(config.hours > 5) config.hours = 5;
return true; return true;
} else { } else {
clearEnergyAccountingConfig(config);
return false; return false;
} }
} }
@@ -713,30 +716,6 @@ bool AmsConfiguration::hasConfig() {
} }
} else { } else {
switch(configVersion) { switch(configVersion) {
case 90:
configVersion = -1; // Prevent loop
if(relocateConfig90()) {
configVersion = 91;
} else {
configVersion = 0;
return false;
}
case 91:
configVersion = -1; // Prevent loop
if(relocateConfig91()) {
configVersion = 92;
} else {
configVersion = 0;
return false;
}
case 92:
configVersion = -1; // Prevent loop
if(relocateConfig92()) {
configVersion = 93;
} else {
configVersion = 0;
return false;
}
case 93: case 93:
configVersion = -1; // Prevent loop configVersion = -1; // Prevent loop
if(relocateConfig93()) { if(relocateConfig93()) {
@@ -829,61 +808,8 @@ void AmsConfiguration::saveTempSensors() {
} }
} }
bool AmsConfiguration::relocateConfig90() {
EntsoeConfig entsoe;
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_ENTSOE_START_90, entsoe);
EEPROM.put(CONFIG_ENTSOE_START, entsoe);
EEPROM.put(EEPROM_CONFIG_ADDRESS, 91);
bool ret = EEPROM.commit();
EEPROM.end();
return ret;
}
bool AmsConfiguration::relocateConfig91() {
WiFiConfig91 wifi91;
WiFiConfig wifi;
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_WIFI_START_91, wifi91);
strcpy(wifi.ssid, wifi91.ssid);
strcpy(wifi.psk, wifi91.psk);
strcpy(wifi.ip, wifi91.ip);
strcpy(wifi.gateway, wifi91.gateway);
strcpy(wifi.subnet, wifi91.subnet);
strcpy(wifi.dns1, wifi91.dns1);
strcpy(wifi.dns2, wifi91.dns2);
strcpy(wifi.hostname, wifi91.hostname);
wifi.mdns = wifi91.mdns;
EEPROM.put(CONFIG_WIFI_START, wifi);
EEPROM.put(EEPROM_CONFIG_ADDRESS, 92);
bool ret = EEPROM.commit();
EEPROM.end();
return ret;
}
bool AmsConfiguration::relocateConfig92() {
WiFiConfig wifi;
EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_WIFI_START, wifi);
#if defined(ESP32)
wifi.power = 195;
#elif defined(ESP8266)
wifi.power = 205;
#endif
EEPROM.put(CONFIG_WIFI_START, wifi);
EnergyAccountingConfig eac;
clearEnergyAccountingConfig(eac);
EEPROM.put(CONFIG_ENERGYACCOUNTING_START, eac);
EEPROM.put(EEPROM_CONFIG_ADDRESS, 93);
bool ret = EEPROM.commit();
EEPROM.end();
return ret;
}
bool AmsConfiguration::relocateConfig93() { bool AmsConfiguration::relocateConfig93() {
MeterConfig meter; MeterConfig95 meter;
EEPROM.begin(EEPROM_SIZE); EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_METER_START_93, meter); EEPROM.get(CONFIG_METER_START_93, meter);
meter.wattageMultiplier = 0; meter.wattageMultiplier = 0;
@@ -910,7 +836,7 @@ bool AmsConfiguration::relocateConfig94() {
} }
bool AmsConfiguration::relocateConfig95() { bool AmsConfiguration::relocateConfig95() {
MeterConfig meter; MeterConfig95 meter;
MeterConfig95 meter95; MeterConfig95 meter95;
EEPROM.begin(EEPROM_SIZE); EEPROM.begin(EEPROM_SIZE);
EEPROM.get(CONFIG_METER_START, meter); EEPROM.get(CONFIG_METER_START, meter);
@@ -931,7 +857,7 @@ bool AmsConfiguration::relocateConfig96() {
SystemConfig sys; SystemConfig sys;
EEPROM.get(CONFIG_SYSTEM_START, sys); EEPROM.get(CONFIG_SYSTEM_START, sys);
MeterConfig meter; MeterConfig100 meter;
EEPROM.get(CONFIG_METER_START, meter); EEPROM.get(CONFIG_METER_START, meter);
meter.source = 1; // Serial meter.source = 1; // Serial
meter.parser = 0; // Auto meter.parser = 0; // Auto

View File

@@ -77,7 +77,7 @@ protected:
unsigned long lastList2 = 0; unsigned long lastList2 = 0;
uint8_t listType = 0, meterType = AmsTypeUnknown; uint8_t listType = 0, meterType = AmsTypeUnknown;
time_t packageTimestamp = 0; time_t packageTimestamp = 0;
String listId, meterId, meterModel; String listId = "", meterId = "", meterModel = "";
time_t meterTimestamp = 0; time_t meterTimestamp = 0;
uint16_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0; uint16_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0;
float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0; float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0;

View File

@@ -89,8 +89,8 @@ private:
EnergyAccountingConfig *config = NULL; EnergyAccountingConfig *config = NULL;
Timezone *tz = NULL; Timezone *tz = NULL;
uint8_t currentHour = 0, currentDay = 0, currentThresholdIdx = 0; uint8_t currentHour = 0, currentDay = 0, currentThresholdIdx = 0;
double use, costHour, costDay; double use = 0, costHour = 0, costDay = 0;
double produce, incomeHour, incomeDay; double produce = 0, incomeHour = 0, incomeDay = 0;
EnergyAccountingData data = { 0, 0, 0, 0, 0, 0 }; EnergyAccountingData data = { 0, 0, 0, 0, 0, 0 };
void calcDayCost(); void calcDayCost();

View File

@@ -185,7 +185,8 @@ double EnergyAccounting::getUseThisHour() {
double EnergyAccounting::getUseToday() { double EnergyAccounting::getUseToday() {
float ret = 0.0; float ret = 0.0;
time_t now = time(nullptr); time_t now = time(nullptr);
if(now < BUILD_EPOCH) return 0; if(now < BUILD_EPOCH) return 0.0;
if(tz == NULL) return 0.0;
tmElements_t utc, local; tmElements_t utc, local;
breakTime(tz->toLocal(now), local); breakTime(tz->toLocal(now), local);
for(int i = 0; i < currentHour; i++) { for(int i = 0; i < currentHour; i++) {
@@ -197,7 +198,7 @@ double EnergyAccounting::getUseToday() {
double EnergyAccounting::getUseThisMonth() { double EnergyAccounting::getUseThisMonth() {
time_t now = time(nullptr); time_t now = time(nullptr);
if(now < BUILD_EPOCH) return 0; if(now < BUILD_EPOCH) return 0.0;
float ret = 0; float ret = 0;
for(int i = 0; i < currentDay; i++) { for(int i = 0; i < currentDay; i++) {
ret += ds->getDayImport(i) / 1000.0; ret += ds->getDayImport(i) / 1000.0;
@@ -212,7 +213,7 @@ double EnergyAccounting::getProducedThisHour() {
double EnergyAccounting::getProducedToday() { double EnergyAccounting::getProducedToday() {
float ret = 0.0; float ret = 0.0;
time_t now = time(nullptr); time_t now = time(nullptr);
if(now < BUILD_EPOCH) return 0; if(now < BUILD_EPOCH) return 0.0;
tmElements_t utc; tmElements_t utc;
for(int i = 0; i < currentHour; i++) { for(int i = 0; i < currentHour; i++) {
breakTime(now - ((currentHour - i) * 3600), utc); breakTime(now - ((currentHour - i) * 3600), utc);
@@ -223,7 +224,7 @@ double EnergyAccounting::getProducedToday() {
double EnergyAccounting::getProducedThisMonth() { double EnergyAccounting::getProducedThisMonth() {
time_t now = time(nullptr); time_t now = time(nullptr);
if(now < BUILD_EPOCH) return 0; if(now < BUILD_EPOCH) return 0.0;
float ret = 0; float ret = 0;
for(int i = 0; i < currentDay; i++) { for(int i = 0; i < currentDay; i++) {
ret += ds->getDayExport(i) / 1000.0; ret += ds->getDayExport(i) / 1000.0;
@@ -279,6 +280,8 @@ uint8_t EnergyAccounting::getCurrentThreshold() {
} }
float EnergyAccounting::getMonthMax() { float EnergyAccounting::getMonthMax() {
if(config == NULL)
return 0.0;
uint8_t count = 0; uint8_t count = 0;
uint32_t maxHour = 0.0; uint32_t maxHour = 0.0;
bool included[5] = { false, false, false, false, false }; bool included[5] = { false, false, false, false, false };
@@ -308,6 +311,8 @@ float EnergyAccounting::getMonthMax() {
} }
EnergyAccountingPeak EnergyAccounting::getPeak(uint8_t num) { EnergyAccountingPeak EnergyAccounting::getPeak(uint8_t num) {
if(config == NULL)
return EnergyAccountingPeak({0,0});
if(num < 1 || num > 5) return EnergyAccountingPeak({0,0}); if(num < 1 || num > 5) return EnergyAccountingPeak({0,0});
uint8_t count = 0; uint8_t count = 0;
@@ -362,7 +367,9 @@ bool EnergyAccounting::load() {
} else if(buf[0] == 4) { } else if(buf[0] == 4) {
EnergyAccountingData4* data = (EnergyAccountingData4*) buf; EnergyAccountingData4* data = (EnergyAccountingData4*) buf;
this->data = { 5, data->month, this->data = { 5, data->month,
(uint16_t) (data->costYesterday / 10), (uint16_t) (data->costThisMonth / 100), (uint16_t) (data->costLastMonth / 100), data->costYesterday,
data->costThisMonth,
data->costLastMonth,
0,0,0, // Income from production 0,0,0, // Income from production
data->peaks[0].day, data->peaks[0].value, data->peaks[0].day, data->peaks[0].value,
data->peaks[1].day, data->peaks[1].value, data->peaks[1].day, data->peaks[1].value,

View File

@@ -64,6 +64,10 @@
{#if sysinfo.upgrading} {#if sysinfo.upgrading}
<Mask active=true message="Device is upgrading, please wait"/> <Mask active=true message="Device is upgrading, please wait"/>
{:else if sysinfo.booting} {:else if sysinfo.booting}
<Mask active=true message="Device is booting, please wait"/> {#if sysinfo.trying}
<Mask active=true message="Device is booting, please wait. Trying to reach it on {sysinfo.trying}"/>
{:else}
<Mask active=true message="Device is booting, please wait"/>
{/if}
{/if} {/if}
</div> </div>

View File

@@ -1,54 +1,79 @@
<script> <script>
export let data; export let data;
export let currency; export let currency;
export let hasExport;
let hasExport = data && (data.om || data.e > 0);
</script> </script>
<div class="mx-2 text-sm"> <div class="mx-2 text-sm">
<strong>Real time calculation</strong> <strong>Real time calculation</strong>
<br/><br/>
{#if data && data.h !== undefined}
<div class="flex"> {#if data}
<div>Hour</div> {#if hasExport && currency}
<div class="flex-auto text-right">{data.h.u ? data.h.u.toFixed(2) : '-'} kWh {#if currency && (hasExport)}/ {data.h.c ? data.h.c.toFixed(2) : '-'} {currency}{/if}</div> <strong>Import</strong>
</div> <div class="grid grid-cols-3 mb-3">
<div class="flex"> <div>Hour</div>
<div>Day</div> <div class="text-right">{data.h.u ? data.h.u.toFixed(2) : '-'} kWh</div>
<div class="flex-auto text-right">{data.d.u ? data.d.u.toFixed(1) : '-'} kWh {#if currency && (hasExport)}/ {data.d.c ? data.d.c.toFixed(2) : '-'} {currency}{/if}</div> <div class="text-right">{data.h.c ? data.h.c.toFixed(2) : '-'} {currency}</div>
</div> <div>Day</div>
<div class="flex"> <div class="text-right">{data.d.u ? data.d.u.toFixed(1) : '-'} kWh</div>
<div>Month</div> <div class="text-right">{data.d.c ? data.d.c.toFixed(1) : '-'} {currency}</div>
<div class="flex-auto text-right">{data.m.u ? data.m.u.toFixed(0) : '-'} kWh {#if currency && (hasExport)}/ {data.m.c ? data.m.c.toFixed(2) : '-'} {currency}{/if}</div> <div>Month</div>
</div> <div class="text-right">{data.m.u ? data.m.u.toFixed(0) : '-'} kWh</div>
<div class="mt-4"> <div class="text-right">{data.m.c ? data.m.c.toFixed(0) : '-'} {currency}</div>
{#if hasExport} </div>
<div class="flex"> <strong>Export</strong>
<div>Hour</div> <div class="grid grid-cols-3">
<div class="flex-auto text-right">{data.h.p ? data.h.p.toFixed(2) : '-'} kWh {#if currency}/ {data.h.i ? data.h.i.toFixed(2) : '-'} {currency}{/if}</div> <div>Hour</div>
</div> <div class="text-right">{data.h.p ? data.h.p.toFixed(2) : '-'} kWh</div>
<div class="flex"> <div class="text-right">{data.h.i ? data.h.i.toFixed(2) : '-'} {currency}</div>
<div>Day</div> <div>Day</div>
<div class="flex-auto text-right">{data.d.p ? data.d.p.toFixed(1) : '-'} kWh {#if currency}/ {data.d.i ? data.d.i.toFixed(2) : '-'} {currency}{/if}</div> <div class="text-right">{data.d.p ? data.d.p.toFixed(1) : '-'} kWh</div>
</div> <div class="text-right">{data.d.i ? data.d.i.toFixed(1) : '-'} {currency}</div>
<div class="flex"> <div>Month</div>
<div>Month</div> <div class="text-right">{data.m.p ? data.m.p.toFixed(0) : '-'} kWh</div>
<div class="flex-auto text-right">{data.m.p ? data.m.p.toFixed(0) : '-'} kWh {#if currency}/ {data.m.i ? data.m.i.toFixed(2) : '-'} {currency}{/if}</div> <div class="text-right">{data.m.i ? data.m.i.toFixed(0) : '-'} {currency}</div>
</div> </div>
{:else if hasExport}
<strong>Import</strong>
<div class="grid grid-cols-2 mb-3">
<div>Hour</div>
<div class="text-right">{data.h.u ? data.h.u.toFixed(2) : '-'} kWh</div>
<div>Day</div>
<div class="text-right">{data.d.u ? data.d.u.toFixed(1) : '-'} kWh</div>
<div>Month</div>
<div class="text-right">{data.m.u ? data.m.u.toFixed(0) : '-'} kWh</div>
</div>
<strong>Export</strong>
<div class="grid grid-cols-2">
<div>Hour</div>
<div class="text-right">{data.h.p ? data.h.p.toFixed(2) : '-'} kWh</div>
<div>Day</div>
<div class="text-right">{data.d.p ? data.d.p.toFixed(1) : '-'} kWh</div>
<div>Month</div>
<div class="text-right">{data.m.p ? data.m.p.toFixed(0) : '-'} kWh</div>
</div>
{:else} {:else}
<div class="flex"> <strong>Consumption</strong>
<div>Hour</div> <div class="grid grid-cols-2 mb-3">
<div class="flex-auto text-right">{data.h.c ? data.h.c.toFixed(2) : '-'} {currency}</div> <div>Hour</div>
</div> <div class="text-right">{data.h.u ? data.h.u.toFixed(2) : '-'} kWh</div>
<div class="flex"> <div>Day</div>
<div>Day</div> <div class="text-right">{data.d.u ? data.d.u.toFixed(1) : '-'} kWh</div>
<div class="flex-auto text-right">{data.d.c ? data.d.c.toFixed(2) : '-'} {currency}</div> <div>Month</div>
</div> <div class="text-right">{data.m.u ? data.m.u.toFixed(0) : '-'} kWh</div>
<div class="flex"> </div>
<div>Month</div> {#if currency}
<div class="flex-auto text-right">{data.m.c ? data.m.c.toFixed(2) : '-'} {currency}</div> <strong>Cost</strong>
</div> <div class="grid grid-cols-2">
<div>Hour</div>
<div class="text-right">{data.h.c ? data.h.c.toFixed(2) : '-'} {currency}</div>
<div>Day</div>
<div class="text-right">{data.d.c ? data.d.c.toFixed(1) : '-'} {currency}</div>
<div>Month</div>
<div class="text-right">{data.m.c ? data.m.c.toFixed(0) : '-'} {currency}</div>
</div>
{/if}
{/if} {/if}
</div>
{/if} {/if}
</div> </div>

View File

@@ -7,6 +7,7 @@
import HelpIcon from './HelpIcon.svelte'; import HelpIcon from './HelpIcon.svelte';
import CountrySelectOptions from './CountrySelectOptions.svelte'; import CountrySelectOptions from './CountrySelectOptions.svelte';
import { Link, navigate } from 'svelte-navigator'; import { Link, navigate } from 'svelte-navigator';
import SubnetOptions from './SubnetOptions.svelte';
export let sysinfo = {} export let sysinfo = {}
@@ -67,8 +68,10 @@
getConfiguration(); getConfiguration();
let isFactoryReset = false; let isFactoryReset = false;
let isFactoryResetComplete = false;
async function factoryReset() { async function factoryReset() {
if(confirm("Are you sure you want to factory reset the device?")) { if(confirm("Are you sure you want to factory reset the device?")) {
isFactoryReset = true;
const data = new URLSearchParams(); const data = new URLSearchParams();
data.append("perform", "true"); data.append("perform", "true");
const response = await fetch('/reset', { const response = await fetch('/reset', {
@@ -76,7 +79,8 @@
body: data body: data
}); });
let res = (await response.json()); let res = (await response.json());
isFactoryReset = res.success; isFactoryReset = false;
isFactoryResetComplete = res.success;
} }
} }
@@ -362,11 +366,9 @@
<option value="dhcp">DHCP</option> <option value="dhcp">DHCP</option>
<option value="static">Static</option> <option value="static">Static</option>
</select> </select>
<input name="ni" bind:value={configuration.n.i} type="text" class="in-m w-full" disabled={configuration.n.m == 'dhcp'}/> <input name="ni" bind:value={configuration.n.i} type="text" class="in-m w-full" disabled={configuration.n.m == 'dhcp'} required={configuration.n.m == 'static'}/>
<select name="ns" bind:value={configuration.n.s} class="in-l" disabled={configuration.n.m == 'dhcp'}> <select name="ns" bind:value={configuration.n.s} class="in-l" disabled={configuration.n.m == 'dhcp'} required={configuration.n.m == 'static'}>
<option value="255.255.255.0">/24</option> <SubnetOptions/>
<option value="255.255.0.0">/16</option>
<option value="255.0.0.0">/8</option>
</select> </select>
</div> </div>
</div> </div>
@@ -765,4 +767,5 @@
<Mask active={loading} message="Loading configuration"/> <Mask active={loading} message="Loading configuration"/>
<Mask active={saving} message="Saving configuration"/> <Mask active={saving} message="Saving configuration"/>
<Mask active={isFactoryReset} message="Device have been factory reset and switched to AP mode"/> <Mask active={isFactoryReset} message="Performing factory reset"/>
<Mask active={isFactoryResetComplete} message="Device have been factory reset and switched to AP mode"/>

View File

@@ -1,6 +1,6 @@
<script> <script>
import { pricesStore, dayPlotStore, monthPlotStore, temperaturesStore } from './DataStores.js'; import { pricesStore, dayPlotStore, monthPlotStore, temperaturesStore } from './DataStores.js';
import { metertype, uiVisibility } from './Helpers.js'; import { ampcol, exportcol, metertype, uiVisibility } from './Helpers.js';
import PowerGauge from './PowerGauge.svelte'; import PowerGauge from './PowerGauge.svelte';
import VoltPlot from './VoltPlot.svelte'; import VoltPlot from './VoltPlot.svelte';
import AmpPlot from './AmpPlot.svelte'; import AmpPlot from './AmpPlot.svelte';
@@ -32,23 +32,23 @@
}); });
</script> </script>
<div class="grid xl:grid-cols-6 lg:grid-cols-4 md:grid-cols-3 sm:grid-cols-2"> <div class="grid 2xl:grid-cols-6 xl:grid-cols-5 lg:grid-cols-4 md:grid-cols-3 sm:grid-cols-2">
{#if uiVisibility(sysinfo.ui.i, data.i)} {#if uiVisibility(sysinfo.ui.i, data.i)}
<div class="cnt"> <div class="cnt">
<div class="grid grid-cols-2"> <div class="grid grid-cols-2">
<div class="col-span-2"> <div class="col-span-2">
<PowerGauge val={data.i ? data.i : 0} max={data.im} unit="W" label="Import" sub={data.p} subunit={prices.currency}/> <PowerGauge val={data.i ? data.i : 0} max={data.im ? data.im : 15000} unit="W" label="Import" sub={data.p} subunit={prices.currency} colorFn={ampcol}/>
</div>
<div>{data.mt ? metertype(data.mt) : '-'}</div>
<div class="text-right">{data.ic ? data.ic.toFixed(1) : '-'} kWh</div>
</div> </div>
<div>{data.mt ? metertype(data.mt) : '-'}</div>
<div class="text-right">{data.ic ? data.ic.toFixed(1) : '-'} kWh</div>
</div> </div>
</div>
{/if} {/if}
{#if uiVisibility(sysinfo.ui.e, data.om || data.e > 0)} {#if uiVisibility(sysinfo.ui.e, data.om || data.e > 0)}
<div class="cnt"> <div class="cnt">
<div class="grid grid-cols-2"> <div class="grid grid-cols-2">
<div class="col-span-2"> <div class="col-span-2">
<PowerGauge val={data.e ? data.e : 0} max={data.om ? data.om : 10000} unit="W" label="Export"/> <PowerGauge val={data.e ? data.e : 0} max={data.om ? data.om * 1000 : 10000} unit="W" label="Export" colorFn={exportcol}/>
</div> </div>
<div></div> <div></div>
<div class="text-right">{data.ec ? data.ec.toFixed(1) : '-'} kWh</div> <div class="text-right">{data.ec ? data.ec.toFixed(1) : '-'} kWh</div>
@@ -56,48 +56,48 @@
</div> </div>
{/if} {/if}
{#if uiVisibility(sysinfo.ui.v, data.u1 > 100 || data.u2 > 100 || data.u3 > 100)} {#if uiVisibility(sysinfo.ui.v, data.u1 > 100 || data.u2 > 100 || data.u3 > 100)}
<div class="cnt"> <div class="cnt">
<VoltPlot u1={data.u1} u2={data.u2} u3={data.u3} ds={data.ds}/> <VoltPlot u1={data.u1} u2={data.u2} u3={data.u3} ds={data.ds}/>
</div> </div>
{/if} {/if}
{#if uiVisibility(sysinfo.ui.a, data.i1 > 0.01 || data.i2 > 0.01 || data.i3 > 0.01)} {#if uiVisibility(sysinfo.ui.a, data.i1 > 0.01 || data.i2 > 0.01 || data.i3 > 0.01)}
<div class="cnt"> <div class="cnt">
<AmpPlot u1={data.u1} u2={data.u2} u3={data.u3} i1={data.i1} i2={data.i2} i3={data.i3} max={data.mf ? data.mf : 32}/> <AmpPlot u1={data.u1} u2={data.u2} u3={data.u3} i1={data.i1} i2={data.i2} i3={data.i3} max={data.mf ? data.mf : 32}/>
</div> </div>
{/if} {/if}
{#if uiVisibility(sysinfo.ui.r, data.ri > 0 || data.re > 0 || data.ric > 0 || data.rec > 0)} {#if uiVisibility(sysinfo.ui.r, data.ri > 0 || data.re > 0 || data.ric > 0 || data.rec > 0)}
<div class="cnt"> <div class="cnt">
<ReactiveData importInstant={data.ri} exportInstant={data.re} importTotal={data.ric} exportTotal={data.rec}/> <ReactiveData importInstant={data.ri} exportInstant={data.re} importTotal={data.ric} exportTotal={data.rec}/>
</div> </div>
{/if} {/if}
{#if uiVisibility(sysinfo.ui.c, data.ea)} {#if uiVisibility(sysinfo.ui.c, data.ea)}
<div class="cnt"> <div class="cnt">
<AccountingData data={data.ea} currency={prices.currency}/> <AccountingData data={data.ea} currency={prices.currency} hasExport={data.om > 0 || data.e > 0}/>
</div> </div>
{/if} {/if}
{#if data && data.pr && (data.pr.startsWith("10YNO") || data.pr == '10Y1001A1001A48H')} {#if uiVisibility(sysinfo.ui.t, data.pr && (data.pr.startsWith("10YNO") || data.pr == '10Y1001A1001A48H'))}
<div class="cnt h-64"> <div class="cnt h-64">
<TariffPeakChart /> <TariffPeakChart />
</div> </div>
{/if} {/if}
{#if uiVisibility(sysinfo.ui.p, (typeof data.p == "number") && !Number.isNaN(data.p))} {#if uiVisibility(sysinfo.ui.p, (typeof data.p == "number") && !Number.isNaN(data.p))}
<div class="cnt xl:col-span-6 lg:col-span-4 md:col-span-3 sm:col-span-2 h-64"> <div class="cnt 2xl:col-span-6 xl:col-span-5 lg:col-span-4 md:col-span-3 sm:col-span-2 h-64">
<PricePlot json={prices}/> <PricePlot json={prices}/>
</div> </div>
{/if} {/if}
{#if uiVisibility(sysinfo.ui.d, dayPlot)} {#if uiVisibility(sysinfo.ui.d, dayPlot)}
<div class="cnt xl:col-span-6 lg:col-span-4 md:col-span-3 sm:col-span-2 h-64"> <div class="cnt 2xl:col-span-6 xl:col-span-5 lg:col-span-4 md:col-span-3 sm:col-span-2 h-64">
<DayPlot json={dayPlot} /> <DayPlot json={dayPlot} />
</div> </div>
{/if} {/if}
{#if uiVisibility(sysinfo.ui.m, monthPlot)} {#if uiVisibility(sysinfo.ui.m, monthPlot)}
<div class="cnt xl:col-span-6 lg:col-span-4 md:col-span-3 sm:col-span-2 h-64"> <div class="cnt 2xl:col-span-6 xl:col-span-5 lg:col-span-4 md:col-span-3 sm:col-span-2 h-64">
<MonthPlot json={monthPlot} /> <MonthPlot json={monthPlot} />
</div> </div>
{/if} {/if}
{#if uiVisibility(sysinfo.ui.s, data.t && data.t != -127 && temperatures.c > 1)} {#if uiVisibility(sysinfo.ui.s, data.t && data.t != -127 && temperatures.c > 1)}
<div class="cnt xl:col-span-6 lg:col-span-4 md:col-span-3 sm:col-span-2 h-64"> <div class="cnt 2xl:col-span-6 xl:col-span-5 lg:col-span-4 md:col-span-3 sm:col-span-2 h-64">
<TemperaturePlot json={temperatures} /> <TemperaturePlot json={temperatures} />
</div> </div>
{/if} {/if}
</div> </div>

View File

@@ -25,7 +25,8 @@ let sysinfo = {
booting: false, booting: false,
upgrading: false, upgrading: false,
ui: {}, ui: {},
security: 0 security: 0,
trying: null
}; };
export const sysinfoStore = writable(sysinfo); export const sysinfoStore = writable(sysinfo);
export async function getSysinfo() { export async function getSysinfo() {

View File

@@ -15,6 +15,13 @@ export function ampcol(pct) {
else return '#32d900'; else return '#32d900';
}; };
export function exportcol(pct) {
if(pct > 75) return '#32d900';
else if(pct > 50) return '#77d900';
else if(pct > 25) return '#94d900';
else return '#dcd800';
};
export function metertype(mt) { export function metertype(mt) {
switch(mt) { switch(mt) {
case 1: case 1:

View File

@@ -1,6 +1,5 @@
<script> <script>
import PowerGaugeSvg from './PowerGaugeSvg.svelte'; import PowerGaugeSvg from './PowerGaugeSvg.svelte';
import { ampcol } from './Helpers.js';
export let val; export let val;
export let max; export let max;
@@ -8,10 +7,16 @@
export let label; export let label;
export let sub = ""; export let sub = "";
export let subunit = ""; export let subunit = "";
export let colorFn;
let pct = 0;
$: {
pct = (Math.min(val,max)/max) * 100
}
</script> </script>
<div class="pl-root"> <div class="pl-root">
<PowerGaugeSvg pct={val/max * 100} color={ampcol(val/max * 100)}/> <PowerGaugeSvg pct={pct} color={colorFn(pct)}/>
<span class="pl-ov"> <span class="pl-ov">
<span class="pl-lab">{label}</span> <span class="pl-lab">{label}</span>
<br/> <br/>

View File

@@ -1,6 +1,7 @@
<script> <script>
import { sysinfoStore } from './DataStores.js'; import { sysinfoStore } from './DataStores.js';
import Mask from './Mask.svelte' import Mask from './Mask.svelte'
import SubnetOptions from './SubnetOptions.svelte';
export let sysinfo = {} export let sysinfo = {}
@@ -12,7 +13,15 @@
var url = ""; var url = "";
tries++; tries++;
var retry = function() {
setTimeout(scanForDevice, 1000);
};
if(sysinfo.net.ip && tries%3 == 0) { if(sysinfo.net.ip && tries%3 == 0) {
if(sysinfo.net.ip == '0.0.0.0') {
retry();
return;
};
url = "http://" + sysinfo.net.ip; url = "http://" + sysinfo.net.ip;
} else if(sysinfo.hostname && tries%3 == 1) { } else if(sysinfo.hostname && tries%3 == 1) {
url = "http://" + sysinfo.hostname; url = "http://" + sysinfo.hostname;
@@ -22,10 +31,10 @@
url = ""; url = "";
} }
if(console) console.log("Trying url " + url); if(console) console.log("Trying url " + url);
sysinfoStore.update(s => {
var retry = function() { s.trying = url;
setTimeout(scanForDevice, 1000); return s;
}; });
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.timeout = 5000; xhr.timeout = 5000;
@@ -42,12 +51,10 @@
async function handleSubmit(e) { async function handleSubmit(e) {
loadingOrSaving = true; loadingOrSaving = true;
const formData = new FormData(e.target); const formData = new FormData(e.target);
let hostname = sysinfo.hostname;
const data = new URLSearchParams(); const data = new URLSearchParams();
for (let field of formData) { for (let field of formData) {
const [key, value] = field; const [key, value] = field;
data.append(key, value) data.append(key, value)
if(key == 'sh') hostname = value;
} }
const response = await fetch('/save', { const response = await fetch('/save', {
@@ -58,9 +65,15 @@
loadingOrSaving = false; loadingOrSaving = false;
sysinfoStore.update(s => { sysinfoStore.update(s => {
s.hostname = hostname; s.hostname = formData.get('sh');
s.usrcfg = res.success; s.usrcfg = res.success;
s.booting = res.reboot; s.booting = res.reboot;
if(staticIp) {
s.net.ip = formData.get('si');
s.net.mask = formData.get('su');
s.net.gw = formData.get('sg');
s.net.dns1 = formData.get('sd');
}
setTimeout(scanForDevice, 5000); setTimeout(scanForDevice, 5000);
return s; return s;
}); });
@@ -75,14 +88,14 @@
<strong class="text-sm">Setup</strong> <strong class="text-sm">Setup</strong>
<div class="my-3"> <div class="my-3">
SSID<br/> SSID<br/>
<input name="ss" type="text" class="in-s"/> <input name="ss" type="text" class="in-s" required/>
</div> </div>
<div class="my-3"> <div class="my-3">
PSK<br/> PSK<br/>
<input name="sp" type="password" class="in-s" autocomplete="off"/> <input name="sp" type="password" class="in-s" autocomplete="off"/>
</div> </div>
<div> <div>
Hostname: Hostname
<input name="sh" bind:value={sysinfo.hostname} type="text" class="in-s" maxlength="32" pattern="[a-z0-9_-]+" placeholder="Optional, ex.: ams-reader" autocomplete="off"/> <input name="sh" bind:value={sysinfo.hostname} type="text" class="in-s" maxlength="32" pattern="[a-z0-9_-]+" placeholder="Optional, ex.: ams-reader" autocomplete="off"/>
</div> </div>
<div class="my-3"> <div class="my-3">
@@ -92,9 +105,7 @@
<div class="flex"> <div class="flex">
<input name="si" type="text" class="in-f w-full" required={staticIp}/> <input name="si" type="text" class="in-f w-full" required={staticIp}/>
<select name="su" class="in-l" required={staticIp}> <select name="su" class="in-l" required={staticIp}>
<option value="255.255.255.0">/24</option> <SubnetOptions/>
<option value="255.255.0.0">/16</option>
<option value="255.0.0.0">/8</option>
</select> </select>
</div> </div>
{/if} {/if}

View File

@@ -0,0 +1,16 @@
<optgroup label="Most common is /24 (255.255.255.0)">
<option value="255.255.255.0">/24</option>
</optgroup>
<optgroup label="Smaller subnets">
<option value="255.255.255.128">/25</option>
<option value="255.255.255.192">/26</option>
<option value="255.255.255.224">/27</option>
<option value="255.255.255.240">/28</option>
<option value="255.255.255.248">/29</option>
</optgroup>
<optgroup label="Larger subnets">
<option value="255.255.254.0">/23</option>
<option value="255.255.252.0">/22</option>
<option value="255.255.0.0">/16</option>
</optgroup>

View File

@@ -31,7 +31,9 @@
<option value={13}>GPIO13</option> <option value={13}>GPIO13</option>
<option value={14}>GPIO14</option> <option value={14}>GPIO14</option>
<option value={15}>GPIO15</option> <option value={15}>GPIO15</option>
{#if chip == 'esp32s2'}
<option value={16}>GPIO16</option>
{/if}
{#if chip.startsWith('esp32')} {#if chip.startsWith('esp32')}
<option value={17}>GPIO17</option> <option value={17}>GPIO17</option>
{#if chip != 'esp32s2'} {#if chip != 'esp32s2'}

View File

@@ -6,6 +6,7 @@ static const char HEADER_LOCATION[] PROGMEM = "Location";
static const char CACHE_CONTROL_NO_CACHE[] PROGMEM = "no-cache, no-store, must-revalidate"; static const char CACHE_CONTROL_NO_CACHE[] PROGMEM = "no-cache, no-store, must-revalidate";
static const char CACHE_1HR[] PROGMEM = "public, max-age=3600"; static const char CACHE_1HR[] PROGMEM = "public, max-age=3600";
static const char CACHE_1MO[] PROGMEM = "public, max-age=2592000";
static const char PRAGMA_NO_CACHE[] PROGMEM = "no-cache"; static const char PRAGMA_NO_CACHE[] PROGMEM = "no-cache";
static const char EXPIRES_OFF[] PROGMEM = "-1"; static const char EXPIRES_OFF[] PROGMEM = "-1";
static const char AUTHENTICATE_BASIC[] PROGMEM = "Basic realm=\"Secure Area\""; static const char AUTHENTICATE_BASIC[] PROGMEM = "Basic realm=\"Secure Area\"";

View File

@@ -241,10 +241,12 @@ void AmsWebServer::sysinfoJson() {
config->getUiConfig(ui); config->getUiConfig(ui);
String meterModel = meterState->getMeterModel(); String meterModel = meterState->getMeterModel();
meterModel.replace("\\", "\\\\"); if(!meterModel.isEmpty())
meterModel.replace("\\", "\\\\");
String meterId = meterState->getMeterId(); String meterId = meterState->getMeterId();
meterId.replace("\\", "\\\\"); if(!meterId.isEmpty())
meterId.replace("\\", "\\\\");
int size = snprintf_P(buf, BufferSize, SYSINFO_JSON, int size = snprintf_P(buf, BufferSize, SYSINFO_JSON,
VERSION, VERSION,
@@ -356,7 +358,6 @@ void AmsWebServer::dataJson() {
} }
#endif #endif
uint8_t hanStatus; uint8_t hanStatus;
if(meterState->getLastError() != 0) { if(meterState->getLastError() != 0) {
hanStatus = 3; hanStatus = 3;
@@ -405,7 +406,7 @@ void AmsWebServer::dataJson() {
snprintf_P(buf, BufferSize, DATA_JSON, snprintf_P(buf, BufferSize, DATA_JSON,
maxPwr == 0 ? meterState->isThreePhase() ? 20000 : 10000 : maxPwr, maxPwr == 0 ? meterState->isThreePhase() ? 20000 : 10000 : maxPwr,
meterConfig->productionCapacity, meterConfig->productionCapacity,
meterConfig->mainFuse == 0 ? 32 : meterConfig->mainFuse, meterConfig->mainFuse == 0 ? 40 : meterConfig->mainFuse,
meterState->getActiveImportPower(), meterState->getActiveImportPower(),
meterState->getActiveExportPower(), meterState->getActiveExportPower(),
meterState->getReactiveImportPower(), meterState->getReactiveImportPower(),
@@ -452,7 +453,7 @@ void AmsWebServer::dataJson() {
ea->getCostThisMonth(), ea->getCostThisMonth(),
ea->getProducedThisMonth(), ea->getProducedThisMonth(),
ea->getIncomeThisMonth(), ea->getIncomeThisMonth(),
priceRegion.c_str(), eapi == NULL ? "" : priceRegion.c_str(),
meterState->getLastError(), meterState->getLastError(),
eapi == NULL ? 0 : eapi->getLastError(), eapi == NULL ? 0 : eapi->getLastError(),
(uint32_t) now, (uint32_t) now,
@@ -732,7 +733,7 @@ void AmsWebServer::indexCss() {
if(!checkSecurity(2)) if(!checkSecurity(2))
return; return;
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1HR); server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1MO);
server.setContentLength(INDEX_CSS_LEN); server.setContentLength(INDEX_CSS_LEN);
server.send_P(200, MIME_CSS, INDEX_CSS); server.send_P(200, MIME_CSS, INDEX_CSS);
} }
@@ -743,7 +744,7 @@ void AmsWebServer::indexJs() {
if(!checkSecurity(2)) if(!checkSecurity(2))
return; return;
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1HR); server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1MO);
server.setContentLength(INDEX_JS_LEN); server.setContentLength(INDEX_JS_LEN);
server.send_P(200, MIME_JS, INDEX_JS); server.send_P(200, MIME_JS, INDEX_JS);
} }
@@ -1045,16 +1046,18 @@ void AmsWebServer::handleSave() {
success = false; success = false;
} }
#endif #endif
config->setGpioConfig(*gpioConfig); if(success) {
config->setGpioConfig(*gpioConfig);
SystemConfig sys; SystemConfig sys;
config->getSystemConfig(sys); config->getSystemConfig(sys);
sys.boardType = success ? boardType : 0xFF; sys.boardType = success ? boardType : 0xFF;
sys.vendorConfigured = success; sys.vendorConfigured = success;
config->setSystemConfig(sys); config->setSystemConfig(sys);
}
} }
if(server.hasArg(F("s")) && server.arg(F("s")) == F("true")) { if(server.hasArg(F("s")) && server.arg(F("s")) == F("true") && server.hasArg(F("ss")) && !server.arg(F("ss")).isEmpty()) {
SystemConfig sys; SystemConfig sys;
config->getSystemConfig(sys); config->getSystemConfig(sys);

View File

@@ -122,6 +122,8 @@ DSMRParser *dsmrParser = NULL;
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
config.hasConfig(); // Need to run this to make sure all configuration have been migrated before we load GPIO config
if(!config.getGpioConfig(gpioConfig)) { if(!config.getGpioConfig(gpioConfig)) {
config.clearGpio(gpioConfig); config.clearGpio(gpioConfig);
} }
@@ -577,13 +579,14 @@ void loop() {
if(readHanPort() || now - meterState.getLastUpdateMillis() > 30000) { if(readHanPort() || now - meterState.getLastUpdateMillis() > 30000) {
if(now - lastTemperatureRead > 15000) { if(now - lastTemperatureRead > 15000) {
unsigned long start = millis(); unsigned long start = millis();
hw.updateTemperatures(); if(hw.updateTemperatures()) {
lastTemperatureRead = now; lastTemperatureRead = now;
if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) { if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) {
mqttHandler->publishTemperatures(&config, &hw); mqttHandler->publishTemperatures(&config, &hw);
}
debugD("Used %ld ms to update temperature", millis()-start);
} }
debugD("Used %ld ms to update temperature", millis()-start);
} }
if(now - lastSysupdate > 60000) { if(now - lastSysupdate > 60000) {
if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) { if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) {
@@ -597,8 +600,8 @@ void loop() {
meterState.setLastError(98); meterState.setLastError(98);
} }
try { try {
if(meterState.getLastError() > 0) { if(meterState.getListType() == 0) {
if(now - meterAutodetectLastChange > 15000 && (meterConfig.baud == 0 || meterConfig.parity == 0)) { if(now - meterAutodetectLastChange > 20000 && (meterConfig.baud == 0 || meterConfig.parity == 0)) {
meterAutodetect = true; meterAutodetect = true;
meterAutoIndex++; // Default is to try the first one in setup() meterAutoIndex++; // Default is to try the first one in setup()
debugI("Meter serial autodetect, swapping to: %d, %d, %s", bauds[meterAutoIndex], parities[meterAutoIndex], inverts[meterAutoIndex] ? "true" : "false"); debugI("Meter serial autodetect, swapping to: %d, %d, %s", bauds[meterAutoIndex], parities[meterAutoIndex], inverts[meterAutoIndex] ? "true" : "false");
@@ -607,7 +610,6 @@ void loop() {
meterAutodetectLastChange = now; meterAutodetectLastChange = now;
} }
} else if(meterAutodetect) { } else if(meterAutodetect) {
meterAutoIndex--; // Last one worked, so lets use that
debugI("Meter serial autodetected, saving: %d, %d, %s", bauds[meterAutoIndex], parities[meterAutoIndex], inverts[meterAutoIndex] ? "true" : "false"); debugI("Meter serial autodetected, saving: %d, %d, %s", bauds[meterAutoIndex], parities[meterAutoIndex], inverts[meterAutoIndex] ? "true" : "false");
meterAutodetect = false; meterAutodetect = false;
meterConfig.baud = bauds[meterAutoIndex]; meterConfig.baud = bauds[meterAutoIndex];
@@ -862,9 +864,9 @@ bool readHanPort() {
pos = unwrapData((uint8_t *) hanBuffer, ctx); pos = unwrapData((uint8_t *) hanBuffer, ctx);
if(ctx.type > 0 && pos >= 0) { if(ctx.type > 0 && pos >= 0) {
if(ctx.type == DATA_TAG_DLMS) { if(ctx.type == DATA_TAG_DLMS) {
debugV("Received valid DLMS at %d", pos); debugD("Received valid DLMS at %d", pos);
} else if(ctx.type == DATA_TAG_DSMR) { } else if(ctx.type == DATA_TAG_DSMR) {
debugV("Received valid DSMR at %d", pos); debugD("Received valid DSMR at %d", pos);
} else { } else {
// TODO: Move this so that payload is sent to MQTT // TODO: Move this so that payload is sent to MQTT
debugE("Unknown tag %02X at pos %d", ctx.type, pos); debugE("Unknown tag %02X at pos %d", ctx.type, pos);
@@ -879,7 +881,7 @@ bool readHanPort() {
meterState.setLastError(pos); meterState.setLastError(pos);
debugV("Unknown data payload:"); debugV("Unknown data payload:");
len = len + hanSerial->readBytes(hanBuffer+len, BUF_SIZE_HAN-len); len = len + hanSerial->readBytes(hanBuffer+len, BUF_SIZE_HAN-len);
debugPrint(hanBuffer, 0, len); if(Debug.isActive(RemoteDebug::VERBOSE)) debugPrint(hanBuffer, 0, len);
len = 0; len = 0;
return false; return false;
} }
@@ -962,7 +964,7 @@ bool readHanPort() {
bool saveData = false; bool saveData = false;
if(!ds.isHappy() && now > BUILD_EPOCH) { if(!ds.isHappy() && now > BUILD_EPOCH) {
debugV("Its time to update data storage"); debugD("Its time to update data storage");
tmElements_t tm; tmElements_t tm;
breakTime(now, tm); breakTime(now, tm);
if(tm.Minute == 0) { if(tm.Minute == 0) {