Index: dialin/__init__.py =================================================================== diff -u -r8e32afb5793619bd651b8964609a8e9aee3a5e4c -r24e107b2ac852390b49583c5390860aadde6244a --- dialin/__init__.py (.../__init__.py) (revision 8e32afb5793619bd651b8964609a8e9aee3a5e4c) +++ dialin/__init__.py (.../__init__.py) (revision 24e107b2ac852390b49583c5390860aadde6244a) @@ -1,4 +1,4 @@ -from .version import DEV_VERSION +from .version import * from .hd import * from .dg import * from .ui import * Index: dialin/common/msg_ids.py =================================================================== diff -u -rb84708ae24d96295b2562dfe4e0ce866d6488d65 -r24e107b2ac852390b49583c5390860aadde6244a --- dialin/common/msg_ids.py (.../msg_ids.py) (revision b84708ae24d96295b2562dfe4e0ce866d6488d65) +++ dialin/common/msg_ids.py (.../msg_ids.py) (revision 24e107b2ac852390b49583c5390860aadde6244a) @@ -8,9 +8,9 @@ # @file msg_ids.py # # @author (last) Peter Lucia -# @date (last) 03-May-2021 +# @date (last) 11-May-2021 # @author (original) Peter Lucia -# @date (original) 03-May-2021 +# @date (original) 11-May-2021 # ############################################################################ from enum import unique @@ -228,12 +228,17 @@ MSG_ID_HD_ALARM_AUDIO_CURRENT_LG_OVERRIDE = 0X8055 MSG_ID_HD_ALARM_BACKUP_AUDIO_CURRENT_OVERRIDE = 0X8056 MSG_ID_HD_VALVES_CURRENT_OVERRIDE = 0X8057 - MSD_ID_HD_VALVES_POSITION_COUNT_OVERRIDE = 0x8058 MSG_ID_HD_SYRINGE_PUMP_STATUS_OVERRIDE = 0X8059 MSG_ID_HD_SYRINGE_PUMP_ENCODER_STATUS_OVERRIDE = 0X805A MSG_ID_HD_SYRINGE_PUMP_ADC_DAC_STATUS_OVERRIDE = 0X805B MSG_ID_HD_SYRINGE_PUMP_ADC_READ_COUNTER_OVERRIDE = 0X805C + MSG_ID_HD_BUBBLES_DATA_SEND_INTERVAL_OVERRIDE = 0X805D + MSG_ID_HD_BUBBLES_STATUS_OVERRIDE = 0X805E + MSG_ID_HD_BUBBLES_SELF_TEST_REQUEST = 0X8060 + MSG_ID_DG_VOLTAGES_DATA = 0X86 + MSG_ID_DG_CHEM_DISINFECT_DATA = 0X87 MSG_ID_PRESSURE_OCCLUSION_DATA = 0X9 + MSG_ID_HD_BUBBLES_DATA = 0X93 MSG_ID_CAN_ERROR_COUNT = 0X999 MSG_ID_RTC_EPOCH = 0XA MSG_ID_DG_TESTER_LOGIN_REQUEST = 0XA000 Index: dialin/dg/dialysate_generator.py =================================================================== diff -u -r26de67dd19c2cc0f475d1e77b4a887857841f6c1 -r24e107b2ac852390b49583c5390860aadde6244a --- dialin/dg/dialysate_generator.py (.../dialysate_generator.py) (revision 26de67dd19c2cc0f475d1e77b4a887857841f6c1) +++ dialin/dg/dialysate_generator.py (.../dialysate_generator.py) (revision 24e107b2ac852390b49583c5390860aadde6244a) @@ -39,13 +39,32 @@ from .service_record import DGServiceNVRecord from .scheduled_runs_record import DGScheduledRunsNVRecord from .valves import DGValves +from .voltages import DGVoltages from ..utils.conversions import integer_to_bytearray from ..protocols.CAN import (DenaliCanMessenger, DenaliMessage, DenaliChannels) -from ..utils.base import _AbstractSubSystem, _publish, _LogManager +from ..utils.base import _AbstractSubSystem, _publish, _LogManager, DialinEnum from ..common.msg_defs import MsgIds, MsgFieldPositions from .flush import FlushMode +from .chemical_disinfect import ChemicalDisinfect +from enum import unique +@unique +class DGOperationModes(DialinEnum): + # DG operation modes + DG_OP_MODE_FAULT = 0 + DG_OP_MODE_SERVICE = 1 + DG_OP_MODE_INIT_POST = 2 + DG_OP_MODE_STANDBY = 3 + DG_OP_MODE_STANDBY_SOLO = 4 + DG_OP_MODE_RECIRCULATE = 5 + DG_OP_MODE_FILL = 6 + DG_OP_MODE_DRAIN = 7 + DG_OP_MODE_FLUSH = 8 + DG_OP_MODE_DISINFECT = 9 + DG_OP_MODE_CHEMICAL_DISINFECT = 10 + + class DG(_AbstractSubSystem): """ Dialysate Generator (DG) Dialin object API. It provides the basic interface to communicate with @@ -75,19 +94,6 @@ START_POS_FPGA_LAB = END_POS_FPGA_MINOR END_POS_FPGA_LAB = START_POS_FPGA_LAB + 1 - # DG operation modes - DG_OP_MODE_FAULT = 0 - DG_OP_MODE_SERVICE = 1 - DG_OP_MODE_INIT_POST = 2 - DG_OP_MODE_STANDBY = 3 - DG_OP_MODE_STANDBY_SOLO = 4 - DG_OP_MODE_RECIRCULATE = 5 - DG_OP_MODE_FILL = 6 - DG_OP_MODE_DRAIN = 7 - DG_OP_MODE_FLUSH = 8 - DG_OP_MODE_DISINFECT = 9 - DG_OP_MODE_CHEMICAL_DISINFECT = 10 - # DG sub_modes DG_POST_STATE_START = 0 # Start initialize & POST mode state DG_POST_STATE_FPGA = 1 # FPGA POST test state @@ -136,7 +142,7 @@ self.dg_version = None self.fpga_version = None # create properties - self.dg_operation_mode = self.DG_OP_MODE_INIT_POST + self.dg_operation_mode = 0 #self.DG_OP_MODE_INIT_POST self.dg_operation_sub_mode = 0 # Create command groups @@ -166,7 +172,9 @@ self.service_record = DGServiceNVRecord(self.can_interface, self.logger) self.scheduled_runs_record = DGScheduledRunsNVRecord(self.can_interface, self.logger) self.valves = DGValves(self.can_interface, self.logger) + self.voltages = DGVoltages(self.can_interface, self.logger) self.flush = FlushMode(self.can_interface, self.logger) + self.chemical_disinfect = ChemicalDisinfect(self.can_interface, self.logger) def get_version(self): """ Index: dialin/hd/hemodialysis_device.py =================================================================== diff -u -r2b8e96a45047b35b4d10e26da47a45e8d7a24c67 -r24e107b2ac852390b49583c5390860aadde6244a --- dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision 2b8e96a45047b35b4d10e26da47a45e8d7a24c67) +++ dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision 24e107b2ac852390b49583c5390860aadde6244a) @@ -180,7 +180,6 @@ message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_GET_CALIBRATION_RECORD.value) - self.logger.debug("requesting HD calibration data.") # Send message @@ -285,10 +284,7 @@ Constraints: Must be logged into HD. - \returns response message if received, False if no response received - - @return: 1 if successful, zero otherwise - + @return: None """ message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, Index: dialin/hd/syringe_pump.py =================================================================== diff -u -rbe97d97e1ddd765351cdc51cb75aee9e7e63ba58 -r24e107b2ac852390b49583c5390860aadde6244a --- dialin/hd/syringe_pump.py (.../syringe_pump.py) (revision be97d97e1ddd765351cdc51cb75aee9e7e63ba58) +++ dialin/hd/syringe_pump.py (.../syringe_pump.py) (revision 24e107b2ac852390b49583c5390860aadde6244a) @@ -56,6 +56,10 @@ self.syringe_pump_home_v = 0.0 self.syringe_pump_switch_v = 0.0 self.syringe_pump_force_v = 0.0 + self.syringe_pump_status = 0 + self.syringe_pump_encoder_status = 0 + self.syringe_pump_adc_dac_status = 0 + self.syringe_pump_adc_read_counter = 0 def get_syringe_pump_state(self): """ @@ -152,6 +156,38 @@ """ return self.syringe_pump_safety_volume_ml + def get_syringe_pump_status(self): + """ + Gets the current syringe pump status + + @return: latest published syringe pump status by HD firmware + """ + return self.syringe_pump_status + + def get_syringe_pump_encoder_status(self): + """ + Gets the current syringe pump encoder status + + @return: latest published syringe pump encoder status by HD firmware + """ + return self.syringe_pump_encoder_status + + def get_syringe_pump_adc_dac_status(self): + """ + Gets the current syringe pump ADC & DAC status + + @return: latest published syringe pump ADC & DAC status by HD firmware + """ + return self.syringe_pump_adc_dac_status + + def get_syringe_pump_adc_read_counter(self): + """ + Gets the current syringe pump ADC read counter + + @return: latest published ADC read counter by HD firmware + """ + return self.syringe_pump_adc_read_counter + @_publish(["syringe_pump_state", "syringe_pump_set_rate_ml_hr", "syringe_pump_meas_rate_ml_hr","syringe_pump_position", "syringe_pump_volume_ml","syringe_pump_home_v", @@ -186,6 +222,8 @@ message['message'][MsgFieldPositions.START_POS_FIELD_9:MsgFieldPositions.END_POS_FIELD_9])) saf = struct.unpack('f', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_10:MsgFieldPositions.END_POS_FIELD_10])) + sts = struct.unpack('i', bytearray( + message['message'][MsgFieldPositions.START_POS_FIELD_11:MsgFieldPositions.END_POS_FIELD_11])) self.syringe_pump_state = sta[0] self.heparin_state = hep[0] @@ -197,8 +235,12 @@ self.syringe_pump_switch_v = det[0] self.syringe_pump_force_v = frc[0] self.syringe_pump_safety_volume_ml = saf[0] + self.syringe_pump_status = (sts[0] & 0xFF000000) >> 24 + self.syringe_pump_encoder_status = (sts[0] & 0x00FF0000) >> 16 + self.syringe_pump_adc_dac_status = (sts[0] & 0x0000FF00) >> 8 + self.syringe_pump_adc_read_counter = (sts[0] & 0x000000FF) - def cmd_syringe_pump_operation(self, operation=SyringePumpOperations.SYRINGE_PUMP_OP_STOP.value, rate=0.0, volume=0.0): + def cmd_syringe_pump_operation(self, operation: int = SyringePumpOperations.SYRINGE_PUMP_OP_STOP.value, rate: float = 0.0, volume: float = 0.0) -> int: """ Constructs and sends the syringe pump operation command Constraints: @@ -244,7 +286,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_syringe_pump_data_broadcast_interval_override(self, ms=1000, reset=NO_RESET): + def cmd_syringe_pump_data_broadcast_interval_override(self, ms: int = 1000, reset: int = NO_RESET) -> int: """ Constructs and sends the syringe pump data broadcast interval override command Constraints: @@ -283,7 +325,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_syringe_pump_meas_position_override(self, position=0, reset=NO_RESET): + def cmd_syringe_pump_meas_position_override(self, position: int = 0, reset: int = NO_RESET) -> int: """ Constructs and sends the syringe pump measured position override command Constraints: @@ -321,7 +363,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_syringe_pump_meas_rate_override(self, rate=0.0, reset=NO_RESET): + def cmd_syringe_pump_meas_rate_override(self, rate: float = 0.0, reset: int = NO_RESET) -> int: """ Constructs and sends the syringe pump measured rate override command Constraints: @@ -359,7 +401,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_syringe_pump_meas_force_override(self, volts=0.0, reset=NO_RESET): + def cmd_syringe_pump_meas_force_override(self, volts: float = 0.0, reset: int = NO_RESET) -> int: """ Constructs and sends the syringe pump measured force override command Constraints: @@ -371,7 +413,7 @@ """ rst = integer_to_bytearray(reset) - vol = integer_to_bytearray(volts) + vol = float_to_bytearray(volts) payload = rst + vol message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, @@ -397,7 +439,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_syringe_pump_meas_detect_override(self, volts=0.0, reset=NO_RESET): + def cmd_syringe_pump_meas_detect_override(self, volts: float = 0.0, reset: int = NO_RESET) -> int: """ Constructs and sends the syringe pump measured syringe detect override command Constraints: @@ -435,7 +477,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_syringe_pump_meas_home_override(self, volts=0.0, reset=NO_RESET): + def cmd_syringe_pump_meas_home_override(self, volts: float = 0.0, reset: int = NO_RESET) -> int: """ Constructs and sends the syringe pump measured home override command Constraints: @@ -473,7 +515,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_syringe_pump_meas_volume_override(self, volume=0.0, reset=NO_RESET): + def cmd_syringe_pump_meas_volume_override(self, volume: float = 0.0, reset: int = NO_RESET) -> int: """ Constructs and sends the syringe pump measured volume override command Constraints: @@ -511,3 +553,155 @@ self.logger.debug("Timeout!!!!") return False + def cmd_syringe_pump_status_override(self, status: int = 0, reset: int = NO_RESET) -> int: + """ + Constructs and sends the syringe pump status override command + Constraints: + Must be logged into HD. + + @param status: integer - status (0..255) + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + sts = integer_to_bytearray(status & 0x000000FF) + payload = rst + sts + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_SYRINGE_PUMP_STATUS_OVERRIDE.value, + payload=payload) + + self.logger.debug("override HD syringe pump status") + + # Send message + received_message = self.can_interface.send(message) + + # If there is content... + if received_message is not None: + if reset == RESET: + str_res = "reset back to normal: " + else: + str_res = str(status) + self.logger.debug("Syringe pump status overridden to " + str_res + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + self.logger.debug("Timeout!!!!") + return False + + def cmd_syringe_pump_encoder_status_override(self, status: int = 0, reset: int = NO_RESET) -> int: + """ + Constructs and sends the syringe pump encoder status override command + Constraints: + Must be logged into HD. + + @param status: integer - encoder status (0..255) + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + sts = integer_to_bytearray(status & 0x000000FF) + payload = rst + sts + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_SYRINGE_PUMP_ENCODER_STATUS_OVERRIDE.value, + payload=payload) + + self.logger.debug("override HD syringe pump encoder status") + + # Send message + received_message = self.can_interface.send(message) + + # If there is content... + if received_message is not None: + if reset == RESET: + str_res = "reset back to normal: " + else: + str_res = str(status) + self.logger.debug("Syringe pump encoder status overridden to " + str_res + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + self.logger.debug("Timeout!!!!") + return False + + def cmd_syringe_pump_adc_dac_status_override(self, status: int = 0, reset: int = NO_RESET) -> int: + """ + Constructs and sends the syringe pump ADC & DAC status override command + Constraints: + Must be logged into HD. + + @param status: integer - ADC and DAC status (0..255) + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + sts = integer_to_bytearray(status & 0x000000FF) + payload = rst + sts + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_SYRINGE_PUMP_ADC_DAC_STATUS_OVERRIDE.value, + payload=payload) + + self.logger.debug("override HD syringe pump ADC & DAC status") + + # Send message + received_message = self.can_interface.send(message) + + # If there is content... + if received_message is not None: + if reset == RESET: + str_res = "reset back to normal: " + else: + str_res = str(status) + self.logger.debug("Syringe pump ADC & DAC status overridden to " + str_res + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + self.logger.debug("Timeout!!!!") + return False + + def cmd_syringe_pump_adc_read_counter_override(self, counter: int = 0, reset: int = NO_RESET) -> int: + """ + Constructs and sends the syringe pump ADC read counter override command + Constraints: + Must be logged into HD. + + @param counter: integer - status (0..255) + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + ctr = integer_to_bytearray(counter & 0x000000FF) + payload = rst + ctr + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_SYRINGE_PUMP_ADC_READ_COUNTER_OVERRIDE.value, + payload=payload) + + self.logger.debug("override HD syringe pump ADC read counter") + + # Send message + received_message = self.can_interface.send(message) + + # If there is content... + if received_message is not None: + if reset == RESET: + str_res = "reset back to normal: " + else: + str_res = str(counter) + self.logger.debug("Syringe pump ADC read counter overridden to " + str_res + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + self.logger.debug("Timeout!!!!") + return False + Index: dialin/hd/ui_proxy.py =================================================================== diff -u -rf89093ee0f0b9159df2ae4e0b86971f0e0e1b448 -r24e107b2ac852390b49583c5390860aadde6244a --- dialin/hd/ui_proxy.py (.../ui_proxy.py) (revision f89093ee0f0b9159df2ae4e0b86971f0e0e1b448) +++ dialin/hd/ui_proxy.py (.../ui_proxy.py) (revision 24e107b2ac852390b49583c5390860aadde6244a) @@ -1001,7 +1001,7 @@ "treatment_end_cmd_succeeded", "treatment_end_cmd_reject_reason", ]) - def _handler_treatment_end_cmd_response(self, message): + def _handler_treatment_end_cmd_response(self, message: dict) -> None: """ Handler for response from HD regarding treatment end user command. @@ -1068,7 +1068,7 @@ self.logger.debug("Sending ui request to set alarm audio volume to level " + str(volume) + " to HD") self.can_interface.send(message, 0) - def cmd_ui_uf_volume_set(self, uf_volume): + def cmd_ui_uf_volume_set(self, uf_volume: float): """ Constructs and sends the ui set ultrafiltration volume parameter message @@ -1152,13 +1152,12 @@ self.can_interface.send(message, 0) - def cmd_ui_treatment_duration_setting_change_request(self, time_min=0): + def cmd_ui_treatment_duration_setting_change_request(self, time_min: int = 0): """ - Constructs and sends a ui UF change settings confirmed by user message + Constructs and sends a ui UF change settings confirmed by user message - @param time_min: (int) treatment time (in min). - - @return: None + @param time_min: (int) treatment time (in min). + @return: None """ payload = integer_to_bytearray(time_min) Index: setup.py =================================================================== diff -u -r8e32afb5793619bd651b8964609a8e9aee3a5e4c -r24e107b2ac852390b49583c5390860aadde6244a --- setup.py (.../setup.py) (revision 8e32afb5793619bd651b8964609a8e9aee3a5e4c) +++ setup.py (.../setup.py) (revision 24e107b2ac852390b49583c5390860aadde6244a) @@ -40,6 +40,7 @@ "python-can", "python-dateutil", "six", - "wrapt" + "wrapt", + "openpyxl" ] )