Index: dialin/ui/hd_simulator.py =================================================================== diff -u -rde50aa458cde12788863cbd940b70919e44259e6 -r5139daecb04d774c99f681c669a09741937f9c0f --- dialin/ui/hd_simulator.py (.../hd_simulator.py) (revision de50aa458cde12788863cbd940b70919e44259e6) +++ dialin/ui/hd_simulator.py (.../hd_simulator.py) (revision 5139daecb04d774c99f681c669a09741937f9c0f) @@ -17,10 +17,12 @@ import struct from time import sleep from typing import List +import time +import subprocess +from . import utils, messageBuilder from .hd_simulator_alarms import HDProxyAlarms from ..common.msg_defs import RequestRejectReasons, MsgIds -from ..hd.buttons import HDButtons from ..protocols.CAN import (DenaliMessage, DenaliCanMessenger, DenaliChannels) @@ -30,8 +32,6 @@ YES = 1 NO = 0 - - class TreatmentParameterRejections: def __init__(self): self.param_request_valid = RequestRejectReasons.REQUEST_REJECT_REASON_NONE @@ -74,6 +74,77 @@ self.__dict__[attr] = RequestRejectReasons.REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE +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 + UF_START_STATE = 0 # Start state of the ultrafiltration state machine + UF_PAUSED_STATE = 1 # Paused state of the ultrafiltration state machine + UF_RUNNING_STATE = 2 # Running state of the ultrafiltration state machine + UF_OFF_STATE = 3 # Completed/off state of the ultrafiltration state machine + UF_COMPLETED_STATE = 4 # Completed state of ultrafiltration state machine + + # 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 + + AlarmStatus = 2 + AlarmTriggered = 3 + AlarmCleared = 4 + + PressureOcclusion = 9 + + DGDrainPumpData = 36 + DGHeatersData = 44 + LoadCellReadings = 12 + DGPressuresData = 32 + TemperatureSensors = 45 + + CanBUSFaultCount = 2457 + HDDebugText = 0xFFF1 + DGDebugText = 0xFFF2 + + AdjustBloodDialysateReq = 23 + AdjustBloodDialysateRsp = 24 + + AdjustDurationReq = 22 + AdjustDurationRsp = 27 + + AdjustUltrafiltrationStateReq = 16 + AdjustUltrafiltrationStateRsp = 65 + AdjustUltrafiltrationEditReq = 17 + AdjustUltrafiltrationEditRsp = 19 + AdjustUltrafiltrationConfirmReq = 21 + AdjustUltrafiltrationConfirmRsp = 46 + + TreatmentRanges = 26 + + 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 + + class HDSimulator(_AbstractSubSystem): NUM_TREATMENT_PARAMETERS = 18 @@ -135,7 +206,7 @@ return True - def cmd_send_treatment_parameter_manual_validation_response(self, rejections: int): + def cmd_send_treatment_parameter_manual_validation_response(self, rejections: List[int]): """ Sends a manually built treatment parameter validation response @@ -147,7 +218,7 @@ return False if not all([isinstance(each, int) for each in rejections]): - self.logger.error("Not all rejections are enums.") + self.logger.error("Not all rejections are the correct type.") return False payload = bytearray() @@ -282,7 +353,7 @@ @param response: 0=NO, 1=YES @return: None """ - print("Sending: {0}".format(response)) + self.logger.debug("Sending: {0}".format(response)) payload = integer_to_bytearray(response) payload += integer_to_bytearray(reason) @@ -362,3 +433,1158 @@ """ self.logger.info("Test Completed") + @staticmethod + def send_acknowledge_HD(): + """ + the acknowledge from HD + :return: none + """ + subprocess.call(['cansend', 'can0', '020#A5.01.00.FF.FF.00.19.00']) + + @staticmethod + def send_acknowledge_UI(): + """ + the acknowledge from UI + :return: none + """ + subprocess.call(['cansend', 'can0', '100#A5.01.00.FF.FF.00.19.00']) + + @staticmethod + 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']) + + @staticmethod + 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']) + + @staticmethod + 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']) + + @staticmethod + 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']) + + @staticmethod + 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']) + + @staticmethod + def waitForMessageToBeSent(): + """ + 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 + + @staticmethod + 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) + return messageBuilder.toFrames(msg) + + @staticmethod + def setHDDebugText(vText): + """ + the debug text message from HD setter/sender method + :param vText: (str) the debug text + :return: none + """ + frames = HDSimulator.buildHDDebugText(vText) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + 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) + + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGDebugText(vText): + """ + the debug text message from DG setter/sender method + :param vText: (str) the debug text + :return: none + """ + frames = HDSimulator.buildDGDebugText(vText) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '070#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + 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) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + 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 = HDSimulator.buildSetTreatmentParamRanges(vMinTreatmentDuration, vMaxTreatmentDuration, vMinUFVolume, vMaxUFVolume, + vMinDialysateFlowRate, vMaxDialysateFlowRate) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + 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) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + 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 = HDSimulator.buildSetTreatmentBloodFlowRate(vFlowSetPt, vMeasFlow, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + 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) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + 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 = HDSimulator.buildSetTreatmentDialysateFlowRate(vFlowSetPt, vMeasFlow, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + 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) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + 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 = HDSimulator.buildTreatmentAdjustBloodDialysateResponse(vAccepted, vReason, vBloodRate, vDialysate) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + 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) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + 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 = HDSimulator.buildTreatmentAdjustDurationResponse(vAccepted, vReason, vDuration, vUltrafiltration) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildTreatmentAdjustUltrafiltrationStateResponse(vAccepted, vReason, vState): + """ + the Treatment ultrafiltration adjustment response message builder method + | MSG | CAN ID | M.Box | Type | Ack | Src | Dest | Description | + |:---:|:------:|:-----:|:----:|:---:|:---:|:----:|:------------------------:| + | 65 | 0x020 | 6 | Rsp | Y | HD | UI | UF Pause/Resume Response | + + | Payload || + | || + | #1:(U32) | \ref Data::mAccepted | + | #2:(U32) | \ref Data::mReason | + | #3:(U32) | \ref Data::mState | + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vState: (int) Ultrafiltration State + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(GuiActionType.AdjustUltrafiltrationStateRsp, 3 * 4, False, + utils.toI32(vAccepted), + utils.toI32(vReason), + utils.toI32(vState) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + def setTreatmentAdjustUltrafiltrationStateResponse(vAccepted, vReason, vState): + """ + the Treatment ultrafiltration adjustment response message setter/sender method + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vState: (int) Ultrafiltration State + :return: none + """ + frames = HDSimulator.buildTreatmentAdjustUltrafiltrationStateResponse(vAccepted, vReason, vState) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def setTreatmentAdjustUltrafiltrationAccepted(vState): + """ + a convenient method for setTreatmentAdjustUltrafiltrationStateResponse which sends accept true + :return: none + """ + HDSimulator.setTreatmentAdjustUltrafiltrationStateResponse(EResponse.Accepted, 0, vState) + + @staticmethod + def setTreatmentAdjustUltrafiltrationRejected(vReason, vState): + """ + a convenient method for setTreatmentAdjustUltrafiltrationStateResponse which sends accept false + :return: none + """ + HDSimulator.setTreatmentAdjustUltrafiltrationStateResponse(EResponse.Rejected, vReason, vState) + + @staticmethod + def buildTreatmentAdjustUltrafiltrationEditResponse(vAccepted, vReason, vVolume, vDuration, vDurationDiff, vRate, + vRateDiff, vRateOld): + """ + the ultrafiltration volume change response message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #1:(U32) | #2:(U32) | #3:(F32) | #4:(U32) | #5:(F32) | #6:(U32) | #7:(U32) | #8:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: |:--: |:--: |:--: |:--: |:--: |:--: | + |0x1300| 0x020 | 6 | Rsp | Y | HD | UI | UF Vol. Change Response | \ref Data::mAccepted | \ref Data::mReason | \ref Data::mAccepted | \ref Data::mReason | \ref Data::mVolume | \ref Data::mDuration | \ref Data::mRate | \ref Data::mDurationDiff | \ref Data::mRateDiff | \ref Data::mRateOld | + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vVolume: (float) Ultrafiltration Volume + :param vDuration: (int) Treatment Duration + :param vDurationDiff: (int) Duration Difference + :param vRate: (float) Ultrafiltration Rate + :param vRateDiff: (float) Ultrafiltration Rate Difference + :param vRateOld: (float) Ultrafiltration Rate Old + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(GuiActionType.AdjustUltrafiltrationEditRsp, 8 * 4, True, + utils.toI32(vAccepted), + utils.toI32(vReason), + utils.toF32(vVolume), + utils.toI32(vDuration), + utils.toI32(vDurationDiff), + utils.toF32(vRate), + utils.toF32(vRateDiff), + utils.toF32(vRateOld) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + def setTreatmentAdjustUltrafiltrationEditResponse(vAccepted, vReason, vVolume, vDuration, vDurationDiff, vRate, + vRateDiff, vRateOld): + """ + the ultrafiltration volume change response message setter/sender method + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vVolume: (float) Ultrafiltration Volume + :param vDuration: (int) Treatment Duration + :param vDurationDiff: (int) Duration Difference + :param vRate: (float) Ultrafiltration Rate + :param vRateDiff: (float) Ultrafiltration Rate Difference + :param vRateOld: (float) Ultrafiltration Rate Old + :return: none + """ + frames = HDSimulator.buildTreatmentAdjustUltrafiltrationEditResponse(vAccepted, vReason, vVolume, vDuration, vDurationDiff, + vRate, vRateDiff, vRateOld) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def setTreatmentAdjustUltrafiltrationEditRejected(vReason): + """ + a convenient method for setTreatmentAdjustUltrafiltrationEditResponse which only sends a rejection reason + and sends other values all as zero + :param vReason: (int) rejection reason + :return: none + """ + frames = HDSimulator.buildTreatmentAdjustUltrafiltrationEditResponse(0, vReason, 0, 0, 0, 0, 0, 0) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildTreatmentAdjustUltrafiltrationConfirmResponse(vAccepted, vReason, vVolume, vDuration, vRate): + """ + the ultrafiltratin volume Change Confirmation Response message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #3:(F32) | #4:(U32) | #5:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: |:--: | + |0x2E00| 0x020 | 6 | Rsp | Y | HD | UI | UF Vol. Change Confirmation Response | \ref Data::mAccepted | \ref Data::mReason | \ref Data::mVolume | \ref Data::mDuration | \ref Data::mRate | + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vVolume: (float) Ultrafiltration Volume + :param vDuration: (int) Treatment Duration + :param vRate: (float) Ultrafiltration Rate + :return: built message frame(s) + """ + msg = messageBuilder.buildMessage(GuiActionType.AdjustUltrafiltrationConfirmRsp, 5 * 4, True, + utils.toI32(vAccepted), + utils.toI32(vReason), + utils.toF32(vVolume), + utils.toI32(vDuration), + utils.toF32(vRate) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + def setTreatmentAdjustUltrafiltrationConfirmResponse(vAccepted, vReason, vVolume, vDuration, vRate): + """ + the ultrafiltration volume Change Confirmation Response message setter/sender method + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vVolume: (float) Ultrafiltration Volume + :param vDuration: (int) Treatment Duration + :param vRate: (float) Ultrafiltration Rate + :return: none + """ + frames = HDSimulator.buildTreatmentAdjustUltrafiltrationConfirmResponse(vAccepted, vReason, vVolume, vDuration, vRate) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def setTreatmentAdjustUltrafiltrationConfirmRejected(vReason): + """ + a convenient method for setTreatmentAdjustUltrafiltrationConfirmResponse which only sends a rejection reason + and sends other values all as zero + :param vReason: (int) rejection reason + :return: none + """ + frames = HDSimulator.buildTreatmentAdjustUltrafiltrationConfirmResponse(0, vReason, 0, 0, 0) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildTreatmentTime(vSecsTotal, vSecsElap, vSecsRem): + """ + the Treatment Time Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #3:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: | + |0x0D00| 0x040 | 7 | 1 Hz | N | HD | All | Treatment Time Data | \ref Data::mTotal | \ref Data::mElapsed | \ref Data::mRemaining | + :param vSecsTotal: (int) Treatment Total Duration in Seconds + :param vSecsElap: (int) Treatment Total Elapsed Time in Seconds + :param vSecsRem: (int) Treatment Remaining Time in Seconds + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(GuiActionType.TreatmentTime, 3 * 4, False, + utils.toI32(vSecsTotal), + utils.toI32(vSecsElap), + utils.toI32(vSecsRem) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + def setTreatmentTime(vSecsTotal, vSecsElap, vSecsRem=None): + """ + the Treatment Time Data message setter/sender method + :param vSecsTotal: (int) Treatment Total Duration in Seconds + :param vSecsElap: (int) Treatment Total Elapsed Time in Seconds + :param vSecsRem: (int) Treatment Remaining Time in Seconds + :return: none + """ + if vSecsRem is None: + vSecsRem = vSecsTotal - vSecsElap + frames = HDSimulator.buildTreatmentTime(vSecsTotal, vSecsElap, vSecsRem) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildSetTreatmentUltrafiltration(vRefUFVol, vMeasUFVol, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM): + """ + the Outlet Flow Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(F32) | #2:(F32) | #3:(F32) | #4:(F32) | #5:(F32) | #6:(F32) | #7:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: |:--: |:--: |:--: | + |0x0B00| 0x040 | 7 | 1 Hz | N | HD | All | Outlet Flow Data | \ref Data::mRefUFVol | \ref Data::mMeasUFVol | \ref Data::mRotorSpeed | \ref Data::mMotorSpeed | \ref Data::mMotorCtlSpeed | \ref Data::mMotorCtlCurrent | \ref Data::mPWMDtCycle | + :param vRefUFVol: (float) Ref UF Volume + :param vMeasUFVol: (float) Measured UF Volume + :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.DialysateOutletFlow, 4 * 7, False, + utils.toF32(vRefUFVol), + utils.toF32(vMeasUFVol), + utils.toF32(vRotSpd), + utils.toF32(vMotSpd), + utils.toF32(vMCSpd), + utils.toF32(vMCCurr), + utils.toF32(vPWM) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + def setTreatmentUltrafiltration(vRefUFVol, vMeasUFVol, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM): + """ + the Outlet Flow Data message setter/sender method + :param vRefUFVol: (float) Ref UF Volume + :param vMeasUFVol: (float) Measured UF Volume + :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 = HDSimulator.buildSetTreatmentUltrafiltration(vRefUFVol, vMeasUFVol, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildPressureOcclusionData(vArterialPressure, vVenousPressure, vBloodPumpOcclusion, vDialysateInletPumpOcclusion, + vDialysateOutletPumpOcclusion): + """ + the Pressure/Occlusion Data messages builder mehtod + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(F32) | #2:(F32) | #3:(U32) | #4:(U32) | #5:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: |:--: | + |0x0900| 0x040 | 7 | 1 Hz | N | HD | All | PressureOcclusion Data | \ref Data::mArterialPressure | \ref Data::mVenousPressure | \ref Data::mBloodPumpOcclusion | \ref Data::mDialysateInletPumpOcclusion | \ref Data::mDialysateOutletPumpOcclusion | + :param vArterialPressure: (float) Arterial Pressure + :param vVenousPressure: (float) Venous Pressure + :param vBloodPumpOcclusion: (uint) Blood Pump Occlusion + :param vDialysateInletPumpOcclusion: (uint) Dialysate Inlet Pump Occlusion + :param vDialysateOutletPumpOcclusion: (uint) Dialysate Outlet Pump Occlusion + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0009, 4 + 4 + 4 + 4 + 4, False, + utils.toF32(vArterialPressure), + utils.toF32(vVenousPressure), + utils.toI32(vBloodPumpOcclusion), + utils.toI32(vDialysateInletPumpOcclusion), + utils.toI32(vDialysateOutletPumpOcclusion)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setPressureOcclusionData(vArterialPressure, vVenousPressure, vBloodPumpOcclusion, vDialysateInletPumpOcclusion, + vDialysateOutletPumpOcclusion): + """ + the Pressure/Occlusion Data messages setter/sender mehtod + :param vArterialPressure: (float) Arterial Pressure + :param vVenousPressure: (float) Venous Pressure + :param vBloodPumpOcclusion: (uint) Blood Pump Occlusion + :param vDialysateInletPumpOcclusion: (uint) Dialysate Inlet Pump Occlusion + :param vDialysateOutletPumpOcclusion: (uint) Dialysate Outlet Pump Occlusion + :return: none + """ + frames = HDSimulator.buildPressureOcclusionData(vArterialPressure, vVenousPressure, vBloodPumpOcclusion, + vDialysateInletPumpOcclusion, vDialysateOutletPumpOcclusion) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildDGROPumpData(vSetPtPressure, vFlowRate, vPWM): + """ + the DG RO Pump Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(F32) | #3:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: | + |0x1F00| 0x080 | 8 | 1 Hz | N | DG | All | DG RO Pump Data | \ref Data::mPressure | \ref Data::mFlowRate | \ref Data::mPWM | :param vSetPtPressure: + :param vSetPtPressure: (int) set Point Pressure + :param vFlowRate: (float) Flow Rate + :param vPWM: (float) PWM + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x001F, 4 + 4 + 4, False, + utils.toI32(vSetPtPressure), + utils.toF32(vFlowRate), + utils.toF32(vPWM)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGROPumpData(vSetPtPressure, vFlowRate, vPWM): + """ + the DG RO Pump Data message setter/sender method + :param vSetPtPressure: (int) set Point Pressure + :param vFlowRate: (float) Flow Rate + :param vPWM: (float) PWM + :return: none + """ + frames = HDSimulator.buildDGROPumpData(vSetPtPressure, vFlowRate, vPWM) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildDGPressuresData(vROInletPSI, vROOutletPSI, vDrainInletPSI, vDrainOutletPSI): + """ + the DG Pressures Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(F32) | #2:(F32) | #3:(F32) | #4:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: | + |0x2000| 0x080 | 8 | 1 Hz | N | DG | All | DG Pressures Data | \ref Data::mROInletPSI | \ref Data::mROOutletPSI | \ref Data::mDrainInletPSI | \ref Data::mDrainOutletPSI | + :param vROInletPSI: (float) RO Inlet PSI + :param vROOutletPSI: (float) RO Outlet PSI + :param vDrainInletPSI: (float) Drain Inlet PSI + :param vDrainOutletPSI: (float) Drain Outlet PSI + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0020, 4 + 4 + 4 + 4, False, + utils.toF32(vROInletPSI), + utils.toF32(vROOutletPSI), + utils.toF32(vDrainInletPSI), + utils.toF32(vDrainOutletPSI)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGPressuresData(vROInletPSI, vROOutletPSI, vDrainInletPSI, vDrainOutletPSI): + """ + the DG Pressures Data message setter/sender method + :param vROInletPSI: (float) RO Inlet PSI + :param vROOutletPSI: (float) RO Outlet PSI + :param vDrainInletPSI: (float) Drain Inlet PSI + :param vDrainOutletPSI: (float) Drain Outlet PSI + :return: none + """ + frames = HDSimulator.buildDGPressuresData(vROInletPSI, vROOutletPSI, vDrainInletPSI, vDrainOutletPSI) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildDGDrainPumpData(vSetPtRPM, vDACValue): + """ + the DG Drain Pump Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: | + |0x2400| 0x080 | 8 | 1 Hz | N | DG | All | DG Drain Pump Data | \ref Data::mRPM | \ref Data::mDAC | + :param vSetPtRPM: (int) Set Point RPM + :param vDACValue: (int) DAC Value + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0024, 4 + 4, False, + utils.toI32(vSetPtRPM), + utils.toI32(vDACValue)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGDrainPumpData(vSetPtRPM, vDACValue): + """ + the DG Drain Pump Data message setter/sender method + :param vSetPtRPM: (int) Set Point RPM + :param vDACValue: (int) DAC Value + :return: none + """ + frames = HDSimulator.buildDGDrainPumpData(vSetPtRPM, vDACValue) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildDGOperationMode(vDGOpMode): + """ + the DG Operation Mode Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: | + |0x2700| 0x080 | 8 | 1 Hz | N | DG | All | DG Operation Mode Data | \ref Data::mOpMode | + :param vDGOpMode: (int) DG Operation Mode + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0027, 4, False, + utils.toI32(vDGOpMode)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGOperationMode(vDGOpMode): + """ + the DG Operation Mode Data message setter/sender method + :param vDGOpMode: (int) DG Operation Mode + :return: none + """ + frames = HDSimulator.buildDGOperationMode(vDGOpMode) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildDGReservoirData(vActiveReservoir, vFillToVolML, vDrainToVolML): + """ + the DG Reservoir Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #3:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: | + |0x2800| 0x080 | 8 | 1 Hz | N | DG | All | DG Reservoir Data | \ref Data::mActiveReservoir | \ref Data::mFillToVol | \ref Data::mDrainToVol | + :param vActiveReservoir: (int) Active Reservoir + :param vFillToVolML: (int) Fill To Volume ML + :param vDrainToVolML: (int) Drain To Vol ML + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0028, 4 + 4 + 4, False, + utils.toI32(vActiveReservoir), + utils.toI32(vFillToVolML), + utils.toI32(vDrainToVolML)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGReservoirData(vActiveReservoir, vFillToVolML, vDrainToVolML): + """ + the DG Reservoir Data message setter/sender method + :param vActiveReservoir: (int) Active Reservoir + :param vFillToVolML: (int) Fill To Volume ML + :param vDrainToVolML: (int) Drain To Vol ML + :return: none + """ + frames = HDSimulator.buildDGReservoirData(vActiveReservoir, vFillToVolML, vDrainToVolML) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildDGValvesStates(vValvesStates): + """ + the DG Valves States Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U16) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: | + |0x2A00| 0x080 | 8 | 2 Hz | N | DG | All | DG Valves States Data | \ref Data::mStates | + :param vValvesStates: (int)Valves states + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x002A, 2, False, + utils.toI16(vValvesStates)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGValvesStates(vValvesStates): + """ + the DG Valves States Data message setter/sender method + :param vValvesStates: (int)Valves states + :return: none + """ + frames = HDSimulator.buildDGValvesStates(vValvesStates) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildDGHeatersData(vMainPriMaryDC, vSmallPrimaryDC, vTrimmerDC): + """ + the DG Heaters Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #3:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: | + |0x2C00| 0x080 | 8 | 2 Hz | N | DG | All | DG Heaters Data | \ref Data::mMainPrimaryDC | \ref Data::mSmallPrimaryDC | \ref Data::mTrimmerDC | + :param vMainPriMaryDC: (int) Main PriMary DC + :param vSmallPrimaryDC: (int) Small Primary DC + :param vTrimmerDC: (int) Trimmer DC + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x002C, 4 + 4 + 4, False, + utils.toI32(vMainPriMaryDC), + utils.toI32(vSmallPrimaryDC), + utils.toI32(vTrimmerDC)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGHeatersData(vMainPriMaryDC, vSmallPrimaryDC, vTrimmerDC): + """ + the DG Heaters Data message setter/sender method + :param vMainPriMaryDC: (int) Main PriMary DC + :param vSmallPrimaryDC: (int) Small Primary DC + :param vTrimmerDC: (int) Trimmer DC + :return: none + """ + frames = HDSimulator.buildDGHeatersData(vMainPriMaryDC, vSmallPrimaryDC, vTrimmerDC) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildDGLoadCellReadingsData(vRs1Prim, vRs1Bkup, vRs2Prim, vRs2Bkup): + """ + the DG Load Cell Readings Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(F32) | #2:(F32) | #3:(F32) | #4:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: | + |0x0C00| 0x080 | 8 | 10 Hz | N | DG | All | DG Load Cell Readings Data | \ref Data::mReservoir1Prim | \ref Data::mReservoir1Bkup | \ref Data::mReservoir2Prim | \ref Data::mReservoir2Bkup | + :param vRs1Prim: (float) Reservoir 1 Primary + :param vRs1Bkup: (float) Reservoir 1 Backup + :param vRs2Prim: (float) Reservoir 2 Primary + :param vRs2Bkup: (float) Reservoir 2 Backup + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x000C, 4 + 4 + 4 + 4, False, + utils.toF32(vRs1Prim), + utils.toF32(vRs1Bkup), + utils.toF32(vRs2Prim), + utils.toF32(vRs2Bkup)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGLoadCellReadingsData(vRs1Prim, vRs1Bkup, vRs2Prim, vRs2Bkup): + """ + the DG Load Cell Readings Data message setter/sender method + :param vRs1Prim: (float) Reservoir 1 Primary + :param vRs1Bkup: (float) Reservoir 1 Backup + :param vRs2Prim: (float) Reservoir 2 Primary + :param vRs2Bkup: (float) Reservoir 2 Backup + :return: none + """ + frames = HDSimulator.buildDGLoadCellReadingsData(vRs1Prim, vRs1Bkup, vRs2Prim, vRs2Bkup) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildDGTemperaturesData(vInletPrimaryHeater, vOutletPrimaryHeater, vConductivitySensor1, vConductivitySensor2, + vOutletRedundancy, vInletDialysate, vPrimaryHeaterThermocouple, vTrimmerHeaterThermocouple, + vPrimaryHeaterColdJunction, vTrimmerHeaterColdJunction, vPrimaryHeaterInternalTemperature, + vTrimmerHeaterInternalTemperature): + """ + the DG Temperatures Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(F32) | #2:(F32) | #3:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: | + |0x2D00| 0x080 | 8 | 2 Hz | N | DG | All | DG Temperatures Data | \ref Data::mInletPrimaryHeater | \ref Data::mOutletPrimaryHeater | \ref Data::mConductivitySensor1 | + + | #4:(F32) | #5:(F32) | #6:(F32) | #7:(F32) | #8:(F32) | + |:--: |:--: |:--: |:--: |:--: | + | \ref Data::mConductivitySensor2 | \ref Data::mOutletRedundancy | \ref Data::mInletDialysate | \ref Data::mPrimaryHeaterThermoCouple | \ref Data::mTrimmerHeaterThermoCouple | + + | #9:(F32) | #10:(F32) | #11:(F32) | #12:(F32) | + | :--: |:--: |:--: |:--: | + | \ref Data::mPrimaryHeaterColdJunction | \ref Data::mTrimmerHeaterColdJunction | \ref Data::mPrimaryHeaterInternal | \ref Data::mTrimmerHeaterInternal | + :param vInletPrimaryHeater: (float) Inlet Primary Heater + :param vOutletPrimaryHeater: (float) Outlet Primary Heater + :param vConductivitySensor1: (float) Conductivity Sensor 1 + :param vConductivitySensor2: (float) Conductivity Sensor 2 + :param vOutletRedundancy: (float) Outlet Redundancy + :param vInletDialysate: (float) Inlet Dialysate + :param vPrimaryHeaterThermocouple: (float) Primary Heater Thermocouple + :param vTrimmerHeaterThermocouple: (float) Trimmer Heater Thermocouple + :param vPrimaryHeaterColdJunction: (float) Primary Heater ColdJunction + :param vTrimmerHeaterColdJunction: (float) Trimmer Heater ColdJunction + :param vPrimaryHeaterInternalTemperature: (float) Primary Heater Internal Temperature + :param vTrimmerHeaterInternalTemperature: (float) Trimmer HeaterInternal Temperature + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x002D, 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4, False, + utils.toF32(vInletPrimaryHeater), + utils.toF32(vOutletPrimaryHeater), + utils.toF32(vConductivitySensor1), + utils.toF32(vConductivitySensor2), + utils.toF32(vOutletRedundancy), + utils.toF32(vInletDialysate), + utils.toF32(vPrimaryHeaterThermocouple), + utils.toF32(vTrimmerHeaterThermocouple), + utils.toF32(vPrimaryHeaterColdJunction), + utils.toF32(vTrimmerHeaterColdJunction), + utils.toF32(vPrimaryHeaterInternalTemperature), + utils.toF32(vTrimmerHeaterInternalTemperature)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setDGTemperaturesData(vInletPrimaryHeater, vOutletPrimaryHeater, vConductivitySensor1, vConductivitySensor2, + vOutletRedundancy, vInletDialysate, vPrimaryHeaterThermocouple, vTrimmerHeaterThermocouple, + vPrimaryHeaterColdJunction, vTrimmerHeaterColdJunction, vPrimaryHeaterInternalTemperature, + vTrimmerHeaterInternalTemperature): + """ + the DG Temperatures Data message setter/sender method + :param vInletPrimaryHeater: (float) Inlet Primary Heater + :param vOutletPrimaryHeater: (float) Outlet Primary Heater + :param vConductivitySensor1: (float) Conductivity Sensor 1 + :param vConductivitySensor2: (float) Conductivity Sensor 2 + :param vOutletRedundancy: (float) Outlet Redundancy + :param vInletDialysate: (float) Inlet Dialysate + :param vPrimaryHeaterThermocouple: (float) Primary Heater Thermocouple + :param vTrimmerHeaterThermocouple: (float) Trimmer Heater Thermocouple + :param vPrimaryHeaterColdJunction: (float) Primary Heater ColdJunction + :param vTrimmerHeaterColdJunction: (float) Trimmer Heater ColdJunction + :param vPrimaryHeaterInternalTemperature: (float) Primary Heater Internal Temperature + :param vTrimmerHeaterInternalTemperature: (float) Trimmer HeaterInternal Temperature + :return: none + """ + frames = HDSimulator.buildDGTemperaturesData(vInletPrimaryHeater, vOutletPrimaryHeater, vConductivitySensor1, + vConductivitySensor2, vOutletRedundancy, vInletDialysate, + vPrimaryHeaterThermocouple, vTrimmerHeaterThermocouple, vPrimaryHeaterColdJunction, + vTrimmerHeaterColdJunction, vPrimaryHeaterInternalTemperature, + vTrimmerHeaterInternalTemperature) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildTreatmentStatesData(vSubMode, vUFState, vSalineState): + """ + the Treatment States Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #3:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: | + |0x0F00| 0x040 | 7 | 1 Hz | N | HD | All | Treatment States Data | \ref Data::mSubMode | \ref Data::mUFState | \ref Data::mSalineState | + :param vSubMode: (int) Sub-Mode + :param vUFState: (int) UF State + :param vSalineState: (int) Saline Bolus State + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x000F, 4 + 4 + 4, False, + utils.toI32(vSubMode), + utils.toI32(vUFState), + utils.toI32(vSalineState)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setTreatmentStatesData(vSubMode, vUFState, vSalineState): + """ + the Treatment States Data message setter/sender method + :param vSubMode: (int) Sub-Mode + :param vUFState: (int) UF State + :param vSalineState: (int) Saline Bolus State + :return: none + """ + frames = HDSimulator.buildTreatmentStatesData(vSubMode, vUFState, vSalineState) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def setTreatmentStartState(): + """ + starting the treatment for user convenience since Tx is not by default running + :return: none + """ + HDSimulator.setTreatmentStatesData(txStates.TREATMENT_DIALYSIS_STATE, txStates.UF_OFF_STATE, txStates.SALINE_BOLUS_STATE_IDLE) + + @staticmethod + def buildHDOperationModeData(vOpMode): + """ + the HD Operation Mode Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: | + |0x2500| 0x040 | 7 | 1 Hz | N | HD | All | HD Operation Mode Data | \ref Data::mOpMode | + :param vOpMode: (int) Operation Mode + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0025, 4, False, + utils.toI32(vOpMode)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setHDOperationModeData(vOpMode): + """ + the HD Operation Mode Data message setter/sender method + :param vOpMode: (int) Operation Mode + :return: none + """ + frames = HDSimulator.buildHDOperationModeData(vOpMode) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildTreatmentSalineBolusData(vTarget, vCumulative, vDelivered): + """ + the Treatment Saline Bolus Data message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(F32) | #3:(F32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: | + |0x2F00| 0x040 | 7 | 1 Hz | N | HD | All | Treatment Saline Bolus Data | \ref Data::mTarget | \ref Data::mCumulative | \ref Data::mDelivered | + :param vTarget: (int) Saline Bolus Target Volume + :param vCumulative: (float) Saline Bolus Cumulative Volume + :param vDelivered: (float) Saline Bolus Delivered Volume + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x002F, 4 + 4 + 4, False, + utils.toI32(vTarget), + utils.toF32(vCumulative), + utils.toF32(vDelivered)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setTreatmentSalineBolusData(vTarget, vCumulative, vDelivered): + """ + the Treatment Saline Bolus Data message setter/sender method + :param vTarget: (int) Saline Bolus Target Volume + :param vCumulative: (float) Saline Bolus Cumulative Volume + :param vDelivered: (float) Saline Bolus Delivered Volume + :return: none + """ + frames = HDSimulator.buildTreatmentSalineBolusData(vTarget, vCumulative, vDelivered) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildSalineBolusResponse(vAccepted, vReason, vTarget, vState): + """ + the Saline Bolus Response message builder method + | MSG | CAN ID | M.Box | Type | Ack | Src | Dest | Description | #1:(U32) | #2:(U32) | #3:(U32) | #3:(U32) | + |:---:|:------:|:-----:|:----:|:---:|:---:|:----:|:---------------------:|:--------------------:|:-------------------:|:-------------------:|:-------------------:| + | 20 | 0x020 | 6 | Rsp | Y | HD | UI | Saline Bolus Response | \ref Data::mAccepted | \ref Data::mReason | \ref Data::mTarget | \ref Data::mState | + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vTarget: (int) Saline Bolus Target Volume + :param vState: (int) Saline Bolus current State + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0014, 4 + 4 + 4 + 4, True, + utils.toI32(vAccepted), + utils.toI32(vReason), + utils.toI32(vTarget), + utils.toI32(vState)) + return messageBuilder.toFrames(msg) + + @staticmethod + def setSalineBolusResponse(vAccepted, vReason, vTarget, vState): + """ + the Saline Bolus Response message setter/sender method + :param vAccepted: (int) boolean accept/reject response + :param vReason: (int) rejection reason + :param vTarget: (int) Saline Bolus Target Volume + :param vState: (int) Saline Bolus current State + :return: none + """ + frames = HDSimulator.buildSalineBolusResponse(vAccepted, vReason, vTarget, vState) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildCanBUSFaultCount(vCount): + """ + the CANBus fault count message builder method + :param vCount: (int) Fault Count + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(GuiActionType.CanBUSFaultCount, 4 * 1, False, + utils.toI32(vCount) + ) + return messageBuilder.toFrames(msg) + + @staticmethod + def setCanBUSFaultCount(vCount): + """ + the CANBus fault count message setter/sender method + :param vCount: (int) Fault Count + :return: none + """ + frames = HDSimulator.buildCanBUSFaultCount(vCount) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def buildUnknown(): + """ + the unknown message builder method + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(GuiActionType.Unknown, 0, False) + return messageBuilder.toFrames(msg) + + @staticmethod + def sendUnknown_HD(): + """ + the unknown message from HD setter/sender method + :return: none + """ + frames = HDSimulator.buildUnknown() + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '001#{}'.format(frame)]) # send from HD + HDSimulator.waitForMessageToBeSent() + + @staticmethod + def sendUnknown_DG(): + """ + the unknown message from DG setter/sender method + :return: none + """ + frames = HDSimulator.buildUnknown() + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '070#{}'.format(frame)]) # send from DG + HDSimulator.waitForMessageToBeSent()