Index: TD_IsolatedUF/interface.ui =================================================================== diff -u --- TD_IsolatedUF/interface.ui (revision 0) +++ TD_IsolatedUF/interface.ui (revision 4e52f6341607d9780adf49283b378413291faaf1) @@ -0,0 +1,403 @@ + + + ui_interface + + + + 0 + 0 + 465 + 142 + + + + + 100000 + 100000 + + + + + 10 + + + + &3 Treatment/&6 Isolated UF + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + 10 + + + + color: rgb(238, 238, 236); +background-color: rgb(92, 53, 102); + + + 144 [0x9000]: Isolated UF Data + + + Qt::AlignCenter + + + + + + + Send + + + + + + + Reset + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 6 + + + 6 + + + + + Duration (min) + + + + + + + Volume Goal (mL) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + 250 + 0 + + + + 10000 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 10 + + + + 0 + + + Qt::AlignCenter + + + + + + + + + Volume Delivered (mL) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + 250 + 0 + + + + 10000 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 10 + + + + 0 + + + Qt::AlignCenter + + + + + + + + + 2 + + + 2 + + + 2 + + + + + 0 + + + 500 + + + 0 + + + Qt::Horizontal + + + + + + + + 50 + 0 + + + + 0 + + + Qt::AlignCenter + + + + + + + + + Rate (mL/Hr) + + + + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 3000 + + + Qt::Horizontal + + + + + + + + 50 + 0 + + + + 0 + + + Qt::AlignCenter + + + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + + Index: TD_IsolatedUF/loader.py =================================================================== diff -u --- TD_IsolatedUF/loader.py (revision 0) +++ TD_IsolatedUF/loader.py (revision 4e52f6341607d9780adf49283b378413291faaf1) @@ -0,0 +1,98 @@ +""" + TD Isolated UF UI Loader +""" +# Python +import os +import can +import struct + +# Qt +from PySide2 import QtCore, QtWidgets +from PySide2.QtCore import Slot + +# parent +from engine.dynamicloader import DynamicLoader + +# plugin specific +from leahi_dialin.common.msg_defs import MsgIds, MsgFieldPositions +from leahi_dialin.protocols import CAN +from leahi_dialin.utils import conversions + +# hd Simulator +from leahi_dialin.ui.td_messaging import TD_Messaging + +class Loader(DynamicLoader): + """ + TD Isolated UF UI Loader + """ + + def __init__(self): + self.td_interface = TD_Messaging() + self.can_interface = self.td_interface.can_interface + super().__init__(os.path.dirname(__file__)) + + + def _init_loader(self): + """ + finds and creates widgets + :return: none + """ + self.tbSend = self.find_widget(QtWidgets.QToolButton , 'tbSend' ) + self.tbReset = self.find_widget(QtWidgets.QToolButton , 'tbReset' ) + + self.slDuration = self.find_widget(QtWidgets.QSlider , 'slDuration' ) + self.lbDuration = self.find_widget(QtWidgets.QLabel , 'lbDuration' ) + self.slVolumeGoal = self.find_widget(QtWidgets.QSlider , 'slVolumeGoal' ) + self.lbVolumeGoal = self.find_widget(QtWidgets.QLabel , 'lbVolumeGoal' ) + self.slVolumeDelivered = self.find_widget(QtWidgets.QSlider , 'slVolumeDelivered' ) + self.lbVolumeDelivered = self.find_widget(QtWidgets.QLabel , 'lbVolumeDelivered' ) + self.slRate = self.find_widget(QtWidgets.QSlider , 'slRate' ) + self.lbRate = self.find_widget(QtWidgets.QLabel , 'lbRate' ) + + + def _init_connections(self): + """ + initializes the widgets connections + :return: none + """ + self.tbSend .clicked .connect(self.do_send) + self.tbReset .clicked .connect(self.do_reset) + self.slDuration .valueChanged .connect(self.do_send) + self.slDuration .valueChanged .connect(lambda value: self.lbDuration.setText(f"{value}")) + self.slVolumeGoal .valueChanged .connect(self.do_send) + self.slVolumeGoal .valueChanged .connect(lambda value: self.lbVolumeGoal.setText(f"{value}")) + self.slVolumeDelivered .valueChanged .connect(self.do_send) + self.slVolumeDelivered .valueChanged .connect(lambda value: self.lbVolumeDelivered.setText(f"{value}")) + self.slRate .valueChanged .connect(self.do_send) + self.slRate .valueChanged .connect(lambda value: self.lbRate.setText(f"{value}")) + + + @Slot() + def _init_widgets(self): + """ + initializes the widgets' properties + :return: none + """ + self.do_reset() + + + @Slot() + def do_send(self): + """ + slot for sending blood prime data + :return: none + """ + self.td_interface.td_isolated_uf( + self.slDuration.value(), + self.slVolumeGoal.value(), + self.slVolumeDelivered.value(), + self.slRate.value(), + ) + + + @Slot() + def do_reset(self): + self.slDuration .setValue(0) + self.slVolumeGoal .setValue(0) + self.slVolumeDelivered .setValue(0) + self.slRate .setValue(0) Index: TD_TreatmentAdjustmentsIsolatedUF/interface.ui =================================================================== diff -u --- TD_TreatmentAdjustmentsIsolatedUF/interface.ui (revision 0) +++ TD_TreatmentAdjustmentsIsolatedUF/interface.ui (revision 4e52f6341607d9780adf49283b378413291faaf1) @@ -0,0 +1,669 @@ + + + ui_interface + + + + 0 + 0 + 442 + 400 + + + + + 100000 + 100000 + + + + + 10 + + + + &3 Treatment/Adjustments/&6 Isolated UF + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 20 + + + + + 10 + + + + color: rgb(238, 238, 236); +background-color: rgb(92, 53, 102); + + + + Isolated UF Adjustment + + + Qt::AlignCenter + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + color: rgb(238, 238, 236); +background-color: rgb(92, 53, 102); + + + 146: [0x9200]: Duration Change Response + + + Qt::AlignCenter + + + + + + + Send + + + + + + + Reset + + + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Req [0x9100] +Duration (min) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 10 + + + + QFrame::Box + + + QFrame::Raised + + + -- -- + + + Qt::AlignCenter + + + + + + + Reject Reason + + + + + + + Qt::AlignCenter + + + + + + + Volume Goal Max (mL) + + + + + + + + + 8000 + + + Qt::Horizontal + + + + + + + + 50 + 0 + + + + 0 + + + Qt::AlignCenter + + + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + + 10 + + + + color: rgb(238, 238, 236); +background-color: rgb(92, 53, 102); + + + 148: [0x9400]: Volume Goal Change Response + + + Qt::AlignCenter + + + + + + + Send + + + + + + + Copy + + + + + + + Reset + + + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Req [0x9300] + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Reject Reason + + + + + + + Qt::AlignCenter + + + + + + + Volume Goal (mL) + + + + + + + + + + 250 + 0 + + + + 8000 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 10 + + + + 0 + + + Qt::AlignCenter + + + + + + + + + Duration (min) + + + + + + + + + + 250 + 0 + + + + 480 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 10 + + + + 0 + + + Qt::AlignCenter + + + + + + + + + Rate (mL/Hr) + + + + + + + + + 2000 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 10 + + + + 0 + + + Qt::AlignCenter + + + + + + + + + QFrame::Box + + + QFrame::Sunken + + + -- -- + + + Qt::AlignCenter + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + + 0 + 0 + + + + + 10 + + + + color: rgb(238, 238, 236); +background-color: rgb(92, 53, 102); + + + 150: [0x9600]: Confirm Response + + + Qt::AlignCenter + + + + + + + Send + + + + + + + Reset + + + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + Req [0x9500] + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 10 + + + + QFrame::Box + + + QFrame::Raised + + + -- -- + + + Qt::AlignCenter + + + + + + + Reject Reason + + + + + + + Qt::AlignCenter + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + + Index: TD_TreatmentAdjustmentsIsolatedUF/loader.py =================================================================== diff -u --- TD_TreatmentAdjustmentsIsolatedUF/loader.py (revision 0) +++ TD_TreatmentAdjustmentsIsolatedUF/loader.py (revision 4e52f6341607d9780adf49283b378413291faaf1) @@ -0,0 +1,240 @@ +""" + TD Isolated UF UI Loader +""" +# Python +import os +import can +import struct +import datetime + +# Qt +from PySide2 import QtCore, QtWidgets +from PySide2.QtCore import Slot + +# parent +from engine.dynamicloader import DynamicLoader + +# plugin specific +from leahi_dialin.common.msg_defs import MsgIds, MsgFieldPositions +from leahi_dialin.protocols import CAN +from leahi_dialin.utils import conversions + +from leahi_dialin.common.td_defs import TDOpModes +from leahi_dialin.common.td_defs import TDStandbyStates + +# hd Simulator +from leahi_dialin.ui.td_messaging import TD_Messaging + +class Loader(DynamicLoader): + """ + TD Isolated UF UI Loader + """ + def __init__(self): + self.td_interface = TD_Messaging() + self.can_interface = self.td_interface.can_interface + super().__init__(os.path.dirname(__file__)) + + if self.can_interface is not None: + self.can_interface.register_receiving_publication_function( + CAN.DenaliChannels.ui_to_td_ch_id, + MsgIds.MSG_ID_UI_ISOLATED_UF_DURATION_CHANGE_REQUEST.value, + self.handle_duration_request) + self.can_interface.register_receiving_publication_function( + CAN.DenaliChannels.ui_to_td_ch_id, + MsgIds.MSG_ID_UI_ISOLATED_UF_VOLUME_GOAL_CHANGE_REQUEST.value, + self.handle_volume_goal_request) + self.can_interface.register_receiving_publication_function( + CAN.DenaliChannels.ui_to_td_ch_id, + MsgIds.MSG_ID_UI_ISOLATED_UF_CONFIRM_REQUEST.value, + self.handle_confirm_request) + + + def _init_loader(self): + """ + finds and creates widgets + :return: none + """ + self.tbDurationRspSend = self.find_widget(QtWidgets.QToolButton , 'tbDurationRspSend' ) + self.tbDurationRspReset = self.find_widget(QtWidgets.QToolButton , 'tbDurationRspReset' ) + self.lbDurationReq = self.find_widget(QtWidgets.QLabel , 'lbDurationReq' ) + self.sbDurationRspRejectReason = self.find_widget(QtWidgets.QSpinBox , 'sbDurationRspRejectReason' ) + self.slDurationRspVolumeGoalMax = self.find_widget(QtWidgets.QSlider , 'slDurationRspVolumeGoalMax' ) + self.lbDurationRspVolumeGoalMax = self.find_widget(QtWidgets.QLabel , 'lbDurationRspVolumeGoalMax' ) + + self.tbVolumeGoalRspSend = self.find_widget(QtWidgets.QToolButton , 'tbVolumeGoalRspSend' ) + self.tbVolumeGoalRspCopy = self.find_widget(QtWidgets.QToolButton , 'tbVolumeGoalRspCopy' ) + self.tbVolumeGoalRspReset = self.find_widget(QtWidgets.QToolButton , 'tbVolumeGoalRspReset' ) + self.lbVolumeGoalReqParams = self.find_widget(QtWidgets.QLabel , 'lbVolumeGoalReqParams' ) + self.sbVolumeGoalRspRejectReason = self.find_widget(QtWidgets.QSpinBox , 'sbVolumeGoalRspRejectReason' ) + self.slVolumeGoalRspVolumeGoal = self.find_widget(QtWidgets.QSlider , 'slVolumeGoalRspVolumeGoal' ) + self.lbVolumeGoalRspVolumeGoal = self.find_widget(QtWidgets.QLabel , 'lbVolumeGoalRspVolumeGoal' ) + self.slVolumeGoalRspDuration = self.find_widget(QtWidgets.QSlider , 'slVolumeGoalRspDuration' ) + self.lbVolumeGoalRspDuration = self.find_widget(QtWidgets.QLabel , 'lbVolumeGoalRspDuration' ) + self.slVolumeGoalRspRate = self.find_widget(QtWidgets.QSlider , 'slVolumeGoalRspRate' ) + self.lbVolumeGoalRspRate = self.find_widget(QtWidgets.QLabel , 'lbVolumeGoalRspRate' ) + + self.tbConfirmRspSend = self.find_widget(QtWidgets.QToolButton , 'tbConfirmRspSend' ) + self.tbConfirmRspReset = self.find_widget(QtWidgets.QToolButton , 'tbConfirmRspReset' ) + self.lbConfirmReqTimestamp = self.find_widget(QtWidgets.QLabel , 'lbConfirmReqTimestamp' ) + self.sbConfirmRspRejectReason = self.find_widget(QtWidgets.QSpinBox , 'sbConfirmRspRejectReason' ) + + + def _init_connections(self): + """ + initializes the widgets connections + :return: none + """ + self.tbDurationRspSend .clicked .connect(self.do_duration_response) + self.tbDurationRspReset .clicked .connect(self.init_duration_response) + self.slDurationRspVolumeGoalMax .valueChanged .connect(lambda value: self.lbDurationRspVolumeGoalMax.setText(f"{value}")) + + self.tbVolumeGoalRspSend .clicked .connect(self.do_volume_goal_response) + self.tbVolumeGoalRspCopy .clicked .connect(self.copy_volume_goal_response) + self.tbVolumeGoalRspReset .clicked .connect(self.init_volume_goal_response) + self.slVolumeGoalRspVolumeGoal .valueChanged .connect(lambda value: self.lbVolumeGoalRspVolumeGoal.setText(f"{value}")) + self.slVolumeGoalRspDuration .valueChanged .connect(lambda value: self.lbVolumeGoalRspDuration.setText(f"{value}")) + self.slVolumeGoalRspRate .valueChanged .connect(lambda value: self.lbVolumeGoalRspRate.setText(f"{value}")) + + self.tbConfirmRspSend .clicked .connect(self.do_confirm_response) + self.tbConfirmRspReset .clicked .connect(self.init_confirm_response) + + + @Slot() + def _init_widgets(self): + """ + initializes the widgets' properties + :return: none + """ + self.init_duration_response() + self.init_volume_goal_response() + self.init_confirm_response() + + + @Slot() + def init_duration_response(self): + """ + slot for initializing Isolated UF duration change + :return: none + """ + self.lbDurationReq .setText("-- --") + self.sbDurationRspRejectReason .setValue(0) + self.slDurationRspVolumeGoalMax .setValue(0) + + + @Slot() + def handle_duration_request(self, message, timestamp = 0.0): + """ + Called when the user requests UF settings change to firmware from UI + @return: None + """ + message = message['message'] + index = MsgFieldPositions.START_POS_FIELD_1 + value,index = conversions.bytearray_to_integer(message, index) + self.lbDurationReq.setText(f"{value:.0f}") + + + @Slot() + def do_duration_response(self): + """ + slot for UF settings change + :return: none + """ + payload = conversions.integer_to_bytearray(1 if self.sbDurationRspRejectReason.value() == 0 else 0) + payload += conversions.integer_to_bytearray(self.sbDurationRspRejectReason.value()) + payload += conversions.integer_to_bytearray(self.slDurationRspVolumeGoalMax.value()) + + self.td_interface.cmd_send_general_response( + message_id = MsgIds.MSG_ID_TD_ISOLATED_UF_DURATION_CHANGE_RESPONSE.value, + accepted = 1 if self.sbDurationRspRejectReason.value() == 0 else 0, + reason = self.sbDurationRspRejectReason.value(), + is_pure_data = False, + has_parameters = True, + parameters_payload = payload + ) + + + @Slot() + def init_volume_goal_response(self): + """ + slot for initializing Isolated UF duration change + :return: none + """ + self.lbVolumeGoalReqParams .setText("-- --") + self.sbVolumeGoalRspRejectReason .setValue(0) + self.slVolumeGoalRspVolumeGoal .setValue(0) + self.slVolumeGoalRspDuration .setValue(0) + self.slVolumeGoalRspRate .setValue(0) + + + @Slot() + def handle_volume_goal_request(self, message, timestamp = 0.0): + """ + Called when the user requests UF settings change to firmware from UI + @return: None + """ + message = message['message'] + index = MsgFieldPositions.START_POS_FIELD_1 + self.reqDuration,index = conversions.bytearray_to_integer(message, index, False) + self.reqVolumeGoal,index = conversions.bytearray_to_integer(message, index, False) + self.lbVolumeGoalReqParams.setText(f"Duration (min) = {self.reqDuration}, Volume Goal (mL) = {self.reqVolumeGoal}") + + + @Slot() + def copy_volume_goal_response(self): + self.slVolumeGoalRspVolumeGoal .setValue(self.reqVolumeGoal) + self.slVolumeGoalRspDuration .setValue(self.reqDuration) + + + @Slot() + def do_volume_goal_response(self): + """ + slot for UF settings change + :return: none + """ + payload = conversions.integer_to_bytearray(1 if self.sbVolumeGoalRspRejectReason.value() == 0 else 0) + payload += conversions.integer_to_bytearray(self.sbVolumeGoalRspRejectReason.value()) + payload += conversions.integer_to_bytearray(self.slVolumeGoalRspVolumeGoal.value()) + payload += conversions.integer_to_bytearray(self.slVolumeGoalRspDuration.value()) + payload += conversions.integer_to_bytearray(self.slVolumeGoalRspRate.value()) + + self.td_interface.cmd_send_general_response( + message_id = MsgIds.MSG_ID_TD_ISOLATED_UF_VOLUME_GOAL_CHANGE_RESPONSE.value, + accepted = 1 if self.sbVolumeGoalRspRejectReason.value() == 0 else 0, + reason = self.sbVolumeGoalRspRejectReason.value(), + is_pure_data = False, + has_parameters = True, + parameters_payload = payload + ) + + + @Slot() + def init_confirm_response(self): + """ + slot for initializing UF pause/resume + :return: none + """ + self.lbConfirmReqTimestamp .setText("-- --") + self.sbConfirmRspRejectReason .setValue(0) + + + @Slot() + def handle_confirm_request(self, message, timestamp = 0.0): + """ + Called when the user requests pause/resume to firmware from UI + @return: None + """ + message = message['message'] + self.lbConfirmReqTimestamp.setText(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')}") + + + @Slot() + def do_confirm_response(self): + """ + slot for UF pause/resume + :return: none + """ + self.td_interface.cmd_send_general_response( + message_id = MsgIds.MSG_ID_TD_ISOLATED_UF_CONFIRM_RESPONSE.value, + accepted = 1 if self.sbConfirmRspRejectReason.value() == 0 else 0, + reason = self.sbConfirmRspRejectReason.value() + )