More adaptations for Austian meters

This commit is contained in:
Gunnar Skjold
2021-12-07 19:07:43 +01:00
parent 38cba4e8da
commit eb479f8216
6 changed files with 73 additions and 34 deletions

View File

@@ -2,5 +2,30 @@
7E A0 2A 41 08 83 13 04 13 E6 E7 00 0F 40 00 00 00 00 01 01 02 03 09 06 01 00 01 07 00 FF 06 00 00 08 64 02 02 0F 00 16 1B E1
7E A1 1E 41 08 83 13 EE EE E6 E7 00 0F 40 00 00 00 00 01 0D 02 02 09 06 01 01 00 02 81 FF 0A 0B 41 49 44 4F 4E 5F 56 30 30 30 31 02 02 09 06 00 00 60 01 00 FF 0A 10 37 33 35 39 39 39 32 38 39 30 34 39 37 39 39 37 02 02 09 06 00 00 60 01 07 FF 0A 04 36 35 33 34 02 03 09 06 01 00 01 07 00 FF 06 00 00 08 6C 02 02 0F 00 16 1B 02 03 09 06 01 00 02 07 00 FF 06 00 00 00 00 02 02 0F 00 16 1B 02 03 09 06 01 00 03 07 00 FF 06 00 00 00 00 02 02 0F 00 16 1D 02 03 09 06 01 00 04 07 00 FF 06 00 00 02 09 02 02 0F 00 16 1D 02 03 09 06 01 00 1F 07 00 FF 10 00 41 02 02 0F FF 16 21 02 03 09 06 01 00 33 07 00 FF 10 00 13 02 02 0F FF 16 21 02 03 09 06 01 00 47 07 00 FF 10 00 0E 02 02 0F FF 16 21 02 03 09 06 01 00 20 07 00 FF 12 08 F2 02 02 0F FF 16 23 02 03 09 06 01 00 34 07 00 FF 12 08 D1 02 02 0F FF 16 23 02 03 09 06 01 00 48 07 00 FF 12 08 E8 02 02 0F FF 16 23 8B
7E A1 8A 41 08 83 13 EB FD E6 E7 00 0F 40 00 00 00 00 01 12 02 02 09 06 01 01 00 02 81 FF 0A 0B 41 49 44 4F 4E 5F 56 30 30 30 31 02 02 09 06 00 00 60 01 00 FF 0A 10 37 33 35 39 39 39 32 38 39 30 34 39 37 39 39 37 02 02 09 06 00 00 60 01 07 FF 0A 04 36 35 33 34 02 03 09 06 01 00 01 07 00 FF 06 00 00 03 9A 02 02 0F 00 16 1B 02 03 09 06 01 00 02 07 00 FF 06 00 00 00 00 02 02 0F 00 16 1B 02 03 09 06 01 00 03 07 00 FF 06 00 00 00 00 02 02 0F 00 16 1D 02 03 09 06 01 00 04 07 00 FF 06 00 00 02 0E 02 02 0F 00 16 1D 02 03 09 06 01 00 1F 07 00 FF 10 00 11 02 02 0F FF 16 21 02 03 09 06 01 00 33 07 00 FF 10 00 10 02 02 0F FF 16 21 02 03 09 06 01 00 47 07 00 FF 10 00 0E 02 02 0F FF 16 21 02 03 09 06 01 00 20 07 00 FF 12 08 F4 02 02 0F FF 16 23 02 03 09 06 01 00 34 07 00 FF 12 08 CD 02 02 0F FF 16 23 02 03 09 06 01 00 48 07 00 FF 12 08 DC 02 02 0F FF 16 23 02 02 09 06 00 00 01 00 00 FF 09 0C 07 E5 03 18 03 08 00 00 FF 00 00 00 02 03 09 06 01 00 01 08 00 FF 06 00 47 F0 34 02 02 0F 01 16 1E 02 03 09 06 01 00 02 08 00 FF 06 00 00 00 00 02 02 0F 01 16 1E 02 03 09 06 01 00 03 08 00 FF 06 00 00 21 9E 02 02 0F 01 16 20 02 03 09 06 01 00 04 08 00 FF 06 00 08 E0 21 02 02 0F 01 16 20 57
7E A1 8A 41 08 83 13 EB FD E6 E7 00 0F 40 00 00 00 00 01 12 02 02 09 06 01 01 00 02 81 FF 0A 0B 41 49 44 4F 4E 5F 56 30 30 30 31 02 02 09 06 00 00 60 01 00 FF 0A 10 37 33 35 39 39 39 32 38 39 30 34 39 37 39 39 37 02 02 09 06 00 00 60 01 07 FF 0A 04 36 35 33 34 02 03 09 06 01 00 01 07 00 FF 06 00 00 09 6D 02 02 0F 00 16 1B 02 03 09 06 01 00 02 07 00 FF 06 00 00 00 00 02 02 0F 00 16 1B 02 03 09 06 01 00 03 07 00 FF 06 00 00 00 00 02 02 0F 00 16 1D 02 03 09 06 01 00 04 07 00 FF 06 00 00 02 5B 02 02 0F 00 16 1D 02 03 09 06 01 00 1F 07 00 FF 10 00 11 02 02 0F FF 16 21 02 03 09 06 01 00 33 07 00 FF 10 00 03 02 02 0F FF 16 21 02 03 09 06 01 00 47 07 00 FF 10 00 5A 02 02 0F FF 16 21 02 03 09 06 01 00 20 07 00 FF 12 09 04 02 02 0F FF 16 23 02 03 09 06 01 00 34 07 00 FF 12 09 02 02 02 0F FF 16 23 02 03 09 06 01 00 48 07 00 FF 12 08 EC 02 02 0F FF 16 23 02 02 09 06 00 00 01 00 00 FF 09 0C 07 E5 0A 1F 00 14 00 00 FF 00 00 00 02 03 09 06 01 00 01 08 00 FF 06 00 56 9F 52 02 02 0F 01 16 1E 02 03 09 06 01 00 02 08 00 FF 06 00 00 00 00 02 02 0F 01 16 1E 02 03 09 06 01 00 03 08 00 FF 06 00 00 22 D0 02 02 0F 01 16 20 02 03 09 06 01 00 04 08 00 FF 06 00 0A F5 EC 02 02 0F 01 16 20 51 D7 7E
7E A0 2A 41 08 83 13 04 13 E6 E7 00 0F 40 00 00 00 00 01 01 02 03 09 06 01 00 01 07 00 FF 06 00 00 09 56 02 02 0F 00 16 1B AF A1 7E
7E A1 8A 41 08 83 13 EB FD E6 E7 00 0F 40 00 00 00 00
01 12
02 02 09 06 01 01 00 02 81 FF 0A 0B 41 49 44 4F 4E 5F 56 30 30 30 31
02 02 09 06 00 00 60 01 00 FF 0A 10 37 33 35 39 39 39 32 38 39 30 34 39 37 39 39 37
02 02 09 06 00 00 60 01 07 FF 0A 04 36 35 33 34
02 03 09 06 01 00 01 07 00 FF 06 00 00 09 6D 02 02 0F 00 16 1B
02 03 09 06 01 00 02 07 00 FF 06 00 00 00 00 02 02 0F 00 16 1B
02 03 09 06 01 00 03 07 00 FF 06 00 00 00 00 02 02 0F 00 16 1D
02 03 09 06 01 00 04 07 00 FF 06 00 00 02 5B 02 02 0F 00 16 1D
Object with three values Value Object with two values
| Obis code | | Scaling
| | | | | Unit
02 03 09 06 01 00 1F 07 00 FF 10 00 11 02 02 0F FF 16 21
02 03 09 06 01 00 33 07 00 FF 10 00 03 02 02 0F FF 16 21
02 03 09 06 01 00 47 07 00 FF 10 00 5A 02 02 0F FF 16 21
02 03 09 06 01 00 20 07 00 FF 12 09 04 02 02 0F FF 16 23
02 03 09 06 01 00 34 07 00 FF 12 09 02 02 02 0F FF 16 23
02 03 09 06 01 00 48 07 00 FF 12 08 EC 02 02 0F FF 16 23
02 02 09 06 00 00 01 00 00 FF 09 0C 07 E5 0A 1F 00 14 00 00 FF 00 00 00
02 03 09 06 01 00 01 08 00 FF 06 00 56 9F 52 02 02 0F 01 16 1E
02 03 09 06 01 00 02 08 00 FF 06 00 00 00 00 02 02 0F 01 16 1E
02 03 09 06 01 00 03 08 00 FF 06 00 00 22 D0 02 02 0F 01 16 20
02 03 09 06 01 00 04 08 00 FF 06 00 0A F5 EC 02 02 0F 01 16 20
51 D7
7E

View File

@@ -21,9 +21,16 @@ bool AmsDataStorage::update(AmsData* data) {
debugger->printf("(AmsDataStorage) Time is: %d\n", now);
}
if(now < EPOCH_2021_01_01) {
now = data->getMeterTimestamp();
if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("(AmsDataStorage) Using meter timestamp, which is: %d\n", now);
if(data->getMeterTimestamp() > 0) {
now = data->getMeterTimestamp();
if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("(AmsDataStorage) Using meter timestamp, which is: %d\n", now);
}
} else if(data->getPackageTimestamp() > 0) {
now = data->getPackageTimestamp();
if(debugger->isActive(RemoteDebug::DEBUG)) {
debugger->printf("(AmsDataStorage) Using package timestamp, which is: %d\n", now);
}
}
}
if(now-day.lastMeterReadTime < 3595) {

View File

@@ -429,7 +429,7 @@ void loop() {
errorBlink();
}
if (mqttEnabled) {
if (mqttEnabled || config.isMqttChanged()) {
if(mqtt == NULL || !mqtt->connected() || config.isMqttChanged()) {
MQTT_connect();
}
@@ -670,7 +670,7 @@ void readHanPort() {
}
if(currentMeterType == 0) {
uint8_t flag = hanSerial->read();
if(flag == 0x7E) currentMeterType = 1;
if(flag == 0x7E || flag == 0x68) currentMeterType = 1;
else currentMeterType = 2;
hanSerial->readBytes(buf, BUF_SIZE);
return;
@@ -716,7 +716,8 @@ void readHanPort() {
}
}
len = 0;
if(pos >= 0) {
if(pos > 0) {
while(hanSerial->available()) hanSerial->read();
debugI("Valid HDLC, start at %d", pos);
data = IEC6205675(((char *) (buf)) + pos, meterState.getMeterType(), timestamp);
} else {
@@ -774,11 +775,9 @@ void readHanPort() {
meterState.apply(data);
if(ds.update(&meterState)) {
if(ds.update(&data)) {
debugI("Saving day plot");
ds.save();
} else if(data.getListType() == 3) {
debugE("Unable to update day plot");
}
}
delay(1);
@@ -963,7 +962,8 @@ void MQTT_connect() {
debugI("Found MQTT CA file");
file = LittleFS.open(FILE_MQTT_CA, "r");
#if defined(ESP8266)
// Disabled for ESP8266
BearSSL::X509List *serverTrustedCA = new BearSSL::X509List(file);
mqttSecureClient->setTrustAnchors(serverTrustedCA);
#elif defined(ESP32)
mqttSecureClient->loadCACert(file, file.size());
#endif
@@ -971,7 +971,11 @@ void MQTT_connect() {
if(LittleFS.exists(FILE_MQTT_CERT) && LittleFS.exists(FILE_MQTT_KEY)) {
#if defined(ESP8266)
// Disabled for ESP8266
file = LittleFS.open(FILE_MQTT_CERT, "r");
BearSSL::X509List *serverCertList = new BearSSL::X509List(file);
file = LittleFS.open(FILE_MQTT_KEY, "r");
BearSSL::PrivateKey *serverPrivKey = new BearSSL::PrivateKey(file);
mqttSecureClient->setClientRSACert(serverCertList, serverPrivKey);
#elif defined(ESP32)
debugI("Found MQTT certificate file");
file = LittleFS.open(FILE_MQTT_CERT, "r");

View File

@@ -217,7 +217,7 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, CosemDateTime packag
int adiv = 1;
int watt = (l1voltage * l1current) + (l2voltage * l2current) + (l3voltage * l3current);
while(watt / activeImportPower > 2) {
while(activeImportPower > 0 && watt / activeImportPower > 2) {
adiv *= 10;
watt /= 10;
}

View File

@@ -25,7 +25,7 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
HDLCHeader* h = (HDLCHeader*) d;
uint8_t* ptr = (uint8_t*) &h[1];
// Frame format type 3
if((h->format & 0xF0) == 0xA0) {
if(h->flag == HDLC_FLAG && (h->format & 0xF0) == 0xA0) {
// Length field (11 lsb of format)
len = (ntohs(h->format) & 0x7FF) + 2;
if(len > length)
@@ -66,16 +66,13 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
return HDLC_HCS_ERROR;
ptr += sizeof *t3;
} else if((h->format & 0xF0) == 0x00) {
// First byte should be start byte
if(h->flag != MBUS_START)
return HDLC_BOUNDRY_FLAG_MISSING;
} else if(h->flag == MBUS_START) {
// TODO: Check that the two next bytes are identical
// Ignore: Flag + Control field + Address
// Ignore: Control field + Address + Flag
ptr += 3;
headersize += 3;
footersize++;
}
// Extract LLC
@@ -113,8 +110,6 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
if(length < headersize + 18)
return HDLC_FRAME_INCOMPLETE;
uint8_t preheadersize = headersize;
ptr++;
// Encrypted APDU
// http://www.weigu.lu/tutorials/sensors2bus/04_encryption/index.html
@@ -133,6 +128,7 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
len = *ptr;
// 1-byte payload length
ptr++;
headersize += 2;
} else if(((*ptr) & 0xFF) == 0x82) {
HDLCHeader* h = (HDLCHeader*) ptr;
@@ -142,10 +138,11 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
ptr += 3;
headersize += 3;
}
if(len + preheadersize > length)
len = ceil(len/16.0) * 16;
if(len + headersize + footersize > length)
return HDLC_FRAME_INCOMPLETE;
//Serial.printf("\nL: %d : %d, %d : %d\n", length, len, preheadersize, headersize);
//Serial.printf("\nL: %d : %d, %d : %d\n", length, len, headersize, footersize);
// TODO: FCS
@@ -181,25 +178,27 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
br_gcm_aad_inject(&gcmCtx, config->additional_authenticated_data, aadlen);
}
br_gcm_flip(&gcmCtx);
br_gcm_run(&gcmCtx, 0, (void*) (ptr), len - footersize - 2);
br_gcm_run(&gcmCtx, 0, (void*) (ptr), len - authkeylen - 5); // 5 == security tag and frame counter
if(authkeylen > 0 && br_gcm_check_tag_trunc(&gcmCtx, config->authentication_tag, authkeylen) != 1) {
return -91;
return HDLC_ENCRYPTION_AUTH_FAILED;
}
#elif defined(ESP32)
uint8_t cipher_text[len - authkeylen - footersize - 2];
memcpy(cipher_text, ptr, len - authkeylen - footersize - 2);
uint8_t cipher_text[len - authkeylen - 5];
memcpy(cipher_text, ptr, len - authkeylen - 5);
mbedtls_gcm_context m_ctx;
mbedtls_gcm_init(&m_ctx);
int success = mbedtls_gcm_setkey(&m_ctx, MBEDTLS_CIPHER_ID_AES, config->encryption_key, 128);
if (0 != success ) {
return -92;
if (0 != success) {
return HDLC_ENCRYPTION_KEY_FAILED;
}
success = mbedtls_gcm_auth_decrypt(&m_ctx, sizeof(cipher_text), config->initialization_vector, sizeof(config->initialization_vector),
config->additional_authenticated_data, aadlen, config->authentication_tag, authkeylen,
cipher_text, (unsigned char*)(ptr));
if (0 != success) {
return -91;
if (authkeylen > 0 && success == MBEDTLS_ERR_GCM_AUTH_FAILED) {
return HDLC_ENCRYPTION_AUTH_FAILED;
} else if(success == MBEDTLS_ERR_GCM_BAD_INPUT) {
return HDLC_ENCRYPTION_DECRYPT_FAILED;
}
mbedtls_gcm_free(&m_ctx);
#endif
@@ -229,5 +228,5 @@ int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTim
}
// Unknown payload
return 0;
return HDLC_UNKNOWN_DATA;
}

View File

@@ -9,7 +9,11 @@
#define HDLC_FCS_ERROR -2
#define HDLC_HCS_ERROR -3
#define HDLC_FRAME_INCOMPLETE -4
#define HDLC_UNKNOWN_DATA -9
#define HDLC_ENCRYPTION_CONFIG_MISSING -90
#define HDLC_ENCRYPTION_AUTH_FAILED -91
#define HDLC_ENCRYPTION_KEY_FAILED -92
#define HDLC_ENCRYPTION_DECRYPT_FAILED -93
#define MBUS_START 0x68
#define MBUS_END 0x16