mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-25 11:56:04 +00:00
Merge pull request #322 from tbarnekov/extend_power_info
Populate Active Import and Export per phase and export to HA
This commit is contained in:
commit
2850be4e48
@ -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;
|
||||
|
||||
@ -1141,7 +1141,7 @@ 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};
|
||||
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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -1007,7 +1007,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);
|
||||
@ -1287,11 +1287,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);
|
||||
}
|
||||
@ -1368,8 +1368,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);
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user