mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-15 08:22:10 +00:00
Merge branch 'master' into hub-prices
This commit is contained in:
commit
07ed425320
@ -743,7 +743,7 @@ bool AmsConfiguration::relocateConfig86() {
|
||||
}
|
||||
|
||||
bool AmsConfiguration::relocateConfig87() {
|
||||
MeterConfig87 meter87;
|
||||
MeterConfig87 meter87 = {0,0,0,0,0,0,0};
|
||||
MeterConfig meter;
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_METER_START_87, meter87);
|
||||
|
||||
@ -45,6 +45,12 @@ void AmsData::apply(AmsData& other) {
|
||||
this->l1PowerFactor = other.getL1PowerFactor();
|
||||
this->l2PowerFactor = other.getL2PowerFactor();
|
||||
this->l3PowerFactor = other.getL3PowerFactor();
|
||||
this->l1activeImportPower = other.getL1ActiveImportPower();
|
||||
this->l2activeImportPower = other.getL2ActiveImportPower();
|
||||
this->l3activeImportPower = other.getL3ActiveImportPower();
|
||||
this->l1activeExportPower = other.getL1ActiveExportPower();
|
||||
this->l2activeExportPower = other.getL2ActiveExportPower();
|
||||
this->l3activeExportPower = other.getL3ActiveExportPower();
|
||||
case 3:
|
||||
this->meterTimestamp = other.getMeterTimestamp();
|
||||
this->activeImportCounter = other.getActiveImportCounter();
|
||||
@ -161,6 +167,30 @@ float AmsData::getL3PowerFactor() {
|
||||
return this->l3PowerFactor;
|
||||
}
|
||||
|
||||
float AmsData::getL1ActiveImportPower() {
|
||||
return this->l1activeImportPower;
|
||||
}
|
||||
|
||||
float AmsData::getL2ActiveImportPower() {
|
||||
return this->l2activeImportPower;
|
||||
}
|
||||
|
||||
float AmsData::getL3ActiveImportPower() {
|
||||
return this->l3activeImportPower;
|
||||
}
|
||||
|
||||
float AmsData::getL1ActiveExportPower() {
|
||||
return this->l1activeExportPower;
|
||||
}
|
||||
|
||||
float AmsData::getL2ActiveExportPower() {
|
||||
return this->l2activeExportPower;
|
||||
}
|
||||
|
||||
float AmsData::getL3ActiveExportPower() {
|
||||
return this->l3activeExportPower;
|
||||
}
|
||||
|
||||
double AmsData::getActiveImportCounter() {
|
||||
return this->activeImportCounter;
|
||||
}
|
||||
|
||||
@ -54,6 +54,14 @@ public:
|
||||
float getL2PowerFactor();
|
||||
float getL3PowerFactor();
|
||||
|
||||
float getL1ActiveImportPower();
|
||||
float getL2ActiveImportPower();
|
||||
float getL3ActiveImportPower();
|
||||
|
||||
float getL1ActiveExportPower();
|
||||
float getL2ActiveExportPower();
|
||||
float getL3ActiveExportPower();
|
||||
|
||||
double getActiveImportCounter();
|
||||
double getReactiveImportCounter();
|
||||
double getActiveExportCounter();
|
||||
@ -71,6 +79,8 @@ protected:
|
||||
time_t meterTimestamp = 0;
|
||||
uint16_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0;
|
||||
float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0;
|
||||
float l1activeImportPower = 0, l2activeImportPower = 0, l3activeImportPower = 0;
|
||||
float l1activeExportPower = 0, l2activeExportPower = 0, l3activeExportPower = 0;
|
||||
float powerFactor = 0, l1PowerFactor = 0, l2PowerFactor = 0, l3PowerFactor = 0;
|
||||
double activeImportCounter = 0, reactiveImportCounter = 0, activeExportCounter = 0, reactiveExportCounter = 0;
|
||||
bool threePhase = false, twoPhase = false, counterEstimated = false;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#ifndef _AMSTOMQTTBRIDGE_H
|
||||
#define _AMSTOMQTTBRIDGE_H
|
||||
|
||||
#define WIFI_CONNECTION_TIMEOUT 30000;
|
||||
#define WIFI_CONNECTION_TIMEOUT 30000
|
||||
|
||||
#define INVALID_BUTTON_PIN 0xFFFFFFFF
|
||||
|
||||
|
||||
@ -119,7 +119,6 @@ DLMSParser *dlmsParser = NULL;
|
||||
DSMRParser *dsmrParser = NULL;
|
||||
|
||||
void setup() {
|
||||
WiFiConfig wifi;
|
||||
Serial.begin(115200);
|
||||
|
||||
if(!config.getGpioConfig(gpioConfig)) {
|
||||
@ -243,7 +242,6 @@ void setup() {
|
||||
}
|
||||
|
||||
Debug.setSerialEnabled(true);
|
||||
DebugConfig debug;
|
||||
delay(1);
|
||||
|
||||
float vcc = hw.getVcc();
|
||||
@ -433,6 +431,10 @@ void loop() {
|
||||
}
|
||||
}
|
||||
|
||||
if(now > 10000 && now - lastErrorBlink > 3000) {
|
||||
errorBlink();
|
||||
}
|
||||
|
||||
// Only do normal stuff if we're not booted as AP
|
||||
if (WiFi.getMode() != WIFI_AP) {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
@ -503,10 +505,6 @@ void loop() {
|
||||
MDNS.update();
|
||||
#endif
|
||||
|
||||
if(now > 10000 && now - lastErrorBlink > 3000) {
|
||||
errorBlink();
|
||||
}
|
||||
|
||||
if (mqttEnabled || config.isMqttChanged()) {
|
||||
if(mqtt == NULL || !mqtt->connected() || config.isMqttChanged()) {
|
||||
MQTT_connect();
|
||||
@ -586,7 +584,7 @@ void loop() {
|
||||
if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) {
|
||||
mqttHandler->publishTemperatures(&config, &hw);
|
||||
}
|
||||
debugD("Used %d ms to update temperature", millis()-start);
|
||||
debugD("Used %ld ms to update temperature", millis()-start);
|
||||
}
|
||||
if(now - lastSysupdate > 10000) {
|
||||
if(mqtt != NULL && mqttHandler != NULL && WiFi.getMode() != WIFI_AP && WiFi.status() == WL_CONNECTED && mqtt->connected() && !topic.isEmpty()) {
|
||||
@ -720,22 +718,25 @@ void errorBlink() {
|
||||
if(lastError == 3)
|
||||
lastError = 0;
|
||||
lastErrorBlink = millis();
|
||||
for(;lastError < 3;lastError++) {
|
||||
switch(lastError) {
|
||||
while(lastError < 3) {
|
||||
switch(lastError++) {
|
||||
case 0:
|
||||
if(lastErrorBlink - meterState.getLastUpdateMillis() > 30000) {
|
||||
debugW("No HAN data received last 30s, single blink");
|
||||
hw.ledBlink(LED_RED, 1); // If no message received from AMS in 30 sec, blink once
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(mqttEnabled && mqtt != NULL && mqtt->lastError() != 0) {
|
||||
debugW("MQTT connection not available, double blink");
|
||||
hw.ledBlink(LED_RED, 2); // If MQTT error, blink twice
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(WiFi.getMode() != WIFI_AP && WiFi.status() != WL_CONNECTED) {
|
||||
debugW("WiFi not connected, tripe blink");
|
||||
hw.ledBlink(LED_RED, 3); // If WiFi not connected, blink three times
|
||||
return;
|
||||
}
|
||||
@ -822,6 +823,11 @@ bool readHanPort() {
|
||||
}
|
||||
if(pos == DATA_PARSE_INCOMPLETE) {
|
||||
return false;
|
||||
} else if(pos == DATA_PARSE_UNKNOWN_DATA) {
|
||||
len = len + hanSerial->readBytes(hanBuffer+len, BUF_SIZE_HAN-len);
|
||||
debugPrint(hanBuffer, 0, len);
|
||||
len = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(pos == DATA_PARSE_INTERMEDIATE_SEGMENT) {
|
||||
@ -980,17 +986,34 @@ void debugPrint(byte *buffer, int start, int length) {
|
||||
Debug.println("");
|
||||
}
|
||||
|
||||
unsigned long wifiTimeout = WIFI_CONNECTION_TIMEOUT;
|
||||
unsigned long lastWifiRetry = -WIFI_CONNECTION_TIMEOUT;
|
||||
void WiFi_connect() {
|
||||
if(millis() - lastWifiRetry < wifiTimeout) {
|
||||
delay(50);
|
||||
return;
|
||||
}
|
||||
lastWifiRetry = millis();
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
if(WiFi.status() == WL_DISCONNECTED) {
|
||||
if(millis() - lastWifiRetry < WIFI_CONNECTION_TIMEOUT) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(WiFi.getMode() != WIFI_OFF) {
|
||||
switch(WiFi.status()) {
|
||||
case WL_NO_SSID_AVAIL:
|
||||
debugE("WiFi error, no SSID available");
|
||||
break;
|
||||
case WL_CONNECT_FAILED:
|
||||
debugE("WiFi error, connection failed");
|
||||
break;
|
||||
case WL_CONNECTION_LOST:
|
||||
debugE("WiFi error, connection lost");
|
||||
break;
|
||||
#if defined(ESP8266)
|
||||
case WL_WRONG_PASSWORD:
|
||||
debugE("WiFi error, wrong password");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
debugE("WiFi error, %d", WiFi.status());
|
||||
break;
|
||||
}
|
||||
if(wifiReconnectCount > 3) {
|
||||
ESP.restart();
|
||||
return;
|
||||
@ -1024,11 +1047,13 @@ void WiFi_connect() {
|
||||
WiFi.softAPdisconnect(true);
|
||||
WiFi.enableAP(false);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
#if defined(ESP8266)
|
||||
WiFi.forceSleepBegin();
|
||||
#endif
|
||||
yield();
|
||||
wifiTimeout = 5000;
|
||||
return;
|
||||
}
|
||||
wifiTimeout = WIFI_CONNECTION_TIMEOUT;
|
||||
lastWifiRetry = millis();
|
||||
|
||||
WiFiConfig wifi;
|
||||
if(!config.getWiFiConfig(wifi) || strlen(wifi.ssid) == 0) {
|
||||
@ -1116,16 +1141,16 @@ void WiFi_connect() {
|
||||
|
||||
void mqttMessageReceived(String &topic, String &payload) {
|
||||
debugI("Received message for topic %s", topic.c_str() );
|
||||
if(meterConfig.source == METER_SOURCE_MQTT) {
|
||||
DataParserContext ctx = {payload.length()/2};
|
||||
fromHex(hanBuffer, payload, ctx.length);
|
||||
uint16_t pos = unwrapData(hanBuffer, ctx);
|
||||
//if(meterConfig.source == METER_SOURCE_MQTT) {
|
||||
//DataParserContext ctx = {static_cast<uint8_t>(payload.length()/2)};
|
||||
//fromHex(hanBuffer, payload, ctx.length);
|
||||
//uint16_t pos = unwrapData(hanBuffer, ctx);
|
||||
// TODO: Run through DLMS/DMSR parser and apply AmsData
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
int16_t unwrapData(uint8_t *buf, DataParserContext &context) {
|
||||
int16_t ret;
|
||||
int16_t ret = 0;
|
||||
bool doRet = false;
|
||||
uint16_t end = BUF_SIZE_HAN;
|
||||
uint8_t tag = (*buf);
|
||||
@ -1370,7 +1395,7 @@ void MQTT_connect() {
|
||||
#if defined(ESP8266)
|
||||
if(mqttSecureClient) {
|
||||
time_t epoch = time(nullptr);
|
||||
debugD("Setting NTP time %i for secure MQTT connection", epoch);
|
||||
debugD("Setting NTP time %lld for secure MQTT connection", epoch);
|
||||
mqttSecureClient->setX509Time(epoch);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -57,7 +57,7 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
debugger->printf("(EnergyAccounting) Peak hour from day %d: %d\n", data.peaks[i].day, data.peaks[i].value*10);
|
||||
}
|
||||
debugger->printf("(EnergyAccounting) Loaded cost yesterday: %d, this month: %d, last month: %d\n", data.costYesterday / 10.0, data.costThisMonth, data.costLastMonth);
|
||||
debugger->printf("(EnergyAccounting) Loaded cost yesterday: %.2f, this month: %d, last month: %d\n", data.costYesterday / 10.0, data.costThisMonth, data.costLastMonth);
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
|
||||
@ -371,10 +371,10 @@ bool HwTools::ledOff(uint8_t color) {
|
||||
bool HwTools::ledBlink(uint8_t color, uint8_t blink) {
|
||||
for(int i = 0; i < blink; i++) {
|
||||
if(!ledOn(color)) return false;
|
||||
delay(50);
|
||||
delay(150);
|
||||
ledOff(color);
|
||||
if(i != blink)
|
||||
delay(50);
|
||||
if(i != blink-1)
|
||||
delay(250);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -296,6 +296,38 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, MeterConfig* meterCo
|
||||
l3PowerFactor = val;
|
||||
}
|
||||
|
||||
val = getNumber(AMS_OBIS_ACTIVE_IMPORT_L1, sizeof(AMS_OBIS_ACTIVE_IMPORT_L1), ((char *) (d)));
|
||||
if (val != NOVALUE) {
|
||||
listType = 4;
|
||||
l1activeImportPower = val;
|
||||
}
|
||||
val = getNumber(AMS_OBIS_ACTIVE_IMPORT_L2, sizeof(AMS_OBIS_ACTIVE_IMPORT_L2), ((char *) (d)));
|
||||
if (val != NOVALUE) {
|
||||
listType = 4;
|
||||
l2activeImportPower = val;
|
||||
}
|
||||
val = getNumber(AMS_OBIS_ACTIVE_IMPORT_L3, sizeof(AMS_OBIS_ACTIVE_IMPORT_L3), ((char *) (d)));
|
||||
if (val != NOVALUE) {
|
||||
listType = 4;
|
||||
l3activeImportPower = val;
|
||||
}
|
||||
|
||||
val = getNumber(AMS_OBIS_ACTIVE_EXPORT_L1, sizeof(AMS_OBIS_ACTIVE_EXPORT_L1), ((char *) (d)));
|
||||
if (val != NOVALUE) {
|
||||
listType = 4;
|
||||
l1activeExportPower = val;
|
||||
}
|
||||
val = getNumber(AMS_OBIS_ACTIVE_EXPORT_L2, sizeof(AMS_OBIS_ACTIVE_EXPORT_L2), ((char *) (d)));
|
||||
if (val != NOVALUE) {
|
||||
listType = 4;
|
||||
l2activeExportPower = val;
|
||||
}
|
||||
val = getNumber(AMS_OBIS_ACTIVE_EXPORT_L3, sizeof(AMS_OBIS_ACTIVE_EXPORT_L3), ((char *) (d)));
|
||||
if (val != NOVALUE) {
|
||||
listType = 4;
|
||||
l3activeExportPower = val;
|
||||
}
|
||||
|
||||
if(meterType == AmsTypeKamstrup) {
|
||||
if(listType >= 3) {
|
||||
activeImportCounter *= 10;
|
||||
@ -336,12 +368,16 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, MeterConfig* meterCo
|
||||
if(mid != NULL) {
|
||||
switch(mid->base.type) {
|
||||
case CosemTypeString:
|
||||
memcpy(&meterId, mid->str.data, mid->str.length);
|
||||
memcpy(str, mid->oct.data, mid->oct.length);
|
||||
str[mid->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
meterId[mid->str.length] = 0;
|
||||
break;
|
||||
case CosemTypeOctetString:
|
||||
memcpy(&meterId, mid->oct.data, mid->oct.length);
|
||||
meterId[mid->oct.length] = 0;
|
||||
memcpy(str, mid->str.data, mid->str.length);
|
||||
str[mid->str.length] = 0x00;
|
||||
meterId = String(str);
|
||||
meterId[mid->str.length] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,6 +49,12 @@ private:
|
||||
uint8_t AMS_OBIS_POWER_FACTOR_L1[4] = { 33, 7, 0, 255 };
|
||||
uint8_t AMS_OBIS_POWER_FACTOR_L2[4] = { 53, 7, 0, 255 };
|
||||
uint8_t AMS_OBIS_POWER_FACTOR_L3[4] = { 73, 7, 0, 255 };
|
||||
uint8_t AMS_OBIS_ACTIVE_IMPORT_L1[4] = { 21, 7, 0, 255 };
|
||||
uint8_t AMS_OBIS_ACTIVE_IMPORT_L2[4] = { 41, 7, 0, 255 };
|
||||
uint8_t AMS_OBIS_ACTIVE_IMPORT_L3[4] = { 61, 7, 0, 255 };
|
||||
uint8_t AMS_OBIS_ACTIVE_EXPORT_L1[4] = { 22, 7, 0, 255 };
|
||||
uint8_t AMS_OBIS_ACTIVE_EXPORT_L2[4] = { 42, 7, 0, 255 };
|
||||
uint8_t AMS_OBIS_ACTIVE_EXPORT_L3[4] = { 62, 7, 0, 255 };
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
16
src/LNG.cpp
16
src/LNG.cpp
@ -25,38 +25,38 @@ LNG::LNG(const char* payload, uint8_t useMeterType, MeterConfig* meterConfig, Da
|
||||
if(descriptor->obis[3] == 7) {
|
||||
if(descriptor->obis[4] == 0) {
|
||||
o170 = ntohl(item->dlu.data);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data));
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
|
||||
}
|
||||
} else if(descriptor->obis[3] == 8) {
|
||||
if(descriptor->obis[4] == 0) {
|
||||
activeImportCounter = ntohl(item->dlu.data) / 1000.0;
|
||||
listType = listType >= 3 ? listType : 3;
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data));
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
|
||||
} else if(descriptor->obis[4] == 1) {
|
||||
o181 = ntohl(item->dlu.data);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data));
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
|
||||
} else if(descriptor->obis[4] == 2) {
|
||||
o182 = ntohl(item->dlu.data);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data));
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
|
||||
}
|
||||
}
|
||||
} else if(descriptor->obis[2] == 2) {
|
||||
if(descriptor->obis[3] == 7) {
|
||||
if(descriptor->obis[4] == 0) {
|
||||
o270 = ntohl(item->dlu.data);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data));
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
|
||||
}
|
||||
} else if(descriptor->obis[3] == 8) {
|
||||
if(descriptor->obis[4] == 0) {
|
||||
activeExportCounter = ntohl(item->dlu.data) / 1000.0;
|
||||
listType = listType >= 3 ? listType : 3;
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data));
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
|
||||
} else if(descriptor->obis[4] == 1) {
|
||||
o281 = ntohl(item->dlu.data);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data));
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
|
||||
} else if(descriptor->obis[4] == 2) {
|
||||
o282 = ntohl(item->dlu.data);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %d (dlu)", ntohl(item->dlu.data));
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf(" and value %lu (dlu)", ntohl(item->dlu.data));
|
||||
}
|
||||
}
|
||||
} else if(descriptor->obis[2] == 96) {
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#include "Uptime.h"
|
||||
|
||||
uint32_t _uptime_last_value = 0;
|
||||
uint32_t _uptime_rollovers = 0;
|
||||
|
||||
uint64_t millis64() {
|
||||
uint32_t new_low32 = millis();
|
||||
if (new_low32 < _uptime_last_value) _uptime_rollovers++;
|
||||
|
||||
@ -3,8 +3,6 @@
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
static uint32_t _uptime_last_value = 0;
|
||||
static uint32_t _uptime_rollovers = 0;
|
||||
uint64_t millis64();
|
||||
|
||||
#endif
|
||||
|
||||
@ -4,7 +4,6 @@ int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) {
|
||||
uint16_t crcPos = 0;
|
||||
bool reachedEnd = verified;
|
||||
uint8_t lastByte = 0x00;
|
||||
int c = 0;
|
||||
for(int pos = 0; pos < ctx.length; pos++) {
|
||||
uint8_t b = *(buf+pos);
|
||||
if(pos == 0 && b != '/') return DATA_PARSE_BOUNDRY_FLAG_MISSING;
|
||||
|
||||
@ -27,7 +27,7 @@ int8_t GCMParser::parse(uint8_t *d, DataParserContext &ctx) {
|
||||
memcpy(ctx.system_title, ptr, systemTitleLength);
|
||||
memcpy(initialization_vector, ctx.system_title, systemTitleLength);
|
||||
|
||||
int len;
|
||||
int len = 0;
|
||||
int headersize = 2 + systemTitleLength;
|
||||
ptr += systemTitleLength;
|
||||
if(((*ptr) & 0xFF) == 0x81) {
|
||||
|
||||
@ -5,8 +5,6 @@
|
||||
int8_t HDLCParser::parse(uint8_t *d, DataParserContext &ctx) {
|
||||
int len;
|
||||
|
||||
uint8_t flag = *d;
|
||||
|
||||
uint8_t* ptr;
|
||||
if(ctx.length < 3)
|
||||
return DATA_PARSE_INCOMPLETE;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#include "LlcParser.h"
|
||||
|
||||
int8_t LLCParser::parse(uint8_t *buf, DataParserContext &ctx) {
|
||||
LLCHeader* llc = (LLCHeader*) buf;
|
||||
ctx.length -= 3;
|
||||
return 3;
|
||||
}
|
||||
@ -5,8 +5,6 @@ int8_t MBUSParser::parse(uint8_t *d, DataParserContext &ctx) {
|
||||
int headersize = 3;
|
||||
int footersize = 1;
|
||||
|
||||
uint8_t flag = *d;
|
||||
|
||||
uint8_t* ptr;
|
||||
|
||||
// https://m-bus.com/documentation-wired/06-application-layer
|
||||
|
||||
@ -22,7 +22,7 @@ void DnbCurrParser::flush() {
|
||||
}
|
||||
|
||||
size_t DnbCurrParser::write(const uint8_t *buffer, size_t size) {
|
||||
for(int i = 0; i < size; i++) {
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
write(buffer[i]);
|
||||
}
|
||||
return size;
|
||||
|
||||
@ -5,6 +5,10 @@ EntsoeA44Parser::EntsoeA44Parser() {
|
||||
for(int i = 0; i < 24; i++) points[i] = ENTSOE_NO_VALUE;
|
||||
}
|
||||
|
||||
EntsoeA44Parser::~EntsoeA44Parser() {
|
||||
|
||||
}
|
||||
|
||||
char* EntsoeA44Parser::getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
@ -35,7 +39,7 @@ void EntsoeA44Parser::flush() {
|
||||
}
|
||||
|
||||
size_t EntsoeA44Parser::write(const uint8_t *buffer, size_t size) {
|
||||
for(int i = 0; i < size; i++) {
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
write(buffer[i]);
|
||||
}
|
||||
return size;
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
class EntsoeA44Parser: public Stream {
|
||||
public:
|
||||
EntsoeA44Parser();
|
||||
virtual ~EntsoeA44Parser();
|
||||
|
||||
char* getCurrency();
|
||||
char* getMeasurementUnit();
|
||||
|
||||
@ -143,11 +143,11 @@ bool EntsoeApi::loop() {
|
||||
if(midnightMillis == 0) {
|
||||
uint32_t curDayMillis = (((((tm.Hour * 60) + tm.Minute) * 60) + tm.Second) * 1000);
|
||||
midnightMillis = now + (SECS_PER_DAY * 1000) - curDayMillis;
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Setting midnight millis %lu\n", midnightMillis);
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Setting midnight millis %llu\n", midnightMillis);
|
||||
currentDay = tm.Day;
|
||||
return false;
|
||||
} else if(now > midnightMillis && currentDay != tm.Day) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Rotating price objects at %lu\n", t);
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Rotating price objects at %lld\n", t);
|
||||
if(today != NULL) delete today;
|
||||
if(tomorrow != NULL) {
|
||||
today = tomorrow;
|
||||
|
||||
@ -15,6 +15,7 @@ public:
|
||||
this->mqtt = mqtt;
|
||||
this->json = buf;
|
||||
};
|
||||
virtual ~AmsMqttHandler() {};
|
||||
|
||||
virtual bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea);
|
||||
virtual bool publishTemperatures(AmsConfiguration*, HwTools*);
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "web/root/ha1_json.h"
|
||||
#include "web/root/ha2_json.h"
|
||||
#include "web/root/ha3_json.h"
|
||||
#include "web/root/ha4_json.h"
|
||||
#include "web/root/jsonsys_json.h"
|
||||
#include "web/root/jsonprices_json.h"
|
||||
#include "web/root/hadiscover_json.h"
|
||||
@ -34,7 +35,7 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En
|
||||
data->getActiveImportPower()
|
||||
);
|
||||
mqtt->publish(topic + "/power", json);
|
||||
} else if(data->getListType() >= 2) { // publish power counts and volts/amps
|
||||
} else if(data->getListType() <= 3) { // publish power counts and volts/amps
|
||||
snprintf_P(json, BufferSize, HA3_JSON,
|
||||
data->getListId().c_str(),
|
||||
data->getMeterId().c_str(),
|
||||
@ -48,6 +49,29 @@ bool HomeAssistantMqttHandler::publish(AmsData* data, AmsData* previousState, En
|
||||
data->getL3Current(),
|
||||
data->getL1Voltage(),
|
||||
data->getL2Voltage(),
|
||||
data->getL3Voltage()
|
||||
);
|
||||
mqtt->publish(topic + "/power", json);
|
||||
} else if(data->getListType() == 4) { // publish power counts and volts/amps/phase power and PF
|
||||
snprintf_P(json, BufferSize, HA4_JSON,
|
||||
data->getListId().c_str(),
|
||||
data->getMeterId().c_str(),
|
||||
meterModel.c_str(),
|
||||
data->getActiveImportPower(),
|
||||
data->getL1ActiveImportPower(),
|
||||
data->getL2ActiveImportPower(),
|
||||
data->getL3ActiveImportPower(),
|
||||
data->getReactiveImportPower(),
|
||||
data->getActiveExportPower(),
|
||||
data->getL1ActiveExportPower(),
|
||||
data->getL2ActiveExportPower(),
|
||||
data->getL3ActiveExportPower(),
|
||||
data->getReactiveExportPower(),
|
||||
data->getL1Current(),
|
||||
data->getL2Current(),
|
||||
data->getL3Current(),
|
||||
data->getL1Voltage(),
|
||||
data->getL2Voltage(),
|
||||
data->getL3Voltage(),
|
||||
data->getPowerFactor() == 0 ? 1 : data->getPowerFactor(),
|
||||
data->getPowerFactor() == 0 ? 1 : data->getL1PowerFactor(),
|
||||
@ -117,7 +141,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
|
||||
time_t now = time(nullptr);
|
||||
|
||||
float min1hr, min3hr, min6hr;
|
||||
float min1hr = 0.0, min3hr = 0.0, min6hr = 0.0;
|
||||
int8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1;
|
||||
float min = INT16_MAX, max = INT16_MIN;
|
||||
float values[24];
|
||||
@ -167,7 +191,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
|
||||
}
|
||||
|
||||
char ts1hr[21];
|
||||
char ts1hr[24];
|
||||
if(min1hrIdx > -1) {
|
||||
time_t ts = now + (SECS_PER_HOUR * min1hrIdx);
|
||||
//Serial.printf("1hr: %d %lu\n", min1hrIdx, ts);
|
||||
@ -175,7 +199,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
breakTime(ts, tm);
|
||||
sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||
}
|
||||
char ts3hr[21];
|
||||
char ts3hr[24];
|
||||
if(min3hrIdx > -1) {
|
||||
time_t ts = now + (SECS_PER_HOUR * min3hrIdx);
|
||||
//Serial.printf("3hr: %d %lu\n", min3hrIdx, ts);
|
||||
@ -183,7 +207,7 @@ bool HomeAssistantMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
breakTime(ts, tm);
|
||||
sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||
}
|
||||
char ts6hr[21];
|
||||
char ts6hr[24];
|
||||
if(min6hrIdx > -1) {
|
||||
time_t ts = now + (SECS_PER_HOUR * min6hrIdx);
|
||||
//Serial.printf("6hr: %d %lu\n", min6hrIdx, ts);
|
||||
@ -263,13 +287,13 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, EntsoeApi* eapi, Energ
|
||||
peaks++;
|
||||
}
|
||||
snprintf_P(json, BufferSize, HADISCOVER_JSON,
|
||||
FPSTR(sensor.name),
|
||||
topic.c_str(), FPSTR(sensor.topic),
|
||||
sensor.name,
|
||||
topic.c_str(), sensor.topic,
|
||||
haUID.c_str(), uid.c_str(),
|
||||
haUID.c_str(), uid.c_str(),
|
||||
uom.c_str(),
|
||||
FPSTR(sensor.path),
|
||||
FPSTR(sensor.devcl),
|
||||
sensor.path,
|
||||
sensor.devcl,
|
||||
haUID.c_str(),
|
||||
haName.c_str(),
|
||||
haModel.c_str(),
|
||||
|
||||
@ -4,23 +4,29 @@
|
||||
#include "Arduino.h"
|
||||
|
||||
struct HomeAssistantSensor {
|
||||
char* name;
|
||||
char* topic;
|
||||
char* path;
|
||||
char* uom;
|
||||
char* devcl;
|
||||
char* stacl;
|
||||
const char* name;
|
||||
const char* topic;
|
||||
const char* path;
|
||||
const char* uom;
|
||||
const char* devcl;
|
||||
const char* stacl;
|
||||
};
|
||||
|
||||
|
||||
const uint8_t HA_SENSOR_COUNT PROGMEM = 50;
|
||||
const uint8_t HA_SENSOR_COUNT PROGMEM = 60;
|
||||
HomeAssistantSensor HA_SENSORS[HA_SENSOR_COUNT] PROGMEM = {
|
||||
{"Status", "/state", "rssi", "dBm", "signal_strength", "\"measurement\""},
|
||||
{"Supply volt", "/state", "vcc", "V", "voltage", "\"measurement\""},
|
||||
{"Temperature", "/state", "temp", "C", "temperature", "\"measurement\""},
|
||||
{"Active import", "/power", "P", "W", "power", "\"measurement\""},
|
||||
{"L1 active import", "/power", "P1", "W", "power", "\"measurement\""},
|
||||
{"L2 active import", "/power", "P2", "W", "power", "\"measurement\""},
|
||||
{"L3 active import", "/power", "P3", "W", "power", "\"measurement\""},
|
||||
{"Reactive import", "/power", "Q", "VAr", "reactive_power", "\"measurement\""},
|
||||
{"Active export", "/power", "PO", "W", "power", "\"measurement\""},
|
||||
{"L1 active export", "/power", "PO1", "W", "power", "\"measurement\""},
|
||||
{"L2 active export", "/power", "PO2", "W", "power", "\"measurement\""},
|
||||
{"L3 active export", "/power", "PO3", "W", "power", "\"measurement\""},
|
||||
{"Reactive export", "/power", "QO", "VAr", "reactive_power", "\"measurement\""},
|
||||
{"L1 current", "/power", "I1", "A", "current", "\"measurement\""},
|
||||
{"L2 current", "/power", "I2", "A", "current", "\"measurement\""},
|
||||
@ -32,6 +38,10 @@ HomeAssistantSensor HA_SENSORS[HA_SENSOR_COUNT] PROGMEM = {
|
||||
{"Accumulated active export", "/energy", "tPO", "kWh", "energy", "\"total_increasing\""},
|
||||
{"Accumulated reactive import","/energy", "tQI", "kVArh","energy", "\"total_increasing\""},
|
||||
{"Accumulated reactive export","/energy", "tQO", "kVArh","energy", "\"total_increasing\""},
|
||||
{"Power factor", "/power", "PF", "", "power_factor", "\"measurement\""},
|
||||
{"L1 power factor", "/power", "PF1", "", "power_factor", "\"measurement\""},
|
||||
{"L2 power factor", "/power", "PF2", "", "power_factor", "\"measurement\""},
|
||||
{"L3 power factor", "/power", "PF3", "", "power_factor", "\"measurement\""},
|
||||
{"Price current hour", "/prices", "prices['0']", "", "monetary", ""},
|
||||
{"Price next hour", "/prices", "prices['1']", "", "monetary", ""},
|
||||
{"Price in two hour", "/prices", "prices['2']", "", "monetary", ""},
|
||||
|
||||
@ -111,8 +111,14 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccou
|
||||
data->getMeterId().c_str(),
|
||||
meterModel.c_str(),
|
||||
data->getActiveImportPower(),
|
||||
data->getL1ActiveImportPower(),
|
||||
data->getL2ActiveImportPower(),
|
||||
data->getL3ActiveImportPower(),
|
||||
data->getReactiveImportPower(),
|
||||
data->getActiveExportPower(),
|
||||
data->getL1ActiveExportPower(),
|
||||
data->getL2ActiveExportPower(),
|
||||
data->getL3ActiveExportPower(),
|
||||
data->getReactiveExportPower(),
|
||||
data->getL1Current(),
|
||||
data->getL2Current(),
|
||||
@ -143,8 +149,9 @@ bool JsonMqttHandler::publish(AmsData* data, AmsData* previousState, EnergyAccou
|
||||
|
||||
bool JsonMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw) {
|
||||
int count = hw->getTempSensorCount();
|
||||
if(count < 2)
|
||||
if(count < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(json, 24, "{\"temperatures\":{");
|
||||
|
||||
@ -173,7 +180,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
|
||||
time_t now = time(nullptr);
|
||||
|
||||
float min1hr, min3hr, min6hr;
|
||||
float min1hr = 0.0, min3hr = 0.0, min6hr = 0.0;
|
||||
int8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1;
|
||||
float min = INT16_MAX, max = INT16_MIN;
|
||||
float values[24];
|
||||
@ -223,7 +230,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
|
||||
}
|
||||
|
||||
char ts1hr[21];
|
||||
char ts1hr[24];
|
||||
if(min1hrIdx > -1) {
|
||||
time_t ts = now + (SECS_PER_HOUR * min1hrIdx);
|
||||
//Serial.printf("1hr: %d %lu\n", min1hrIdx, ts);
|
||||
@ -231,7 +238,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
breakTime(ts, tm);
|
||||
sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||
}
|
||||
char ts3hr[21];
|
||||
char ts3hr[24];
|
||||
if(min3hrIdx > -1) {
|
||||
time_t ts = now + (SECS_PER_HOUR * min3hrIdx);
|
||||
//Serial.printf("3hr: %d %lu\n", min3hrIdx, ts);
|
||||
@ -239,7 +246,7 @@ bool JsonMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
breakTime(ts, tm);
|
||||
sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||
}
|
||||
char ts6hr[21];
|
||||
char ts6hr[24];
|
||||
if(min6hrIdx > -1) {
|
||||
time_t ts = now + (SECS_PER_HOUR * min6hrIdx);
|
||||
//Serial.printf("6hr: %d %lu\n", min6hrIdx, ts);
|
||||
|
||||
@ -11,6 +11,24 @@ bool RawMqttHandler::publish(AmsData* data, AmsData* meterState, EnergyAccountin
|
||||
}
|
||||
switch(data->getListType()) {
|
||||
case 4:
|
||||
if(full || meterState->getL1ActiveImportPower() != data->getL1ActiveImportPower()) {
|
||||
mqtt->publish(topic + "/meter/import/l1", String(data->getL1ActiveImportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL2ActiveImportPower() != data->getL2ActiveImportPower()) {
|
||||
mqtt->publish(topic + "/meter/import/l2", String(data->getL2ActiveImportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL3ActiveImportPower() != data->getL3ActiveImportPower()) {
|
||||
mqtt->publish(topic + "/meter/import/l3", String(data->getL3ActiveImportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL1ActiveExportPower() != data->getL1ActiveExportPower()) {
|
||||
mqtt->publish(topic + "/meter/export/l1", String(data->getL1ActiveExportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL2ActiveExportPower() != data->getL2ActiveExportPower()) {
|
||||
mqtt->publish(topic + "/meter/export/l2", String(data->getL2ActiveExportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getL3ActiveExportPower() != data->getL3ActiveExportPower()) {
|
||||
mqtt->publish(topic + "/meter/export/l3", String(data->getL3ActiveExportPower(), 2));
|
||||
}
|
||||
if(full || meterState->getPowerFactor() != data->getPowerFactor()) {
|
||||
mqtt->publish(topic + "/meter/powerfactor", String(data->getPowerFactor(), 2));
|
||||
}
|
||||
@ -106,7 +124,7 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
|
||||
time_t now = time(nullptr);
|
||||
|
||||
float min1hr, min3hr, min6hr;
|
||||
float min1hr = 0.0, min3hr = 0.0, min6hr = 0.0;
|
||||
int8_t min1hrIdx = -1, min3hrIdx = -1, min6hrIdx = -1;
|
||||
float min = INT16_MAX, max = INT16_MIN;
|
||||
float values[34];
|
||||
@ -157,7 +175,7 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
|
||||
}
|
||||
|
||||
char ts1hr[21];
|
||||
char ts1hr[24];
|
||||
if(min1hrIdx > -1) {
|
||||
time_t ts = now + (SECS_PER_HOUR * min1hrIdx);
|
||||
//Serial.printf("1hr: %d %lu\n", min1hrIdx, ts);
|
||||
@ -165,7 +183,7 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
breakTime(ts, tm);
|
||||
sprintf(ts1hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||
}
|
||||
char ts3hr[21];
|
||||
char ts3hr[24];
|
||||
if(min3hrIdx > -1) {
|
||||
time_t ts = now + (SECS_PER_HOUR * min3hrIdx);
|
||||
//Serial.printf("3hr: %d %lu\n", min3hrIdx, ts);
|
||||
@ -173,7 +191,7 @@ bool RawMqttHandler::publishPrices(EntsoeApi* eapi) {
|
||||
breakTime(ts, tm);
|
||||
sprintf(ts3hr, "%04d-%02d-%02dT%02d:00:00Z", tm.Year+1970, tm.Month, tm.Day, tm.Hour);
|
||||
}
|
||||
char ts6hr[21];
|
||||
char ts6hr[24];
|
||||
if(min6hrIdx > -1) {
|
||||
time_t ts = now + (SECS_PER_HOUR * min6hrIdx);
|
||||
//Serial.printf("6hr: %d %lu\n", min6hrIdx, ts);
|
||||
|
||||
@ -1015,7 +1015,7 @@ void AmsWebServer::handleSetup() {
|
||||
server.sendHeader("Location", String("/"), true);
|
||||
server.send (302, MIME_PLAIN, "");
|
||||
} else {
|
||||
SystemConfig sys { server.arg("board").toInt() };
|
||||
SystemConfig sys { static_cast<uint8_t>(server.arg("board").toInt()) };
|
||||
|
||||
DebugConfig debugConfig;
|
||||
config->getDebugConfig(debugConfig);
|
||||
@ -1085,6 +1085,16 @@ void AmsWebServer::handleSetup() {
|
||||
gpioConfig->vccResistorGnd = 22;
|
||||
gpioConfig->vccResistorVcc = 33;
|
||||
break;
|
||||
case 7: // Pow-U+
|
||||
gpioConfig->hanPin = 16;
|
||||
gpioConfig->apPin = 0;
|
||||
gpioConfig->ledPinRed = 13;
|
||||
gpioConfig->ledPinGreen = 14;
|
||||
gpioConfig->ledRgbInverted = true;
|
||||
gpioConfig->vccPin = 10;
|
||||
gpioConfig->vccResistorGnd = 22;
|
||||
gpioConfig->vccResistorVcc = 33;
|
||||
break;
|
||||
case 101: // D1
|
||||
gpioConfig->hanPin = 5;
|
||||
gpioConfig->apPin = 4;
|
||||
@ -1285,11 +1295,11 @@ void AmsWebServer::handleSave() {
|
||||
if(server.hasArg("dc") && server.arg("dc") == "true") {
|
||||
printD("Received Domoticz config");
|
||||
DomoticzConfig domo {
|
||||
server.arg("elidx").toInt(),
|
||||
server.arg("vl1idx").toInt(),
|
||||
server.arg("vl2idx").toInt(),
|
||||
server.arg("vl3idx").toInt(),
|
||||
server.arg("cl1idx").toInt()
|
||||
static_cast<uint16_t>(server.arg("elidx").toInt()),
|
||||
static_cast<uint16_t>(server.arg("vl1idx").toInt()),
|
||||
static_cast<uint16_t>(server.arg("vl2idx").toInt()),
|
||||
static_cast<uint16_t>(server.arg("vl3idx").toInt()),
|
||||
static_cast<uint16_t>(server.arg("cl1idx").toInt())
|
||||
};
|
||||
config->setDomoticzConfig(domo);
|
||||
}
|
||||
@ -1310,24 +1320,24 @@ void AmsWebServer::handleSave() {
|
||||
config->setWebConfig(webConfig);
|
||||
}
|
||||
|
||||
if(server.hasArg("gpioConfig") && server.arg("gpioConfig") == "true") {
|
||||
if(server.hasArg("gc") && server.arg("gc") == "true") {
|
||||
printD("Received GPIO config");
|
||||
gpioConfig->hanPin = server.hasArg("hanPin") && !server.arg("hanPin").isEmpty() ? server.arg("hanPin").toInt() : 3;
|
||||
gpioConfig->ledPin = server.hasArg("ledPin") && !server.arg("ledPin").isEmpty() ? server.arg("ledPin").toInt() : 0xFF;
|
||||
gpioConfig->ledInverted = server.hasArg("ledInverted") && server.arg("ledInverted") == "true";
|
||||
gpioConfig->ledPinRed = server.hasArg("ledPinRed") && !server.arg("ledPinRed").isEmpty() ? server.arg("ledPinRed").toInt() : 0xFF;
|
||||
gpioConfig->ledPinGreen = server.hasArg("ledPinGreen") && !server.arg("ledPinGreen").isEmpty() ? server.arg("ledPinGreen").toInt() : 0xFF;
|
||||
gpioConfig->ledPinBlue = server.hasArg("ledPinBlue") && !server.arg("ledPinBlue").isEmpty() ? server.arg("ledPinBlue").toInt() : 0xFF;
|
||||
gpioConfig->ledRgbInverted = server.hasArg("ledRgbInverted") && server.arg("ledRgbInverted") == "true";
|
||||
gpioConfig->apPin = server.hasArg("apPin") && !server.arg("apPin").isEmpty() ? server.arg("apPin").toInt() : 0xFF;
|
||||
gpioConfig->tempSensorPin = server.hasArg("tempSensorPin") && !server.arg("tempSensorPin").isEmpty() ?server.arg("tempSensorPin").toInt() : 0xFF;
|
||||
gpioConfig->tempAnalogSensorPin = server.hasArg("tempAnalogSensorPin") && !server.arg("tempAnalogSensorPin").isEmpty() ?server.arg("tempAnalogSensorPin").toInt() : 0xFF;
|
||||
gpioConfig->vccPin = server.hasArg("vccPin") && !server.arg("vccPin").isEmpty() ? server.arg("vccPin").toInt() : 0xFF;
|
||||
gpioConfig->vccOffset = server.hasArg("vccOffset") && !server.arg("vccOffset").isEmpty() ? server.arg("vccOffset").toFloat() * 100 : 0;
|
||||
gpioConfig->vccMultiplier = server.hasArg("vccMultiplier") && !server.arg("vccMultiplier").isEmpty() ? server.arg("vccMultiplier").toFloat() * 1000 : 1000;
|
||||
gpioConfig->vccBootLimit = server.hasArg("vccBootLimit") && !server.arg("vccBootLimit").isEmpty() ? server.arg("vccBootLimit").toFloat() * 10 : 0;
|
||||
gpioConfig->vccResistorGnd = server.hasArg("vccResistorGnd") && !server.arg("vccResistorGnd").isEmpty() ? server.arg("vccResistorGnd").toInt() : 0;
|
||||
gpioConfig->vccResistorVcc = server.hasArg("vccResistorVcc") && !server.arg("vccResistorVcc").isEmpty() ? server.arg("vccResistorVcc").toInt() : 0;
|
||||
gpioConfig->hanPin = server.hasArg("h") && !server.arg("h").isEmpty() ? server.arg("h").toInt() : 3;
|
||||
gpioConfig->ledPin = server.hasArg("l") && !server.arg("l").isEmpty() ? server.arg("l").toInt() : 0xFF;
|
||||
gpioConfig->ledInverted = server.hasArg("i") && server.arg("i") == "true";
|
||||
gpioConfig->ledPinRed = server.hasArg("r") && !server.arg("r").isEmpty() ? server.arg("r").toInt() : 0xFF;
|
||||
gpioConfig->ledPinGreen = server.hasArg("e") && !server.arg("e").isEmpty() ? server.arg("e").toInt() : 0xFF;
|
||||
gpioConfig->ledPinBlue = server.hasArg("b") && !server.arg("b").isEmpty() ? server.arg("b").toInt() : 0xFF;
|
||||
gpioConfig->ledRgbInverted = server.hasArg("n") && server.arg("n") == "true";
|
||||
gpioConfig->apPin = server.hasArg("a") && !server.arg("a").isEmpty() ? server.arg("a").toInt() : 0xFF;
|
||||
gpioConfig->tempSensorPin = server.hasArg("t") && !server.arg("t").isEmpty() ?server.arg("t").toInt() : 0xFF;
|
||||
gpioConfig->tempAnalogSensorPin = server.hasArg("m") && !server.arg("m").isEmpty() ?server.arg("m").toInt() : 0xFF;
|
||||
gpioConfig->vccPin = server.hasArg("v") && !server.arg("v").isEmpty() ? server.arg("v").toInt() : 0xFF;
|
||||
gpioConfig->vccOffset = server.hasArg("o") && !server.arg("o").isEmpty() ? server.arg("o").toFloat() * 100 : 0;
|
||||
gpioConfig->vccMultiplier = server.hasArg("u") && !server.arg("u").isEmpty() ? server.arg("u").toFloat() * 1000 : 1000;
|
||||
gpioConfig->vccBootLimit = server.hasArg("c") && !server.arg("c").isEmpty() ? server.arg("c").toFloat() * 10 : 0;
|
||||
gpioConfig->vccResistorGnd = server.hasArg("d") && !server.arg("d").isEmpty() ? server.arg("d").toInt() : 0;
|
||||
gpioConfig->vccResistorVcc = server.hasArg("s") && !server.arg("s").isEmpty() ? server.arg("s").toInt() : 0;
|
||||
config->setGpioConfig(*gpioConfig);
|
||||
}
|
||||
|
||||
@ -1366,8 +1376,8 @@ void AmsWebServer::handleSave() {
|
||||
NtpConfig ntp {
|
||||
server.hasArg("n") && server.arg("n") == "true",
|
||||
server.hasArg("nd") && server.arg("nd") == "true",
|
||||
server.arg("o").toInt() / 10,
|
||||
server.arg("so").toInt() / 10
|
||||
static_cast<int16_t>(server.arg("o").toInt() / 10),
|
||||
static_cast<int16_t>(server.arg("so").toInt() / 10)
|
||||
};
|
||||
strcpy(ntp.server, server.arg("ns").c_str());
|
||||
config->setNtpConfig(ntp);
|
||||
@ -1459,32 +1469,32 @@ void AmsWebServer::configGpioHtml() {
|
||||
String html = String((const __FlashStringHelper*) GPIO_HTML);
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
html.replace("${gpio.max}", "44");
|
||||
html.replace("${g}", "44");
|
||||
#elif defined(ESP32)
|
||||
html.replace("${gpio.max}", "39");
|
||||
html.replace("${g}", "39");
|
||||
#else
|
||||
html.replace("${gpio.max}", "16");
|
||||
html.replace("${g}", "16");
|
||||
#endif
|
||||
|
||||
html.replace("${options.han}", getSerialSelectOptions(gpioConfig->hanPin));
|
||||
html.replace("${h}", getSerialSelectOptions(gpioConfig->hanPin));
|
||||
|
||||
html.replace("${config.ledPin}", gpioConfig->ledPin == 0xFF ? "" : String(gpioConfig->ledPin));
|
||||
html.replace("${config.ledInverted}", gpioConfig->ledInverted ? "checked" : "");
|
||||
html.replace("${config.ledPinRed}", gpioConfig->ledPinRed == 0xFF ? "" : String(gpioConfig->ledPinRed));
|
||||
html.replace("${config.ledPinGreen}", gpioConfig->ledPinGreen == 0xFF ? "" : String(gpioConfig->ledPinGreen));
|
||||
html.replace("${config.ledPinBlue}", gpioConfig->ledPinBlue == 0xFF ? "" : String(gpioConfig->ledPinBlue));
|
||||
html.replace("${config.ledRgbInverted}", gpioConfig->ledRgbInverted ? "checked" : "");
|
||||
html.replace("${config.apPin}", gpioConfig->apPin == 0xFF ? "" : String(gpioConfig->apPin));
|
||||
html.replace("${config.tempSensorPin}", gpioConfig->tempSensorPin == 0xFF ? "" : String(gpioConfig->tempSensorPin));
|
||||
html.replace("${config.tempAnalogSensorPin}", gpioConfig->tempAnalogSensorPin == 0xFF ? "" : String(gpioConfig->tempAnalogSensorPin));
|
||||
html.replace("${config.vccPin}", gpioConfig->vccPin == 0xFF ? "" : String(gpioConfig->vccPin));
|
||||
html.replace("${l}", gpioConfig->ledPin == 0xFF ? "" : String(gpioConfig->ledPin));
|
||||
html.replace("${i}", gpioConfig->ledInverted ? "checked" : "");
|
||||
html.replace("${r}", gpioConfig->ledPinRed == 0xFF ? "" : String(gpioConfig->ledPinRed));
|
||||
html.replace("${e}", gpioConfig->ledPinGreen == 0xFF ? "" : String(gpioConfig->ledPinGreen));
|
||||
html.replace("${b}", gpioConfig->ledPinBlue == 0xFF ? "" : String(gpioConfig->ledPinBlue));
|
||||
html.replace("${n}", gpioConfig->ledRgbInverted ? "checked" : "");
|
||||
html.replace("${a}", gpioConfig->apPin == 0xFF ? "" : String(gpioConfig->apPin));
|
||||
html.replace("${t}", gpioConfig->tempSensorPin == 0xFF ? "" : String(gpioConfig->tempSensorPin));
|
||||
html.replace("${m}", gpioConfig->tempAnalogSensorPin == 0xFF ? "" : String(gpioConfig->tempAnalogSensorPin));
|
||||
html.replace("${v}", gpioConfig->vccPin == 0xFF ? "" : String(gpioConfig->vccPin));
|
||||
|
||||
html.replace("${config.vccOffset}", gpioConfig->vccOffset > 0 ? String(gpioConfig->vccOffset / 100.0, 2) : "");
|
||||
html.replace("${config.vccMultiplier}", gpioConfig->vccMultiplier > 0 ? String(gpioConfig->vccMultiplier / 1000.0, 2) : "");
|
||||
html.replace("${config.vccBootLimit}", gpioConfig->vccBootLimit > 0 ? String(gpioConfig->vccBootLimit / 10.0, 1) : "");
|
||||
html.replace("${o}", gpioConfig->vccOffset > 0 ? String(gpioConfig->vccOffset / 100.0, 2) : "");
|
||||
html.replace("${u}", gpioConfig->vccMultiplier > 0 ? String(gpioConfig->vccMultiplier / 1000.0, 2) : "");
|
||||
html.replace("${c}", gpioConfig->vccBootLimit > 0 ? String(gpioConfig->vccBootLimit / 10.0, 1) : "");
|
||||
|
||||
html.replace("${config.vccResistorGnd}", gpioConfig->vccResistorGnd > 0 ? String(gpioConfig->vccResistorGnd) : "");
|
||||
html.replace("${config.vccResistorVcc}", gpioConfig->vccResistorVcc > 0 ? String(gpioConfig->vccResistorVcc) : "");
|
||||
html.replace("${d}", gpioConfig->vccResistorGnd > 0 ? String(gpioConfig->vccResistorGnd) : "");
|
||||
html.replace("${s}", gpioConfig->vccResistorVcc > 0 ? String(gpioConfig->vccResistorVcc) : "");
|
||||
|
||||
server.sendHeader(HEADER_CACHE_CONTROL, "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
@ -1597,21 +1607,21 @@ HTTPUpload& AmsWebServer::uploadFile(const char* path) {
|
||||
}
|
||||
file = LittleFS.open(path, "w");
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("handleFileUpload Open file and write: %lu\n", upload.currentSize);
|
||||
debugger->printf("handleFileUpload Open file and write: %u\n", upload.currentSize);
|
||||
}
|
||||
size_t written = file.write(upload.buf, upload.currentSize);
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("handleFileUpload Written: %lu\n", written);
|
||||
debugger->printf("handleFileUpload Written: %u\n", written);
|
||||
}
|
||||
}
|
||||
} else if(upload.status == UPLOAD_FILE_WRITE) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("handleFileUpload Writing: %lu\n", upload.currentSize);
|
||||
debugger->printf("handleFileUpload Writing: %u\n", upload.currentSize);
|
||||
}
|
||||
if(file) {
|
||||
size_t written = file.write(upload.buf, upload.currentSize);
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("handleFileUpload Written: %lu\n", written);
|
||||
debugger->printf("handleFileUpload Written: %u\n", written);
|
||||
}
|
||||
delay(1);
|
||||
if(written != upload.currentSize) {
|
||||
@ -2328,7 +2338,7 @@ void AmsWebServer::configFileDownload() {
|
||||
ds->getHourImport(23)
|
||||
));
|
||||
if(day.activeExport > 0) {
|
||||
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",
|
||||
server.sendContent(buf, snprintf(buf, BufferSize, " %u %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),
|
||||
@ -2397,7 +2407,7 @@ void AmsWebServer::configFileDownload() {
|
||||
ds->getDayImport(31)
|
||||
));
|
||||
if(month.activeExport > 0) {
|
||||
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",
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, " %u %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),
|
||||
|
||||
@ -61,7 +61,11 @@ private:
|
||||
bool performRestart = false;
|
||||
bool performUpgrade = false;
|
||||
bool rebootForUpgrade = false;
|
||||
#if defined(AMS2MQTT_FIRMWARE_URL)
|
||||
String customFirmwareUrl = AMS2MQTT_FIRMWARE_URL;
|
||||
#else
|
||||
String customFirmwareUrl;
|
||||
#endif
|
||||
|
||||
static const uint16_t BufferSize = 2048;
|
||||
char* buf;
|
||||
|
||||
@ -23,8 +23,8 @@
|
||||
"v" : %.3f,
|
||||
"r" : %d,
|
||||
"t" : %.2f,
|
||||
"u" : %lu,
|
||||
"m" : %lu,
|
||||
"u" : %u,
|
||||
"m" : %u,
|
||||
"em" : %d,
|
||||
"hm" : %d,
|
||||
"wm" : %d,
|
||||
@ -53,5 +53,5 @@
|
||||
"p" : %.2f
|
||||
}
|
||||
},
|
||||
"c" : %lu
|
||||
"c" : %u
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
<div class="alert alert-warning">!!WARNING!!<br/>Do not change anything here unless you know exactly what you are doing! Changing things here could cause the device to stop responding</div>
|
||||
<form method="post" action="/save">
|
||||
<input type="hidden" name="gpioConfig" value="true"/>
|
||||
<input type="hidden" name="gc" value="true"/>
|
||||
<div class="my-3 p-3 bg-white rounded shadow">
|
||||
<h6>GPIO settings</h6>
|
||||
<div class="d-flex flex-row flex-wrap">
|
||||
@ -8,18 +8,18 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">HAN</span>
|
||||
</div>
|
||||
<select name="hanPin" class="form-control">
|
||||
${options.han}
|
||||
<select name="h" class="form-control">
|
||||
${h}
|
||||
</select>
|
||||
</div>
|
||||
<div class="m-2 input-group input-group-sm" style="width: 150px;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">LED</span>
|
||||
</div>
|
||||
<input name="ledPin" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPin}"/>
|
||||
<input name="l" type="number" min="2" max="${g}" class="form-control" value="${l}"/>
|
||||
<div class="input-group-append" title="Inverted">
|
||||
<label class="input-group-text">
|
||||
<input type="checkbox" name="ledInverted" value="true" ${config.ledInverted}/> inv
|
||||
<input type="checkbox" name="i" value="true" ${i}/> inv
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -27,12 +27,12 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">RGB</span>
|
||||
</div>
|
||||
<input name="ledPinRed" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPinRed}"/>
|
||||
<input name="ledPinGreen" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPinGreen}"/>
|
||||
<input name="ledPinBlue" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPinBlue}"/>
|
||||
<input name="r" type="number" min="2" max="${g}" class="form-control" value="${r}"/>
|
||||
<input name="e" type="number" min="2" max="${g}" class="form-control" value="${e}"/>
|
||||
<input name="b" type="number" min="2" max="${g}" class="form-control" value="${b}"/>
|
||||
<div class="input-group-append" title="Inverted">
|
||||
<label class="input-group-text">
|
||||
<input type="checkbox" name="ledRgbInverted" value="true" ${config.ledRgbInverted}/> inv
|
||||
<input type="checkbox" name="n" value="true" ${n}/> inv
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -40,31 +40,31 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">AP button</span>
|
||||
</div>
|
||||
<input name="apPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.apPin}"/>
|
||||
<input name="a" type="number" min="0" max="${g}" class="form-control" value="${a}"/>
|
||||
</div>
|
||||
<div class="m-2 input-group input-group-sm" style="width: 150px;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Temperature</span>
|
||||
</div>
|
||||
<input name="tempSensorPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.tempSensorPin}"/>
|
||||
<input name="t" type="number" min="0" max="${g}" class="form-control" value="${t}"/>
|
||||
</div>
|
||||
<div class="m-2 input-group input-group-sm" style="width: 150px;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Analog temp</span>
|
||||
</div>
|
||||
<input name="tempAnalogSensorPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.tempAnalogSensorPin}"/>
|
||||
<input name="m" type="number" min="0" max="${g}" class="form-control" value="${m}"/>
|
||||
</div>
|
||||
<div class="m-2 input-group input-group-sm" style="width: 100px;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Vcc</span>
|
||||
</div>
|
||||
<input name="vccPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.vccPin}"/>
|
||||
<input name="v" type="number" min="0" max="${g}" class="form-control" value="${v}"/>
|
||||
</div>
|
||||
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">GND resistor</span>
|
||||
</div>
|
||||
<input type="number" min="1" max="1000" step="1" class="form-control" name="vccResistorGnd" value="${config.vccResistorGnd}" />
|
||||
<input type="number" min="1" max="1000" step="1" class="form-control" name="d" value="${d}" />
|
||||
<div class="input-group-append" title="Inverted">
|
||||
<label class="input-group-text">kΩ</label>
|
||||
</div>
|
||||
@ -73,7 +73,7 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Vcc resistor</span>
|
||||
</div>
|
||||
<input type="number" min="1" max="1000" step="1" class="form-control" name="vccResistorVcc" value="${config.vccResistorVcc}" />
|
||||
<input type="number" min="1" max="1000" step="1" class="form-control" name="s" value="${s}" />
|
||||
<div class="input-group-append" title="Inverted">
|
||||
<label class="input-group-text">kΩ</label>
|
||||
</div>
|
||||
@ -82,19 +82,19 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Multiplier</span>
|
||||
</div>
|
||||
<input type="number" min="0.1" max="10" step="0.01" class="form-control" name="vccMultiplier" value="${config.vccMultiplier}" />
|
||||
<input type="number" min="0.1" max="10" step="0.01" class="form-control" name="u" value="${u}" />
|
||||
</div>
|
||||
<div class="m-2 input-group input-group-sm" style="width: 120px;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Offset</span>
|
||||
</div>
|
||||
<input type="number" min="0.0" max="3.5" step="0.01" class="form-control" name="vccOffset" value="${config.vccOffset}" />
|
||||
<input type="number" min="0.0" max="3.5" step="0.01" class="form-control" name="o" value="${o}" />
|
||||
</div>
|
||||
<div class="m-2 input-group input-group-sm" style="width: 130px;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Boot limit</span>
|
||||
</div>
|
||||
<input type="number" min="2.5" max="3.5" step="0.1" class="form-control" name="vccBootLimit" value="${config.vccBootLimit}" />
|
||||
<input type="number" min="2.5" max="3.5" step="0.1" class="form-control" name="c" value="${c}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -3,5 +3,5 @@
|
||||
"tPO" : %.2f,
|
||||
"tQI" : %.2f,
|
||||
"tQO" : %.2f,
|
||||
"rtc" : %lu
|
||||
"rtc" : %lld
|
||||
}
|
||||
|
||||
@ -11,9 +11,5 @@
|
||||
"I3" : %.2f,
|
||||
"U1" : %.2f,
|
||||
"U2" : %.2f,
|
||||
"U3" : %.2f,
|
||||
"PF" : %.2f,
|
||||
"PF1" : %.2f,
|
||||
"PF2" : %.2f,
|
||||
"PF3" : %.2f
|
||||
"U3" : %.2f
|
||||
}
|
||||
|
||||
25
web/ha4.json
Normal file
25
web/ha4.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"lv" : "%s",
|
||||
"id" : "%s",
|
||||
"type" : "%s",
|
||||
"P" : %d,
|
||||
"P1" : %.2f,
|
||||
"P2" : %.2f,
|
||||
"P3" : %.2f,
|
||||
"Q" : %d,
|
||||
"PO" : %d,
|
||||
"PO1" : %.2f,
|
||||
"PO2" : %.2f,
|
||||
"PO3" : %.2f,
|
||||
"QO" : %d,
|
||||
"I1" : %.2f,
|
||||
"I2" : %.2f,
|
||||
"I3" : %.2f,
|
||||
"U1" : %.2f,
|
||||
"U2" : %.2f,
|
||||
"U3" : %.2f,
|
||||
"PF" : %.2f,
|
||||
"PF1" : %.2f,
|
||||
"PF2" : %.2f,
|
||||
"PF3" : %.2f
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
{
|
||||
"id" : "%s",
|
||||
"name" : "%s",
|
||||
"up" : %lu,
|
||||
"t" : %lu,
|
||||
"up" : %u,
|
||||
"t" : %lld,
|
||||
"vcc" : %.3f,
|
||||
"rssi": %d,
|
||||
"temp": %.2f,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
{
|
||||
"id" : "%s",
|
||||
"name" : "%s",
|
||||
"up" : %lu,
|
||||
"t" : %lu,
|
||||
"up" : %u,
|
||||
"t" : %lld,
|
||||
"vcc" : %.3f,
|
||||
"rssi": %d,
|
||||
"temp": %.2f,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
{
|
||||
"id" : "%s",
|
||||
"name" : "%s",
|
||||
"up" : %lu,
|
||||
"t" : %lu,
|
||||
"up" : %u,
|
||||
"t" : %lld,
|
||||
"vcc" : %.3f,
|
||||
"rssi": %d,
|
||||
"temp": %.2f,
|
||||
@ -24,7 +24,7 @@
|
||||
"tPO" : %.3f,
|
||||
"tQI" : %.3f,
|
||||
"tQO" : %.3f,
|
||||
"rtc" : %lu
|
||||
"rtc" : %lld
|
||||
},
|
||||
"realtime" : {
|
||||
"h" : %.2f,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
{
|
||||
"id" : "%s",
|
||||
"name" : "%s",
|
||||
"up" : %lu,
|
||||
"t" : %lu,
|
||||
"up" : %u,
|
||||
"t" : %lld,
|
||||
"vcc" : %.3f,
|
||||
"rssi": %d,
|
||||
"temp": %.2f,
|
||||
@ -11,8 +11,14 @@
|
||||
"id" : "%s",
|
||||
"type" : "%s",
|
||||
"P" : %d,
|
||||
"P1" : %.2f,
|
||||
"P2" : %.2f,
|
||||
"P3" : %.2f,
|
||||
"Q" : %d,
|
||||
"PO" : %d,
|
||||
"PO1" : %.2f,
|
||||
"PO2" : %.2f,
|
||||
"PO3" : %.2f,
|
||||
"QO" : %d,
|
||||
"I1" : %.2f,
|
||||
"I2" : %.2f,
|
||||
@ -28,7 +34,7 @@
|
||||
"tPO" : %.2f,
|
||||
"tQI" : %.2f,
|
||||
"tQO" : %.2f,
|
||||
"rtc" : %lu
|
||||
"rtc" : %lld
|
||||
},
|
||||
"realtime" : {
|
||||
"h" : %.2f,
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
<select name="board" class="form-control" required>
|
||||
<option value=""></option>
|
||||
<optgroup label="Custom hardware">
|
||||
<option value="7" ${config.boardType7}>Pow-U+ (ESP32) from amsleser.no</option>
|
||||
<option value="6" ${config.boardType6}>Pow-P1 from amsleser.no</option>
|
||||
<option value="5" ${config.boardType5}>Pow-K+ (ESP32) from amsleser.no</option>
|
||||
<option value="4" ${config.boardType4}>Pow-U or Pow-K from amsleser.no (GPIO12)</option>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user