/* * Simple sketch to simulate reading data from a Kamstrup * AMS Meter. * * Created 24. October 2017 by Roar Fredriksen */ #include #include "Kaifa.h" #include "HanReader.h" #include "HanToJson.h" // The HAN Port reader HanReader hanReader; byte meterType = 1; // Start with Kaifa int sampleIndex = 0; byte kaifa_samples[] = { // List #1 0x7E, 0xA0, 0x27, 0x01, 0x02, 0x01, 0x10, 0x5A, 0x87, 0xE6, 0xE7, 0x00, 0x0F, 0x40, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x07, 0xE1, 0x09, 0x0E, 0x04, 0x13, 0x1F, 0x02, 0xFF, 0x80, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x00, 0x03, 0x98, 0xAB, 0xAD, 0x7E, // List#2 0x7E, 0xA0, 0x79, 0x01, 0x02, 0x01, 0x10, 0x80, 0x93, 0xE6, 0xE7, 0x00, 0x0F, 0x40, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x07, 0xE1, 0x09, 0x0E, 0x04, 0x13, 0x1F, 0x0A, 0xFF, 0x80, 0x00, 0x00, 0x02, 0x0D, 0x09, 0x07, 0x4B, 0x46, 0x4D, 0x5F, 0x30, 0x30, 0x31, 0x09, 0x10, 0x36, 0x39, 0x37, 0x30, 0x36, 0x33, 0x31, 0x34, 0x30, 0x31, 0x37, 0x35, 0x33, 0x39, 0x38, 0x35, 0x09, 0x08, 0x4D, 0x41, 0x33, 0x30, 0x34, 0x48, 0x33, 0x45, 0x06, 0x00, 0x00, 0x03, 0x96, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x05, 0x64, 0x06, 0x00, 0x00, 0x0C, 0x92, 0x06, 0x00, 0x00, 0x0C, 0x49, 0x06, 0x00, 0x00, 0x09, 0x46, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x4E, 0x1F, 0x85, 0x7E, // List#3 0x7E, 0xA0, 0x9B, 0x01, 0x02, 0x01, 0x10, 0xEE, 0xAE, 0xE6, 0xE7, 0x00, 0x0F, 0x40, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x07, 0xE1, 0x09, 0x0E, 0x04, 0x14, 0x00, 0x0A, 0xFF, 0x80, 0x00, 0x00, 0x02, 0x12, 0x09, 0x07, 0x4B, 0x46, 0x4D, 0x5F, 0x30, 0x30, 0x31, 0x09, 0x10, 0x36, 0x39, 0x37, 0x30, 0x36, 0x33, 0x31, 0x34, 0x30, 0x31, 0x37, 0x35, 0x33, 0x39, 0x38, 0x35, 0x09, 0x08, 0x4D, 0x41, 0x33, 0x30, 0x34, 0x48, 0x33, 0x45, 0x06, 0x00, 0x00, 0x03, 0xFE, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, 0x07, 0x91, 0x06, 0x00, 0x00, 0x0C, 0x9D, 0x06, 0x00, 0x00, 0x0D, 0x66, 0x06, 0x00, 0x00, 0x09, 0x41, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x4C, 0x09, 0x0C, 0x07, 0xE1, 0x09, 0x0E, 0x04, 0x14, 0x00, 0x0A, 0xFF, 0x80, 0x00, 0x00, 0x06, 0x00, 0x02, 0xBF, 0x69, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF7, 0x06, 0x00, 0x00, 0x3F, 0xFC, 0x71, 0x71, 0x7E, // List#2.1 0x7e, 0xa0, 0x65, 0x01, 0x02, 0x01, 0x10, 0xf0, 0x50, 0xe6, 0xe7, 0x00, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x09, 0x0c, 0x07, 0xe3, 0x05, 0x08, 0x03, 0x16, 0x20, 0x28, 0xff, 0x80, 0x00, 0x00, 0x02, 0x09, 0x09, 0x07, 0x4b, 0x46, 0x4d, 0x5f, 0x30, 0x30, 0x31, 0x09, 0x10, 0x36, 0x39, 0x37, 0x30, 0x36, 0x33, 0x31, 0x34, 0x30, 0x31, 0x39, 0x39, 0x31, 0x36, 0x38, 0x34, 0x09, 0x08, 0x4d, 0x41, 0x31, 0x30, 0x35, 0x48, 0x32, 0x45, 0x06, 0x00, 0x00, 0x03, 0xa5, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x0e, 0x06, 0x00, 0x00, 0x09, 0x0a, 0x98, 0x76, 0x7e, }; byte aidon_samples[] = { // From Aidon-HAN-Interface-Description-v10A-ID-34331.pdf // List 2 sending (1-phase) 0x7e, 0xa0, 0xd2, 0x41, 0x08, 0x83, 0x13, 0x82, 0xd6, 0xe6, 0xe7, 0x00, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x02, 0x09, 0x06, 0x01, 0x01, 0x00, 0x02, 0x81, 0xff, 0x0a, 0x0b, 0x41, 0x49, 0x44, 0x4f, 0x4e, 0x5f, 0x56, 0x30, 0x30, 0x30, 0x31, 0x02, 0x02, 0x09, 0x06, 0x00, 0x00, 0x60, 0x01, 0x00, 0xff, 0x0a, 0x10, 0x37, 0x33, 0x35, 0x39, 0x39, 0x39, 0x32, 0x38, 0x39, 0x30, 0x39, 0x34, 0x31, 0x37, 0x34, 0x32, 0x02, 0x02, 0x09, 0x06, 0x00, 0x00, 0x60, 0x01, 0x07, 0xff, 0x0a, 0x04, 0x36, 0x35, 0x31, 0x35, 0x02, 0x03, 0x09, 0x06, 0x01, 0x00, 0x01, 0x07, 0x00, 0xff, 0x06, 0x00, 0x00, 0x05, 0x52, 0x02, 0x02, 0x0f, 0x00, 0x16, 0x1b, 0x02, 0x03, 0x09, 0x06, 0x01, 0x00, 0x02, 0x07, 0x00, 0xff, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x0f, 0x00, 0x16, 0x1b, 0x02, 0x03, 0x09, 0x06, 0x01, 0x00, 0x03, 0x07, 0x00, 0xff, 0x06, 0x00, 0x00, 0x03, 0xe4, 0x02, 0x02, 0x0f, 0x00, 0x16, 0x1d, 0x02, 0x03, 0x09, 0x06, 0x01, 0x00, 0x04, 0x07, 0x00, 0xff, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x0f, 0x00, 0x16, 0x1d, 0x02, 0x03, 0x09, 0x06, 0x01, 0x00, 0x1f, 0x07, 0x00, 0xff, 0x10, 0x00, 0x5d, 0x02, 0x02, 0x0f, 0xff, 0x16, 0x21, 0x02, 0x03, 0x09, 0x06, 0x01, 0x00, 0x20, 0x07, 0x00, 0xff, 0x12, 0x09, 0xc4, 0x02, 0x02, 0x0f, 0xff, 0x16, 0x23, 0xe0, 0xc4, 0x7e }; byte kamstrup_samples[] = { // [2017-10-20 04.43.32.368 - Received 229 (0xE5) bytes] // List #1 0x7E, 0xA0, 0xE2, 0x2B, 0x21, 0x13, 0x23, 0x9A, 0xE6, 0xE7, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x07, 0xE2, 0x03, 0x04, 0x07, 0x14, 0x3B, 0x32, 0xFF, 0x80, 0x00, 0x00, 0x02, 0x19, 0x0A, 0x0E, 0x4B, 0x61, 0x6D, 0x73, 0x74, 0x72, 0x75, 0x70, 0x5F, 0x56, 0x30, 0x30, 0x30, 0x31, 0x09, 0x06, 0x01, 0x01, 0x00, 0x00, 0x05, 0xFF, 0x0A, 0x10, 0x35, 0x37, 0x30, 0x36, 0x35, 0x36, 0x37, 0x32, 0x37, 0x34, 0x33, 0x38, 0x39, 0x37, 0x30, 0x32, 0x09, 0x06, 0x01, 0x01, 0x60, 0x01, 0x01, 0xFF, 0x0A, 0x12, 0x36, 0x38, 0x34, 0x31, 0x31, 0x32, 0x31, 0x42, 0x4E, 0x32, 0x34, 0x33, 0x31, 0x30, 0x31, 0x30, 0x34, 0x30, 0x09, 0x06, 0x01, 0x01, 0x01, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x11, 0x28, 0x09, 0x06, 0x01, 0x01, 0x02, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x09, 0x06, 0x01, 0x01, 0x03, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x84, 0x09, 0x06, 0x01, 0x01, 0x04, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x09, 0x06, 0x01, 0x01, 0x1F, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x05, 0x66, 0x09, 0x06, 0x01, 0x01, 0x33, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x03, 0x0C, 0x09, 0x06, 0x01, 0x01, 0x47, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x05, 0x5A, 0x09, 0x06, 0x01, 0x01, 0x20, 0x07, 0x00, 0xFF, 0x12, 0x00, 0xE0, 0x09, 0x06, 0x01, 0x01, 0x34, 0x07, 0x00, 0xFF, 0x12, 0x00, 0xDF, 0x09, 0x06, 0x01, 0x01, 0x48, 0x07, 0x00, 0xFF, 0x12, 0x00, 0xDF, 0xA1, 0xD8, 0x7E, // List #2 0x7E, 0xA1, 0x2C, 0x2B, 0x21, 0x13, 0xFC, 0x04, 0xE6, 0xE7, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x07, 0xE2, 0x03, 0x04, 0x07, 0x15, 0x00, 0x05, 0xFF, 0x80, 0x00, 0x00, 0x02, 0x23, 0x0A, 0x0E, 0x4B, 0x61, 0x6D, 0x73, 0x74, 0x72, 0x75, 0x70, 0x5F, 0x56, 0x30, 0x30, 0x30, 0x31, 0x09, 0x06, 0x01, 0x01, 0x00, 0x00, 0x05, 0xFF, 0x0A, 0x10, 0x35, 0x37, 0x30, 0x36, 0x35, 0x36, 0x37, 0x32, 0x37, 0x34, 0x33, 0x38, 0x39, 0x37, 0x30, 0x32, 0x09, 0x06, 0x01, 0x01, 0x60, 0x01, 0x01, 0xFF, 0x0A, 0x12, 0x36, 0x38, 0x34, 0x31, 0x31, 0x32, 0x31, 0x42, 0x4E, 0x32, 0x34, 0x33, 0x31, 0x30, 0x31, 0x30, 0x34, 0x30, 0x09, 0x06, 0x01, 0x01, 0x01, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x0E, 0x3B, 0x09, 0x06, 0x01, 0x01, 0x02, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x09, 0x06, 0x01, 0x01, 0x03, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x86, 0x09, 0x06, 0x01, 0x01, 0x04, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x09, 0x06, 0x01, 0x01, 0x1F, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x04, 0x21, 0x09, 0x06, 0x01, 0x01, 0x33, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x03, 0x0C, 0x09, 0x06, 0x01, 0x01, 0x47, 0x07, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x04, 0x1C, 0x09, 0x06, 0x01, 0x01, 0x20, 0x07, 0x00, 0xFF, 0x12, 0x00, 0xE2, 0x09, 0x06, 0x01, 0x01, 0x34, 0x07, 0x00, 0xFF, 0x12, 0x00, 0xE0, 0x09, 0x06, 0x01, 0x01, 0x48, 0x07, 0x00, 0xFF, 0x12, 0x00, 0xDF, 0x09, 0x06, 0x00, 0x01, 0x01, 0x00, 0x00, 0xFF, 0x09, 0x0C, 0x07, 0xE2, 0x03, 0x04, 0x07, 0x15, 0x00, 0x05, 0xFF, 0x80, 0x00, 0x00, 0x09, 0x06, 0x01, 0x01, 0x01, 0x08, 0x00, 0xFF, 0x06, 0x00, 0x1A, 0x40, 0x49, 0x09, 0x06, 0x01, 0x01, 0x02, 0x08, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x09, 0x06, 0x01, 0x01, 0x03, 0x08, 0x00, 0xFF, 0x06, 0x00, 0x00, 0x05, 0x64, 0x09, 0x06, 0x01, 0x01, 0x04, 0x08, 0x00, 0xFF, 0x06, 0x00, 0x02, 0x7B, 0x21, 0x20, 0x92, 0x7E }; void setup() { Serial.begin(115200); while (!Serial) {} Serial.println("Serial debugging port initialized"); // initialize the HanReader // (passing no han port, as we are feeding data manually, but provide Serial for debugging) hanReader.setup(NULL, &Serial); hanReader.compensateFor09HeaderBug = true; // Starting with Kaifa } void loopKaifa() { if (sampleIndex >= sizeof(kaifa_samples)) { meterType++; sampleIndex = 0; hanReader.setup(NULL, &Serial); hanReader.compensateFor09HeaderBug = false; Serial.println("Done with Kaifa"); } // Read one byte from the "port", and see if we got a full package if (hanReader.read(kaifa_samples[sampleIndex++])) { StaticJsonDocument<500> doc; JsonObject data = doc.createNestedObject("data"); hanToJson(data, meterType, hanReader); Serial.println("Kaifa JsonData: "); serializeJsonPretty(doc, Serial); Serial.println(); } } void loopAidon() { if (sampleIndex >= sizeof(aidon_samples)) { meterType++; sampleIndex = 0; hanReader.setup(NULL, &Serial); Serial.println("Done with Aidon"); } // Read one byte from the "port", and see if we got a full package if (hanReader.read(aidon_samples[sampleIndex++])) { DynamicJsonDocument doc(500); JsonObject data = doc.createNestedObject("data"); hanToJson(data, meterType, hanReader); Serial.println("Aidon JsonData: "); serializeJsonPretty(doc, Serial); Serial.println(); } } void loopKamstrup() { if (sampleIndex >= sizeof(kamstrup_samples)) { meterType++; sampleIndex = 0; hanReader.setup(NULL, &Serial); Serial.println("Done with Kamstrup"); } // Read one byte from the "port", and see if we got a full package if (hanReader.read(kamstrup_samples[sampleIndex++])) { DynamicJsonDocument doc(500); JsonObject data = doc.createNestedObject("data"); hanToJson(data, meterType, hanReader); Serial.println("Kamstrup JsonData: "); serializeJsonPretty(doc, Serial); Serial.println(); } } void loop() { delay(2); switch (meterType) { case 1: // Kaifa return loopKaifa(); case 2: // Aidon return loopAidon(); case 3: // Kamstrup return loopKamstrup(); default: Serial.println("Done"); while (true) ; break; } }