#include "ZPAElectricity.h" // BCC is calculated as follows (source https://github.com/lvzon/dsmr-p1-parser/blob/master/doc/IEC-62056-21-notes.md): // The BCC is calculated over the bytes after STX up to and including the ETX byte // To calculate this BCC, take the first byte XOR 0xff // XOR this value with the second byte, and so forth up to and including the last byte (include 0x03 ETX !!), // and XOR the final value with 0xff. // State flags bool stateZPAreading = false; uint32_t lastZPAcharRead = 0; uint8_t localBCC; String ZPAreadData = ""; bool ZPAreading() { return stateZPAreading; } void ZPArequestData() { Serial2.updateBaudRate(300); Serial.println(F("Requesting data")); Serial2.print(F("/?!\r\n")); // Start reading, set up actual time stateZPAreading = true; lastZPAcharRead = millis(); } void ZPAchangeBaudrate(char baud) { int baudrate = 300; switch (baud) { case '1': baudrate = 300; break; case '2': baudrate = 1200; break; case '3': baudrate = 2400; break; case '4': baudrate = 4800; break; } Serial.print(F("Change baudrate to ")); Serial.print(baud); Serial.print(F(" (")); Serial.print(baudrate); Serial.println(F(")")); Serial2.write(0x06); Serial2.print(F("0")); Serial2.print(baud); Serial2.print(F("0\r\n")); Serial2.flush(); Serial2.updateBaudRate(baudrate); } void handleZPASerial() { if (!stateZPAreading) return; if (Serial2.available()) { char r = Serial2.read(); lastZPAcharRead = millis(); if (r == 0x02) { Serial.println(F("")); localBCC = 0xFF; ZPAreadData = ""; return; } if (r == 0x03) { Serial.println(F("")); Serial.print(F("Checksum : ")); uint8_t remoteBCC = Serial2.read(); Serial.print(remoteBCC, HEX); Serial.println(); Serial.print(F("Calculated : ")); localBCC = localBCC ^ r; localBCC = localBCC ^ 0xFF; Serial.print(localBCC, HEX); Serial.println(); Serial.println(); Serial.println(F("Changing back baudrate to 300")); Serial2.updateBaudRate(300); stateZPAreading = false; return; } // Calculate BCC checksum localBCC = localBCC ^ r; ZPAreadData += r; Serial.write(r); } } void handleZPA() { handleZPASerial(); if (stateZPAreading && (millis() > lastZPAcharRead + ZPA_READ_TIMEOUT)) { Serial.println(F("ZPA Read TIMEOUT, stopping, setting baudrate to 300")); stateZPAreading = false; ZPAreadData = ""; Serial2.updateBaudRate(300); } }