Index: dialin/dg/drain_pump.py =================================================================== diff -u -r1647ec71451f356dc8c61528781a5eff30859604 -r98be8e8e674df17d358ae22b77c59639e8c1b365 --- dialin/dg/drain_pump.py (.../drain_pump.py) (revision 1647ec71451f356dc8c61528781a5eff30859604) +++ dialin/dg/drain_pump.py (.../drain_pump.py) (revision 98be8e8e674df17d358ae22b77c59639e8c1b365) @@ -93,6 +93,8 @@ def cmd_drain_pump_speed_set_point_override(self, speed, reset=NO_RESET): """ Constructs and sends the drain pump speed set point override command + Constraints: + Must be logged into DG. @param speed: integer - speed set point (in RPM) to override with @param reset: integer - 1 to reset a previous override, 0 to override @@ -129,7 +131,10 @@ def cmd_drain_pump_data_broadcast_interval_override(self, ms, reset=NO_RESET): """ - Constructs and sends the drain pump speed set point override command + Constructs and sends the drain pump speed set point 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). @param ms: integer - interval (in ms) to override with @param reset: integer - 1 to reset a previous override, 0 to override Index: dialin/dg/valves.py =================================================================== diff -u -r3995adb7a16b5b7569582ba781685ca75f9af49f -r98be8e8e674df17d358ae22b77c59639e8c1b365 --- dialin/dg/valves.py (.../valves.py) (revision 3995adb7a16b5b7569582ba781685ca75f9af49f) +++ dialin/dg/valves.py (.../valves.py) (revision 98be8e8e674df17d358ae22b77c59639e8c1b365) @@ -55,6 +55,7 @@ VALVE_RESERVOIR_2 = 11 # VR2 VALVE_PRODUCTION_DRAIN = 12 # VPD + def __init__(self, can_interface=None): """ @@ -71,19 +72,19 @@ self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_valves_sync) self.valve_states_all = 0x0000 - self.valve_state_VRF = DEENERGIZED - self.valve_state_VRI = DEENERGIZED - self.valve_state_VRD = DEENERGIZED - self.valve_state_VRO = DEENERGIZED - self.valve_state_VPO = DEENERGIZED - self.valve_state_VBF = DEENERGIZED - self.valve_state_VRC = DEENERGIZED - self.valve_state_VDR = DEENERGIZED - self.valve_state_VPI = DEENERGIZED - self.valve_state_VSP = DEENERGIZED - self.valve_state_VR1 = DEENERGIZED - self.valve_state_VR2 = DEENERGIZED - self.valve_state_VPD = DEENERGIZED + self.valve_state_VRF = {"id": self.VALVE_RESERVOIR_FILL, "state": DEENERGIZED} + self.valve_state_VRI = {"id": self.VALVE_RESERVOIR_INLET, "state": DEENERGIZED} + self.valve_state_VRD = {"id": self.VALVE_RESERVOIR_DRAIN, "state": DEENERGIZED} + self.valve_state_VRO = {"id": self.VALVE_RESERVOIR_OUTLET, "state": DEENERGIZED} + self.valve_state_VPO = {"id": self.VALVE_PRESSURE_OUTLET, "state": DEENERGIZED} + self.valve_state_VBF = {"id": self.VALVE_BYPASS_FILTER, "state": DEENERGIZED} + self.valve_state_VRC = {"id": self.VALVE_RECIRCULATE, "state": DEENERGIZED} + 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_VPD = {"id": self.VALVE_PRODUCTION_DRAIN, "state": DEENERGIZED} def get_valve_states(self): """ @@ -107,21 +108,70 @@ ]\n """ return [ - self.valve_state_VRF, - self.valve_state_VRI, - self.valve_state_VRD, - self.valve_state_VRO, - self.valve_state_VPO, - self.valve_state_VBF, - self.valve_state_VRC, - self.valve_state_VDR, - self.valve_state_VPI, - self.valve_state_VSP, - self.valve_state_VR1, - self.valve_state_VR2, - self.valve_state_VPD + self.valve_state_VRF.get("state", None), + self.valve_state_VRI.get("state", None), + self.valve_state_VRD.get("state", None), + self.valve_state_VRO.get("state", None), + self.valve_state_VPO.get("state", None), + self.valve_state_VBF.get("state", None), + self.valve_state_VRC.get("state", None), + 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_VPD.get("state", None) ] + def sort_by_id(self, observation): + """ + Converts a published dictionary of valve state information to an ordered list + of tuples. + + For example: + >>> dg = DG() + >>> observation = {'datetime': datetime.datetime(2020, 7, 13, 10, 43, 27, 433357), + 'valve_state_VBF': {'id': 5, 'state': True}, + 'valve_state_VDR': {'id': 7, 'state': True}, + 'valve_state_VPD': {'id': 12, 'state': True}, + 'valve_state_VPI': {'id': 8, 'state': True}, + 'valve_state_VPO': {'id': 4, 'state': True}, + 'valve_state_VR1': {'id': 10, 'state': True}, + 'valve_state_VR2': {'id': 11, 'state': True}, + 'valve_state_VRC': {'id': 6, 'state': True}, + 'valve_state_VRD': {'id': 2, 'state': True}, + 'valve_state_VRF': {'id': 0, 'state': True}, + 'valve_state_VRI': {'id': 1, 'state': True}, + 'valve_state_VRO': {'id': 3, 'state': True}, + 'valve_state_VSP': {'id': 9, 'state': True}, + 'valve_states_all': 8191} + >>> print(dg.valves.sort_by_id(observation)) + ('valve_state_VRF', 0, True) + ('valve_state_VRI', 1, True) + ('valve_state_VRD', 2, True) + ('valve_state_VRO', 3, True) + ('valve_state_VPO', 4, True) + ('valve_state_VBF', 5, True) + ('valve_state_VRC', 6, True) + ('valve_state_VDR', 7, True) + ('valve_state_VPI', 8, True) + ('valve_state_VSP', 9, True) + ('valve_state_VR1', 10, True) + ('valve_state_VR2', 11, True) + ('valve_state_VPD', 12, True) + + @param observation: dictionary of the observed valve states + @return: a list of tuples of the valve states + """ + + result = [] + for key, value in observation.items(): + if isinstance(value, dict): + result.append((key, value.get("id", None), value.get("state", None))) + + result = sorted(result, key=lambda each: each[1]) + return result + def _binary_to_valve_state(self, binary): """ @param binary: binary value @@ -160,19 +210,19 @@ vst = struct.unpack('H', bytearray(message['message'][self.START_POS_VALVES_STATES:self.END_POS_VALVES_STATES])) self.valve_states_all = vst[0] # Extract each valve state from U16 valves states using bit-masking - self.valve_state_VRF = self._binary_to_valve_state(vst[0] & 1) - self.valve_state_VRI = self._binary_to_valve_state(vst[0] & 2) - self.valve_state_VRD = self._binary_to_valve_state(vst[0] & 4) - self.valve_state_VRO = self._binary_to_valve_state(vst[0] & 8) - self.valve_state_VPO = self._binary_to_valve_state(vst[0] & 16) - self.valve_state_VBF = self._binary_to_valve_state(vst[0] & 32) - self.valve_state_VRC = self._binary_to_valve_state(vst[0] & 64) - self.valve_state_VDR = self._binary_to_valve_state(vst[0] & 128) - self.valve_state_VPI = self._binary_to_valve_state(vst[0] & 256) - self.valve_state_VSP = self._binary_to_valve_state(vst[0] & 512) - self.valve_state_VR1 = self._binary_to_valve_state(vst[0] & 1024) - self.valve_state_VR2 = self._binary_to_valve_state(vst[0] & 2048) - self.valve_state_VPD = self._binary_to_valve_state(vst[0] & 4096) + self.valve_state_VRF["state"] = self._binary_to_valve_state(vst[0] & 1) + self.valve_state_VRI["state"] = self._binary_to_valve_state(vst[0] & 2) + self.valve_state_VRD["state"] = self._binary_to_valve_state(vst[0] & 4) + self.valve_state_VRO["state"] = self._binary_to_valve_state(vst[0] & 8) + self.valve_state_VPO["state"] = self._binary_to_valve_state(vst[0] & 16) + self.valve_state_VBF["state"] = self._binary_to_valve_state(vst[0] & 32) + self.valve_state_VRC["state"] = self._binary_to_valve_state(vst[0] & 64) + 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_VPD["state"] = self._binary_to_valve_state(vst[0] & 4096) def cmd_valve_override(self, state, valve, reset=NO_RESET): """ Index: dialin/hd/alarms.py =================================================================== diff -u -r17e48d8bf1a8960537d0615f7118bb8532e1015c -r98be8e8e674df17d358ae22b77c59639e8c1b365 --- dialin/hd/alarms.py (.../alarms.py) (revision 17e48d8bf1a8960537d0615f7118bb8532e1015c) +++ dialin/hd/alarms.py (.../alarms.py) (revision 98be8e8e674df17d358ae22b77c59639e8c1b365) @@ -287,6 +287,10 @@ def cmd_alarm_state_override(self, state, alarm, reset=NO_RESET): """ Constructs and sends the alarm state override command + Constraints: + Must be logged into HD. + Given alarm must be valid. + If inactivating alarm, given alarm must be recoverable (clearable). @param state: integer - 1 for alarm active, 0 for alarm inactive @param alarm: integer - ID of alarm to override @@ -320,6 +324,9 @@ def cmd_alarm_time_override(self, time_ms, alarm, reset=NO_RESET): """ Constructs and sends the alarm time override command + Constraints: + Must be logged into HD. + Given alarm must be valid. @param time_ms: integer - time (in ms) since alarm was activated @param alarm: integer - ID of alarm to override @@ -359,6 +366,9 @@ def cmd_alarm_lamp_pattern_override(self, pattern, reset=NO_RESET): """ Constructs and sends the alarm lamp pattern override command. + Constraints: + Must be logged into HD. + Given pattern must be one of the patterns listed below. @param pattern: integer - ID of alarm lamp pattern to override with @param reset: integer - 1 to reset a previous override, 0 to override Index: dialin/hd/hemodialysis_device.py =================================================================== diff -u -r17e48d8bf1a8960537d0615f7118bb8532e1015c -r98be8e8e674df17d358ae22b77c59639e8c1b365 --- dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision 17e48d8bf1a8960537d0615f7118bb8532e1015c) +++ dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision 98be8e8e674df17d358ae22b77c59639e8c1b365) @@ -154,20 +154,31 @@ print("Login Timeout!!!!") return False - def cmd_hd_safety_shutdown_override(self): + def cmd_hd_safety_shutdown_override(self, active=True, reset=NO_RESET): """ Constructs and sends an HD safety shutdown override command via CAN bus. + Constraints: + Must be logged into HD. \returns response message if received, False if no response received - @param msg: byte array - properly formatted HD message to insert - + @param active: boolean - True to activate safety shutdown, False to deactivate + @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ + if active: + sft=1 + else: + sft=0 + rst = integer_to_bytearray(reset) + saf = integer_to_bytearray(sft) + payload = rst + saf + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, - message_id=self.MSG_ID_HD_SAFETY_SHUTDOWN_OVERRIDE) + message_id=self.MSG_ID_HD_SAFETY_SHUTDOWN_OVERRIDE, + payload=payload) print("overriding HD safety shutdown") Index: dialin/hd/pressure_occlusion.py =================================================================== diff -u -r17e48d8bf1a8960537d0615f7118bb8532e1015c -r98be8e8e674df17d358ae22b77c59639e8c1b365 --- dialin/hd/pressure_occlusion.py (.../pressure_occlusion.py) (revision 17e48d8bf1a8960537d0615f7118bb8532e1015c) +++ dialin/hd/pressure_occlusion.py (.../pressure_occlusion.py) (revision 98be8e8e674df17d358ae22b77c59639e8c1b365) @@ -143,6 +143,8 @@ def cmd_arterial_pressure_measured_override(self, pres, reset=NO_RESET): """ Constructs and sends the measured arterial pressure override command + Constraints: + Must be logged into HD. @param pres: float - measured arterial pressure (in mmHg) to override with @param reset: integer - 1 to reset a previous override, 0 to override @@ -180,6 +182,8 @@ """ Constructs and sends the measured venous pressure \n override command. + Constraints: + Must be logged into HD. @param pres: float - venous pressure (in mmHg) to override with @param reset: integer - 1 to reset a previous override, 0 to override @@ -216,6 +220,8 @@ def cmd_blood_pump_measured_occlusion_override(self, occl, reset=NO_RESET): """ Constructs and sends the measured blood pump occlusion pressure override command + Constraints: + Must be logged into HD. @param occl: float - pressure (in mmHg) to override with @param reset: integer - 1 to reset a previous override, 0 to override @@ -253,6 +259,8 @@ """ Constructs and sends the measured dialysate inlet pump occlusion pressure override \n command. + Constraints: + Must be logged into HD. @param occl: float - pressure (in mmHg) to override with @param reset: integer - 1 to reset a previous override, 0 to override @@ -290,6 +298,8 @@ """ Constructs and sends the measured dialysate outlet pump occlusion pressure override \n command. + Constraints: + Must be logged into HD. @param occl: float - pressure (in mmHg) to override with @param reset: integer - 1 to reset a previous override, 0 to override @@ -326,6 +336,9 @@ def cmd_pressure_occlusion_broadcast_interval_override(self, ms, reset=NO_RESET): """ Constructs and sends the pressure/occlusion broadcast interval override command + Constraints: + Must be logged into HD. + Given interval must be non-zero and a multiple of the DG 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 Index: dialin/hd/watchdog.py =================================================================== diff -u -r17e48d8bf1a8960537d0615f7118bb8532e1015c -r98be8e8e674df17d358ae22b77c59639e8c1b365 --- dialin/hd/watchdog.py (.../watchdog.py) (revision 17e48d8bf1a8960537d0615f7118bb8532e1015c) +++ dialin/hd/watchdog.py (.../watchdog.py) (revision 98be8e8e674df17d358ae22b77c59639e8c1b365) @@ -42,6 +42,10 @@ def cmd_watchdog_task_check_in_override(self, state, task, reset=NO_RESET): """ Constructs and sends the watchdog task check-in override command + Constraints: + Must be logged into HD. + Given task must be valid. + Given state must be a 0 or 1. @param state: integer - 1 for task checked in, 0 for task not checked in @param task: integer - ID of task to override