119 lines
2.6 KiB
C++
119 lines
2.6 KiB
C++
|
#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("<STX>"));
|
||
|
localBCC = 0xFF;
|
||
|
ZPAreadData = "";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (r == 0x03) {
|
||
|
Serial.println(F("<ETX>"));
|
||
|
Serial.print(F("Checksum <BCC>: "));
|
||
|
uint8_t remoteBCC = Serial2.read();
|
||
|
Serial.print(remoteBCC, HEX);
|
||
|
Serial.println();
|
||
|
Serial.print(F("Calculated <BCC>: "));
|
||
|
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);
|
||
|
}
|
||
|
}
|