mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-13 15:37:03 +00:00
Preparations for selectable MQTT payload format
This commit is contained in:
parent
90b62638ed
commit
9c8552869c
@ -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]
|
||||
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
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;
|
||||
|
||||
// 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();
|
||||
@ -127,7 +121,7 @@ void setup() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
hanReader.setup(hanSerial, 0);
|
||||
hanReader.setup(hanSerial, debugger);
|
||||
|
||||
// Compensate for the known Kaifa bug
|
||||
hanReader.compensateFor09HeaderBug = (config.getMeterType() == 1);
|
||||
@ -175,10 +169,8 @@ void loop() {
|
||||
|
||||
// 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();
|
||||
@ -278,59 +270,27 @@ void readHanPort() {
|
||||
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
|
||||
}
|
||||
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 +325,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 +355,7 @@ void WiFi_connect() {
|
||||
}
|
||||
lastWifiRetry = millis();
|
||||
|
||||
if (debugger)
|
||||
{
|
||||
if (debugger) {
|
||||
debugger->println();
|
||||
debugger->println();
|
||||
debugger->print("Connecting to WiFi network ");
|
||||
@ -408,7 +368,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 +434,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
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;
|
||||
}
|
||||
|
||||
int HwTools::getWifiRssi() {
|
||||
int rssi = WiFi.RSSI();
|
||||
return isnan(rssi) ? -100.0 : rssi;
|
||||
}
|
||||
@ -28,6 +28,7 @@ class HwTools {
|
||||
public:
|
||||
double getVcc();
|
||||
double getTemperature();
|
||||
int getWifiRssi();
|
||||
|
||||
HwTools() {
|
||||
oneWire = new OneWire(TEMP_SENSOR_PIN);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user