mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-05-22 21:39:41 +00:00
Support start and end date on prices
This commit is contained in:
@@ -47,13 +47,17 @@ struct PriceConfig {
|
||||
uint8_t days;
|
||||
uint32_t hours;
|
||||
uint8_t type;
|
||||
uint16_t value;
|
||||
uint32_t value;
|
||||
uint8_t start_month;
|
||||
uint8_t start_dayofmonth;
|
||||
uint8_t end_month;
|
||||
uint8_t end_dayofmonth;
|
||||
};
|
||||
|
||||
struct PricePart {
|
||||
char name[32];
|
||||
char description[32];
|
||||
uint16_t value;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
class PriceService {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "FirmwareVersion.h"
|
||||
#include <LittleFS.h>
|
||||
#include "AmsStorage.h"
|
||||
#include "hexutils.h"
|
||||
|
||||
#include "GcmParser.h"
|
||||
|
||||
@@ -112,13 +113,18 @@ float PriceService::getValueForHour(uint8_t direction, time_t ts, int8_t hour) {
|
||||
for (uint8_t i = 0; i < priceConfig.size(); i++) {
|
||||
PriceConfig pc = priceConfig.at(i);
|
||||
if(pc.type == PRICE_TYPE_FIXED) continue;
|
||||
if((pc.direction & direction) == direction && (pc.days & day) == day && (pc.hours & hrs) == hrs) {
|
||||
uint8_t start_month = pc.start_month == 0 || pc.start_month > 12 ? 1 : pc.start_month;
|
||||
uint8_t start_dayofmonth = pc.start_dayofmonth == 0 || pc.start_dayofmonth > 31 ? 1 : pc.start_dayofmonth;
|
||||
uint8_t end_month = pc.end_month == 0 || pc.end_month > 12 ? 1 : pc.end_month;
|
||||
uint8_t end_dayofmonth = pc.end_dayofmonth == 0 || pc.end_dayofmonth > 31 ? 1 : pc.end_dayofmonth;
|
||||
|
||||
if((pc.direction & direction) == direction && (pc.days & day) == day && (pc.hours & hrs) == hrs && tm.Month >= start_month && tm.Day >= start_dayofmonth && tm.Month <= end_month && tm.Day <= end_dayofmonth) {
|
||||
switch(pc.type) {
|
||||
case PRICE_TYPE_ADD:
|
||||
ret += pc.value / 10000.0;
|
||||
break;
|
||||
case PRICE_TYPE_PCT:
|
||||
ret += ((pc.value / 100.0) * ret) / 100.0;
|
||||
ret += ((pc.value / 10000.0) * ret) / 100.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -135,13 +141,17 @@ float PriceService::getEnergyPriceForHour(uint8_t direction, time_t ts, int8_t h
|
||||
float value = PRICE_NO_VALUE;
|
||||
for (uint8_t i = 0; i < priceConfig.size(); i++) {
|
||||
PriceConfig pc = priceConfig.at(i);
|
||||
if((pc.direction & direction) == direction && (pc.days & day) == day && (pc.hours & hrs) == hrs) {
|
||||
if(pc.type == PRICE_TYPE_FIXED) {
|
||||
if(value == PRICE_NO_VALUE) {
|
||||
value = pc.value / 10000.0;
|
||||
} else {
|
||||
value += pc.value / 10000.0;
|
||||
}
|
||||
if(pc.type != PRICE_TYPE_FIXED) continue;
|
||||
uint8_t start_month = pc.start_month == 0 || pc.start_month > 12 ? 1 : pc.start_month;
|
||||
uint8_t start_dayofmonth = pc.start_dayofmonth == 0 || pc.start_dayofmonth > 31 ? 1 : pc.start_dayofmonth;
|
||||
uint8_t end_month = pc.end_month == 0 || pc.end_month > 12 ? 1 : pc.end_month;
|
||||
uint8_t end_dayofmonth = pc.end_dayofmonth == 0 || pc.end_dayofmonth > 31 ? 1 : pc.end_dayofmonth;
|
||||
|
||||
if((pc.direction & direction) == direction && (pc.days & day) == day && (pc.hours & hrs) == hrs && tm.Month >= start_month && tm.Day >= start_dayofmonth && tm.Month <= end_month && tm.Day <= end_dayofmonth) {
|
||||
if(value == PRICE_NO_VALUE) {
|
||||
value = pc.value / 10000.0;
|
||||
} else {
|
||||
value += pc.value / 10000.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -526,6 +536,8 @@ std::vector<PriceConfig>& PriceService::getPriceConfig() {
|
||||
}
|
||||
|
||||
void PriceService::setPriceConfig(uint8_t index, PriceConfig &priceConfig) {
|
||||
stripNonAscii((uint8_t*) priceConfig.name, 32);
|
||||
|
||||
if(this->priceConfig.capacity() != index+1)
|
||||
this->priceConfig.resize(index+1);
|
||||
if(this->priceConfig.size() > index)
|
||||
|
||||
22
lib/SvelteUi/app/dist/index.js
vendored
22
lib/SvelteUi/app/dist/index.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { priceConfigStore, getPriceConfig } from './ConfigurationStore'
|
||||
import { wiki } from './Helpers.js';
|
||||
import { monthnames, wiki, zeropad } from './Helpers.js';
|
||||
import Mask from './Mask.svelte'
|
||||
import HelpIcon from './HelpIcon.svelte';
|
||||
import TrashIcon from './TrashIcon.svelte';
|
||||
@@ -35,6 +35,11 @@
|
||||
data.append("ra"+i, e.a);
|
||||
data.append("rh"+i, e.h);
|
||||
data.append("rv"+i, e.v);
|
||||
|
||||
data.append("rsm"+i, e.s.m);
|
||||
data.append("rsd"+i, e.s.d);
|
||||
data.append("rem"+i, e.e.m);
|
||||
data.append("red"+i, e.e.d);
|
||||
});
|
||||
|
||||
const response = await fetch('save', {
|
||||
@@ -66,7 +71,9 @@
|
||||
d: 3,
|
||||
a: [0,1,2,3,4,5,6,7],
|
||||
h: [0,1,2,3,4,5,6,7,8,9, 10,11,12,13,14,15,16,17,18,19, 20,21,22,23],
|
||||
v: 0.01
|
||||
v: 0.001,
|
||||
s: {m:0,d:0},
|
||||
e: {m:0,d:0}
|
||||
});
|
||||
configuration.o = arr
|
||||
};
|
||||
@@ -100,7 +107,7 @@
|
||||
<option value={1}>+</option>
|
||||
<option value={2}>%</option>
|
||||
</select>
|
||||
<input name="rv" type="number" class="in-l tr" style="width: 100px;" min="0.01" max="65.53" step="0.01" bind:value={c.v}/>
|
||||
<input name="rv" type="number" class="in-l tr" style="width: 100px;" min="0.0001" max="99.9999" step="0.0001" bind:value={c.v}/>
|
||||
</div>
|
||||
<div class="flex flex-wrap mr-3">
|
||||
<span class="mr-2">Days:</span>
|
||||
@@ -110,19 +117,54 @@
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap">
|
||||
<div class="flex flex-wrap mr-3">
|
||||
<span class="mr-2">Hours:</span>
|
||||
<div>
|
||||
{#each {length: 12} as _,i}
|
||||
<span class={c.h.includes(i) ? 'bd-on' : 'bd-off'} on:click={() => c.h = toggleDay(c.h, i)}>{i.toString().padStart(2,'0')}</span>
|
||||
{/each}
|
||||
</div>
|
||||
<div>
|
||||
{#each {length: 12} as _,i}
|
||||
<span class={c.h.includes(i+12) ? 'bd-on' : 'bd-off'} on:click={() => c.h = toggleDay(c.h, i+12)}>{(i+12).toString().padStart(2,'0')}</span>
|
||||
{/each}
|
||||
<div>
|
||||
{#each {length: 8} as _,i}
|
||||
<span class={c.h.includes(i) ? 'bd-on' : 'bd-off'} on:click={() => c.h = toggleDay(c.h, i)}>{i.toString().padStart(2,'0')}</span>
|
||||
{/each}
|
||||
</div>
|
||||
<div>
|
||||
{#each {length: 8} as _,i}
|
||||
<span class={c.h.includes(i+8) ? 'bd-on' : 'bd-off'} on:click={() => c.h = toggleDay(c.h, i+8)}>{(i+8).toString().padStart(2,'0')}</span>
|
||||
{/each}
|
||||
</div>
|
||||
<div>
|
||||
{#each {length: 8} as _,i}
|
||||
<span class={c.h.includes(i+16) ? 'bd-on' : 'bd-off'} on:click={() => c.h = toggleDay(c.h, i+16)}>{(i+16).toString().padStart(2,'0')}</span>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap mr-3">
|
||||
<select name="rsm" class="in-f" bind:value={c.s.m}>
|
||||
<option value={0}>-</option>
|
||||
{#each {length: 31} as _,i}
|
||||
<option value={i+1}>{i+1}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<select name="rsd" class="in-m" bind:value={c.s.d}>
|
||||
<option value={0}>-</option>
|
||||
{#each {length: 12} as _,i}
|
||||
<option value={i+1}>{monthnames[i]}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<input class="in-m" disabled value="to" style="width: 20px;color:#888;"/>
|
||||
<select name="rem" class="in-m" bind:value={c.e.m}>
|
||||
<option value={0}>-</option>
|
||||
{#each {length: 31} as _,i}
|
||||
<option value={i+1}>{i+1}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<select name="red" class="in-l" bind:value={c.e.d}>
|
||||
<option value={0}>-</option>
|
||||
{#each {length: 12} as _,i}
|
||||
<option value={i+1}>{monthnames[i]}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mt-1.5 ml-3">
|
||||
<span class="text-red-500 text-xs" on:click={() => deleteRow(rn)} on:keypress={() => deleteRow(rn)}><TrashIcon/></span>
|
||||
</div>
|
||||
|
||||
@@ -17,23 +17,23 @@ export default defineConfig({
|
||||
plugins: [svelte()],
|
||||
server: {
|
||||
proxy: {
|
||||
"/data.json": "http://192.168.233.187",
|
||||
"/energyprice.json": "http://192.168.233.187",
|
||||
"/dayplot.json": "http://192.168.233.187",
|
||||
"/monthplot.json": "http://192.168.233.187",
|
||||
"/temperature.json": "http://192.168.233.187",
|
||||
"/sysinfo.json": "http://192.168.233.187",
|
||||
"/configuration.json": "http://192.168.233.187",
|
||||
"/tariff.json": "http://192.168.233.187",
|
||||
"/realtime.json": "http://192.168.233.187",
|
||||
"/priceconfig.json": "http://192.168.233.187",
|
||||
"/save": "http://192.168.233.187",
|
||||
"/reboot": "http://192.168.233.187",
|
||||
"/configfile": "http://192.168.233.187",
|
||||
"/upgrade": "http://192.168.233.187",
|
||||
"/mqtt-ca": "http://192.168.233.187",
|
||||
"/mqtt-cert": "http://192.168.233.187",
|
||||
"/mqtt-key": "http://192.168.233.187",
|
||||
"/data.json": "http://192.168.233.115",
|
||||
"/energyprice.json": "http://192.168.233.115",
|
||||
"/dayplot.json": "http://192.168.233.115",
|
||||
"/monthplot.json": "http://192.168.233.115",
|
||||
"/temperature.json": "http://192.168.233.115",
|
||||
"/sysinfo.json": "http://192.168.233.115",
|
||||
"/configuration.json": "http://192.168.233.115",
|
||||
"/tariff.json": "http://192.168.233.115",
|
||||
"/realtime.json": "http://192.168.233.115",
|
||||
"/priceconfig.json": "http://192.168.233.115",
|
||||
"/save": "http://192.168.233.115",
|
||||
"/reboot": "http://192.168.233.115",
|
||||
"/configfile": "http://192.168.233.115",
|
||||
"/upgrade": "http://192.168.233.115",
|
||||
"/mqtt-ca": "http://192.168.233.115",
|
||||
"/mqtt-cert": "http://192.168.233.115",
|
||||
"/mqtt-key": "http://192.168.233.115",
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,5 +4,7 @@
|
||||
"d" : %d,
|
||||
"a" : [%s],
|
||||
"h" : [%s],
|
||||
"v" : %.4f
|
||||
"v" : %.4f,
|
||||
"s" : { "m":%d,"d":%d},
|
||||
"e" : { "m":%d,"d":%d}
|
||||
}%s
|
||||
@@ -1145,7 +1145,11 @@ void AmsWebServer::priceConfigJson() {
|
||||
p.direction,
|
||||
days.c_str(),
|
||||
hours.c_str(),
|
||||
p.value / 100.0,
|
||||
p.value / 10000.0,
|
||||
p.start_month,
|
||||
p.start_dayofmonth,
|
||||
p.end_month,
|
||||
p.end_dayofmonth,
|
||||
i == pc.size()-1 ? "" : ","
|
||||
);
|
||||
server.sendContent(buf);
|
||||
@@ -1717,7 +1721,7 @@ void AmsWebServer::handleSave() {
|
||||
snprintf_P(buf, BufferSize, PSTR("rd%d"), i);
|
||||
pc.direction = server.arg(buf).toInt();
|
||||
snprintf_P(buf, BufferSize, PSTR("rv%d"), i);
|
||||
pc.value = server.arg(buf).toFloat() * 100;
|
||||
pc.value = server.arg(buf).toFloat() * 10000;
|
||||
snprintf_P(buf, BufferSize, PSTR("rn%d"), i);
|
||||
String name = server.arg(buf);
|
||||
strcpy(pc.name, name.c_str());
|
||||
@@ -1746,6 +1750,18 @@ void AmsWebServer::handleSave() {
|
||||
h++;
|
||||
}
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("rsm%d"), i);
|
||||
pc.start_month = server.arg(buf).toInt();
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("rsd%d"), i);
|
||||
pc.start_dayofmonth = server.arg(buf).toInt();
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("rem%d"), i);
|
||||
pc.end_month = server.arg(buf).toInt();
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("red%d"), i);
|
||||
pc.end_dayofmonth = server.arg(buf).toInt();
|
||||
|
||||
ps->setPriceConfig(i, pc);
|
||||
}
|
||||
ps->save();
|
||||
|
||||
Reference in New Issue
Block a user