Merge pull request #39 from gskjold/dev-v1.1.0-mqttraw

Merged code preparations for other MQTT payload formats
This commit is contained in:
Gunnar Skjold 2020-02-22 16:37:29 +01:00 committed by GitHub
commit 001e3376df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 579 additions and 441 deletions

View File

@ -1,9 +0,0 @@
name=HanToJson
version=1.0.0
author=roarfred
maintainer=roarfred <not@important.com>
sentence=HAN reader data to Json
paragraph=HAN reader data to Json
category=Sensors
url=https://github.com/roarfred/AmsToMqttBridge
architectures=*

View File

@ -1,287 +0,0 @@
#include "HanToJson.h"
#include "Aidon.h"
#include "Kaifa.h"
#include "Kamstrup.h"
static void hanToJsonKaifa3phase(int listSize, JsonObject& data, HanReader& hanReader, Stream *debugger)
{
if (listSize >= (int)Kaifa::List3PhaseShort)
{
data["lv"] = hanReader.getString( (int)Kaifa_List3Phase::ListVersionIdentifier);
data["id"] = hanReader.getString( (int)Kaifa_List3Phase::MeterID);
data["type"] = hanReader.getString( (int)Kaifa_List3Phase::MeterType);
data["P"] = hanReader.getInt( (int)Kaifa_List3Phase::ActiveImportPower);
data["Q"] = hanReader.getInt( (int)Kaifa_List3Phase::ReactiveImportPower);
data["PO"] = hanReader.getInt( (int)Kaifa_List3Phase::ActiveExportPower);
data["QO"] = hanReader.getInt( (int)Kaifa_List3Phase::ReactiveExportPower);
data["I1"] = ((double) hanReader.getInt((int)Kaifa_List3Phase::CurrentL1)) / 1000;
data["I2"] = ((double) hanReader.getInt((int)Kaifa_List3Phase::CurrentL2)) / 1000;
data["I3"] = ((double) hanReader.getInt((int)Kaifa_List3Phase::CurrentL3)) / 1000;
data["U1"] = ((double) hanReader.getInt((int)Kaifa_List3Phase::VoltageL1)) / 10;
data["U2"] = ((double) hanReader.getInt((int)Kaifa_List3Phase::VoltageL2)) / 10;
data["U3"] = ((double) hanReader.getInt((int)Kaifa_List3Phase::VoltageL3)) / 10;
}
if (listSize >= (int)Kaifa::List3PhaseLong)
{
data["rtc"] = hanReader.getTime( (int)Kaifa_List3Phase::MeterClock);
data["tPI"] = hanReader.getInt( (int)Kaifa_List3Phase::CumulativeActiveImportEnergy);
data["tPO"] = hanReader.getInt( (int)Kaifa_List3Phase::CumulativeActiveExportEnergy);
data["tQI"] = hanReader.getInt( (int)Kaifa_List3Phase::CumulativeReactiveImportEnergy);
data["tQO"] = hanReader.getInt( (int)Kaifa_List3Phase::CumulativeReactiveExportEnergy);
}
}
static void hanToJsonKaifa1phase(int listSize, JsonObject& data, HanReader& hanReader, Stream *debugger)
{
if (listSize >= (int)Kaifa::List1PhaseShort)
{
data["lv"] = hanReader.getString( (int)Kaifa_List1Phase::ListVersionIdentifier);
data["id"] = hanReader.getString( (int)Kaifa_List1Phase::MeterID);
data["type"] = hanReader.getString( (int)Kaifa_List1Phase::MeterType);
data["P"] = hanReader.getInt( (int)Kaifa_List1Phase::ActiveImportPower);
data["Q"] = hanReader.getInt( (int)Kaifa_List1Phase::ReactiveImportPower);
data["PO"] = hanReader.getInt( (int)Kaifa_List1Phase::ActiveExportPower);
data["QO"] = hanReader.getInt( (int)Kaifa_List1Phase::ReactiveExportPower);
data["I1"] = ((double) hanReader.getInt((int)Kaifa_List1Phase::CurrentL1)) / 1000;
data["U1"] = ((double) hanReader.getInt((int)Kaifa_List1Phase::VoltageL1)) / 10;
}
if (listSize >= (int)Kaifa::List1PhaseLong)
{
data["rtc"] = hanReader.getTime( (int)Kaifa_List1Phase::MeterClock);
data["tPI"] = hanReader.getInt( (int)Kaifa_List1Phase::CumulativeActiveImportEnergy);
data["tPO"] = hanReader.getInt( (int)Kaifa_List1Phase::CumulativeActiveExportEnergy);
data["tQI"] = hanReader.getInt( (int)Kaifa_List1Phase::CumulativeReactiveImportEnergy);
data["tQO"] = hanReader.getInt( (int)Kaifa_List1Phase::CumulativeReactiveExportEnergy);
}
}
static void hanToJsonKaifa(JsonObject& data, HanReader& hanReader, Stream *debugger)
{
int listSize = hanReader.getListSize();
if (listSize == (int)Kaifa::List1)
{
// Handle listSize == 1 specially
data["P"] = hanReader.getInt( (int)Kaifa_List1::ActivePowerImported);
return;
}
switch (listSize) {
case (int)Kaifa::List3PhaseShort:
case (int)Kaifa::List3PhaseLong:
return hanToJsonKaifa3phase(listSize, data, hanReader, debugger);
case (int)Kaifa::List1PhaseShort:
case (int)Kaifa::List1PhaseLong:
return hanToJsonKaifa1phase(listSize, data, hanReader, debugger);
default:
if (debugger) debugger->printf("Warning: Unknown listSize %d\n", listSize);
return;
}
}
static void hanToJsonAidon3phase(int listSize, JsonObject& data, HanReader& hanReader, Stream *debugger) {
if (listSize >= (int)Aidon::List3PhaseShort) {
data["lv"] = hanReader.getString( (int)Aidon_List3Phase::ListVersionIdentifier);
data["id"] = hanReader.getString( (int)Aidon_List3Phase::MeterID);
data["type"] = hanReader.getString( (int)Aidon_List3Phase::MeterType);
data["P"] = hanReader.getInt( (int)Aidon_List3Phase::ActiveImportPower);
data["Q"] = hanReader.getInt( (int)Aidon_List3Phase::ReactiveImportPower);
data["PO"] = hanReader.getInt( (int)Aidon_List3Phase::ActiveExportPower);
data["QO"] = hanReader.getInt( (int)Aidon_List3Phase::ReactiveExportPower);
data["I1"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::CurrentL1)) / 10;
data["I2"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::CurrentL2)) / 10;
data["I3"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::CurrentL3)) / 10;
data["U1"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::VoltageL1)) / 10;
data["U2"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::VoltageL2)) / 10;
data["U3"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::VoltageL3)) / 10;
}
if (listSize >= (int)Aidon::List3PhaseLong)
{
data["rtc"] = hanReader.getTime( (int)Aidon_List3Phase::Timestamp);
data["tPI"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::CumulativeActiveImportEnergy)) / 100;
data["tPO"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::CumulativeActiveExportEnergy)) / 100;
data["tQI"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::CumulativeReactiveImportEnergy)) / 100;
data["tQO"] = ((double) hanReader.getInt( (int)Aidon_List3Phase::CumulativeReactiveExportEnergy)) / 100;
}
}
static void hanToJsonAidon1phase(int listSize, JsonObject& data, HanReader& hanReader, Stream *debugger)
{
if (listSize >= (int)Aidon::List1PhaseShort)
{
data["lv"] = hanReader.getString( (int)Aidon_List1Phase::ListVersionIdentifier);
data["id"] = hanReader.getString( (int)Aidon_List1Phase::MeterID);
data["type"] = hanReader.getString( (int)Aidon_List1Phase::MeterType);
data["P"] = hanReader.getInt( (int)Aidon_List1Phase::ActiveImportPower);
data["Q"] = hanReader.getInt( (int)Aidon_List1Phase::ReactiveImportPower);
data["PO"] = hanReader.getInt( (int)Aidon_List1Phase::ActiveExportPower);
data["QO"] = hanReader.getInt( (int)Aidon_List1Phase::ReactiveExportPower);
data["I1"] = ((double) hanReader.getInt( (int)Aidon_List1Phase::CurrentL1)) / 10;
data["U1"] = ((double) hanReader.getInt( (int)Aidon_List1Phase::VoltageL1)) / 10;
}
if (listSize >= (int)Aidon::List1PhaseLong)
{
data["rtc"] = hanReader.getTime( (int)Aidon_List1Phase::Timestamp);
data["tPI"] = ((double) hanReader.getInt( (int)Aidon_List1Phase::CumulativeActiveImportEnergy)) / 100;
data["tPO"] = ((double) hanReader.getInt( (int)Aidon_List1Phase::CumulativeActiveExportEnergy)) / 100;
data["tQI"] = ((double) hanReader.getInt( (int)Aidon_List1Phase::CumulativeReactiveImportEnergy)) / 100;
data["tQO"] = ((double) hanReader.getInt( (int)Aidon_List1Phase::CumulativeReactiveExportEnergy)) / 100;
}
}
static void hanToJsonAidon3phaseIT(int listSize, JsonObject& data, HanReader& hanReader, Stream *debugger)
{
if (listSize >= (int)Aidon::List3PhaseITShort)
{
data["lv"] = hanReader.getString( (int)Aidon_List3PhaseIT::ListVersionIdentifier);
data["id"] = hanReader.getString( (int)Aidon_List3PhaseIT::MeterID);
data["type"] = hanReader.getString( (int)Aidon_List3PhaseIT::MeterType);
data["P"] = hanReader.getInt( (int)Aidon_List3PhaseIT::ActiveImportPower);
data["Q"] = hanReader.getInt( (int)Aidon_List3PhaseIT::ReactiveImportPower);
data["PO"] = hanReader.getInt( (int)Aidon_List3PhaseIT::ActiveExportPower);
data["QO"] = hanReader.getInt( (int)Aidon_List3PhaseIT::ReactiveExportPower);
data["I1"] = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL1)) / 10;
data["I2"] = 0;
data["I3"] = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL3)) / 10;
data["U1"] = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL1)) / 10;
data["U2"] = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL2)) / 10;
data["U3"] = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL3)) / 10;
}
if (listSize >= (int)Aidon::List3PhaseITLong)
{
data["rtc"] = hanReader.getTime( (int)Aidon_List3PhaseIT::Timestamp);
data["tPI"] = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeActiveImportEnergy)) / 100;
data["tPO"] = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeActiveExportEnergy)) / 100;
data["tQI"] = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeReactiveImportEnergy)) / 100;
data["tQO"] = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeReactiveExportEnergy)) / 100;
}
}
static void hanToJsonAidon(JsonObject& data, HanReader& hanReader, Stream *debugger)
{
int listSize = hanReader.getListSize();
// Based on the list number, get all details
// according to OBIS specifications for the meter
if (listSize == (int)Aidon::List1)
{
// Handle listSize == 1 specially
data["P"] = hanReader.getInt((int)Aidon_List1::ActiveImportPower);
return;
}
switch (listSize) {
case (int)Aidon::List3PhaseShort:
case (int)Aidon::List3PhaseLong:
return hanToJsonAidon3phase(listSize, data, hanReader, debugger);
case (int)Aidon::List1PhaseShort:
case (int)Aidon::List1PhaseLong:
return hanToJsonAidon1phase(listSize, data, hanReader, debugger);
case (int)Aidon::List3PhaseITShort:
case (int)Aidon::List3PhaseITLong:
return hanToJsonAidon3phaseIT(listSize, data, hanReader, debugger);
default:
if (debugger) debugger->printf("Warning: Unknown listSize %d\n", listSize);
return;
}
}
static void hanToJsonKamstrup3phase(int listSize, JsonObject& data, HanReader& hanReader, Stream *debugger) {
if (listSize >= (int)Kamstrup::List3PhaseShort) {
data["lv"] = hanReader.getString( (int)Kamstrup_List3Phase::ListVersionIdentifier);
data["id"] = hanReader.getString( (int)Kamstrup_List3Phase::MeterID);
data["type"] = hanReader.getString( (int)Kamstrup_List3Phase::MeterType);
data["P"] = hanReader.getInt( (int)Kamstrup_List3Phase::ActiveImportPower);
data["Q"] = hanReader.getInt( (int)Kamstrup_List3Phase::ReactiveImportPower);
data["PO"] = hanReader.getInt( (int)Kamstrup_List3Phase::ActiveExportPower);
data["QO"] = hanReader.getInt( (int)Kamstrup_List3Phase::ReactiveExportPower);
data["I1"] = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CurrentL1)) / 100;
data["I2"] = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CurrentL2)) / 100;
data["I3"] = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CurrentL3)) / 100;
data["U1"] = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL1);
data["U2"] = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL2);
data["U3"] = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL3);
}
if (listSize >= (int)Kamstrup::List3PhaseLong)
{
data["rtc"] = hanReader.getTime( (int)Kamstrup_List3Phase::MeterClock);
data["tPI"] = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeActiveImportEnergy)) / 100;
data["tPO"] = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeActiveExportEnergy)) / 100;
data["tQI"] = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeReactiveImportEnergy)) / 100;
data["tQO"] = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeReactiveExportEnergy)) / 100;
}
}
static void hanToJsonKamstrup1phase(int listSize, JsonObject& data, HanReader& hanReader, Stream *debugger) {
if (listSize >= (int)Kamstrup::List1PhaseShort) {
data["lv"] = hanReader.getString( (int)Kamstrup_List1Phase::ListVersionIdentifier);
data["id"] = hanReader.getString( (int)Kamstrup_List1Phase::MeterID);
data["type"] = hanReader.getString( (int)Kamstrup_List1Phase::MeterType);
data["P"] = hanReader.getInt( (int)Kamstrup_List1Phase::ActiveImportPower);
data["Q"] = hanReader.getInt( (int)Kamstrup_List1Phase::ReactiveImportPower);
data["PO"] = hanReader.getInt( (int)Kamstrup_List1Phase::ActiveExportPower);
data["QO"] = hanReader.getInt( (int)Kamstrup_List1Phase::ReactiveExportPower);
data["I1"] = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CurrentL1)) / 100;
data["U1"] = hanReader.getInt( (int)Kamstrup_List1Phase::VoltageL1);
}
if (listSize >= (int)Kamstrup::List1PhaseLong)
{
data["rtc"] = hanReader.getTime( (int)Kamstrup_List1Phase::MeterClock);
data["tPI"] = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeActiveImportEnergy)) / 100;
data["tPO"] = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeActiveExportEnergy)) / 100;
data["tQI"] = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeReactiveImportEnergy)) / 100;
data["tQO"] = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeReactiveExportEnergy)) / 100;
}
}
static void hanToJsonKamstrup(JsonObject& data, HanReader& hanReader, Stream *debugger) {
int listSize = hanReader.getListSize();
switch (listSize) {
case (int)Kamstrup::List3PhaseShort:
case (int)Kamstrup::List3PhaseLong:
return hanToJsonKamstrup3phase(listSize, data, hanReader, debugger);
case (int)Kamstrup::List1PhaseShort:
case (int)Kamstrup::List1PhaseLong:
return hanToJsonKamstrup1phase(listSize, data, hanReader, debugger);
default:
if (debugger) debugger->printf("Warning: Unknown listSize %d\n", listSize);
return;
}
}
void hanToJson(JsonObject& data, byte meterType, HanReader& hanReader, Stream *debugger)
{
// Based on the list number, get all details
// according to OBIS specifications for the meter
switch (meterType)
{
case 1: // Kaifa
return hanToJsonKaifa(data, hanReader, debugger);
case 2: // Aidon
return hanToJsonAidon(data, hanReader, debugger);
case 3: // Kamstrup
return hanToJsonKamstrup(data, hanReader, debugger);
default:
if (debugger) {
debugger->print("Meter type ");
debugger->print(meterType, HEX);
debugger->println(" is unknown");
}
break;
}
}
void hanToJson(JsonObject& data, byte meterType, HanReader& hanReader)
{
return hanToJson(data, meterType, hanReader, NULL);
}

View File

@ -1,17 +0,0 @@
#ifndef _HANTOJSON_h
#define _HANTOJSON_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <ArduinoJson.h>
#include "HanReader.h"
void hanToJson(JsonObject& data, byte meterType, HanReader& hanReader);
void hanToJson(JsonObject& root, byte meterType, HanReader& hanReader, Stream *debugPort);
#endif

View File

@ -4,7 +4,7 @@ extra_configs = platformio-user.ini
[common]
framework = arduino
lib_deps = HanReader@1.0.0, HanToJson@1.0.0, ArduinoJson@6.14.1, MQTT@^2.4.7, DallasTemperature@3.8.1, EspSoftwareSerial@6.7.1, Base64@^1.0.0
lib_deps = HanReader@1.0.0, ArduinoJson@6.14.1, MQTT@^2.4.7, DallasTemperature@3.8.1, EspSoftwareSerial@6.7.1, Base64@^1.0.0
[env:hw1esp12e]
platform = espressif8266

348
src/AmsData.cpp Normal file
View File

@ -0,0 +1,348 @@
#include "AmsData.h"
#include "Kaifa.h"
#include "Aidon.h"
#include "Kamstrup.h"
AmsData::AmsData() {}
AmsData::AmsData(int meterType, HanReader& hanReader) {
lastUpdateMillis = millis();
packageTimestamp = hanReader.getPackageTime();
int listSize = hanReader.getListSize();
switch(meterType) {
case METER_TYPE_KAIFA:
extractFromKaifa(hanReader, listSize);
break;
case METER_TYPE_AIDON:
extractFromAidon(hanReader, listSize);
break;
case METER_TYPE_KAMSTRUP:
extractFromKamstrup(hanReader, listSize);
break;
}
}
void AmsData::extractFromKaifa(HanReader& hanReader, int listSize) {
switch(listSize) {
case (int)Kaifa::List1:
listType = 1;
break;
case (int)Kaifa::List3PhaseShort:
threePhase = true;
case (int)Kaifa::List1PhaseShort:
listType = 2;
break;
case (int)Kaifa::List3PhaseLong:
threePhase = true;
case (int)Kaifa::List1PhaseLong:
listType = 3;
break;
}
if(listSize == (int)Kaifa::List1) {
activeImportPower = hanReader.getInt((int)Kaifa_List1::ActivePowerImported);
} else {
switch(listSize) {
case (int)Kaifa::List3PhaseLong:
meterTimestamp = hanReader.getTime( (int)Kaifa_List3Phase::MeterClock);
activeImportCounter = hanReader.getInt( (int)Kaifa_List3Phase::CumulativeActiveImportEnergy);
activeExportCounter = hanReader.getInt( (int)Kaifa_List3Phase::CumulativeActiveExportEnergy);
reactiveImportCounter = hanReader.getInt( (int)Kaifa_List3Phase::CumulativeReactiveImportEnergy);
reactiveExportCounter = hanReader.getInt( (int)Kaifa_List3Phase::CumulativeReactiveExportEnergy);
case (int)Kaifa::List3PhaseShort:
listId = hanReader.getString( (int)Kaifa_List3Phase::ListVersionIdentifier);
meterId = hanReader.getString( (int)Kaifa_List3Phase::MeterID);
meterType = hanReader.getString( (int)Kaifa_List3Phase::MeterType);
activeImportPower = hanReader.getInt( (int)Kaifa_List3Phase::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (int)Kaifa_List3Phase::ReactiveImportPower);
activeExportPower = hanReader.getInt( (int)Kaifa_List3Phase::ActiveExportPower);
reactiveExportPower = hanReader.getInt( (int)Kaifa_List3Phase::ReactiveExportPower);
l1current = ((double) hanReader.getInt((int)Kaifa_List3Phase::CurrentL1)) / 1000;
l2current = ((double) hanReader.getInt((int)Kaifa_List3Phase::CurrentL2)) / 1000;
l3current = ((double) hanReader.getInt((int)Kaifa_List3Phase::CurrentL3)) / 1000;
l1voltage = ((double) hanReader.getInt((int)Kaifa_List3Phase::VoltageL1)) / 10;
l2voltage = ((double) hanReader.getInt((int)Kaifa_List3Phase::VoltageL2)) / 10;
l3voltage = ((double) hanReader.getInt((int)Kaifa_List3Phase::VoltageL3)) / 10;
break;
case (int)Kaifa::List1PhaseLong:
meterTimestamp = hanReader.getTime( (int)Kaifa_List1Phase::MeterClock);
activeImportCounter = hanReader.getInt( (int)Kaifa_List1Phase::CumulativeActiveImportEnergy);
activeExportCounter = hanReader.getInt( (int)Kaifa_List1Phase::CumulativeActiveExportEnergy);
reactiveImportCounter = hanReader.getInt( (int)Kaifa_List1Phase::CumulativeReactiveImportEnergy);
reactiveExportCounter = hanReader.getInt( (int)Kaifa_List1Phase::CumulativeReactiveExportEnergy);
case (int)Kaifa::List1PhaseShort:
listId = hanReader.getString( (int)Kaifa_List1Phase::ListVersionIdentifier);
meterId = hanReader.getString( (int)Kaifa_List1Phase::MeterID);
meterType = hanReader.getString( (int)Kaifa_List1Phase::MeterType);
activeImportPower = hanReader.getInt( (int)Kaifa_List1Phase::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (int)Kaifa_List1Phase::ReactiveImportPower);
activeExportPower = hanReader.getInt( (int)Kaifa_List1Phase::ActiveExportPower);
reactiveExportPower = hanReader.getInt( (int)Kaifa_List1Phase::ReactiveExportPower);
l1current = ((double) hanReader.getInt((int)Kaifa_List1Phase::CurrentL1)) / 1000;
l1voltage = ((double) hanReader.getInt((int)Kaifa_List1Phase::VoltageL1)) / 10;
break;
}
}
}
void AmsData::extractFromAidon(HanReader& hanReader, int listSize) {
switch(listSize) {
case (int)Aidon::List1:
listType = 1;
break;
case (int)Aidon::List3PhaseITShort:
case (int)Aidon::List3PhaseShort:
threePhase = true;
case (int)Aidon::List1PhaseShort:
listType = 2;
break;
case (int)Aidon::List3PhaseITLong:
case (int)Aidon::List3PhaseLong:
threePhase = true;
case (int)Aidon::List1PhaseLong:
listType = 3;
break;
}
if(listSize == (int)Aidon::List1) {
activeImportPower = hanReader.getInt((int)Aidon_List1::ActiveImportPower);
} else {
switch(listSize) {
case (int)Aidon::List3PhaseLong:
meterTimestamp = hanReader.getTime( (int)Aidon_List3Phase::Timestamp);
activeImportCounter = ((double) hanReader.getInt( (int)Aidon_List3Phase::CumulativeActiveImportEnergy)) / 100;
activeExportCounter = ((double) hanReader.getInt( (int)Aidon_List3Phase::CumulativeActiveExportEnergy)) / 100;
reactiveImportCounter = ((double) hanReader.getInt( (int)Aidon_List3Phase::CumulativeReactiveImportEnergy)) / 100;
reactiveExportCounter = ((double) hanReader.getInt( (int)Aidon_List3Phase::CumulativeReactiveExportEnergy)) / 100;
case (int)Aidon::List3PhaseShort:
listId = hanReader.getString( (int)Aidon_List3Phase::ListVersionIdentifier);
meterId = hanReader.getString( (int)Aidon_List3Phase::MeterID);
meterType = hanReader.getString( (int)Aidon_List3Phase::MeterType);
activeImportPower = hanReader.getInt( (int)Aidon_List3Phase::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (int)Aidon_List3Phase::ReactiveImportPower);
activeExportPower = hanReader.getInt( (int)Aidon_List3Phase::ActiveExportPower);
reactiveExportPower = hanReader.getInt( (int)Aidon_List3Phase::ReactiveExportPower);
l1current = ((double) hanReader.getInt( (int)Aidon_List3Phase::CurrentL1)) / 10;
l2current = ((double) hanReader.getInt( (int)Aidon_List3Phase::CurrentL2)) / 10;
l3current = ((double) hanReader.getInt( (int)Aidon_List3Phase::CurrentL3)) / 10;
l1voltage = ((double) hanReader.getInt( (int)Aidon_List3Phase::VoltageL1)) / 10;
l2voltage = ((double) hanReader.getInt( (int)Aidon_List3Phase::VoltageL2)) / 10;
l3voltage = ((double) hanReader.getInt( (int)Aidon_List3Phase::VoltageL3)) / 10;
break;
case (int)Aidon::List1PhaseLong:
meterTimestamp = hanReader.getTime( (int)Aidon_List1Phase::Timestamp);
activeImportCounter = ((double) hanReader.getInt( (int)Aidon_List1Phase::CumulativeActiveImportEnergy)) / 100;
activeExportCounter = ((double) hanReader.getInt( (int)Aidon_List1Phase::CumulativeActiveExportEnergy)) / 100;
reactiveImportCounter = ((double) hanReader.getInt( (int)Aidon_List1Phase::CumulativeReactiveImportEnergy)) / 100;
reactiveExportCounter = ((double) hanReader.getInt( (int)Aidon_List1Phase::CumulativeReactiveExportEnergy)) / 100;
case (int)Aidon::List1PhaseShort:
listId = hanReader.getString( (int)Aidon_List1Phase::ListVersionIdentifier);
meterId = hanReader.getString( (int)Aidon_List1Phase::MeterID);
meterType = hanReader.getString( (int)Aidon_List1Phase::MeterType);
activeImportPower = hanReader.getInt( (int)Aidon_List1Phase::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (int)Aidon_List1Phase::ReactiveImportPower);
activeExportPower = hanReader.getInt( (int)Aidon_List1Phase::ActiveExportPower);
reactiveExportPower = hanReader.getInt( (int)Aidon_List1Phase::ReactiveExportPower);
l1current = ((double) hanReader.getInt( (int)Aidon_List1Phase::CurrentL1)) / 10;
l1voltage = ((double) hanReader.getInt( (int)Aidon_List1Phase::VoltageL1)) / 10;
break;
case (int)Aidon::List3PhaseITLong:
meterTimestamp = hanReader.getTime( (int)Aidon_List3PhaseIT::Timestamp);
activeImportCounter = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeActiveImportEnergy)) / 100;
activeExportCounter = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeActiveExportEnergy)) / 100;
reactiveImportCounter = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeReactiveImportEnergy)) / 100;
reactiveExportCounter = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CumulativeReactiveExportEnergy)) / 100;
case (int)Aidon::List3PhaseITShort:
listId = hanReader.getString( (int)Aidon_List3PhaseIT::ListVersionIdentifier);
meterId = hanReader.getString( (int)Aidon_List3PhaseIT::MeterID);
meterType = hanReader.getString( (int)Aidon_List3PhaseIT::MeterType);
activeImportPower = hanReader.getInt( (int)Aidon_List3PhaseIT::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (int)Aidon_List3PhaseIT::ReactiveImportPower);
activeExportPower = hanReader.getInt( (int)Aidon_List3PhaseIT::ActiveExportPower);
reactiveExportPower = hanReader.getInt( (int)Aidon_List3PhaseIT::ReactiveExportPower);
l1current = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL1)) / 10;
l3current = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::CurrentL3)) / 10;
l1voltage = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL1)) / 10;
l2voltage = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL2)) / 10;
l3voltage = ((double) hanReader.getInt( (int)Aidon_List3PhaseIT::VoltageL3)) / 10;
threePhase = true;
break;
}
}
}
void AmsData::extractFromKamstrup(HanReader& hanReader, int listSize) {
switch(listSize) {
case (int)Kamstrup::List3PhaseShort:
threePhase = true;
case (int)Kamstrup::List1PhaseShort:
listType = 2;
break;
case (int)Kamstrup::List3PhaseLong:
threePhase = true;
case (int)Kamstrup::List1PhaseLong:
listType = 3;
break;
}
switch(listSize) {
case (int)Kamstrup::List3PhaseLong:
meterTimestamp = hanReader.getTime( (int)Kamstrup_List3Phase::MeterClock);
activeImportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeActiveImportEnergy)) / 100;
activeExportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeActiveExportEnergy)) / 100;
reactiveImportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeReactiveImportEnergy)) / 100;
reactiveExportCounter = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CumulativeReactiveExportEnergy)) / 100;
case (int)Kamstrup::List3PhaseShort:
listId = hanReader.getString( (int)Kamstrup_List3Phase::ListVersionIdentifier);
meterId = hanReader.getString( (int)Kamstrup_List3Phase::MeterID);
meterType = hanReader.getString( (int)Kamstrup_List3Phase::MeterType);
activeImportPower = hanReader.getInt( (int)Kamstrup_List3Phase::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (int)Kamstrup_List3Phase::ReactiveImportPower);
activeExportPower = hanReader.getInt( (int)Kamstrup_List3Phase::ActiveExportPower);
reactiveExportPower = hanReader.getInt( (int)Kamstrup_List3Phase::ReactiveExportPower);
l1current = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CurrentL1)) / 100;
l2current = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CurrentL2)) / 100;
l3current = ((double) hanReader.getInt((int)Kamstrup_List3Phase::CurrentL3)) / 100;
l1voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL1);
l2voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL2);
l3voltage = hanReader.getInt( (int)Kamstrup_List3Phase::VoltageL3);
break;
case (int)Kamstrup::List1PhaseLong:
meterTimestamp = hanReader.getTime( (int)Kamstrup_List1Phase::MeterClock);
activeImportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeActiveImportEnergy)) / 100;
activeExportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeActiveExportEnergy)) / 100;
reactiveImportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeReactiveImportEnergy)) / 100;
reactiveExportCounter = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CumulativeReactiveExportEnergy)) / 100;
case (int)Kamstrup::List1PhaseShort:
listId = hanReader.getString( (int)Kamstrup_List1Phase::ListVersionIdentifier);
meterId = hanReader.getString( (int)Kamstrup_List1Phase::MeterID);
meterType = hanReader.getString( (int)Kamstrup_List1Phase::MeterType);
activeImportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ActiveImportPower);
reactiveImportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ReactiveImportPower);
activeExportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ActiveExportPower);
reactiveExportPower = hanReader.getInt( (int)Kamstrup_List1Phase::ReactiveExportPower);
l1current = ((double) hanReader.getInt((int)Kamstrup_List1Phase::CurrentL1)) / 100;
l1voltage = hanReader.getInt( (int)Kamstrup_List1Phase::VoltageL1);
break;
}
}
void AmsData::apply(AmsData& other) {
this->lastUpdateMillis = other.getLastUpdateMillis();
this->packageTimestamp = other.getPackageTimestamp();
this->listType = max(this->listType, other.getListType());
switch(other.getListType()) {
case 3:
this->meterTimestamp = other.getMeterTimestamp();
this->activeImportCounter = other.getActiveImportCounter();
this->activeExportCounter = other.getActiveExportCounter();
this->reactiveImportCounter = other.getReactiveImportCounter();
this->reactiveExportCounter = other.getReactiveExportCounter();
case 2:
this->listId = other.getListId();
this->meterId = other.getMeterId();
this->meterType = other.getMeterType();
this->reactiveImportPower = other.getReactiveImportPower();
this->activeExportPower = other.getActiveExportPower();
this->reactiveExportPower = other.getReactiveExportPower();
this->l1current = other.getL1Current();
this->l2current = other.getL2Current();
this->l3current = other.getL3Current();
this->l1voltage = other.getL1Voltage();
this->l2voltage = other.getL2Voltage();
this->l3voltage = other.getL3Voltage();
this->threePhase = other.isThreePhase();
case 1:
this->activeImportPower = other.getActiveImportPower();
}
}
unsigned long AmsData::getLastUpdateMillis() {
return this->lastUpdateMillis;
}
unsigned long AmsData::getPackageTimestamp() {
return this->packageTimestamp;
}
int AmsData::getListType() {
return this->listType;
}
String AmsData::getListId() {
return this->listId;
}
String AmsData::getMeterId() {
return this->meterId;
}
String AmsData::getMeterType() {
return this->meterType;
}
unsigned long AmsData::getMeterTimestamp() {
return this->meterTimestamp;
}
int AmsData::getActiveImportPower() {
return this->activeImportPower;
}
int AmsData::getReactiveImportPower() {
return this->reactiveImportPower;
}
int AmsData::getActiveExportPower() {
return this->activeExportPower;
}
int AmsData::getReactiveExportPower() {
return this->reactiveExportPower;
}
double AmsData::getL1Voltage() {
return this->l1voltage;
}
double AmsData::getL2Voltage() {
return this->l2voltage;
}
double AmsData::getL3Voltage() {
return this->l3voltage;
}
double AmsData::getL1Current() {
return this->l1current;
}
double AmsData::getL2Current() {
return this->l2current;
}
double AmsData::getL3Current() {
return this->l3current;
}
double AmsData::getActiveImportCounter() {
return this->activeImportCounter;
}
double AmsData::getReactiveImportCounter() {
return this->reactiveImportCounter;
}
double AmsData::getActiveExportCounter() {
return this->activeExportCounter;
}
double AmsData::getReactiveExportCounter() {
return this->reactiveExportCounter;
}
bool AmsData::isThreePhase() {
return this->threePhase;
}

66
src/AmsData.h Normal file
View File

@ -0,0 +1,66 @@
#ifndef _AMSDATA_H
#define _AMSDATA_H
#include "Arduino.h"
#include "HanReader.h"
#define METER_TYPE_KAIFA 1
#define METER_TYPE_AIDON 2
#define METER_TYPE_KAMSTRUP 3
class AmsData {
public:
AmsData();
AmsData(int meterType, HanReader& hanReader);
void apply(AmsData& other);
unsigned long getLastUpdateMillis();
unsigned long getPackageTimestamp();
int getListType();
String getListId();
String getMeterId();
String getMeterType();
unsigned long getMeterTimestamp();
int getActiveImportPower();
int getReactiveImportPower();
int getActiveExportPower();
int getReactiveExportPower();
double getL1Voltage();
double getL2Voltage();
double getL3Voltage();
double getL1Current();
double getL2Current();
double getL3Current();
double getActiveImportCounter();
double getReactiveImportCounter();
double getActiveExportCounter();
double getReactiveExportCounter();
bool isThreePhase();
private:
unsigned long lastUpdateMillis;
int listType;
unsigned long packageTimestamp;
String listId, meterId, meterType;
unsigned long meterTimestamp;
int activeImportPower, reactiveImportPower, activeExportPower, reactiveExportPower;
double l1voltage, l2voltage, l3voltage, l1current, l2current, l3current;
double activeImportCounter, reactiveImportCounter, activeExportCounter, reactiveExportCounter;
bool threePhase;
void extractFromKaifa(HanReader& hanReader, int listSize);
void extractFromAidon(HanReader& hanReader, int listSize);
void extractFromKamstrup(HanReader& hanReader, int listSize);
};
#endif

View File

@ -28,23 +28,17 @@ HwTools hw;
DNSServer dnsServer;
// Configuration
AmsConfiguration config;
// Web server
AmsWebServer ws;
// WiFi client and MQTT client
WiFiClient *client;
MQTTClient mqtt(512);
// Object used for debugging
Stream* debugger = NULL;
// The HAN Port reader, used to read serial data and decode DLMS
HanReader hanReader;
// the setup function runs once when you press reset or power the board
void setup() {
if(config.hasConfig()) {
config.load();
@ -111,12 +105,17 @@ void setup() {
}
#if SOFTWARE_SERIAL
if(debugger) debugger->println("HAN has software serial");
if(config.getMeterType() == 3) {
hanSerial->begin(2400, SWSERIAL_8N1);
} else {
hanSerial->begin(2400, SWSERIAL_8E1);
}
#else
if(debugger) {
debugger->println("HAN has hardware serial");
debugger->flush();
}
if(config.getMeterType() == 3) {
hanSerial->begin(2400, SERIAL_8N1);
} else {
@ -132,6 +131,11 @@ void setup() {
// Compensate for the known Kaifa bug
hanReader.compensateFor09HeaderBug = (config.getMeterType() == 1);
// Empty buffer before starting
while (hanSerial->available() > 0) {
hanSerial->read();
}
ws.setup(&config, debugger, &mqtt);
}
@ -145,6 +149,10 @@ bool wifiConnected = false;
unsigned long lastTemperatureRead = 0;
double temperature = -127;
bool even = true;
unsigned long lastRead = 0;
unsigned long lastSuccessfulRead = 0;
void loop() {
unsigned long now = millis();
if (digitalRead(AP_BUTTON_PIN) == LOW) {
@ -167,18 +175,16 @@ void loop() {
buttonActive = false;
}
}
if(now - lastTemperatureRead > 10000) {
if(now - lastTemperatureRead > 5000) {
temperature = hw.getTemperature();
lastTemperatureRead = now;
}
// Only do normal stuff if we're not booted as AP
if (WiFi.getMode() != WIFI_AP) {
// Turn off the LED
led_off();
// Reconnect to WiFi and MQTT as needed
if (WiFi.status() != WL_CONNECTED) {
wifiConnected = false;
WiFi_connect();
@ -207,7 +213,11 @@ void loop() {
else led_off();
}
readHanPort();
if(lastRead-now > 100) {
yield();
readHanPort();
lastRead = now;
}
ws.loop();
delay(1); // Needed for auto modem sleep
}
@ -271,66 +281,34 @@ void mqttMessageReceived(String &topic, String &payload)
// Ideas could be to query for values or to initiate OTA firmware update
}
bool even = true;
unsigned long lastSuccessfulRead = 0;
void readHanPort() {
if (hanReader.read()) {
lastSuccessfulRead = millis();
if(config.getMeterType() > 0) {
// Flash LED on, this shows us that data is received
led_on();
// Get the timestamp (as unix time) from the package
time_t time = hanReader.getPackageTime();
if (debugger) debugger->print("Time of the package is: ");
if (debugger) debugger->println(time);
// Define a json object to keep the data
StaticJsonDocument<1024> json;
// Any generic useful info here
json["id"] = WiFi.macAddress();
json["up"] = millis();
json["t"] = time;
double vcc = hw.getVcc();
if(vcc > 0) {
json["vcc"] = vcc;
}
float rssi = WiFi.RSSI();
rssi = isnan(rssi) ? -100.0 : rssi;
json["rssi"] = rssi;
if(temperature != -127) {
json["temp"] = temperature;
}
// Add a sub-structure to the json object,
// to keep the data from the meter itself
JsonObject data = json.createNestedObject("data");
hanToJson(data, config.getMeterType(), hanReader);
AmsData data(config.getMeterType(), hanReader);
ws.setData(data);
if(!config.getMqttHost().isEmpty() && !config.getMqttPublishTopic().isEmpty()) {
// Write the json to the debug port
StaticJsonDocument<512> json;
hanToJson(json, data, hw, temperature);
if (debugger) {
debugger->print("Sending data to MQTT: ");
serializeJsonPretty(json, *debugger);
debugger->println();
}
// Publish the json to the MQTT server
String msg;
serializeJson(json, msg);
mqtt.publish(config.getMqttPublishTopic(), msg.c_str());
mqtt.loop();
delay(10); // Needed to preserve power
delay(10);
}
ws.setJson(json);
// Flash LED off
led_off();
} else {
// Auto detect meter if not set
for(int i = 1; i <= 3; i++) {
String list;
switch(i) {
@ -365,6 +343,7 @@ void readHanPort() {
}
}
// Switch parity if meter is still not detected
if(config.getMeterType() == 0 && millis() - lastSuccessfulRead > 10000) {
lastSuccessfulRead = millis();
if(debugger) debugger->println("No data for current setting, switching parity");
@ -394,8 +373,7 @@ void WiFi_connect() {
}
lastWifiRetry = millis();
if (debugger)
{
if (debugger) {
debugger->println();
debugger->println();
debugger->print("Connecting to WiFi network ");
@ -408,7 +386,6 @@ void WiFi_connect() {
WiFi.enableAP(false);
WiFi.mode(WIFI_STA);
// WiFi.setOutputPower(0);
if(!config.getWifiIp().isEmpty()) {
IPAddress ip, gw, sn(255,255,255,0);
ip.fromString(config.getWifiIp());
@ -475,7 +452,7 @@ void sendMqttData(String data)
return;
// Build a json with the message in a "data" attribute
StaticJsonDocument<500> json;
StaticJsonDocument<128> json;
json["id"] = WiFi.macAddress();
json["up"] = millis();
json["data"] = data;

46
src/HanToJson.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "HanToJson.h"
void hanToJson(JsonDocument& json, AmsData& data, HwTools& hw, double temperature) {
json["id"] = WiFi.macAddress();
json["up"] = millis();
json["t"] = data.getPackageTimestamp();
double vcc = hw.getVcc();
if(vcc > 0) {
json["vcc"] = vcc;
}
json["rssi"] = hw.getWifiRssi();
if(temperature != DEVICE_DISCONNECTED_C) {
json["temp"] = temperature;
}
// Add a sub-structure to the json object,
// to keep the data from the meter itself
JsonObject jd = json.createNestedObject("data");
switch(data.getListType()) {
case 3:
jd["rtc"] = data.getMeterTimestamp();
jd["tPI"] = data.getActiveImportCounter();
jd["tPO"] = data.getActiveExportCounter();
jd["tQI"] = data.getReactiveImportCounter();
jd["tQO"] = data.getReactiveExportCounter();
case 2:
jd["lv"] = data.getListId();
jd["id"] = data.getMeterId();
jd["type"] = data.getMeterType();
jd["Q"] = data.getReactiveImportPower();
jd["PO"] = data.getActiveExportPower();
jd["QO"] = data.getReactiveExportPower();
jd["I1"] = data.getL1Current();
jd["I2"] = data.getL2Current();
jd["I3"] = data.getL3Current();
jd["U1"] = data.getL1Voltage();
jd["U2"] = data.getL2Voltage();
jd["U3"] = data.getL3Voltage();
case 1:
jd["P"] = data.getActiveImportPower();
}
}

16
src/HanToJson.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _HANTOJSON_h
#define _HANTOJSON_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <ArduinoJson.h>
#include "AmsData.h"
#include "HwTools.h"
void hanToJson(JsonDocument& json, AmsData& data, HwTools& hw, double temperature);
#endif

View File

@ -30,3 +30,7 @@ double HwTools::getTemperature() {
return DEVICE_DISCONNECTED_C;
}
int HwTools::getWifiRssi() {
int rssi = WiFi.RSSI();
return isnan(rssi) ? -100.0 : rssi;
}

View File

@ -28,6 +28,7 @@ class HwTools {
public:
double getVcc();
double getTemperature();
int getWifiRssi();
HwTools() {
oneWire = new OneWire(TEMP_SENSOR_PIN);

View File

@ -35,65 +35,16 @@ void AmsWebServer::loop() {
server.handleClient();
}
void AmsWebServer::setJson(StaticJsonDocument<1024> json) {
if(!json.isNull()) {
p = json["data"]["P"].as<int>();
po = json["data"]["PO"].as<int>();
void AmsWebServer::setData(AmsData& data) {
this->data.apply(data);
if(json["data"].containsKey("U1")) {
u1 = json["data"]["U1"].as<double>();
i1 = json["data"]["I1"].as<double>();
if(json["data"].containsKey("U2")) {
u2 = json["data"]["U2"].as<double>();
i2 = json["data"]["I2"].as<double>();
if(json["data"].containsKey("U3")) {
u3 = json["data"]["U3"].as<double>();
i3 = json["data"]["I3"].as<double>();
}
// Only way to determine if you have more than one phase is to run this code here
if(maxPwr == 0 && config->hasConfig() && config->getMainFuse() > 0 && config->getDistributionSystem() > 0) {
int volt = config->getDistributionSystem() == 2 ? 400 : 230;
if(u2 > 0) {
maxPwr = config->getMainFuse() * sqrt(3) * volt;
} else {
maxPwr = config->getMainFuse() * 230;
}
}
}
if(json["data"].containsKey("tPI")) {
tpi = json["data"]["tPI"].as<double>();
tpo = json["data"]["tPO"].as<double>();
tqi = json["data"]["tQI"].as<double>();
tqo = json["data"]["tQO"].as<double>();
}
if(maxPwr == 0 && data.getListType() > 1 && config->hasConfig() && config->getMainFuse() > 0 && config->getDistributionSystem() > 0) {
int volt = config->getDistributionSystem() == 2 ? 400 : 230;
if(data.isThreePhase()) {
maxPwr = config->getMainFuse() * sqrt(3) * volt;
} else {
if(po > 0) {
json["data"]["PO"] = po;
}
if(u1 > 0) {
json["data"]["U1"] = u1;
json["data"]["I1"] = i1;
}
if(u2 > 0) {
json["data"]["U2"] = u2;
json["data"]["I2"] = i2;
}
if(u3 > 0) {
json["data"]["U3"] = u3;
json["data"]["I3"] = i3;
}
if(tpi > 0) {
json["data"]["tPI"] = tpi;
json["data"]["tPO"] = tpo;
json["data"]["tQI"] = tqi;
json["data"]["tQO"] = tqo;
}
maxPwr = config->getMainFuse() * 230;
}
this->json = json;
}
}
@ -139,8 +90,19 @@ void AmsWebServer::indexHtml() {
html.replace("boot.css", BOOTSTRAP_URL);
}
html.replace("${data.P}", String(p));
html.replace("${data.PO}", String(po));
double u1 = data.getL1Voltage();
double u2 = data.getL2Voltage();
double u3 = data.getL3Voltage();
double i1 = data.getL1Current();
double i2 = data.getL2Current();
double i3 = data.getL3Current();
double tpi = data.getActiveImportCounter();
double tpo = data.getActiveExportCounter();
double tqi = data.getReactiveImportCounter();
double tqo = data.getReactiveExportCounter();
html.replace("${data.P}", String(data.getActiveImportPower()));
html.replace("${data.PO}", String(data.getActiveExportPower()));
html.replace("${display.production}", config->getProductionCapacity() > 0 ? "" : "none");
html.replace("${data.U1}", u1 > 0 ? String(u1, 1) : "");
@ -168,9 +130,8 @@ void AmsWebServer::indexHtml() {
html.replace("${temp}", temp > 0 ? String(temp, 1) : "");
html.replace("${display.temp}", temp != DEVICE_DISCONNECTED_C ? "" : "none");
float rssi = WiFi.RSSI();
rssi = isnan(rssi) ? -100.0 : rssi;
html.replace("${wifi.rssi}", vcc > 0 ? String(rssi, 0) : "");
int rssi = hw.getWifiRssi();
html.replace("${wifi.rssi}", vcc > 0 ? String(rssi) : "");
html.replace("${wifi.channel}", WiFi.channel() > 0 ? String(WiFi.channel()) : "");
html.replace("${wifi.ssid}", !WiFi.SSID().isEmpty() ? String(WiFi.SSID()) : "");
@ -330,25 +291,58 @@ void AmsWebServer::dataJson() {
StaticJsonDocument<768> json;
String jsonStr;
if(!this->json.isNull() && this->json.containsKey("data")) {
if(data.getActiveImportPower() > 0) {
int maxPwr = this->maxPwr;
if(maxPwr == 0) {
if(u2 > 0) {
if(data.isThreePhase()) {
maxPwr = 20000;
} else {
maxPwr = 10000;
}
}
json["up"] = this->json["up"];
json["t"] = this->json["t"];
json["data"] = this->json["data"];
json["up"] = data.getLastUpdateMillis();
json["t"] = data.getPackageTimestamp();
json.createNestedObject("data");
json["data"]["P"] = data.getActiveImportPower();
json["data"]["PO"] = data.getActiveExportPower();
json["p_pct"] = min(p*100/maxPwr, 100);
double u1 = data.getL1Voltage();
double u2 = data.getL2Voltage();
double u3 = data.getL3Voltage();
double i1 = data.getL1Current();
double i2 = data.getL2Current();
double i3 = data.getL3Current();
double tpi = data.getActiveImportCounter();
double tpo = data.getActiveExportCounter();
double tqi = data.getReactiveImportCounter();
double tqo = data.getReactiveExportCounter();
if(u1 > 0) {
json["data"]["U1"] = u1;
json["data"]["I1"] = i1;
}
if(u2 > 0) {
json["data"]["U2"] = u2;
json["data"]["I2"] = i2;
}
if(u3 > 0) {
json["data"]["U3"] = u3;
json["data"]["I3"] = i3;
}
if(tpi > 0) {
json["data"]["tPI"] = tpi;
json["data"]["tPO"] = tpo;
json["data"]["tQI"] = tqi;
json["data"]["tQO"] = tqo;
}
json["p_pct"] = min(data.getActiveImportPower()*100/maxPwr, 100);
if(config->getProductionCapacity() > 0) {
int maxPrd = config->getProductionCapacity() * 1000;
json["po_pct"] = min(po*100/maxPrd, 100);
json["po_pct"] = min(data.getActiveExportPower()*100/maxPrd, 100);
}
} else {
json["p_pct"] = -1;

View File

@ -3,10 +3,11 @@
#define BOOTSTRAP_URL "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css"
#include <ArduinoJson.h>
#include <MQTT.h>
#include <ArduinoJson.h>
#include "AmsConfiguration.h"
#include "HwTools.h"
#include "AmsData.h"
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
@ -28,17 +29,15 @@ class AmsWebServer {
public:
void setup(AmsConfiguration* config, Stream* debugger, MQTTClient* mqtt);
void loop();
void setJson(StaticJsonDocument<1024> json);
void setData(AmsData& data);
private:
int maxPwr;
HwTools hw;
AmsConfiguration* config;
AmsData data;
Stream* debugger;
MQTTClient* mqtt;
StaticJsonDocument<1024> json;
int maxPwr;
int p, po;
double u1, u2, u3, i1, i2, i3, tpi, tpo, tqi, tqo;
#if defined(ESP8266)
ESP8266WebServer server;