mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-04-25 20:01:46 +00:00
Merge pull request #39 from gskjold/dev-v1.1.0-mqttraw
Merged code preparations for other MQTT payload formats
This commit is contained in:
@@ -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=*
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -4,7 +4,7 @@ extra_configs = platformio-user.ini
|
|||||||
|
|
||||||
[common]
|
[common]
|
||||||
framework = arduino
|
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]
|
[env:hw1esp12e]
|
||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
|
|||||||
348
src/AmsData.cpp
Normal file
348
src/AmsData.cpp
Normal 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
66
src/AmsData.h
Normal 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
|
||||||
@@ -28,23 +28,17 @@ HwTools hw;
|
|||||||
|
|
||||||
DNSServer dnsServer;
|
DNSServer dnsServer;
|
||||||
|
|
||||||
// Configuration
|
|
||||||
AmsConfiguration config;
|
AmsConfiguration config;
|
||||||
|
|
||||||
// Web server
|
|
||||||
AmsWebServer ws;
|
AmsWebServer ws;
|
||||||
|
|
||||||
// WiFi client and MQTT client
|
|
||||||
WiFiClient *client;
|
WiFiClient *client;
|
||||||
MQTTClient mqtt(512);
|
MQTTClient mqtt(512);
|
||||||
|
|
||||||
// Object used for debugging
|
|
||||||
Stream* debugger = NULL;
|
Stream* debugger = NULL;
|
||||||
|
|
||||||
// The HAN Port reader, used to read serial data and decode DLMS
|
|
||||||
HanReader hanReader;
|
HanReader hanReader;
|
||||||
|
|
||||||
// the setup function runs once when you press reset or power the board
|
|
||||||
void setup() {
|
void setup() {
|
||||||
if(config.hasConfig()) {
|
if(config.hasConfig()) {
|
||||||
config.load();
|
config.load();
|
||||||
@@ -111,12 +105,17 @@ void setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if SOFTWARE_SERIAL
|
#if SOFTWARE_SERIAL
|
||||||
|
if(debugger) debugger->println("HAN has software serial");
|
||||||
if(config.getMeterType() == 3) {
|
if(config.getMeterType() == 3) {
|
||||||
hanSerial->begin(2400, SWSERIAL_8N1);
|
hanSerial->begin(2400, SWSERIAL_8N1);
|
||||||
} else {
|
} else {
|
||||||
hanSerial->begin(2400, SWSERIAL_8E1);
|
hanSerial->begin(2400, SWSERIAL_8E1);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
if(debugger) {
|
||||||
|
debugger->println("HAN has hardware serial");
|
||||||
|
debugger->flush();
|
||||||
|
}
|
||||||
if(config.getMeterType() == 3) {
|
if(config.getMeterType() == 3) {
|
||||||
hanSerial->begin(2400, SERIAL_8N1);
|
hanSerial->begin(2400, SERIAL_8N1);
|
||||||
} else {
|
} else {
|
||||||
@@ -132,6 +131,11 @@ void setup() {
|
|||||||
// Compensate for the known Kaifa bug
|
// Compensate for the known Kaifa bug
|
||||||
hanReader.compensateFor09HeaderBug = (config.getMeterType() == 1);
|
hanReader.compensateFor09HeaderBug = (config.getMeterType() == 1);
|
||||||
|
|
||||||
|
// Empty buffer before starting
|
||||||
|
while (hanSerial->available() > 0) {
|
||||||
|
hanSerial->read();
|
||||||
|
}
|
||||||
|
|
||||||
ws.setup(&config, debugger, &mqtt);
|
ws.setup(&config, debugger, &mqtt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,6 +149,10 @@ bool wifiConnected = false;
|
|||||||
unsigned long lastTemperatureRead = 0;
|
unsigned long lastTemperatureRead = 0;
|
||||||
double temperature = -127;
|
double temperature = -127;
|
||||||
|
|
||||||
|
bool even = true;
|
||||||
|
unsigned long lastRead = 0;
|
||||||
|
unsigned long lastSuccessfulRead = 0;
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
if (digitalRead(AP_BUTTON_PIN) == LOW) {
|
if (digitalRead(AP_BUTTON_PIN) == LOW) {
|
||||||
@@ -167,18 +175,16 @@ void loop() {
|
|||||||
buttonActive = false;
|
buttonActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(now - lastTemperatureRead > 10000) {
|
if(now - lastTemperatureRead > 5000) {
|
||||||
temperature = hw.getTemperature();
|
temperature = hw.getTemperature();
|
||||||
lastTemperatureRead = now;
|
lastTemperatureRead = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only do normal stuff if we're not booted as AP
|
// Only do normal stuff if we're not booted as AP
|
||||||
if (WiFi.getMode() != WIFI_AP) {
|
if (WiFi.getMode() != WIFI_AP) {
|
||||||
// Turn off the LED
|
|
||||||
led_off();
|
led_off();
|
||||||
|
|
||||||
// Reconnect to WiFi and MQTT as needed
|
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
wifiConnected = false;
|
wifiConnected = false;
|
||||||
WiFi_connect();
|
WiFi_connect();
|
||||||
@@ -207,7 +213,11 @@ void loop() {
|
|||||||
else led_off();
|
else led_off();
|
||||||
|
|
||||||
}
|
}
|
||||||
readHanPort();
|
if(lastRead-now > 100) {
|
||||||
|
yield();
|
||||||
|
readHanPort();
|
||||||
|
lastRead = now;
|
||||||
|
}
|
||||||
ws.loop();
|
ws.loop();
|
||||||
delay(1); // Needed for auto modem sleep
|
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
|
// Ideas could be to query for values or to initiate OTA firmware update
|
||||||
}
|
}
|
||||||
|
|
||||||
bool even = true;
|
|
||||||
unsigned long lastSuccessfulRead = 0;
|
|
||||||
void readHanPort() {
|
void readHanPort() {
|
||||||
if (hanReader.read()) {
|
if (hanReader.read()) {
|
||||||
lastSuccessfulRead = millis();
|
lastSuccessfulRead = millis();
|
||||||
|
|
||||||
if(config.getMeterType() > 0) {
|
if(config.getMeterType() > 0) {
|
||||||
// Flash LED on, this shows us that data is received
|
|
||||||
led_on();
|
led_on();
|
||||||
|
|
||||||
// Get the timestamp (as unix time) from the package
|
AmsData data(config.getMeterType(), hanReader);
|
||||||
time_t time = hanReader.getPackageTime();
|
ws.setData(data);
|
||||||
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);
|
|
||||||
|
|
||||||
if(!config.getMqttHost().isEmpty() && !config.getMqttPublishTopic().isEmpty()) {
|
if(!config.getMqttHost().isEmpty() && !config.getMqttPublishTopic().isEmpty()) {
|
||||||
// Write the json to the debug port
|
StaticJsonDocument<512> json;
|
||||||
|
hanToJson(json, data, hw, temperature);
|
||||||
if (debugger) {
|
if (debugger) {
|
||||||
debugger->print("Sending data to MQTT: ");
|
debugger->print("Sending data to MQTT: ");
|
||||||
serializeJsonPretty(json, *debugger);
|
serializeJsonPretty(json, *debugger);
|
||||||
debugger->println();
|
debugger->println();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish the json to the MQTT server
|
|
||||||
String msg;
|
String msg;
|
||||||
serializeJson(json, msg);
|
serializeJson(json, msg);
|
||||||
|
|
||||||
mqtt.publish(config.getMqttPublishTopic(), msg.c_str());
|
mqtt.publish(config.getMqttPublishTopic(), msg.c_str());
|
||||||
mqtt.loop();
|
mqtt.loop();
|
||||||
delay(10); // Needed to preserve power
|
delay(10);
|
||||||
}
|
}
|
||||||
ws.setJson(json);
|
|
||||||
|
|
||||||
// Flash LED off
|
|
||||||
led_off();
|
led_off();
|
||||||
} else {
|
} else {
|
||||||
|
// Auto detect meter if not set
|
||||||
for(int i = 1; i <= 3; i++) {
|
for(int i = 1; i <= 3; i++) {
|
||||||
String list;
|
String list;
|
||||||
switch(i) {
|
switch(i) {
|
||||||
@@ -365,6 +343,7 @@ void readHanPort() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Switch parity if meter is still not detected
|
||||||
if(config.getMeterType() == 0 && millis() - lastSuccessfulRead > 10000) {
|
if(config.getMeterType() == 0 && millis() - lastSuccessfulRead > 10000) {
|
||||||
lastSuccessfulRead = millis();
|
lastSuccessfulRead = millis();
|
||||||
if(debugger) debugger->println("No data for current setting, switching parity");
|
if(debugger) debugger->println("No data for current setting, switching parity");
|
||||||
@@ -394,8 +373,7 @@ void WiFi_connect() {
|
|||||||
}
|
}
|
||||||
lastWifiRetry = millis();
|
lastWifiRetry = millis();
|
||||||
|
|
||||||
if (debugger)
|
if (debugger) {
|
||||||
{
|
|
||||||
debugger->println();
|
debugger->println();
|
||||||
debugger->println();
|
debugger->println();
|
||||||
debugger->print("Connecting to WiFi network ");
|
debugger->print("Connecting to WiFi network ");
|
||||||
@@ -408,7 +386,6 @@ void WiFi_connect() {
|
|||||||
|
|
||||||
WiFi.enableAP(false);
|
WiFi.enableAP(false);
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
// WiFi.setOutputPower(0);
|
|
||||||
if(!config.getWifiIp().isEmpty()) {
|
if(!config.getWifiIp().isEmpty()) {
|
||||||
IPAddress ip, gw, sn(255,255,255,0);
|
IPAddress ip, gw, sn(255,255,255,0);
|
||||||
ip.fromString(config.getWifiIp());
|
ip.fromString(config.getWifiIp());
|
||||||
@@ -475,7 +452,7 @@ void sendMqttData(String data)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Build a json with the message in a "data" attribute
|
// Build a json with the message in a "data" attribute
|
||||||
StaticJsonDocument<500> json;
|
StaticJsonDocument<128> json;
|
||||||
json["id"] = WiFi.macAddress();
|
json["id"] = WiFi.macAddress();
|
||||||
json["up"] = millis();
|
json["up"] = millis();
|
||||||
json["data"] = data;
|
json["data"] = data;
|
||||||
|
|||||||
46
src/HanToJson.cpp
Normal file
46
src/HanToJson.cpp
Normal 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
16
src/HanToJson.h
Normal 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
|
||||||
@@ -30,3 +30,7 @@ double HwTools::getTemperature() {
|
|||||||
return DEVICE_DISCONNECTED_C;
|
return DEVICE_DISCONNECTED_C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int HwTools::getWifiRssi() {
|
||||||
|
int rssi = WiFi.RSSI();
|
||||||
|
return isnan(rssi) ? -100.0 : rssi;
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ class HwTools {
|
|||||||
public:
|
public:
|
||||||
double getVcc();
|
double getVcc();
|
||||||
double getTemperature();
|
double getTemperature();
|
||||||
|
int getWifiRssi();
|
||||||
|
|
||||||
HwTools() {
|
HwTools() {
|
||||||
oneWire = new OneWire(TEMP_SENSOR_PIN);
|
oneWire = new OneWire(TEMP_SENSOR_PIN);
|
||||||
|
|||||||
@@ -35,65 +35,16 @@ void AmsWebServer::loop() {
|
|||||||
server.handleClient();
|
server.handleClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsWebServer::setJson(StaticJsonDocument<1024> json) {
|
void AmsWebServer::setData(AmsData& data) {
|
||||||
if(!json.isNull()) {
|
this->data.apply(data);
|
||||||
p = json["data"]["P"].as<int>();
|
|
||||||
po = json["data"]["PO"].as<int>();
|
|
||||||
|
|
||||||
if(json["data"].containsKey("U1")) {
|
if(maxPwr == 0 && data.getListType() > 1 && config->hasConfig() && config->getMainFuse() > 0 && config->getDistributionSystem() > 0) {
|
||||||
u1 = json["data"]["U1"].as<double>();
|
int volt = config->getDistributionSystem() == 2 ? 400 : 230;
|
||||||
i1 = json["data"]["I1"].as<double>();
|
if(data.isThreePhase()) {
|
||||||
|
maxPwr = config->getMainFuse() * sqrt(3) * volt;
|
||||||
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>();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if(po > 0) {
|
maxPwr = config->getMainFuse() * 230;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this->json = json;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,8 +90,19 @@ void AmsWebServer::indexHtml() {
|
|||||||
html.replace("boot.css", BOOTSTRAP_URL);
|
html.replace("boot.css", BOOTSTRAP_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
html.replace("${data.P}", String(p));
|
double u1 = data.getL1Voltage();
|
||||||
html.replace("${data.PO}", String(po));
|
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("${display.production}", config->getProductionCapacity() > 0 ? "" : "none");
|
||||||
|
|
||||||
html.replace("${data.U1}", u1 > 0 ? String(u1, 1) : "");
|
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("${temp}", temp > 0 ? String(temp, 1) : "");
|
||||||
html.replace("${display.temp}", temp != DEVICE_DISCONNECTED_C ? "" : "none");
|
html.replace("${display.temp}", temp != DEVICE_DISCONNECTED_C ? "" : "none");
|
||||||
|
|
||||||
float rssi = WiFi.RSSI();
|
int rssi = hw.getWifiRssi();
|
||||||
rssi = isnan(rssi) ? -100.0 : rssi;
|
html.replace("${wifi.rssi}", vcc > 0 ? String(rssi) : "");
|
||||||
html.replace("${wifi.rssi}", vcc > 0 ? String(rssi, 0) : "");
|
|
||||||
html.replace("${wifi.channel}", WiFi.channel() > 0 ? String(WiFi.channel()) : "");
|
html.replace("${wifi.channel}", WiFi.channel() > 0 ? String(WiFi.channel()) : "");
|
||||||
html.replace("${wifi.ssid}", !WiFi.SSID().isEmpty() ? String(WiFi.SSID()) : "");
|
html.replace("${wifi.ssid}", !WiFi.SSID().isEmpty() ? String(WiFi.SSID()) : "");
|
||||||
|
|
||||||
@@ -330,25 +291,58 @@ void AmsWebServer::dataJson() {
|
|||||||
StaticJsonDocument<768> json;
|
StaticJsonDocument<768> json;
|
||||||
|
|
||||||
String jsonStr;
|
String jsonStr;
|
||||||
if(!this->json.isNull() && this->json.containsKey("data")) {
|
if(data.getActiveImportPower() > 0) {
|
||||||
int maxPwr = this->maxPwr;
|
int maxPwr = this->maxPwr;
|
||||||
if(maxPwr == 0) {
|
if(maxPwr == 0) {
|
||||||
if(u2 > 0) {
|
if(data.isThreePhase()) {
|
||||||
maxPwr = 20000;
|
maxPwr = 20000;
|
||||||
} else {
|
} else {
|
||||||
maxPwr = 10000;
|
maxPwr = 10000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
json["up"] = this->json["up"];
|
json["up"] = data.getLastUpdateMillis();
|
||||||
json["t"] = this->json["t"];
|
json["t"] = data.getPackageTimestamp();
|
||||||
json["data"] = this->json["data"];
|
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) {
|
if(config->getProductionCapacity() > 0) {
|
||||||
int maxPrd = config->getProductionCapacity() * 1000;
|
int maxPrd = config->getProductionCapacity() * 1000;
|
||||||
json["po_pct"] = min(po*100/maxPrd, 100);
|
json["po_pct"] = min(data.getActiveExportPower()*100/maxPrd, 100);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
json["p_pct"] = -1;
|
json["p_pct"] = -1;
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
#define BOOTSTRAP_URL "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css"
|
#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 <MQTT.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
#include "AmsConfiguration.h"
|
#include "AmsConfiguration.h"
|
||||||
#include "HwTools.h"
|
#include "HwTools.h"
|
||||||
|
#include "AmsData.h"
|
||||||
|
|
||||||
#if defined(ARDUINO) && ARDUINO >= 100
|
#if defined(ARDUINO) && ARDUINO >= 100
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
@@ -28,17 +29,15 @@ class AmsWebServer {
|
|||||||
public:
|
public:
|
||||||
void setup(AmsConfiguration* config, Stream* debugger, MQTTClient* mqtt);
|
void setup(AmsConfiguration* config, Stream* debugger, MQTTClient* mqtt);
|
||||||
void loop();
|
void loop();
|
||||||
void setJson(StaticJsonDocument<1024> json);
|
void setData(AmsData& data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int maxPwr;
|
||||||
HwTools hw;
|
HwTools hw;
|
||||||
AmsConfiguration* config;
|
AmsConfiguration* config;
|
||||||
|
AmsData data;
|
||||||
Stream* debugger;
|
Stream* debugger;
|
||||||
MQTTClient* mqtt;
|
MQTTClient* mqtt;
|
||||||
StaticJsonDocument<1024> json;
|
|
||||||
int maxPwr;
|
|
||||||
int p, po;
|
|
||||||
double u1, u2, u3, i1, i2, i3, tpi, tpo, tqi, tqo;
|
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
ESP8266WebServer server;
|
ESP8266WebServer server;
|
||||||
|
|||||||
Reference in New Issue
Block a user