Skip to content

Instantly share code, notes, and snippets.

@puckipedia
Last active October 13, 2019 17:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save puckipedia/b96f3039e0aec441274326d97452150f to your computer and use it in GitHub Desktop.
Save puckipedia/b96f3039e0aec441274326d97452150f to your computer and use it in GitHub Desktop.
// code is MIT licensed etc etc copyright 2018 Puck Meerburg that kind of stuff
// -- Libraries used --
// DSMR lib: https://github.com/matthijskooijman/arduino-dsmr
#include <dsmr.h>
// MQTT client: https://github.com/knolleary/pubsubclient
#include <PubSubClient.h>
// ESP8266 OTA
#include <ArduinoOTA.h>
// look I'm not going to pay for a signal inverter. hooray for software
#define INVERT_SERIAL
#ifdef INVERT_SERIAL
#define ESP8266_REG(addr) *((volatile uint32_t *)(0x60000000+(addr)))
#define USC0(u) ESP8266_REG(0x020+(0xF00*(u&1))) //CONF0
#define UCRXI 19 // Invert RX
#endif
#include <ESP8266WiFi.h>
using P1Data = ParsedData<
identification,
timestamp,
/* FixedValue */ energy_delivered_tariff1,
/* FixedValue */ energy_delivered_tariff2,
/* FixedValue */ energy_returned_tariff1,
/* FixedValue */ energy_returned_tariff2,
/* String */ electricity_tariff,
/* FixedValue */ power_delivered,
/* FixedValue */ power_returned
>;
// pin 3 is the request pin, but I'm like 90% certain it isn't connected on mine
P1Reader reader(&Serial, 3);
// connect via wifi
WiFiClient wifiClient;
// yes! mqtt!
PubSubClient mqtt("[mqtt host]", 1883, wifiClient);
void setup() {
// setup serial, both debug + non-debug
Serial.begin(115200);
// connect to the wifi
WiFi.begin("[wifi ssid]", "[wifi pass]");
WiFi.hostname("SmartMeter");
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println(WiFi.localIP());
// I have used this a few times, super useful
ArduinoOTA.onStart([]() { mqtt.publish("power/update", "updating", false); });
ArduinoOTA.onEnd([]() { });
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { });
ArduinoOTA.begin();
Serial.println("Flipping RX bit now... Goodbye!");
delay(1000);
// use GPIO13/D7 for receiving from the P1 port, to allow for less work when debugging
Serial.pins(15, 13);
#ifdef INVERT_SERIAL
USC0(0) |= (1 << UCRXI); // magick the UART into inverse mode
#endif
reader.enable(false);
}
void loop() {
// ensure that MQTT is connected
if (!mqtt.connected()) {
// if the connection dies, the MQTT server will set power/status to disconnected. useful for debugging
while (!mqtt.connect("smartmeter", "bot_smartmeter", "[mqtt pass]", "power/status", 1, 1, "disconnected"));
mqtt.publish("power/status", "active", true);
}
// call event loop for subparts
mqtt.loop();
reader.loop();
ArduinoOTA.handle();
if (reader.available()) {
P1Data data;
String err;
// do we have data?
if (reader.parse(&data, &err)) {
// put it all into the MQTT world
mqtt.publish("power/identification", data.identification.c_str(), false);
mqtt.publish("power/timestamp", data.timestamp.c_str(), false);
char buffer[24];
itoa(data.energy_delivered_tariff1.int_val(), buffer, 10);
mqtt.publish("power/energy/delivered/t1", buffer, true);
itoa(data.energy_delivered_tariff2.int_val(), buffer, 10);
mqtt.publish("power/energy/delivered/t2", buffer, true);
itoa(data.energy_returned_tariff1.int_val(), buffer, 10);
mqtt.publish("power/energy/returned/t1", buffer, true);
itoa(data.energy_returned_tariff2.int_val(), buffer, 10);
mqtt.publish("power/energy/returned/t2", buffer, true);
mqtt.publish("power/tariff", data.electricity_tariff.c_str(), false);
itoa(data.power_delivered.int_val(), buffer, 10);
mqtt.publish("power/power/delivered", buffer, true);
itoa(data.power_returned.int_val(), buffer, 10);
mqtt.publish("power/power/returned", buffer, true);
} else {
// error occured. who cares.
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment