Index: dialin/hd/alarms.py =================================================================== diff -u -r68418c949ee594c0f28b358c674a26f49eb244e6 -r21cc5bfbf3079f194f7bad44e87146da5a986226 --- dialin/hd/alarms.py (.../alarms.py) (revision 68418c949ee594c0f28b358c674a26f49eb244e6) +++ dialin/hd/alarms.py (.../alarms.py) (revision 21cc5bfbf3079f194f7bad44e87146da5a986226) @@ -84,7 +84,7 @@ channel_id = DenaliChannels.hd_alarm_broadcast_ch_id msg_id = MsgIds.MSG_ID_ALARM_TRIGGERED.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, - self._handler_alarm_activate) + self._handler_alarm_trigger) msg_id = MsgIds.MSG_ID_ALARM_CLEARED.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_alarm_clear) @@ -96,6 +96,11 @@ self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_alarm_information_sync) + self.hd_alarm_status_timestamp = 0.0 + self.hd_alarm_triggered_timestamp = 0.0 + self.hd_alarm_cleared_timestamp = 0.0 + self.hd_alarm_clr_condition_timestamp = 0.0 + self.hd_alarm_information_timestamp = 0.0 # composite alarm status based on latest HD alarm status broadcast message self.alarms_priority_state = 0 self.alarm_top = 0 @@ -404,8 +409,8 @@ for x in range(500): self.alarm_states[x] = False - @publish(["alarms_state", "alarm_top", "alarms_silence_expires_in", "alarms_escalates_in", "alarms_flags"]) - def _handler_alarms_status_sync(self, message): + @publish(["hd_alarm_status_timestamp", "alarms_state", "alarm_top", "alarms_silence_expires_in", "alarms_escalates_in", "alarms_flags"]) + def _handler_alarms_status_sync(self, message, timestamp=0.0): """ Handles published alarms status messages. alarms status data are captured for reference. @@ -430,8 +435,10 @@ message['message'][self.START_POS_ALARMS_FLAGS:self.END_POS_ALARMS_FLAGS]), byteorder=DenaliMessage.BYTE_ORDER) - @publish(["alarm_states", "alarm_conditions", "alarm_priorities", "alarm_ranks", "alarm_clear_top_only_flags"]) - def _handler_alarm_activate(self, message): + self.hd_alarm_status_timestamp = timestamp + + @publish(["hd_alarm_triggered_timestamp", "alarm_states", "alarm_conditions", "alarm_priorities", "alarm_ranks", "alarm_clear_top_only_flags"]) + def _handler_alarm_trigger(self, message, timestamp=0.0): """ Handles published HD alarm activation messages. @@ -463,9 +470,10 @@ self.alarm_priorities[alarm_id[0]] = priority[0] self.alarm_ranks[alarm_id[0]] = rank[0] self.alarm_clear_top_only_flags[alarm_id[0]] = clr_top_only[0] + self.hd_alarm_triggered_timestamp = timestamp - @publish(["alarm_states", "alarm_conditions"]) - def _handler_alarm_clear(self, message): + @publish(["hd_alarm_cleared_timestamp", "alarm_states", "alarm_conditions"]) + def _handler_alarm_clear(self, message, timestamp=0.0): """ Handles published HD alarm clear messages. @@ -475,9 +483,10 @@ alarm_id = struct.unpack('i', bytearray(message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1])) self.alarm_states[alarm_id[0]] = False self.alarm_conditions[alarm_id[0]] = False + self.hd_alarm_cleared_timestamp = timestamp - @publish(["alarm_conditions", "alarm_conditions"]) - def _handler_alarm_condition_clear(self, message): + @publish(["hd_alarm_clr_condition_timestamp", "alarm_conditions", "alarm_conditions"]) + def _handler_alarm_condition_clear(self, message, timestamp=0.0): """ Handles published HD alarm clear alarm condition messages. @@ -486,10 +495,11 @@ """ alarm_id = struct.unpack('i', bytearray(message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1])) self.alarm_conditions[alarm_id[0]] = False + self.hd_alarm_clr_condition_timestamp = timestamp - @publish(["alarm_volume", "alarm_audio_curr_hg", "alarm_audio_curr_lg", "alarm_backup_audio_curr", + @publish(["hd_alarm_information_timestamp", "alarm_volume", "alarm_audio_curr_hg", "alarm_audio_curr_lg", "alarm_backup_audio_curr", "safety_shutdown_active", "alarm_table_button_blockers", "alarm_state_button_blockers"]) - def _handler_alarm_information_sync(self, message): + def _handler_alarm_information_sync(self, message, timestamp=0.0): """ Handles published HD alarm information broadcast messages. @@ -531,6 +541,7 @@ self.alarm_state_button_blockers[self.AlarmResponseButtons.HD_ALARM_RESPONSE_BUTTON_RESUME.value] = True if srs[0] else False self.alarm_state_button_blockers[self.AlarmResponseButtons.HD_ALARM_RESPONSE_BUTTON_RINSEBACK.value] = True if srb[0] else False self.alarm_state_button_blockers[self.AlarmResponseButtons.HD_ALARM_RESPONSE_BUTTON_END_TREATMENT.value] = True if set[0] else False + self.hd_alarm_information_timestamp = timestamp def cmd_clear_all_alarms(self) -> int: """ Index: dialin/hd/hemodialysis_device.py =================================================================== diff -u -rae43c05f20c84d0d1ff8954d9e2b78df43ec5352 -r21cc5bfbf3079f194f7bad44e87146da5a986226 --- dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision ae43c05f20c84d0d1ff8954d9e2b78df43ec5352) +++ dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision 21cc5bfbf3079f194f7bad44e87146da5a986226) @@ -121,6 +121,9 @@ self._handler_ui_version_response_sync) # create properties + self.hd_op_mode_timestamp = 0.0 + self.hd_debug_events_timestamp = 0.0 + self.ui_version_info_response_timestamp = 0.0 self.hd_operation_mode = HDOpModes.MODE_INIT.value self.hd_operation_sub_mode = 0 self.hd_logged_in = False @@ -201,8 +204,8 @@ """ return self.ui_version - @publish(["hd_debug_events"]) - def _handler_hd_debug_event_sync(self, message): + @publish(["hd_debug_events_timestamp","hd_debug_events"]) + def _handler_hd_debug_event_sync(self, message, timestamp = 0.0): payload = message['message'] message_length = payload[self._HD_DEBUG_EVENT_MSG_LEN_INDEX] @@ -215,6 +218,7 @@ char, char_index = bytearray_to_byte(payload, index + i, False) temp_message += chr(char) + self.hd_debug_events_timestamp = timestamp self.hd_debug_events.insert(self.hd_debug_event_index, temp_message) self.hd_last_debug_event = temp_message @@ -231,8 +235,8 @@ """ self.hd_logged_in = logged_in - @publish(["hd_operation_mode"]) - def _handler_hd_op_mode_sync(self, message): + @publish(["hd_op_mode_timestamp","hd_operation_mode", "hd_operation_sub_mode"]) + def _handler_hd_op_mode_sync(self, message, timestamp = 0.0): """ Handles published HD operation mode messages. Current HD operation mode is captured for reference. @@ -247,8 +251,10 @@ self.hd_operation_mode = mode[0] self.hd_operation_sub_mode = smode[0] + self.hd_op_mode_timestamp = timestamp - def _handler_ui_version_response_sync(self,message): + + def _handler_ui_version_response_sync(self,message, timestamp = 0.0): """ Handler for response from HD regarding its version. @@ -272,6 +278,8 @@ compatibility = struct.unpack(' 0 for each in [major, minor, micro, build, compatibility]]): self.ui_version = f"v{major[0]}.{minor[0]}.{micro[0]}-{build[0]}.{compatibility[0]}" self.logger.debug(f"UI VERSION: {self.ui_version}") Index: dialin/hd/post_treatment.py =================================================================== diff -u -racd09d02879e8add4cf7f694f5db8e423a76c341 -r21cc5bfbf3079f194f7bad44e87146da5a986226 --- dialin/hd/post_treatment.py (.../post_treatment.py) (revision acd09d02879e8add4cf7f694f5db8e423a76c341) +++ dialin/hd/post_treatment.py (.../post_treatment.py) (revision 21cc5bfbf3079f194f7bad44e87146da5a986226) @@ -51,7 +51,7 @@ self.can_interface.register_receiving_publication_function(DenaliChannels.hd_sync_broadcast_ch_id, MsgIds.MSG_ID_HD_POST_TREATMENT_STATE.value, self._handler_post_treatment_sub_mode_sync) - + self.hd_post_treatment_state = 0.0 self.post_treatment_sub_mode = 0 self.post_treatment_drain_state = 0 @@ -61,8 +61,8 @@ """ return self.post_treatment_sub_mode - @publish(["post_treatment_sub_mode", "post_treatment_drain_state"]) - def _handler_post_treatment_sub_mode_sync(self, message): + @publish(["hd_post_treatment_state","post_treatment_sub_mode", "post_treatment_drain_state"]) + def _handler_post_treatment_sub_mode_sync(self, message, timestamp=0.0): """ Handles published post treatment sub mode data messages. Sub mode data is also captured for reference. @@ -75,4 +75,5 @@ index = MsgFieldPositions.START_POS_FIELD_1 self.post_treatment_sub_mode, index = bytearray_to_integer(payload, index, False) self.post_treatment_drain_state, index = bytearray_to_integer(payload, index, False) + self.hd_post_treatment_state = timestamp Index: dialin/hd/pretreatment.py =================================================================== diff -u -racd09d02879e8add4cf7f694f5db8e423a76c341 -r21cc5bfbf3079f194f7bad44e87146da5a986226 --- dialin/hd/pretreatment.py (.../pretreatment.py) (revision acd09d02879e8add4cf7f694f5db8e423a76c341) +++ dialin/hd/pretreatment.py (.../pretreatment.py) (revision 21cc5bfbf3079f194f7bad44e87146da5a986226) @@ -75,6 +75,10 @@ MsgIds.MSG_ID_HD_PRIMING_STATUS_DATA.value, self._handler_prime_progress_sync) + self.hd_pre_treatment_state_timestamp = 0.0 + self.hd_no_cart_st_timestamp = 0.0 + self.hd_dry_st_timestamp = 0.0 + self.hd_priming_timestamp = 0.0 self.pre_treatment_submode = 0 self.pre_treatment_sample_water_state = 0 self.pre_treatment_consumable_self_test_state = 0 @@ -225,6 +229,7 @@ return self.pre_treatment_wet_self_test_state @publish([ + "hd_pre_treatment_state_timestamp", "pre_treatment_submode", "pre_treatment_sample_water_state", "pre_treatment_consumable_self_test_state", @@ -237,7 +242,7 @@ "pre_treatment_wet_self_test_state", "pre_treatment_reservoir_state" ]) - def _handler_pre_treatment_state_sync(self, message): + def _handler_pre_treatment_state_sync(self, message, timestamp=0.0): """ Handles published pre-treatment state data messages. @@ -268,12 +273,14 @@ # Yes, I know we should do the new way, but we we need a task to cover all these in one shot! self.pre_treatment_reservoir_state = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_11:MsgFieldPositions.END_POS_FIELD_11]))[0] + self.hd_pre_treatment_state_timestamp = timestamp @publish([ + "hd_no_cart_st_timestamp", "no_cart_self_test_timeout", "no_cart_self_test_time_countdown" ]) - def _handler_no_cart_self_test_progress_sync(self, message): + def _handler_no_cart_self_test_progress_sync(self, message, timestamp=0.0): """ Handles published no cartridge self-test progress data messages. @@ -284,12 +291,14 @@ message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1]))[0] self.no_cart_self_test_time_countdown = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2]))[0] + self.hd_no_cart_st_timestamp = timestamp @publish([ + "hd_dry_st_timestamp", "dry_self_test_timeout", "dry_self_test_time_countdown" ]) - def _handler_dry_self_test_progress_sync(self, message): + def _handler_dry_self_test_progress_sync(self, message, timestamp=0.0): """ Handles published dry self-test progress data messages. @@ -301,12 +310,14 @@ message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1]))[0] self.dry_self_test_time_countdown = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2]))[0] + self.hd_dry_st_timestamp = timestamp @publish([ + "hd_priming_timestamp", "prime_timeout", "prime_time_countdown" ]) - def _handler_prime_progress_sync(self, message): + def _handler_prime_progress_sync(self, message, timestamp=0.0): """ Handles published prime progress data messages. @@ -318,3 +329,4 @@ message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1]))[0] self.prime_time_countdown = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2]))[0] + self.hd_priming_timestamp = timestamp \ No newline at end of file Index: dialin/hd/treatment.py =================================================================== diff -u -racd09d02879e8add4cf7f694f5db8e423a76c341 -r21cc5bfbf3079f194f7bad44e87146da5a986226 --- dialin/hd/treatment.py (.../treatment.py) (revision acd09d02879e8add4cf7f694f5db8e423a76c341) +++ dialin/hd/treatment.py (.../treatment.py) (revision 21cc5bfbf3079f194f7bad44e87146da5a986226) @@ -116,6 +116,14 @@ self.can_interface.register_receiving_publication_function(DenaliChannels.hd_to_dialin_ch_id, msg_id, self._handler_treatment_current_parameters) + self.hd_treatment_time_timestamp = 0.0 + self.hd_treatment_state_timestamp = 0.0 + self.hd_saline_bolus_timestamp = 0.0 + self.hd_rinseback_progress_timestamp = 0.0 + self.hd_blood_prime_progress_timestamp = 0.0 + self.hd_recirc_progress_timestamp = 0.0 + self.hd_treatment_stop_timer_data_timestamp = 0.0 + self.hd_res_current_treatment_parameters_timestamp = 0.0 # treatment duration data self.treatment_time_prescribed = 0 self.treatment_time_elapsed = 0 @@ -462,11 +470,12 @@ @publish([ + "hd_treatment_time_timestamp", "treatment_time_prescribed", "treatment_time_elapsed", "treatment_time_remaining" ]) - def _handler_treatment_time_sync(self, message): + def _handler_treatment_time_sync(self, message, timestamp=0.0): """ Handles published treatment time data messages. treatment time data are captured for reference. @@ -485,8 +494,10 @@ self.treatment_time_prescribed = tot[0] self.treatment_time_elapsed = ela[0] self.treatment_time_remaining = rem[0] + self.hd_treatment_time_timestamp = timestamp @publish([ + "hd_treatment_state_timestamp", "treatment_state", "treatment_uf_state", "saline_bolus_state", @@ -498,7 +509,7 @@ "treatment_stop_state", "dialysis_state" ]) - def _handler_treatment_state_sync(self, message): + def _handler_treatment_state_sync(self, message, timestamp=0.0): """ Handles published treatment state data messages. treatment state data are captured for reference. @@ -538,13 +549,15 @@ self.treatment_end_state = txe[0] self.treatment_stop_state = txs[0] self.dialysis_state = dia[0] + self.hd_treatment_state_timestamp = timestamp @publish([ + "hd_saline_bolus_timestamp", "saline_bolus_max_vol", "saline_bolus_cum_vol", "saline_bolus_bol_vol" ]) - def _handler_saline_bolus_data_sync(self, message): + def _handler_saline_bolus_data_sync(self, message, timestamp=0.0): """ Handles published saline bolus data messages. Saline bolus data are captured for reference. @@ -563,15 +576,17 @@ self.saline_bolus_max_vol = mxm[0] self.saline_bolus_cum_vol = cum[0] self.saline_bolus_bol_vol = bol[0] + self.hd_saline_bolus_timestamp = timestamp @publish([ + "hd_rinseback_progress_timestamp", "rinseback_tgt_vol", "rinseback_cum_vol", "rinseback_cur_rate", "rinseback_timeout_secs", "rinseback_countdown_secs" ]) - def _handler_rinseback_data_sync(self, message): + def _handler_rinseback_data_sync(self, message, timestamp=0.0): """ Handles published rinseback data (progress) messages. Rinseback data are captured for reference. @@ -596,12 +611,14 @@ self.rinseback_cur_rate = rat[0] self.rinseback_timeout_secs = tmo[0] self.rinseback_countdown_secs = cdn[0] + self.hd_rinseback_progress_timestamp = timestamp @publish([ + "hd_blood_prime_progress_timestamp", "blood_prime_tgt_vol", "blood_prime_cum_vol" ]) - def _handler_blood_prime_data_sync(self, message): + def _handler_blood_prime_data_sync(self, message, timestamp=0.0): """ Handles published blood prime data (progress) messages. Blood prime data are captured for reference. @@ -617,12 +634,14 @@ self.blood_prime_tgt_vol = tgt[0] self.blood_prime_cum_vol = cum[0] + self.hd_blood_prime_progress_timestamp = timestamp @publish([ + "hd_recirc_progress_timestamp", "recirc_timeout_secs", "recirc_countdown_secs" ]) - def _handler_recirculate_data_sync(self, message): + def _handler_recirculate_data_sync(self, message, timestamp=0.0): """ Handles published recirculate data (progress) messages. Recirculate data are captured for reference. @@ -638,9 +657,10 @@ self.recirc_timeout_secs = tmo[0] self.recirc_countdown_secs = cdn[0] + self.hd_recirc_progress_timestamp = timestamp - @publish(["treatment_stop_timeout_secs", "treatment_stop_timeout_countdown_secs"]) - def _handler_treatment_stop_timer_data_sync(self, message) -> None: + @publish(["hd_treatment_stop_timer_data_timestamp","treatment_stop_timeout_secs", "treatment_stop_timeout_countdown_secs"]) + def _handler_treatment_stop_timer_data_sync(self, message, timestamp=0.0) -> None: """ Handles published treatment stop progress data messages. @@ -655,15 +675,16 @@ self.treatment_stop_timeout_secs = tmo[0] self.treatment_stop_timeout_countdown_secs = cnd[0] + self.hd_treatment_stop_timer_data_timestamp = timestamp - @publish(["accepted", "current_blood_flow", "current_dialysate_flow", + @publish(["hd_res_current_treatment_parameters_timestamp", "accepted", "current_blood_flow", "current_dialysate_flow", "current_treatment_duration", "current_heparin_pre_stop", "current_saline_bolus_volume", "current_acid_concentrate", "current_bicarb_concentrate", "current_dialyzer_type", "current_heparin_type", "current_blood_pressure_measurement_interval", "current_rinseback_flow_rate", "current_arterial_low", "current_arterial_high", "current_venous_low", "current_venous_high", "current_heparin_bolus", "current_heparin_dispense", "current_dialysate_temp", "current_uf_volume"]) - def _handler_treatment_current_parameters(self, message) -> None: + def _handler_treatment_current_parameters(self, message, timestamp=0.0) -> None: """ Handles published current treatment parameters messages. @@ -731,6 +752,7 @@ self.current_heparin_dispense = hepdispense[0] self.current_dialysate_temp = dialtemp[0] self.current_uf_volume = ufvol[0] + self.hd_res_current_treatment_parameters_timestamp = timestamp def cmd_set_treatment_param_blood_flow_rate(self, flow: int) -> int: """ Index: dialin/protocols/CAN.py =================================================================== diff -u -r8ab23ed705264e4cdc7e43689d01f9c243ed612b -r21cc5bfbf3079f194f7bad44e87146da5a986226 --- dialin/protocols/CAN.py (.../CAN.py) (revision 8ab23ed705264e4cdc7e43689d01f9c243ed612b) +++ dialin/protocols/CAN.py (.../CAN.py) (revision 21cc5bfbf3079f194f7bad44e87146da5a986226) @@ -661,7 +661,7 @@ for function_id in self.sync_response_dictionary[dialin_ch_id][dialin_msg_id]: self.thread_pool_executor.submit( self.sync_response_dictionary[dialin_ch_id][dialin_msg_id][function_id], - complete_dialin_message) + complete_dialin_message, message.timestamp) self.message_queue_mutex.release() else: self.logger.critical("Invalid message: {}\n".format(self.messages))