Index: dialin/common/msg_defs.py =================================================================== diff -u -rf89093ee0f0b9159df2ae4e0b86971f0e0e1b448 -r2b8e96a45047b35b4d10e26da47a45e8d7a24c67 --- dialin/common/msg_defs.py (.../msg_defs.py) (revision f89093ee0f0b9159df2ae4e0b86971f0e0e1b448) +++ dialin/common/msg_defs.py (.../msg_defs.py) (revision 2b8e96a45047b35b4d10e26da47a45e8d7a24c67) @@ -58,6 +58,7 @@ REQUEST_REJECT_REASON_SALINE_BOLUS_NOT_IN_PROGRESS = 22 NUM_OF_REQUEST_REJECT_REASONS = 23 + class MsgFieldPositions: # Generic response msg field byte positions (where 32-bit data fields are used) START_POS_FIELD_1 = 6 # Hardcoded for now to avoid cyclic import issue. See protocols.CAN.DenaliMessage class Index: dialin/common/msg_ids.py =================================================================== diff -u -rf876b77eab64261c89b8928b038e18de8125742a -r2b8e96a45047b35b4d10e26da47a45e8d7a24c67 --- dialin/common/msg_ids.py (.../msg_ids.py) (revision f876b77eab64261c89b8928b038e18de8125742a) +++ dialin/common/msg_ids.py (.../msg_ids.py) (revision 2b8e96a45047b35b4d10e26da47a45e8d7a24c67) @@ -8,9 +8,9 @@ # @file msg_ids.py # # @author (last) Peter Lucia -# @date (last) 29-Apr-2021 +# @date (last) 03-May-2021 # @author (original) Peter Lucia -# @date (original) 29-Apr-2021 +# @date (original) 03-May-2021 # ############################################################################ from enum import unique @@ -228,6 +228,12 @@ 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 + 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_DG_VOLTAGES_DATA = 0X86 + MSG_ID_DG_CHEM_DISINFECT_DATA = 0X87 MSG_ID_PRESSURE_OCCLUSION_DATA = 0X9 MSG_ID_CAN_ERROR_COUNT = 0X999 MSG_ID_RTC_EPOCH = 0XA @@ -262,7 +268,7 @@ MSG_ID___AVAILABLE_13 = 0XA01E MSG_ID___AVAILABLE_14 = 0XA01F MSG_ID___AVAILABLE_15 = 0XA020 - MSG_ID_HEAT_DISINFECT_PUBLISH_INTERVAL_OVERRIDE = 0XA021 + MSG_ID___AVAILABLE_16 = 0XA021 MSG_ID_DG_SOFTWARE_RESET_REQUEST = 0XA022 MSG_ID_DG_CONCENTRATE_PUMP_MEASURED_SPEED_OVERRIDE = 0XA023 MSG_ID_CONCENTRATE_PUMP_TARGET_SPEED_OVERRIDE = 0XA024 Index: dialin/dg/dialysate_generator.py =================================================================== diff -u -r9704b6d2e632edb5084358361a6b264202ea4e94 -r2b8e96a45047b35b4d10e26da47a45e8d7a24c67 --- dialin/dg/dialysate_generator.py (.../dialysate_generator.py) (revision 9704b6d2e632edb5084358361a6b264202ea4e94) +++ dialin/dg/dialysate_generator.py (.../dialysate_generator.py) (revision 2b8e96a45047b35b4d10e26da47a45e8d7a24c67) @@ -45,6 +45,7 @@ from ..utils.base import _AbstractSubSystem, _publish, _LogManager from ..common.msg_defs import MsgIds, MsgFieldPositions from .flush import FlushMode +from .chemical_disinfect import ChemicalDisinfect class DG(_AbstractSubSystem): @@ -169,6 +170,7 @@ 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/dg/uv_reactors.py =================================================================== diff -u -rf89093ee0f0b9159df2ae4e0b86971f0e0e1b448 -r2b8e96a45047b35b4d10e26da47a45e8d7a24c67 --- dialin/dg/uv_reactors.py (.../uv_reactors.py) (revision f89093ee0f0b9159df2ae4e0b86971f0e0e1b448) +++ dialin/dg/uv_reactors.py (.../uv_reactors.py) (revision 2b8e96a45047b35b4d10e26da47a45e8d7a24c67) @@ -23,6 +23,14 @@ UV_REACTOR_STATE_ON = 1 +@unique +class ReactorsHealthStatus(DialinEnum): + + UV_REACTOR_NOT_HEALTHY = 0 + UV_REACTOR_HEALTHY = 1 + UV_REACTOR_OFF = 2 + + class UVReactors(_AbstractSubSystem): """ @@ -46,36 +54,36 @@ self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_uv_reactors_sync) - self.inlet_uv_reactor_health = 0.0 - self.outlet_uv_reactor_health = 0.0 - self.inlet_uv_reactor_state = 0.0 - self.outlet_uv_reactor_state = 0.0 + self.inlet_uv_reactor_health = 0 + self.outlet_uv_reactor_health = 0 + self.inlet_uv_reactor_state = 0 + self.outlet_uv_reactor_state = 0 - def get_inlet_uv_reactor_health(self): + def get_inlet_uv_reactor_health(self) -> int: """ Gets the inlet UV reactor health @return: Inlet UV reactor health """ return self.inlet_uv_reactor_health - def get_outlet_uv_reactor_health(self): + def get_outlet_uv_reactor_health(self) -> int: """ Gets the outlet UV reactor health @return: Outlet UV reactor health """ return self.outlet_uv_reactor_health - def get_inlet_uv_reactor_state(self): + def get_inlet_uv_reactor_state(self) -> int: """ Gets the inlet UV reactor state @return: Inlet UV reactor state """ return self.inlet_uv_reactor_state - def get_outlet_uv_reactor_state(self): + def get_outlet_uv_reactor_state(self) -> int: """ Gets the outlet UV reactor state @@ -85,33 +93,30 @@ @_publish(['inlet_uv_reactor_health', 'outlet_uv_reactor_health', 'inlet_uv_reactor_state', 'outlet_uv_reactor_state']) - def _handler_uv_reactors_sync(self, message): + def _handler_uv_reactors_sync(self, message:dict) -> None: """ Handles published thermistors message. @param message: published thermistors message @return: none """ - inlet_health = struct.unpack('f', bytearray( + inlet_health = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1]))[0] - outlet_health = struct.unpack('f', bytearray( + outlet_health = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2]))[0] - inlet_state = struct.unpack('f', bytearray( + inlet_state = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_3:MsgFieldPositions.END_POS_FIELD_3]))[0] - outlet_state = struct.unpack('f', bytearray( + outlet_state = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_4:MsgFieldPositions.END_POS_FIELD_4]))[0] self.inlet_uv_reactor_health = inlet_health self.outlet_uv_reactor_health = outlet_health # Check if the received state from firmware is in range otherwise, the state will be unknown - self.inlet_uv_reactor_state = ReactorsStates(inlet_state).name if ReactorsStates.has_value(inlet_state)\ - else 'Inlet UV reactor state unknown' + self.inlet_uv_reactor_state = inlet_state + self.outlet_uv_reactor_state = outlet_state - self.outlet_uv_reactor_state = ReactorsStates(outlet_state).name if ReactorsStates.has_value(outlet_state)\ - else 'Outlet UV reactor state unknown' - - def cmd_uv_reactors_data_broadcast_interval_override(self, ms, reset=NO_RESET): + def cmd_uv_reactors_data_broadcast_interval_override(self, ms:int, reset:int=NO_RESET) -> int: """ Constructs and sends the UV reactors data publish interval. Constraints: @@ -152,22 +157,22 @@ self.logger.debug("Timeout!!!!") return False - def cmd_uv_reactors_health_override(self, health, reactor, reset=NO_RESET): + def cmd_uv_reactors_health_override(self, health:int, reactor:int, reset:int=NO_RESET) -> int: """ Constructs and sends the UV reactors' health override command. Constraints: Must be logged into DG. - @param reactor: (int) UV reactor index @param health: (int) 0 for unhealthy and 1 for healthy + @param reactor: (int) UV reactor index @param reset: (int) 0 for no reset and 1 for reset """ reset_value = integer_to_bytearray(reset) rctr = integer_to_bytearray(reactor) hlth = integer_to_bytearray(health) - payload = reset_value + rctr + hlth + payload = reset_value + hlth + rctr - message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_dg_ch_id, message_id=MsgIds.MSG_ID_DG_UV_REACTORS_HEALTH_OVERRIDE.value, payload=payload) # Send message @@ -181,18 +186,20 @@ self.logger.debug("UV reactors health override Timeout!!!") return False - def cmd_start_stop_inlet_uv_reactor(self, state=ReactorsStates.UV_REACTOR_STATE_OFF.name): + def cmd_start_stop_inlet_uv_reactor(self, state:int=ReactorsStates.UV_REACTOR_STATE_OFF.value) -> int: """ Constructs and sends a start/stop command to the DG inlet UV reactor @param: state: (int) the state of the inlet UV reactor. 0 for Off and 1 for On. @return: 1 if successful, zero otherwise """ - if state == ReactorsStates.UV_REACTOR_STATE_ON.name: - payload = integer_to_bytearray(1) + rst = integer_to_bytearray(0) + inlet_uv_reactor_index = integer_to_bytearray(0) + if state == ReactorsStates.UV_REACTOR_STATE_ON.value: + payload = rst + integer_to_bytearray(1) + inlet_uv_reactor_index operation = 'Turning on ' else: - payload = integer_to_bytearray(0) + payload = rst + integer_to_bytearray(0) + inlet_uv_reactor_index operation = 'Turning off ' message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_dg_ch_id, @@ -210,21 +217,23 @@ self.logger.debug(operation + "inlet UV reactor timeout!!") return False - def cmd_start_stop_outlet_uv_reactor(self, state=ReactorsStates.UV_REACTOR_STATE_OFF.name): + def cmd_start_stop_outlet_uv_reactor(self, state:int=ReactorsStates.UV_REACTOR_STATE_ON.value) -> int: """ Constructs and sends a start/stop command to the DG outlet UV reactor @param: state: (int) the state of the outlet UV reactor. 0 for Off and 1 for On. @return: 1 if successful, zero otherwise """ - if state == ReactorsStates.UV_REACTOR_STATE_ON: - payload = integer_to_bytearray(1) + rst = integer_to_bytearray(0) + outlet_uv_reactor_index = integer_to_bytearray(1) + if state == ReactorsStates.UV_REACTOR_STATE_ON.value: + payload = rst + integer_to_bytearray(1) + outlet_uv_reactor_index operation = 'Turning on ' else: - payload = integer_to_bytearray(0) + payload = rst + integer_to_bytearray(0) + outlet_uv_reactor_index operation = 'Turning off ' - message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_dg_ch_id, message_id=MsgIds.MSG_ID_DG_START_STOP_UV_REACTORS.value, payload=payload) # Send message Index: dialin/dg/valves.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r2b8e96a45047b35b4d10e26da47a45e8d7a24c67 --- dialin/dg/valves.py (.../valves.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/dg/valves.py (.../valves.py) (revision 2b8e96a45047b35b4d10e26da47a45e8d7a24c67) @@ -29,7 +29,7 @@ @unique -class VPiVSPVBfStates(DialinEnum): +class VPiVSPVBfVRD1VRD2States(DialinEnum): VALVE_STATE_CLOSED = 0 VALVE_STATE_OPEN = 1 @@ -38,8 +38,8 @@ @unique class VPdStates(DialinEnum): - VALVE_STATE_OPEN_C_TO_NO = 0 - VALVE_STATE_DRAIN_C_TO_NC = 1 + VALVE_STATE_DRAIN_C_TO_NO = 0 + VALVE_STATE_OPEN_C_TO_NC = 1 @unique @@ -90,8 +90,8 @@ VALVE_DRAIN = 7 # VDR VALVE_PRESSURE_INLET = 8 # VPI VALVE_SAMPLING_PORT = 9 # VSP - VALVE_RESERVOIR_1 = 10 # VR1 - VALVE_RESERVOIR_2 = 11 # VR2 + VALVE_RESERVOIR_DRAIN_1 = 10 # VRD1 + VALVE_RESERVOIR_DRAIN_2 = 11 # VRD2 VALVE_PRODUCTION_DRAIN = 12 # VPD NUM_OF_VALVES = 13 # Number of valves @@ -121,8 +121,8 @@ self.valve_state_VDR = {"id": self.VALVE_DRAIN, "state": DEENERGIZED} self.valve_state_VPI = {"id": self.VALVE_PRESSURE_INLET, "state": DEENERGIZED} self.valve_state_VSP = {"id": self.VALVE_SAMPLING_PORT, "state": DEENERGIZED} - self.valve_state_VR1 = {"id": self.VALVE_RESERVOIR_1, "state": DEENERGIZED} - self.valve_state_VR2 = {"id": self.VALVE_RESERVOIR_2, "state": DEENERGIZED} + self.valve_state_VRD1 = {"id": self.VALVE_RESERVOIR_DRAIN_1, "state": DEENERGIZED} + self.valve_state_VRD2 = {"id": self.VALVE_RESERVOIR_DRAIN_2, "state": DEENERGIZED} self.valve_state_VPD = {"id": self.VALVE_PRODUCTION_DRAIN, "state": DEENERGIZED} self.valve_states_enum = [0 for i in range(self.NUM_OF_VALVES)] @@ -143,8 +143,8 @@ Valve Drain \n Valve Pressure Inlet \n Valve Sampling Port \n - Valve Reservoir 1 (spare for now including DG FPGA, as valve is of passive air relief type) \n - Valve Reservoir 2 (spare for now including DG FPGA, as valve is of passive air relief type) \n + Valve Reservoir 1 Drain \n + Valve Reservoir 2 Drain \n Valve Production Drain \n ]\n """ @@ -159,8 +159,8 @@ self.valve_state_VDR.get("state", None), self.valve_state_VPI.get("state", None), self.valve_state_VSP.get("state", None), - self.valve_state_VR1.get("state", None), - self.valve_state_VR2.get("state", None), + self.valve_state_VRD1.get("state", None), + self.valve_state_VRD2.get("state", None), self.valve_state_VPD.get("state", None) ] @@ -239,8 +239,8 @@ "valve_state_VDR", "valve_state_VPI", "valve_state_VSP", - "valve_state_VR1", - "valve_state_VR2", + "valve_state_VRD1", + "valve_state_VRD2", "valve_state_VPD", "valve_states_enum" ]) @@ -265,22 +265,22 @@ self.valve_state_VDR["state"] = self._binary_to_valve_state(vst[0] & 128) self.valve_state_VPI["state"] = self._binary_to_valve_state(vst[0] & 256) self.valve_state_VSP["state"] = self._binary_to_valve_state(vst[0] & 512) - self.valve_state_VR1["state"] = self._binary_to_valve_state(vst[0] & 1024) - self.valve_state_VR2["state"] = self._binary_to_valve_state(vst[0] & 2048) + self.valve_state_VRD1["state"] = self._binary_to_valve_state(vst[0] & 1024) + self.valve_state_VRD2["state"] = self._binary_to_valve_state(vst[0] & 2048) self.valve_state_VPD["state"] = self._binary_to_valve_state(vst[0] & 4096) self.valve_states_enum[self.VALVE_RESERVOIR_FILL] = VRdVRfStates(self._binary_to_valve_state(vst[0] & 1)).name # VRF self.valve_states_enum[self.VALVE_RESERVOIR_INLET] = VRoVRiStates(self._binary_to_valve_state(vst[0] & 2)).name # VRI self.valve_states_enum[self.VALVE_RESERVOIR_DRAIN] = VRdVRfStates(self._binary_to_valve_state(vst[0] & 4)).name # VRD self.valve_states_enum[self.VALVE_RESERVOIR_OUTLET] = VRoVRiStates(self._binary_to_valve_state(vst[0] & 8)).name # VRO self.valve_states_enum[self.VALVE_PRESSURE_OUTLET] = VPoStates(self._binary_to_valve_state(vst[0] & 16)).name # VPO - self.valve_states_enum[self.VALVE_BYPASS_FILTER] = VPiVSPVBfStates(self._binary_to_valve_state(vst[0] & 32)).name # VBF + self.valve_states_enum[self.VALVE_BYPASS_FILTER] = VPiVSPVBfVRD1VRD2States(self._binary_to_valve_state(vst[0] & 32)).name # VBF self.valve_states_enum[self.VALVE_RECIRCULATE] = VDrVRcStates(self._binary_to_valve_state(vst[0] & 64)).name # VRC self.valve_states_enum[self.VALVE_DRAIN] = VDrVRcStates(self._binary_to_valve_state(vst[0] & 128)).name # VDR - self.valve_states_enum[self.VALVE_PRESSURE_INLET] = VPiVSPVBfStates(self._binary_to_valve_state(vst[0] & 256)).name # VPI - self.valve_states_enum[self.VALVE_SAMPLING_PORT] = VPiVSPVBfStates(self._binary_to_valve_state(vst[0] & 512)).name # VSP - self.valve_states_enum[self.VALVE_RESERVOIR_1] = self._binary_to_valve_state(vst[0] & 1024) # VR1 - self.valve_states_enum[self.VALVE_RESERVOIR_2] = self._binary_to_valve_state(vst[0] & 2048) # VR2 + self.valve_states_enum[self.VALVE_PRESSURE_INLET] = VPiVSPVBfVRD1VRD2States(self._binary_to_valve_state(vst[0] & 256)).name # VPI + self.valve_states_enum[self.VALVE_SAMPLING_PORT] = VPiVSPVBfVRD1VRD2States(self._binary_to_valve_state(vst[0] & 512)).name # VSP + self.valve_states_enum[self.VALVE_RESERVOIR_DRAIN_1] = VPiVSPVBfVRD1VRD2States(self._binary_to_valve_state(vst[0] & 1024)).name # VRD1 + self.valve_states_enum[self.VALVE_RESERVOIR_DRAIN_2] = VPiVSPVBfVRD1VRD2States(self._binary_to_valve_state(vst[0] & 2048)).name # VRD2 self.valve_states_enum[self.VALVE_PRODUCTION_DRAIN] = VPdStates(self._binary_to_valve_state(vst[0] & 4096)).name # VPD def cmd_valve_override(self, state, valve, reset=NO_RESET): @@ -306,8 +306,8 @@ 7 = Valve Drain \n 8 = Valve Pressure Inlet \n 9 = Valve Sampling Port \n - 10 = Valve Reservoir 1 (spare for now including DG FPGA, as valve is of passive air relief type) \n - 11 = Valve Reservoir 2 (spare for now including DG FPGA, as valve is of passive air relief type) \n + 10 = Valve Reservoir 1 Drain \n + 11 = Valve Reservoir 2 Drain \n 12 = Valve Production Drain \n """ Index: dialin/hd/hemodialysis_device.py =================================================================== diff -u -rf89093ee0f0b9159df2ae4e0b86971f0e0e1b448 -r2b8e96a45047b35b4d10e26da47a45e8d7a24c67 --- dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision f89093ee0f0b9159df2ae4e0b86971f0e0e1b448) +++ dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision 2b8e96a45047b35b4d10e26da47a45e8d7a24c67) @@ -17,6 +17,7 @@ from .accelerometer import HDAccelerometer from .air_trap import HDAirTrap from .alarms import HDAlarms +from .blood_leak import HDBloodLeak from .buttons import HDButtons from .fluid_leak import HDFluidLeak from .ui_proxy import HDUIProxy @@ -94,6 +95,7 @@ self.air_trap = HDAirTrap(self.can_interface, self.logger) self.alarms = HDAlarms(self.can_interface, self.logger) self.buttons = HDButtons(self.can_interface, self.logger) + self.blood_leak = HDBloodLeak(self.can_interface, self.logger) self.fluid_leak = HDFluidLeak(self.can_interface, self.logger) self.ui = HDUIProxy(self.can_interface, self.logger) self.rtc = HDRTC(self.can_interface, self.logger) Index: dialin/hd/valves.py =================================================================== diff -u -rf89093ee0f0b9159df2ae4e0b86971f0e0e1b448 -r2b8e96a45047b35b4d10e26da47a45e8d7a24c67 --- dialin/hd/valves.py (.../valves.py) (revision f89093ee0f0b9159df2ae4e0b86971f0e0e1b448) +++ dialin/hd/valves.py (.../valves.py) (revision 2b8e96a45047b35b4d10e26da47a45e8d7a24c67) @@ -16,7 +16,7 @@ import struct -from ..utils.conversions import integer_to_bytearray +from ..utils.conversions import integer_to_bytearray, float_to_bytearray from .constants import NO_RESET from ..protocols.CAN import (DenaliMessage, DenaliChannels) from ..utils.base import _AbstractSubSystem, _publish, DialinEnum @@ -137,7 +137,7 @@ """ return self.valves_status - def cmd_hd_valves_broadcast_interval_override(self, ms, reset=NO_RESET): + def cmd_hd_valves_broadcast_interval_override(self, ms:int, reset:int=NO_RESET) -> int: """ Constructs and sends broadcast time interval Constraints: @@ -168,7 +168,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_set_hd_valve_position(self, valve, position, reset=NO_RESET): + def cmd_set_hd_valve_position(self, valve:int, position:int, reset:int=NO_RESET) -> int: """ Constructs and sends the HD valves set position for a valve @@ -203,8 +203,78 @@ self.logger.debug("HD cmd_valve_override Timeout!!!") return False - def cmd_set_hd_valve_pwm(self, valve, pwm, direction, reset=NO_RESET): + def cmd_set_hd_valve_current_override(self, valve:int, current:float, reset:int=NO_RESET) -> int: """ + Constructs and sends the HD valves set position for a valve + + @param valve: integer - Valve number: + VDI = 0 + VDO = 1 + VBA = 2 + VBV = 3 + @param current: float value to override current + @param reset: integer - 1 to reset a previous override, 0 to override + @returns 1 if successful, zero otherwise + """ + reset_value = integer_to_bytearray(reset) + vlv = integer_to_bytearray(valve) + cur = float_to_bytearray(current) + payload = reset_value + cur + vlv + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_VALVES_CURRENT_OVERRIDE.value, + payload=payload) + # Send message + received_message = self.can_interface.send(message) + + # If there is content... + if received_message is not None: + + self.logger.debug("Setting {} current to {:5.3f} A".format(str(ValvesEnum(valve).name), current)) + + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + self.logger.debug("HD current override Timeout!!!") + return False + + def cmd_set_hd_valve_position_count_override(self, valve:int, position_count:int, reset:int=NO_RESET) -> int: + """ + Constructs and sends the HD valves set position for a valve + + @param valve: integer - Valve number: + VDI = 0 + VDO = 1 + VBA = 2 + VBV = 3 + @param position_count: integer value + @param reset: integer - 1 to reset a previous override, 0 to override + @returns 1 if successful, zero otherwise + """ + reset_value = integer_to_bytearray(reset) + vlv = integer_to_bytearray(valve) + pos = integer_to_bytearray(position_count) + payload = reset_value + pos + vlv + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSD_ID_HD_VALVES_POSITION_COUNT_OVERRIDE.value, + payload=payload) + # Send message + received_message = self.can_interface.send(message) + + # If there is content... + if received_message is not None: + + self.logger.debug("Setting {} position to {} ".format(str(ValvesEnum(valve).name), position_count)) + + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + self.logger.debug("HD current override Timeout!!!") + return False + + def cmd_set_hd_valve_pwm(self, valve:int, pwm:int, direction:int, reset:int=NO_RESET) -> int: + """ Constructs and sends the HD valves PWM command @param valve: integer - Valve number: @@ -238,7 +308,7 @@ self.logger.debug("HD cmd_valve_override Timeout!!!") return False - def cmd_home_hd_valve(self, valve): + def cmd_home_hd_valve(self, valve:int) -> int: """ Constructs and sends the HD valves home command @@ -265,7 +335,7 @@ self.logger.debug("HD Homing Valve Timeout!!!") return False - def cmd_set_hd_air_trap_valve(self, valve_state=AirTrapState.STATE_CLOSED.name): + def cmd_set_hd_air_trap_valve(self, valve_state:int=AirTrapState.STATE_CLOSED.value) -> int: """ Constructs and sends an open/close command to the HD air trap valve @@ -294,7 +364,7 @@ return False @_publish(["valves_status"]) - def _handler_hd_valves_sync(self, message): + def _handler_hd_valves_sync(self, message:dict) -> None: """ Handles published HD valves data messages. HD valves data are captured for reference. @@ -335,4 +405,3 @@ if AirTrapState.has_value(air_trap): self.hd_air_trap_status = AirTrapState(air_trap).name -