mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-16 16:47:15 +00:00
83 lines
2.4 KiB
C++
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;
|
|
}
|