mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-12 00:02:53 +00:00
Added hour to tariff peaks (#1028)
* Added hour to tariff peaks * Some adjustments
This commit is contained in:
parent
c307103605
commit
46cd8c6e68
@ -13,6 +13,12 @@
|
||||
#include "PriceService.h"
|
||||
|
||||
struct EnergyAccountingPeak {
|
||||
uint8_t day;
|
||||
uint8_t hour;
|
||||
uint16_t value;
|
||||
};
|
||||
|
||||
struct EnergyAccountingPeak6 {
|
||||
uint8_t day;
|
||||
uint16_t value;
|
||||
};
|
||||
@ -32,34 +38,19 @@ struct EnergyAccountingData {
|
||||
EnergyAccountingPeak peaks[5];
|
||||
};
|
||||
|
||||
struct EnergyAccountingData5 {
|
||||
struct EnergyAccountingData6 {
|
||||
uint8_t version;
|
||||
uint8_t month;
|
||||
uint16_t costYesterday;
|
||||
uint16_t costThisMonth;
|
||||
uint16_t costLastMonth;
|
||||
uint16_t incomeYesterday;
|
||||
uint16_t incomeThisMonth;
|
||||
uint16_t incomeLastMonth;
|
||||
EnergyAccountingPeak peaks[5];
|
||||
};
|
||||
|
||||
struct EnergyAccountingData4 {
|
||||
uint8_t version;
|
||||
uint8_t month;
|
||||
uint16_t costYesterday;
|
||||
uint16_t costThisMonth;
|
||||
uint16_t costLastMonth;
|
||||
EnergyAccountingPeak peaks[5];
|
||||
};
|
||||
|
||||
struct EnergyAccountingData2 {
|
||||
uint8_t version;
|
||||
uint8_t month;
|
||||
uint16_t maxHour;
|
||||
uint16_t costYesterday;
|
||||
uint16_t costThisMonth;
|
||||
uint16_t costLastMonth;
|
||||
int32_t costYesterday;
|
||||
int32_t costThisMonth;
|
||||
int32_t costLastMonth;
|
||||
int32_t incomeYesterday;
|
||||
int32_t incomeThisMonth;
|
||||
int32_t incomeLastMonth;
|
||||
uint32_t lastMonthImport;
|
||||
uint32_t lastMonthExport;
|
||||
uint8_t lastMonthAccuracy;
|
||||
EnergyAccountingPeak6 peaks[5];
|
||||
};
|
||||
|
||||
struct EnergyAccountingRealtimeData {
|
||||
@ -142,7 +133,7 @@ private:
|
||||
String currency = "";
|
||||
|
||||
void calcDayCost();
|
||||
bool updateMax(uint16_t val, uint8_t day);
|
||||
bool updateMax(uint16_t val, uint8_t day, uint8_t hour);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -72,15 +72,15 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
||||
this->realtimeData->currentHour = local.Hour;
|
||||
this->realtimeData->currentDay = local.Day;
|
||||
if(!load()) {
|
||||
data = { 6, local.Month,
|
||||
data = { 7, local.Month,
|
||||
0, 0, 0, // Cost
|
||||
0, 0, 0, // Income
|
||||
0, 0, 0, // Last month import, export and accuracy
|
||||
0, 0, // Peak 1
|
||||
0, 0, // Peak 2
|
||||
0, 0, // Peak 3
|
||||
0, 0, // Peak 4
|
||||
0, 0 // Peak 5
|
||||
0, 0, 0, // Peak 1
|
||||
0, 0, 0, // Peak 2
|
||||
0, 0, 0, // Peak 3
|
||||
0, 0, 0, // Peak 4
|
||||
0, 0, 0 // Peak 5
|
||||
};
|
||||
}
|
||||
init = true;
|
||||
@ -97,7 +97,7 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
||||
uint16_t val = round(ds->getHourImport(oneHrAgo.Hour) / 10.0);
|
||||
|
||||
breakTime(tz->toLocal(now-3600), oneHrAgoLocal);
|
||||
ret |= updateMax(val, oneHrAgoLocal.Day);
|
||||
ret |= updateMax(val, oneHrAgoLocal.Day, oneHrAgoLocal.Hour);
|
||||
|
||||
this->realtimeData->currentHour = local.Hour; // Need to be defined here so that day cost is correctly calculated
|
||||
if(local.Hour > 0) {
|
||||
@ -407,85 +407,29 @@ bool EnergyAccounting::load() {
|
||||
char buf[file.size()];
|
||||
file.readBytes(buf, file.size());
|
||||
|
||||
if(buf[0] == 6) {
|
||||
if(buf[0] == 7) {
|
||||
EnergyAccountingData* data = (EnergyAccountingData*) buf;
|
||||
memcpy(&this->data, data, sizeof(this->data));
|
||||
ret = true;
|
||||
} else if(buf[0] == 5) {
|
||||
EnergyAccountingData5* data = (EnergyAccountingData5*) buf;
|
||||
this->data = { 6, data->month,
|
||||
((uint32_t) data->costYesterday) * 10,
|
||||
((uint32_t) data->costThisMonth) * 100,
|
||||
((uint32_t) data->costLastMonth) * 100,
|
||||
((uint32_t) data->incomeYesterday) * 10,
|
||||
((uint32_t) data->incomeThisMonth) * 100,
|
||||
((uint32_t) data->incomeLastMonth) * 100,
|
||||
0,0,0, // Last month import, export and accuracy
|
||||
data->peaks[0].day, data->peaks[0].value,
|
||||
data->peaks[1].day, data->peaks[1].value,
|
||||
data->peaks[2].day, data->peaks[2].value,
|
||||
data->peaks[3].day, data->peaks[3].value,
|
||||
data->peaks[4].day, data->peaks[4].value
|
||||
};
|
||||
ret = true;
|
||||
} else if(buf[0] == 4) {
|
||||
EnergyAccountingData4* data = (EnergyAccountingData4*) buf;
|
||||
this->data = { 5, data->month,
|
||||
((uint32_t) data->costYesterday) * 10,
|
||||
((uint32_t) data->costThisMonth) * 100,
|
||||
((uint32_t) data->costLastMonth) * 100,
|
||||
0,0,0, // Income from production
|
||||
0,0,0, // Last month import, export and accuracy
|
||||
data->peaks[0].day, data->peaks[0].value,
|
||||
data->peaks[1].day, data->peaks[1].value,
|
||||
data->peaks[2].day, data->peaks[2].value,
|
||||
data->peaks[3].day, data->peaks[3].value,
|
||||
data->peaks[4].day, data->peaks[4].value
|
||||
};
|
||||
ret = true;
|
||||
} else if(buf[0] == 3) {
|
||||
EnergyAccountingData* data = (EnergyAccountingData*) buf;
|
||||
this->data = { 5, data->month,
|
||||
data->costYesterday * 10,
|
||||
} else if(buf[0] == 6) {
|
||||
EnergyAccountingData6* data = (EnergyAccountingData6*) buf;
|
||||
this->data = { 7, data->month,
|
||||
data->costYesterday,
|
||||
data->costThisMonth,
|
||||
data->costLastMonth,
|
||||
0,0,0, // Income from production
|
||||
0,0,0, // Last month import, export and accuracy
|
||||
data->peaks[0].day, data->peaks[0].value,
|
||||
data->peaks[1].day, data->peaks[1].value,
|
||||
data->peaks[2].day, data->peaks[2].value,
|
||||
data->peaks[3].day, data->peaks[3].value,
|
||||
data->peaks[4].day, data->peaks[4].value
|
||||
data->incomeYesterday,
|
||||
data->incomeThisMonth,
|
||||
data->incomeLastMonth,
|
||||
data->lastMonthImport,
|
||||
data->lastMonthExport,
|
||||
data->lastMonthAccuracy,
|
||||
data->peaks[0].day, 0, data->peaks[0].value,
|
||||
data->peaks[1].day, 0, data->peaks[1].value,
|
||||
data->peaks[2].day, 0, data->peaks[2].value,
|
||||
data->peaks[3].day, 0, data->peaks[3].value,
|
||||
data->peaks[4].day, 0, data->peaks[4].value
|
||||
};
|
||||
ret = true;
|
||||
} else {
|
||||
data = { 5, 0,
|
||||
0, 0, 0, // Cost
|
||||
0,0,0, // Income from production
|
||||
0,0,0, // Last month import, export and accuracy
|
||||
0, 0, // Peak 1
|
||||
0, 0, // Peak 2
|
||||
0, 0, // Peak 3
|
||||
0, 0, // Peak 4
|
||||
0, 0 // Peak 5
|
||||
};
|
||||
if(buf[0] == 2) {
|
||||
EnergyAccountingData2* data = (EnergyAccountingData2*) buf;
|
||||
this->data.month = data->month;
|
||||
this->data.costYesterday = data->costYesterday * 10;
|
||||
this->data.costThisMonth = data->costThisMonth;
|
||||
this->data.costLastMonth = data->costLastMonth;
|
||||
uint8_t b = 0;
|
||||
for(uint8_t i = sizeof(this->data); i < file.size(); i+=2) {
|
||||
this->data.peaks[b].day = b;
|
||||
memcpy(&this->data.peaks[b].value, buf+i, 2);
|
||||
b++;
|
||||
if(b >= config->hours || b >= 5) break;
|
||||
}
|
||||
ret = true;
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
@ -518,11 +462,12 @@ void EnergyAccounting::setData(EnergyAccountingData& data) {
|
||||
this->data = data;
|
||||
}
|
||||
|
||||
bool EnergyAccounting::updateMax(uint16_t val, uint8_t day) {
|
||||
bool EnergyAccounting::updateMax(uint16_t val, uint8_t day, uint8_t hour) {
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
if(data.peaks[i].day == day || data.peaks[i].day == 0) {
|
||||
if(val > data.peaks[i].value) {
|
||||
data.peaks[i].day = day;
|
||||
data.peaks[i].hour = hour;
|
||||
data.peaks[i].value = val;
|
||||
return true;
|
||||
}
|
||||
|
||||
12
lib/SvelteUi/app/dist/index.js
vendored
12
lib/SvelteUi/app/dist/index.js
vendored
File diff suppressed because one or more lines are too long
@ -61,7 +61,7 @@
|
||||
{#if !isNaN(yScale(tick.value))}
|
||||
<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' ? '85%' : ''}>{tick.label}</text>
|
||||
<text y="-4" x={tick.align == 'right' ? '90%' : ''}>{tick.label}</text>
|
||||
</g>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
@ -128,7 +128,7 @@
|
||||
{/if}
|
||||
{#if uiVisibility(sysinfo.ui.t, data.pr && (data.pr.startsWith("NO") || data.pr.startsWith("10YNO") || data.pr.startsWith('10Y1001A1001A4')))}
|
||||
<div class="cnt h-64">
|
||||
<TariffPeakChart title={translations.dashboard?.tariffpeak ?? "Tariff peaks"} tariffData={tariffData} translations={translations}/>
|
||||
<TariffPeakChart title={translations.dashboard?.tariffpeak ?? "Tariff peaks"} tariffData={tariffData} realtime={data.ea} translations={translations}/>
|
||||
</div>
|
||||
{/if}
|
||||
{#if uiVisibility(sysinfo.ui.l, data.hm == 1)}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { zeropad } from './Helpers.js';
|
||||
import { ampcol, zeropad } from './Helpers.js';
|
||||
import BarChart from './BarChart.svelte';
|
||||
|
||||
export let title;
|
||||
@ -12,6 +12,7 @@
|
||||
let min = 0;
|
||||
|
||||
export let tariffData;
|
||||
export let realtime;
|
||||
|
||||
$: {
|
||||
let i = 0;
|
||||
@ -24,16 +25,36 @@
|
||||
label: 0
|
||||
});
|
||||
|
||||
console.log(realtime);
|
||||
|
||||
if(tariffData && !isNaN(realtime?.h?.u)) {
|
||||
points.push({
|
||||
label: realtime.h.u.toFixed(2),
|
||||
value: realtime.h.u,
|
||||
title: realtime.h.u.toFixed(2) + ' kWh',
|
||||
color: ampcol(realtime.h.u/tariffData.c*100.0)
|
||||
});
|
||||
xTicks.push({
|
||||
label: translations.common?.now ?? "Now"
|
||||
});
|
||||
}
|
||||
|
||||
if(tariffData && tariffData.p) {
|
||||
for(i = 0; i < tariffData.p.length; i++) {
|
||||
let peak = tariffData.p[i];
|
||||
let daylabel = peak.d > 0 ? zeropad(peak.d) + "." + (translations.months ? translations.months?.[new Date().getMonth()] : zeropad(new Date().getMonth()+1)) : "-";
|
||||
let title = daylabel;
|
||||
if(!isNaN(peak.h))
|
||||
title = title + ' ' + zeropad(peak.h) + ':00';
|
||||
title = title + ': ' + peak.v.toFixed(2) + ' kWh';
|
||||
points.push({
|
||||
label: peak.v.toFixed(2),
|
||||
value: peak.v,
|
||||
title: title,
|
||||
color: dark ? '#5c2da5' : '#7c3aed'
|
||||
});
|
||||
xTicks.push({
|
||||
label: peak.d > 0 ? zeropad(peak.d) + "." + (translations.months ? translations.months?.[new Date().getMonth()] : zeropad(new Date().getMonth()+1)) : "-"
|
||||
label: daylabel
|
||||
})
|
||||
max = Math.max(max, peak.v);
|
||||
}
|
||||
@ -71,7 +92,7 @@
|
||||
config = {
|
||||
title: title,
|
||||
dark: document.documentElement.classList.contains('dark'),
|
||||
padding: { top: 20, right: 35, bottom: 20, left: 35 },
|
||||
padding: { top: 20, right: 20, bottom: 20, left: 20 },
|
||||
y: {
|
||||
min: min,
|
||||
max: max,
|
||||
|
||||
@ -17,27 +17,27 @@ export default defineConfig({
|
||||
plugins: [svelte()],
|
||||
server: {
|
||||
proxy: {
|
||||
"/data.json": "http://192.168.21.192",
|
||||
"/energyprice.json": "http://192.168.21.192",
|
||||
"/dayplot.json": "http://192.168.21.192",
|
||||
"/monthplot.json": "http://192.168.21.192",
|
||||
"/temperature.json": "http://192.168.21.192",
|
||||
"/sysinfo.json": "http://192.168.21.192",
|
||||
"/configuration.json": "http://192.168.21.192",
|
||||
"/tariff.json": "http://192.168.21.192",
|
||||
"/realtime.json": "http://192.168.21.192",
|
||||
"/priceconfig.json": "http://192.168.21.192",
|
||||
"/translations.json": "http://192.168.21.192",
|
||||
"/cloudkey.json": "http://192.168.21.192",
|
||||
"/wifiscan.json": "http://192.168.21.192",
|
||||
"/save": "http://192.168.21.192",
|
||||
"/reboot": "http://192.168.21.192",
|
||||
"/configfile": "http://192.168.21.192",
|
||||
"/upgrade": "http://192.168.21.192",
|
||||
"/mqtt-ca": "http://192.168.21.192",
|
||||
"/mqtt-cert": "http://192.168.21.192",
|
||||
"/mqtt-key": "http://192.168.21.192",
|
||||
"/logo.svg": "http://192.168.21.192",
|
||||
"/data.json": "http://192.168.21.122",
|
||||
"/energyprice.json": "http://192.168.21.122",
|
||||
"/dayplot.json": "http://192.168.21.122",
|
||||
"/monthplot.json": "http://192.168.21.122",
|
||||
"/temperature.json": "http://192.168.21.122",
|
||||
"/sysinfo.json": "http://192.168.21.122",
|
||||
"/configuration.json": "http://192.168.21.122",
|
||||
"/tariff.json": "http://192.168.21.122",
|
||||
"/realtime.json": "http://192.168.21.122",
|
||||
"/priceconfig.json": "http://192.168.21.122",
|
||||
"/translations.json": "http://192.168.21.122",
|
||||
"/cloudkey.json": "http://192.168.21.122",
|
||||
"/wifiscan.json": "http://192.168.21.122",
|
||||
"/save": "http://192.168.21.122",
|
||||
"/reboot": "http://192.168.21.122",
|
||||
"/configfile": "http://192.168.21.122",
|
||||
"/upgrade": "http://192.168.21.122",
|
||||
"/mqtt-ca": "http://192.168.21.122",
|
||||
"/mqtt-cert": "http://192.168.21.122",
|
||||
"/mqtt-key": "http://192.168.21.122",
|
||||
"/logo.svg": "http://192.168.21.122",
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -2097,8 +2097,9 @@ void AmsWebServer::tariffJson() {
|
||||
String peaks;
|
||||
for(uint8_t x = 0;x < min((uint8_t) 5, eac->hours); x++) {
|
||||
EnergyAccountingPeak peak = ea->getPeak(x+1);
|
||||
int len = snprintf_P(buf, BufferSize, PSTR("{\"d\":%d,\"v\":%.2f}"),
|
||||
int len = snprintf_P(buf, BufferSize, PSTR("{\"d\":%d,\"h\":%d,\"v\":%.2f}"),
|
||||
peak.day,
|
||||
peak.hour,
|
||||
peak.value / 100.0
|
||||
);
|
||||
buf[len] = '\0';
|
||||
@ -2592,7 +2593,7 @@ void AmsWebServer::configFileDownload() {
|
||||
EnergyAccountingConfig eac;
|
||||
config->getEnergyAccountingConfig(eac);
|
||||
EnergyAccountingData ead = ea->getData();
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("energyaccounting %d %d %.2f %.2f %.2f %.2f %.2f %.2f %d %.2f %d %.2f %d %.2f %d %.2f %d %.2f %.2f %.2f"),
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("energyaccounting %d %d %.2f %.2f %.2f %.2f %.2f %.2f %d %d %.2f %d %d %.2f %d %d %.2f %d %d %.2f %d %d %.2f %.2f %.2f"),
|
||||
ead.version,
|
||||
ead.month,
|
||||
ea->getCostYesterday(),
|
||||
@ -2602,14 +2603,19 @@ void AmsWebServer::configFileDownload() {
|
||||
ea->getIncomeThisMonth(),
|
||||
ea->getIncomeLastMonth(),
|
||||
ead.peaks[0].day,
|
||||
ead.peaks[0].hour,
|
||||
ead.peaks[0].value / 100.0,
|
||||
ead.peaks[1].day,
|
||||
ead.peaks[1].hour,
|
||||
ead.peaks[1].value / 100.0,
|
||||
ead.peaks[2].day,
|
||||
ead.peaks[2].hour,
|
||||
ead.peaks[2].value / 100.0,
|
||||
ead.peaks[3].day,
|
||||
ead.peaks[3].hour,
|
||||
ead.peaks[3].value / 100.0,
|
||||
ead.peaks[4].day,
|
||||
ead.peaks[4].hour,
|
||||
ead.peaks[4].value / 100.0,
|
||||
ea->getUseLastMonth(),
|
||||
ea->getProducedLastMonth()
|
||||
|
||||
@ -2164,11 +2164,11 @@ void configFileParse() {
|
||||
0, 0, 0, // Cost
|
||||
0, 0, 0, // Income
|
||||
0, 0, 0, // Last month import, export and accuracy
|
||||
0, 0, // Peak 1
|
||||
0, 0, // Peak 2
|
||||
0, 0, // Peak 3
|
||||
0, 0, // Peak 4
|
||||
0, 0 // Peak 5
|
||||
0, 0, 0, // Peak 1
|
||||
0, 0, 0, // Peak 2
|
||||
0, 0, 0, // Peak 3
|
||||
0, 0, 0, // Peak 4
|
||||
0, 0, 0 // Peak 5
|
||||
};
|
||||
uint8_t peak = 0;
|
||||
uint64_t totalImport = 0, totalExport = 0;
|
||||
@ -2184,7 +2184,7 @@ void configFileParse() {
|
||||
} else if(i == 2) {
|
||||
float val = String(pch).toFloat();
|
||||
if(val > 0.0) {
|
||||
ead.peaks[0] = { 1, (uint16_t) (val*100) };
|
||||
ead.peaks[0] = { 1, 0, (uint16_t) (val*100) };
|
||||
}
|
||||
} else if(i == 3) {
|
||||
float val = String(pch).toFloat();
|
||||
@ -2196,7 +2196,6 @@ void configFileParse() {
|
||||
float val = String(pch).toFloat();
|
||||
ead.costLastMonth = val * 100;
|
||||
} else if(i >= 6 && i < 18) {
|
||||
uint8_t hour = i-6;
|
||||
{
|
||||
long val = String(pch).toInt();
|
||||
ead.peaks[peak].day = val;
|
||||
@ -2209,6 +2208,47 @@ void configFileParse() {
|
||||
}
|
||||
peak++;
|
||||
}
|
||||
} else if(ead.version < 7) {
|
||||
if(i == 1) {
|
||||
long val = String(pch).toInt();
|
||||
ead.month = val;
|
||||
} else if(i == 2) {
|
||||
float val = String(pch).toFloat();
|
||||
ead.costYesterday = val * 100;
|
||||
} else if(i == 3) {
|
||||
float val = String(pch).toFloat();
|
||||
ead.costThisMonth = val * 100;
|
||||
} else if(i == 4) {
|
||||
float val = String(pch).toFloat();
|
||||
ead.costLastMonth = val * 100;
|
||||
} else if(i == 5) {
|
||||
float val = String(pch).toFloat();
|
||||
ead.incomeYesterday= val * 100;
|
||||
} else if(i == 6) {
|
||||
float val = String(pch).toFloat();
|
||||
ead.incomeThisMonth = val * 100;
|
||||
} else if(i == 7) {
|
||||
float val = String(pch).toFloat();
|
||||
ead.incomeLastMonth = val * 100;
|
||||
} else if(i >= 8 && i < 18) {
|
||||
{
|
||||
long val = String(pch).toInt();
|
||||
ead.peaks[peak].day = val;
|
||||
}
|
||||
pch = strtok (NULL, " ");
|
||||
i++;
|
||||
{
|
||||
float val = String(pch).toFloat();
|
||||
ead.peaks[peak].value = val * 100;
|
||||
}
|
||||
peak++;
|
||||
} else if(i == 18) {
|
||||
float val = String(pch).toFloat();
|
||||
totalImport = val * 1000;
|
||||
} else if(i == 19) {
|
||||
float val = String(pch).toFloat();
|
||||
totalExport = val * 1000;
|
||||
}
|
||||
} else {
|
||||
if(i == 1) {
|
||||
long val = String(pch).toInt();
|
||||
@ -2231,14 +2271,19 @@ void configFileParse() {
|
||||
} else if(i == 7) {
|
||||
float val = String(pch).toFloat();
|
||||
ead.incomeLastMonth = val * 100;
|
||||
} else if(i >= 8 && i < 18) {
|
||||
uint8_t hour = i-8;
|
||||
} else if(i >= 8 && i < 23) {
|
||||
{
|
||||
long val = String(pch).toInt();
|
||||
ead.peaks[peak].day = val;
|
||||
}
|
||||
pch = strtok (NULL, " ");
|
||||
i++;
|
||||
{
|
||||
long val = String(pch).toInt();
|
||||
ead.peaks[peak].hour = val;
|
||||
}
|
||||
pch = strtok (NULL, " ");
|
||||
i++;
|
||||
{
|
||||
float val = String(pch).toFloat();
|
||||
ead.peaks[peak].value = val * 100;
|
||||
@ -2265,7 +2310,7 @@ void configFileParse() {
|
||||
ead.lastMonthImport = importUpdate;
|
||||
ead.lastMonthExport = exportUpdate;
|
||||
|
||||
ead.version = 6;
|
||||
ead.version = 7;
|
||||
ea.setData(ead);
|
||||
sEa = true;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user