Index: dialin/squish/denaliMessages.py =================================================================== diff -u -r87cf0bc784212d2608c58d1388b37396aa0a4656 -rccc07090d6993ade7fc1d9ea12e7601ca6d9a9ef --- dialin/squish/denaliMessages.py (.../denaliMessages.py) (revision 87cf0bc784212d2608c58d1388b37396aa0a4656) +++ dialin/squish/denaliMessages.py (.../denaliMessages.py) (revision ccc07090d6993ade7fc1d9ea12e7601ca6d9a9ef) @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- ########################################################################### # # Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. @@ -7,8 +8,8 @@ # # @file denaliMessages.py # -# @author (last) Peter Lucia -# @date (last) 09-Jul-2020 +# @author (last) Behrouz NematiPour +# @date (last) 20-Oct-2020 # @author (original) Peter Lucia # @date (original) 09-Jul-2020 # @@ -21,211 +22,355 @@ from dialin.squish import messageBuilder +class txStates: + # Saline states + SALINE_BOLUS_STATE_IDLE = 0 # No saline bolus delivery is in progress + SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP = 1 # Wait for pumps to stop before starting bolus + SALINE_BOLUS_STATE_IN_PROGRESS = 2 # A saline bolus delivery is in progress + SALINE_BOLUS_STATE_MAX_DELIVERED = 3 # Maximum saline bolus volume reached - no more saline bolus deliveries allowed + + # UF states + # UI only cares about the actual state and _NOT could be any other state + UF_PAUSED_STATE_NOT = 0 + UF_PAUSED_STATE = 1 + + # Sub Mode + # UI only cares about the actual state and _NOT could be any other state + TREATMENT_DIALYSIS_STATE_NOT = 0 + TREATMENT_DIALYSIS_STATE = 1 + + class EResponse: Rejected = 0 Accepted = 1 class GuiActionType: - Unknown = 0 - PowerOff = 1 - KeepAlive = 7 - BloodFlow = 5 - DialysateInletFlow = 8 - DialysateOutletFlow = 11 - TreatmentTime = 13 - PowerOffBroadcast = 14 + Unknown = 0 + PowerOff = 1 + KeepAlive = 7 + BloodFlow = 5 + DialysateInletFlow = 8 + DialysateOutletFlow = 11 + TreatmentTime = 13 + PowerOffBroadcast = 14 - AlarmStatus = 2 - AlarmTriggered = 3 - AlarmCleared = 4 + AlarmStatus = 2 + AlarmTriggered = 3 + AlarmCleared = 4 - PressureOcclusion = 9 + PressureOcclusion = 9 - DGDrainPumpData = 36 - DGHeatersData = 44 - LoadCellReadings = 12 - DGPressuresData = 32 - TemperatureSensors = 45 + DGDrainPumpData = 36 + DGHeatersData = 44 + LoadCellReadings = 12 + DGPressuresData = 32 + TemperatureSensors = 45 + + CanBUSFaultCount = 2457 + HDDebugText = 0xFFF1 + DGDebugText = 0xFFF2 - CanBUSFaultCount = 2457 - HDDebugText = 0xFFF1 - DGDebugText = 0xFFF2 + AdjustBloodDialysateReq = 23 + AdjustBloodDialysateRsp = 24 - AdjustBloodDialysateReq = 23 - AdjustBloodDialysateRsp = 24 + AdjustDurationReq = 22 + AdjustDurationRsp = 27 - AdjustDurationReq = 22 - AdjustDurationRsp = 27 - - AdjustUltrafiltrationStateReq = 16 # Req and Rsp are the same in this specific message - - AdjustUltrafiltrationEditReq = 17 - AdjustUltrafiltrationEditRsp = 19 - + AdjustUltrafiltrationStateReq = 16 # Req and Rsp are the same in this specific message + AdjustUltrafiltrationEditReq = 17 + AdjustUltrafiltrationEditRsp = 19 AdjustUltrafiltrationConfirmReq = 21 AdjustUltrafiltrationConfirmRsp = 46 - TreatmentRanges = 26 + TreatmentRanges = 26 - String = 65279 + String = 65279 + Acknow = 65535 + AcknowGeneric = 0 # Generic Acknowledgment is not a unique message ID and inherits its Id from the actual message. Zero is a placeholder - Acknow = 65535 - AcknowGeneric = 0 # Generic Acknowledgment is not a unique message ID and inherits its Id from the actual message. Zero is a placeholder - - def send_acknowledge_HD(): + """ + the acknowledge from HD + :return: none + """ subprocess.call(['cansend', 'can0', '020#A5.01.00.FF.FF.00.19.00']) def send_acknowledge_UI(): + """ + the acknowledge from UI + :return: none + """ subprocess.call(['cansend', 'can0', '100#A5.01.00.FF.FF.00.19.00']) def send_CheckIn_DG(): + """ + check-in (keep alive) message from DG + :return: none + """ subprocess.call(['cansend', 'can0', '010#A5.01.00.06.00.00.76.00']) def show_PowerOffDialog(): + """ + the message from HD to UI to show the power off dialog + :return: none + """ subprocess.call(['cansend', 'can0', '020#A5.01.00.01.00.01.00.38']) def hide_PowerOffDialog(): + """ + the message from HD to UI to hide the power off dialog + :return: none + """ subprocess.call(['cansend', 'can0', '020#A5.01.00.01.00.01.01.09']) def show_PowerOffNotificationDialog(): + """ + the message from HD to UI to shew the shutting down notipication box + :return: none + """ subprocess.call(['cansend', 'can0', '040#A5.01.00.0E.00.00.24.00']) def show_PowerOffRejectionDialog(): + """ + the message from HD to UI to show the power off dialog + :return: none + """ subprocess.call(['cansend', 'can0', '020#A5.01.00.01.00.01.02.5A']) -################################################################################################## -# After each multi-frame message put a 100ms sleep, time.sleep(0.1) # -# it seems it's needed otherwise the test will check a value which has not been received yet. # -################################################################################################## def waitForMessageToBeSent(): - time.sleep(0.050) # 50ms + """ + After each multi-frame message put a 100ms sleep, time.sleep(0.1) # + it seems it's needed otherwise the test will check a value which has not been received yet. # + :return: none + """ + time.sleep(0.050) # 50ms -## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def buildHDDebugText(vText): + """ + the debug text message from HD builder method + :param vText: (str) the debug text + :return: none + """ len = 40 - txt = messageBuilder.textToByte(vText, len) # + 1 null term - msg = messageBuilder.buildMessage(GuiActionType.HDDebugText, 1 * (len + 1), False, txt) + txt = messageBuilder.textToByte(vText, len) # + 1 null term + msg = messageBuilder.buildMessage( GuiActionType.HDDebugText, 1 * (len + 1), False, txt) return messageBuilder.toFrames(msg) -## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -def setHDDebugText(vText): +def setHDDebugText (vText): + """ + the debug text message from HD setter/sender method + :param vText: (str) the debug text + :return: none + """ frames = buildHDDebugText(vText) frames = messageBuilder.toCandumpFormat(frames) for frame in frames: subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) waitForMessageToBeSent() -## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def buildDGDebugText(vText): + """ + the debug text message from DG builder method + :param vText: (str) the debug text + :return: none + """ len = 40 - txt = messageBuilder.textToByte(vText, len) # + 1 null term - msg = messageBuilder.buildMessage(GuiActionType.DGDebugText, 1 * (len + 1), False, txt) + txt = messageBuilder.textToByte(vText, len) # + 1 null term + msg = messageBuilder.buildMessage( GuiActionType.DGDebugText, 1 * (len + 1), False, txt) return messageBuilder.toFrames(msg) -## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -def setDGDebugText(vText): +def setDGDebugText (vText): + """ + the debug text message from DG setter/sender method + :param vText: (str) the debug text + :return: none + """ frames = buildDGDebugText(vText) frames = messageBuilder.toCandumpFormat(frames) for frame in frames: subprocess.call(['cansend', 'can0', '070#{}'.format(frame)]) waitForMessageToBeSent() -## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -def buildSetTreatmentParamRanges(vMinTreatmentDuration, vMaxTreatmentDuration, vMinUFVolume, vMaxUFVolume, - vMinDialysateFlowRate, vMaxDialysateFlowRate): +def buildSetTreatmentParamRanges(vMinTreatmentDuration, vMaxTreatmentDuration, vMinUFVolume, vMaxUFVolume, vMinDialysateFlowRate, vMaxDialysateFlowRate): + """ + the Treatment adjustment param ranges data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #3:(F32) | #4:(F32) | #5:(U32) | #6:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: |:--: |:--: | + |0x1A00| 0x020 | 6 | 1/60 Hz| Y | HD | UI | Treatment adjustment param ranges Data | \ref Data::mDuration_Min | \ref Data::mDuration_Max | \ref Data::mUltrafiltration_Volume_Min | \ref Data::mUltrafiltration_Volume_Max | \ref Data::mDialysate_Flow_Min | \ref Data::mDialysate_Flow_Max | + :param vMinTreatmentDuration: (int) Min Treatment Duration + :param vMaxTreatmentDuration: (int) Max Treatment Duration + :param vMinUFVolume: (float) Min UF Volume + :param vMaxUFVolume: (float) Max UF Volume + :param vMinDialysateFlowRate: (int) Min Dialysate Flow Rate + :param vMaxDialysateFlowRate: (int) Max Dialysate Flow Rate + :return: (str) built message frame(s) + """ msg = messageBuilder.buildMessage(GuiActionType.TreatmentRanges, 4 * 6, True, - utils.toI32(vMinTreatmentDuration), - utils.toI32(vMaxTreatmentDuration), - utils.toF32(vMinUFVolume), - utils.toF32(vMaxUFVolume), - utils.toI32(vMinDialysateFlowRate), - utils.toI32(vMaxDialysateFlowRate) - ) + utils.toI32(vMinTreatmentDuration), + utils.toI32(vMaxTreatmentDuration), + utils.toF32(vMinUFVolume ), + utils.toF32(vMaxUFVolume ), + utils.toI32(vMinDialysateFlowRate), + utils.toI32(vMaxDialysateFlowRate) + ) return messageBuilder.toFrames(msg) -def setTreatmentParamRanges(vMinTreatmentDuration, vMaxTreatmentDuration, vMinUFVolume, vMaxUFVolume, - vMinDialysateFlowRate, vMaxDialysateFlowRate): - frames = buildSetTreatmentParamRanges(vMinTreatmentDuration, vMaxTreatmentDuration, vMinUFVolume, vMaxUFVolume, - vMinDialysateFlowRate, vMaxDialysateFlowRate) +def setTreatmentParamRanges(vMinTreatmentDuration, vMaxTreatmentDuration, vMinUFVolume, vMaxUFVolume, vMinDialysateFlowRate, vMaxDialysateFlowRate): + """ + the Treatment adjustment param ranges data message setter/sender method + :param vMinTreatmentDuration: (int) Min Treatment Duration + :param vMaxTreatmentDuration: (int) Max Treatment Duration + :param vMinUFVolume: (float) Min UF Volume + :param vMaxUFVolume: (float) Max UF Volume + :param vMinDialysateFlowRate: (int) Min Dialysate Flow Rate + :param vMaxDialysateFlowRate: (int) Max Dialysate Flow Rate + :return: none + """ + frames = buildSetTreatmentParamRanges(vMinTreatmentDuration, vMaxTreatmentDuration, vMinUFVolume, vMaxUFVolume, vMinDialysateFlowRate, vMaxDialysateFlowRate) frames = messageBuilder.toCandumpFormat(frames) for frame in frames: subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) waitForMessageToBeSent() def buildSetTreatmentBloodFlowRate(vFlowSetPt, vMeasFlow, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM): + """ + the Blood Flow Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(S32) | #2:(F32) | #3:(F32) | #4:(F32) | #5:(F32) | #6:(F32) | #7:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: |:--: |:--: |:--: | + |0x0500| 0x040 | 7 | 1 Hz | N | HD | All | Blood Flow Data | \ref Data::mFlowSetPoint | \ref Data::mMeasuredFlow | \ref Data::mRotorSpeed | \ref Data::mMotorSpeed | \ref Data::mMotorCtlSpeed | \ref Data::mMotorCtlCurrent | \ref Data::mPWMDutyCycle | + :param vFlowSetPt: (signed int) Flow Set Point + :param vMeasFlow: (float) Measured Flow + :param vRotSpd: (float) Rot Speed + :param vMotSpd: (float) Motor Speed + :param vMCSpd: (float) MC Speed + :param vMCCurr: (float) MC Current + :param vPWM: (float) PWM + :return: (str) built message frame(s) + """ msg = messageBuilder.buildMessage(GuiActionType.BloodFlow, 4 * 7, False, - utils.toI32(vFlowSetPt), - utils.toF32(vMeasFlow), - utils.toF32(vRotSpd), - utils.toF32(vMotSpd), - utils.toF32(vMCSpd), - utils.toF32(vMCCurr), - utils.toF32(vPWM) - ) + utils.toI32(vFlowSetPt ), + utils.toF32(vMeasFlow ), + utils.toF32(vRotSpd ), + utils.toF32(vMotSpd ), + utils.toF32(vMCSpd ), + utils.toF32(vMCCurr ), + utils.toF32(vPWM ) + ) return messageBuilder.toFrames(msg) def setTreatmentBloodFlowRate(vFlowSetPt, vMeasFlow, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM): + """ + the Blood Flow Data message setter/sender method + :param vFlowSetPt: (signed int) Flow Set Point + :param vMeasFlow: (float) Measured Flow + :param vRotSpd: (float) Rot Speed + :param vMotSpd: (float) Motor Speed + :param vMCSpd: (float) MC Speed + :param vMCCurr: (float) MC Current + :param vPWM: (float) PWM + :return: none + """ frames = buildSetTreatmentBloodFlowRate(vFlowSetPt, vMeasFlow, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM) frames = messageBuilder.toCandumpFormat(frames) for frame in frames: subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) waitForMessageToBeSent() + - def buildSetTreatmentDialysateFlowRate(vFlowSetPt, vMeasFlow, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM): + """ + the Dialysate Flow Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(S32) | #2:(F32) | #3:(F32) | #4:(F32) | #5:(F32) | #6:(F32) | #7:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: |:--: |:--: |:--: | + |0x0800| 0x040 | 7 | 1 Hz | N | HD | All | Dialysate Flow Data | mFlowSetPoint | mMeasuredFlow | mRotorSpeed | mMotorSpeed | mMotorCtlSpeed | mMotorCtlCurrent | mPWMDutyCycle | + :param vFlowSetPt: (signed int) Flow Set Point + :param vMeasFlow: (float) Measured Flow + :param vRotSpd: (float) Rot Speed + :param vMotSpd: (float) Motor Speed + :param vMCSpd: (float) MC Speed + :param vMCCurr: (float) MC Current + :param vPWM: (float) PWM + :return: (str) built message frame(s) + """ msg = messageBuilder.buildMessage(GuiActionType.DialysateInletFlow, 4 * 7, False, - utils.toI32(vFlowSetPt), - utils.toF32(vMeasFlow), - utils.toF32(vRotSpd), - utils.toF32(vMotSpd), - utils.toF32(vMCSpd), - utils.toF32(vMCCurr), - utils.toF32(vPWM) - ) + utils.toI32(vFlowSetPt), + utils.toF32(vMeasFlow), + utils.toF32(vRotSpd), + utils.toF32(vMotSpd), + utils.toF32(vMCSpd), + utils.toF32(vMCCurr), + utils.toF32(vPWM) + ) return messageBuilder.toFrames(msg) def setTreatmentDialysateFlowRate(vFlowSetPt, vMeasFlow, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM): + """ + the Dialysate Flow Data message setter/sender method + :param vFlowSetPt: (signed int) Flow Set Point + :param vMeasFlow: (float) Measured Flow + :param vRotSpd: (float) Rot Speed + :param vMotSpd: (float) Motor Speed + :param vMCSpd: (float) MC Speed + :param vMCCurr: (float) MC Current + :param vPWM: (float) PWM + :return: none + """ frames = buildSetTreatmentDialysateFlowRate(vFlowSetPt, vMeasFlow, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM) frames = messageBuilder.toCandumpFormat(frames) for frame in frames: subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) waitForMessageToBeSent() - + def buildTreatmentAdjustBloodDialysateResponse(vAccepted, vReason, vBloodRate, vDialysate): + """ + the Blood/dialysate rate change Response message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #3:(U32) | #4:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: | + |0x1800| 0x020 | 6 | Rsp | Y | HD | UI | Blood/dialysate rate change Response | \ref Data::mAccepted | \ref Data::mReason | \ref Data::mBloodRate | \ref Data::mDialysateRate | + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vBloodRate: (int) Blood Flow Rate + :param vDialysate: (int) Dialysate Flow Rate + :return: (str) built message frame(s) + """ msg = messageBuilder.buildMessage(GuiActionType.AdjustBloodDialysateRsp, 4 * 4, True, - utils.toI32(vAccepted), - utils.toI32(vReason), - utils.toI32(vBloodRate), - utils.toI32(vDialysate) - ) + utils.toI32(vAccepted), + utils.toI32(vReason), + utils.toI32(vBloodRate), + utils.toI32(vDialysate) + ) return messageBuilder.toFrames(msg) def sendTreatmentAdjustBloodDialysateResponse(vAccepted, vReason, vBloodRate, vDialysate): + """ + the Blood/dialysate rate change Response message setter/sender method + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vBloodRate: (int) Blood Flow Rate + :param vDialysate: (int) Dialysate Flow Rate + :return: none + """ frames = buildTreatmentAdjustBloodDialysateResponse(vAccepted, vReason, vBloodRate, vDialysate) frames = messageBuilder.toCandumpFormat(frames) for frame in frames: @@ -234,16 +379,35 @@ def buildTreatmentAdjustDurationResponse(vAccepted, vReason, vDuration, vUltrafiltration): + """ + the Treatment Duration change Response message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #3:(U32) | #5:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: | + |0x1B00| 0x020 | 6 | Rsp | Y | HD | UI | Treatment Duration change Response | \ref Data::mAccepted | \ref Data::mReason | \ref Data::mDuration | \ref Data::mUFVolume | + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vDuration: (int) Treatment Duration + :param vUltrafiltration: (float) Ultrafiltration Volume + :return: (str) built message frame(s) + """ msg = messageBuilder.buildMessage(GuiActionType.AdjustDurationRsp, 4 * 4, True, - utils.toI32(vAccepted), - utils.toI32(vReason), - utils.toI32(vDuration), - utils.toF32(vUltrafiltration) - ) + utils.toI32(vAccepted), + utils.toI32(vReason), + utils.toI32(vDuration), + utils.toF32(vUltrafiltration) + ) return messageBuilder.toFrames(msg) def sendTreatmentAdjustDurationResponse(vAccepted, vReason, vDuration, vUltrafiltration): + """ + the Treatment Duration change Response message setter/sender method + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vDuration: (int) Treatment Duration + :param vUltrafiltration: (float) Ultrafiltration Volume + :return: none + """ frames = buildTreatmentAdjustDurationResponse(vAccepted, vReason, vDuration, vUltrafiltration) frames = messageBuilder.toCandumpFormat(frames) for frame in frames: @@ -252,13 +416,27 @@ def buildTreatmentAdjustUltrafiltrationStateResponse(vState): - msg = messageBuilder.buildMessage(GuiActionType.AdjustUltrafiltrationStateReq, 1 * 4, False, - utils.toI32(vState) - ) + """ + the Treatment ultrafiltration adjustment response message builder method + | MSG | CAN ID | M.Box | Type | Ack | Src | Dest | Description | #1:(U08) | + |:----:|:------:|:-----:|:----:|:---:|:---:|:----:|:-----------: |:--: | + |0x1000| 0x100 | 9 | Rsp | N | HD | UI | Generic response ACK/NAK | mAccepted | + :param vState: (-128