mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-19 17:48:30 +00:00
Implemented reading of all values from all lists. Added WiFi and MQTT, and now reports as json to mqtt server
This commit is contained in:
parent
84e4e0cb34
commit
3e7d91a809
@ -11,6 +11,17 @@
|
||||
*
|
||||
* Created 14. september 2017 by Roar Fredriksen
|
||||
*/
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
// WiFi and MQTT endpoints
|
||||
const char* ssid = "Roar_Etne";
|
||||
const char* password = "**********";
|
||||
const char* mqtt_server = "192.168.10.203";
|
||||
|
||||
WiFiClient espClient;
|
||||
PubSubClient client(espClient);
|
||||
|
||||
#include "DlmsReader.h"
|
||||
#include "Crc16.h"
|
||||
@ -30,6 +41,24 @@ void setup() {
|
||||
Serial1.println("Serial1");
|
||||
Serial1.println("Serial debugging port initialized");
|
||||
|
||||
// Initialize wifi
|
||||
Serial1.print("Connecting to ");
|
||||
Serial1.println(ssid);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial1.print(".");
|
||||
}
|
||||
|
||||
Serial1.println("");
|
||||
Serial1.println("WiFi connected");
|
||||
Serial1.println("IP address: ");
|
||||
Serial1.println(WiFi.localIP());
|
||||
|
||||
client.setServer(mqtt_server, 1883);
|
||||
|
||||
// Initialize H/W serial port for MBus communication
|
||||
Serial.begin(2400, SERIAL_8E1);
|
||||
while (!Serial) {}
|
||||
@ -39,11 +68,16 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (!client.connected()) {
|
||||
reconnect();
|
||||
}
|
||||
client.loop();
|
||||
|
||||
if (Serial.available())
|
||||
{
|
||||
byte newByte = Serial.read();
|
||||
//if (newByte < 0x10) Serial1.print("0");
|
||||
Serial1.print(newByte, HEX);
|
||||
//Serial1.print(newByte, HEX);
|
||||
|
||||
if (reader.Read(newByte))
|
||||
{
|
||||
@ -53,33 +87,88 @@ void loop() {
|
||||
Serial1.println("");
|
||||
Serial1.print("List #");
|
||||
Serial1.print(list, HEX);
|
||||
|
||||
time_t time = kaifa.GetPackageTime(buffer, 0, bytesRead);
|
||||
Serial1.print(" (time is ");
|
||||
Serial1.print(time);
|
||||
Serial1.print(")");
|
||||
Serial1.print(": ");
|
||||
|
||||
if (list == 0x01)
|
||||
time_t time = kaifa.GetPackageTime(buffer, 0, bytesRead);
|
||||
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["id"] = "espdebugger";
|
||||
root["up"] = millis();
|
||||
root["t"] = time;
|
||||
|
||||
JsonObject& data = root.createNestedObject("data");
|
||||
|
||||
if (list == (byte)List::List1)
|
||||
{
|
||||
int consumption = kaifa.GetInt(0, buffer, 0, bytesRead);
|
||||
Serial1.print(" consumption is ");
|
||||
Serial1.print(consumption);
|
||||
Serial1.println(" Watts");
|
||||
data["P"] = kaifa.GetInt((int)List1_ObisObjects::ActivePowerImported, buffer, 0, bytesRead);
|
||||
}
|
||||
writeAndEmptyBuffer();
|
||||
else if (list == (byte)List::List2)
|
||||
{
|
||||
data["lv"] = kaifa.GetString((int)List2_ObisObjects::ObisListVersionIdentifier, buffer, 0, bytesRead);
|
||||
data["id"] = kaifa.GetString((int)List2_ObisObjects::MeterID, buffer, 0, bytesRead);
|
||||
data["type"] = kaifa.GetString((int)List2_ObisObjects::MeterType, buffer, 0, bytesRead);
|
||||
data["P"] = kaifa.GetInt((int)List2_ObisObjects::ActivePowerImported, buffer, 0, bytesRead);
|
||||
data["Q"] = kaifa.GetInt((int)List2_ObisObjects::ReactivePowerImported, buffer, 0, bytesRead);
|
||||
data["I1"] = kaifa.GetInt((int)List2_ObisObjects::CurrentPhaseL1, buffer, 0, bytesRead);
|
||||
data["I2"] = kaifa.GetInt((int)List2_ObisObjects::CurrentPhaseL2, buffer, 0, bytesRead);
|
||||
data["I3"] = kaifa.GetInt((int)List2_ObisObjects::CurrentPhaseL3, buffer, 0, bytesRead);
|
||||
data["U1"] = kaifa.GetInt((int)List2_ObisObjects::VoltagePhaseL1, buffer, 0, bytesRead);
|
||||
data["U2"] = kaifa.GetInt((int)List2_ObisObjects::VoltagePhaseL1, buffer, 0, bytesRead);
|
||||
data["U3"] = kaifa.GetInt((int)List2_ObisObjects::VoltagePhaseL1, buffer, 0, bytesRead);
|
||||
}
|
||||
else if (list == (byte)List::List3)
|
||||
{
|
||||
data["lv"] = kaifa.GetString((int)List3_ObisObjects::ObisListVersionIdentifier, buffer, 0, bytesRead);
|
||||
data["id"] = kaifa.GetString((int)List3_ObisObjects::MeterID, buffer, 0, bytesRead);
|
||||
data["type"] = kaifa.GetString((int)List3_ObisObjects::MeterType, buffer, 0, bytesRead);
|
||||
data["P"] = kaifa.GetInt((int)List3_ObisObjects::ActivePowerImported, buffer, 0, bytesRead);
|
||||
data["Q"] = kaifa.GetInt((int)List3_ObisObjects::ReactivePowerImported, buffer, 0, bytesRead);
|
||||
data["I1"] = kaifa.GetInt((int)List3_ObisObjects::CurrentPhaseL1, buffer, 0, bytesRead);
|
||||
data["I2"] = kaifa.GetInt((int)List3_ObisObjects::CurrentPhaseL2, buffer, 0, bytesRead);
|
||||
data["I3"] = kaifa.GetInt((int)List3_ObisObjects::CurrentPhaseL3, buffer, 0, bytesRead);
|
||||
data["U1"] = kaifa.GetInt((int)List3_ObisObjects::VoltagePhaseL1, buffer, 0, bytesRead);
|
||||
data["U2"] = kaifa.GetInt((int)List3_ObisObjects::VoltagePhaseL1, buffer, 0, bytesRead);
|
||||
data["U3"] = kaifa.GetInt((int)List3_ObisObjects::VoltagePhaseL1, buffer, 0, bytesRead);
|
||||
data["tPI"] = kaifa.GetInt((int)List3_ObisObjects::TotalActiveEnergyImported, buffer, 0, bytesRead);
|
||||
data["tPO"] = kaifa.GetInt((int)List3_ObisObjects::TotalActiveEnergyExported, buffer, 0, bytesRead);
|
||||
data["tQI"] = kaifa.GetInt((int)List3_ObisObjects::TotalReactiveEnergyImported, buffer, 0, bytesRead);
|
||||
data["tQO"] = kaifa.GetInt((int)List3_ObisObjects::TotalReactiveEnergyExported, buffer, 0, bytesRead);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial1.println("Invalid list");
|
||||
return;
|
||||
}
|
||||
|
||||
root.printTo(Serial1);
|
||||
Serial1.println();
|
||||
|
||||
char msg[1024];
|
||||
root.printTo(msg, 1024);
|
||||
client.publish("sensors/out/espdebugger", msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void writeAndEmptyBuffer()
|
||||
{
|
||||
for (int i = 0; i < bytesRead; i++)
|
||||
{
|
||||
if (buffer[i] < 0x10) Serial1.print("0");
|
||||
Serial1.print(buffer[i], HEX);
|
||||
Serial1.print(" ");
|
||||
void reconnect() {
|
||||
// Loop until we're reconnected
|
||||
while (!client.connected()) {
|
||||
Serial1.print("Attempting MQTT connection...");
|
||||
// Attempt to connect
|
||||
if (client.connect("ESP8266Client")) {
|
||||
Serial1.println("connected");
|
||||
// Once connected, publish an announcement...
|
||||
// client.publish("sensors", "hello world");
|
||||
// ... and resubscribe
|
||||
// client.subscribe("inTopic");
|
||||
} else {
|
||||
Serial1.print("failed, rc=");
|
||||
Serial1.print(client.state());
|
||||
Serial1.println(" try again in 5 seconds");
|
||||
// Wait 5 seconds before retrying
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
Serial1.println();
|
||||
bytesRead = 0;
|
||||
}
|
||||
|
||||
@ -6,11 +6,11 @@ byte KaifaHan::GetListID(byte *buffer, int start, int length)
|
||||
if (length > 23)
|
||||
{
|
||||
byte list = buffer[start + 23];
|
||||
if (list == List1) return List1;
|
||||
if (list == List2) return List2;
|
||||
if (list == List3) return List3;
|
||||
if (list == (byte)List::List1) return (byte)List::List1;
|
||||
if (list == (byte)List::List2) return (byte)List::List2;
|
||||
if (list == (byte)List::List3) return (byte)List::List3;
|
||||
}
|
||||
return ListUnknown;
|
||||
return (byte)List::ListUnknown;
|
||||
}
|
||||
|
||||
long KaifaHan::GetPackageTime(byte *buffer, int start, int length)
|
||||
@ -30,27 +30,51 @@ long KaifaHan::GetPackageTime(byte *buffer, int start, int length)
|
||||
|
||||
int KaifaHan::GetInt(int dataPosition, byte *buffer, int start, int length)
|
||||
{
|
||||
const int dataStart = 24;
|
||||
int value = 0;
|
||||
int foundPosition = 0;
|
||||
for (int i = start + dataStart; i < start + length; i++)
|
||||
int valuePosition = findValuePosition(dataPosition, buffer, start, length);
|
||||
if (valuePosition > 0)
|
||||
{
|
||||
if (foundPosition == 0)
|
||||
{
|
||||
if (buffer[i] == 0x06)
|
||||
foundPosition = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = value << 8 |
|
||||
buffer[i];
|
||||
if (i == foundPosition + 4)
|
||||
return value;
|
||||
}
|
||||
int value = 0;
|
||||
for (int i = valuePosition + 1; i < valuePosition + 5; i++)
|
||||
{
|
||||
value = value << 8 | buffer[i];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KaifaHan::findValuePosition(int dataPosition, byte *buffer, int start, int length)
|
||||
{
|
||||
const int dataStart = 24;
|
||||
for (int i=start + dataStart; i<length; i++)
|
||||
{
|
||||
if (dataPosition-- == 0)
|
||||
return i;
|
||||
else if (buffer[i] == 0x09) // string value
|
||||
i += buffer[i+1] + 1;
|
||||
else if (buffer[i] == 0x06) // integer value
|
||||
i += 4;
|
||||
else
|
||||
return 0; // unknown data type found
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
String KaifaHan::GetString(int dataPosition, byte *buffer, int start, int length)
|
||||
{
|
||||
int valuePosition = findValuePosition(dataPosition, buffer, start, length);
|
||||
if (valuePosition > 0)
|
||||
{
|
||||
String value = String("");
|
||||
for (int i = valuePosition + 2; i < valuePosition + buffer[valuePosition + 1]; i++)
|
||||
{
|
||||
value += String((char)buffer[i]);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return String("");
|
||||
}
|
||||
|
||||
time_t KaifaHan::toUnixTime(int year, int month, int day, int hour, int minute, int second)
|
||||
{
|
||||
byte daysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
@ -10,19 +10,64 @@
|
||||
class KaifaHan
|
||||
{
|
||||
public:
|
||||
const byte ListUnknown = 0x00;
|
||||
const byte List1 = 0x01;
|
||||
const byte List2 = 0x0D;
|
||||
const byte List3 = 0x12;
|
||||
byte GetListID(byte *buffer, int start, int length);
|
||||
long GetPackageTime(byte *buffer, int start, int length);
|
||||
int GetInt(int dataPosition, byte *buffer, int start, int length);
|
||||
String GetString(int dataPosition, byte *buffer, int start, int length);
|
||||
protected:
|
||||
|
||||
|
||||
private:
|
||||
int findValuePosition(int dataPosition, byte *buffer, int start, int length);
|
||||
time_t toUnixTime(int year, int month, int day, int hour, int minute, int second);
|
||||
};
|
||||
|
||||
enum class List : byte {
|
||||
ListUnknown = 0x00,
|
||||
List1 = 0x01,
|
||||
List2 = 0x0D,
|
||||
List3 = 0x12
|
||||
};
|
||||
|
||||
|
||||
enum class List1_ObisObjects {
|
||||
ActivePowerImported
|
||||
};
|
||||
|
||||
enum class List2_ObisObjects {
|
||||
ObisListVersionIdentifier,
|
||||
MeterID,
|
||||
MeterType,
|
||||
ActivePowerImported,
|
||||
ActivePowerExported,
|
||||
ReactivePowerImported,
|
||||
ReactivePowerExported,
|
||||
CurrentPhaseL1,
|
||||
CurrentPhaseL2,
|
||||
CurrentPhaseL3,
|
||||
VoltagePhaseL1,
|
||||
VoltagePhaseL2,
|
||||
VoltagePhaseL3
|
||||
};
|
||||
|
||||
enum class List3_ObisObjects {
|
||||
ObisListVersionIdentifier,
|
||||
MeterID,
|
||||
MeterType,
|
||||
ActivePowerImported,
|
||||
ActivePowerExported,
|
||||
ReactivePowerImported,
|
||||
ReactivePowerExported,
|
||||
CurrentPhaseL1,
|
||||
CurrentPhaseL2,
|
||||
CurrentPhaseL3,
|
||||
VoltagePhaseL1,
|
||||
VoltagePhaseL2,
|
||||
VoltagePhaseL3,
|
||||
ClockAndDate,
|
||||
TotalActiveEnergyImported,
|
||||
TotalActiveEnergyExported,
|
||||
TotalReactiveEnergyImported,
|
||||
TotalReactiveEnergyExported
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user