Index: dialin/dg/accelerometer.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/accelerometer.py (.../accelerometer.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/dg/accelerometer.py (.../accelerometer.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -124,14 +124,14 @@ message['message'][MsgFieldPositions.START_POS_FIELD_9:MsgFieldPositions.END_POS_FIELD_9])) self.tilts = self.AccelerometerVector( x[0], y[0], z[0] ) - def cmd_accel_vector_override(self, mag, axis, reset=NO_RESET): + def cmd_accel_vector_override(self, axis: int, mag: int, reset: int = NO_RESET) -> int: """ Constructs and sends the accelerometer vector override command Constraints: Must be logged into DG. - @param mag: float - axis magnitude (in g) to override with @param axis: integer - accelerometer axis to override + @param mag: float - axis magnitude (in g) to override with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ @@ -164,14 +164,14 @@ self.logger.debug("Timeout!!!!") return False - def cmd_accel_max_vector_override(self, mag, axis, reset=NO_RESET): + def cmd_accel_max_vector_override(self, axis: int, mag: float, reset: int = NO_RESET) -> int: """ Constructs and sends the accelerometer maximum vector override command Constraints: Must be logged into DG. - @param mag: float - axis magnitude (in g) to override with @param axis: integer - accelerometer axis to override + @param mag: float - axis magnitude (in g) to override with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ Index: dialin/dg/concentrate_pumps.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/concentrate_pumps.py (.../concentrate_pumps.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/dg/concentrate_pumps.py (.../concentrate_pumps.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -126,12 +126,12 @@ self.logger.error("Timeout!!!!") return False - def cmd_concentrate_pump_target_speed_override(self, speed, pump_id): + def cmd_concentrate_pump_target_speed_override(self, pump_id: int, speed: float) -> int: """ Constructs and sends the concentrate pump target speed override command - @param speed: float - target speed value to override concentrate pump with @param pump_id: unsigned int - concentrate pump ID + @param speed: float - target speed value to override concentrate pump with @return: 1 if successful, zero otherwise Concentrate pump IDs: \n @@ -161,12 +161,12 @@ self.logger.error("Timeout!!!!") return False - def cmd_concentrate_pump_measured_speed_override(self, speed, pump_id, reset=NO_RESET): + def cmd_concentrate_pump_measured_speed_override(self, pump_id: int, speed: float, reset: int = NO_RESET) -> int: """ Constructs and sends the concentrate pump measured speed override command - @param speed: float - measured speed value to override concentrate pump with @param pump_id: unsigned int - concentrate pump ID + @param speed: float - measured speed value to override concentrate pump with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise Index: dialin/dg/conductivity_sensors.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/conductivity_sensors.py (.../conductivity_sensors.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/dg/conductivity_sensors.py (.../conductivity_sensors.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -94,12 +94,12 @@ self.conductivity_sensor_cd1 = cd1[0] self.conductivity_sensor_cd2 = cd2[0] - def cmd_conductivity_sensor_override(self, conductivity, sensor, reset=NO_RESET): + def cmd_conductivity_sensor_override(self, sensor: int, conductivity: float, reset: int = NO_RESET) -> int: """ Constructs and sends the conductivity value override command - @param conductivity: float - conductivity value to override sensor with @param sensor: unsigned int - sensor ID + @param conductivity: float - conductivity value to override sensor with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise Index: dialin/dg/dialysate_generator.py =================================================================== diff -u -rbfb0c47181dc8a73d09825ab697a7799dd520417 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/dialysate_generator.py (.../dialysate_generator.py) (revision bfb0c47181dc8a73d09825ab697a7799dd520417) +++ dialin/dg/dialysate_generator.py (.../dialysate_generator.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -23,7 +23,6 @@ from .fans import Fans from .hd_proxy import DGHDProxy from .heaters import Heaters -from .heat_disinfect import HeatDisinfect from .load_cells import DGLoadCells from .pressures import DGPressures from .reservoirs import DGReservoirs @@ -43,9 +42,30 @@ from ..utils import * from ..utils.base import _AbstractSubSystem, _publish, _LogManager from ..protocols.CAN import (DenaliCanMessenger, DenaliMessage, DenaliChannels) +from .voltages import DGVoltages +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 +95,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 +143,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,6 +173,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/dg/load_cells.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/load_cells.py (.../load_cells.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/dg/load_cells.py (.../load_cells.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -87,15 +87,15 @@ self.load_cell_B1 = b1[0] self.load_cell_B2 = b2[0] - def cmd_load_cell_override(self, grams, sensor, reset=NO_RESET): + def cmd_load_cell_override(self, sensor: int, grams: float, reset: int = NO_RESET) -> int: """ Constructs and sends the load cell override command Constraints: Must be logged into DG. Given sensor must be one of the sensors listed below. - @param grams: float - weight (in grams) to override sensor with @param sensor: unsigned int - sensor ID + @param grams: float - weight (in grams) to override sensor with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise Index: dialin/dg/pressures.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/pressures.py (.../pressures.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/dg/pressures.py (.../pressures.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -95,15 +95,15 @@ self.drain_pump_inlet_pressure = dri[0] self.drain_pump_outlet_pressure = dro[0] - def cmd_pressure_override(self, pressure, sensor, reset=NO_RESET): + def cmd_pressure_override(self, sensor: int, pressure: int, reset: int = NO_RESET) -> int: """ Constructs and sends the pressure override command. Constraints: Must be logged into DG. Given sensor must be one of the sensors listed below. - @param pressure: unsigned int - pressure (in PSI) @param sensor: unsigned int - sensor ID + @param pressure: unsigned int - pressure (in PSI) @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise Index: dialin/dg/temperature_sensors.py =================================================================== diff -u -r9704b6d2e632edb5084358361a6b264202ea4e94 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/temperature_sensors.py (.../temperature_sensors.py) (revision 9704b6d2e632edb5084358361a6b264202ea4e94) +++ dialin/dg/temperature_sensors.py (.../temperature_sensors.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -232,7 +232,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_temperature_sensors_override_value(self, sensor_value, sensor_index, reset=NO_RESET): + def cmd_temperature_sensors_override_value(self, sensor_index: int, sensor_value: float, reset: int = NO_RESET) -> int: """ Constructs and sends the value override of a temperature sensor. Constraints: Index: dialin/dg/thermistors.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/thermistors.py (.../thermistors.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/dg/thermistors.py (.../thermistors.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -70,7 +70,7 @@ self.thermistors[ThermistorsNames.THERMISTOR_POWER_SUPPLY_1.name] = pwr_supply_1 self.thermistors[ThermistorsNames.THERMISTOR_POWER_SUPPLY_2.name] = pwr_supply_2 - def cmd_thermistors_value_override(self, value, thermistor, reset=NO_RESET): + def cmd_thermistors_value_override(self, thermistor: int, value: float, reset: int = NO_RESET) -> int: """ Constructs and sends the thermistors value override command Constraints: @@ -79,6 +79,7 @@ @param value: float the temperature to be set @param thermistor: (int) thermistor index @param reset: (int) 1 to reset a previous override, 0 to override + @return 1 if successful, zero otherwise """ reset_value = integer_to_bytearray(reset) vlu = float_to_bytearray(value) Index: dialin/dg/uv_reactors.py =================================================================== diff -u -r0f4ba40a63c79697d979203f67ef0338a12cae23 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/uv_reactors.py (.../uv_reactors.py) (revision 0f4ba40a63c79697d979203f67ef0338a12cae23) +++ dialin/dg/uv_reactors.py (.../uv_reactors.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -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,38 +93,35 @@ @_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: Must be logged into DG. - Given interval must be non-zero and a multiple of the DG priority task interval (10 ms). + Given interval must be non-zero and a multiple of the DG general task interval (50 ms). @param ms: (int) interval (in ms) to override with @param reset: (int) 1 to reset a previous override, 0 to override @@ -158,17 +163,17 @@ 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 @return 1 if successful, zero otherwise """ 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 @@ -182,18 +187,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, @@ -211,21 +218,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 -r0f4ba40a63c79697d979203f67ef0338a12cae23 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/dg/valves.py (.../valves.py) (revision 0f4ba40a63c79697d979203f67ef0338a12cae23) +++ dialin/dg/valves.py (.../valves.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -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, valve: int, state: bool, reset: int = NO_RESET) -> int: @@ -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 """ @@ -338,7 +338,7 @@ Constructs and sends the valve state override command. Constraints: Must be logged into DG. - Given interval must be non-zero and a multiple of the DG priority task interval (10 ms). + Given interval must be non-zero and a multiple of the DG general task interval (50 ms). @param ms: unsigned int - broadcast interval (in ms) @param reset: integer - 1 to reset a previous override, 0 to override Index: dialin/hd/accelerometer.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/accelerometer.py (.../accelerometer.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/hd/accelerometer.py (.../accelerometer.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -124,14 +124,14 @@ message['message'][MsgFieldPositions.START_POS_FIELD_9:MsgFieldPositions.END_POS_FIELD_9])) self.tilts = self.AccelerometerVector( x[0], y[0], z[0] ) - def cmd_accel_vector_override(self, mag, axis, reset=NO_RESET): + def cmd_accel_vector_override(self, axis: int, mag: float, reset: int=NO_RESET) -> int: """ Constructs and sends the accelerometer vector override command Constraints: Must be logged into HD. - @param mag: float - axis magnitude (in g) to override with @param axis: integer - accelerometer axis to override + @param mag: float - axis magnitude (in g) to override with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ @@ -164,14 +164,14 @@ self.logger.debug("Timeout!!!!") return False - def cmd_accel_max_vector_override(self, mag, axis, reset=NO_RESET): + def cmd_accel_max_vector_override(self, axis: int, mag: float, reset: int=NO_RESET) -> int: """ Constructs and sends the accelerometer maximum vector override command Constraints: Must be logged into HD. - @param mag: float - axis magnitude (in g) to override with @param axis: integer - accelerometer axis to override + @param mag: float - axis magnitude (in g) to override with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ @@ -204,7 +204,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_accel_broadcast_interval_override(self, ms, reset=NO_RESET): + def cmd_accel_broadcast_interval_override(self, ms: int, reset: int = NO_RESET) -> int: """ Constructs and sends the accelerometer broadcast interval override command Constraints: Index: dialin/hd/alarms.py =================================================================== diff -u -r0f4ba40a63c79697d979203f67ef0338a12cae23 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/alarms.py (.../alarms.py) (revision 0f4ba40a63c79697d979203f67ef0338a12cae23) +++ dialin/hd/alarms.py (.../alarms.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -17,11 +17,11 @@ from logging import Logger from .constants import RESET, NO_RESET -from ..common.msg_defs import MsgIds +from ..common.msg_defs import MsgIds, MsgFieldPositions from ..protocols.CAN import (DenaliMessage, DenaliChannels) from ..utils.base import _AbstractSubSystem, _publish -from ..utils.conversions import integer_to_bytearray +from ..utils.conversions import integer_to_bytearray, float_to_bytearray class HDAlarms(_AbstractSubSystem): @@ -77,15 +77,16 @@ msg_id = MsgIds.MSG_ID_ALARM_TRIGGERED.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_alarm_activate) - channel_id = DenaliChannels.hd_alarm_broadcast_ch_id msg_id = MsgIds.MSG_ID_ALARM_CLEARED.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_alarm_clear) - - channel_id = DenaliChannels.hd_alarm_broadcast_ch_id msg_id = MsgIds.MSG_ID_ALARM_CONDITION_CLEARED.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_alarm_condition_clear) + channel_id = DenaliChannels.hd_sync_broadcast_ch_id + msg_id = MsgIds.MSG_ID_HD_ALARM_INFORMATION.value + self.can_interface.register_receiving_publication_function(channel_id, msg_id, + self._handler_alarm_information_sync) # composite alarm status based on latest HD alarm status broadcast message self.alarms_state = 0 @@ -99,6 +100,13 @@ # alarm condition states based on received HD alarm activation and clear condition messages self.alarm_conditions = [False] * 500 + # alarm information + self.alarm_volume = 0 + self.alarm_audio_curr_hg = 0.0 + self.alarm_audio_curr_lg = 0.0 + self.alarm_backup_audio_curr = 0.0 + self.safety_shutdown_active = False + def get_current_alarms_state(self): """ Gets the current alarms state. @@ -178,13 +186,55 @@ TBD = result & 2048 TBD = result & 4096 TBD = result & 8192 - TBD = result & 16384 + No Minimize = result & 16384 Condition Detected = result & 32768 @return: (int) The alarms flags value """ return self.alarms_flags + def get_alarm_volume(self): + """ + Gets the alarm audio volume level. + + @return: (int) current alarm audio volume (1..5) + """ + return self.alarm_volume + + def get_alarm_audio_current_hg(self): + """ + Gets the alarm audio current - high gain. + + @return: (float) alarm audio current - high gain (in mA) + """ + return self.alarm_audio_curr_hg + + + def get_alarm_audio_current_lg(self): + """ + Gets the alarm audio current - low gain. + + @return: (float) alarm audio current - low gain (in mA) + """ + return self.alarm_audio_curr_lg + + + def get_alarm_backup_audio_current(self): + """ + Gets the alarm backup audio current. + + @return: (float) alarm backup audio current (in mA) + """ + return self.alarm_backup_audio_curr + + def get_safety_shutdown_activated(self): + """ + Gets the state of the HD safety shutdown signal. + + @return: (bool) safety shutdown line is activated (T/F) + """ + return self.safety_shutdown_active + @_publish(["alarms_state", "alarm_top", "alarms_silence_expires_in", "alarms_escalates_in", "alarms_flags"]) def _handler_alarms_status_sync(self, message): """ @@ -255,6 +305,27 @@ alarm_id = struct.unpack(' int: """ Constructs and sends the clear all active alarms command. @@ -421,3 +492,195 @@ self.logger.debug("Timeout!!!!") return False + def cmd_alarm_info_broadcast_interval_override(self, ms:int=1000, reset:int=NO_RESET): + """ + Constructs and sends the alarm information broadcast interval override command + Constraints: + Must be logged into HD. + Given interval must be non-zero and a multiple of the HD general task interval (50 ms). + + @param ms: integer - interval (in ms) to override with + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + mis = integer_to_bytearray(ms) + payload = rst + mis + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_ALARM_INFO_SEND_INTERVAL_OVERRIDE.value, + payload=payload) + + self.logger.debug("override alarm information broadcast interval") + + # 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(ms) + " ms: " + self.logger.debug("Alarm information broadcast interval 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_alarm_audio_volume_override(self, volume:int=5, reset:int=NO_RESET): + """ + Constructs and sends the alarm audio volume override command + Constraints: + Must be logged into HD. + Given volume must be an integer between 1 and 5. + + @param volume: integer - alarm audio volume level (1..5) + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + vol = integer_to_bytearray(volume) + payload = rst + vol + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_ALARM_AUDIO_VOLUME_LEVEL_OVERRIDE.value, + payload=payload) + + self.logger.debug("override alarm audio volume level") + + # 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(volume) + ": " + self.logger.debug("Alarm audio volume level 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_alarm_audio_current_hg_override(self, current:float=0.0, reset:int=NO_RESET): + """ + Constructs and sends the alarm audio current (high gain) override command + Constraints: + Must be logged into HD. + + @param current: float - current (in mA) for high gain alarm audio + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + cur = float_to_bytearray(current) + payload = rst + cur + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_ALARM_AUDIO_CURRENT_HG_OVERRIDE.value, + payload=payload) + + self.logger.debug("override alarm audio high gain current") + + # 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(current) + " mA: " + self.logger.debug("Alarm audio high gain current 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_alarm_audio_current_lg_override(self, current:float=0.0, reset:int=NO_RESET): + """ + Constructs and sends the alarm audio current (low gain) override command + Constraints: + Must be logged into HD. + + @param current: float - current (in mA) for low gain alarm audio + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + cur = float_to_bytearray(current) + payload = rst + cur + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_ALARM_AUDIO_CURRENT_LG_OVERRIDE.value, + payload=payload) + + self.logger.debug("override alarm audio high gain current") + + # 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(current) + " mA: " + self.logger.debug("Alarm audio low gain current 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_alarm_backup_audio_current_override(self, current:float=0.0, reset:int=NO_RESET): + """ + Constructs and sends the backup alarm audio current override command + Constraints: + Must be logged into HD. + + @param current: float - current (in mA) for backup alarm audio + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + cur = float_to_bytearray(current) + payload = rst + cur + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_ALARM_BACKUP_AUDIO_CURRENT_OVERRIDE.value, + payload=payload) + + self.logger.debug("override alarm backup audio current") + + # 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(current) + " mA: " + self.logger.debug("Alarm backup audio current 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/blood_flow.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/blood_flow.py (.../blood_flow.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/hd/blood_flow.py (.../blood_flow.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -157,7 +157,7 @@ self.pwm_duty_cycle_pct = pwm[0] self.flow_signal_strength = sig[0] - def cmd_blood_flow_set_point_override(self, flow, mode=PUMP_CONTROL_MODE_CLOSED_LOOP, reset=NO_RESET): + def cmd_blood_flow_set_point_override(self, flow: int, mode: int = PUMP_CONTROL_MODE_CLOSED_LOOP, reset: int = NO_RESET) -> int: """ Constructs and sends the blood flow set point override command Constraints: @@ -206,7 +206,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_blood_flow_measured_override(self, flow, reset=NO_RESET): + def cmd_blood_flow_measured_override(self, flow: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured blood flow override command Constraints: @@ -245,7 +245,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_blood_pump_measured_motor_controller_speed_override(self, speed, reset=NO_RESET): + def cmd_blood_pump_measured_motor_controller_speed_override(self, speed: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured blood pump motor controller speed \n override command. @@ -285,7 +285,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_blood_pump_measured_motor_controller_current_override(self, curr, reset=NO_RESET): + def cmd_blood_pump_measured_motor_controller_current_override(self, curr: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured blood pump motor controller current override command Constraints: @@ -324,7 +324,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_blood_pump_measured_motor_speed_override(self, speed, reset=NO_RESET): + def cmd_blood_pump_measured_motor_speed_override(self, speed: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured blood pump motor speed override \n command. @@ -364,7 +364,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_blood_pump_measured_rotor_speed_override(self, speed, reset=NO_RESET): + def cmd_blood_pump_measured_rotor_speed_override(self, speed: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured blood pump rotor speed override \n command. @@ -404,7 +404,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_blood_flow_signal_strength_override(self, signal_strength, reset=NO_RESET): + def cmd_blood_flow_signal_strength_override(self, signal_strength: float, reset: int =NO_RESET) -> int: """ Constructs and sends the measured blood flow signal strength % override \n command. @@ -444,7 +444,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_blood_flow_broadcast_interval_override(self, ms, reset=NO_RESET): + def cmd_blood_flow_broadcast_interval_override(self, ms: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured blood flow broadcast interval override command Constraints: @@ -484,7 +484,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_home_blood_pump(self): + def cmd_home_blood_pump(self) -> int: """ Constructs and sends a blood pump home request message to the HD. Constraints: Index: dialin/hd/buttons.py =================================================================== diff -u -r2e392c92d55178f457a67423ba8c503a86dcf3c8 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/buttons.py (.../buttons.py) (revision 2e392c92d55178f457a67423ba8c503a86dcf3c8) +++ dialin/hd/buttons.py (.../buttons.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -29,12 +29,6 @@ Hemodialysis Device (HD) Dialin API sub-class for button related commands. """ - START_POS_POWEROFF = DenaliMessage.PAYLOAD_START_INDEX - END_POS_POWEROFF_STATUS = START_POS_POWEROFF + 2 - - PRESSED = 1 - RELEASED = 0 - def __init__(self, can_interface: DenaliCanMessenger, logger: Logger): """ HD_Buttons constructor Index: dialin/hd/dialysate_inlet_flow.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/dialysate_inlet_flow.py (.../dialysate_inlet_flow.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/hd/dialysate_inlet_flow.py (.../dialysate_inlet_flow.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -162,7 +162,10 @@ self.pwm_duty_cycle_pct = pwm[0] self.flow_signal_strength = sig[0] - def cmd_dialysate_inlet_flow_set_point_override(self, flow, mode=PUMP_CONTROL_MODE_CLOSED_LOOP, reset=NO_RESET): + def cmd_dialysate_inlet_flow_set_point_override(self, + flow: int, + mode: int = PUMP_CONTROL_MODE_CLOSED_LOOP, + reset: int = NO_RESET) -> int: """ Constructs and sends the dialysate flow set point override command Constraints: @@ -211,7 +214,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_inlet_flow_measured_override(self, flow, reset=NO_RESET): + def cmd_dialysate_inlet_flow_measured_override(self, flow: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate flow override command Constraints: @@ -250,7 +253,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_inlet_pump_measured_motor_controller_speed_override(self, speed, reset=NO_RESET): + def cmd_dialysate_inlet_pump_measured_motor_controller_speed_override(self, speed: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate inlet pump motor controller speed \n override command. @@ -290,7 +293,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_inlet_pump_measured_motor_controller_current_override(self, curr, reset=NO_RESET): + def cmd_dialysate_inlet_pump_measured_motor_controller_current_override(self, curr: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate inlet pump motor current override command Constraints: @@ -329,7 +332,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_inlet_pump_measured_motor_speed_override(self, speed, reset=NO_RESET): + def cmd_dialysate_inlet_pump_measured_motor_speed_override(self, speed: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate inlet pump motor speed override \n command. @@ -369,7 +372,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_inlet_pump_measured_rotor_speed_override(self, speed, reset=NO_RESET): + def cmd_dialysate_inlet_pump_measured_rotor_speed_override(self, speed: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate inlet pump rotor speed override \n command. @@ -409,7 +412,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_flow_signal_strength_override(self, signal_strength, reset=NO_RESET): + def cmd_dialysate_flow_signal_strength_override(self, signal_strength: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate flow signal strength % override \n command. @@ -449,7 +452,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_inlet_flow_broadcast_interval_override(self, ms, reset=NO_RESET): + def cmd_dialysate_inlet_flow_broadcast_interval_override(self, ms: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate inlet flow broadcast interval override command Constraints: @@ -488,7 +491,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_home_dialysate_inlet_pump(self): + def cmd_home_dialysate_inlet_pump(self) -> int: """ Constructs and sends a dialysate inlet pump home request message to the HD. Constraints: Index: dialin/hd/dialysate_outlet_flow.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/dialysate_outlet_flow.py (.../dialysate_outlet_flow.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/hd/dialysate_outlet_flow.py (.../dialysate_outlet_flow.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -147,7 +147,10 @@ self.measured_dialysate_outlet_pump_mc_current = mccurr[0] self.pwm_duty_cycle_pct = pwm[0] - def cmd_dialysate_outlet_flow_set_point_override(self, flow, mode=PUMP_CONTROL_MODE_CLOSED_LOOP, reset=NO_RESET): + def cmd_dialysate_outlet_flow_set_point_override(self, + flow: int, + mode: int = PUMP_CONTROL_MODE_CLOSED_LOOP, + reset: int =NO_RESET) -> int: """ Constructs and sends the dialysate outlet pump set point override command Constraints: @@ -196,7 +199,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_outlet_reference_uf_volume_override(self, refvol, reset=NO_RESET): + def cmd_dialysate_outlet_reference_uf_volume_override(self, refvol: float, reset: int = NO_RESET) -> int: """ Constructs and sends the UF reference volume override command Constraints: @@ -236,7 +239,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_outlet_measured_uf_volume_override(self, measvol, reset=NO_RESET): + def cmd_dialysate_outlet_measured_uf_volume_override(self, measvol: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured UF volume override command Constraints: @@ -275,7 +278,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_outlet_pump_measured_motor_controller_speed_override(self, speed, reset=NO_RESET): + def cmd_dialysate_outlet_pump_measured_motor_controller_speed_override(self, speed: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate outlet pump motor controller measured speed \n override command. @@ -315,7 +318,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_outlet_pump_measured_motor_controller_current_override(self, curr, reset=NO_RESET): + def cmd_dialysate_outlet_pump_measured_motor_controller_current_override(self, curr: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate outlet pump motor current override command Constraints: @@ -354,7 +357,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_outlet_pump_measured_motor_speed_override(self, speed, reset=NO_RESET): + def cmd_dialysate_outlet_pump_measured_motor_speed_override(self, speed: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate outlet pump motor speed override \n command. @@ -394,7 +397,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_outlet_pump_measured_rotor_speed_override(self, speed, reset=NO_RESET): + def cmd_dialysate_outlet_pump_measured_rotor_speed_override(self, speed: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate outlet pump rotor speed override \n command. @@ -434,7 +437,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_outlet_flow_broadcast_interval_override(self, ms, reset=NO_RESET): + def cmd_dialysate_outlet_flow_broadcast_interval_override(self, ms: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate outlet flow broadcast interval override command Constraints: @@ -474,16 +477,16 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_outlet_pump_load_cell_weight_override(self, weight, sensor, reset=NO_RESET): + def cmd_dialysate_outlet_pump_load_cell_weight_override(self, sensor: int, weight: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured load cell weight override command. Constraints: Must be logged into HD. Given sensor must be one of the sensors listed below. - @param weight: float - weight (in g) to override with - @param sensor: integer - ID of load cell to override - @param reset: integer - 1 to reset a previous override, 0 to override + @param sensor: integer - ID of load cell to override + @param weight: float - weight (in g) to override with + @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise Load Cells: \n @@ -522,7 +525,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_set_load_cell_weights(self, r1p, r1b, r2p, r2b): + def cmd_set_load_cell_weights(self, r1p: float, r1b: float, r2p: float, r2b: float) -> int: """ Constructs and sends the set load cell weights command. @@ -550,7 +553,7 @@ return 0 - def cmd_home_dialysate_outlet_pump(self): + def cmd_home_dialysate_outlet_pump(self) -> int: """ Constructs and sends a dialysate outlet pump home request message to the HD. Constraints: Index: dialin/hd/fluid_leak.py =================================================================== diff -u -r33e3f9f462c34f5ac8f8319dc3fada668b829190 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/fluid_leak.py (.../fluid_leak.py) (revision 33e3f9f462c34f5ac8f8319dc3fada668b829190) +++ dialin/hd/fluid_leak.py (.../fluid_leak.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -90,7 +90,7 @@ payload = rst + det message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, - message_id=MsgIds.MSG_ID_HD_FLUID_LEAK_STATE_DETECTOR_OVERRIDE.value, + message_id=MsgIds.MSG_ID_HD_FLUID_LEAK_STATE_OVERRIDE.value, payload=payload) self.logger.debug("Override fluid leak detector state value") Index: dialin/hd/hemodialysis_device.py =================================================================== diff -u -r2e392c92d55178f457a67423ba8c503a86dcf3c8 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision 2e392c92d55178f457a67423ba8c503a86dcf3c8) +++ dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -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 @@ -27,6 +28,7 @@ from .dialysate_outlet_flow import HDDialysateOutletFlow from .treatment import HDTreatment from .valves import HDValves +from .voltages import HDVoltages from .calibration_record import HDCalibrationNVRecord from .system_record import HDSystemNVRecords from .service_record import HDServiceNVRecords @@ -93,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) @@ -105,6 +108,7 @@ self.pressure_occlusion = HDPressureOcclusion(self.can_interface, self.logger) self.syringe_pump = HDSyringePump(self.can_interface, self.logger) self.valves = HDValves(self.can_interface, self.logger) + self.voltages = HDVoltages(self.can_interface, self.logger) self.calibration_record = HDCalibrationNVRecord(self.can_interface, self.logger) self.system_record = HDSystemNVRecords(self.can_interface, self.logger) self.service_record = HDServiceNVRecords(self.can_interface, self.logger) Index: dialin/hd/pressure_occlusion.py =================================================================== diff -u -r4ff3b2874eb12aee034d1f85ae32c161d05efc00 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/pressure_occlusion.py (.../pressure_occlusion.py) (revision 4ff3b2874eb12aee034d1f85ae32c161d05efc00) +++ dialin/hd/pressure_occlusion.py (.../pressure_occlusion.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -121,7 +121,7 @@ self.dialysate_inlet_pump_occlusion = dpi[0] self.dialysate_outlet_pump_occlusion = dpo[0] - def cmd_arterial_pressure_measured_override(self, pres, reset=NO_RESET): + def cmd_arterial_pressure_measured_override(self, pres: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured arterial pressure override command Constraints: @@ -159,7 +159,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_venous_pressure_measured_override(self, pres, reset=NO_RESET): + def cmd_venous_pressure_measured_override(self, pres: float, reset: int = NO_RESET) -> int: """ Constructs and sends the measured venous pressure \n override command. @@ -198,7 +198,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_blood_pump_measured_occlusion_override(self, occl, reset=NO_RESET): + def cmd_blood_pump_measured_occlusion_override(self, occl: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured blood pump occlusion pressure override command Constraints: @@ -236,7 +236,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_inlet_pump_measured_occlusion_override(self, occl, reset=NO_RESET): + def cmd_dialysate_inlet_pump_measured_occlusion_override(self, occl: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate inlet pump occlusion pressure override \n command. @@ -275,7 +275,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_dialysate_outlet_pump_measured_occlusion_override(self, occl, reset=NO_RESET): + def cmd_dialysate_outlet_pump_measured_occlusion_override(self, occl: int, reset: int = NO_RESET) -> int: """ Constructs and sends the measured dialysate outlet pump occlusion pressure override \n command. @@ -314,7 +314,7 @@ self.logger.debug("Timeout!!!!") return False - def cmd_pressure_occlusion_broadcast_interval_override(self, ms, reset=NO_RESET): + def cmd_pressure_occlusion_broadcast_interval_override(self, ms: int, reset: int = NO_RESET) -> int: """ Constructs and sends the pressure/occlusion broadcast interval override command Constraints: Index: dialin/hd/syringe_pump.py =================================================================== diff -u -r2e392c92d55178f457a67423ba8c503a86dcf3c8 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/syringe_pump.py (.../syringe_pump.py) (revision 2e392c92d55178f457a67423ba8c503a86dcf3c8) +++ dialin/hd/syringe_pump.py (.../syringe_pump.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -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,6 +235,10 @@ 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: int = SyringePumpOperations.SYRINGE_PUMP_OP_STOP.value, rate: float = 0.0, @@ -373,7 +415,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, @@ -513,3 +555,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 -r46ebf93d3666db40f25ad1e9170426853aa845d4 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/ui_proxy.py (.../ui_proxy.py) (revision 46ebf93d3666db40f25ad1e9170426853aa845d4) +++ dialin/hd/ui_proxy.py (.../ui_proxy.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -46,9 +46,8 @@ RESPONSE_ACCEPTED = 1 # start treatment command IDs - START_TREATMENT_CMD_INITIATE_TREATMENT_WORKFLOW = 0 - START_TREATMENT_CMD_CANCEL_TREATMENT_WORKFLOW = 1 - START_TREATMENT_CMD_START_TREATMENT = 2 + START_TREATMENT_CMD_CANCEL_TREATMENT_WORKFLOW = 0 + START_TREATMENT_CMD_INITIATE_TREATMENT_WORKFLOW = 1 # HD version message field positions START_POS_MAJOR = DenaliMessage.PAYLOAD_START_INDEX @@ -697,10 +696,10 @@ self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_DIALYZER_TYPE.value] = dlz[0] self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_BLOOD_PRESSURE_MEAS_INTERVAL_MIN.value] = bpi[0] self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_RINSEBACK_FLOW_RATE_ML_MIN.value] = rbf[0] - self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_ARTERIAL_PRESSURE_HIGH_LIMIT_MMHG.value] = apl[0] - self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_ARTERIAL_PRESSURE_LOW_LIMIT_MMHG.value] = aph[0] - self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_VENOUS_PRESSURE_HIGH_LIMIT_MMHG.value] = vpl[0] - self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_VENOUS_PRESSURE_LOW_LIMIT_MMHG.value] = vph[0] + self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_ARTERIAL_PRESSURE_HIGH_LIMIT_MMHG.value] = aph[0] + self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_ARTERIAL_PRESSURE_LOW_LIMIT_MMHG.value] = apl[0] + self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_VENOUS_PRESSURE_HIGH_LIMIT_MMHG.value] = vph[0] + self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_VENOUS_PRESSURE_LOW_LIMIT_MMHG.value] = vpl[0] self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_DISPENSE_RATE_ML_HR.value] = hdr[0] self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME_ML.value] = hbv[0] self.treatment_parameters_reject_reasons[self.TreatmentParameters.TREATMENT_PARAM_DIALYSATE_TEMPERATURE_C.value] = tmp[0] @@ -1200,9 +1199,8 @@ Constructs and sends a ui start treatment command message Constraints: Command must be one of the following: - START_TREATMENT_CMD_INITIATE_TREATMENT_WORKFLOW = 0 - START_TREATMENT_CMD_CANCEL_TREATMENT_WORKFLOW = 1 - START_TREATMENT_CMD_START_TREATMENT = 2 + START_TREATMENT_CMD_CANCEL_TREATMENT_WORKFLOW = 0 + START_TREATMENT_CMD_INITIATE_TREATMENT_WORKFLOW = 1 @param cmnd: (int) start treatment command code @@ -1212,7 +1210,7 @@ cmd = integer_to_bytearray(cmnd) payload = cmd message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, - message_id=MsgIds.MSG_ID_UI_START_TREATMENT_REQUEST.value, + message_id=MsgIds.MSG_ID_UI_INITIATE_TREATMENT_REQUEST.value, payload=payload) self.logger.debug("Sending start treatment command request.") @@ -1254,21 +1252,21 @@ def cmd_set_treatment_parameters(self, bld_flow: int = 100, dia_flow: int = 100, - duration: int = 60, - hep_rate: float = 0.1, - hep_bol : float = 0.1, - hep_stop: int = 1, + duration: int = 240, + hep_rate: float = 0.0, + hep_bol : float = 0.0, + hep_stop: int = 0, sal_bol : int = 100, acid : int = 0, bicarb : int = 0, dialyzer: int = 0, - dia_temp: float = 35, + dia_temp: float = 37.0, art_low : int = -300, - art_high: int = -200, - ven_low : int = -100, - ven_high: int = 100, - bp_intvl: int = 15, - rb_flow : int = 50) -> None: + art_high: int = 0, + ven_low : int = 20, + ven_high: int = 400, + bp_intvl: int = 30, + rb_flow : int = 75) -> None: """ Constructs and sends a ui set treatment parameters message Constraints: @@ -1339,17 +1337,25 @@ self.can_interface.send(message, 0) - def cmd_ui_confirm_treatment_parameters(self) -> None: + def cmd_ui_confirm_treatment_parameters(self, cmd: int = 0) -> None: """ Constructs and sends a ui confirm treatment parameters message + Constraints: + Command must be one of the following: + REJECT = 0 (user rejects treatment parameters) + CONFIRM = 1 (uesr confirms treatment parameters) + @param cmd: (int) confirm treatment parameters command code + @return: None """ + payload = integer_to_bytearray(cmd) message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, - message_id=MsgIds.MSG_ID_UI_USER_CONFIRM_TREATMENT_PARAMS.value) + message_id=MsgIds.MSG_ID_UI_USER_CONFIRM_TREATMENT_PARAMS.value, + payload=payload) - self.logger.debug("Sending confirm treatment parameters messge.") + self.logger.debug("Sending confirm treatment parameters message.") self.can_interface.send(message, 0) Index: dialin/hd/valves.py =================================================================== diff -u -r2e392c92d55178f457a67423ba8c503a86dcf3c8 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/hd/valves.py (.../valves.py) (revision 2e392c92d55178f457a67423ba8c503a86dcf3c8) +++ dialin/hd/valves.py (.../valves.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -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 @@ -140,6 +140,9 @@ def cmd_hd_valves_broadcast_interval_override(self, ms: int, reset: int = NO_RESET) -> int: """ Constructs and sends broadcast time interval + Constraints: + Must be logged into HD. + Given interval must be non-zero and a multiple of the HD general task interval (50 ms). @param ms: Publish time interval in ms @param reset: integer - 1 to reset a previous override, 0 to override @@ -200,8 +203,78 @@ self.logger.debug("HD cmd_valve_override Timeout!!!") return False - def cmd_set_hd_valve_pwm(self, valve: int, pwm: int, direction: int, reset: int = NO_RESET) -> int: + 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: @@ -271,7 +344,7 @@ @returns 1 if successful, zero otherwise """ - if valve_state == AirTrapState.STATE_OPEN: + if valve_state == AirTrapState.STATE_OPEN.value: payload = integer_to_bytearray(1) else: payload = integer_to_bytearray(0) @@ -292,7 +365,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. @@ -330,7 +403,5 @@ self.valves_status[vlv_name] = {'Valve': vlv_name, 'PosID': ValvesPositions(pos_ID).name, 'PosCnt': pos_cnt, 'Cmd': next_pos, 'State': ValvesStates(state_ID).name, 'Current': current, 'PosA': pos_a, 'PosB': pos_b, 'PosC': pos_c, 'PWM': pwm} - - if AirTrapState.has_value(air_trap): - self.hd_air_trap_status = AirTrapState(air_trap).name - + # Update the air trap valve's status + self.hd_air_trap_status = air_trap Index: dialin/ui/dg_simulator.py =================================================================== diff -u -rbfb0c47181dc8a73d09825ab697a7799dd520417 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/ui/dg_simulator.py (.../dg_simulator.py) (revision bfb0c47181dc8a73d09825ab697a7799dd520417) +++ dialin/ui/dg_simulator.py (.../dg_simulator.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -50,7 +50,7 @@ MsgIds.MSG_ID_REQUEST_FW_VERSIONS.value, self._handler_request_dg_version) self.can_interface.register_receiving_publication_function(DenaliChannels.ui_sync_broadcast_ch_id, - MsgIdsDialin.DMSG_ID_UI_SYSTEM_USAGE_REQUEST.value, + MsgIdsDialin.MSG_DIALIN_ID_UI_SYSTEM_USAGE_REQUEST.value, self._handler_system_usage_response) def _handler_system_usage_response(self, message: dict) -> None: @@ -66,7 +66,7 @@ payload += integer_to_bytearray(1619887863) message = DenaliMessage.build_message(channel_id=DenaliChannels.dg_to_ui_ch_id, - message_id=MsgIdsDialin.DMSG_ID_DG_SYSTEM_USAGE_RESPONSE.value, + message_id=MsgIdsDialin.MSG_DIALIN_ID_DG_SYSTEM_USAGE_RESPONSE.value, payload=payload) self.can_interface.send(message, 0) @@ -434,7 +434,7 @@ payload = b'0123456789\0' message = DenaliMessage.build_message(channel_id=DenaliChannels.dg_to_ui_ch_id, - message_id=MsgIdsDialin.DMSG_ID_DG_SERIAL_NUMBER_RESPONSE.value, + message_id=MsgIdsDialin.MSG_DIALIN_ID_DG_SERIAL_NUMBER_RESPONSE.value, payload=payload) self.can_interface.send(message, 0) Index: dialin/ui/hd_simulator.py =================================================================== diff -u -rbfb0c47181dc8a73d09825ab697a7799dd520417 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- dialin/ui/hd_simulator.py (.../hd_simulator.py) (revision bfb0c47181dc8a73d09825ab697a7799dd520417) +++ dialin/ui/hd_simulator.py (.../hd_simulator.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -80,7 +80,7 @@ MsgIds.MSG_ID_REQUEST_FW_VERSIONS.value, self._handler_request_hd_version) self.can_interface.register_receiving_publication_function(DenaliChannels.ui_sync_broadcast_ch_id, - MsgIdsDialin.DMSG_ID_UI_SYSTEM_USAGE_REQUEST.value, + MsgIdsDialin.MSG_DIALIN_ID_UI_SYSTEM_USAGE_REQUEST.value, self._handler_system_usage_response) self.alarms_simulator = HDAlarmsSimulator(self.can_interface, self.logger) @@ -98,7 +98,7 @@ payload += integer_to_bytearray(1619887863) message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, - message_id=MsgIdsDialin.DMSG_ID_HD_SYSTEM_USAGE_RESPONSE.value, + message_id=MsgIdsDialin.MSG_DIALIN_ID_HD_SYSTEM_USAGE_RESPONSE.value, payload=payload) self.can_interface.send(message, 0) @@ -330,17 +330,21 @@ self.can_interface.send(message, 0) - def cmd_send_hd_operation_mode(self, mode): + def cmd_send_hd_operation_mode(self, opMode, subMode): """ Broadcasts the current HD operation mode - @param: (int) mode + @param: (int) opMode + @param: (int) subMode @return: None """ - if not isinstance(mode, int): + if not isinstance(opMode, int): raise ValueError("Provided mode is not of type 'int'") + if not isinstance(subMode, int): + raise ValueError("Provided mode is not of type 'int'") - payload = integer_to_bytearray(mode) + payload = integer_to_bytearray(opMode) + payload += integer_to_bytearray(subMode) message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_sync_broadcast_ch_id, message_id=MsgIds.MSG_ID_HD_OP_MODE.value, @@ -672,7 +676,7 @@ :param dialysate_flow_rate: (int) Dialysate Flow Rate :return: None """ - + if not isinstance(accepted, int): accepted = int(accepted) if not isinstance(reason, int): @@ -1141,7 +1145,6 @@ self.can_interface.send(message, 0) - def cmd_send_treatment_adjust_pressures_limit_response(self, vAccepted, vReason, vArterialLow, vArterialHigh, vVenousLow, vVenousHigh): """ @@ -1391,7 +1394,7 @@ payload = bytearray('0123456789\0', encoding="utf-8") message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, - message_id=MsgIdsDialin.DMSG_ID_HD_SERIAL_NUMBER_RESPONSE.value, + message_id=MsgIdsDialin.MSG_DIALIN_ID_HD_SERIAL_NUMBER_RESPONSE.value, payload=payload) self.can_interface.send(message, 0) @@ -1431,3 +1434,273 @@ @return: (HDAlarmsSimulator) the alarms simulator """ return self.alarms_simulator + + def cmd_send_pre_treatment_state_data(self, + sub_mode, + water_sample_state, + consumables_self_test_state, + no_cartridge_self_test_state, + installation_state, + dry_self_test_state, + prime_state, + recirculate_state, + patient_connection_state): + """ + sends the broadcast message of the pre-treatment states + :param sub_mode : (U32) the main pre treatment state + :param water_sample_state : (U32) water sample state + :param consumables_self_test_state : (U32) consumables self test state + :param no_cartridge_self_test_state : (U32) no cartridge self-test state + :param installation_state : (U32) installation state + :param dry_self_test_state : (U32) dry self-test state + :param prime_state : (U32) prime state + :param recirculate_state : (U32) recirculate state + :param patient_connection_state : (U32) patient connection state + :return: + """ + payload = integer_to_bytearray(sub_mode) + payload += integer_to_bytearray(water_sample_state) + payload += integer_to_bytearray(consumables_self_test_state) + payload += integer_to_bytearray(no_cartridge_self_test_state) + payload += integer_to_bytearray(installation_state) + payload += integer_to_bytearray(dry_self_test_state) + payload += integer_to_bytearray(prime_state) + payload += integer_to_bytearray(recirculate_state) + payload += integer_to_bytearray(patient_connection_state) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_sync_broadcast_ch_id, + message_id=MsgIds.MSG_ID_PRE_TREATMENT_STATE.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_general_response(self, message_id, accepted, reason, fromHD = True): + """ + :param message_id: (int) the message id + :param accepted: (int) boolean accept/reject response + :param reason: (int) rejection reason + :return: none + """ + payload = integer_to_bytearray(accepted) + payload += integer_to_bytearray(reason) + + message = DenaliMessage.build_message(channel_id= DenaliChannels.hd_to_ui_ch_id if fromHD else DenaliChannels.dg_to_ui_ch_id, + message_id=message_id, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_general_progress_data(self, message_id, total, countdown, fromHD = True): + """ + send the pretreatment filter flush progress data + :param accepted: (U32) Total time in second + :param reason: (U32) count down time in second + :return: None + """ + payload = integer_to_bytearray(total) + payload += integer_to_bytearray(countdown) + + message = DenaliMessage.build_message(channel_id= DenaliChannels.hd_to_ui_ch_id if fromHD else DenaliChannels.dg_to_ui_ch_id, + message_id=message_id, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_pre_treatment_filter_flush_progress_data(self, total, countdown): + """ + send the pretreatment filter flush progress data + :param accepted: (U32) Total time in second + :param reason: (U32) count down time in second + :return: None + """ + payload = integer_to_bytearray(total) + payload += integer_to_bytearray(countdown) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dg_to_ui_ch_id, + message_id=MsgIds.MSG_ID_DG_FILTER_FLUSH_PROGRESS.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_pre_treatment_water_sample_response(self, accepted, reason ): + """ + send the pretreatment water sample response + :param accepted: (U32) accept or reject + :param reason: (U32) rejection reason + :return: None + """ + payload = integer_to_bytearray(accepted) + payload += integer_to_bytearray(reason) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=MsgIds.MSG_ID_HD_SAMPLE_WATER_CMD_RESPONSE.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_pre_treatment_self_test_no_cartridge_progress_data(self, total, countdown): + """ + send the pretreatment no cartridge self-tests progress data + :param accepted: (U32) Total time in second + :param reason: (U32) count down time in second + :return: None + """ + payload = integer_to_bytearray(total) + payload += integer_to_bytearray(countdown) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=MsgIds.MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_pre_treatment_self_test_dry_progress_data(self, total, countdown): + """ + send the pretreatment dry self-tests progress data + :param accepted: (U32) Total time in second + :param reason: (U32) count down time in second + :return: None + """ + payload = integer_to_bytearray(total) + payload += integer_to_bytearray(countdown) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=MsgIds.MSG_ID_HD_DRY_SELF_TEST_PROGRESS.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_pre_treatment_disposables_prime_progress_data(self, timeout, countdown): + """ + Broadcasts the progress time data of pre-treatment disposables priming to the UI + :param timeout : (int) the total progress time timeout in seconds + :param countdown: (int) the remaining time in seconds + :return: None + """ + payload = bytearray() + payload += integer_to_bytearray(timeout) + payload += integer_to_bytearray(countdown) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_sync_broadcast_ch_id, + message_id=MsgIds.MSG_ID_HD_PRIMING_STATUS_DATA.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_pre_treatment_prime_start_response(self, accepted, reason ): + """ + send the pretreatment prime start response + :param accepted: (U32) accept or reject + :param reason: (U32) rejection reason + :return: None + """ + payload = integer_to_bytearray(accepted) + payload += integer_to_bytearray(reason) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=MsgIds.MSG_ID_HD_START_PRIME_RESPONSE.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_pre_treatment_continue_to_treament_response(self, accepted, reason ): + """ + send the pretreatment continue to treatment response + :param accepted: (U32) accept or reject + :param reason: (U32) rejection reason + :return: None + """ + payload = integer_to_bytearray(accepted) + payload += integer_to_bytearray(reason) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=MsgIds.MSG_ID_HD_START_TREATMENT_RESPONSE.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_pre_treatment_patient_connection_confirm_response(self, accepted, reason ): + """ + send the pretreatment patient connection confirm response + :param accepted: (U32) accept or reject + :param reason: (U32) rejection reason + :return: None + """ + payload = integer_to_bytearray(accepted) + payload += integer_to_bytearray(reason) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=MsgIds.MSG_ID_HD_PATIENT_CONNECTION_CONFIRM_RESPONSE.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_post_treatment_disposable_removal_confirm_response(self, accepted, reason ): + """ + send post treatment disposable removal confirm response + :param accepted: (U32) accept or reject + :param reason: (U32) rejection reason + :return: None + """ + payload = integer_to_bytearray(accepted) + payload += integer_to_bytearray(reason) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=MsgIds.MSG_ID_HD_DISPOSABLE_REMOVAL_CONFIRM_RESPONSE.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_post_treatment_disposable_removal_confirm_response(self, accepted, reason ): + """ + send post treatment disposable removal confirm response + :param accepted: (U32) accept or reject + :param reason: (U32) rejection reason + :return: None + """ + payload = integer_to_bytearray(accepted) + payload += integer_to_bytearray(reason) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=MsgIds.MSG_ID_HD_DISPOSABLE_REMOVAL_CONFIRM_RESPONSE.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_post_treatment_log_response(self, accepted, reason, parameters): + """ + send post treatment log response + :param accepted: (U32) accept or reject + :param reason: (U32) rejection reason + :param parameters: (array of values) + :return: None + """ + payload = integer_to_bytearray(accepted) + payload += integer_to_bytearray(reason) + for parameter in parameters: + payload += parameter + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=MsgIds.MSG_ID_HD_TREATMENT_LOG_DATA_RESPONSE.value, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_dg_disinfection_state(self, subMode, flushMode, heatMode, chemicalMode): + """ + Broadcasts the current DG disinfection mode + :param subMode (int): disinfect states + :param flushMode (int): flush states + :param heatMode (int): heat states + :param ChemicalMode (int): chemical states + :return: + """ + payload = integer_to_bytearray(subMode) + payload += integer_to_bytearray(flushMode) + payload += integer_to_bytearray(heatMode) + payload += integer_to_bytearray(chemicalMode) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dg_sync_broadcast_ch_id, + message_id=MsgIdsDialin.MSG_DIALIN_ID_HD_DISINFECT_STATE.value, + payload=payload) + self.can_interface.send(message, 0) \ No newline at end of file Index: tests/peter/test_calibration.py =================================================================== diff -u -r46ebf93d3666db40f25ad1e9170426853aa845d4 -r97592c35f4d79caf180f4bfc8f68bd4823829347 --- tests/peter/test_calibration.py (.../test_calibration.py) (revision 46ebf93d3666db40f25ad1e9170426853aa845d4) +++ tests/peter/test_calibration.py (.../test_calibration.py) (revision 97592c35f4d79caf180f4bfc8f68bd4823829347) @@ -291,12 +291,4 @@ # test_hd_calibration_record() # test_hd_service_record() - test_hd_system_record() - # test_crc() - - - - - - - + # test_hd_system_record() \ No newline at end of file