From 5e0c7a876221cbd1c9e7ad220eaa2d4e7607f2b3 Mon Sep 17 00:00:00 2001 From: Mario Coray Date: Fri, 5 Apr 2024 16:36:37 +0200 Subject: [PATCH 1/3] assume local time when extracting timestamps from dlms messages without timezone info --- smartmeter_datacollector/smartmeter/cosem.py | 3 ++- .../smartmeter/hdlc_dlms_parser.py | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/smartmeter_datacollector/smartmeter/cosem.py b/smartmeter_datacollector/smartmeter/cosem.py index 4500963..28d0ac1 100644 --- a/smartmeter_datacollector/smartmeter/cosem.py +++ b/smartmeter_datacollector/smartmeter/cosem.py @@ -146,7 +146,8 @@ def retrieve_time_from_dlms_registers(self, dlms_objects: Dict[OBISCode, Any]) - if clock_obj and isinstance(clock_obj, GXDLMSClock): timestamp = self._extract_datetime(clock_obj) if timestamp: - return timestamp + # assume local time if tzinfo is None + return timestamp.astimezone(timestamp.tzinfo) return None def get_register(self, obis: OBISCode) -> Optional[RegisterCosem]: diff --git a/smartmeter_datacollector/smartmeter/hdlc_dlms_parser.py b/smartmeter_datacollector/smartmeter/hdlc_dlms_parser.py index cd8d22e..a2db3e3 100644 --- a/smartmeter_datacollector/smartmeter/hdlc_dlms_parser.py +++ b/smartmeter_datacollector/smartmeter/hdlc_dlms_parser.py @@ -86,8 +86,10 @@ def extract_data_from_hdlc_frames(self) -> bool: def extract_message_time(self) -> Optional[datetime]: if not isinstance(self._dlms_data.time, GXDateTime): return None - if isinstance(self._dlms_data.time.value, datetime): - return self._dlms_data.time.value + dt = self._dlms_data.time.value + if isinstance(dt, datetime): + # assume local time if tzinfo is None + return dt.astimezone(dt.tzinfo) return None def parse_to_dlms_objects(self) -> List[GXDLMSObject]: @@ -133,9 +135,8 @@ def convert_dlms_bundle_to_reader_data(self, dlms_objects: List[GXDLMSObject], self._use_system_time = True timestamp = datetime.now(timezone.utc) - if not timestamp.tzinfo: - # if timezone info not set, assume UTC - timestamp = timestamp.replace(tzinfo=timezone.utc) + # convert to UTC format + timestamp = timestamp.astimezone(timezone.utc) # Extract register data data_points: List[MeterDataPoint] = [] From 9b7058c1a8b5746e3fd4a1936fac45420e341176 Mon Sep 17 00:00:00 2001 From: Mario Coray Date: Fri, 5 Apr 2024 16:38:45 +0200 Subject: [PATCH 2/3] test: compare extracted time in local time format to make tests succeed in each timezone --- tests/test_hdlc_dlms_parser.py | 3 ++- tests/test_iskraam550.py | 2 +- tests/test_lge450.py | 2 +- tests/test_lge570.py | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_hdlc_dlms_parser.py b/tests/test_hdlc_dlms_parser.py index f4908e7..76f843a 100644 --- a/tests/test_hdlc_dlms_parser.py +++ b/tests/test_hdlc_dlms_parser.py @@ -62,7 +62,8 @@ def test_parse_dlms_to_meter_data(self, unencrypted_valid_data_lg: List[bytes], assert any(data.type == MeterDataPointTypes.ACTIVE_POWER_N.value for data in meter_data) assert all(isinstance(data.value, float) for data in meter_data) assert all(data.source == "LGZ1030655933512" for data in meter_data) - assert all(data.timestamp.strftime(r"%m/%d/%y %H:%M:%S") == "07/06/21 14:58:18" for data in meter_data) + assert all(data.timestamp.astimezone().strftime(r"%m/%d/%y %H:%M:%S") + == "07/06/21 14:58:18" for data in meter_data) def test_parse_dlms_to_meter_data2(self, unencrypted_valid_data_lg2: List[bytes], cosem_config_lg: Cosem): parser = prepare_parser(unencrypted_valid_data_lg2, cosem_config_lg) diff --git a/tests/test_iskraam550.py b/tests/test_iskraam550.py index f58f1d1..f156d85 100644 --- a/tests/test_iskraam550.py +++ b/tests/test_iskraam550.py @@ -65,4 +65,4 @@ def data_received(): assert any(data.type == MeterDataPointTypes.REACTIVE_ENERGY_Q4.value for data in values) assert any(data.type == MeterDataPointTypes.POWER_FACTOR.value for data in values) assert all(data.source == "ISK1030775213859" for data in values) - assert all(data.timestamp.strftime(r"%m/%d/%y %H:%M:%S") == "08/15/20 06:19:45" for data in values) + assert all(data.timestamp.astimezone().strftime(r"%m/%d/%y %H:%M:%S") == "08/15/20 06:19:45" for data in values) diff --git a/tests/test_lge450.py b/tests/test_lge450.py index 469ee50..48d6ba4 100644 --- a/tests/test_lge450.py +++ b/tests/test_lge450.py @@ -65,7 +65,7 @@ def data_received(): assert any(data.type == MeterDataPointTypes.REACTIVE_ENERGY_Q4.value for data in values) assert any(data.type == MeterDataPointTypes.POWER_FACTOR.value for data in values) assert all(data.source == "LGZ1030655933512" for data in values) - assert all(data.timestamp.strftime(r"%m/%d/%y %H:%M:%S") == "07/06/21 14:58:18" for data in values) + assert all(data.timestamp.astimezone().strftime(r"%m/%d/%y %H:%M:%S") == "07/06/21 14:58:18" for data in values) @pytest.mark.asyncio diff --git a/tests/test_lge570.py b/tests/test_lge570.py index a80ab44..c6a52f7 100644 --- a/tests/test_lge570.py +++ b/tests/test_lge570.py @@ -17,7 +17,6 @@ from .utils import * -@pytest.mark.skipif(sys.version_info < (3, 8), reason="Python3.7 does not support AsyncMock.") @pytest.mark.asyncio async def test_lge570_parse_and_provide_encrypted_data(mocker: MockerFixture, encrypted_valid_data_lge570: List[bytes]): From 87c7b206ba64e0eaa40061e5b19e82be644044da Mon Sep 17 00:00:00 2001 From: Mario Coray Date: Fri, 5 Apr 2024 17:12:39 +0200 Subject: [PATCH 3/3] fix iskra unit test: here message time contains timezone info --- tests/test_iskraam550.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_iskraam550.py b/tests/test_iskraam550.py index f156d85..54a8335 100644 --- a/tests/test_iskraam550.py +++ b/tests/test_iskraam550.py @@ -65,4 +65,5 @@ def data_received(): assert any(data.type == MeterDataPointTypes.REACTIVE_ENERGY_Q4.value for data in values) assert any(data.type == MeterDataPointTypes.POWER_FACTOR.value for data in values) assert all(data.source == "ISK1030775213859" for data in values) - assert all(data.timestamp.astimezone().strftime(r"%m/%d/%y %H:%M:%S") == "08/15/20 06:19:45" for data in values) + # message time comes with timezone info (+02:00) + assert all(data.timestamp.strftime(r"%m/%d/%y %H:%M:%S") == "08/15/20 04:19:45" for data in values)