Fix parsing with invalid timestamps

Sometimes the timestamp in the DSMR message is invalid (when no data
read read from the mbus meter?), and then parsing fails.
Fixing this by handling the exception and returning None for invalid
timestamps. Fixes: #120
This commit is contained in:
Jean-Louis Dupond 2023-01-30 14:09:17 +01:00
parent 026b91cd49
commit edf535f987
2 changed files with 29 additions and 2 deletions

View File

@ -4,14 +4,23 @@ import pytz
def timestamp(value): def timestamp(value):
naive_datetime = datetime.datetime.strptime(value[:-1], '%y%m%d%H%M%S') try:
naive_datetime = datetime.datetime.strptime(value[:-1], '%y%m%d%H%M%S')
except ValueError:
return None
# TODO comment on this exception # Timestamp has the following format:
# YYMMDDhhmmssX
# ASCII presentation of Time stamp with
# Year, Month, Day, Hour, Minute, Second,
# and an indication whether DST is active
# (X=S) or DST is not active (X=W)
if len(value) == 13: if len(value) == 13:
is_dst = value[12] == 'S' # assume format 160322150000W is_dst = value[12] == 'S' # assume format 160322150000W
else: else:
is_dst = False is_dst = False
# TODO : Use system timezone
local_tz = pytz.timezone('Europe/Amsterdam') local_tz = pytz.timezone('Europe/Amsterdam')
localized_datetime = local_tz.localize(naive_datetime, is_dst=is_dst) localized_datetime = local_tz.localize(naive_datetime, is_dst=is_dst)

View File

@ -244,3 +244,21 @@ class TelegramParserV5Test(unittest.TestCase):
corrupted_telegram = TELEGRAM_V5.replace('!6EEE\r\n', '') corrupted_telegram = TELEGRAM_V5.replace('!6EEE\r\n', '')
with self.assertRaises(ParseError): with self.assertRaises(ParseError):
TelegramParser.validate_checksum(corrupted_telegram) TelegramParser.validate_checksum(corrupted_telegram)
def test_gas_timestamp_invalid(self):
# Issue 120
# Sometimes a MBUS device (For ex a Gas Meter) returns an invalid timestamp
# Instead of failing, we should just ignore the timestamp
invalid_date_telegram = TELEGRAM_V5.replace(
'0-1:24.2.1(170102161005W)(00000.107*m3)\r\n',
'0-1:24.2.1(632525252525S)(00000.000)\r\n'
)
invalid_date_telegram = invalid_date_telegram.replace('!6EEE\r\n', '!90C2\r\n')
parser = TelegramParser(telegram_specifications.V5)
result = parser.parse(invalid_date_telegram)
# HOURLY_GAS_METER_READING (0-1:24.2.1)
assert isinstance(result[obis.HOURLY_GAS_METER_READING], MBusObject)
assert result[obis.HOURLY_GAS_METER_READING].unit is None
assert isinstance(result[obis.HOURLY_GAS_METER_READING].value, Decimal)
assert result[obis.HOURLY_GAS_METER_READING].value == Decimal('0.000')