mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-04-15 00:38:00 +00:00
Added export to graph
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
#include "version.h"
|
||||
|
||||
AmsDataStorage::AmsDataStorage(RemoteDebug* debugger) {
|
||||
day.version = 3;
|
||||
month.version = 4;
|
||||
day.version = 4;
|
||||
month.version = 5;
|
||||
this->debugger = debugger;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,8 @@ bool AmsDataStorage::update(AmsData* data) {
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) {
|
||||
debugger->printf("(AmsDataStorage) Clearing hour: %d\n", i);
|
||||
}
|
||||
setHour(i, 0);
|
||||
setHourImport(i, 0);
|
||||
setHourExport(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +94,8 @@ bool AmsDataStorage::update(AmsData* data) {
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) {
|
||||
debugger->printf("(AmsDataStorage) Clearing day: %d\n", i);
|
||||
}
|
||||
setDay(i, 0);
|
||||
setDayImport(i, 0);
|
||||
setDayExport(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,21 +116,24 @@ bool AmsDataStorage::update(AmsData* data) {
|
||||
debugger->printf("(AmsDataStorage) Too long since last day update, clearing data\n");
|
||||
}
|
||||
for(int i = 0; i<24; i++) {
|
||||
setHour(i, 0);
|
||||
setHourImport(i, 0);
|
||||
setHourExport(i, 0);
|
||||
}
|
||||
} else if(now - day.lastMeterReadTime < 4000) {
|
||||
int16_t val = (((data->getActiveImportCounter() * 1000) - day.activeImport) - ((data->getActiveExportCounter() * 1000) - day.activeExport));
|
||||
setHour(utcYesterday.Hour, val);
|
||||
uint32_t imp = (data->getActiveImportCounter() * 1000) - day.activeImport;
|
||||
uint32_t exp = (data->getActiveExportCounter() * 1000) - day.activeExport;
|
||||
setHourImport(utcYesterday.Hour, imp);
|
||||
setHourExport(utcYesterday.Hour, exp);
|
||||
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(AmsDataStorage) Usage for hour %d: %d\n", ltzYesterDay.Hour, val);
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(AmsDataStorage) Usage for hour %d: %d - %d\n", ltzYesterDay.Hour, imp, exp);
|
||||
|
||||
day.activeImport = data->getActiveImportCounter() * 1000;
|
||||
day.activeExport = data->getActiveExportCounter() * 1000;
|
||||
day.lastMeterReadTime = now;
|
||||
} else {
|
||||
float mins = (now - day.lastMeterReadTime) / 60.0;
|
||||
uint16_t im = ((data->getActiveImportCounter() * 1000) - day.activeImport);
|
||||
uint16_t ex = ((data->getActiveExportCounter() * 1000) - day.activeExport);
|
||||
uint32_t im = (data->getActiveImportCounter() * 1000) - day.activeImport;
|
||||
uint32_t ex = (data->getActiveExportCounter() * 1000) - day.activeExport;
|
||||
float ipm = im / mins;
|
||||
float epm = ex / mins;
|
||||
|
||||
@@ -146,15 +151,17 @@ bool AmsDataStorage::update(AmsData* data) {
|
||||
if(minutes < 1) break;
|
||||
|
||||
breakTime(day.lastMeterReadTime, last);
|
||||
float val = ((ipm * minutes) - (epm * minutes));
|
||||
setHour(last.Hour, val);
|
||||
float imp = (ipm * minutes);
|
||||
float exp = (epm * minutes);
|
||||
setHourImport(last.Hour, imp);
|
||||
setHourExport(last.Hour, exp);
|
||||
|
||||
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||
debugger->printf("(AmsDataStorage) Estimated usage for hour %u: %.1f (%lld)\n", last.Hour, val, (int64_t) cur);
|
||||
debugger->printf("(AmsDataStorage) Estimated usage for hour %u: %.1f - %.1f (%lld)\n", last.Hour, imp, exp, (int64_t) cur);
|
||||
}
|
||||
|
||||
day.activeImport += ipm * minutes;
|
||||
day.activeExport += epm * minutes;
|
||||
day.activeImport += imp;
|
||||
day.activeExport += exp;
|
||||
day.lastMeterReadTime = cur;
|
||||
}
|
||||
}
|
||||
@@ -171,33 +178,23 @@ bool AmsDataStorage::update(AmsData* data) {
|
||||
debugger->printf("(AmsDataStorage) Too long since last month update, clearing data\n");
|
||||
}
|
||||
for(int i = 1; i<=31; i++) {
|
||||
setDay(i, 0);
|
||||
setDayImport(i, 0);
|
||||
setDayExport(i, 0);
|
||||
}
|
||||
} else if(now - month.lastMeterReadTime < 86500 && now - month.lastMeterReadTime > 86300) {
|
||||
int32_t val = (month.activeImport == 0 ? 0 : ((data->getActiveImportCounter() * 1000) - month.activeImport) - ((data->getActiveExportCounter() * 1000) - month.activeExport));
|
||||
int32_t imp = (data->getActiveImportCounter() * 1000) - month.activeImport;
|
||||
int32_t exp = (data->getActiveExportCounter() * 1000) - month.activeExport;
|
||||
|
||||
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||
debugger->printf("(AmsDataStorage) Usage for day %d: %d\n", ltzYesterDay.Day, val);
|
||||
debugger->printf("(AmsDataStorage) Usage for day %d: %d - %d\n", ltzYesterDay.Day, imp, exp);
|
||||
}
|
||||
|
||||
setDay(ltzYesterDay.Day, val);
|
||||
setDayImport(ltzYesterDay.Day, imp);
|
||||
setDayExport(ltzYesterDay.Day, exp);
|
||||
month.activeImport = data->getActiveImportCounter() * 1000;
|
||||
month.activeExport = data->getActiveExportCounter() * 1000;
|
||||
month.lastMeterReadTime = now;
|
||||
} else {
|
||||
float hrs = (now - month.lastMeterReadTime) / 3600.0;
|
||||
uint16_t im = ((data->getActiveImportCounter() * 1000) - month.activeImport);
|
||||
uint16_t ex = ((data->getActiveExportCounter() * 1000) - month.activeExport);
|
||||
float iph = im / hrs;
|
||||
float eph = ex / hrs;
|
||||
|
||||
// There is something wacky going on when it ends up here. The total value (im) is way way lower than it should be, which in
|
||||
// turn causes low values for all estimates. And then when it returns to the normal case above, the value is waaay higher.
|
||||
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("(AmsDataStorage) Since last month update, hours: %.1f, import: %d (%.2f/hr), export: %d (%.2f/hr)\n", hrs, im, iph, ex, eph);
|
||||
}
|
||||
|
||||
// Make sure last month read is at midnight
|
||||
tmElements_t last;
|
||||
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
||||
@@ -206,21 +203,33 @@ bool AmsDataStorage::update(AmsData* data) {
|
||||
debugger->printf("(AmsDataStorage) Last month read after resetting to midnight: %lld\n", (int64_t) month.lastMeterReadTime);
|
||||
}
|
||||
|
||||
float hrs = (now - month.lastMeterReadTime) / 3600.0;
|
||||
uint32_t im = (data->getActiveImportCounter() * 1000) - month.activeImport;
|
||||
uint32_t ex = (data->getActiveExportCounter() * 1000) - month.activeExport;
|
||||
float iph = im / hrs;
|
||||
float eph = ex / hrs;
|
||||
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("(AmsDataStorage) Since last month update, hours: %.1f, import: %d (%.2f/hr), export: %d (%.2f/hr)\n", hrs, im, iph, ex, eph);
|
||||
}
|
||||
|
||||
time_t stopAt = now - (ltz.Hour * 3600) - (ltz.Minute * 60) - ltz.Second;
|
||||
while(month.lastMeterReadTime < stopAt) {
|
||||
time_t cur = min(month.lastMeterReadTime + 86400, stopAt);
|
||||
uint8_t hours = round((cur - month.lastMeterReadTime) / 3600.0);
|
||||
|
||||
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
||||
float val = ((iph * hours) - (eph * hours));
|
||||
setDay(last.Day, val);
|
||||
float imp = (iph * hours);
|
||||
float exp = (eph * hours);
|
||||
setDayImport(last.Day, imp);
|
||||
setDayExport(last.Day, exp);
|
||||
|
||||
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||
debugger->printf("(AmsDataStorage) Estimated usage for day %u: %.1f (%lld)\n", last.Day, val, (int64_t) cur);
|
||||
debugger->printf("(AmsDataStorage) Estimated usage for day %u: %.1f - %.1f (%lld)\n", last.Day, imp, exp, (int64_t) cur);
|
||||
}
|
||||
|
||||
month.activeImport += iph * hours;
|
||||
month.activeExport += eph * hours;
|
||||
month.activeImport += imp;
|
||||
month.activeExport += exp;
|
||||
month.lastMeterReadTime = cur;
|
||||
}
|
||||
}
|
||||
@@ -229,24 +238,44 @@ bool AmsDataStorage::update(AmsData* data) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AmsDataStorage::setHour(uint8_t hour, int32_t val) {
|
||||
void AmsDataStorage::setHourImport(uint8_t hour, int32_t val) {
|
||||
if(hour < 0 || hour > 24) return;
|
||||
day.points[hour] = val / 10;
|
||||
day.hImport[hour] = val / 10;
|
||||
}
|
||||
|
||||
int32_t AmsDataStorage::getHour(uint8_t hour) {
|
||||
int32_t AmsDataStorage::getHourImport(uint8_t hour) {
|
||||
if(hour < 0 || hour > 24) return 0;
|
||||
return day.points[hour] * 10;
|
||||
return day.hImport[hour] * 10;
|
||||
}
|
||||
|
||||
void AmsDataStorage::setDay(uint8_t day, int32_t val) {
|
||||
void AmsDataStorage::setHourExport(uint8_t hour, int32_t val) {
|
||||
if(hour < 0 || hour > 24) return;
|
||||
day.hExport[hour] = val / 10;
|
||||
}
|
||||
|
||||
int32_t AmsDataStorage::getHourExport(uint8_t hour) {
|
||||
if(hour < 0 || hour > 24) return 0;
|
||||
return day.hExport[hour] * 10;
|
||||
}
|
||||
|
||||
void AmsDataStorage::setDayImport(uint8_t day, int32_t val) {
|
||||
if(day < 1 || day > 31) return;
|
||||
month.points[day-1] = val / 10;
|
||||
month.dImport[day-1] = val / 10;
|
||||
}
|
||||
|
||||
int32_t AmsDataStorage::getDay(uint8_t day) {
|
||||
int32_t AmsDataStorage::getDayImport(uint8_t day) {
|
||||
if(day < 1 || day > 31) return 0;
|
||||
return (month.points[day-1] * 10);
|
||||
return (month.dImport[day-1] * 10);
|
||||
}
|
||||
|
||||
void AmsDataStorage::setDayExport(uint8_t day, int32_t val) {
|
||||
if(day < 1 || day > 31) return;
|
||||
month.dExport[day-1] = val / 10;
|
||||
}
|
||||
|
||||
int32_t AmsDataStorage::getDayExport(uint8_t day) {
|
||||
if(day < 1 || day > 31) return 0;
|
||||
return (month.dExport[day-1] * 10);
|
||||
}
|
||||
|
||||
bool AmsDataStorage::load() {
|
||||
@@ -320,17 +349,27 @@ MonthDataPoints AmsDataStorage::getMonthData() {
|
||||
}
|
||||
|
||||
bool AmsDataStorage::setDayData(DayDataPoints& day) {
|
||||
if(day.version == 3) {
|
||||
if(day.version == 4) {
|
||||
this->day = day;
|
||||
return true;
|
||||
} else if(day.version == 3) {
|
||||
this->day = day;
|
||||
for(uint8_t i = 0; i < 24; i++) this->day.hExport[i] = 0;
|
||||
this->day.version = 4;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AmsDataStorage::setMonthData(MonthDataPoints& month) {
|
||||
if(month.version == 4) {
|
||||
if(month.version == 5) {
|
||||
this->month = month;
|
||||
return true;
|
||||
} else if(month.version == 4) {
|
||||
this->month = month;
|
||||
for(uint8_t i = 0; i < 31; i++) this->month.dExport[i] = 0;
|
||||
this->month.version = 5;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,27 +7,31 @@
|
||||
|
||||
struct DayDataPoints {
|
||||
uint8_t version;
|
||||
int16_t points[24];
|
||||
int16_t hImport[24];
|
||||
time_t lastMeterReadTime;
|
||||
uint32_t activeImport;
|
||||
uint32_t activeExport;
|
||||
}; // 37 bytes
|
||||
int16_t hExport[24];
|
||||
}; // 112 bytes
|
||||
|
||||
struct MonthDataPoints {
|
||||
uint8_t version;
|
||||
int16_t points[31];
|
||||
int16_t dImport[31];
|
||||
time_t lastMeterReadTime;
|
||||
uint32_t activeImport;
|
||||
uint32_t activeExport;
|
||||
}; // 75 bytes
|
||||
int16_t dExport[31];
|
||||
}; // 141 bytes
|
||||
|
||||
class AmsDataStorage {
|
||||
public:
|
||||
AmsDataStorage(RemoteDebug*);
|
||||
void setTimezone(Timezone*);
|
||||
bool update(AmsData*);
|
||||
int32_t getHour(uint8_t);
|
||||
int32_t getDay(uint8_t);
|
||||
int32_t getHourImport(uint8_t);
|
||||
int32_t getHourExport(uint8_t);
|
||||
int32_t getDayImport(uint8_t);
|
||||
int32_t getDayExport(uint8_t);
|
||||
bool load();
|
||||
bool save();
|
||||
|
||||
@@ -43,14 +47,22 @@ public:
|
||||
private:
|
||||
Timezone* tz;
|
||||
DayDataPoints day = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
MonthDataPoints month = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
RemoteDebug* debugger;
|
||||
void setHour(uint8_t, int32_t);
|
||||
void setDay(uint8_t, int32_t);
|
||||
void setHourImport(uint8_t, int32_t);
|
||||
void setHourExport(uint8_t, int32_t);
|
||||
void setDayImport(uint8_t, int32_t);
|
||||
void setDayExport(uint8_t, int32_t);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -122,7 +122,7 @@ bool EnergyAccounting::calcDayUse() {
|
||||
uint8_t lim = local.Day == 1 ? local.Hour : 24;
|
||||
for(int i = 0; i < lim; i++) {
|
||||
breakTime(now - ((lim - i) * 3600), utc);
|
||||
int16_t val = ds->getHour(utc.Hour) / 10.0;
|
||||
int16_t val = ds->getHourImport(utc.Hour) / 10.0;
|
||||
if(val > data.maxHour) {
|
||||
data.maxHour = val;
|
||||
ret = true;
|
||||
@@ -142,7 +142,7 @@ void EnergyAccounting::calcDayCost() {
|
||||
float price = eapi->getValueForHour(i - local.Hour);
|
||||
if(price == ENTSOE_NO_VALUE) break;
|
||||
breakTime(now - ((local.Hour - i) * 3600), utc);
|
||||
int16_t wh = ds->getHour(utc.Hour);
|
||||
int16_t wh = ds->getHourImport(utc.Hour);
|
||||
costDay += price * (wh / 1000.0);
|
||||
}
|
||||
initPrice = true;
|
||||
@@ -165,7 +165,7 @@ double EnergyAccounting::getUseToday() {
|
||||
breakTime(tz->toLocal(now), local);
|
||||
for(int i = 0; i < local.Hour; i++) {
|
||||
breakTime(now - ((local.Hour - i) * 3600), utc);
|
||||
ret += ds->getHour(utc.Hour) / 1000.0;
|
||||
ret += ds->getHourImport(utc.Hour) / 1000.0;
|
||||
}
|
||||
return ret + getUseThisHour();
|
||||
}
|
||||
@@ -188,7 +188,7 @@ double EnergyAccounting::getUseThisMonth() {
|
||||
breakTime(now, tm);
|
||||
float ret = 0;
|
||||
for(int i = 0; i < tm.Day; i++) {
|
||||
ret += ds->getDay(i) / 1000.0;
|
||||
ret += ds->getDayImport(i) / 1000.0;
|
||||
}
|
||||
return ret + getUseToday();
|
||||
}
|
||||
|
||||
@@ -755,30 +755,54 @@ void AmsWebServer::dayplotJson() {
|
||||
notFound();
|
||||
} else {
|
||||
snprintf_P(buf, BufferSize, DAYPLOT_JSON,
|
||||
ds->getHour(0) / 1000.0,
|
||||
ds->getHour(1) / 1000.0,
|
||||
ds->getHour(2) / 1000.0,
|
||||
ds->getHour(3) / 1000.0,
|
||||
ds->getHour(4) / 1000.0,
|
||||
ds->getHour(5) / 1000.0,
|
||||
ds->getHour(6) / 1000.0,
|
||||
ds->getHour(7) / 1000.0,
|
||||
ds->getHour(8) / 1000.0,
|
||||
ds->getHour(9) / 1000.0,
|
||||
ds->getHour(10) / 1000.0,
|
||||
ds->getHour(11) / 1000.0,
|
||||
ds->getHour(12) / 1000.0,
|
||||
ds->getHour(13) / 1000.0,
|
||||
ds->getHour(14) / 1000.0,
|
||||
ds->getHour(15) / 1000.0,
|
||||
ds->getHour(16) / 1000.0,
|
||||
ds->getHour(17) / 1000.0,
|
||||
ds->getHour(18) / 1000.0,
|
||||
ds->getHour(19) / 1000.0,
|
||||
ds->getHour(20) / 1000.0,
|
||||
ds->getHour(21) / 1000.0,
|
||||
ds->getHour(22) / 1000.0,
|
||||
ds->getHour(23) / 1000.0
|
||||
ds->getHourImport(0) / 1000.0,
|
||||
ds->getHourImport(1) / 1000.0,
|
||||
ds->getHourImport(2) / 1000.0,
|
||||
ds->getHourImport(3) / 1000.0,
|
||||
ds->getHourImport(4) / 1000.0,
|
||||
ds->getHourImport(5) / 1000.0,
|
||||
ds->getHourImport(6) / 1000.0,
|
||||
ds->getHourImport(7) / 1000.0,
|
||||
ds->getHourImport(8) / 1000.0,
|
||||
ds->getHourImport(9) / 1000.0,
|
||||
ds->getHourImport(10) / 1000.0,
|
||||
ds->getHourImport(11) / 1000.0,
|
||||
ds->getHourImport(12) / 1000.0,
|
||||
ds->getHourImport(13) / 1000.0,
|
||||
ds->getHourImport(14) / 1000.0,
|
||||
ds->getHourImport(15) / 1000.0,
|
||||
ds->getHourImport(16) / 1000.0,
|
||||
ds->getHourImport(17) / 1000.0,
|
||||
ds->getHourImport(18) / 1000.0,
|
||||
ds->getHourImport(19) / 1000.0,
|
||||
ds->getHourImport(20) / 1000.0,
|
||||
ds->getHourImport(21) / 1000.0,
|
||||
ds->getHourImport(22) / 1000.0,
|
||||
ds->getHourImport(23) / 1000.0,
|
||||
ds->getHourExport(0) / 1000.0,
|
||||
ds->getHourExport(1) / 1000.0,
|
||||
ds->getHourExport(2) / 1000.0,
|
||||
ds->getHourExport(3) / 1000.0,
|
||||
ds->getHourExport(4) / 1000.0,
|
||||
ds->getHourExport(5) / 1000.0,
|
||||
ds->getHourExport(6) / 1000.0,
|
||||
ds->getHourExport(7) / 1000.0,
|
||||
ds->getHourExport(8) / 1000.0,
|
||||
ds->getHourExport(9) / 1000.0,
|
||||
ds->getHourExport(10) / 1000.0,
|
||||
ds->getHourExport(11) / 1000.0,
|
||||
ds->getHourExport(12) / 1000.0,
|
||||
ds->getHourExport(13) / 1000.0,
|
||||
ds->getHourExport(14) / 1000.0,
|
||||
ds->getHourExport(15) / 1000.0,
|
||||
ds->getHourExport(16) / 1000.0,
|
||||
ds->getHourExport(17) / 1000.0,
|
||||
ds->getHourExport(18) / 1000.0,
|
||||
ds->getHourExport(19) / 1000.0,
|
||||
ds->getHourExport(20) / 1000.0,
|
||||
ds->getHourExport(21) / 1000.0,
|
||||
ds->getHourExport(22) / 1000.0,
|
||||
ds->getHourExport(23) / 1000.0
|
||||
);
|
||||
|
||||
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||
@@ -800,37 +824,68 @@ void AmsWebServer::monthplotJson() {
|
||||
notFound();
|
||||
} else {
|
||||
snprintf_P(buf, BufferSize, MONTHPLOT_JSON,
|
||||
ds->getDay(1) / 1000.0,
|
||||
ds->getDay(2) / 1000.0,
|
||||
ds->getDay(3) / 1000.0,
|
||||
ds->getDay(4) / 1000.0,
|
||||
ds->getDay(5) / 1000.0,
|
||||
ds->getDay(6) / 1000.0,
|
||||
ds->getDay(7) / 1000.0,
|
||||
ds->getDay(8) / 1000.0,
|
||||
ds->getDay(9) / 1000.0,
|
||||
ds->getDay(10) / 1000.0,
|
||||
ds->getDay(11) / 1000.0,
|
||||
ds->getDay(12) / 1000.0,
|
||||
ds->getDay(13) / 1000.0,
|
||||
ds->getDay(14) / 1000.0,
|
||||
ds->getDay(15) / 1000.0,
|
||||
ds->getDay(16) / 1000.0,
|
||||
ds->getDay(17) / 1000.0,
|
||||
ds->getDay(18) / 1000.0,
|
||||
ds->getDay(19) / 1000.0,
|
||||
ds->getDay(20) / 1000.0,
|
||||
ds->getDay(21) / 1000.0,
|
||||
ds->getDay(22) / 1000.0,
|
||||
ds->getDay(23) / 1000.0,
|
||||
ds->getDay(24) / 1000.0,
|
||||
ds->getDay(25) / 1000.0,
|
||||
ds->getDay(26) / 1000.0,
|
||||
ds->getDay(27) / 1000.0,
|
||||
ds->getDay(28) / 1000.0,
|
||||
ds->getDay(29) / 1000.0,
|
||||
ds->getDay(30) / 1000.0,
|
||||
ds->getDay(31) / 1000.0
|
||||
ds->getDayImport(1) / 1000.0,
|
||||
ds->getDayImport(2) / 1000.0,
|
||||
ds->getDayImport(3) / 1000.0,
|
||||
ds->getDayImport(4) / 1000.0,
|
||||
ds->getDayImport(5) / 1000.0,
|
||||
ds->getDayImport(6) / 1000.0,
|
||||
ds->getDayImport(7) / 1000.0,
|
||||
ds->getDayImport(8) / 1000.0,
|
||||
ds->getDayImport(9) / 1000.0,
|
||||
ds->getDayImport(10) / 1000.0,
|
||||
ds->getDayImport(11) / 1000.0,
|
||||
ds->getDayImport(12) / 1000.0,
|
||||
ds->getDayImport(13) / 1000.0,
|
||||
ds->getDayImport(14) / 1000.0,
|
||||
ds->getDayImport(15) / 1000.0,
|
||||
ds->getDayImport(16) / 1000.0,
|
||||
ds->getDayImport(17) / 1000.0,
|
||||
ds->getDayImport(18) / 1000.0,
|
||||
ds->getDayImport(19) / 1000.0,
|
||||
ds->getDayImport(20) / 1000.0,
|
||||
ds->getDayImport(21) / 1000.0,
|
||||
ds->getDayImport(22) / 1000.0,
|
||||
ds->getDayImport(23) / 1000.0,
|
||||
ds->getDayImport(24) / 1000.0,
|
||||
ds->getDayImport(25) / 1000.0,
|
||||
ds->getDayImport(26) / 1000.0,
|
||||
ds->getDayImport(27) / 1000.0,
|
||||
ds->getDayImport(28) / 1000.0,
|
||||
ds->getDayImport(29) / 1000.0,
|
||||
ds->getDayImport(30) / 1000.0,
|
||||
ds->getDayImport(31) / 1000.0,
|
||||
ds->getDayExport(1) / 1000.0,
|
||||
ds->getDayExport(2) / 1000.0,
|
||||
ds->getDayExport(3) / 1000.0,
|
||||
ds->getDayExport(4) / 1000.0,
|
||||
ds->getDayExport(5) / 1000.0,
|
||||
ds->getDayExport(6) / 1000.0,
|
||||
ds->getDayExport(7) / 1000.0,
|
||||
ds->getDayExport(8) / 1000.0,
|
||||
ds->getDayExport(9) / 1000.0,
|
||||
ds->getDayExport(10) / 1000.0,
|
||||
ds->getDayExport(11) / 1000.0,
|
||||
ds->getDayExport(12) / 1000.0,
|
||||
ds->getDayExport(13) / 1000.0,
|
||||
ds->getDayExport(14) / 1000.0,
|
||||
ds->getDayExport(15) / 1000.0,
|
||||
ds->getDayExport(16) / 1000.0,
|
||||
ds->getDayExport(17) / 1000.0,
|
||||
ds->getDayExport(18) / 1000.0,
|
||||
ds->getDayExport(19) / 1000.0,
|
||||
ds->getDayExport(20) / 1000.0,
|
||||
ds->getDayExport(21) / 1000.0,
|
||||
ds->getDayExport(22) / 1000.0,
|
||||
ds->getDayExport(23) / 1000.0,
|
||||
ds->getDayExport(24) / 1000.0,
|
||||
ds->getDayExport(25) / 1000.0,
|
||||
ds->getDayExport(26) / 1000.0,
|
||||
ds->getDayExport(27) / 1000.0,
|
||||
ds->getDayExport(28) / 1000.0,
|
||||
ds->getDayExport(29) / 1000.0,
|
||||
ds->getDayExport(30) / 1000.0,
|
||||
ds->getDayExport(31) / 1000.0
|
||||
);
|
||||
|
||||
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||
@@ -2155,83 +2210,138 @@ void AmsWebServer::configFileDownload() {
|
||||
|
||||
if(ds != NULL) {
|
||||
DayDataPoints day = ds->getDayData();
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, (char*) F("dayplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, (char*) F("dayplot %d %lld %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
|
||||
day.version,
|
||||
day.lastMeterReadTime,
|
||||
day.activeImport,
|
||||
ds->getHour(0),
|
||||
ds->getHour(1),
|
||||
ds->getHour(2),
|
||||
ds->getHour(3),
|
||||
ds->getHour(4),
|
||||
ds->getHour(5),
|
||||
ds->getHour(6),
|
||||
ds->getHour(7),
|
||||
ds->getHour(8),
|
||||
ds->getHour(9),
|
||||
ds->getHour(10),
|
||||
ds->getHour(11),
|
||||
ds->getHour(12),
|
||||
ds->getHour(13),
|
||||
ds->getHour(14),
|
||||
ds->getHour(15),
|
||||
ds->getHour(16),
|
||||
ds->getHour(17),
|
||||
ds->getHour(18),
|
||||
ds->getHour(19),
|
||||
ds->getHour(20),
|
||||
ds->getHour(21),
|
||||
ds->getHour(22),
|
||||
ds->getHour(23)
|
||||
ds->getHourImport(0),
|
||||
ds->getHourImport(1),
|
||||
ds->getHourImport(2),
|
||||
ds->getHourImport(3),
|
||||
ds->getHourImport(4),
|
||||
ds->getHourImport(5),
|
||||
ds->getHourImport(6),
|
||||
ds->getHourImport(7),
|
||||
ds->getHourImport(8),
|
||||
ds->getHourImport(9),
|
||||
ds->getHourImport(10),
|
||||
ds->getHourImport(11),
|
||||
ds->getHourImport(12),
|
||||
ds->getHourImport(13),
|
||||
ds->getHourImport(14),
|
||||
ds->getHourImport(15),
|
||||
ds->getHourImport(16),
|
||||
ds->getHourImport(17),
|
||||
ds->getHourImport(18),
|
||||
ds->getHourImport(19),
|
||||
ds->getHourImport(20),
|
||||
ds->getHourImport(21),
|
||||
ds->getHourImport(22),
|
||||
ds->getHourImport(23)
|
||||
));
|
||||
if(day.activeExport > 0) {
|
||||
server.sendContent(buf, snprintf(buf, BufferSize, " %lu\n",
|
||||
day.activeExport
|
||||
server.sendContent(buf, snprintf(buf, BufferSize, " %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
||||
day.activeExport,
|
||||
ds->getHourExport(0),
|
||||
ds->getHourExport(1),
|
||||
ds->getHourExport(2),
|
||||
ds->getHourExport(3),
|
||||
ds->getHourExport(4),
|
||||
ds->getHourExport(5),
|
||||
ds->getHourExport(6),
|
||||
ds->getHourExport(7),
|
||||
ds->getHourExport(8),
|
||||
ds->getHourExport(9),
|
||||
ds->getHourExport(10),
|
||||
ds->getHourExport(11),
|
||||
ds->getHourExport(12),
|
||||
ds->getHourExport(13),
|
||||
ds->getHourExport(14),
|
||||
ds->getHourExport(15),
|
||||
ds->getHourExport(16),
|
||||
ds->getHourExport(17),
|
||||
ds->getHourExport(18),
|
||||
ds->getHourExport(19),
|
||||
ds->getHourExport(20),
|
||||
ds->getHourExport(21),
|
||||
ds->getHourExport(22),
|
||||
ds->getHourExport(23)
|
||||
));
|
||||
} else {
|
||||
server.sendContent("\n");
|
||||
}
|
||||
|
||||
MonthDataPoints month = ds->getMonthData();
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, (char*) F("monthplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, (char*) F("monthplot %d %lld %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
|
||||
month.version,
|
||||
month.lastMeterReadTime,
|
||||
month.activeImport,
|
||||
ds->getDay(1),
|
||||
ds->getDay(2),
|
||||
ds->getDay(3),
|
||||
ds->getDay(4),
|
||||
ds->getDay(5),
|
||||
ds->getDay(6),
|
||||
ds->getDay(7),
|
||||
ds->getDay(8),
|
||||
ds->getDay(9),
|
||||
ds->getDay(10),
|
||||
ds->getDay(11),
|
||||
ds->getDay(12),
|
||||
ds->getDay(13),
|
||||
ds->getDay(14),
|
||||
ds->getDay(15),
|
||||
ds->getDay(16),
|
||||
ds->getDay(17),
|
||||
ds->getDay(18),
|
||||
ds->getDay(19),
|
||||
ds->getDay(20),
|
||||
ds->getDay(21),
|
||||
ds->getDay(22),
|
||||
ds->getDay(23),
|
||||
ds->getDay(24),
|
||||
ds->getDay(25),
|
||||
ds->getDay(26),
|
||||
ds->getDay(27),
|
||||
ds->getDay(28),
|
||||
ds->getDay(29),
|
||||
ds->getDay(30),
|
||||
ds->getDay(31)
|
||||
ds->getDayImport(1),
|
||||
ds->getDayImport(2),
|
||||
ds->getDayImport(3),
|
||||
ds->getDayImport(4),
|
||||
ds->getDayImport(5),
|
||||
ds->getDayImport(6),
|
||||
ds->getDayImport(7),
|
||||
ds->getDayImport(8),
|
||||
ds->getDayImport(9),
|
||||
ds->getDayImport(10),
|
||||
ds->getDayImport(11),
|
||||
ds->getDayImport(12),
|
||||
ds->getDayImport(13),
|
||||
ds->getDayImport(14),
|
||||
ds->getDayImport(15),
|
||||
ds->getDayImport(16),
|
||||
ds->getDayImport(17),
|
||||
ds->getDayImport(18),
|
||||
ds->getDayImport(19),
|
||||
ds->getDayImport(20),
|
||||
ds->getDayImport(21),
|
||||
ds->getDayImport(22),
|
||||
ds->getDayImport(23),
|
||||
ds->getDayImport(24),
|
||||
ds->getDayImport(25),
|
||||
ds->getDayImport(26),
|
||||
ds->getDayImport(27),
|
||||
ds->getDayImport(28),
|
||||
ds->getDayImport(29),
|
||||
ds->getDayImport(30),
|
||||
ds->getDayImport(31)
|
||||
));
|
||||
if(month.activeExport > 0) {
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, " %lu\n",
|
||||
month.activeExport
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, " %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
||||
month.activeExport,
|
||||
ds->getDayExport(1),
|
||||
ds->getDayExport(2),
|
||||
ds->getDayExport(3),
|
||||
ds->getDayExport(4),
|
||||
ds->getDayExport(5),
|
||||
ds->getDayExport(6),
|
||||
ds->getDayExport(7),
|
||||
ds->getDayExport(8),
|
||||
ds->getDayExport(9),
|
||||
ds->getDayExport(10),
|
||||
ds->getDayExport(11),
|
||||
ds->getDayExport(12),
|
||||
ds->getDayExport(13),
|
||||
ds->getDayExport(14),
|
||||
ds->getDayExport(15),
|
||||
ds->getDayExport(16),
|
||||
ds->getDayExport(17),
|
||||
ds->getDayExport(18),
|
||||
ds->getDayExport(19),
|
||||
ds->getDayExport(20),
|
||||
ds->getDayExport(21),
|
||||
ds->getDayExport(22),
|
||||
ds->getDayExport(23),
|
||||
ds->getDayExport(24),
|
||||
ds->getDayExport(25),
|
||||
ds->getDayExport(26),
|
||||
ds->getDayExport(27),
|
||||
ds->getDayExport(28),
|
||||
ds->getDayExport(29),
|
||||
ds->getDayExport(30),
|
||||
ds->getDayExport(31)
|
||||
));
|
||||
} else {
|
||||
server.sendContent("\n");
|
||||
@@ -2436,7 +2546,7 @@ void AmsWebServer::configFileParse() {
|
||||
}
|
||||
} else if(strncmp(buf, "dayplot ", 8) == 0 && ds != NULL) {
|
||||
int i = 0;
|
||||
DayDataPoints day = { 3 }; // Use a version we know the multiplier of the data points
|
||||
DayDataPoints day = { 4 }; // Use a version we know the multiplier of the data points
|
||||
char * pch = strtok (buf+8," ");
|
||||
while (pch != NULL) {
|
||||
long val = String(pch).toInt();
|
||||
@@ -2445,11 +2555,11 @@ void AmsWebServer::configFileParse() {
|
||||
} else if(i == 2) {
|
||||
day.activeImport = val;
|
||||
} else if(i > 2 && i < 27) {
|
||||
day.points[i-3] = val / 10;
|
||||
day.hImport[i-3] = val / 10;
|
||||
} else if(i == 27) {
|
||||
day.activeExport = val;
|
||||
} else if(i > 27 && i < 52) {
|
||||
// TODO: Export points
|
||||
day.hExport[i-28] = val / 10;
|
||||
}
|
||||
|
||||
pch = strtok (NULL, " ");
|
||||
@@ -2458,7 +2568,7 @@ void AmsWebServer::configFileParse() {
|
||||
ds->setDayData(day);
|
||||
} else if(strncmp(buf, "monthplot ", 10) == 0 && ds != NULL) {
|
||||
int i = 0;
|
||||
MonthDataPoints month = { 4 }; // Use a version we know the multiplier of the data points
|
||||
MonthDataPoints month = { 5 }; // Use a version we know the multiplier of the data points
|
||||
char * pch = strtok (buf+10," ");
|
||||
while (pch != NULL) {
|
||||
long val = String(pch).toInt();
|
||||
@@ -2467,11 +2577,11 @@ void AmsWebServer::configFileParse() {
|
||||
} else if(i == 2) {
|
||||
month.activeImport = val;
|
||||
} else if(i > 2 && i < 34) {
|
||||
month.points[i-3] = val / 10;
|
||||
month.dImport[i-3] = val / 10;
|
||||
} else if(i == 34) {
|
||||
month.activeExport = val;
|
||||
} else if(i > 34 && i < 66) {
|
||||
// TODO: Export points
|
||||
month.dExport[i-35] = val / 10;
|
||||
}
|
||||
|
||||
pch = strtok (NULL, " ");
|
||||
|
||||
@@ -31,6 +31,7 @@ var eo = {
|
||||
titleTextStyle: {
|
||||
fontSize: 14
|
||||
},
|
||||
colors: ['#6f42c1', '#6f42c1'],
|
||||
backgroundColor: { fill:'transparent' },
|
||||
bar: { groupWidth: '90%' },
|
||||
legend: { position: 'none' },
|
||||
@@ -40,6 +41,7 @@ var eo = {
|
||||
},
|
||||
tooltip: { trigger: 'none'},
|
||||
enableInteractivity: false,
|
||||
isStacked: true
|
||||
};
|
||||
|
||||
// Month plot
|
||||
@@ -50,6 +52,7 @@ var mo = {
|
||||
titleTextStyle: {
|
||||
fontSize: 14
|
||||
},
|
||||
colors: ['#6f42c1', '#6f42c1'],
|
||||
backgroundColor: { fill:'transparent' },
|
||||
bar: { groupWidth: '90%' },
|
||||
legend: { position: 'none' },
|
||||
@@ -59,6 +62,7 @@ var mo = {
|
||||
},
|
||||
tooltip: { trigger: 'none'},
|
||||
enableInteractivity: false,
|
||||
isStacked: true
|
||||
};
|
||||
|
||||
// Voltage plot
|
||||
@@ -468,24 +472,27 @@ var drawDay = function() {
|
||||
timeout: 30000,
|
||||
dataType: 'json',
|
||||
}).done(function(json) {
|
||||
data = [['Hour','kWh', { role: 'style' }, { role: 'annotation' }]];
|
||||
data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }]];
|
||||
var r = 1;
|
||||
var hour = moment.utc().hours();
|
||||
var offset = moment().utcOffset()/60;
|
||||
var min = 0;
|
||||
for(var i = hour; i<24; i++) {
|
||||
var val = json["h"+zeropad(i)];
|
||||
data[r++] = [zeropad((i+offset)%24), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(1)];
|
||||
Math.min(0, val);
|
||||
var imp = json["i"+zeropad(i)];
|
||||
var exp = json["e"+zeropad(i)];
|
||||
data[r++] = [zeropad((i+offset)%24), imp, "opacity: 0.9;", exp == 0 ? imp.toFixed(1) : imp.toFixed(1) + '\n' + -exp.toFixed(1), exp == 0 ? 0 : -exp, "opacity: 0.9;"];
|
||||
min = Math.min(0, -exp);
|
||||
};
|
||||
for(var i = 0; i < hour; i++) {
|
||||
var val = json["h"+zeropad(i)];
|
||||
data[r++] = [zeropad((i+offset)%24), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(1)];
|
||||
Math.min(0, val);
|
||||
var imp = json["i"+zeropad(i)];
|
||||
var exp = json["e"+zeropad(i)];
|
||||
data[r++] = [zeropad((i+offset)%24), imp, "opacity: 0.9;", exp == 0 ? imp.toFixed(1) : imp.toFixed(1) + '\n' + -exp.toFixed(1), exp == 0 ? 0 : -exp, "opacity: 0.9;"];
|
||||
min = Math.min(0, -exp);
|
||||
};
|
||||
ea = google.visualization.arrayToDataTable(data);
|
||||
if(min == 0)
|
||||
eo.vAxis.minValue = 0;
|
||||
|
||||
ep.draw(ea, eo);
|
||||
|
||||
setTimeout(drawDay, (61-moment().minute())*60000);
|
||||
@@ -498,20 +505,22 @@ var drawMonth = function() {
|
||||
timeout: 30000,
|
||||
dataType: 'json',
|
||||
}).done(function(json) {
|
||||
data = [['Day','kWh', { role: 'style' }, { role: 'annotation' }]];
|
||||
data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }]];
|
||||
var r = 1;
|
||||
var day = moment().date();
|
||||
var eom = moment().subtract(1, 'months').endOf('month').date();
|
||||
var min = 0;
|
||||
for(var i = day; i<=eom; i++) {
|
||||
var val = json["d"+zeropad(i)];
|
||||
data[r++] = [zeropad((i)), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(0)];
|
||||
Math.min(0, val);
|
||||
var imp = json["i"+zeropad(i)];
|
||||
var exp = json["e"+zeropad(i)];
|
||||
data[r++] = [zeropad(i), imp, "opacity: 0.9;", exp == 0 ? imp.toFixed(0) : imp.toFixed(0) + '\n' + -exp.toFixed(0), exp == 0 ? 0 : -exp, "opacity: 0.9;"];
|
||||
min = Math.min(0, -exp);
|
||||
}
|
||||
for(var i = 1; i < day; i++) {
|
||||
var val = json["d"+zeropad(i)];
|
||||
data[r++] = [zeropad((i)), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(0)];
|
||||
Math.min(0, val);
|
||||
var imp = json["i"+zeropad(i)];
|
||||
var exp = json["e"+zeropad(i)];
|
||||
data[r++] = [zeropad(i), imp, "opacity: 0.9;", exp == 0 ? imp.toFixed(0) : imp.toFixed(0) + '\n' + -exp.toFixed(0), exp == 0 ? 0 : -exp, "opacity: 0.9;"];
|
||||
min = Math.min(0, -exp);
|
||||
}
|
||||
ma = google.visualization.arrayToDataTable(data);
|
||||
if(min == 0)
|
||||
|
||||
@@ -1,26 +1,50 @@
|
||||
{
|
||||
"h00" : %.2f,
|
||||
"h01" : %.2f,
|
||||
"h02" : %.2f,
|
||||
"h03" : %.2f,
|
||||
"h04" : %.2f,
|
||||
"h05" : %.2f,
|
||||
"h06" : %.2f,
|
||||
"h07" : %.2f,
|
||||
"h08" : %.2f,
|
||||
"h09" : %.2f,
|
||||
"h10" : %.2f,
|
||||
"h11" : %.2f,
|
||||
"h12" : %.2f,
|
||||
"h13" : %.2f,
|
||||
"h14" : %.2f,
|
||||
"h15" : %.2f,
|
||||
"h16" : %.2f,
|
||||
"h17" : %.2f,
|
||||
"h18" : %.2f,
|
||||
"h19" : %.2f,
|
||||
"h20" : %.2f,
|
||||
"h21" : %.2f,
|
||||
"h22" : %.2f,
|
||||
"h23" : %.2f
|
||||
"i00" : %.2f,
|
||||
"i01" : %.2f,
|
||||
"i02" : %.2f,
|
||||
"i03" : %.2f,
|
||||
"i04" : %.2f,
|
||||
"i05" : %.2f,
|
||||
"i06" : %.2f,
|
||||
"i07" : %.2f,
|
||||
"i08" : %.2f,
|
||||
"i09" : %.2f,
|
||||
"i10" : %.2f,
|
||||
"i11" : %.2f,
|
||||
"i12" : %.2f,
|
||||
"i13" : %.2f,
|
||||
"i14" : %.2f,
|
||||
"i15" : %.2f,
|
||||
"i16" : %.2f,
|
||||
"i17" : %.2f,
|
||||
"i18" : %.2f,
|
||||
"i19" : %.2f,
|
||||
"i20" : %.2f,
|
||||
"i21" : %.2f,
|
||||
"i22" : %.2f,
|
||||
"i23" : %.2f,
|
||||
"e00" : %.2f,
|
||||
"e01" : %.2f,
|
||||
"e02" : %.2f,
|
||||
"e03" : %.2f,
|
||||
"e04" : %.2f,
|
||||
"e05" : %.2f,
|
||||
"e06" : %.2f,
|
||||
"e07" : %.2f,
|
||||
"e08" : %.2f,
|
||||
"e09" : %.2f,
|
||||
"e10" : %.2f,
|
||||
"e11" : %.2f,
|
||||
"e12" : %.2f,
|
||||
"e13" : %.2f,
|
||||
"e14" : %.2f,
|
||||
"e15" : %.2f,
|
||||
"e16" : %.2f,
|
||||
"e17" : %.2f,
|
||||
"e18" : %.2f,
|
||||
"e19" : %.2f,
|
||||
"e20" : %.2f,
|
||||
"e21" : %.2f,
|
||||
"e22" : %.2f,
|
||||
"e23" : %.2f
|
||||
}
|
||||
|
||||
@@ -1,33 +1,64 @@
|
||||
{
|
||||
"d01" : %.2f,
|
||||
"d02" : %.2f,
|
||||
"d03" : %.2f,
|
||||
"d04" : %.2f,
|
||||
"d05" : %.2f,
|
||||
"d06" : %.2f,
|
||||
"d07" : %.2f,
|
||||
"d08" : %.2f,
|
||||
"d09" : %.2f,
|
||||
"d10" : %.2f,
|
||||
"d11" : %.2f,
|
||||
"d12" : %.2f,
|
||||
"d13" : %.2f,
|
||||
"d14" : %.2f,
|
||||
"d15" : %.2f,
|
||||
"d16" : %.2f,
|
||||
"d17" : %.2f,
|
||||
"d18" : %.2f,
|
||||
"d19" : %.2f,
|
||||
"d20" : %.2f,
|
||||
"d21" : %.2f,
|
||||
"d22" : %.2f,
|
||||
"d23" : %.2f,
|
||||
"d24" : %.2f,
|
||||
"d25" : %.2f,
|
||||
"d26" : %.2f,
|
||||
"d27" : %.2f,
|
||||
"d28" : %.2f,
|
||||
"d29" : %.2f,
|
||||
"d30" : %.2f,
|
||||
"d31" : %.2f
|
||||
"i01" : %.2f,
|
||||
"i02" : %.2f,
|
||||
"i03" : %.2f,
|
||||
"i04" : %.2f,
|
||||
"i05" : %.2f,
|
||||
"i06" : %.2f,
|
||||
"i07" : %.2f,
|
||||
"i08" : %.2f,
|
||||
"i09" : %.2f,
|
||||
"i10" : %.2f,
|
||||
"i11" : %.2f,
|
||||
"i12" : %.2f,
|
||||
"i13" : %.2f,
|
||||
"i14" : %.2f,
|
||||
"i15" : %.2f,
|
||||
"i16" : %.2f,
|
||||
"i17" : %.2f,
|
||||
"i18" : %.2f,
|
||||
"i19" : %.2f,
|
||||
"i20" : %.2f,
|
||||
"i21" : %.2f,
|
||||
"i22" : %.2f,
|
||||
"i23" : %.2f,
|
||||
"i24" : %.2f,
|
||||
"i25" : %.2f,
|
||||
"i26" : %.2f,
|
||||
"i27" : %.2f,
|
||||
"i28" : %.2f,
|
||||
"i29" : %.2f,
|
||||
"i30" : %.2f,
|
||||
"i31" : %.2f,
|
||||
"e01" : %.2f,
|
||||
"e02" : %.2f,
|
||||
"e03" : %.2f,
|
||||
"e04" : %.2f,
|
||||
"e05" : %.2f,
|
||||
"e06" : %.2f,
|
||||
"e07" : %.2f,
|
||||
"e08" : %.2f,
|
||||
"e09" : %.2f,
|
||||
"e10" : %.2f,
|
||||
"e11" : %.2f,
|
||||
"e12" : %.2f,
|
||||
"e13" : %.2f,
|
||||
"e14" : %.2f,
|
||||
"e15" : %.2f,
|
||||
"e16" : %.2f,
|
||||
"e17" : %.2f,
|
||||
"e18" : %.2f,
|
||||
"e19" : %.2f,
|
||||
"e20" : %.2f,
|
||||
"e21" : %.2f,
|
||||
"e22" : %.2f,
|
||||
"e23" : %.2f,
|
||||
"e24" : %.2f,
|
||||
"e25" : %.2f,
|
||||
"e26" : %.2f,
|
||||
"e27" : %.2f,
|
||||
"e28" : %.2f,
|
||||
"e29" : %.2f,
|
||||
"e30" : %.2f,
|
||||
"e31" : %.2f
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user