mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-03-23 09:30:53 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2978116207 | ||
|
|
998b986604 | ||
|
|
7799431405 | ||
|
|
508c14a671 | ||
|
|
4a7ef87269 | ||
|
|
3a4fc707b0 | ||
|
|
5d2e320b07 | ||
|
|
d12613b91a | ||
|
|
e6a02f34ab | ||
|
|
0b2ffbfd77 | ||
|
|
cab6c54ed9 | ||
|
|
313024f273 | ||
|
|
91fc078c5e | ||
|
|
5b9d44a3e9 |
@@ -17,8 +17,10 @@ extra_scripts =
|
|||||||
pre:scripts/addversion.py
|
pre:scripts/addversion.py
|
||||||
scripts/makeweb.py
|
scripts/makeweb.py
|
||||||
|
|
||||||
|
# Sticking to v2.0.3 because of #298
|
||||||
|
|
||||||
[env:esp32]
|
[env:esp32]
|
||||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4/platform-espressif32-2.0.4.zip
|
platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.3/platform-espressif32-2.0.3.zip
|
||||||
framework = arduino
|
framework = arduino
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
board_build.f_cpu = 160000000L
|
board_build.f_cpu = 160000000L
|
||||||
@@ -33,8 +35,8 @@ extra_scripts =
|
|||||||
# https://github.com/Jason2866/esp32-arduino-lib-builder
|
# https://github.com/Jason2866/esp32-arduino-lib-builder
|
||||||
|
|
||||||
[env:esp32s2]
|
[env:esp32s2]
|
||||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4/platform-espressif32-2.0.4.zip
|
platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.3/platform-espressif32-2.0.3.zip
|
||||||
platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#2.0.4
|
platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#2.0.3
|
||||||
framework = arduino
|
framework = arduino
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
board_build.mcu = esp32s2
|
board_build.mcu = esp32s2
|
||||||
@@ -50,7 +52,7 @@ extra_scripts =
|
|||||||
scripts/makeweb.py
|
scripts/makeweb.py
|
||||||
|
|
||||||
[env:esp32solo]
|
[env:esp32solo]
|
||||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.4/platform-espressif32-solo1-2.0.4.zip
|
platform = https://github.com/tasmota/platform-espressif32/releases/download/v.2.0.3/platform-espressif32-solo1-v.2.0.3.zip
|
||||||
framework = arduino
|
framework = arduino
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
board_build.f_cpu = 160000000L
|
board_build.f_cpu = 160000000L
|
||||||
|
|||||||
@@ -63,8 +63,10 @@ void AmsConfiguration::clearWifi(WiFiConfig& config) {
|
|||||||
uint16_t chipId;
|
uint16_t chipId;
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
chipId = ESP.getEfuseMac();
|
chipId = ESP.getEfuseMac();
|
||||||
|
config.power = 195;
|
||||||
#else
|
#else
|
||||||
chipId = ESP.getChipId();
|
chipId = ESP.getChipId();
|
||||||
|
config.power = 205;
|
||||||
#endif
|
#endif
|
||||||
strcpy(config.hostname, (String("ams-") + String(chipId, HEX)).c_str());
|
strcpy(config.hostname, (String("ams-") + String(chipId, HEX)).c_str());
|
||||||
config.mdns = true;
|
config.mdns = true;
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ void setup() {
|
|||||||
gpioConfig.hanPin = 3;
|
gpioConfig.hanPin = 3;
|
||||||
gpioConfig.ledPin = 2;
|
gpioConfig.ledPin = 2;
|
||||||
gpioConfig.ledInverted = true;
|
gpioConfig.ledInverted = true;
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
gpioConfig.hanPin = 18;
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
gpioConfig.hanPin = 16;
|
gpioConfig.hanPin = 16;
|
||||||
gpioConfig.ledPin = 2;
|
gpioConfig.ledPin = 2;
|
||||||
@@ -155,6 +157,7 @@ void setup() {
|
|||||||
gpioConfig.tempSensorPin = 14;
|
gpioConfig.tempSensorPin = 14;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(1);
|
delay(1);
|
||||||
config.loadTempSensors();
|
config.loadTempSensors();
|
||||||
hw.setup(&gpioConfig, &config);
|
hw.setup(&gpioConfig, &config);
|
||||||
@@ -1032,6 +1035,7 @@ void WiFi_connect() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.setSleep(WIFI_PS_MIN_MODEM);
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
if(wifi.power >= 195)
|
if(wifi.power >= 195)
|
||||||
WiFi.setTxPower(WIFI_POWER_19_5dBm);
|
WiFi.setTxPower(WIFI_POWER_19_5dBm);
|
||||||
@@ -1055,6 +1059,8 @@ void WiFi_connect() {
|
|||||||
WiFi.setTxPower(WIFI_POWER_5dBm);
|
WiFi.setTxPower(WIFI_POWER_5dBm);
|
||||||
else if(wifi.power >= 20)
|
else if(wifi.power >= 20)
|
||||||
WiFi.setTxPower(WIFI_POWER_2dBm);
|
WiFi.setTxPower(WIFI_POWER_2dBm);
|
||||||
|
else
|
||||||
|
WiFi.setTxPower(WIFI_POWER_MINUS_1dBm);
|
||||||
#elif defined(ESP8266)
|
#elif defined(ESP8266)
|
||||||
WiFi.setOutputPower(wifi.power / 10.0);
|
WiFi.setOutputPower(wifi.power / 10.0);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use = 0;
|
use = 0;
|
||||||
|
produce = 0;
|
||||||
costHour = 0;
|
costHour = 0;
|
||||||
currentHour = local.Hour;
|
currentHour = local.Hour;
|
||||||
|
|
||||||
@@ -106,19 +107,24 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned long ms = this->lastUpdateMillis > amsData->getLastUpdateMillis() ? 0 : amsData->getLastUpdateMillis() - this->lastUpdateMillis;
|
unsigned long ms = this->lastUpdateMillis > amsData->getLastUpdateMillis() ? 0 : amsData->getLastUpdateMillis() - this->lastUpdateMillis;
|
||||||
float kwh = (amsData->getActiveImportPower() * (((float) ms) / 3600000.0)) / 1000.0;
|
float kwhi = (amsData->getActiveImportPower() * (((float) ms) / 3600000.0)) / 1000.0;
|
||||||
|
float kwhe = (amsData->getActiveExportPower() * (((float) ms) / 3600000.0)) / 1000.0;
|
||||||
lastUpdateMillis = amsData->getLastUpdateMillis();
|
lastUpdateMillis = amsData->getLastUpdateMillis();
|
||||||
if(kwh > 0) {
|
if(kwhi > 0) {
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(EnergyAccounting) Adding %.4f kWh\n", kwh);
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(EnergyAccounting) Adding %.4f kWh import\n", kwhi);
|
||||||
use += kwh;
|
use += kwhi;
|
||||||
if(eapi != NULL && eapi->getValueForHour(0) != ENTSOE_NO_VALUE) {
|
if(eapi != NULL && eapi->getValueForHour(0) != ENTSOE_NO_VALUE) {
|
||||||
float price = eapi->getValueForHour(0);
|
float price = eapi->getValueForHour(0);
|
||||||
float cost = price * kwh;
|
float cost = price * kwhi;
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(EnergyAccounting) and %.4f %s\n", cost / 100.0, eapi->getCurrency());
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(EnergyAccounting) and %.4f %s\n", cost / 100.0, eapi->getCurrency());
|
||||||
costHour += cost;
|
costHour += cost;
|
||||||
costDay += cost;
|
costDay += cost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(kwhe > 0) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(EnergyAccounting) Adding %.4f kWh export\n", kwhe);
|
||||||
|
produce += kwhe;
|
||||||
|
}
|
||||||
|
|
||||||
if(config != NULL) {
|
if(config != NULL) {
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(EnergyAccounting) calculating threshold, currently at %d\n", currentThresholdIdx);
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(EnergyAccounting) calculating threshold, currently at %d\n", currentThresholdIdx);
|
||||||
@@ -136,10 +142,10 @@ void EnergyAccounting::calcDayCost() {
|
|||||||
|
|
||||||
if(eapi != NULL && eapi->getValueForHour(0) != ENTSOE_NO_VALUE) {
|
if(eapi != NULL && eapi->getValueForHour(0) != ENTSOE_NO_VALUE) {
|
||||||
if(initPrice) costDay = 0;
|
if(initPrice) costDay = 0;
|
||||||
for(int i = 0; i < local.Hour; i++) {
|
for(int i = 0; i < currentHour; i++) {
|
||||||
float price = eapi->getValueForHour(i - local.Hour);
|
float price = eapi->getValueForHour(i - currentHour);
|
||||||
if(price == ENTSOE_NO_VALUE) break;
|
if(price == ENTSOE_NO_VALUE) break;
|
||||||
breakTime(now - ((local.Hour - i) * 3600), utc);
|
breakTime(now - ((currentHour - i) * 3600), utc);
|
||||||
int16_t wh = ds->getHourImport(utc.Hour);
|
int16_t wh = ds->getHourImport(utc.Hour);
|
||||||
costDay += price * (wh / 1000.0);
|
costDay += price * (wh / 1000.0);
|
||||||
}
|
}
|
||||||
@@ -151,23 +157,59 @@ double EnergyAccounting::getUseThisHour() {
|
|||||||
return use;
|
return use;
|
||||||
}
|
}
|
||||||
|
|
||||||
double EnergyAccounting::getCostThisHour() {
|
|
||||||
return costHour;
|
|
||||||
}
|
|
||||||
|
|
||||||
double EnergyAccounting::getUseToday() {
|
double EnergyAccounting::getUseToday() {
|
||||||
float ret = 0.0;
|
float ret = 0.0;
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
if(now < BUILD_EPOCH) return 0;
|
if(now < BUILD_EPOCH) return 0;
|
||||||
tmElements_t local, utc;
|
tmElements_t utc;
|
||||||
breakTime(tz->toLocal(now), local);
|
for(int i = 0; i < currentHour; i++) {
|
||||||
for(int i = 0; i < local.Hour; i++) {
|
breakTime(now - ((currentHour - i) * 3600), utc);
|
||||||
breakTime(now - ((local.Hour - i) * 3600), utc);
|
|
||||||
ret += ds->getHourImport(utc.Hour) / 1000.0;
|
ret += ds->getHourImport(utc.Hour) / 1000.0;
|
||||||
}
|
}
|
||||||
return ret + getUseThisHour();
|
return ret + getUseThisHour();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double EnergyAccounting::getUseThisMonth() {
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
if(now < BUILD_EPOCH) return 0;
|
||||||
|
float ret = 0;
|
||||||
|
for(int i = 0; i < currentDay; i++) {
|
||||||
|
ret += ds->getDayImport(i) / 1000.0;
|
||||||
|
}
|
||||||
|
return ret + getUseToday();
|
||||||
|
}
|
||||||
|
|
||||||
|
double EnergyAccounting::getProducedThisHour() {
|
||||||
|
return produce;
|
||||||
|
}
|
||||||
|
|
||||||
|
double EnergyAccounting::getProducedToday() {
|
||||||
|
float ret = 0.0;
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
if(now < BUILD_EPOCH) return 0;
|
||||||
|
tmElements_t utc;
|
||||||
|
for(int i = 0; i < currentHour; i++) {
|
||||||
|
breakTime(now - ((currentHour - i) * 3600), utc);
|
||||||
|
ret += ds->getHourExport(utc.Hour) / 1000.0;
|
||||||
|
}
|
||||||
|
return ret + getProducedThisHour();
|
||||||
|
}
|
||||||
|
|
||||||
|
double EnergyAccounting::getProducedThisMonth() {
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
if(now < BUILD_EPOCH) return 0;
|
||||||
|
float ret = 0;
|
||||||
|
for(int i = 0; i < currentDay; i++) {
|
||||||
|
ret += ds->getDayExport(i) / 1000.0;
|
||||||
|
}
|
||||||
|
return ret + getProducedToday();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double EnergyAccounting::getCostThisHour() {
|
||||||
|
return costHour;
|
||||||
|
}
|
||||||
|
|
||||||
double EnergyAccounting::getCostToday() {
|
double EnergyAccounting::getCostToday() {
|
||||||
return costDay;
|
return costDay;
|
||||||
}
|
}
|
||||||
@@ -176,21 +218,6 @@ double EnergyAccounting::getCostYesterday() {
|
|||||||
return data.costYesterday / 10.0;
|
return data.costYesterday / 10.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double EnergyAccounting::getUseThisMonth() {
|
|
||||||
time_t now = time(nullptr);
|
|
||||||
if(now < BUILD_EPOCH) return 0;
|
|
||||||
tmElements_t tm;
|
|
||||||
if(tz != NULL)
|
|
||||||
breakTime(tz->toLocal(now), tm);
|
|
||||||
else
|
|
||||||
breakTime(now, tm);
|
|
||||||
float ret = 0;
|
|
||||||
for(int i = 0; i < tm.Day; i++) {
|
|
||||||
ret += ds->getDayImport(i) / 1000.0;
|
|
||||||
}
|
|
||||||
return ret + getUseToday();
|
|
||||||
}
|
|
||||||
|
|
||||||
double EnergyAccounting::getCostThisMonth() {
|
double EnergyAccounting::getCostThisMonth() {
|
||||||
return data.costThisMonth + getCostToday();
|
return data.costThisMonth + getCostToday();
|
||||||
}
|
}
|
||||||
@@ -251,6 +278,7 @@ bool EnergyAccounting::load() {
|
|||||||
if(buf[0] == 4) {
|
if(buf[0] == 4) {
|
||||||
EnergyAccountingData* data = (EnergyAccountingData*) buf;
|
EnergyAccountingData* data = (EnergyAccountingData*) buf;
|
||||||
memcpy(&this->data, data, sizeof(this->data));
|
memcpy(&this->data, data, sizeof(this->data));
|
||||||
|
ret = true;
|
||||||
} else if(buf[0] == 3) {
|
} else if(buf[0] == 3) {
|
||||||
EnergyAccountingData* data = (EnergyAccountingData*) buf;
|
EnergyAccountingData* data = (EnergyAccountingData*) buf;
|
||||||
this->data = { 4, data->month,
|
this->data = { 4, data->month,
|
||||||
|
|||||||
@@ -42,11 +42,16 @@ public:
|
|||||||
bool save();
|
bool save();
|
||||||
|
|
||||||
double getUseThisHour();
|
double getUseThisHour();
|
||||||
double getCostThisHour();
|
|
||||||
double getUseToday();
|
double getUseToday();
|
||||||
|
double getUseThisMonth();
|
||||||
|
|
||||||
|
double getProducedThisHour();
|
||||||
|
double getProducedToday();
|
||||||
|
double getProducedThisMonth();
|
||||||
|
|
||||||
|
double getCostThisHour();
|
||||||
double getCostToday();
|
double getCostToday();
|
||||||
double getCostYesterday();
|
double getCostYesterday();
|
||||||
double getUseThisMonth();
|
|
||||||
double getCostThisMonth();
|
double getCostThisMonth();
|
||||||
uint16_t getCostLastMonth();
|
uint16_t getCostLastMonth();
|
||||||
|
|
||||||
@@ -66,6 +71,7 @@ private:
|
|||||||
Timezone *tz = NULL;
|
Timezone *tz = NULL;
|
||||||
uint8_t currentHour = 0, currentDay = 0, currentThresholdIdx = 0;
|
uint8_t currentHour = 0, currentDay = 0, currentThresholdIdx = 0;
|
||||||
double use, costHour, costDay;
|
double use, costHour, costDay;
|
||||||
|
double produce;
|
||||||
EnergyAccountingData data = { 0, 0, 0, 0, 0, 0 };
|
EnergyAccountingData data = { 0, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
void calcDayCost();
|
void calcDayCost();
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En
|
|||||||
data->getMeterTimestamp()
|
data->getMeterTimestamp()
|
||||||
);
|
);
|
||||||
mqtt->publish(topic + "/energy", json);
|
mqtt->publish(topic + "/energy", json);
|
||||||
|
mqtt->loop();
|
||||||
}
|
}
|
||||||
String meterModel = data->getMeterModel();
|
String meterModel = data->getMeterModel();
|
||||||
meterModel.replace("\\", "\\\\");
|
meterModel.replace("\\", "\\\\");
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccou
|
|||||||
ea->getUseThisHour(),
|
ea->getUseThisHour(),
|
||||||
ea->getUseToday(),
|
ea->getUseToday(),
|
||||||
ea->getCurrentThreshold(),
|
ea->getCurrentThreshold(),
|
||||||
ea->getMonthMax()
|
ea->getMonthMax(),
|
||||||
|
ea->getProducedThisHour(),
|
||||||
|
ea->getProducedToday()
|
||||||
);
|
);
|
||||||
return mqtt->publish(topic, json);
|
return mqtt->publish(topic, json);
|
||||||
} else if(data->getListType() == 2) {
|
} else if(data->getListType() == 2) {
|
||||||
@@ -55,7 +57,9 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccou
|
|||||||
ea->getUseThisHour(),
|
ea->getUseThisHour(),
|
||||||
ea->getUseToday(),
|
ea->getUseToday(),
|
||||||
ea->getCurrentThreshold(),
|
ea->getCurrentThreshold(),
|
||||||
ea->getMonthMax()
|
ea->getMonthMax(),
|
||||||
|
ea->getProducedThisHour(),
|
||||||
|
ea->getProducedToday()
|
||||||
);
|
);
|
||||||
return mqtt->publish(topic, json);
|
return mqtt->publish(topic, json);
|
||||||
} else if(data->getListType() == 3) {
|
} else if(data->getListType() == 3) {
|
||||||
@@ -88,7 +92,9 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccou
|
|||||||
ea->getUseThisHour(),
|
ea->getUseThisHour(),
|
||||||
ea->getUseToday(),
|
ea->getUseToday(),
|
||||||
ea->getCurrentThreshold(),
|
ea->getCurrentThreshold(),
|
||||||
ea->getMonthMax()
|
ea->getMonthMax(),
|
||||||
|
ea->getProducedThisHour(),
|
||||||
|
ea->getProducedToday()
|
||||||
);
|
);
|
||||||
return mqtt->publish(topic, json);
|
return mqtt->publish(topic, json);
|
||||||
} else if(data->getListType() == 4) {
|
} else if(data->getListType() == 4) {
|
||||||
@@ -125,7 +131,9 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccou
|
|||||||
ea->getUseThisHour(),
|
ea->getUseThisHour(),
|
||||||
ea->getUseToday(),
|
ea->getUseToday(),
|
||||||
ea->getCurrentThreshold(),
|
ea->getCurrentThreshold(),
|
||||||
ea->getMonthMax()
|
ea->getMonthMax(),
|
||||||
|
ea->getProducedThisHour(),
|
||||||
|
ea->getProducedToday()
|
||||||
);
|
);
|
||||||
return mqtt->publish(topic, json);
|
return mqtt->publish(topic, json);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState, EnergyAccountin
|
|||||||
mqtt->publish(topic + "/realtime/import/day", String(ea->getUseToday(), 2));
|
mqtt->publish(topic + "/realtime/import/day", String(ea->getUseToday(), 2));
|
||||||
mqtt->publish(topic + "/realtime/import/threshold", String(ea->getCurrentThreshold(), 10), true, 0);
|
mqtt->publish(topic + "/realtime/import/threshold", String(ea->getCurrentThreshold(), 10), true, 0);
|
||||||
mqtt->publish(topic + "/realtime/import/monthmax", String(ea->getMonthMax(), 3), true, 0);
|
mqtt->publish(topic + "/realtime/import/monthmax", String(ea->getMonthMax(), 3), true, 0);
|
||||||
|
mqtt->publish(topic + "/realtime/export/hour", String(ea->getProducedThisHour(), 3));
|
||||||
|
mqtt->publish(topic + "/realtime/export/day", String(ea->getProducedToday(), 2));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -747,10 +747,13 @@ void AmsWebServer::dataJson() {
|
|||||||
ea->getCurrentThreshold(),
|
ea->getCurrentThreshold(),
|
||||||
ea->getUseThisHour(),
|
ea->getUseThisHour(),
|
||||||
ea->getCostThisHour(),
|
ea->getCostThisHour(),
|
||||||
|
ea->getProducedThisHour(),
|
||||||
ea->getUseToday(),
|
ea->getUseToday(),
|
||||||
ea->getCostToday(),
|
ea->getCostToday(),
|
||||||
|
ea->getProducedToday(),
|
||||||
ea->getUseThisMonth(),
|
ea->getUseThisMonth(),
|
||||||
ea->getCostThisMonth(),
|
ea->getCostThisMonth(),
|
||||||
|
ea->getProducedThisMonth(),
|
||||||
(uint32_t) time(nullptr)
|
(uint32_t) time(nullptr)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -927,42 +930,42 @@ void AmsWebServer::energyPriceJson() {
|
|||||||
|
|
||||||
snprintf_P(buf, BufferSize, ENERGYPRICE_JSON,
|
snprintf_P(buf, BufferSize, ENERGYPRICE_JSON,
|
||||||
eapi == NULL ? "" : eapi->getCurrency(),
|
eapi == NULL ? "" : eapi->getCurrency(),
|
||||||
prices[0] == ENTSOE_NO_VALUE ? "null" : String(prices[0], 2).c_str(),
|
prices[0] == ENTSOE_NO_VALUE ? "null" : String(prices[0], 4).c_str(),
|
||||||
prices[1] == ENTSOE_NO_VALUE ? "null" : String(prices[1], 2).c_str(),
|
prices[1] == ENTSOE_NO_VALUE ? "null" : String(prices[1], 4).c_str(),
|
||||||
prices[2] == ENTSOE_NO_VALUE ? "null" : String(prices[2], 2).c_str(),
|
prices[2] == ENTSOE_NO_VALUE ? "null" : String(prices[2], 4).c_str(),
|
||||||
prices[3] == ENTSOE_NO_VALUE ? "null" : String(prices[3], 2).c_str(),
|
prices[3] == ENTSOE_NO_VALUE ? "null" : String(prices[3], 4).c_str(),
|
||||||
prices[4] == ENTSOE_NO_VALUE ? "null" : String(prices[4], 2).c_str(),
|
prices[4] == ENTSOE_NO_VALUE ? "null" : String(prices[4], 4).c_str(),
|
||||||
prices[5] == ENTSOE_NO_VALUE ? "null" : String(prices[5], 2).c_str(),
|
prices[5] == ENTSOE_NO_VALUE ? "null" : String(prices[5], 4).c_str(),
|
||||||
prices[6] == ENTSOE_NO_VALUE ? "null" : String(prices[6], 2).c_str(),
|
prices[6] == ENTSOE_NO_VALUE ? "null" : String(prices[6], 4).c_str(),
|
||||||
prices[7] == ENTSOE_NO_VALUE ? "null" : String(prices[7], 2).c_str(),
|
prices[7] == ENTSOE_NO_VALUE ? "null" : String(prices[7], 4).c_str(),
|
||||||
prices[8] == ENTSOE_NO_VALUE ? "null" : String(prices[8], 2).c_str(),
|
prices[8] == ENTSOE_NO_VALUE ? "null" : String(prices[8], 4).c_str(),
|
||||||
prices[9] == ENTSOE_NO_VALUE ? "null" : String(prices[9], 2).c_str(),
|
prices[9] == ENTSOE_NO_VALUE ? "null" : String(prices[9], 4).c_str(),
|
||||||
prices[10] == ENTSOE_NO_VALUE ? "null" : String(prices[10], 2).c_str(),
|
prices[10] == ENTSOE_NO_VALUE ? "null" : String(prices[10], 4).c_str(),
|
||||||
prices[11] == ENTSOE_NO_VALUE ? "null" : String(prices[11], 2).c_str(),
|
prices[11] == ENTSOE_NO_VALUE ? "null" : String(prices[11], 4).c_str(),
|
||||||
prices[12] == ENTSOE_NO_VALUE ? "null" : String(prices[12], 2).c_str(),
|
prices[12] == ENTSOE_NO_VALUE ? "null" : String(prices[12], 4).c_str(),
|
||||||
prices[13] == ENTSOE_NO_VALUE ? "null" : String(prices[13], 2).c_str(),
|
prices[13] == ENTSOE_NO_VALUE ? "null" : String(prices[13], 4).c_str(),
|
||||||
prices[14] == ENTSOE_NO_VALUE ? "null" : String(prices[14], 2).c_str(),
|
prices[14] == ENTSOE_NO_VALUE ? "null" : String(prices[14], 4).c_str(),
|
||||||
prices[15] == ENTSOE_NO_VALUE ? "null" : String(prices[15], 2).c_str(),
|
prices[15] == ENTSOE_NO_VALUE ? "null" : String(prices[15], 4).c_str(),
|
||||||
prices[16] == ENTSOE_NO_VALUE ? "null" : String(prices[16], 2).c_str(),
|
prices[16] == ENTSOE_NO_VALUE ? "null" : String(prices[16], 4).c_str(),
|
||||||
prices[17] == ENTSOE_NO_VALUE ? "null" : String(prices[17], 2).c_str(),
|
prices[17] == ENTSOE_NO_VALUE ? "null" : String(prices[17], 4).c_str(),
|
||||||
prices[18] == ENTSOE_NO_VALUE ? "null" : String(prices[18], 2).c_str(),
|
prices[18] == ENTSOE_NO_VALUE ? "null" : String(prices[18], 4).c_str(),
|
||||||
prices[19] == ENTSOE_NO_VALUE ? "null" : String(prices[19], 2).c_str(),
|
prices[19] == ENTSOE_NO_VALUE ? "null" : String(prices[19], 4).c_str(),
|
||||||
prices[20] == ENTSOE_NO_VALUE ? "null" : String(prices[20], 2).c_str(),
|
prices[20] == ENTSOE_NO_VALUE ? "null" : String(prices[20], 4).c_str(),
|
||||||
prices[21] == ENTSOE_NO_VALUE ? "null" : String(prices[21], 2).c_str(),
|
prices[21] == ENTSOE_NO_VALUE ? "null" : String(prices[21], 4).c_str(),
|
||||||
prices[22] == ENTSOE_NO_VALUE ? "null" : String(prices[22], 2).c_str(),
|
prices[22] == ENTSOE_NO_VALUE ? "null" : String(prices[22], 4).c_str(),
|
||||||
prices[23] == ENTSOE_NO_VALUE ? "null" : String(prices[23], 2).c_str(),
|
prices[23] == ENTSOE_NO_VALUE ? "null" : String(prices[23], 4).c_str(),
|
||||||
prices[24] == ENTSOE_NO_VALUE ? "null" : String(prices[24], 2).c_str(),
|
prices[24] == ENTSOE_NO_VALUE ? "null" : String(prices[24], 4).c_str(),
|
||||||
prices[25] == ENTSOE_NO_VALUE ? "null" : String(prices[25], 2).c_str(),
|
prices[25] == ENTSOE_NO_VALUE ? "null" : String(prices[25], 4).c_str(),
|
||||||
prices[26] == ENTSOE_NO_VALUE ? "null" : String(prices[26], 2).c_str(),
|
prices[26] == ENTSOE_NO_VALUE ? "null" : String(prices[26], 4).c_str(),
|
||||||
prices[27] == ENTSOE_NO_VALUE ? "null" : String(prices[27], 2).c_str(),
|
prices[27] == ENTSOE_NO_VALUE ? "null" : String(prices[27], 4).c_str(),
|
||||||
prices[28] == ENTSOE_NO_VALUE ? "null" : String(prices[28], 2).c_str(),
|
prices[28] == ENTSOE_NO_VALUE ? "null" : String(prices[28], 4).c_str(),
|
||||||
prices[29] == ENTSOE_NO_VALUE ? "null" : String(prices[29], 2).c_str(),
|
prices[29] == ENTSOE_NO_VALUE ? "null" : String(prices[29], 4).c_str(),
|
||||||
prices[30] == ENTSOE_NO_VALUE ? "null" : String(prices[30], 2).c_str(),
|
prices[30] == ENTSOE_NO_VALUE ? "null" : String(prices[30], 4).c_str(),
|
||||||
prices[31] == ENTSOE_NO_VALUE ? "null" : String(prices[31], 2).c_str(),
|
prices[31] == ENTSOE_NO_VALUE ? "null" : String(prices[31], 4).c_str(),
|
||||||
prices[32] == ENTSOE_NO_VALUE ? "null" : String(prices[32], 2).c_str(),
|
prices[32] == ENTSOE_NO_VALUE ? "null" : String(prices[32], 4).c_str(),
|
||||||
prices[33] == ENTSOE_NO_VALUE ? "null" : String(prices[33], 2).c_str(),
|
prices[33] == ENTSOE_NO_VALUE ? "null" : String(prices[33], 4).c_str(),
|
||||||
prices[34] == ENTSOE_NO_VALUE ? "null" : String(prices[34], 2).c_str(),
|
prices[34] == ENTSOE_NO_VALUE ? "null" : String(prices[34], 4).c_str(),
|
||||||
prices[35] == ENTSOE_NO_VALUE ? "null" : String(prices[35], 2).c_str()
|
prices[35] == ENTSOE_NO_VALUE ? "null" : String(prices[35], 4).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||||
@@ -1036,7 +1039,7 @@ void AmsWebServer::handleSetup() {
|
|||||||
gpioConfig->ledPinRed = 13;
|
gpioConfig->ledPinRed = 13;
|
||||||
gpioConfig->ledPinGreen = 14;
|
gpioConfig->ledPinGreen = 14;
|
||||||
gpioConfig->ledRgbInverted = true;
|
gpioConfig->ledRgbInverted = true;
|
||||||
gpioConfig->vccPin = 35;
|
gpioConfig->vccPin = 10;
|
||||||
gpioConfig->vccResistorGnd = 22;
|
gpioConfig->vccResistorGnd = 22;
|
||||||
gpioConfig->vccResistorVcc = 33;
|
gpioConfig->vccResistorVcc = 33;
|
||||||
break;
|
break;
|
||||||
@@ -1659,7 +1662,7 @@ void AmsWebServer::firmwareUpload() {
|
|||||||
}
|
}
|
||||||
uploadFile(FILE_FIRMWARE);
|
uploadFile(FILE_FIRMWARE);
|
||||||
if(upload.status == UPLOAD_FILE_END) {
|
if(upload.status == UPLOAD_FILE_END) {
|
||||||
performRestart = true;
|
rebootForUpgrade = true;
|
||||||
server.sendHeader("Location","/restart-wait");
|
server.sendHeader("Location","/restart-wait");
|
||||||
server.send(303);
|
server.send(303);
|
||||||
}
|
}
|
||||||
@@ -1672,109 +1675,9 @@ void AmsWebServer::firmwareDownload() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
printD("Firmware download URL triggered");
|
printD("Firmware download URL triggered");
|
||||||
if(server.hasArg("version")) {
|
performUpgrade = true;
|
||||||
String version = server.arg("version");
|
server.sendHeader("Location","/restart-wait");
|
||||||
String versionStripped = version.substring(1);
|
server.send(303);
|
||||||
printI("Downloading firmware...");
|
|
||||||
HTTPClient httpClient;
|
|
||||||
httpClient.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
|
||||||
httpClient.setReuse(false);
|
|
||||||
httpClient.setTimeout(60000);
|
|
||||||
httpClient.setUserAgent("ams2mqtt/" + String(VERSION));
|
|
||||||
|
|
||||||
#if defined(ESP8266)
|
|
||||||
WiFiClient client;
|
|
||||||
String url = "http://ams2mqtt.no23.cc/releases/download/" + version + "/ams2mqtt-esp8266-" + versionStripped + ".bin";
|
|
||||||
/*
|
|
||||||
t_httpUpdate_return ret = ESPhttpUpdate.update(client, url, VERSION);
|
|
||||||
switch(ret) {
|
|
||||||
case HTTP_UPDATE_FAILED:
|
|
||||||
printE("[update] Update failed.");
|
|
||||||
server.sendHeader("Location","/");
|
|
||||||
server.send(303);
|
|
||||||
break;
|
|
||||||
case HTTP_UPDATE_NO_UPDATES:
|
|
||||||
printI("[update] Update no Update.");
|
|
||||||
server.sendHeader("Location","/");
|
|
||||||
server.send(303);
|
|
||||||
break;
|
|
||||||
case HTTP_UPDATE_OK:
|
|
||||||
printI("[update] Update ok."); // may not be called since we reboot the ESP
|
|
||||||
performRestart = true;
|
|
||||||
server.sendHeader("Location","/restart-wait");
|
|
||||||
server.send(303);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
*/
|
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
|
||||||
httpClient.setConnectTimeout(60000);
|
|
||||||
String url = "https://github.com/gskjold/AmsToMqttBridge/releases/download/" + version + "/ams2mqtt-esp32s2-" + versionStripped + ".bin";
|
|
||||||
httpClient.addHeader("Referer", "https://github.com/gskjold/AmsToMqttBridge/releases");
|
|
||||||
#elif defined(ESP32)
|
|
||||||
httpClient.setConnectTimeout(60000);
|
|
||||||
#if defined(CONFIG_FREERTOS_UNICORE)
|
|
||||||
String url = "https://github.com/gskjold/AmsToMqttBridge/releases/download/" + version + "/ams2mqtt-esp32solo-" + versionStripped + ".bin";
|
|
||||||
#else
|
|
||||||
String url = "https://github.com/gskjold/AmsToMqttBridge/releases/download/" + version + "/ams2mqtt-esp32-" + versionStripped + ".bin";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
httpClient.addHeader("Referer", "https://github.com/gskjold/AmsToMqttBridge/releases");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printD("Downloading from URL:");
|
|
||||||
printD(url);
|
|
||||||
|
|
||||||
#if defined(ESP8266)
|
|
||||||
if(httpClient.begin(client, url)) {
|
|
||||||
#elif defined(ESP32)
|
|
||||||
if(httpClient.begin(url)) {
|
|
||||||
#endif
|
|
||||||
printD("HTTP client setup successful");
|
|
||||||
int status = httpClient.GET();
|
|
||||||
if(status == HTTP_CODE_OK) {
|
|
||||||
printD("Received OK from server");
|
|
||||||
if(LittleFS.begin()) {
|
|
||||||
#if defined(ESP32)
|
|
||||||
esp_task_wdt_delete(NULL);
|
|
||||||
esp_task_wdt_deinit();
|
|
||||||
#elif defined(ESP8266)
|
|
||||||
ESP.wdtDisable();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printI("Downloading firmware to LittleFS");
|
|
||||||
file = LittleFS.open(FILE_FIRMWARE, "w");
|
|
||||||
int len = httpClient.writeToStream(&file);
|
|
||||||
file.close();
|
|
||||||
LittleFS.end();
|
|
||||||
performRestart = true;
|
|
||||||
server.sendHeader("Location","/restart-wait");
|
|
||||||
server.send(303);
|
|
||||||
} else {
|
|
||||||
printE("Unable to open LittleFS for writing");
|
|
||||||
server.sendHeader("Location","/");
|
|
||||||
server.send(303);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
printE("Communication error: ");
|
|
||||||
debugger->printf("%d\n", status);
|
|
||||||
printE(httpClient.errorToString(status));
|
|
||||||
printD(httpClient.getString());
|
|
||||||
server.sendHeader("Location","/");
|
|
||||||
server.send(303);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
printE("Unable to configure HTTP client");
|
|
||||||
server.sendHeader("Location","/");
|
|
||||||
server.send(303);
|
|
||||||
}
|
|
||||||
httpClient.end();
|
|
||||||
} else {
|
|
||||||
printI("No firmware version specified...");
|
|
||||||
server.sendHeader("Location","/");
|
|
||||||
server.send(303);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsWebServer::restartHtml() {
|
void AmsWebServer::restartHtml() {
|
||||||
@@ -1824,6 +1727,14 @@ void AmsWebServer::restartWaitHtml() {
|
|||||||
}
|
}
|
||||||
html.replace("${hostname}", wifi.hostname);
|
html.replace("${hostname}", wifi.hostname);
|
||||||
|
|
||||||
|
if(performUpgrade || rebootForUpgrade) {
|
||||||
|
html.replace("{rs}", "d-none");
|
||||||
|
html.replace("{us}", "");
|
||||||
|
} else {
|
||||||
|
html.replace("{rs}", "");
|
||||||
|
html.replace("{us}", "d-none");
|
||||||
|
}
|
||||||
|
|
||||||
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||||
server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE);
|
server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE);
|
||||||
server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF);
|
server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF);
|
||||||
@@ -1832,7 +1743,7 @@ void AmsWebServer::restartWaitHtml() {
|
|||||||
server.send(200, MIME_HTML, html);
|
server.send(200, MIME_HTML, html);
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
if(performRestart) {
|
if(performRestart || rebootForUpgrade) {
|
||||||
if(ds != NULL) {
|
if(ds != NULL) {
|
||||||
ds->save();
|
ds->save();
|
||||||
}
|
}
|
||||||
@@ -1844,6 +1755,40 @@ void AmsWebServer::restartWaitHtml() {
|
|||||||
ESP.restart();
|
ESP.restart();
|
||||||
#endif
|
#endif
|
||||||
performRestart = false;
|
performRestart = false;
|
||||||
|
} else if(performUpgrade) {
|
||||||
|
WiFiClient client;
|
||||||
|
String url = "http://ams2mqtt.rewiredinvent.no/hub/firmware/update";
|
||||||
|
#if defined(ESP8266)
|
||||||
|
String chipType = "esp8266";
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
String chipType = "esp32s2";
|
||||||
|
#elif defined(ESP32)
|
||||||
|
#if defined(CONFIG_FREERTOS_UNICORE)
|
||||||
|
String chipType = "esp32solo";
|
||||||
|
#else
|
||||||
|
String chipType = "esp32";
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
|
t_httpUpdate_return ret = ESPhttpUpdate.update(client, url, VERSION);
|
||||||
|
#elif defined(ESP32)
|
||||||
|
HTTPUpdate httpUpdate;
|
||||||
|
HTTPUpdateResult ret = httpUpdate.update(client, url, String(VERSION) + "-" + chipType);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(ret) {
|
||||||
|
case HTTP_UPDATE_FAILED:
|
||||||
|
printE("Update failed");
|
||||||
|
break;
|
||||||
|
case HTTP_UPDATE_NO_UPDATES:
|
||||||
|
printI("No Update");
|
||||||
|
break;
|
||||||
|
case HTTP_UPDATE_OK:
|
||||||
|
printI("Update OK");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
performUpgrade = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <WebServer.h>
|
#include <WebServer.h>
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
|
#include <HTTPUpdate.h>
|
||||||
#else
|
#else
|
||||||
#warning "Unsupported board type"
|
#warning "Unsupported board type"
|
||||||
#endif
|
#endif
|
||||||
@@ -58,6 +59,8 @@ private:
|
|||||||
bool uploading = false;
|
bool uploading = false;
|
||||||
File file;
|
File file;
|
||||||
bool performRestart = false;
|
bool performRestart = false;
|
||||||
|
bool performUpgrade = false;
|
||||||
|
bool rebootForUpgrade = false;
|
||||||
|
|
||||||
static const uint16_t BufferSize = 2048;
|
static const uint16_t BufferSize = 2048;
|
||||||
char* buf;
|
char* buf;
|
||||||
|
|||||||
@@ -478,7 +478,7 @@ var drawDay = function() {
|
|||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
}).done(function(json) {
|
}).done(function(json) {
|
||||||
data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }]];
|
data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }, { role: 'annotation' }]];
|
||||||
var r = 1;
|
var r = 1;
|
||||||
var hour = moment.utc().hours();
|
var hour = moment.utc().hours();
|
||||||
var offset = moment().utcOffset()/60;
|
var offset = moment().utcOffset()/60;
|
||||||
@@ -486,13 +486,13 @@ var drawDay = function() {
|
|||||||
for(var i = hour; i<24; i++) {
|
for(var i = hour; i<24; i++) {
|
||||||
var imp = json["i"+zeropad(i)];
|
var imp = json["i"+zeropad(i)];
|
||||||
var exp = json["e"+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;"];
|
data[r++] = [zeropad((i+offset)%24), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(1), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(1)];
|
||||||
min = Math.min(0, -exp);
|
min = Math.min(0, -exp);
|
||||||
};
|
};
|
||||||
for(var i = 0; i < hour; i++) {
|
for(var i = 0; i < hour; i++) {
|
||||||
var imp = json["i"+zeropad(i)];
|
var imp = json["i"+zeropad(i)];
|
||||||
var exp = json["e"+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;"];
|
data[r++] = [zeropad((i+offset)%24), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(1), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(1)];
|
||||||
min = Math.min(0, -exp);
|
min = Math.min(0, -exp);
|
||||||
};
|
};
|
||||||
ea = google.visualization.arrayToDataTable(data);
|
ea = google.visualization.arrayToDataTable(data);
|
||||||
@@ -511,7 +511,7 @@ var drawMonth = function() {
|
|||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
}).done(function(json) {
|
}).done(function(json) {
|
||||||
data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }]];
|
data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }, { role: 'annotation' }]];
|
||||||
var r = 1;
|
var r = 1;
|
||||||
var day = moment().date();
|
var day = moment().date();
|
||||||
var eom = moment().subtract(1, 'months').endOf('month').date();
|
var eom = moment().subtract(1, 'months').endOf('month').date();
|
||||||
@@ -519,13 +519,13 @@ var drawMonth = function() {
|
|||||||
for(var i = day; i<=eom; i++) {
|
for(var i = day; i<=eom; i++) {
|
||||||
var imp = json["i"+zeropad(i)];
|
var imp = json["i"+zeropad(i)];
|
||||||
var exp = json["e"+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;"];
|
data[r++] = [zeropad(i), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(0), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(0)];
|
||||||
min = Math.min(0, -exp);
|
min = Math.min(0, -exp);
|
||||||
}
|
}
|
||||||
for(var i = 1; i < day; i++) {
|
for(var i = 1; i < day; i++) {
|
||||||
var imp = json["i"+zeropad(i)];
|
var imp = json["i"+zeropad(i)];
|
||||||
var exp = json["e"+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;"];
|
data[r++] = [zeropad(i), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(0), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(0)];
|
||||||
min = Math.min(0, -exp);
|
min = Math.min(0, -exp);
|
||||||
}
|
}
|
||||||
ma = google.visualization.arrayToDataTable(data);
|
ma = google.visualization.arrayToDataTable(data);
|
||||||
@@ -790,6 +790,12 @@ var fetch = function() {
|
|||||||
if(currency) {
|
if(currency) {
|
||||||
$('.sp').show();
|
$('.sp').show();
|
||||||
}
|
}
|
||||||
|
if(om > 0) {
|
||||||
|
$('.se').removeClass('d-none');
|
||||||
|
$('#eache').html(json.ea.h.p.toFixed(2));
|
||||||
|
$('#eacde').html(json.ea.d.p.toFixed(1));
|
||||||
|
$('#eacme').html(json.ea.m.p.toFixed(0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(json.me) {
|
if(json.me) {
|
||||||
@@ -878,7 +884,7 @@ var fetch = function() {
|
|||||||
|
|
||||||
var upgrade = function() {
|
var upgrade = function() {
|
||||||
if(nextVersion) {
|
if(nextVersion) {
|
||||||
if(confirm("Are you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) {
|
if(confirm("WARNING: Please keep USB power connected while upgrading. Are you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) {
|
||||||
$('#loading-indicator').show();
|
$('#loading-indicator').show();
|
||||||
window.location.href="/upgrade?version=" + nextVersion.tag_name;
|
window.location.href="/upgrade?version=" + nextVersion.tag_name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,15 +38,18 @@
|
|||||||
"t" : %d,
|
"t" : %d,
|
||||||
"h" : {
|
"h" : {
|
||||||
"u" : %.2f,
|
"u" : %.2f,
|
||||||
"c" : %.2f
|
"c" : %.2f,
|
||||||
|
"p" : %.2f
|
||||||
},
|
},
|
||||||
"d" : {
|
"d" : {
|
||||||
"u" : %.2f,
|
"u" : %.2f,
|
||||||
"c" : %.2f
|
"c" : %.2f,
|
||||||
|
"p" : %.2f
|
||||||
},
|
},
|
||||||
"m" : {
|
"m" : {
|
||||||
"u" : %.2f,
|
"u" : %.2f,
|
||||||
"c" : %.2f
|
"c" : %.2f,
|
||||||
|
"p" : %.2f
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"c" : %lu
|
"c" : %lu
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<div id="newVersion" class="alert alert-info d-none">New version <span id="newVersionTag"></span>!
|
<div id="newVersion" class="alert alert-info d-none">New version <span id="newVersionTag"></span>!
|
||||||
<a id="newVersionUrl" href="#" target="_blank">view</a>
|
<a id="newVersionUrl" href="#" target="_blank">view</a> or <a href="javascript:upgrade();">click here to upgrade</a>
|
||||||
<span class="d-none ssl-capable"> or <a href="javascript:upgrade();">upgrade</a></span>
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@@ -3,5 +3,5 @@
|
|||||||
"tPO" : %.2f,
|
"tPO" : %.2f,
|
||||||
"tQI" : %.2f,
|
"tQI" : %.2f,
|
||||||
"tQO" : %.2f,
|
"tQO" : %.2f,
|
||||||
"rtc" : %llu
|
"rtc" : %lu
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@
|
|||||||
|
|
||||||
<div class="col-xl-12 mb-3">
|
<div class="col-xl-12 mb-3">
|
||||||
<div class="bg-white rounded shadow pt-3 pb-3" style="font-size: 14px;">
|
<div class="bg-white rounded shadow pt-3 pb-3" style="font-size: 14px;">
|
||||||
<strong class="mr-3 ml-3">Real time calculation</strong><br/>
|
<strong class="mr-3 ml-3">Real time consumption</strong><br/>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-sm-6">
|
<div class="col-lg-3 col-sm-6">
|
||||||
<div class="mr-3 ml-3 d-flex">
|
<div class="mr-3 ml-3 d-flex">
|
||||||
@@ -151,6 +151,35 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<strong class="mr-3 ml-3 se d-none">Real time production</strong><br/>
|
||||||
|
<div class="row se d-none">
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Hour</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="eache"></span> kWh
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Day</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="eacde"></span> kWh
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Month</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="eacme"></span> kWh
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-sm-6"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
"h" : %.2f,
|
"h" : %.2f,
|
||||||
"d" : %.1f,
|
"d" : %.1f,
|
||||||
"t" : %d,
|
"t" : %d,
|
||||||
"x" : %.2f
|
"x" : %.2f,
|
||||||
|
"he" : %.2f,
|
||||||
|
"de" : %.1f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
"h" : %.2f,
|
"h" : %.2f,
|
||||||
"d" : %.1f,
|
"d" : %.1f,
|
||||||
"t" : %d,
|
"t" : %d,
|
||||||
"x" : %.2f
|
"x" : %.2f,
|
||||||
|
"he" : %.2f,
|
||||||
|
"de" : %.1f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
"h" : %.2f,
|
"h" : %.2f,
|
||||||
"d" : %.1f,
|
"d" : %.1f,
|
||||||
"t" : %d,
|
"t" : %d,
|
||||||
"x" : %.2f
|
"x" : %.2f,
|
||||||
|
"he" : %.2f,
|
||||||
|
"de" : %.1f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
"h" : %.2f,
|
"h" : %.2f,
|
||||||
"d" : %.1f,
|
"d" : %.1f,
|
||||||
"t" : %d,
|
"t" : %d,
|
||||||
"x" : %.2f
|
"x" : %.2f,
|
||||||
|
"he" : %.2f,
|
||||||
|
"de" : %.1f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,10 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</header>
|
</header>
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
<div class="my-3 p-3 bg-white rounded shadow {rs}">
|
||||||
Device is rebooting. You will be redirected to the main page when it is available again.
|
Device is rebooting. You will be redirected to the main page when it is available again.
|
||||||
</div>
|
</div>
|
||||||
|
<div class="alert alert-warning shadow {us}">Firmware upgrade in progress, DO NOT disconnect power from the device. You will be redirected to the main page when firmware upgrade is complete.</div>
|
||||||
</main>
|
</main>
|
||||||
<script>
|
<script>
|
||||||
var tries = 0;
|
var tries = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user