Index: leahi_dialin/common/td_defs.py =================================================================== diff -u -r272d33ed055f9d107788a17a76f2b9bc5bb510aa -r99005b6f96d49ad13fa01a44889579c386dc803a --- leahi_dialin/common/td_defs.py (.../td_defs.py) (revision 272d33ed055f9d107788a17a76f2b9bc5bb510aa) +++ leahi_dialin/common/td_defs.py (.../td_defs.py) (revision 99005b6f96d49ad13fa01a44889579c386dc803a) @@ -1437,23 +1437,11 @@ @unique class TDUsageInformationRecordFields(RecordsBaseEnum): - RO_WATER_GEN_TOTAL_L = (0, DataTypes.F32) # Total RO water generated in liters. (Cannot be reset) - RO_WATER_GEN_SINCE_LAST_SERVICE_L = (1, DataTypes.F32) # RO water generated since last treatment in liters - LAST_BASIC_FLUSH_COMPLETE_DATE_EPOCH = (2, DataTypes.U32) # Last basic flush complete date in epoch. - LAST_HEAT_DISINFECT_COMPLETE_DATE_EPOCH = (3, DataTypes.U32) # Last heat disinfect complete date in epoch. - LAST_HEAT_ACTIVE_COOL_COMPLETE_DATE_EPOCH = (4, DataTypes.U32) # Last heat disinfect active cool complete date in epoch. - LAST_FILTER_FLUSH_COMPLETE_DATE_EPOCH = (5, DataTypes.U32) # Last filter flush complete date in epoch. - LAST_RESET_TIME_EPOCH = (6, DataTypes.U32) # Last time the record was reset in epoch. - NUM_OF_USAGE_INFO_RECORD_FIELDS = (7, DataTypes.NONE) # Number of Usage Information Record Fields + LAST_RESET_TIME_EPOCH = (0, DataTypes.U32) # Last time the record was reset in epoch. + NUM_OF_USAGE_INFO_RECORD_FIELDS = (1, DataTypes.NONE) # Number of Usage Information Record Fields TDUsageInformationRecordFields._str_list = { # Official Name : Accepted strings - 'RO_WATER_GEN_TOTAL_L': [], - 'RO_WATER_GEN_SINCE_LAST_SERVICE_L': [], - 'LAST_BASIC_FLUSH_COMPLETE_DATE_EPOCH': [], - 'LAST_HEAT_DISINFECT_COMPLETE_DATE_EPOCH': [], - 'LAST_HEAT_ACTIVE_COOL_COMPLETE_DATE_EPOCH': [], - 'LAST_FILTER_FLUSH_COMPLETE_DATE_EPOCH': [], 'LAST_RESET_TIME_EPOCH': [], 'NUM_OF_USAGE_INFO_RECORD_FIELDS': [], } Index: leahi_dialin/td/modules/records.py =================================================================== diff -u -rbe799e12803dba3054ff893b68f8b79a9dde440b -r99005b6f96d49ad13fa01a44889579c386dc803a --- leahi_dialin/td/modules/records.py (.../records.py) (revision be799e12803dba3054ff893b68f8b79a9dde440b) +++ leahi_dialin/td/modules/records.py (.../records.py) (revision 99005b6f96d49ad13fa01a44889579c386dc803a) @@ -18,10 +18,10 @@ from logging import Logger # Project imports -from leahi_dialin.dd.modules.records_get_responses import DDRecordsGetHandlers -from leahi_dialin.dd.modules.records_get_requests import DDRecordsGetRequests -from leahi_dialin.dd.modules.records_set_responses import DDRecordsSetHandlers -from leahi_dialin.dd.modules.records_set_requests import DDRecordsSetRequests +from leahi_dialin.dd.modules.records_get_responses import TDRecordsGetHandlers +from leahi_dialin.dd.modules.records_get_requests import TDRecordsGetRequests +from leahi_dialin.dd.modules.records_set_responses import TDRecordsSetHandlers +from leahi_dialin.dd.modules.records_set_requests import TDRecordsSetRequests from leahi_dialin.common import td_enum_repository from leahi_dialin.common.msg_defs import RequestRejectReasons from leahi_dialin.common.msg_ids import MsgIds @@ -30,7 +30,7 @@ from leahi_dialin.utils.conversions import integer_to_bytearray -class TDRecords(DDRecordsGetHandlers, DDRecordsGetRequests, DDRecordsSetHandlers, DDRecordsSetRequests): +class TDRecords(TDRecordsGetHandlers, TDRecordsGetRequests, TDRecordsSetHandlers, TDRecordsSetRequests): """ TD interface containing records related commands. """ Index: leahi_dialin/td/modules/records_get_requests.py =================================================================== diff -u --- leahi_dialin/td/modules/records_get_requests.py (revision 0) +++ leahi_dialin/td/modules/records_get_requests.py (revision 99005b6f96d49ad13fa01a44889579c386dc803a) @@ -0,0 +1,76 @@ +########################################################################### +# +# Copyright (c) 2020-2024 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file records_get_requests.py +# +# @author (last) Zoltan Miskolci +# @date (last) 11-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 11-Aug-2026 +# +############################################################################ + +# Project imports +from leahi_dialin.common.msg_ids import MsgIds +from leahi_dialin.common.override_templates import cmd_generic_override +from leahi_dialin.protocols.CAN import CanChannels +from leahi_dialin.utils.abstract_classes import AbstractSubSystem + + +class TDRecordsGetRequests(AbstractSubSystem): + """ + Part of the TD Records + """ + def __init__(self, *args, **kwargs): + """ + The sub record class to handle all the get handlers. + """ + # Passing the arguments over to the next class too + super().__init__(*args, **kwargs) + + + # ================================================= Request Records Methods ================================================= + def cmd_request_service_records(self) -> int: + """ + Constructs and sends a request for TD Service Records. + Constraints: + Must be logged into TD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + # msg_id = MsgIds.MSG_ID_UI_TD_NVM_GET_SERVICE_RECORD_REQUEST, + msg_id = MsgIds.MSG_ID_UNUSED, + entity_name = f'TD Service Record request', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_request_usage_information_records(self) -> int: + """ + Constructs and sends a request for TD Usage Information Records. + Constraints: + Must be logged into TD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + return cmd_generic_override( + payload = None, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + # msg_id = MsgIds.MSG_ID_UI_TD_NVM_GET_USAGE_INFO_RECORD_REQUEST, + msg_id = MsgIds.MSG_ID_UNUSED, + entity_name = f'TD Usage Information Record request', + override_text = '', + logger = self.logger, + can_interface = self.can_interface) Index: leahi_dialin/td/modules/records_get_responses.py =================================================================== diff -u --- leahi_dialin/td/modules/records_get_responses.py (revision 0) +++ leahi_dialin/td/modules/records_get_responses.py (revision 99005b6f96d49ad13fa01a44889579c386dc803a) @@ -0,0 +1,100 @@ +########################################################################### +# +# Copyright (c) 2020-2024 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file records_get_responses.py +# +# @author (last) Zoltan Miskolci +# @date (last) 11-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 11-Aug-2026 +# +############################################################################ + +# Project imports +from leahi_dialin.common import td_enum_repository +from leahi_dialin.common.generic_defs import DataTypes +from leahi_dialin.common.msg_defs import RequestRejectReasons +from leahi_dialin.common.msg_ids import MsgIds +from leahi_dialin.protocols.CAN import CanChannels +from leahi_dialin.utils.abstract_classes import AbstractSubSystem, LocalVars +from leahi_dialin.utils.base import publish + + +class TDRecordsGetHandlers(AbstractSubSystem): + """ + Part of the TD Records + """ + + def __init__(self, *args, **kwargs): + """ + The sub record class to handle all the get handlers. + """ + if self.can_interface is not None: + # Data Request Response messages + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.td_sync_broadcast_ch_id, + # message_id = MsgIds.MSG_ID_TD_UI_NVM_GET_SERVICE_RECORD_RESPONSE.value, + message_id = MsgIds.MSG_ID_UNUSED.value, + function = self._handler_service_record_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.td_sync_broadcast_ch_id, + # message_id = MsgIds.MSG_ID_TD_UI_NVM_GET_USAGE_INFO_RECORD_RESPONSE.value, + message_id = MsgIds.MSG_ID_UNUSED.value, + function = self._handler_usage_info_record_sync) + + # Passing the arguments over to the next class too + super().__init__(*args, **kwargs) + + + +# ================================================= CAN Message Handler Methods ================================================= + # @publish([MsgIds.MSG_ID_TD_UI_NVM_GET_SERVICE_RECORD_RESPONSE.name.lower(), "get_service_rec_ack", "get_service_rec_rr", "service_records", "get_service_rec_timestamp"]) + @publish([MsgIds.MSG_ID_UNUSED.name.lower(), "get_service_rec_ack", "get_service_rec_rr", "service_records", "get_service_rec_timestamp"]) + def _handler_service_record_sync(self, message, timestamp = 0.0): + """ + Handles published TD Service Record data messages. + TD Service Records are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).get_service_rec_ack, DataTypes.BOOL)) + msg_list.append((type(self).get_service_rec_rr, DataTypes.U32)) + for member in td_enum_repository.TDServiceRecordFields: + if member is not td_enum_repository.TDServiceRecordFields.NUM_OF_SERVICE_RECORD_FIELDS: + msg_list.append((self.service_records, member.name, member.datatype())) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + if isinstance(self.get_service_rec_rr, int): + self.get_service_rec_rr = RequestRejectReasons(self.get_service_rec_rr) + self.get_service_rec_timestamp = timestamp + + + # @publish([MsgIds.MSG_ID_TD_UI_NVM_GET_USAGE_INFO_RECORD_RESPONSE.name.lower(), "get_usage_info_rec_ack", "get_usage_info_rec_rr", "usage_info_records", "get_usage_info_rec_timestamp"]) + @publish([MsgIds.MSG_ID_UNUSED.name.lower(), "get_usage_info_rec_ack", "get_usage_info_rec_rr", "usage_info_records", "get_usage_info_rec_timestamp"]) + def _handler_usage_info_record_sync(self, message, timestamp = 0.0): + """ + Handles published TD Usage Information Record data messages. + TD Usage Information Records are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).get_usage_info_rec_ack, DataTypes.BOOL)) + msg_list.append((type(self).get_usage_info_rec_rr, DataTypes.U32)) + for member in td_enum_repository.TDUsageInformationRecordFields: + if member is not td_enum_repository.TDUsageInformationRecordFields.NUM_OF_USAGE_INFO_RECORD_FIELDS: + msg_list.append((self.usage_info_records, member.name, member.datatype())) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + if isinstance(self.get_usage_info_rec_rr, int): + self.get_usage_info_rec_rr = RequestRejectReasons(self.get_usage_info_rec_rr) + self.get_usage_info_rec_timestamp = timestamp Index: leahi_dialin/td/modules/records_set_requests.py =================================================================== diff -u --- leahi_dialin/td/modules/records_set_requests.py (revision 0) +++ leahi_dialin/td/modules/records_set_requests.py (revision 99005b6f96d49ad13fa01a44889579c386dc803a) @@ -0,0 +1,111 @@ +########################################################################### +# +# Copyright (c) 2020-2024 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file records_set_requests.py +# +# @author (last) Zoltan Miskolci +# @date (last) 11-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 11-Aug-2026 +# +############################################################################ + +# Project imports +from leahi_dialin.common.msg_ids import MsgIds +from leahi_dialin.common.override_templates import cmd_generic_override +from leahi_dialin.protocols.CAN import CanChannels +from leahi_dialin.utils.abstract_classes import AbstractSubSystem +from leahi_dialin.utils.conversions import integer_to_bytearray + + +class TDRecordsSetRequests(AbstractSubSystem): + """ + Part of the TD Records + """ + + def __init__(self, *args, **kwargs): + """ + The sub record class to handle all the set requests. + """ + # Passing the arguments over to the next class too + super().__init__(*args, **kwargs) + + + +# ================================================= Set Records Main Methods ================================================= + def cmd_set_service_records(self, + water_recovery: int=0, + primary_filter_replacement_date: int=0, + secondary_filter_replacement_date: int=0, + ro_membrane_replacement_date: int=0, + service_loc: int=0, + last_service_date: int=0, + service_interval_sec: int=0, + last_reset_time: int=0) -> int: + """ + Constructs and sends a command for setting the Service Records. + Constraints: + Must be logged into TD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = integer_to_bytearray(water_recovery) + payload += integer_to_bytearray(primary_filter_replacement_date) + payload += integer_to_bytearray(secondary_filter_replacement_date) + payload += integer_to_bytearray(ro_membrane_replacement_date) + payload += integer_to_bytearray(service_loc) + payload += integer_to_bytearray(last_service_date) + payload += integer_to_bytearray(service_interval_sec) + payload += integer_to_bytearray(last_reset_time) + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + # msg_id = MsgIds.MSG_ID_UI_TD_NVM_SET_SERVICE_RECORD_REQUEST, + msg_id = MsgIds.MSG_ID_UNUSED, + entity_name = f'New TD Service Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) + + + def cmd_set_usage_info_records(self, + primary_filter_treatment_count: int=0, + primary_filter_disinfection_count: int=0, + secondary_filter_treatment_count: int=0, + secondary_filter_disinfection_count: int=0, + ro_membrane_treatment_count: int=0, + ro_membrane_disinfection_count: int=0, + last_reset_time: int=0) -> int: + """ + Constructs and sends a command for setting the Usage Information Records. + Constraints: + Must be logged into TD. + Must be in Service mode. + + @return: 1 if successful, zero otherwise + """ + payload = integer_to_bytearray(primary_filter_treatment_count) + payload += integer_to_bytearray(primary_filter_disinfection_count) + payload += integer_to_bytearray(secondary_filter_treatment_count) + payload += integer_to_bytearray(secondary_filter_disinfection_count) + payload += integer_to_bytearray(ro_membrane_treatment_count) + payload += integer_to_bytearray(ro_membrane_disinfection_count) + payload += integer_to_bytearray(last_reset_time) + + return cmd_generic_override( + payload = payload, + reset = None, + channel_id = CanChannels.dialin_to_dd_ch_id, + # msg_id = MsgIds.MSG_ID_UI_TD_NVM_SET_USAGE_INFO_RECORD_REQUEST, + msg_id = MsgIds.MSG_ID_UNUSED, + entity_name = f'New TD Usage Information Record', + override_text = 'being set', + logger = self.logger, + can_interface = self.can_interface) Index: leahi_dialin/td/modules/records_set_responses.py =================================================================== diff -u --- leahi_dialin/td/modules/records_set_responses.py (revision 0) +++ leahi_dialin/td/modules/records_set_responses.py (revision 99005b6f96d49ad13fa01a44889579c386dc803a) @@ -0,0 +1,96 @@ +########################################################################### +# +# Copyright (c) 2020-2024 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file records_set_responses.py +# +# @author (last) Zoltan Miskolci +# @date (last) 11-Aug-2026 +# @author (original) Zoltan Miskolci +# @date (original) 11-Aug-2026 +# +############################################################################ + +# Project imports +from leahi_dialin.common import td_enum_repository +from leahi_dialin.common.generic_defs import DataTypes +from leahi_dialin.common.msg_defs import RequestRejectReasons +from leahi_dialin.common.msg_ids import MsgIds +from leahi_dialin.protocols.CAN import CanChannels +from leahi_dialin.utils.abstract_classes import AbstractSubSystem +from leahi_dialin.utils.base import publish + + +class TDRecordsSetHandlers(AbstractSubSystem): + """ + Part of the TD Records + """ + + def __init__(self, *args, **kwargs): + """ + The sub record class to handle all the set handlers. + """ + if self.can_interface is not None: + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.td_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_UNUSED.value, + # message_id = MsgIds.MSG_ID_TD_UI_NVM_SET_SERVICE_RECORD_RESPONSE.value, + function = self._handler_set_service_rec_rr_sync) + self.can_interface.register_receiving_publication_function(channel_id = CanChannels.td_sync_broadcast_ch_id, + message_id = MsgIds.MSG_ID_UNUSED.value, + # message_id = MsgIds.MSG_ID_TD_UI_NVM_SET_USAGE_INFO_RECORD_RESPONSE.value, + function = self._handler_set_usage_info_rec_rr_sync) + + # Passing the arguments over to the next class too + super().__init__(*args, **kwargs) + + +# ================================================= Reject Reason Message Handler Methods ================================================= + # @publish([MsgIds.MSG_ID_TD_UI_NVM_SET_SERVICE_RECORD_RESPONSE.name.lower(), "set_service_rec_ack", "set_service_rec_rr", "set_service_rec_rr_timestamp"]) + @publish([MsgIds.MSG_ID_UNUSED.name.lower(), "set_service_rec_ack", "set_service_rec_rr", "set_service_rec_rr_timestamp"]) + def _handler_set_service_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published TD Set TD Service Records Reject Reason data messages. + TD Set TD Service Records Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).set_service_rec_ack, DataTypes.BOOL)) + for ser_rec in td_enum_repository.TDServiceRecordFields: + msg_list.append((self.set_service_rec_rr, ser_rec, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + for ser_rec in self.set_service_rec_rr: + if isinstance(self.set_service_rec_rr[ser_rec], int): + self.set_service_rec_rr[ser_rec] = RequestRejectReasons(self.set_service_rec_rr[ser_rec]) + self.set_service_rec_rr_timestamp = timestamp + + + # @publish([MsgIds.MSG_ID_TD_UI_NVM_SET_USAGE_INFO_RECORD_RESPONSE.name.lower(), "set_usage_info_rec_ack", "set_usage_info_rec_rr", "set_usage_info_rec_rr_timestamp"]) + @publish([MsgIds.MSG_ID_UNUSED.name.lower(), "set_usage_info_rec_ack", "set_usage_info_rec_rr", "set_usage_info_rec_rr_timestamp"]) + def _handler_set_usage_info_rec_rr_sync(self, message, timestamp = 0.0): + """ + Handles published TD Set TD Usage Information Records Reject Reason data messages. + TD Set TD Usage Information Records Reject Reason are captured for reference. + + @param message: published data message + @return: none + """ + msg_list = [] + msg_list.append((type(self).set_usage_info_rec_ack, DataTypes.BOOL)) + for info_rec in td_enum_repository.TDUsageInformationRecordFields: + msg_list.append((self.set_usage_info_rec_rr, info_rec, DataTypes.U32)) + + self.process_into_vars(decoder_list = msg_list, message = message) + + # Convert to enum + for info_rec in self.set_usage_info_rec_rr: + if isinstance(self.set_usage_info_rec_rr[info_rec], int): + self.set_usage_info_rec_rr[info_rec] = RequestRejectReasons(self.set_usage_info_rec_rr[info_rec]) + self.set_usage_info_rec_rr_timestamp = timestamp