diff --git a/frames/EGM5G35.txt b/frames/EGM5G35.txt new file mode 100644 index 00000000..bfd44aab --- /dev/null +++ b/frames/EGM5G35.txt @@ -0,0 +1,14 @@ +2F 45 47 4D 35 47 33 35 // DSMR Identifier +0D 0A // CRLF +0D 0A // CRLF +00 // System title, blank +82 // Two-byte length follows +02 30 // 560 bytes +30 // Security tag 0011 0000, 0=Compression off, 0=Unicast, 1=Encryption, 1=Authentication, 0000= Security Suite ID +00 00 00 00 // Frame counter, blank + +// Encrypted payload follows (560 - security tag - frame counter = 555 bytes) +30 10 73 D6 59 85 96 B0 2A 8B CC E7 33 AD 19 A3 A5 4A 4D 0E 3A CE F6 33 DB 57 0A 45 9A C3 5B F0 D4 C0 AA 15 B9 93 B0 E8 67 85 EC 22 CA 40 8C D7 1A B5 62 AE DF 0F 48 EA D9 E6 56 FB 84 B3 7B 47 C6 29 12 F1 EE BB 22 88 26 75 5C F8 A2 20 F4 93 F3 64 CA 7C C6 60 32 62 B0 7F F9 7F 71 0A 9F DF AB 61 89 6A 9A 10 B1 DF 94 2C 74 8F 51 B6 09 5C F2 45 6C 38 54 52 FE B6 CB 1F 42 F2 93 DC 57 BE EE 5A 0D F8 1F 53 55 0E 21 EF 46 0A 72 74 CA AB D8 9C A9 05 9E FD 54 5E CC 7B 71 40 E1 22 B2 25 5C D5 63 80 BD 97 6E 54 4B 24 A6 58 1F 79 1F 45 C7 DF C0 83 3B 7F 1E C7 43 B9 26 F6 EB 6E F2 B1 7C 99 3A 91 EA 39 72 E5 FB 72 B1 E1 24 AF 9D 19 8A 6C 50 69 97 90 D3 3D 68 97 57 C2 EC 49 EF 12 1D 11 44 46 70 46 88 88 98 37 6F B0 93 FC D2 3F 37 66 1C C7 F0 93 E3 AF 4D 3C BE 41 8E B9 48 77 A9 92 5B 42 0A 96 E5 34 4D 30 56 90 5A 08 03 CC 41 78 58 79 FD 89 82 E0 46 3D 66 AA 42 85 F4 A8 46 2D 4A E4 81 12 40 68 D6 F5 F9 11 5A 94 51 21 3C 9F 4F F7 FE B3 B5 BF 1E D2 12 CF B9 FB 28 D0 B4 82 9E 11 D8 1C FC E3 36 EC DE 8A 7C 83 76 F7 EB 3D 2C 4A B7 7F 75 91 F1 F5 18 D4 70 6A C9 3E 3D 3F 9E 0F C6 0F A7 E7 20 11 03 E7 75 4E 40 F1 5E BA 86 30 6D C0 28 C4 14 47 DF 6A EF CC FE E4 B6 23 58 2B 9D 4F BF 6A A8 93 84 F4 CD 4D FF 47 B5 C4 81 D2 DA D3 6B C3 F4 1D C4 6E E1 9B 24 30 91 7B 33 57 67 B6 E4 93 FE 8B 5B AE 8A 0D 81 DE A5 C3 3F 82 9A CE E2 BA 6D 50 39 FC 99 E6 7A 7B B4 E9 A9 84 78 AF 2D 4C D2 15 53 6B 98 2B 1F C8 3D 57 9E 49 68 40 0C D3 4A 9E D6 4F 1F 12 50 84 32 AD 62 C6 D3 42 34 46 66 65 56 49 81 F4 BC 8E C6 75 77 11 1F 29 BB 80 20 23 0A 80 D5 31 50 16 89 6F 07 4A 25 BE F0 4B 60 36 87 AE A6 2A 53 79 22 15 A5 2A C7 1D 15 7B 87 DD B5 07 3D 1C 28 C1 B6 51 47 2F 39 DE D9 B9 29 B6 78 +21 // End of DSMR (!) +46 45 30 43 // FE0C - Checksum +0D 0A // CRLF diff --git a/lib/AmsConfiguration/include/hexutils.h b/lib/AmsConfiguration/include/hexutils.h index 45d6285a..73f62c66 100644 --- a/lib/AmsConfiguration/include/hexutils.h +++ b/lib/AmsConfiguration/include/hexutils.h @@ -14,5 +14,6 @@ String toHex(uint8_t* in); String toHex(uint8_t* in, uint16_t size); void fromHex(uint8_t *out, String in, uint16_t size); bool stripNonAscii(uint8_t* in, uint16_t size, bool extended = false); +void debugPrint(uint8_t *buffer, uint16_t start, uint16_t length, Print* debugger); #endif \ No newline at end of file diff --git a/lib/AmsConfiguration/src/hexutils.cpp b/lib/AmsConfiguration/src/hexutils.cpp index 35819aa0..c60e6350 100644 --- a/lib/AmsConfiguration/src/hexutils.cpp +++ b/lib/AmsConfiguration/src/hexutils.cpp @@ -45,4 +45,20 @@ bool stripNonAscii(uint8_t* in, uint16_t size, bool extended) { } memset(in+size-1, 0, 1); // Make sure the last character is null-terminator return ret; +} + +void debugPrint(uint8_t *buffer, uint16_t start, uint16_t length, Print* debugger) { + for (uint16_t i = start; i < start + length; i++) { + if (buffer[i] < 0x10) + debugger->print(F("0")); + debugger->print(buffer[i], HEX); + debugger->print(F(" ")); + if ((i - start + 1) % 16 == 0) + debugger->println(F("")); + else if ((i - start + 1) % 4 == 0) + debugger->print(F(" ")); + + yield(); // Let other get some resources too + } + debugger->println(F("")); } \ No newline at end of file diff --git a/lib/AmsDecoder/include/DsmrParser.h b/lib/AmsDecoder/include/DsmrParser.h index 4e2a7f94..91abf8a0 100644 --- a/lib/AmsDecoder/include/DsmrParser.h +++ b/lib/AmsDecoder/include/DsmrParser.h @@ -9,15 +9,19 @@ #include "Arduino.h" #include "DataParser.h" +#include "GcmParser.h" class DSMRParser { public: - int8_t parse(uint8_t *buf, DataParserContext &ctx, bool verified); + DSMRParser(GCMParser* gcmParser) { this->gcmParser = gcmParser; }; + int8_t parse(uint8_t *buf, DataParserContext &ctx, bool verified, Print* debugger); uint16_t getCrc(); uint16_t getCrcCalc(); private: uint16_t crc; uint16_t crc_calc; + + GCMParser* gcmParser; }; #endif diff --git a/lib/AmsDecoder/include/GcmParser.h b/lib/AmsDecoder/include/GcmParser.h index fb65ee49..73594446 100644 --- a/lib/AmsDecoder/include/GcmParser.h +++ b/lib/AmsDecoder/include/GcmParser.h @@ -18,7 +18,7 @@ class GCMParser { public: GCMParser(uint8_t *encryption_key, uint8_t *authentication_key); - int8_t parse(uint8_t *buf, DataParserContext &ctx); + int8_t parse(uint8_t *buf, DataParserContext &ctx, bool hastag = true); private: uint8_t encryption_key[16]; uint8_t authentication_key[16]; diff --git a/lib/AmsDecoder/src/DsmrParser.cpp b/lib/AmsDecoder/src/DsmrParser.cpp index 6d2379df..e638f015 100644 --- a/lib/AmsDecoder/src/DsmrParser.cpp +++ b/lib/AmsDecoder/src/DsmrParser.cpp @@ -9,27 +9,77 @@ #include "hexutils.h" #include "lwip/def.h" -int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) { +// verified indicates that this data was encapsulated in something else, so we know this has the correct size etc +int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified, Print* debugger) { + uint16_t lenBefore = ctx.length; uint16_t crcPos = 0; bool reachedEnd = verified; uint8_t lastByte = 0x00; - for(int pos = 0; pos < ctx.length; pos++) { + for(uint16_t pos = 0; pos < ctx.length; pos++) { uint8_t b = *(buf+pos); if(pos == 0 && b != '/') return DATA_PARSE_BOUNDRY_FLAG_MISSING; - if(pos > 0 && b == '!' && lastByte == '\n') crcPos = pos+1; - if(crcPos > 0 && b == '\n') reachedEnd = true; + if(pos > 0 && b == '!') crcPos = pos+1; + if(crcPos > 0 && b == 0x0A && lastByte == 0x0D) { + reachedEnd = true; + ctx.length = pos; + break; + } lastByte = b; } if(!reachedEnd) return DATA_PARSE_INCOMPLETE; buf[ctx.length+1] = '\0'; - if(crcPos > 0) { + + // If we expect data to be encrypted and it was not previously verified, decrypt content + if(gcmParser != NULL && !verified) { + uint8_t* ptr = (uint8_t*) buf; + while(*ptr != 0x0D && *ptr != 0x0A) ptr++; + while(*ptr == 0x0D || *ptr == 0x0A) ptr++; + uint16_t pos = ptr-buf; + DataParserContext gcmCtx = { + DATA_TAG_GCM, + crcPos - pos - 1, + ctx.timestamp + }; + if(debugger != NULL) { + debugger->printf_P(PSTR("DSMR wants to decrypt at position %lu, length: %d, payload:\n"), pos, gcmCtx.length); + debugPrint(ptr, 0, gcmCtx.length, debugger); + } + int8_t gcmRet = gcmParser->parse(ptr, gcmCtx, false); + if(gcmRet < 0) { + if(debugger != NULL) { + debugger->printf_P(PSTR(" - Failed! (%d)\n"), gcmRet); + } + return gcmRet; + } else { + if(debugger != NULL) { + debugger->printf_P(PSTR(" - Success! (%d)\n"), gcmRet); + } + ptr += gcmRet; + for(uint16_t i = 0; i < gcmCtx.length; i++) { + buf[pos++] = ptr[i]; + } + ptr = buf + crcPos - 1; + crcPos = pos + 1; + while(*ptr != '\0') { + ctx.length = pos; + buf[pos++] = *(ptr++); + } + while(pos < lenBefore) { + buf[pos++] = '\0'; + } + } + } else if(crcPos > 0) { crc_calc = crc16(buf, crcPos); crc = 0x0000; fromHex((uint8_t*) &crc, String((char*) buf+crcPos), 2); crc = ntohs(crc); - if(crc != crc_calc) + if(crc != crc_calc) { + if(debugger != NULL) { + debugger->printf_P(PSTR("CRC incorrrect, %04X != %04X at position %lu\n"), crc, crc_calc, crcPos); + } return DATA_PARSE_FOOTER_CHECKSUM_ERROR; + } } return DATA_PARSE_OK; } diff --git a/lib/AmsDecoder/src/GcmParser.cpp b/lib/AmsDecoder/src/GcmParser.cpp index eb605792..54de8a71 100644 --- a/lib/AmsDecoder/src/GcmParser.cpp +++ b/lib/AmsDecoder/src/GcmParser.cpp @@ -17,25 +17,34 @@ GCMParser::GCMParser(uint8_t *encryption_key, uint8_t *authentication_key) { memcpy(this->authentication_key, authentication_key, 16); } -int8_t GCMParser::parse(uint8_t *d, DataParserContext &ctx) { +int8_t GCMParser::parse(uint8_t *d, DataParserContext &ctx, bool hastag) { if(ctx.length < 12) return DATA_PARSE_INCOMPLETE; + uint32_t headersize = 0; uint8_t* ptr = (uint8_t*) d; - if(*ptr != GCM_TAG) return DATA_PARSE_BOUNDRY_FLAG_MISSING; - ptr++; + if(hastag) { + if(*ptr != GCM_TAG) return DATA_PARSE_BOUNDRY_FLAG_MISSING; + ptr++; + headersize++; + } // Encrypted APDU // http://www.weigu.lu/tutorials/sensors2bus/04_encryption/index.html uint8_t systemTitleLength = *ptr; ptr++; + headersize++; uint8_t initialization_vector[12]; - memcpy(ctx.system_title, ptr, systemTitleLength); - memcpy(initialization_vector, ctx.system_title, systemTitleLength); + memset(ctx.system_title, 0, 8); + memset(initialization_vector, 0, 12); + if(systemTitleLength > 0) { + memcpy(ctx.system_title, ptr, systemTitleLength); + memcpy(initialization_vector, ctx.system_title, systemTitleLength); + ptr += systemTitleLength; + headersize += systemTitleLength; + } uint32_t len = 0; - uint32_t headersize = 2 + systemTitleLength; - ptr += systemTitleLength; if(((*ptr) & 0xFF) == 0x81) { // 1-byte payload length ptr++; diff --git a/lib/CloudConnector/include/CloudConnector.h b/lib/CloudConnector/include/CloudConnector.h index fcc15128..49cf8efc 100644 --- a/lib/CloudConnector/include/CloudConnector.h +++ b/lib/CloudConnector/include/CloudConnector.h @@ -110,7 +110,6 @@ private: char* pers = "amsreader"; bool init(); - void debugPrint(byte *buffer, int start, int length); String meterManufacturer(uint8_t type) { switch(type) { diff --git a/lib/CloudConnector/src/CloudConnector.cpp b/lib/CloudConnector/src/CloudConnector.cpp index dc83e92f..43509d9d 100644 --- a/lib/CloudConnector/src/CloudConnector.cpp +++ b/lib/CloudConnector/src/CloudConnector.cpp @@ -597,22 +597,6 @@ void CloudConnector::setEnergyAccountingConfig(EnergyAccountingConfig& eac) { this->lastEac = 0; } -void CloudConnector::debugPrint(byte *buffer, int start, int length) { - for (int i = start; i < start + length; i++) { - if (buffer[i] < 0x10) - debugger->print(F("0")); - debugger->print(buffer[i], HEX); - debugger->print(F(" ")); - if ((i - start + 1) % 16 == 0) - debugger->println(F("")); - else if ((i - start + 1) % 4 == 0) - debugger->print(F(" ")); - - yield(); // Let other get some resources too - } - debugger->println(F("")); -} - String CloudConnector::generateSeed() { uint8_t key[16]; ESPRandom::uuid4(key); diff --git a/lib/MeterCommunicators/include/PassiveMeterCommunicator.h b/lib/MeterCommunicators/include/PassiveMeterCommunicator.h index 84acb717..dee40e58 100644 --- a/lib/MeterCommunicators/include/PassiveMeterCommunicator.h +++ b/lib/MeterCommunicators/include/PassiveMeterCommunicator.h @@ -89,7 +89,6 @@ protected: void setupHanPort(uint32_t baud, uint8_t parityOrdinal, bool invert, bool passive = true); int16_t unwrapData(uint8_t *buf, DataParserContext &context); - void debugPrint(byte *buffer, int start, int length); void printHanReadError(int pos); void handleAutodetect(unsigned long now); }; diff --git a/lib/MeterCommunicators/src/KmpCommunicator.cpp b/lib/MeterCommunicators/src/KmpCommunicator.cpp index 381922dc..e7aa2add 100644 --- a/lib/MeterCommunicators/src/KmpCommunicator.cpp +++ b/lib/MeterCommunicators/src/KmpCommunicator.cpp @@ -8,6 +8,7 @@ #include "Uptime.h" #include "crc.h" #include "OBIScodes.h" +#include "hexutils.h" void KmpCommunicator::configure(MeterConfig& meterConfig) { this->meterConfig = meterConfig; @@ -43,7 +44,7 @@ bool KmpCommunicator::loop() { #endif { debugger->printf_P(PSTR(" payload:\n")); - debugPrint(hanBuffer, 0, hanBufferSize); + debugPrint(hanBuffer, 0, hanBufferSize, debugger); } } return ret; diff --git a/lib/MeterCommunicators/src/PassiveMeterCommunicator.cpp b/lib/MeterCommunicators/src/PassiveMeterCommunicator.cpp index 43f31c51..f00ac922 100644 --- a/lib/MeterCommunicators/src/PassiveMeterCommunicator.cpp +++ b/lib/MeterCommunicators/src/PassiveMeterCommunicator.cpp @@ -9,6 +9,7 @@ #include "IEC6205621.h" #include "LNG.h" #include "LNG2.h" +#include "hexutils.h" #if defined(ESP32) #include @@ -32,10 +33,23 @@ void PassiveMeterCommunicator::configure(MeterConfig& meterConfig, Timezone* tz) this->configChanged = false; this->tz = tz; setupHanPort(meterConfig.baud, meterConfig.parity, meterConfig.invert); + if(dsmrParser != NULL) { + delete dsmrParser; + dsmrParser = NULL; + } if(gcmParser != NULL) { delete gcmParser; gcmParser = NULL; } + bool encen = false; + for(uint8_t i = 0; i < 16; i++) { + if(meterConfig.encryptionKey[i] > 0) { + encen = true; + } + } + if(encen) { + gcmParser = new GCMParser(meterConfig.encryptionKey, meterConfig.authenticationKey); + } } bool PassiveMeterCommunicator::loop() { @@ -68,9 +82,9 @@ bool PassiveMeterCommunicator::loop() { hanSerial->readBytes(hanBuffer, hanBufferSize); len = 0; #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::INFO)) -#endif -debugger->printf_P(PSTR("Buffer overflow, resetting\n")); + if (debugger->isActive(RemoteDebug::INFO)) + #endif + debugger->printf_P(PSTR("Buffer overflow, resetting\n")); return false; } hanBuffer[len++] = hanSerial->read(); @@ -80,46 +94,46 @@ debugger->printf_P(PSTR("Buffer overflow, resetting\n")); switch(ctx.type) { case DATA_TAG_DLMS: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::DEBUG)) -#endif -debugger->printf_P(PSTR("Received valid DLMS at %d\n"), pos); + if (debugger->isActive(RemoteDebug::DEBUG)) + #endif + debugger->printf_P(PSTR("Received valid DLMS at %d +%d\n"), pos, ctx.length); break; case DATA_TAG_DSMR: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::DEBUG)) -#endif -debugger->printf_P(PSTR("Received valid DSMR at %d\n"), pos); + if (debugger->isActive(RemoteDebug::DEBUG)) + #endif + debugger->printf_P(PSTR("Received valid DSMR at %d +%d\n"), pos, ctx.length); break; case DATA_TAG_SNRM: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::DEBUG)) -#endif -debugger->printf_P(PSTR("Received valid SNMR at %d\n"), pos); + if (debugger->isActive(RemoteDebug::DEBUG)) + #endif + debugger->printf_P(PSTR("Received valid SNMR at %d +%d\n"), pos, ctx.length); break; case DATA_TAG_AARE: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::DEBUG)) -#endif -debugger->printf_P(PSTR("Received valid AARE at %d\n"), pos); + if (debugger->isActive(RemoteDebug::DEBUG)) + #endif + debugger->printf_P(PSTR("Received valid AARE at %d +%d\n"), pos, ctx.length); break; case DATA_TAG_RES: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::DEBUG)) -#endif -debugger->printf_P(PSTR("Received valid Get Response at %d\n"), pos); + if (debugger->isActive(RemoteDebug::DEBUG)) + #endif + debugger->printf_P(PSTR("Received valid Get Response at %d +%d\n"), pos, ctx.length); break; case DATA_TAG_HDLC: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::DEBUG)) -#endif -debugger->printf_P(PSTR("Received valid HDLC at %d\n"), pos); + if (debugger->isActive(RemoteDebug::DEBUG)) + #endif + debugger->printf_P(PSTR("Received valid HDLC at %d +%d\n"), pos, ctx.length); break; default: // TODO: Move this so that payload is sent to MQTT #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::ERROR)) -#endif -debugger->printf_P(PSTR("Unknown tag %02X at pos %d\n"), ctx.type, pos); + if (debugger->isActive(RemoteDebug::ERROR)) + #endif + debugger->printf_P(PSTR("Unknown tag %02X at pos %d\n"), ctx.type, pos); len = 0; return false; } @@ -129,26 +143,26 @@ debugger->printf_P(PSTR("Unknown tag %02X at pos %d\n"), ctx.type, pos); end = millis(); if(end-start > 1000) { #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::WARNING)) -#endif -debugger->printf_P(PSTR("Used %dms to unwrap HAN data\n"), end-start); + if (debugger->isActive(RemoteDebug::WARNING)) + #endif + debugger->printf_P(PSTR("Used %dms to unwrap HAN data\n"), end-start); } if(pos == DATA_PARSE_INCOMPLETE) { return false; } else if(pos == DATA_PARSE_UNKNOWN_DATA) { #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::WARNING)) -#endif -debugger->printf_P(PSTR("Unknown data received\n")); + if (debugger->isActive(RemoteDebug::WARNING)) + #endif + debugger->printf_P(PSTR("Unknown data received\n")); lastError = pos; len = len + hanSerial->readBytes(hanBuffer+len, hanBufferSize-len); #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -{ + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + { debugger->printf_P(PSTR(" payload:\n")); - debugPrint(hanBuffer, 0, len); + debugPrint(hanBuffer, 0, len, debugger); } len = 0; return false; @@ -164,11 +178,11 @@ if (debugger->isActive(RemoteDebug::VERBOSE)) pt->publishBytes(hanBuffer, len); } #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -{ + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + { debugger->printf_P(PSTR(" payload:\n")); - debugPrint(hanBuffer, 0, len); + debugPrint(hanBuffer, 0, len, debugger); } while(hanSerial->available()) hanSerial->read(); // Make sure it is all empty, in case we overflowed buffer above len = 0; @@ -177,17 +191,17 @@ if (debugger->isActive(RemoteDebug::VERBOSE)) if(ctx.type == 0) { #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::WARNING)) -#endif -debugger->printf_P(PSTR("Ended up with context type %d, return code %d and length: %lu/%lu\n"), ctx.type, pos, ctx.length, len); + if (debugger->isActive(RemoteDebug::WARNING)) + #endif + debugger->printf_P(PSTR("Ended up with context type %d, return code %d and length: %lu/%lu\n"), ctx.type, pos, ctx.length, len); lastError = pos; len = len + hanSerial->readBytes(hanBuffer+len, hanBufferSize-len); #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -{ + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + { debugger->printf_P(PSTR(" payload:\n")); - debugPrint(hanBuffer, 0, len); + debugPrint(hanBuffer, 0, len, debugger); } len = 0; return false; @@ -226,7 +240,7 @@ debugger->printf_P(PSTR("Using application data:\n")); #if defined(AMS_REMOTE_DEBUG) if (debugger->isActive(RemoteDebug::VERBOSE)) #endif -debugPrint((byte*) payload, 0, ctx.length); +debugPrint((byte*) payload, 0, ctx.length, debugger); // Rudimentary detector for L&G proprietary format, this is terrible code... Fix later if(payload[0] == CosemTypeStructure && payload[2] == CosemTypeArray && payload[1] == payload[3]) { @@ -351,8 +365,8 @@ int16_t PassiveMeterCommunicator::unwrapData(uint8_t *buf, DataParserContext &co if(res >= 0) doRet = true; break; case DATA_TAG_DSMR: - if(dsmrParser == NULL) dsmrParser = new DSMRParser(); - res = dsmrParser->parse(buf, context, lastTag != DATA_TAG_NONE); + if(dsmrParser == NULL) dsmrParser = new DSMRParser(gcmParser); + res = dsmrParser->parse(buf, context, lastTag != DATA_TAG_NONE, debugger->isActive(RemoteDebug::VERBOSE) ? debugger : NULL); if(res >= 0) doRet = true; break; case DATA_TAG_SNRM: @@ -363,9 +377,9 @@ int16_t PassiveMeterCommunicator::unwrapData(uint8_t *buf, DataParserContext &co break; default: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::ERROR)) -#endif -debugger->printf_P(PSTR("Ended up in default case while unwrapping...(tag %02X)\n"), tag); + if (debugger->isActive(RemoteDebug::ERROR)) + #endif + debugger->printf_P(PSTR("Ended up in default case while unwrapping...(tag %02X)\n"), tag); return DATA_PARSE_UNKNOWN_DATA; } lastTag = tag; @@ -374,9 +388,9 @@ debugger->printf_P(PSTR("Ended up in default case while unwrapping...(tag %02X)\ } if(context.length > end) { #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("Context length %lu > %lu:\n"), context.length, end); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("Context length %lu > %lu:\n"), context.length, end); context.type = 0; context.length = 0; return false; @@ -384,78 +398,78 @@ debugger->printf_P(PSTR("Context length %lu > %lu:\n"), context.length, end); switch(tag) { case DATA_TAG_HDLC: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("HDLC frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("HDLC frame:\n")); if(pt != NULL) { pt->publishBytes(buf, curLen); } break; case DATA_TAG_MBUS: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("MBUS frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("MBUS frame:\n")); if(pt != NULL) { pt->publishBytes(buf, curLen); } break; case DATA_TAG_GBT: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("GBT frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("GBT frame:\n")); break; case DATA_TAG_GCM: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("GCM frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("GCM frame:\n")); break; case DATA_TAG_LLC: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("LLC frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("LLC frame:\n")); break; case DATA_TAG_DLMS: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("DLMS frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("DLMS frame:\n")); break; case DATA_TAG_DSMR: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("DSMR frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("DSMR frame:\n")); if(pt != NULL) { pt->publishString((char*) buf); } break; case DATA_TAG_SNRM: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("SNMR frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("SNMR frame:\n")); break; case DATA_TAG_AARE: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("AARE frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("AARE frame:\n")); break; case DATA_TAG_RES: #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugger->printf_P(PSTR("RES frame:\n")); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugger->printf_P(PSTR("RES frame:\n")); break; } #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::VERBOSE)) -#endif -debugPrint(buf, 0, curLen); + if (debugger->isActive(RemoteDebug::VERBOSE)) + #endif + debugPrint(buf, 0, curLen, debugger); if(res == DATA_PARSE_FINAL_SEGMENT) { if(tag == DATA_TAG_MBUS) { res = mbusParser->write(buf, context); @@ -479,28 +493,12 @@ debugPrint(buf, 0, curLen); tag = (*buf); } #if defined(AMS_REMOTE_DEBUG) -if (debugger->isActive(RemoteDebug::ERROR)) -#endif -debugger->printf_P(PSTR("Got to end of unwrap method...\n")); + if (debugger->isActive(RemoteDebug::ERROR)) + #endif + debugger->printf_P(PSTR("Got to end of unwrap method...\n")); return DATA_PARSE_UNKNOWN_DATA; } -void PassiveMeterCommunicator::debugPrint(byte *buffer, int start, int length) { - for (int i = start; i < start + length; i++) { - if (buffer[i] < 0x10) - debugger->print(F("0")); - debugger->print(buffer[i], HEX); - debugger->print(F(" ")); - if ((i - start + 1) % 16 == 0) - debugger->println(F("")); - else if ((i - start + 1) % 4 == 0) - debugger->print(F(" ")); - - yield(); // Let other get some resources too - } - debugger->println(F("")); -} - void PassiveMeterCommunicator::printHanReadError(int pos) { #if defined(AMS_REMOTE_DEBUG) if (debugger->isActive(RemoteDebug::WARNING)) diff --git a/lib/PriceService/include/PriceService.h b/lib/PriceService/include/PriceService.h index b0a619a2..af720b21 100644 --- a/lib/PriceService/include/PriceService.h +++ b/lib/PriceService/include/PriceService.h @@ -129,7 +129,5 @@ private: PricesContainer* fetchPrices(time_t); bool retrieve(const char* url, Stream* doc); float getCurrencyMultiplier(const char* from, const char* to, time_t t); - - void debugPrint(byte *buffer, int start, int length); }; #endif diff --git a/lib/PriceService/src/PriceService.cpp b/lib/PriceService/src/PriceService.cpp index dabed5c9..a536d384 100644 --- a/lib/PriceService/src/PriceService.cpp +++ b/lib/PriceService/src/PriceService.cpp @@ -540,22 +540,6 @@ debugger->printf(http->getString().c_str()); return NULL; } -void PriceService::debugPrint(byte *buffer, int start, int length) { - for (int i = start; i < start + length; i++) { - if (buffer[i] < 0x10) - debugger->print(F("0")); - debugger->print(buffer[i], HEX); - debugger->print(F(" ")); - if ((i - start + 1) % 16 == 0) - debugger->println(F("")); - else if ((i - start + 1) % 4 == 0) - debugger->print(F(" ")); - - yield(); // Let other get some resources too - } - debugger->println(F("")); -} - int16_t PriceService::getLastError() { return lastError; } diff --git a/tmp/KamstrupPullCommunicator.cpp b/tmp/KamstrupPullCommunicator.cpp index ad9de363..770a3620 100644 --- a/tmp/KamstrupPullCommunicator.cpp +++ b/tmp/KamstrupPullCommunicator.cpp @@ -7,6 +7,7 @@ #include "KamstrupPullCommunicator.h" #include "Uptime.h" #include "Cosem.h" +#include "hexutils.h" #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) #include @@ -259,7 +260,7 @@ AmsData* KamstrupPullCommunicator::getData(AmsData& meterState) { byte* payload = ((byte *) (hanBuffer)) + pos; if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf_P(PSTR("Received data from Kamstrup meter:\n")); - debugPrint(payload, 0, min(ctx.length, (uint16_t) BUF_SIZE_HAN)); + debugPrint(payload, 0, min(ctx.length, (uint16_t) BUF_SIZE_HAN), debugger); } if(hanBuffer[11] == DATA_TAG_RES) { @@ -332,7 +333,7 @@ void KamstrupPullCommunicator::sendConnectMessage() { if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf_P(PSTR("Sending data to Kamstrup meter:\n")); - debugPrint(hanBuffer, 0, i); + debugPrint(hanBuffer, 0, i, debugger); } state = STATE_CONNECTING; len = 0; @@ -350,7 +351,7 @@ bool KamstrupPullCommunicator::checkForConnectConfirmed() { byte* payload = ((byte *) (hanBuffer)) + pos; if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf_P(PSTR("Received data from Kamstrup meter:\n")); - debugPrint(payload, 0, min(ctx.length, (uint16_t) BUF_SIZE_HAN)); + debugPrint(payload, 0, min(ctx.length, (uint16_t) BUF_SIZE_HAN), debugger); } len = 0; @@ -531,7 +532,7 @@ void KamstrupPullCommunicator::sendAssociateMessage() { if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf_P(PSTR("Sending data to Kamstrup meter:\n")); - debugPrint(hanBuffer, 0, i); + debugPrint(hanBuffer, 0, i, debugger); } state = STATE_CONNECTED_ASSOCIATING; len = 0; @@ -549,7 +550,7 @@ bool KamstrupPullCommunicator::checkForAssociationConfirmed() { byte* payload = ((byte *) (hanBuffer)) + pos; if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf_P(PSTR("Received data from Kamstrup meter:\n")); - debugPrint(payload, 0, ctx.length); + debugPrint(payload, 0, ctx.length, debugger); } len = 0; dataAvailable = false; @@ -642,7 +643,7 @@ bool KamstrupPullCommunicator::requestData() { if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf_P(PSTR("Sending data to Kamstrup meter:\n")); - debugPrint(hanBuffer, 0, i); + debugPrint(hanBuffer, 0, i, debugger); } len = 0; @@ -674,7 +675,7 @@ void KamstrupPullCommunicator::sendDisconnectMessage() { if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf_P(PSTR("Sending data to Kamstrup meter:\n")); - debugPrint(hanBuffer, 0, i); + debugPrint(hanBuffer, 0, i, debugger); } state = STATE_DISCONNECTING; len = 0; @@ -692,7 +693,7 @@ bool KamstrupPullCommunicator::checkForDisconnectMessage() { if(debugger->isActive(RemoteDebug::INFO)) { debugger->printf_P(PSTR("Received data from Kamstrup meter:\n")); - debugPrint(hanBuffer, 0, ctx.length); + debugPrint(hanBuffer, 0, ctx.length, debugger); } for(int i = 0; i 1) lastError = 90+err; } - -void KamstrupPullCommunicator::debugPrint(byte *buffer, int start, int length) { - for (int i = start; i < start + length; i++) { - if (buffer[i] < 0x10) - debugger->print(F("0")); - debugger->print(buffer[i], HEX); - debugger->print(F(" ")); - if ((i - start + 1) % 16 == 0) - debugger->println(F("")); - else if ((i - start + 1) % 4 == 0) - debugger->print(F(" ")); - - yield(); // Let other get some resources too - } - debugger->println(F("")); -} diff --git a/tmp/KamstrupPullCommunicator.h b/tmp/KamstrupPullCommunicator.h index 6b6ddbb2..dc642d62 100644 --- a/tmp/KamstrupPullCommunicator.h +++ b/tmp/KamstrupPullCommunicator.h @@ -72,8 +72,6 @@ private: bool requestData(); void sendDisconnectMessage(); bool checkForDisconnectMessage(); - - void debugPrint(byte *buffer, int start, int length); }; #endif