Index: .gitignore =================================================================== diff -u -r01777f61bd58d75904abc7f29033813f0e947736 -re5b68dd61c18dd97545d5e527a7f0a8f84061cb6 --- .gitignore (.../.gitignore) (revision 01777f61bd58d75904abc7f29033813f0e947736) +++ .gitignore (.../.gitignore) (revision e5b68dd61c18dd97545d5e527a7f0a8f84061cb6) @@ -24,4 +24,4 @@ docs/source/modules.rst docs/source/dialin.common.rst *.swp - +testsuites Fisheye: Tag e5b68dd61c18dd97545d5e527a7f0a8f84061cb6 refers to a dead (removed) revision in file `dialin/squish/README.md'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e5b68dd61c18dd97545d5e527a7f0a8f84061cb6 refers to a dead (removed) revision in file `dialin/squish/__init__.py'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e5b68dd61c18dd97545d5e527a7f0a8f84061cb6 refers to a dead (removed) revision in file `dialin/squish/crc.py'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e5b68dd61c18dd97545d5e527a7f0a8f84061cb6 refers to a dead (removed) revision in file `dialin/squish/denaliMessages.py'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e5b68dd61c18dd97545d5e527a7f0a8f84061cb6 refers to a dead (removed) revision in file `dialin/squish/globals.py'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e5b68dd61c18dd97545d5e527a7f0a8f84061cb6 refers to a dead (removed) revision in file `dialin/squish/messageBuilder.py'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e5b68dd61c18dd97545d5e527a7f0a8f84061cb6 refers to a dead (removed) revision in file `dialin/squish/unittests.py'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag e5b68dd61c18dd97545d5e527a7f0a8f84061cb6 refers to a dead (removed) revision in file `dialin/squish/utils.py'. Fisheye: No comparison available. Pass `N' to diff? Index: dialin/ui/crc.py =================================================================== diff -u --- dialin/ui/crc.py (revision 0) +++ dialin/ui/crc.py (revision e5b68dd61c18dd97545d5e527a7f0a8f84061cb6) @@ -0,0 +1,62 @@ +########################################################################### +# +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file crc.py +# +# @author (last) Peter Lucia +# @date (last) 21-Oct-2020 +# @author (original) Peter Lucia +# @date (original) 09-Jul-2020 +# +############################################################################ + +crc8_table = ( + 0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, + 67, 114, 33, 16, 135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109, + 134, 183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168, + 197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235, + 61, 12, 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19, + 126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80, + 187, 138, 217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, + 248, 201, 154, 171, 60, 13, 94, 111, 65, 112, 35, 18, 133, 180, 231, 214, + 122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84, + 57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23, + 252, 205, 158, 175, 56, 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210, + 191, 142, 221, 236, 123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145, + 71, 118, 37, 20, 131, 178, 225, 208, 254, 207, 156, 173, 58, 11, 88, 105, + 4, 53, 102, 87, 192, 241, 162, 147, 189, 140, 223, 238, 121, 72, 27, 42, + 193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239, + 130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172 +) + +def crc8(vData): + """ + generates crc8 for the data vData + :param vData: byte of data + :return: (int) the crc code + """ + crc = 0 + l = len(vData) + i = 0 + while l > 0: + crc = crc8_table[vData[i] ^ crc ] + l = l - 1 + i = i + 1 + return crc + + +def calcCRC8(vString, vDelimiter='.'): + """ + calculates crc8 for each character in string vString + :param vString: (str) the bytes of data + :param vDelimiter: (character) the string delimiter + :return: the hex formatted crc of the given string + """ + str = vString.replace(vDelimiter, '') + ba = bytearray.fromhex(str) + x = '{:02X}'.format(crc8(ba), 'x') + return x Index: dialin/ui/globals.py =================================================================== diff -u --- dialin/ui/globals.py (revision 0) +++ dialin/ui/globals.py (revision e5b68dd61c18dd97545d5e527a7f0a8f84061cb6) @@ -0,0 +1,18 @@ +########################################################################### +# +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file globals.py +# +# @author (last) Peter Lucia +# @date (last) 21-Oct-2020 +# @author (original) Peter Lucia +# @date (original) 09-Jul-2020 +# +############################################################################ + +def SRSUI(vSRSUI = ""): + return "SRSUI " + "{}".format(vSRSUI).rjust(3, '0') Index: dialin/ui/hd_simulator.py =================================================================== diff -u -r287af45040e35882e001fb3ea835f304007870c4 -re5b68dd61c18dd97545d5e527a7f0a8f84061cb6 --- dialin/ui/hd_simulator.py (.../hd_simulator.py) (revision 287af45040e35882e001fb3ea835f304007870c4) +++ dialin/ui/hd_simulator.py (.../hd_simulator.py) (revision e5b68dd61c18dd97545d5e527a7f0a8f84061cb6) @@ -20,7 +20,6 @@ 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 +29,6 @@ YES = 1 NO = 0 - - class TreatmentParameterRejections: def __init__(self): self.param_request_valid = RequestRejectReasons.REQUEST_REJECT_REASON_NONE @@ -74,6 +71,79 @@ 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 @@ -361,3 +431,1275 @@ """ self.logger.info("Test Completed") + +import time +import subprocess + +from dialin.ui import utils, messageBuilder + + +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']) + + +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 + + +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) + + +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) + + return messageBuilder.toFrames(msg) + + +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): + """ + 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) + + +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) + ) + 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) + ) + 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) + ) + 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: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildTreatmentAdjustUltrafiltrationStateResponse(vAccepted, vReason, vState) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + waitForMessageToBeSent() + + +def setTreatmentAdjustUltrafiltrationAccepted(vState): + """ + a convenient method for setTreatmentAdjustUltrafiltrationStateResponse which sends accept true + :return: none + """ + setTreatmentAdjustUltrafiltrationStateResponse(EResponse.Accepted, 0, vState) + + +def setTreatmentAdjustUltrafiltrationRejected(vReason, vState): + """ + a convenient method for setTreatmentAdjustUltrafiltrationStateResponse which sends accept false + :return: none + """ + setTreatmentAdjustUltrafiltrationStateResponse(EResponse.Rejected, vReason, vState) + + +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) + + +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 = buildTreatmentAdjustUltrafiltrationEditResponse(vAccepted, vReason, vVolume, vDuration, vDurationDiff, + vRate, vRateDiff, vRateOld) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + waitForMessageToBeSent() + + +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 = buildTreatmentAdjustUltrafiltrationEditResponse(0, vReason, 0, 0, 0, 0, 0, 0) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildTreatmentAdjustUltrafiltrationConfirmResponse(vAccepted, vReason, vVolume, vDuration, vRate) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + waitForMessageToBeSent() + + +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 = buildTreatmentAdjustUltrafiltrationConfirmResponse(0, vReason, 0, 0, 0) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildTreatmentTime(vSecsTotal, vSecsElap, vSecsRem) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildSetTreatmentUltrafiltration(vRefUFVol, vMeasUFVol, vRotSpd, vMotSpd, vMCSpd, vMCCurr, vPWM) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildPressureOcclusionData(vArterialPressure, vVenousPressure, vBloodPumpOcclusion, + vDialysateInletPumpOcclusion, vDialysateOutletPumpOcclusion) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildDGROPumpData(vSetPtPressure, vFlowRate, vPWM) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildDGPressuresData(vROInletPSI, vROOutletPSI, vDrainInletPSI, vDrainOutletPSI) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildDGDrainPumpData(vSetPtRPM, vDACValue) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +def setDGOperationMode(vDGOpMode): + """ + the DG Operation Mode Data message setter/sender method + :param vDGOpMode: (int) DG Operation Mode + :return: none + """ + frames = buildDGOperationMode(vDGOpMode) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildDGReservoirData(vActiveReservoir, vFillToVolML, vDrainToVolML) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +def setDGValvesStates(vValvesStates): + """ + the DG Valves States Data message setter/sender method + :param vValvesStates: (int)Valves states + :return: none + """ + frames = buildDGValvesStates(vValvesStates) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildDGHeatersData(vMainPriMaryDC, vSmallPrimaryDC, vTrimmerDC) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildDGLoadCellReadingsData(vRs1Prim, vRs1Bkup, vRs2Prim, vRs2Bkup) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '080#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = 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)]) + waitForMessageToBeSent() + + +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) + + +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 = buildTreatmentStatesData(vSubMode, vUFState, vSalineState) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + waitForMessageToBeSent() + + +def setTreatmentStartState(): + """ + starting the treatment for user convenience since Tx is not by default running + :return: none + """ + setTreatmentStatesData(txStates.TREATMENT_DIALYSIS_STATE, txStates.UF_OFF_STATE, txStates.SALINE_BOLUS_STATE_IDLE) + + +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) + + +def setHDOperationModeData(vOpMode): + """ + the HD Operation Mode Data message setter/sender method + :param vOpMode: (int) Operation Mode + :return: none + """ + frames = buildHDOperationModeData(vOpMode) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + waitForMessageToBeSent() + + +##################### SALINE BOLUS + +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) + + +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 = buildTreatmentSalineBolusData(vTarget, vCumulative, vDelivered) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + waitForMessageToBeSent() + + +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) + + +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 = buildSalineBolusResponse(vAccepted, vReason, vTarget, vState) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + waitForMessageToBeSent() + + +################# END SALINE BOLUS + + +################# START CANBUS +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) + + +def setCanBUSFaultCount(vCount): + """ + the CANBus fault count message setter/sender method + :param vCount: (int) Fault Count + :return: none + """ + frames = buildCanBUSFaultCount(vCount) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + waitForMessageToBeSent() + + +def buildUnknown(): + """ + the unknown message builder method + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(GuiActionType.Unknown, 0, False) + return messageBuilder.toFrames(msg) + + +def sendUnknown_HD(): + """ + the unknown message from HD setter/sender method + :return: none + """ + frames = buildUnknown() + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '001#{}'.format(frame)]) # send from HD + waitForMessageToBeSent() + + +def sendUnknown_DG(): + """ + the unknown message from DG setter/sender method + :return: none + """ + frames = buildUnknown() + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '070#{}'.format(frame)]) # send from DG + waitForMessageToBeSent() + + +############### START ALARMS + +def clear_all_alarms(): + """ + a convenient method for setAlarmStatus to clear all alarms + :return: none + """ + setAlarmStatus(0, 0, 0, 0, 0) + + +def buildAlarmStatus(vState, vTop, vEscalatesIn, vMuteTimeout, vFlags): + """ + the Alarm Status message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | #2:(U32) | #3:(U32) | #4:(U32) | #5:(U16) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: |:--: |:--: |:--: |:--: | + |0x0200| 0x001 | 1 | 1 Hz | N | HD | All | Alarm Status | \ref Data::mState | \ref Data::mTop | \ref Data::mEscalatesIn | \ref Data::mMuteTimeout | \ref Data::mFlags | + :param vState: (int) Alarm State + :param vTop: (int) Top priority Alaram ID + :param vEscalatesIn: (int) Alarm Escalation + :param vMuteTimeout: (int) Mute Timeout + :param vFlags: (int16) Alarm Flags + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0002, 4 + 4 + 4 + 4 + 2, False, + utils.toI32(vState), + utils.toI32(vTop), + utils.toI32(vEscalatesIn), + utils.toI32(vMuteTimeout), + utils.toI16(vFlags)) + return messageBuilder.toFrames(msg) + + +def setAlarmStatus(vState, vTop, vEscalatesIn, vMuteTimeout, vFlags): + """ + the Alarm Status message setter/sender method + :param vState: (int) Alarm State + :param vTop: (int) Top priority Alaram ID + :param vEscalatesIn: (int) Alarm Escalation + :param vMuteTimeout: (int) Mute Timeout + :param vFlags: (int16) Alarm Flags + :return: none + """ + frames = buildAlarmStatus(vState, vTop, vEscalatesIn, vMuteTimeout, vFlags) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '001#{}'.format(frame)]) + waitForMessageToBeSent() + + +def buildAlarmTriggered(vAlarmID): + """ + the Alarm Triggered message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: | + |0x0300| 0x001 | 1 | Event | Y | HD | All | Alarm Triggered | \ref Data::mAlarmID | + :param vAlarmID: (int) Alarm ID + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0003, 4, True, + utils.toI32(vAlarmID)) + return messageBuilder.toFrames(msg) + + +def setAlarmTriggered(vAlarmID): + """ + the Alarm Triggered message setter/sender method + :param vAlarmID: (int) Alarm ID + :return: none + """ + frames = buildAlarmTriggered(vAlarmID) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '001#{}'.format(frame)]) + waitForMessageToBeSent() + + +def buildAlarmCleared(vAlarmID): + """ + the Alarm Cleared message builder method + | MSG | CAN ID | Box | Type | Ack | Src | Dst | Description | #1:(U32) | + |:----:|:------:|:---:|:------:|:---:|:---:|:---:|:-----------: |:--: | + |0x0400| 0x001 | 1 | Event | Y | HD | All | Alarm Cleared | \ref Data::mAlarmID | + :param vAlarmID: (int) Alarm ID + :return: (str) built message frame(s) + """ + msg = messageBuilder.buildMessage(0x0004, 4, True, + utils.toI32(vAlarmID)) + return messageBuilder.toFrames(msg) + + +def setAlarmCleared(vAlarmID): + """ + the Alarm Cleared message setter/sender method + :param vAlarmID: (int) Alarm ID + :return: none + """ + frames = buildAlarmCleared(vAlarmID) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '001#{}'.format(frame)]) + waitForMessageToBeSent() + +################## STOP ALARMS \ No newline at end of file Index: dialin/ui/messageBuilder.py =================================================================== diff -u --- dialin/ui/messageBuilder.py (revision 0) +++ dialin/ui/messageBuilder.py (revision e5b68dd61c18dd97545d5e527a7f0a8f84061cb6) @@ -0,0 +1,94 @@ +########################################################################### +# +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file messageBuilder.py +# +# @author (last) Peter Lucia +# @date (last) 21-Oct-2020 +# @author (original) Peter Lucia +# @date (original) 09-Jul-2020 +# +############################################################################ + +from dialin.ui import utils, crc + +syncByte = 'A5' + +def toCandumpFormat(vMsg): + """ + the converter method which converts the message vMsg to the string that candump tool understands. + :param vMsg: the message + :return: converted string to candump tool format + """ + if type(vMsg) == list: + for index, value in enumerate(vMsg): + vMsg[index] = ".".join(utils.partition(value, 2, False)) + else: + vMsg = ".".join(utils.partition(vMsg, 2, False)) + return vMsg + +def toFrames(vMsg): + """ + converts the message vMsg to frames + :param vMsg: adds the crc8 checksum at the end of the message vMsg + :return: the frames + """ + mLen = 16 + padded = utils.padding(vMsg, mLen) + frames = utils.partition(padded, mLen, False) + return frames + +def addCRC8(vString, vDelimiter = ""): + """ + adds the crc8 checksum at the end of the string vString + :param vString: the string to be used + :param vDelimiter: the string delimiter + :return: the string with crc8 + """ + return vString + vDelimiter + crc.calcCRC8(vString, vDelimiter) + + +def textToByte(vText, vLen): + """ + converts the string vText to bytes by the length of vLen + :param vText: + :param vLen: + :return: converted text + """ + text = "" + l = len(vText) + for i in range(vLen): + if i < l: + text += utils.toI08(ord(vText[i])) + else: + text += utils.toI08(0) + text += utils.toI08(0) #null /0 + return text + + +def buildMessage(vMsgID, vLen, vAck, *vArgs): + """ + builds message from the parameter givven + :param vMsgID: the message ID + :param vLen: length of the message payload in bytes + :param vAck: if true the message requires acknowledge back + :param vArgs: payload arguments. + :return: + """ + msg = "" + if vAck: + seq = -1 + else: + seq = 1 + + msg += utils.toI16(seq) # always used seq# (-)1 (for now) + msg += utils.toI16(vMsgID) + msg += utils.toI08(vLen) + for arg in vArgs: + msg += arg + msg += crc.calcCRC8(msg) + return syncByte + msg Index: dialin/ui/unittests.py =================================================================== diff -u --- dialin/ui/unittests.py (revision 0) +++ dialin/ui/unittests.py (revision e5b68dd61c18dd97545d5e527a7f0a8f84061cb6) @@ -0,0 +1,82 @@ +########################################################################### +# +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file unittests.py +# +# @author (last) Peter Lucia +# @date (last) 21-Oct-2020 +# @author (original) Peter Lucia +# @date (original) 09-Jul-2020 +# +############################################################################ + +import test +import sys +from subprocess import check_output + +from dialin.ui import crc + +MICRO = [8, 9] + + +def test_python_version(): + """ + tests the current python version compatibility + :return: + """ + test.compare(sys.version_info.major,3) + test.compare(sys.version_info.minor,6) + + test.compare(sys.version_info.micro in MICRO, True) + +def test_crc8(): + """ + test case for crc8 method + :return: + """ + strByte1 = ( "4B 43 09 00 14 00 00" + "00 00 00 00 00 00 00 00" + "00 00 00 00 00 00 00 00" + "00 00" # 9D + ) + + strByte2 = ( "4C 43 02 00 12 03 00" + "00 00 14 00 00 00 00 00" + "00 00 00 00 00 00 7F 00" # 55 + ) + + strByte3 = ( "4A 43 05 00 1C 00 00" + "00 00 00 00 00 00 00 00" + "00 00 00 00 00 00 6A B6" + "99 43 D5 68 6F 44 00 00" + "00 00" #4F + ) + + strByte4 = ( "FB 18 07 00 04 00 00" + "00 00" #7F + ) + + test.compare(crc.calcCRC8(strByte1, ' '), '9D') + test.compare(crc.calcCRC8(strByte2, ' '), '55') + test.compare(crc.calcCRC8(strByte3, ' '), '4F') + test.compare(crc.calcCRC8(strByte4, ' '), '7F') + +def test_can0(): + """ + check if the can0 bus driver presents + :return: + """ + canid = "can0" + ipa = "ip a" + ipa = check_output(ipa, shell=True) + loc = str(ipa).find(canid) + fnd = loc >= 0 + if (fnd): + msg = "can device '{}' found".format(canid) + else: + msg = "No can device registered as '{}'".format(canid) + test.compare(loc >= 0, True, msg) Index: dialin/ui/utils.py =================================================================== diff -u --- dialin/ui/utils.py (revision 0) +++ dialin/ui/utils.py (revision e5b68dd61c18dd97545d5e527a7f0a8f84061cb6) @@ -0,0 +1,139 @@ +########################################################################### +# +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# +# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +# +# @file utils.py +# +# @author (last) Peter Lucia +# @date (last) 21-Oct-2020 +# @author (original) Peter Lucia +# @date (original) 09-Jul-2020 +# +############################################################################ + +import time +import struct + +def SRSUI(vSRSUI = ""): + return "SRSUI " + "{}".format(vSRSUI).rjust(3, '0') + + +def waitForGUI(vDelay = 2): + """ + a global 2 seconds default wait mehod which is used to wait for GUI animations mostly + to make sure the object is avaialable. + :param vDelay: (int) amout of second for delay + :return: none + """ + time.sleep(vDelay) + + +def toUXX(vValue, vByteCount, vDelimiter): + """ + converts the value vValue to hex + :param vValue: (int) the value + :param vByteCount: (int) number of bytes the value will take eg. U32=4, ... + :param vDelimiter: (str) the output delimiter + :return: hex formated conversion of the vValue + """ + x = '{0:0{1}X}'.format(int(vValue) & (2**(4*vByteCount)-1), vByteCount, 'x') + bytes = partition(x, 2) + return vDelimiter.join(bytes) + + +def toI32(vValue, vDelimiter = ""): + """ + a convenient method for toUXX to convert the value vValue to integer 4 bytes + :param vValue: (int) the value + :param vDelimiter: (str) the output delimiter + :return: hex formated conversion of the vValue to int 4 bytes + """ + return toUXX(vValue, 8, vDelimiter) + + +def toI16(vValue, vDelimiter = ""): + """ + a convenient method for toUXX to convert the value vValue to integer 2 bytes + :param vValue: (int) the value + :param vDelimiter: (str) the output delimiter + :return: hex formated conversion of the vValue to int 2 bytes + """ + return toUXX(vValue, 4, vDelimiter) + + +def toI08(vValue, vDelimiter = ""): + """ + a convenient method for toUXX to convert the value vValue to integer 1 byte + :param vValue: (int) the value + :param vDelimiter: (str) the output delimiter + :return: hex formated conversion of the vValue to int 1 bytes + """ + return toUXX(vValue, 2, vDelimiter) + + +def toF32(vValue): + """ + converts value vValue to floating point 4 bytes. + :param vValue: (float) the value + :return: hex formated conversion of the vValue to float 4 bytes + """ + return '{:08X}'.format(struct.unpack('f', vValue))[0],'X') + +def partition(vString, vPart, vRightDirection=True): + """ + splits the given string into sections of vPart long + and puts the sections from left to right if vRightDirection is False + and puts the sections from right to left if vRightDirection is True + after the split is done + :param vString: (str) the given string + :param vPart: (int) length of the section + :param vRightDirection: (bool) order of sections in the output list + :return: (list) the section of the string vString in list + """ + return [vString[i: i + vPart] for i in range(0, len(vString), vPart)][::-1 if vRightDirection else 1] + +def padding(vString, vLen): + """ + added zero at the right side of the string to be of length of vLen + :param vString: (str) the string to add trainling zero to + :param vLen: (int) the entire length of the string + :return: (str) padded string + """ + lStr = len(vString) + lPad = int(lStr / vLen) * vLen + ( vLen * (1 if lStr % vLen else 0) ) + return vString.ljust(lPad, "0") + +def tstStart(vTestName): + """ + test case start print out with time + :param vTestName: (str) name of the test case + :return: none - prints out on the console + """ + print(time.strftime("%H:%M:%S Start", time.localtime()) + " - " + vTestName) + +def tstDone(): + """ + test case end print out with time + :return: none - prints out on the console + """ + print(time.strftime("%H:%M:%S Done ", time.localtime())) + +def l2ml(vValue): + """ + converts liter to mili liter + :param (int) vValue: the value in liter. + :return: (int) vValue converted to miliiliter. + """ + return int(round (vValue, 3) * 1000) + +def ml2l(vValue): + """ + converts mili liter to liter + :param (int) vValue: the value in miliiliter. + :return: (int) vValue converted to liter. + """ + return vValue / 1000 + Index: tests/unit_tests/test_imports.py =================================================================== diff -u -r8ea13ae6dd10732bfcc456798f4785c4d88c95d3 -re5b68dd61c18dd97545d5e527a7f0a8f84061cb6 --- tests/unit_tests/test_imports.py (.../test_imports.py) (revision 8ea13ae6dd10732bfcc456798f4785c4d88c95d3) +++ tests/unit_tests/test_imports.py (.../test_imports.py) (revision e5b68dd61c18dd97545d5e527a7f0a8f84061cb6) @@ -66,14 +66,6 @@ import dialin print(dialin.__version__) - def test_squish(self): - from dialin.squish import (denaliMessages, - crc, - globals, - messageBuilder, - unittests, - utils) - def test_package_imports(self): from dialin import HD, HDSimulator, DG