Compare commits

...

9 Commits

Author SHA1 Message Date
Gunnar Skjold
0093410e05 Removed kicad backup 2023-02-10 18:57:50 +01:00
Gunnar Skjold
ee63a606e8 Fixed voltage read issue 2023-02-10 18:55:55 +01:00
Gunnar Skjold
d0ccd2d007 Minor ui adjustment 2023-02-10 17:28:19 +01:00
Gunnar Skjold
bb2f74d1ca Various UI improvements 2023-02-06 18:20:48 +01:00
Gunnar Skjold
dfef18fa09 Updated Entsoe endpoint 2023-02-06 11:32:53 +01:00
Gunnar Skjold
485c21dc69 Removed unnecessary build flag 2023-02-06 10:59:40 +01:00
Gunnar Skjold
9ceb84bc9c C3 build 2023-02-06 07:46:34 +01:00
Gunnar Skjold
24e68428c4 Commited gui dist files 2023-02-05 19:26:48 +01:00
Gunnar Skjold
c2c5855e6a Fixed issue where authentication key got corrupted from configfile upload 2023-02-02 16:15:03 +01:00
27 changed files with 382 additions and 372 deletions

View File

@@ -284,7 +284,7 @@ PricesContainer* EntsoeApi::fetchPrices(time_t t) {
breakTime(tz->toUTC(e2), d2);
snprintf(buf, BufferSize, "%s?securityToken=%s&documentType=A44&periodStart=%04d%02d%02d%02d%02d&periodEnd=%04d%02d%02d%02d%02d&in_Domain=%s&out_Domain=%s",
"https://transparency.entsoe.eu/api", getToken(),
"https://web-api.tp.entsoe.eu/api", getToken(),
d1.Year+1970, d1.Month, d1.Day, d1.Hour, 00,
d2.Year+1970, d2.Month, d2.Day, d2.Hour, 00,
config->area, config->area);

View File

@@ -119,68 +119,96 @@ void HwTools::getAdcChannel(uint8_t pin, AdcConfig& config) {
config.unit = ADC_UNIT_1;
config.channel = ADC1_CHANNEL_4;
break;
#if defined(ADC1_CHANNEL_5_GPIO_NUM)
case ADC1_CHANNEL_5_GPIO_NUM:
config.unit = ADC_UNIT_1;
config.channel = ADC1_CHANNEL_5;
break;
#endif
#if defined(ADC1_CHANNEL_6_GPIO_NUM)
case ADC1_CHANNEL_6_GPIO_NUM:
config.unit = ADC_UNIT_1;
config.channel = ADC1_CHANNEL_6;
break;
#endif
#if defined(ADC1_CHANNEL_7_GPIO_NUM)
case ADC1_CHANNEL_7_GPIO_NUM:
config.unit = ADC_UNIT_1;
config.channel = ADC1_CHANNEL_7;
break;
#if defined(CONFIG_IDF_TARGET_ESP32S2)
#endif
#if defined(ADC1_CHANNEL_8_GPIO_NUM)
case ADC1_CHANNEL_8_GPIO_NUM:
config.unit = ADC_UNIT_1;
config.channel = ADC1_CHANNEL_8;
break;
#endif
#if defined(ADC1_CHANNEL_9_GPIO_NUM)
case ADC1_CHANNEL_9_GPIO_NUM:
config.unit = ADC_UNIT_1;
config.channel = ADC1_CHANNEL_9;
break;
#endif
#if defined(ADC2_CHANNEL_0_GPIO_NUM)
case ADC2_CHANNEL_0_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_0;
break;
#endif
#if defined(ADC2_CHANNEL_1_GPIO_NUM)
case ADC2_CHANNEL_1_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_1;
break;
#endif
#if defined(ADC2_CHANNEL_2_GPIO_NUM)
case ADC2_CHANNEL_2_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_2;
break;
#endif
#if defined(ADC2_CHANNEL_3_GPIO_NUM)
case ADC2_CHANNEL_3_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_3;
break;
#endif
#if defined(ADC2_CHANNEL_4_GPIO_NUM)
case ADC2_CHANNEL_4_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_4;
break;
#endif
#if defined(ADC2_CHANNEL_5_GPIO_NUM)
case ADC2_CHANNEL_5_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_5;
break;
#endif
#if defined(ADC2_CHANNEL_6_GPIO_NUM)
case ADC2_CHANNEL_6_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_6;
break;
#endif
#if defined(ADC2_CHANNEL_7_GPIO_NUM)
case ADC2_CHANNEL_7_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_7;
break;
#endif
#if defined(ADC2_CHANNEL_8_GPIO_NUM)
case ADC2_CHANNEL_8_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_8;
break;
#endif
#if defined(ADC2_CHANNEL_9_GPIO_NUM)
case ADC2_CHANNEL_9_GPIO_NUM:
config.unit = ADC_UNIT_2;
config.channel = ADC2_CHANNEL_9;
break;
#endif
}
#endif
}

View File

@@ -8,8 +8,6 @@ pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files

19
lib/SvelteUi/app/dist/favicon.svg vendored Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<title>Amsleser</title>
<g transform="translate(-29.5,-83)">
<circle r="4.8016944" cy="123.56455" cx="55.064552"
style="fill:none;stroke:#045c7c;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path d="m 41.298717,103.9049 a 24,24 0 0 1 27.531669,0"
style="fill:none;stroke:#045c7c;stroke-width:3.3;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path d="m 35.562952,95.713384 a 34,34 0 0 1 39.003199,-2e-6"
style="fill:none;stroke:#045c7c;stroke-width:3.3;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path d="m 47.034482,112.09642 a 14,14 0 0 1 16.06014,0"
style="fill:none;stroke:#045c7c;stroke-width:3.3;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle r="3" cy="105.99158" cx="38.181862"
style="fill:none;stroke:#045c7c;stroke-width:2.4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle r="3" cy="97.959579" cx="77.491386"
style="fill:none;stroke:#045c7c;stroke-width:2.4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

6
lib/SvelteUi/app/dist/github.svg vendored Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false">
<title>GitHub</title>
<path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="#f8f9fa" fill-rule="evenodd"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
lib/SvelteUi/app/dist/index.css vendored Normal file

File diff suppressed because one or more lines are too long

16
lib/SvelteUi/app/dist/index.html vendored Normal file
View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.svg">
<link rel="mask-icon" href="/favicon.svg" color="#000000">
<title>AMS reader</title>
<script type="module" crossorigin src="/index.js"></script>
<link rel="stylesheet" href="/index.css">
</head>
<body class="bg-gray-100">
<div id="app"></div>
</body>
</html>

13
lib/SvelteUi/app/dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -11,6 +11,10 @@
@apply bg-white m-2 p-2 rounded shadow-lg
}
.gwf {
@apply 2xl:col-span-6 xl:col-span-5 lg:col-span-4 md:col-span-3 sm:col-span-2 h-64
}
.in-pre {
@apply flex items-center bg-gray-100 rounded-l-md border border-r-0 border-gray-300 px-3 whitespace-nowrap text-sm
}
@@ -38,25 +42,28 @@
@apply text-right
}
.bd-grn {
.bd-green {
@apply my-auto bg-green-500 text-green-100 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded
}
.bd-ylo {
.bd-yellow {
@apply my-auto bg-yellow-500 text-yellow-100 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded
}
.bd-red {
@apply my-auto bg-red-500 text-red-100 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded
}
.bd-blu {
.bd-blue {
@apply my-auto bg-blue-500 text-blue-100 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded
}
.bd-gry {
.bd-gray {
@apply my-auto bg-gray-500 text-gray-100 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded
}
.btn-pri {
@apply py-2 px-4 rounded bg-blue-500 text-white mr-3
}
.btn-pri-sm {
@apply text-xs py-1 px-2 rounded bg-blue-500 text-white mr-3
}
.pl-root {
position: relative;

View File

@@ -1,7 +1,15 @@
<script>
import { fmtnum } from "./Helpers";
export let data;
export let currency;
export let hasExport;
let cols = 3
$: {
cols = currency ? 3 : 2;
}
</script>
<div class="mx-2 text-sm">
@@ -9,69 +17,50 @@
<br/><br/>
{#if data}
{#if hasExport && currency}
{#if hasExport}
<strong>Import</strong>
<div class="grid grid-cols-3 mb-3">
<div class="grid grid-cols-{cols} mb-3">
<div>Hour</div>
<div class="text-right">{data.h.u ? data.h.u.toFixed(2) : '-'} kWh</div>
<div class="text-right">{data.h.c ? data.h.c.toFixed(2) : '-'} {currency}</div>
<div class="text-right">{fmtnum(data.h.u,2)} kWh</div>
{#if currency}<div class="text-right">{fmtnum(data.h.c,2)} {currency}</div>{/if}
<div>Day</div>
<div class="text-right">{data.d.u ? data.d.u.toFixed(1) : '-'} kWh</div>
<div class="text-right">{data.d.c ? data.d.c.toFixed(1) : '-'} {currency}</div>
<div class="text-right">{fmtnum(data.d.u,1)} kWh</div>
{#if currency}<div class="text-right">{fmtnum(data.d.c,1)} {currency}</div>{/if}
<div>Month</div>
<div class="text-right">{data.m.u ? data.m.u.toFixed(0) : '-'} kWh</div>
<div class="text-right">{data.m.c ? data.m.c.toFixed(0) : '-'} {currency}</div>
<div class="text-right">{fmtnum(data.m.u)} kWh</div>
{#if currency}<div class="text-right">{fmtnum(data.m.c)} {currency}</div>{/if}
</div>
<strong>Export</strong>
<div class="grid grid-cols-3">
<div class="grid grid-cols-{cols}">
<div>Hour</div>
<div class="text-right">{data.h.p ? data.h.p.toFixed(2) : '-'} kWh</div>
<div class="text-right">{data.h.i ? data.h.i.toFixed(2) : '-'} {currency}</div>
<div class="text-right">{fmtnum(data.h.p,2)} kWh</div>
{#if currency}<div class="text-right">{fmtnum(data.h.i,2)} {currency}</div>{/if}
<div>Day</div>
<div class="text-right">{data.d.p ? data.d.p.toFixed(1) : '-'} kWh</div>
<div class="text-right">{data.d.i ? data.d.i.toFixed(1) : '-'} {currency}</div>
<div class="text-right">{fmtnum(data.d.p,1)} kWh</div>
{#if currency}<div class="text-right">{fmtnum(data.d.i,1)} {currency}</div>{/if}
<div>Month</div>
<div class="text-right">{data.m.p ? data.m.p.toFixed(0) : '-'} kWh</div>
<div class="text-right">{data.m.i ? data.m.i.toFixed(0) : '-'} {currency}</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 class="text-right">{fmtnum(data.m.p)} kWh</div>
{#if currency}<div class="text-right">{fmtnum(data.m.i)} {currency}</div>{/if}
</div>
{:else}
<strong>Consumption</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 class="text-right">{fmtnum(data.h.u,2)} kWh</div>
<div>Day</div>
<div class="text-right">{data.d.u ? data.d.u.toFixed(1) : '-'} kWh</div>
<div class="text-right">{fmtnum(data.d.u,1)} kWh</div>
<div>Month</div>
<div class="text-right">{data.m.u ? data.m.u.toFixed(0) : '-'} kWh</div>
<div class="text-right">{fmtnum(data.m.u)} kWh</div>
</div>
{#if currency}
<strong>Cost</strong>
<div class="grid grid-cols-2">
<div>Hour</div>
<div class="text-right">{data.h.c ? data.h.c.toFixed(2) : '-'} {currency}</div>
<div class="text-right">{fmtnum(data.h.c,2)} {currency}</div>
<div>Day</div>
<div class="text-right">{data.d.c ? data.d.c.toFixed(1) : '-'} {currency}</div>
<div class="text-right">{fmtnum(data.d.c,1)} {currency}</div>
<div>Month</div>
<div class="text-right">{data.m.c ? data.m.c.toFixed(0) : '-'} {currency}</div>
<div class="text-right">{fmtnum(data.m.c)} {currency}</div>
</div>
{/if}
{/if}

View File

@@ -1,6 +1,6 @@
<script>
import BarChart from './BarChart.svelte';
import { ampcol } from './Helpers.js';
import { ampcol, fmtnum } from './Helpers.js';
export let u1;
export let u2;
@@ -12,32 +12,28 @@
let config = {};
function point(v) {
return {
label: fmtnum(v) +'A',
value: isNaN(v) ? 0 : v,
color: ampcol(v ? (v)/(max)*100 : 0)
};
};
$: {
let xTicks = [];
let points = [];
if(u1 > 0) {
xTicks.push({ label: 'L1' });
points.push({
label: i1 ? (i1 > 10 ? i1.toFixed(0) : i1.toFixed(1)) + 'A' : '-',
value: i1 ? i1 : 0,
color: ampcol(i1 ? (i1)/(max)*100 : 0)
});
points.push(point(i1));
}
if(u2 > 0) {
xTicks.push({ label: 'L2' });
points.push({
label: i2 ? (i2 > 10 ? i2.toFixed(0) : i2.toFixed(1)) + 'A' : '-',
value: i2 ? i2 : 0,
color: ampcol(i2 ? (i2)/(max)*100 : 0)
});
points.push(point(i2));
}
if(u3 > 0) {
xTicks.push({ label: 'L3' });
points.push({
label: i3 ? (i3 > 10 ? i3.toFixed(0) : i3.toFixed(1)) + 'A' : '-',
value: i3 ? i3 : 0,
color: ampcol(i3 ? (i3)/(max)*100 : 0)
});
points.push(point(i3));
}
config = {
padding: { top: 20, right: 15, bottom: 20, left: 35 },

View File

@@ -3,14 +3,4 @@
export let title;
export let text;
</script>
{#if color == 'green'}
<span title={title} class="bd-grn">{text}</span>
{:else if color === `yellow`}
<span title={title} class="bd-ylo">{text}</span>
{:else if color === `red`}
<span title={title} class="bd-red">{text}</span>
{:else if color === `blue`}
<span title={title} class="bd-blu">{text}</span>
{:else if color === `gray`}
<span title={title} class="bd-gry">{text}</span>
{/if}
<span title={title} class="bd-{color}">{text}</span>

View File

@@ -1,6 +1,7 @@
<script>
import { getConfiguration, configurationStore } from './ConfigurationStore'
import { sysinfoStore } from './DataStores.js';
import { wiki } from './Helpers.js';
import UartSelectOptions from './UartSelectOptions.svelte';
import Mask from './Mask.svelte'
import Badge from './Badge.svelte';
@@ -12,6 +13,41 @@
export let sysinfo = {}
let uiElements = [{
name: 'Import gauge',
key: 'i'
},{
name: 'Export gauge',
key: 'e'
},{
name: 'Voltage',
key: 'v'
},{
name: 'Amperage',
key: 'a'
},{
name: 'Reactive',
key: 'r'
},{
name: 'Realtime',
key: 'c'
},{
name: 'Peaks',
key: 't'
},{
name: 'Price',
key: 'p'
},{
name: 'Day plot',
key: 'd'
},{
name: 'Month plot',
key: 'm'
},{
name: 'Temperature plot',
key: 's'
}];
let loading = true;
let saving = false;
@@ -133,13 +169,18 @@
if(configuration.q.p == 8883) configuration.q.p = 1883;
}
}
let gpioMax = 44;
$: {
gpioMax = sysinfo.chip == 'esp8266' ? 16 : sysinfo.chip == 'esp32s2' ? 44 : 39;
}
</script>
<form on:submit|preventDefault={handleSubmit} autocomplete="off">
<div class="grid xl:grid-cols-4 lg:grid-cols-2 md:grid-cols-2">
<div class="cnt">
<strong class="text-sm">General</strong>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/General-configuration" target="_blank" class="float-right"><HelpIcon/></a>
<a href="{wiki('General-configuration')}" target="_blank" class="float-right"><HelpIcon/></a>
<input type="hidden" name="g" value="true"/>
<div class="my-1">
<div class="flex">
@@ -149,7 +190,7 @@
</div>
<div>
Time zone<br/>
<select name="gt" bind:value={configuration.g.t} class="in-l">
<select name="gt" bind:value={configuration.g.t} class="in-l w-full">
<CountrySelectOptions/>
</select>
</div>
@@ -196,10 +237,9 @@
<div class="w-1/2">
Currency<br/>
<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>
{#each ["NOK","SEK","DKK","EUR"] as c}
<option value={c}>{c}</option>
{/each}
</select>
</div>
<div class="w-1/2">
@@ -235,20 +275,16 @@
</div>
<div class="cnt">
<strong class="text-sm">Meter</strong>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/Meter-configuration" target="_blank" class="float-right"><HelpIcon/></a>
<a href="{wiki('Meter-configuration')}" target="_blank" class="float-right"><HelpIcon/></a>
<input type="hidden" name="m" value="true"/>
<div class="my-1">
<span>Serial configuration</span>
<div class="flex">
<select name="mb" bind:value={configuration.m.b} class="in-f">
<option value={0} disabled={configuration.m.b != 0}>Autodetect</option>
<option value={2400}>2400</option>
<option value={4800}>4800</option>
<option value={9600}>9600</option>
<option value={19200}>19200</option>
<option value={38400}>38400</option>
<option value={57600}>57600</option>
<option value={115200}>115200</option>
{#each [24,48,96,192,384,576,1152] as b}
<option value={b*100}>{b*100}</option>
{/each}
</select>
<select name="mp" bind:value={configuration.m.p} class="in-l" disabled={configuration.m.b == 0}>
<option value={0} disabled={configuration.m.b != 0}>-</option>
@@ -324,7 +360,7 @@
</div>
<div class="cnt">
<strong class="text-sm">WiFi</strong>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/WiFi-configuration" target="_blank" class="float-right"><HelpIcon/></a>
<a href="{wiki('WiFi-configuration')}" target="_blank" class="float-right"><HelpIcon/></a>
<input type="hidden" name="w" value="true"/>
<div class="my-1">
SSID<br/>
@@ -358,7 +394,7 @@
</div>
<div class="cnt">
<strong class="text-sm">Network</strong>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/Network-configuration" target="_blank" class="float-right"><HelpIcon/></a>
<a href="{wiki('Network-configuration')}" target="_blank" class="float-right"><HelpIcon/></a>
<div class="my-1">
IP<br/>
<div class="flex">
@@ -398,7 +434,7 @@
</div>
<div class="cnt">
<strong class="text-sm">MQTT</strong>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/MQTT-configuration" target="_blank" class="float-right"><HelpIcon/></a>
<a href="{wiki('MQTT-configuration')}" target="_blank" class="float-right"><HelpIcon/></a>
<input type="hidden" name="q" value="true"/>
<div class="my-1">
Server
@@ -473,7 +509,7 @@
{#if configuration.q.m == 3}
<div class="cnt">
<strong class="text-sm">Domoticz</strong>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/MQTT-configuration#domoticz" target="_blank" class="float-right"><HelpIcon/></a>
<a href="{wiki('MQTT-configuration#domoticz')}" target="_blank" class="float-right"><HelpIcon/></a>
<input type="hidden" name="o" value="true"/>
<div class="my-1 flex">
<div class="w-1/2">
@@ -498,54 +534,16 @@
{#if configuration.p.r.startsWith("10YNO") || configuration.p.r == '10Y1001A1001A48H'}
<div class="cnt">
<strong class="text-sm">Tariff thresholds</strong>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/Threshold-configuration" target="_blank" class="float-right"><HelpIcon/></a>
<a href="{wiki('Threshold-configuration')}" target="_blank" class="float-right"><HelpIcon/></a>
<input type="hidden" name="t" value="true"/>
<div class="flex flex-wrap my-1">
{#each {length: 9} as _, i}
<label class="flex w-40 m-1">
<span class="in-pre">1</span>
<input name="t0" bind:value={configuration.t.t[0]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-post">kWh</span>
</label>
<label class="flex w-40 m-1">
<span class="in-pre">2</span>
<input name="t1" bind:value={configuration.t.t[1]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-post">kWh</span>
</label>
<label class="flex w-40 m-1">
<span class="in-pre">3</span>
<input name="t2" bind:value={configuration.t.t[2]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-post">kWh</span>
</label>
<label class="flex w-40 m-1">
<span class="in-pre">4</span>
<input name="t3" bind:value={configuration.t.t[3]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-post">kWh</span>
</label>
<label class="flex w-40 m-1">
<span class="in-pre">5</span>
<input name="t4" bind:value={configuration.t.t[4]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-post">kWh</span>
</label>
<label class="flex w-40 m-1">
<span class="in-pre">6</span>
<input name="t5" bind:value={configuration.t.t[5]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-post">kWh</span>
</label>
<label class="flex w-40 m-1">
<span class="in-pre">7</span>
<input name="t6" bind:value={configuration.t.t[6]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-post">kWh</span>
</label>
<label class="flex w-40 m-1">
<span class="in-pre">8</span>
<input name="t7" bind:value={configuration.t.t[7]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-post">kWh</span>
</label>
<label class="flex w-40 m-1">
<span class="in-pre">9</span>
<input name="t8" bind:value={configuration.t.t[8]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-pre">{i+1}</span>
<input name="t{i}" bind:value={configuration.t.t[i]} type="number" min="0" max="255" class="in-txt w-full"/>
<span class="in-post">kWh</span>
</label>
{/each}
</div>
<label class="flex m-1">
<span class="in-pre">Average of</span>
@@ -556,103 +554,25 @@
{/if}
<div class="cnt">
<strong class="text-sm">User interface</strong>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/User-interface" target="_blank" class="float-right"><HelpIcon/></a>
<a href="{wiki('User-interface')}" target="_blank" class="float-right"><HelpIcon/></a>
<input type="hidden" name="u" value="true"/>
<div class="flex flex-wrap">
<div class="w-1/2">
Import gauge<br/>
<select name="ui" bind:value={configuration.u.i} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Export gauge<br/>
<select name="ue" bind:value={configuration.u.e} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Voltage<br/>
<select name="uv" bind:value={configuration.u.v} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Amperage<br/>
<select name="ua" bind:value={configuration.u.a} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Reactive<br/>
<select name="ur" bind:value={configuration.u.r} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Realtime<br/>
<select name="uc" bind:value={configuration.u.c} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Peaks<br/>
<select name="ut" bind:value={configuration.u.t} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Price<br/>
<select name="up" bind:value={configuration.u.p} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Day plot<br/>
<select name="ud" bind:value={configuration.u.d} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Month plot<br/>
<select name="um" bind:value={configuration.u.m} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
<div class="w-1/2">
Temperature plot<br/>
<select name="us" bind:value={configuration.u.s} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
{#each uiElements as el}
<div class="w-1/2">
{el.name}<br/>
<select name="u{el.key}" bind:value={configuration.u[el.key]} class="in-s">
<option value={0}>Hide</option>
<option value={1}>Show</option>
<option value={2}>Dynamic</option>
</select>
</div>
{/each}
</div>
</div>
{#if sysinfo.board > 20 || sysinfo.chip == 'esp8266'}
<div class="cnt">
<strong class="text-sm">Hardware</strong>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/GPIO-configuration" target="_blank" class="float-right"><HelpIcon/></a>
<a href="{wiki('GPIO-configuration')}" target="_blank" class="float-right"><HelpIcon/></a>
{#if sysinfo.board > 20}
<input type="hidden" name="i" value="true"/>
<div class="flex flex-wrap">
@@ -664,34 +584,34 @@
</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 w-full"/>
<input name="ia" bind:value={configuration.i.a} type="number" min="0" max={gpioMax} class="in-m tr w-full"/>
</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 w-full"/>
<input name="ilp" bind:value={configuration.i.l.p} type="number" min="0" max={gpioMax} class="in-l tr w-full"/>
</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 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"/>
<input name="irr" bind:value={configuration.i.r.r} type="number" min="0" max={gpioMax} class="in-f tr w-1/3"/>
<input name="irg" bind:value={configuration.i.r.g} type="number" min="0" max={gpioMax} class="in-m tr w-1/3"/>
<input name="irb" bind:value={configuration.i.r.b} type="number" min="0" max={gpioMax} class="in-l tr w-1/3"/>
</div>
</div>
<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 w-full"/>
<input name="itd" bind:value={configuration.i.t.d} type="number" min="0" max={gpioMax} class="in-f tr w-full"/>
</div>
<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 w-full"/>
<input name="ita" bind:value={configuration.i.t.a} type="number" min="0" max={gpioMax} class="in-l tr w-full"/>
</div>
{#if sysinfo.chip != 'esp8266'}
<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 w-full"/>
<input name="ivp" bind:value={configuration.i.v.p} type="number" min="0" max={gpioMax} class="in-s tr w-full"/>
</div>
{/if}
{#if configuration.i.v.p > 0}

View File

@@ -2,6 +2,7 @@
import { sysinfoStore } from './DataStores.js';
import Mask from './Mask.svelte'
import { navigate } from 'svelte-navigator';
import { wiki } from './Helpers';
export let sysinfo = {}
@@ -41,7 +42,7 @@
<hr/>
<div class="my-3">
Enable one-click upgrade? (implies data collection)<br/>
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/Data-collection-on-one-click-firmware-upgrade" target="_blank" class="text-blue-600 hover:text-blue-800">Read more</a><br/>
<a href="{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">

View File

@@ -81,22 +81,22 @@
</div>
{/if}
{#if uiVisibility(sysinfo.ui.p, (typeof data.p == "number") && !Number.isNaN(data.p))}
<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">
<div class="cnt gwf">
<PricePlot json={prices}/>
</div>
{/if}
{#if uiVisibility(sysinfo.ui.d, dayPlot)}
<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">
<div class="cnt gwf">
<DayPlot json={dayPlot} />
</div>
{/if}
{#if uiVisibility(sysinfo.ui.m, monthPlot)}
<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">
<div class="cnt gwf">
<MonthPlot json={monthPlot} />
</div>
{/if}
{#if uiVisibility(sysinfo.ui.s, data.t && data.t != -127 && temperatures.c > 1)}
<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">
<div class="cnt gwf">
<TemperaturePlot json={temperatures} />
</div>
{/if}

View File

@@ -1,8 +1,8 @@
<script>
import { Link } from "svelte-navigator";
import { sysinfoStore, getGitHubReleases, gitHubReleaseStore } from './DataStores.js';
import { upgrade, getNextVersion } from './UpgradeHelper';
import { boardtype, hanError, mqttError, priceError, isBusPowered } from './Helpers.js';
import { upgrade, getNextVersion, upgradeWarningText } from './UpgradeHelper';
import { boardtype, hanError, mqttError, priceError, isBusPowered, wiki, bcol } from './Helpers.js';
import AmsleserSvg from "./../assets/favicon.svg";
import GitHubLogo from './../assets/github.svg';
import Uptime from "./Uptime.svelte";
@@ -20,7 +20,7 @@
function askUpgrade() {
if(confirm('Do you want to upgrade this device to ' + nextVersion.tag_name + '?')) {
if(!isBusPowered(sysinfo.board) || confirm('WARNING: ' + boardtype(sysinfo.chip, sysinfo.board) + ' must be connected to an external power supply during firmware upgrade. Failure to do so may cause power-down during upload resulting in non-functioning unit.')) {
if(!isBusPowered(sysinfo.board) || confirm(upgradeWarningText(boardtype(sysinfo.chip, sysinfo.board)))) {
sysinfoStore.update(s => {
s.upgrading = true;
return s;
@@ -54,10 +54,10 @@
<div class="flex-none my-auto">Free mem: {data.m ? (data.m/1000).toFixed(1) : '-'}kb</div>
</div>
<div class="flex-auto flex-wrap my-auto justify-center p-2">
<Badge title="ESP" text={sysinfo.booting ? 'Booting' : data.v > 2.0 ? data.v.toFixed(2)+"V" : "ESP"} color={sysinfo.booting ? 'yellow' : data.em === 1 ? 'green' : data.em === 2 ? 'yellow' : data.em === 3 ? 'red' : 'gray'}/>
<Badge title="HAN" text="HAN" color={sysinfo.booting ? 'gray' : data.hm === 1 ? 'green' : data.hm === 2 ? 'yellow' : data.hm === 3 ? 'red' : 'gray'}/>
<Badge title="WiFi" text={data.r ? data.r.toFixed(0)+"dBm" : "WiFi"} color={sysinfo.booting ? 'gray' : data.wm === 1 ? 'green' : data.wm === 2 ? 'yellow' : data.wm === 3 ? 'red' : 'gray'}/>
<Badge title="MQTT" text="MQTT" color={sysinfo.booting ? 'gray' : data.mm === 1 ? 'green' : data.mm === 2 ? 'yellow' : data.mm === 3 ? 'red' : 'gray'}/>
<Badge title="ESP" text={sysinfo.booting ? 'Booting' : data.v > 2.0 ? data.v.toFixed(2)+"V" : "ESP"} color={bcol(sysinfo.booting ? 2 : data.em)}/>
<Badge title="HAN" text="HAN" color={bcol(sysinfo.booting ? 9 : data.hm)}/>
<Badge title="WiFi" text={data.r ? data.r.toFixed(0)+"dBm" : "WiFi"} color={bcol(sysinfo.booting ? 9 : data.wm)}/>
<Badge title="MQTT" text="MQTT" color={bcol(sysinfo.booting ? 9 : data.mm)}/>
</div>
{#if data.he < 0 || data.he > 0}
<div class="bd-red">{ 'HAN: ' + hanError(data.he) }</div>
@@ -84,7 +84,7 @@
</div>
{/if}
<div class="flex-none px-1 mt-1" title="Documentation">
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki" target='_blank' rel="noreferrer"><HelpIcon/></a>
<a href={wiki('')} target='_blank' rel="noreferrer"><HelpIcon/></a>
</div>
{#if sysinfo.fwconsent === 1 && nextVersion}
<div class="flex-none mr-3 text-yellow-500" title="New version: {nextVersion.tag_name}">

View File

@@ -1,5 +1,9 @@
export let monthnames = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
export function bcol(num) {
return num === 1 ? 'green' : num === 2 ? 'yellow' : num === 3 ? 'red' : 'gray';
}
export function voltcol(volt) {
if(volt > 218 && volt < 242) return '#32d900';
if(volt > 212 && volt < 248) return '#b1d900';
@@ -160,3 +164,14 @@ export function isBusPowered(boardType) {
export function uiVisibility(choice, state) {
return choice == 1 || (choice == 2 && state);
}
export function wiki(page) {
return "https://github.com/UtilitechAS/amsreader-firmware/wiki/" + page;
}
export function fmtnum(v,d) {
if(isNaN(v)) return '-';
if(isNaN(d))
d = v < 10 ? 1 : 0;
return v.toFixed(d);
}

View File

@@ -5,8 +5,8 @@
export let exportTotal;
</script>
<div class="mx-2">
<strong class="text-sm">Reactive</strong>
<div class="mx-2 text-sm">
<strong>Reactive</strong>
<div class="grid grid-cols-2 mt-4">
<div>Instant in</div>

View File

@@ -1,13 +1,42 @@
<script>
import { metertype, boardtype, isBusPowered } from './Helpers.js';
import { getSysinfo, gitHubReleaseStore, sysinfoStore } from './DataStores.js';
import { upgrade, getNextVersion } from './UpgradeHelper';
import { upgrade, getNextVersion, upgradeWarningText } from './UpgradeHelper';
import DownloadIcon from './DownloadIcon.svelte';
import { Link } from 'svelte-navigator';
import Mask from './Mask.svelte';
export let data;
export let sysinfo;
let cfgItems = [{
name: 'WiFi',
key: 'iw'
},{
name: 'MQTT',
key: 'im'
},{
name: 'Web',
key: 'ie'
},{
name: 'Meter',
key: 'it'
},{
name: 'Thresholds',
key: 'ih'
},{
name: 'GPIO',
key: 'ig'
},{
name: 'Domoticz',
key: 'id'
},{
name: 'NTP',
key: 'in'
},{
name: 'Price API',
key: 'is'
}];
let nextVersion = {};
gitHubReleaseStore.subscribe(releases => {
@@ -19,7 +48,7 @@
function askUpgrade() {
if(confirm('Do you want to upgrade this device to ' + nextVersion.tag_name + '?')) {
if((sysinfo.board != 2 && sysinfo.board != 4 && sysinfo.board != 7) || confirm('WARNING: ' + boardtype(sysinfo.chip, sysinfo.board) + ' must be connected to an external power supply during firmware upgrade. Failure to do so may cause power-down during upload resulting in non-functioning unit.')) {
if((sysinfo.board != 2 && sysinfo.board != 4 && sysinfo.board != 7) || confirm(upgradeWarningText(boardtype(sysinfo.chip, sysinfo.board)))) {
sysinfoStore.update(s => {
s.upgrading = true;
return s;
@@ -64,7 +93,7 @@
Chip: {sysinfo.chip}
</div>
<div class="my-2">
Device: {boardtype(sysinfo.chip, sysinfo.board)}
Device: <Link to="/vendor">{boardtype(sysinfo.chip, sysinfo.board)}</Link>
</div>
<div class="my-2">
MAC: {sysinfo.mac}
@@ -76,7 +105,7 @@
{/if}
<div class="my-2">
<Link to="/consent">
<span class="text-xs py-1 px-2 rounded bg-blue-500 text-white mr-3 ">Update consents</span>
<span class="btn-pri-sm">Update 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>
@@ -129,13 +158,13 @@
</div>
{#if sysinfo.fwconsent === 2}
<div class="my-2">
<div class="bd-ylo">You have disabled one-click firmware upgrade, link to self-upgrade is disabled</div>
<div class="bd-yellow">You have disabled one-click firmware upgrade, link to self-upgrade is disabled</div>
</div>
{/if}
{/if}
{#if (sysinfo.security == 0 || data.a) && isBusPowered(sysinfo.board) }
<div class="bd-red">
{boardtype(sysinfo.chip, sysinfo.board)} must be connected to an external power supply during firmware upgrade. Failure to do so may cause power-down during upload resulting in non-functioning unit.
{upgradeWarningText(boardtype(sysinfo.chip, sysinfo.board))}
</div>
{/if}
{#if sysinfo.security == 0 || data.a}
@@ -143,10 +172,10 @@
<form action="/firmware" enctype="multipart/form-data" method="post" on:submit={() => firmwareUploading=true} autocomplete="off">
<input style="display:none" name="file" type="file" accept=".bin" bind:this={firmwareFileInput} bind:files={firmwareFiles}>
{#if firmwareFiles.length == 0}
<button type="button" on:click={()=>{firmwareFileInput.click();}} class="text-xs py-1 px-2 rounded bg-blue-500 text-white float-right mr-3">Select firmware file for upgrade</button>
<button type="button" on:click={()=>{firmwareFileInput.click();}} class="btn-pri-sm float-right">Select firmware file for upgrade</button>
{:else}
{firmwareFiles[0].name}
<button type="submit" class="ml-2 text-xs py-1 px-2 rounded bg-blue-500 text-white float-right mr-3">Upload</button>
<button type="submit" class="btn-pri-sm float-right">Upload</button>
{/if}
</form>
</div>
@@ -157,28 +186,22 @@
<strong class="text-sm">Configuration</strong>
<form method="get" action="/configfile.cfg" autocomplete="off">
<div class="grid grid-cols-2">
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="iw" value="true" checked/> WiFi</label>
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="im" value="true" checked/> MQTT</label>
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="ie" value="true" checked/> Web</label>
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="it" value="true" checked/> Meter</label>
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="ih" value="true" checked/> Thresholds</label>
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="ig" value="true" checked/> GPIO</label>
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="id" value="true" checked/> Domoticz</label>
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="in" value="true" checked/> NTP</label>
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="is" value="true" checked/> Price API</label>
{#each cfgItems as el}
<label class="my-1 mx-3"><input type="checkbox" class="rounded" name="{el.key}" value="true" checked/> {el.name}</label>
{/each}
<label class="my-1 mx-3 col-span-2"><input type="checkbox" class="rounded" name="ic" value="true"/> Include Secrets<br/><small>(SSID, PSK, passwords and tokens)</small></label>
</div>
{#if configFiles.length == 0}
<button type="submit" class="ml-2 text-xs py-1 px-2 rounded bg-blue-500 text-white float-right mr-3">Download</button>
<button type="submit" class="btn-pri-sm float-right">Download</button>
{/if}
</form>
<form action="/configfile" enctype="multipart/form-data" method="post" on:submit={() => configUploading=true} autocomplete="off">
<input style="display:none" name="file" type="file" accept=".cfg" bind:this={configFileInput} bind:files={configFiles}>
{#if configFiles.length == 0}
<button type="button" on:click={()=>{configFileInput.click();}} class="text-xs py-1 px-2 rounded bg-blue-500 text-white mr-3">Select file...</button>
<button type="button" on:click={()=>{configFileInput.click();}} class="btn-pri-sm">Select file...</button>
{:else}
{configFiles[0].name}
<button type="submit" class="ml-2 text-xs py-1 px-2 rounded bg-blue-500 text-white mr-3">Upload</button>
<button type="submit" class="btn-pri-sm">Upload</button>
{/if}
</form>
</div>

View File

@@ -1,5 +1,10 @@
<script>
export let chip;
let gpioMax = 44;
$: {
gpioMax = chip == 'esp8266' ? 16 : chip == 'esp32s2' ? 44 : 39;
}
</script>
<option value={3}>UART0</option>
@@ -13,48 +18,15 @@
{#if chip == 'esp32s2'}
<option value={18}>UART1</option>
{/if}
<option value={4}>GPIO4</option>
<option value={5}>GPIO5</option>
{#if chip.startsWith('esp32')}
<option value={6}>GPIO6</option>
<option value={7}>GPIO7</option>
<option value={8}>GPIO8</option>
{/if}
{#if chip == 'esp8266'}
<option value={9}>GPIO9</option>
{/if}
<option value={10}>GPIO10</option>
{#if chip.startsWith('esp32')}
<option value={11}>GPIO11</option>
{/if}
<option value={12}>GPIO12</option>
<option value={13}>GPIO13</option>
<option value={14}>GPIO14</option>
<option value={15}>GPIO15</option>
{#if chip == 'esp32s2'}
<option value={16}>GPIO16</option>
{/if}
{#if chip.startsWith('esp32')}
<option value={17}>GPIO17</option>
{#if chip != 'esp32s2'}
<option value={18}>GPIO18</option>
{/if}
<option value={19}>GPIO19</option>
<option value={21}>GPIO21</option>
<option value={22}>GPIO22</option>
<option value={23}>GPIO23</option>
<option value={25}>GPIO25</option>
<option value={32}>GPIO32</option>
<option value={33}>GPIO33</option>
<option value={34}>GPIO34</option>
<option value={35}>GPIO35</option>
<option value={36}>GPIO36</option>
<option value={39}>GPIO39</option>
{/if}
{#if chip == 'esp32s2'}
<option value={40}>GPIO40</option>
<option value={41}>GPIO41</option>
<option value={42}>GPIO42</option>
<option value={43}>GPIO43</option>
<option value={44}>GPIO44</option>
{#each {length: gpioMax+1} as _, i}
{#if i > 3
&& !(chip == 'esp32' && (i == 9 || i == 16))
&& !(chip == 'esp32s2' && i == 18)
&& !(chip == 'esp8266' && (i == 3 || i == 113))
}
<option value={i}>GPIO{i}</option>
{/if}
{/each}
{/if}

View File

@@ -1,31 +1,33 @@
export async function upgrade(version) {
const data = new URLSearchParams()
data.append('version', version.tag_name);
export function upgradeWarningText(board) {
return 'WARNING: ' + board + ' must be connected to an external power supply during firmware upgrade. Failure to do so may cause power-down during upload resulting in non-functioning unit.'
}
export async function upgrade() {
const response = await fetch('/upgrade', {
method: 'POST',
body: data
method: 'POST'
});
let res = (await response.json())
await response.json();
}
export function getNextVersion(currentVersion, releases) {
export function getNextVersion(currentVersion, releases_orig) {
if(/^v\d{1,2}\.\d{1,2}\.\d{1,2}$/.test(currentVersion)) {
var v = currentVersion.substring(1).split('.');
var v_major = parseInt(v[0]);
var v_minor = parseInt(v[1]);
var v_patch = parseInt(v[2]);
let v = currentVersion.substring(1).split('.');
let v_major = parseInt(v[0]);
let v_minor = parseInt(v[1]);
let v_patch = parseInt(v[2]);
let releases = [...releases_orig];
releases.reverse();
var next_patch;
var next_minor;
var next_major;
for(var i = 0; i < releases.length; i++) {
var release = releases[i];
var ver2 = release.tag_name;
var v2 = ver2.substring(1).split('.');
var v2_major = parseInt(v2[0]);
var v2_minor = parseInt(v2[1]);
var v2_patch = parseInt(v2[2]);
let next_patch;
let next_minor;
let next_major;
for(let i = 0; i < releases.length; i++) {
let release = releases[i];
let ver2 = release.tag_name;
let v2 = ver2.substring(1).split('.');
let v2_major = parseInt(v2[0]);
let v2_minor = parseInt(v2[1]);
let v2_patch = parseInt(v2[2]);
if(v2_major == v_major) {
if(v2_minor == v_minor) {
@@ -37,10 +39,10 @@ export function getNextVersion(currentVersion, releases) {
}
} else if(v2_major == v_major+1) {
if(next_major) {
var mv = next_major.tag_name.substring(1).split('.');
var mv_major = parseInt(mv[0]);
var mv_minor = parseInt(mv[1]);
var mv_patch = parseInt(mv[2]);
let mv = next_major.tag_name.substring(1).split('.');
let mv_major = parseInt(mv[0]);
let mv_minor = parseInt(mv[1]);
let mv_patch = parseInt(mv[2]);
if(v2_minor == mv_minor) {
next_major = release;
}
@@ -58,6 +60,6 @@ export function getNextVersion(currentVersion, releases) {
}
return false;
} else {
return releases[0];
return releases_orig[0];
}
}

View File

@@ -31,6 +31,11 @@
});
navigate(sysinfo.usrcfg ? "/" : "/setup");
}
let cc = false;
$: {
cc = !sysinfo.usrcfg;
}
</script>
<div class="grid xl:grid-cols-4 lg:grid-cols-3 md:grid-cols-2">
@@ -38,6 +43,9 @@
<form on:submit|preventDefault={handleSubmit} autocomplete="off">
<input type="hidden" name="v" value="true"/>
<strong class="text-sm">Initial configuration</strong>
{#if sysinfo.usrcfg}
<div class="bd-red">WARNING: Changing this configuration will affect basic configuration of your device. Only make changes here if instructed by vendor</div>
{/if}
<div class="my-3">
Board type<br/>
<select name="vb" bind:value={sysinfo.board} class="in-s">
@@ -53,7 +61,7 @@
</div>
{/if}
<div class="my-3">
<label><input type="checkbox" name="vr" value="true" class="rounded mb-1" checked /> Clear all other configuration</label>
<label><input type="checkbox" name="vr" value="true" class="rounded mb-1" bind:checked={cc} /> Clear all other configuration</label>
</div>
<div class="my-3">
<button type="submit" class="btn-pri">Save</button>

View File

@@ -1,48 +1,42 @@
<script>
import BarChart from './BarChart.svelte';
import { voltcol } from './Helpers.js';
import { fmtnum, voltcol } from './Helpers.js';
export let u1;
export let u2;
export let u3;
export let ds;
let min = 200;
let max = 260;
let config = {};
function point(v) {
return {
label: fmtnum(v) + 'V',
value: isNaN(v) ? 0 : v,
color: voltcol(v ? v : 0)
};
};
$: {
let xTicks = [];
let points = [];
if(u1 > 0) {
xTicks.push({ label: ds === 1 ? 'L1-L2' : 'L1' });
points.push({
label: u1 ? u1.toFixed(0) + 'V' : '-',
value: u1 ? u1 : 0,
color: voltcol(u1 ? u1 : 0)
});
points.push(point(u1));
}
if(u2 > 0) {
xTicks.push({ label: ds === 1 ? 'L1-L3' : 'L2' });
points.push({
label: u2 ? u2.toFixed(0) + 'V' : '-',
value: u2 ? u2 : 0,
color: voltcol(u2 ? u2 : 0)
});
points.push(point(u2));
}
if(u3 > 0) {
xTicks.push({ label: ds === 1 ? 'L2-L3' : 'L3' });
points.push({
label: u3 ? u3.toFixed(0) + 'V' : '-',
value: u3 ? u3 : 0,
color: voltcol(u3 ? u3 : 0)
});
points.push(point(u3));
}
config = {
padding: { top: 20, right: 15, bottom: 20, left: 35 },
y: {
min: min,
max: max,
min: 200,
max: 260,
ticks: [
{ value: 207, label: '-10%' },
{ value: 230, label: '230v' },

View File

@@ -17,18 +17,18 @@ export default defineConfig({
plugins: [svelte()],
server: {
proxy: {
"/data.json": "http://192.168.233.244",
"/energyprice.json": "http://192.168.233.244",
"/dayplot.json": "http://192.168.233.244",
"/monthplot.json": "http://192.168.233.244",
"/temperature.json": "http://192.168.233.244",
"/sysinfo.json": "http://192.168.233.244",
"/configuration.json": "http://192.168.233.244",
"/tariff.json": "http://192.168.233.244",
"/save": "http://192.168.233.244",
"/reboot": "http://192.168.233.244",
"/configfile": "http://192.168.233.244",
"/upgrade": "http://192.168.233.244"
"/data.json": "http://192.168.233.235",
"/energyprice.json": "http://192.168.233.235",
"/dayplot.json": "http://192.168.233.235",
"/monthplot.json": "http://192.168.233.235",
"/temperature.json": "http://192.168.233.235",
"/sysinfo.json": "http://192.168.233.235",
"/configuration.json": "http://192.168.233.235",
"/tariff.json": "http://192.168.233.235",
"/save": "http://192.168.233.235",
"/reboot": "http://192.168.233.235",
"/configfile": "http://192.168.233.235",
"/upgrade": "http://192.168.233.235"
}
}
})

View File

@@ -73,3 +73,15 @@ lib_compat_mode = off
lib_deps = ${esp32.lib_deps}
lib_ignore = ${common.lib_ignore}
extra_scripts = ${common.extra_scripts}
[env:esp32c3]
platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.5.3/platform-espressif32-2.0.5.3.zip
framework = arduino
board = esp32-c3-devkitm-1
board_build.mcu = esp32c3
build_flags = ${common.build_flags}
lib_ldf_mode = off
lib_compat_mode = off
lib_deps = ${esp32.lib_deps}
lib_ignore = ${common.lib_ignore}
extra_scripts = ${common.extra_scripts}

View File

@@ -1600,7 +1600,7 @@ void configFileParse() {
fromHex(meter.encryptionKey, String(buf+19), 16);
} else if(strncmp_P(buf, PSTR("meterAuthenticationKey "), 23) == 0) {
if(!lMeter) { config.getMeterConfig(meter); lMeter = true; };
fromHex(meter.authenticationKey, String(buf+19), 16);
fromHex(meter.authenticationKey, String(buf+23), 16);
} else if(strncmp_P(buf, PSTR("gpioHanPin "), 11) == 0) {
if(!lGpio) { config.getGpioConfig(gpio); lGpio = true; };
gpio.hanPin = String(buf+11).toInt();