2024-04-06 11:34:04 +02:00

83 lines
2.4 KiB
C++

/**
* @copyright Utilitech AS 2023
* License: Fair Source
*
*/
#include "RealtimePlot.h"
#include <stdlib.h>
RealtimePlot::RealtimePlot() {
values = (int8_t*) malloc(REALTIME_SIZE);
scaling = (uint8_t*) malloc(REALTIME_SIZE);
memset(values, 0, REALTIME_SIZE);
memset(scaling, 0, REALTIME_SIZE);
}
void RealtimePlot::update(AmsData& data) {
unsigned long now = millis();
uint16_t pos = (now / REALTIME_SAMPLE) % REALTIME_SIZE;
if(lastMillis == 0) {
lastMillis = now;
lastReading = data.getActiveImportCounter() - data.getActiveExportCounter();
lastPos = pos;
return;
}
if(pos == lastPos && data.isCounterEstimated()) return;
unsigned long ms = now - lastMillis;
int32_t val; // A bit hacky this one, but just to avoid spikes at end of hour. Will mostly be correct
if(data.isCounterEstimated()) {
val = ((data.getActiveImportCounter() - data.getActiveExportCounter() - lastReading) * 1000) / (((float) ms) / 3600000.0);
} else {
val = data.getActiveImportPower() - data.getActiveExportPower();
}
uint8_t scale = 0;
int32_t update = val / pow(10, scale);
while(update > INT8_MAX || update < INT8_MIN) {
update = val / pow(10, ++scale);
}
if(pos < lastPos) {
for(uint16_t i = lastPos+1; i < REALTIME_SIZE; i++) {
values[i] = update;
scaling[i] = scale;
}
for(uint16_t i = 0; i <= pos; i++) {
values[i] = update;
scaling[i] = scale;
}
} else {
for(uint16_t i = lastPos+1; i <= pos; i++) {
values[i] = update;
scaling[i] = scale;
}
}
lastMillis = now;
lastReading = data.getActiveImportCounter() - data.getActiveExportCounter();
lastPos = pos;
}
int32_t RealtimePlot::getValue(uint16_t req) {
if(req > REALTIME_SIZE) return 0;
unsigned long now = millis();
if(req * REALTIME_SAMPLE > now) return 0;
unsigned long reqTime = now - (req * REALTIME_SAMPLE);
uint16_t pos = (now / REALTIME_SAMPLE) % REALTIME_SIZE;
uint16_t getPos;
if(reqTime > lastMillis) {
getPos = lastPos;
} else if(req > pos) {
getPos = REALTIME_SIZE + pos - req;
} else {
getPos = pos - req;
}
return values[getPos] * pow(10, scaling[getPos]);
}
int16_t RealtimePlot::getSize() {
return REALTIME_SIZE;
}