Support start and end date on prices

This commit is contained in:
Gunnar Skjold
2024-01-06 18:58:50 +01:00
parent bad107926c
commit 48ab87ba50
7 changed files with 130 additions and 54 deletions

View File

@@ -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 {

View File

@@ -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)

File diff suppressed because one or more lines are too long

View File

@@ -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>

View File

@@ -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",
}
}
})

View File

@@ -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

View File

@@ -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();