More v2.2

This commit is contained in:
Gunnar Skjold 2022-11-29 20:20:56 +01:00
parent 2dcc874592
commit 02ae3fc7f5
11 changed files with 145 additions and 62 deletions

View File

@ -860,12 +860,13 @@ bool AmsConfiguration::relocateConfig96() {
EEPROM.get(CONFIG_NTP_START, ntp96);
ntp.enable = ntp96.enable;
ntp.dhcp = ntp96.dhcp;
if(ntp96.offset == 0 && ntp96.summerOffset == 0) {
strcpy(ntp.timezone, "GMT");
} else if(ntp96.offset == 360 && ntp96.summerOffset == 360) {
if(ntp96.offset == 360 && ntp96.summerOffset == 360) {
strcpy(ntp.timezone, "Europe/Oslo");
} else {
strcpy(ntp.timezone, "GMT");
}
EEPROM.get(CONFIG_NTP_START, ntp);
strcpy(ntp.server, ntp96.server);
EEPROM.put(CONFIG_NTP_START, ntp);
EEPROM.put(EEPROM_CONFIG_ADDRESS, 100);
bool ret = EEPROM.commit();

View File

@ -373,7 +373,7 @@ bool HwTools::ledBlink(uint8_t color, uint8_t blink) {
if(!ledOn(color)) return false;
delay(75);
ledOff(color);
delay(75);
if(i != blink) delay(75);
}
return true;
}

View File

@ -1,5 +1,5 @@
<script>
import { Router, Route } from "svelte-navigator";
import { Router, Route, navigate } from "svelte-navigator";
import { getSysinfo, sysinfoStore, dataStore } from './lib/DataStores.js';
import Header from './lib/Header.svelte';
@ -10,10 +10,18 @@
import SetupPanel from './lib/SetupPanel.svelte';
import Mask from './lib/Mask.svelte';
import FileUploadComponent from "./lib/FileUploadComponent.svelte";
import ConsentComponent from "./lib/ConsentComponent.svelte";
let sysinfo = {};
sysinfoStore.subscribe(update => {
sysinfo = update;
if(sysinfo.vndcfg === false) {
navigate("/vendor");
} else if(sysinfo.usrcfg === false) {
navigate("/setup");
} else if(sysinfo.fwconsent === 0) {
navigate("/consent");
}
});
getSysinfo();
let data = {};
@ -26,13 +34,7 @@
<Router>
<Header data={data} sysinfo={sysinfo}/>
<Route path="/">
{#if sysinfo.vndcfg === false}
<VendorPanel sysinfo={sysinfo}/>
{:else if sysinfo.usrcfg === false}
<SetupPanel sysinfo={sysinfo}/>
{:else}
<Dashboard data={data}/>
{/if}
</Route>
<Route path="/configuration">
<ConfigurationPanel sysinfo={sysinfo}/>
@ -49,6 +51,15 @@
<Route path="/mqtt-key">
<FileUploadComponent title="private key" action="/mqtt-key"/>
</Route>
<Route path="/consent">
<ConsentComponent sysinfo={sysinfo}/>
</Route>
<Route path="/setup">
<SetupPanel sysinfo={sysinfo}/>
</Route>
<Route path="/vendor">
<VendorPanel sysinfo={sysinfo}/>
</Route>
</Router>
{#if sysinfo.upgrading}

View File

@ -26,7 +26,7 @@
@apply in-txt rounded-l-md
}
.in-m {
@apply in-txt border-l-0 w-full
@apply in-txt border-l-0
}
.in-l {
@apply in-txt border-l-0 rounded-r-md

View File

@ -36,7 +36,7 @@
{#each config.y.ticks as tick}
<g class="tick tick-{tick.value} tick-{tick.color}" transform="translate(0, {yScale(tick.value)})">
<line x2="100%"></line>
<text y="-4" x={tick.align == 'right' ? '90%' : ''}>{tick.label}</text>
<text y="-4" x={tick.align == 'right' ? '85%' : ''}>{tick.label}</text>
</g>
{/each}
</g>

View File

@ -11,7 +11,8 @@
export let sysinfo = {}
let loadingOrSaving = true;
let loading = true;
let saving = false;
let configuration = {
g: {
@ -50,7 +51,7 @@
configurationStore.subscribe(update => {
if(update.version) {
configuration = update;
loadingOrSaving = false;
loading = false;
}
});
getConfiguration();
@ -70,7 +71,7 @@
}
async function handleSubmit(e) {
loadingOrSaving = true;
saving = true;
const formData = new FormData(e.target);
const data = new URLSearchParams();
for (let field of formData) {
@ -89,7 +90,7 @@
return s;
});
loadingOrSaving = false;
saving = false;
navigate("/");
}
@ -176,18 +177,18 @@
</div>
<div class="my-1">
<div class="flex">
<div>
<div class="w-1/2">
Currency<br/>
<select name="pc" bind:value={configuration.p.c} class="in-f">
<select name="pc" bind:value={configuration.p.c} class="in-f w-full">
<option value="NOK">NOK</option>
<option value="SEK">SEK</option>
<option value="DKK">DKK</option>
<option value="EUR">EUR</option>
</select>
</div>
<div>
<div class="w-1/2">
Multiplier<br/>
<input name="pm" bind:value={configuration.p.m} type="number" min="0.001" max="1000" step="0.001" class="in-l tr"/>
<input name="pm" bind:value={configuration.p.m} type="number" min="0.001" max="1000" step="0.001" class="in-l tr w-full"/>
</div>
</div>
</div>
@ -256,14 +257,14 @@
<div class="mx-1">
Main fuse<br/>
<label class="flex">
<input name="mf" bind:value={configuration.m.f} type="number" min="5" max="255" class="in-f tr"/>
<input name="mf" bind:value={configuration.m.f} type="number" min="5" max="255" class="in-f tr w-full"/>
<span class="in-post">A</span>
</label>
</div>
<div class="mx-1">
Production<br/>
<label class="flex">
<input name="mr" bind:value={configuration.m.r} type="number" min="0" max="255" class="in-f tr"/>
<input name="mr" bind:value={configuration.m.r} type="number" min="0" max="255" class="in-f tr w-full"/>
<span class="in-post">kWp</span>
</label>
</div>
@ -293,11 +294,11 @@
</div>
<div class="w-1/4">
Volt<br/>
<input name="mmv" bind:value={configuration.m.m.v} type="number" min="0.00" max="655.35" step="0.01" class="in-m tr"/>
<input name="mmv" bind:value={configuration.m.m.v} type="number" min="0.00" max="655.35" step="0.01" class="in-m tr w-full"/>
</div>
<div class="w-1/4">
Amp<br/>
<input name="mma" bind:value={configuration.m.m.a} type="number" min="0.00" max="655.35" step="0.01" class="in-m tr"/>
<input name="mma" bind:value={configuration.m.m.a} type="number" min="0.00" max="655.35" step="0.01" class="in-m tr w-full"/>
</div>
<div class="w-1/4">
Acc.<br/>
@ -319,7 +320,7 @@
<input name="wp" bind:value={configuration.w.p} type="password" class="in-s"/>
</div>
<div class="my-1 flex">
<div>
<div class="w-1/2">
Power saving<br/>
<select name="wz" bind:value={configuration.w.z} class="in-s">
<option value={255}>Default</option>
@ -328,12 +329,12 @@
<option value={2}>Maximum</option>
</select>
</div>
<div class="ml-2">
<div class="ml-2 w-1/2">
Power<br/>
<label class="flex">
<input name="ww" bind:value={configuration.w.w} type="number" min="0" max="20.5" step="0.5" class="in-f tr"/>
<div class="flex">
<input name="ww" bind:value={configuration.w.w} type="number" min="0" max="20.5" step="0.5" class="in-f tr w-full"/>
<span class="in-post">dBm</span>
</label>
</div>
</div>
</div>
</div>
@ -347,7 +348,7 @@
<option value="dhcp">DHCP</option>
<option value="static">Static</option>
</select>
<input name="ni" bind:value={configuration.n.i} type="text" class="in-m" 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'}/>
<select name="ns" bind:value={configuration.n.s} class="in-l" disabled={configuration.n.m == 'dhcp'}>
<option value="255.255.255.0">/24</option>
<option value="255.255.0.0">/16</option>
@ -390,8 +391,8 @@
{/if}
<br/>
<div class="flex">
<input name="qh" bind:value={configuration.q.h} type="text" class="in-f w-full"/>
<input name="qp" bind:value={configuration.q.p} type="number" min="1024" max="65535" class="in-l tr"/>
<input name="qh" bind:value={configuration.q.h} type="text" class="in-f w-3/4"/>
<input name="qp" bind:value={configuration.q.p} type="number" min="1024" max="65535" class="in-l tr w-1/4"/>
</div>
</div>
{#if configuration.q.s.e}
@ -519,42 +520,42 @@
{#if sysinfo.board > 20}
<input type="hidden" name="i" value="true"/>
<div class="flex flex-wrap">
<div>
<div class="w-1/3">
HAN<br/>
<select name="ih" bind:value={configuration.i.h} class="in-f">
<select name="ih" bind:value={configuration.i.h} class="in-f w-full">
<UartSelectOptions chip={sysinfo.chip}/>
</select>
</div>
<div>
<div class="w-1/3">
AP button<br/>
<input name="ia" bind:value={configuration.i.a} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-m tr"/>
<input name="ia" bind:value={configuration.i.a} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-m tr w-full"/>
</div>
<div>
<div class="w-1/3">
LED<label class="ml-4"><input name="ili" value="true" bind:checked={configuration.i.l.i} type="checkbox" class="rounded mb-1"/> inv</label><br/>
<div class="flex">
<input name="ilp" bind:value={configuration.i.l.p} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-l tr"/>
<input name="ilp" bind:value={configuration.i.l.p} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-l tr w-full"/>
</div>
</div>
<div>
<div class="w-full">
RGB<label class="ml-4"><input name="iri" value="true" bind:checked={configuration.i.r.i} type="checkbox" class="rounded mb-1"/> inverted</label><br/>
<div class="flex">
<input name="irr" bind:value={configuration.i.r.r} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-f tr"/>
<input name="irg" bind:value={configuration.i.r.g} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-m tr"/>
<input name="irb" bind:value={configuration.i.r.b} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-l tr"/>
<input name="irr" bind:value={configuration.i.r.r} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-f tr w-1/3"/>
<input name="irg" bind:value={configuration.i.r.g} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-m tr w-1/3"/>
<input name="irb" bind:value={configuration.i.r.b} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-l tr w-1/3"/>
</div>
</div>
<div class="my-1">
<div class="my-1 w-1/3">
Temperature<br/>
<input name="itd" bind:value={configuration.i.t.d} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-f tr"/>
<input name="itd" bind:value={configuration.i.t.d} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-f tr w-full"/>
</div>
<div class="my-1">
<div class="my-1 pr-1 w-1/3">
Analog temp<br/>
<input name="ita" bind:value={configuration.i.t.a} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-l tr"/>
<input name="ita" bind:value={configuration.i.t.a} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-l tr w-full"/>
</div>
{#if sysinfo.chip != 'esp8266'}
<div class="my-1">
<div class="my-1 pl-1 w-1/3">
Vcc<br/>
<input name="ivp" bind:value={configuration.i.v.p} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-s tr"/>
<input name="ivp" bind:value={configuration.i.v.p} type="number" min="0" max={sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39} class="in-s tr w-full"/>
</div>
{/if}
{#if configuration.i.v.p > 0}
@ -571,18 +572,18 @@
{#if sysinfo.chip == 'esp8266'}
<input type="hidden" name="iv" value="true"/>
<div class="my-1 flex flex-wrap">
<div>
<div class="w-1/3">
Vcc offset<br/>
<input name="ivo" bind:value={configuration.i.v.o} type="number" min="0.0" max="3.5" step="0.01" class="in-f tr"/>
<input name="ivo" bind:value={configuration.i.v.o} type="number" min="0.0" max="3.5" step="0.01" class="in-f tr w-full"/>
</div>
<div>
<div class="w-1/3 pr-1">
Multiplier<br/>
<input name="ivm" bind:value={configuration.i.v.m} type="number" min="0.1" max="10" step="0.01" class="in-l tr"/>
<input name="ivm" bind:value={configuration.i.v.m} type="number" min="0.1" max="10" step="0.01" class="in-l tr w-full"/>
</div>
{#if sysinfo.board == 2 || sysinfo.board == 100}
<div>
<div class="w-1/3 pl-1">
Boot limit<br/>
<input name="ivb" bind:value={configuration.i.v.b} type="number" min="2.5" max="3.5" step="0.1" class="in-s tr"/>
<input name="ivb" bind:value={configuration.i.v.b} type="number" min="2.5" max="3.5" step="0.1" class="in-s tr w-full"/>
</div>
{/if}
</div>
@ -627,5 +628,7 @@
</div>
</div>
</form>
<Mask active={loadingOrSaving} message="Loading configuration"/>
<Mask active={loading} message="Loading configuration"/>
<Mask active={saving} message="Saving configuration"/>
<Mask active={isFactoryReset} message="Device have been factory reset and switched to AP mode"/>

View File

@ -0,0 +1,54 @@
<script>
import { sysinfoStore } from './DataStores.js';
import Mask from './Mask.svelte'
import { navigate } from 'svelte-navigator';
export let sysinfo = {}
let loadingOrSaving = false;
async function handleSubmit(e) {
loadingOrSaving = true;
const formData = new FormData(e.target)
const data = new URLSearchParams()
for (let field of formData) {
const [key, value] = field
data.append(key, value)
}
const response = await fetch('/save', {
method: 'POST',
body: data
});
let res = (await response.json())
loadingOrSaving = false;
sysinfoStore.update(s => {
s.fwconsent = formData['sf'] === true ? 1 : formData['sf'] === false ? 2 : 0;
s.booting = res.reboot;
return s;
});
navigate("/");
}
</script>
<div class="grid xl:grid-cols-3 lg:grid-cols-2">
<div class="cnt">
<form on:submit|preventDefault={handleSubmit}>
<div>
Below are some stuff we need to know
</div>
<hr/>
<div class="my-3">
Enable one-click upgrade? (implies data collection)<br/>
<a href="https://github.com/gskjold/AmsToMqttBridge/wiki/Data-collection-on-one-click-firmware-upgrade" target="_blank" class="text-blue-600 hover:text-blue-800">Read more</a><br/>
<label><input type="radio" name="sf" value={1} checked={sysinfo.fwconsent === 1} class="rounded m-2" required/> Yes</label><label><input type="radio" name="sf" value={2} checked={sysinfo.fwconsent === 2} class="rounded m-2" required/> No</label><br/>
</div>
<div class="my-3">
<button type="submit" class="btn-pri">Save</button>
</div>
</form>
</div>
</div>
<Mask active={loadingOrSaving} message="Saving preferences"/>

View File

@ -3,6 +3,7 @@
import { getSysinfo, gitHubReleaseStore, sysinfoStore } from './DataStores.js';
import { upgrade, getNextVersion } from './UpgradeHelper';
import DownloadIcon from './DownloadIcon.svelte';
import { Link } from 'svelte-navigator';
export let sysinfo;
@ -60,7 +61,10 @@
MAC: {sysinfo.mac}
</div>
<div class="my-2">
<button on:click={askReboot} class="text-xs py-1 px-2 rounded bg-yellow-500 text-white mr-3">Reboot</button>
<Link to="/consent">
<span class="text-xs py-1 px-2 rounded bg-blue-500 text-white mr-3 ">Change consents</span>
</Link>
<button on:click={askReboot} class="text-xs py-1 px-2 rounded bg-yellow-500 text-white mr-3 float-right">Reboot</button>
</div>
</div>
{#if sysinfo.meter}

View File

@ -59,7 +59,7 @@
if(tariffData && tariffData.c) {
yTicks.push({
label: tariffData.c.toFixed(1),
label: tariffData.c.toFixed(0),
color: 'orange',
value: tariffData.c,
});
@ -70,7 +70,7 @@
config = {
title: "Tariff peaks",
padding: { top: 20, right: 15, bottom: 20, left: 35 },
padding: { top: 20, right: 35, bottom: 20, left: 35 },
y: {
min: min,
max: max,

View File

@ -3,6 +3,7 @@
import BoardTypeSelectOptions from './BoardTypeSelectOptions.svelte';
import UartSelectOptions from './UartSelectOptions.svelte';
import Mask from './Mask.svelte'
import { navigate } from 'svelte-navigator';
export let sysinfo = {}
@ -28,6 +29,7 @@
s.booting = res.reboot;
return s;
});
navigate("/");
}
</script>

View File

@ -41,6 +41,9 @@ void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, Meter
server.on(F("/"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on(F("/configuration"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on(F("/status"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on(F("/consent"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on(F("/vendor"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on(F("/setup"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on(F("/mqtt-ca"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on(F("/mqtt-cert"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
server.on(F("/mqtt-key"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this));
@ -184,7 +187,7 @@ void AmsWebServer::sysinfoJson() {
#else
chipId = ESP.getChipId();
#endif
String chipIdStr = String(chipId, HEX);;
String chipIdStr = String(chipId, HEX);
doc[PSTR("chipId")] = chipIdStr;
doc[PSTR("mac")] = WiFi.macAddress();
@ -1033,6 +1036,11 @@ void AmsWebServer::handleSave() {
config->setSystemConfig(sys);
performRestart = true;
} else if(server.hasArg(F("sf")) && !server.arg(F("sf")).isEmpty()) {
SystemConfig sys;
config->getSystemConfig(sys);
sys.dataCollectionConsent = server.hasArg(F("sf")) && (server.arg(F("sf")) == F("true") || server.arg(F("sf")) == F("1")) ? 1 : 2;
config->setSystemConfig(sys);
}
if(server.hasArg(F("m")) && server.arg(F("m")) == F("true")) {
@ -1612,7 +1620,7 @@ void AmsWebServer::tariffJson() {
JsonArray peaks = doc.createNestedArray(PSTR("p"));
for(uint8_t x = 0;x < min((uint8_t) 5, eac->hours); x++) {
JsonObject p = peaks.createNestedObject();
EnergyAccountingPeak peak = ea->getPeak(x);
EnergyAccountingPeak peak = ea->getPeak(x+1);
p["d"] = peak.day;
p["v"] = peak.value / 100.0;
}