/*
# Example of DlmsCosemLib
https://github.com/Zeppelin500/DlmsCosemLib
## Licence
****************************************************
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************
The example decodes an already encrypted payload (plaintext) of a M-Bus DLMS/COSEM telegram and send the records via serial.
*/
#include <DlmsCosemLib.h> // Library to decode DLMS / COSEM Plaintext
#include <ArduinoJson.h> // is used to transfer the decoded recordings
// init the library class
DlmsCosemLib dlms;
unsigned long timer = 5000;
void setup() {
Serial.begin(9600);
}
void loop() {
if(millis() - timer > 5000){
timer = millis();
// payload plaintext of a DLMS / COSEM M-Bus Telegram of an austrian energy meter.
uint8_t plaintext[] = {0x0F,0x80,0x06,0x87,0x0E,0x0C,0x07,0xE5,0x09,0x1B,0x01,0x09,0x2F,0x0F,0x00,0xFF,0x88,0x80,0x02,0x23,0x09,0x0C,0x07,0xE5,0x09,0x1B,0x01,0x09,0x2F,0x0F,0x00,0xFF,0x88,0x80,0x09,0x06,0x01,0x00,0x01,0x08,0x00,0xFF,0x06,0x00,0x00,0x32,0x89,0x02,0x02,0x0F,0x00,0x16,0x1E,0x09,0x06,0x01,0x00,0x02,0x08,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x02,0x02,0x0F,0x00,0x16,0x1E,0x09,0x06,0x01,0x00,0x01,0x07,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x02,0x02,0x0F,0x00,0x16,0x1B,0x09,0x06,0x01,0x00,0x02,0x07,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x02,0x02,0x0F,0x00,0x16,0x1B,0x09,0x06,0x01,0x00,0x20,0x07,0x00,0xFF,0x12,0x09,0x21,0x02,0x02,0x0F,0xFF,0x16,0x23,0x09,0x06,0x01,0x00,0x34,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFF,0x16,0x23,0x09,0x06,0x01,0x00,0x48,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFF,0x16,0x23,0x09,0x06,0x01,0x00,0x1F,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFE,0x16,0x21,0x09,0x06,0x01,0x00,0x33,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFE,0x16,0x21,0x09,0x06,0x01,0x00,0x47,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFE,0x16,0x21,0x09,0x06,0x01,0x00,0x0D,0x07,0x00,0xFF,0x12,0x03,0xE8,0x02,0x02,0x0F,0xFD,0x16,0xFF,0x09,0x0C,0x31,0x38,0x31,0x32,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x39};
// Plaintext with an Error to show the error message.
//uint8_t plaintext[] = {0x0F,0x80,0x06,0x87,0x0E,0x0C,0x07,0xE5,0x09,0x1B,0x01,0x09,0x2F,0x0F,0x00,0xFF,0x88,0x80,0x02,0x23,0x09,0x0C,0x07,0xE5,0x09,0x1B,0x01,0x09,0x2F,0x0F,0x00,0xFF,0x88,0x80,0x09,0x06,0x01,0x00,0x01,0x08,0x00,0xFF,0x06,0x00,0x00,0x32,0x89,0x02,0x02,0x0F,0x00,0x16,0x1E,0x09,0x06,0x01,0x00,0x02,0x08,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x02,0x02,0x0F,0x00,0x16,0x1E,0x09,0x06,0x01,0x00,0x01,0x07,0x00,0xFF,0x55,0x00,0x00,0x00,0x00,0x02,0x02,0x0F,0x00,0x16,0x1B,0x09,0x06,0x01,0x00,0x02,0x07,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x02,0x02,0x0F,0x00,0x16,0x1B,0x09,0x06,0x01,0x00,0x20,0x07,0x00,0xFF,0x12,0x09,0x21,0x02,0x02,0x0F,0xFF,0x16,0x23,0x09,0x06,0x01,0x00,0x34,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFF,0x16,0x23,0x09,0x06,0x01,0x00,0x48,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFF,0x16,0x23,0x09,0x06,0x01,0x00,0x1F,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFE,0x16,0x21,0x09,0x06,0x01,0x00,0x33,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFE,0x16,0x21,0x09,0x06,0x01,0x00,0x47,0x07,0x00,0xFF,0x12,0x00,0x00,0x02,0x02,0x0F,0xFE,0x16,0x21,0x09,0x06,0x01,0x00,0x0D,0x07,0x00,0xFF,0x12,0x03,0xE8,0x02,0x02,0x0F,0xFD,0x16,0xFF,0x09,0x0C,0x31,0x38,0x31,0x32,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x39};
// another meter
//uint8_t plaintext[] = {0x0F,0x00,0x00,0x55,0x39,0x0C,0x07,0xE0,0x09,0x08,0x04,0x13,0x0D,0x19,0x00,0xFF,0xC4,0x80,0x02,0x07,0x09,0x0C,0x07,0xE0,0x09,0x08,0x04,0x13,0x0D,0x19,0x00,0x00,0x00,0x80,0x09,0x06,0x01,0x00,0x01,0x08,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x02,0x02,0x0F,0x00,0x16,0x1E,0x09,0x06,0x01,0x00,0x03,0x08,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x02,0x02,0x0F,0x00,0x16,0x20};
//init the JSON
JsonDocument jsonBuffer;
JsonArray root = jsonBuffer.add<JsonArray>();
// decode
int8_t fields = dlms.decode(&plaintext[0], sizeof(plaintext), root);
char jsonstring[3074] = { 0 };
serializeJson(root, jsonstring);
Serial.print("fields = ");
Serial.println(fields);
Serial.println("###################### new message ###################### ");
Serial.println(String("jsonstring = " + String(jsonstring)).c_str());
Serial.println("###################### records ########################## ");
// Send Records
if (fields > 0) {
const char *meternumber = root[fields]["meter_number"]; // after the last Record
Serial.println(String("MeterNumber = " + String(meternumber)).c_str());
const char *timestamp = root[0]["timestamp"]; // before the first Record
Serial.println(String("Timestamp = " + String(timestamp)).c_str());
for (uint8_t i = 1; i < fields; i++) {
const char *obisString = root[i]["obis"];
const char *name = root[i]["name"];
const char *units = root[i]["units"];
double value = root[i]["value_scaled"].as<double>();
Serial.println("");
Serial.println(String(String(name) + "_OBIScode = " + String(obisString)).c_str());
Serial.println(String(String(name) + " = " + String(value, 3)).c_str());
Serial.println(String(String(name) + "_unit = " + String(units)).c_str());
}
}else{
char error[40] = {0};
strcpy(error,dlms.getError(fields)); // errors are coded as negative values in the "fields" variable
Serial.println(String("error = " + String(error)).c_str());
}
Serial.println("###################### end of message ###################### ");
}
}