mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-13 23:45:25 +00:00
Fixes after testing
This commit is contained in:
parent
580085f717
commit
5c38d1cf3e
@ -301,7 +301,6 @@ bool longPressActive = false;
|
||||
bool wifiConnected = false;
|
||||
|
||||
unsigned long lastTemperatureRead = 0;
|
||||
unsigned long lastSuccessfulRead = 0;
|
||||
unsigned long lastErrorBlink = 0;
|
||||
int lastError = 0;
|
||||
|
||||
@ -558,7 +557,7 @@ void errorBlink() {
|
||||
for(;lastError < 3;lastError++) {
|
||||
switch(lastError) {
|
||||
case 0:
|
||||
if(lastErrorBlink - lastSuccessfulRead > 30000) {
|
||||
if(lastErrorBlink - meterState.getLastUpdateMillis() > 30000) {
|
||||
hw.ledBlink(LED_RED, 1); // If no message received from AMS in 30 sec, blink once
|
||||
return;
|
||||
}
|
||||
@ -645,11 +644,12 @@ void readHanPort() {
|
||||
hanSerial->readBytes(buf, BUF_SIZE);
|
||||
return;
|
||||
}
|
||||
CosemDateTime timestamp;
|
||||
AmsData data;
|
||||
if(currentMeterType == 1) {
|
||||
size_t len = hanSerial->readBytes(buf, BUF_SIZE); // TODO: read one byte at the time. This blocks up the GUI
|
||||
if(len > 0) {
|
||||
int pos = HDLC_validate((uint8_t *) buf, len, hc);
|
||||
int pos = HDLC_validate((uint8_t *) buf, len, hc, ×tamp);
|
||||
if(pos == HDLC_ENCRYPTION_CONFIG_MISSING) {
|
||||
hc = new HDLCConfig();
|
||||
memcpy(hc->encryption_key, meterConfig.encryptionKey, 16);
|
||||
@ -671,7 +671,7 @@ void readHanPort() {
|
||||
}
|
||||
if(pos >= 0) {
|
||||
debugI("Valid HDLC, start at %d", pos);
|
||||
data = IEC6205675(((char *) (buf)) + pos, meterState.getMeterType());
|
||||
data = IEC6205675(((char *) (buf)) + pos, meterState.getMeterType(), timestamp);
|
||||
} else {
|
||||
debugW("Invalid HDLC, returned with %d", pos);
|
||||
currentMeterType = 0;
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
#include "IEC6205675.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
IEC6205675::IEC6205675(const char* d, uint8_t useMeterType) {
|
||||
IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, CosemDateTime packageTimestamp) {
|
||||
uint32_t u32;
|
||||
int32_t s32;
|
||||
char str[64];
|
||||
|
||||
this->packageTimestamp = getTimestamp(packageTimestamp);
|
||||
|
||||
u32 = getUnsignedNumber(AMS_OBIS_ACTIVE_IMPORT, sizeof(AMS_OBIS_ACTIVE_IMPORT), ((char *) (d)));
|
||||
if(u32 == 0xFFFFFFFF) {
|
||||
CosemData* data = getCosemDataAt(1, ((char *) (d)));
|
||||
@ -94,20 +96,7 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType) {
|
||||
case CosemTypeOctetString: {
|
||||
if(data->oct.length == 0x0C) {
|
||||
AmsOctetTimestamp* ts = (AmsOctetTimestamp*) data;
|
||||
tmElements_t tm;
|
||||
tm.Year = ntohs(ts->year) - 1970;
|
||||
tm.Month = ts->month;
|
||||
tm.Day = ts->dayOfMonth;
|
||||
tm.Hour = ts->hour;
|
||||
tm.Minute = ts->minute;
|
||||
tm.Second = ts->second;
|
||||
|
||||
time_t time = makeTime(tm);
|
||||
int16_t deviation = ntohs(ts->deviation);
|
||||
if(deviation >= -720 && deviation <= 720) {
|
||||
time -= deviation * 60;
|
||||
}
|
||||
meterTimestamp = time;
|
||||
meterTimestamp = getTimestamp(ts->dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -419,23 +408,28 @@ time_t IEC6205675::getTimestamp(uint8_t* obis, int matchlength, const char* ptr)
|
||||
case CosemTypeOctetString: {
|
||||
if(item->oct.length == 0x0C) {
|
||||
AmsOctetTimestamp* ts = (AmsOctetTimestamp*) item;
|
||||
tmElements_t tm;
|
||||
tm.Year = ntohs(ts->year) - 1970;
|
||||
tm.Month = ts->month;
|
||||
tm.Day = ts->dayOfMonth;
|
||||
tm.Hour = ts->hour;
|
||||
tm.Minute = ts->minute;
|
||||
tm.Second = ts->second;
|
||||
|
||||
time_t time = makeTime(tm);
|
||||
int16_t deviation = ntohs(ts->deviation);
|
||||
if(deviation >= -720 && deviation <= 720) {
|
||||
time -= deviation * 60;
|
||||
}
|
||||
return time;
|
||||
//Serial.printf("\nYear: %d, Month: %d, Day: %d, Hour: %d, Minutes %d, Second: %d, Deviation: %d\n", ntohs(ts->dt.year), ts->dt.month, ts->dt.dayOfMonth, ts->dt.hour, ts->dt.minute, ts->dt.second, ntohs(ts->dt.deviation));
|
||||
return getTimestamp(ts->dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t IEC6205675::getTimestamp(CosemDateTime timestamp) {
|
||||
tmElements_t tm;
|
||||
tm.Year = ntohs(timestamp.year) - 1970;
|
||||
tm.Month = timestamp.month;
|
||||
tm.Day = timestamp.dayOfMonth;
|
||||
tm.Hour = timestamp.hour;
|
||||
tm.Minute = timestamp.minute;
|
||||
tm.Second = timestamp.second;
|
||||
|
||||
time_t time = makeTime(tm);
|
||||
int16_t deviation = ntohs(timestamp.deviation);
|
||||
if(deviation >= -720 && deviation <= 720) {
|
||||
time -= deviation * 60;
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
@ -5,21 +5,13 @@
|
||||
#include "ams/hdlc.h"
|
||||
|
||||
struct AmsOctetTimestamp {
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t dayOfMonth;
|
||||
uint8_t dayOfWeek;
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
uint8_t hundredths;
|
||||
int16_t deviation;
|
||||
uint8_t status;
|
||||
uint8_t type;
|
||||
CosemDateTime dt;
|
||||
} __attribute__((packed));
|
||||
|
||||
class IEC6205675 : public AmsData {
|
||||
public:
|
||||
IEC6205675(const char* payload, uint8_t useMeterType);
|
||||
IEC6205675(const char* payload, uint8_t useMeterType, CosemDateTime packageTimestamp);
|
||||
|
||||
private:
|
||||
CosemData* getCosemDataAt(uint8_t index, const char* ptr);
|
||||
@ -28,6 +20,7 @@ private:
|
||||
uint32_t getSignedNumber(uint8_t* obis, int matchlength, const char* ptr);
|
||||
uint32_t getUnsignedNumber(uint8_t* obis, int matchlength, const char* ptr);
|
||||
time_t getTimestamp(uint8_t* obis, int matchlength, const char* ptr);
|
||||
time_t getTimestamp(CosemDateTime timestamp);
|
||||
|
||||
uint8_t AMS_OBIS_VERSION[6] = { 1, 1, 0, 2, 129, 255 };
|
||||
uint8_t AMS_OBIS_METER_MODEL[4] = { 96, 1, 1, 255 };
|
||||
|
||||
@ -15,7 +15,7 @@ void mbus_hexdump(const uint8_t* buf, int len) {
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
int HDLC_validate(const uint8_t* d, int len, HDLCConfig* config) {
|
||||
int HDLC_validate(const uint8_t* d, int len, HDLCConfig* config, CosemDateTime* timestamp) {
|
||||
//mbus_hexdump(d, len);
|
||||
|
||||
HDLCHeader* h = (HDLCHeader*) d;
|
||||
@ -74,13 +74,18 @@ int HDLC_validate(const uint8_t* d, int len, HDLCConfig* config) {
|
||||
ptr += sizeof *adpu;
|
||||
|
||||
// ADPU timestamp
|
||||
// TODO : extract and return
|
||||
CosemData* dateTime = (CosemData*) ptr;
|
||||
if(dateTime->base.type == CosemTypeOctetString) {
|
||||
if(dateTime->base.length == 0x0C) {
|
||||
memcpy(timestamp, ptr+1, dateTime->base.length);
|
||||
}
|
||||
ptr += 2 + dateTime->base.length;
|
||||
} else if(dateTime->base.type == CosemTypeNull) {
|
||||
ptr++;
|
||||
} else if(dateTime->base.type == CosemTypeDateTime) {
|
||||
memcpy(timestamp, ptr, dateTime->base.length);
|
||||
} else if(dateTime->base.type == 0x0C) { // Kamstrup bug...
|
||||
memcpy(timestamp, ptr, dateTime->base.length);
|
||||
ptr += 13;
|
||||
} else {
|
||||
return -99;
|
||||
|
||||
@ -51,7 +51,8 @@ enum CosemType {
|
||||
CosemTypeString = 0x0A,
|
||||
CosemTypeDLongUnsigned = 0x06,
|
||||
CosemTypeLongSigned = 0x10,
|
||||
CosemTypeLongUnsigned = 0x12
|
||||
CosemTypeLongUnsigned = 0x12,
|
||||
CosemTypeDateTime = 0x19
|
||||
};
|
||||
|
||||
struct CosemBasic {
|
||||
@ -80,6 +81,20 @@ struct CosemLongSigned {
|
||||
int16_t data;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct CosemDateTime {
|
||||
uint8_t type;
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t dayOfMonth;
|
||||
uint8_t dayOfWeek;
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
uint8_t hundredths;
|
||||
int16_t deviation;
|
||||
uint8_t status;
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef union {
|
||||
struct CosemBasic base;
|
||||
struct CosemString str;
|
||||
@ -87,9 +102,10 @@ typedef union {
|
||||
struct CosemLongUnsigned lu;
|
||||
struct CosemDLongUnsigned dlu;
|
||||
struct CosemLongSigned ls;
|
||||
struct CosemDateTime dt;
|
||||
} CosemData;
|
||||
|
||||
void mbus_hexdump(const uint8_t* buf, int len);
|
||||
int HDLC_validate(const uint8_t* d, int len, HDLCConfig* config);
|
||||
int HDLC_validate(const uint8_t* d, int len, HDLCConfig* config, CosemDateTime* timestamp);
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user