diff --git a/Code/Arduino/HanReader/examples/Kamstrup/mqtt/KamstrupMqtt.ino b/Code/Arduino/HanReader/examples/Kamstrup/mqtt/KamstrupMqtt.ino new file mode 100644 index 00000000..ba47176e --- /dev/null +++ b/Code/Arduino/HanReader/examples/Kamstrup/mqtt/KamstrupMqtt.ino @@ -0,0 +1,197 @@ +/* +* Simple sketch to simulate reading data from a Kamstrup +* AMS Meter. +* +* Created 24. October 2017 by Roar Fredriksen +* Modified 06. November 2017 by Ruben Andreassen +*/ + +#include +#include +#include + +#include +#include + +// The HAN Port reader +HanReader hanReader; + +// WiFi and MQTT endpoints +const char* ssid = "ssid"; +const char* password = "password"; +const char* mqtt_server = "ip or dns"; +const char* mqtt_topic = "sensors/out/espams"; +const char* device_name = "espams"; + +bool enableDebug = false; + +WiFiClient espClient; +PubSubClient client(espClient); + +void setup() { + //setupDebugPort(); //Comment out this line if you dont need debugging on Serial1 + setupWiFi(); + setupMqtt(); + + // initialize the HanReader + // (passing no han port, as we are feeding data manually, but provide Serial for debugging) + if (enableDebug) { + hanReader.setup(&Serial, 2400, SERIAL_8N1, &Serial1); + } else { + hanReader.setup(&Serial, 2400, SERIAL_8N1, NULL); + } +} + +void setupMqtt() +{ + client.setServer(mqtt_server, 1883); +} + +void setupDebugPort() +{ + enableDebug = true; + // Initialize the Serial port for debugging + Serial1.begin(115200); + while (!Serial1) {} + Serial1.setDebugOutput(true); + Serial1.println("Serial1"); + Serial1.println("Serial debugging port initialized"); +} + + +void setupWiFi() +{ + // Initialize wifi + if (enableDebug) { + Serial1.print("Connecting to "); + Serial1.println(ssid); + } + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + if (enableDebug) Serial1.print("."); + } + + if (enableDebug) { + Serial1.println(""); + Serial1.println("WiFi connected"); + Serial1.println("IP address: "); + Serial1.println(WiFi.localIP()); + } +} + +void loop() { + loopMqtt(); + + // Read one byte from the port, and see if we got a full package + if (hanReader.read()) + { + // Get the list identifier + int listSize = hanReader.getListSize(); + + if (enableDebug) { + Serial1.println(""); + Serial1.print("List size: "); + Serial1.print(listSize); + Serial1.print(": "); + } + + // Only care for the ACtive Power Imported, which is found in the first list + if (listSize == (int)Kamstrup::List1 || listSize == (int)Kamstrup::List2) + { + // Define a json object to keep the data + StaticJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.createObject(); + + // Any generic useful info here + root["dn"] = device_name; + root["up"] = millis(); + + // Add a sub-structure to the json object, + // to keep the data from the meter itself + JsonObject& data = root.createNestedObject("data"); + + data["ls"] = listSize; + + data["lvi"] = hanReader.getString((int)Kamstrup_List1::ListVersionIdentifier); + data["mid"] = hanReader.getString((int)Kamstrup_List1::MeterID); + data["mt"] = hanReader.getString((int)Kamstrup_List1::MeterType); + data["t"] = hanReader.getPackageTime(); + + data["aip"] = hanReader.getInt((int)Kamstrup_List1::ActiveImportPower); //power + data["aep"] = hanReader.getInt((int)Kamstrup_List1::ActiveExportPower); + data["rip"] = hanReader.getInt((int)Kamstrup_List1::ReactiveImportPower); + data["rep"] = hanReader.getInt((int)Kamstrup_List1::ReactiveExportPower); + + data["al1"] = (float)hanReader.getInt((int)Kamstrup_List1::CurrentL1) / 100.0; + data["al2"] = (float)hanReader.getInt((int)Kamstrup_List1::CurrentL2) / 100.0; + data["al3"] = (float)hanReader.getInt((int)Kamstrup_List1::CurrentL3) / 100.0; + + data["vl1"] = hanReader.getInt((int)Kamstrup_List1::VoltageL1); + data["vl2"] = hanReader.getInt((int)Kamstrup_List1::VoltageL2); + data["vl3"] = hanReader.getInt((int)Kamstrup_List1::VoltageL3); + + if (listSize == (int)Kamstrup::List2) + { + data["cl"] = hanReader.getTime((int)Kamstrup_List2::MeterClock); + data["caie"] = hanReader.getInt((int)Kamstrup_List2::CumulativeActiveImportEnergy); + data["caee"] = hanReader.getInt((int)Kamstrup_List2::CumulativeActiveExportEnergy); + data["crie"] = hanReader.getInt((int)Kamstrup_List2::CumulativeReactiveImportEnergy); + data["cree"] = hanReader.getInt((int)Kamstrup_List2::CumulativeReactiveExportEnergy); + } + + if (enableDebug) { + root.printTo(Serial1); + Serial1.println("JSON length"); + Serial1.println(root.measureLength()); + Serial1.println(""); + } + + // Publish the json to the MQTT server + char msg[MQTT_MAX_PACKET_SIZE]; + root.printTo(msg, MQTT_MAX_PACKET_SIZE); + bool result = client.publish(mqtt_topic, msg); + + if (enableDebug) { + Serial1.println("MQTT publish result:"); + Serial1.println(result); + } + } + } +} + + +// Ensure the MQTT lirary gets some attention too +void loopMqtt() +{ + if (!client.connected()) { + reconnectMqtt(); + } + client.loop(); +} + +void reconnectMqtt() { + // Loop until we're reconnected + while (!client.connected()) { + if (enableDebug) Serial1.print("Attempting MQTT connection..."); + // Attempt to connect + if (client.connect("ESP8266Client")) { + if (enableDebug) Serial1.println("connected"); + // Once connected, publish an announcement... + // client.publish("sensors", "hello world"); + // ... and resubscribe + // client.subscribe("inTopic"); + } + else { + if (enableDebug) { + Serial1.print("failed, rc="); + Serial1.print(client.state()); + Serial1.println(" try again in 5 seconds"); + } + // Wait 5 seconds before retrying + delay(5000); + } + } +} diff --git a/Code/Arduino/HanReader/examples/Kamstrup/mqtt/README.md b/Code/Arduino/HanReader/examples/Kamstrup/mqtt/README.md new file mode 100644 index 00000000..d925fb09 --- /dev/null +++ b/Code/Arduino/HanReader/examples/Kamstrup/mqtt/README.md @@ -0,0 +1,95 @@ +# Setup + +1. Copy AmsToMqttBridge\Code\Arduino\HanReader\src to Arduino\libraries +2. Download the following libraries and put them in Arduino\libraries + - ESP8266WiFi + - PubSubClient + - ArduinoJson +3. **Set MQTT_MAX_PACKET_SIZE in PubSubClient.h to at least 512 (i used 1024)** +4. Edit the following variables in the project: + - ssid + - password + - mqtt_server + - mqtt_topic + - device_name + +## Output example: +### List 1 +``` +{ + "dn": "espams", + "up": 1475902, + "data": { + "ls": 25, + "lvi": "Kamstrup_V0001", + "mid": "5706567274389702", + "mt": "6841121BN243101040", + "t": 1510088840, + "aip": 3499, + "aep": 0, + "rip": 0, + "rep": 424, + "al1": 10.27, + "al2": 6.37, + "al3": 11.79, + "vl1": 231, + "vl2": 226, + "vl3": 231 + } +} +``` +### List 2 +``` +{ + "dn": "espams", + "up": 1041212, + "data": { + "ls": 35, + "lvi": "Kamstrup_V0001", + "mid": "5706567274389702", + "mt": "6841121BN243101040", + "t": 1510088405, + "aip": 4459, + "aep": 0, + "rip": 0, + "rep": 207, + "al1": 14.72, + "al2": 6.39, + "al3": 15.02, + "vl1": 231, + "vl2": 227, + "vl3": 231, + "cl": 1510088405, + "caie": 588500, + "caee": 0, + "crie": 93, + "cree": 80831 + } +} +``` + +### List 1 and 2 fields +- dn = Device Name +- up = MS since last reboot +- ls = List Size +- lvi = List Version Identifier +- mid = Meter ID +- mt = Meter Type +- t = Time +- aie = Active Import Power +- aep = Active Export Power +- rip = Reactive Import Power +- rep = Reactive Export Power +- al1 = Current L1 +- al2 = Current L2 +- al3 = Current L3 +- cl1 = Voltage L1 +- cl2 = Voltage L2 +- cl3 = Voltage L3 + +### List 2 additional fields +- cl = Meter Clock +- caie = Cumulative Active Import Energy +- caee = Cumulative Active Export Energy +- crie = Cumulative Reactive Import Energy +- cree = Cumulative Reactive Export Energy \ No newline at end of file