Index: shared/scripts/crc.py =================================================================== diff -u --- shared/scripts/crc.py (revision 0) +++ shared/scripts/crc.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 +# date 2020/04/08 +# author Behrouz NematiPour +# + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +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): + 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 = '.'): + str = vString.replace(vDelimiter, '') + ba = bytearray.fromhex(str) + x = '{:02X}'.format(crc8(ba), 'x') + return x Index: shared/scripts/denaliMessages.py =================================================================== diff -u --- shared/scripts/denaliMessages.py (revision 0) +++ shared/scripts/denaliMessages.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 denaliMessages.py +# date 2020/04/08 +# author Behrouz NematiPour +# + +import subprocess +import utils +import messageBuilder + +from enum import Enum + +class GuiActionType(Enum): + Unknown = 0 + PowerOff = 1 + KeepAlive = 7 + BloodFlow = 5 + DialysateInletFlow = 8 + DialysateOutletFlow = 11 + TreatmentTime = 13 + PowerOffBroadcast = 14 + + AlarmStatus = 2 + AlarmTriggered = 3 + AlarmCleared = 4 + + PressureOcclusion = 9 + + AdjustBloodDialysateReq = 23 # 23 + AdjustBloodDialysateRsp = 24 # 24 + + TreatmentRanges = 26 # 26 + + String = 65279 + + Acknow = 65535 + +def send_acknowledge_HD(): + subprocess.call(['cansend', 'can0', '020#A5.01.00.FF.FF.00.44.00']) + +def send_acknowledge_UI(): + subprocess.call(['cansend', 'can0', '100#A5.01.00.FF.FF.00.44.00']) + +def show_PowerOffDialog(): + subprocess.call(['cansend', 'can0', '020#A5.01.00.01.00.01.00.38']) + +def hide_PowerOffDialog(): + subprocess.call(['cansend', 'can0', '020#A5.01.00.01.00.01.01.09']) + +def show_PowerOffNotificationDialog(): + subprocess.call(['cansend', 'can0', '040#A5.01.00.0E.00.00.24.00']) + +def show_PowerOffRejectionDialog(): + subprocess.call(['cansend', 'can0', '020#A5.01.00.01.00.01.02.5A']) + +# This message needs to be acknowledged by seq# 01.00 : just call send_acknowledge_UI after this +def buildSetTreatmentParamRanges(vMinTreatmentDuration, vMaxTreatmentDuration, vMinUFVolume, vMaxUFVolume, vMinDialysateFlowRate, vMaxDialysateFlowRate): + msg = messageBuilder.buildMessage( 5, 4 * 7, + utils.toU32(vMinTreatmentDuration), + utils.toU32(vMaxTreatmentDuration), + utils.toU32(vMinUFVolume ), + utils.toU32(vMaxUFVolume ), + utils.toU32(vMinDialysateFlowRate), + utils.toU32(vMaxDialysateFlowRate) + ) + return messageBuilder.toFrames(msg) + +def setTreatmentParamRanges(): # ---------------vvvvv---------------- + subprocess.call(['cansend', 'can0', '040#A5.FF.FF.1A.00.18.02.00']) + subprocess.call(['cansend', 'can0', '040#00.00.E0.01.00.00.00.00']) + subprocess.call(['cansend', 'can0', '040#00.00.9A.09.00.00.96.00']) + subprocess.call(['cansend', 'can0', '040#00.00.26.02.00.00.C6.00']) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def buildSetTreatmentBloodFlowRate(vFlowSetPt, vMeasFlow = 0, vRotSpd = 0, vMotSpd = 0, vMCSpd = 0, vMCCurr = 0, vPWM = 0): + msg = messageBuilder.buildMessage( 5, 4 * 7, + utils.toU32(vFlowSetPt ), + utils.toU32(vMeasFlow ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vRotSpd ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vMotSpd ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vMCSpd ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vMCCurr ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vPWM ) # it has to be F32 and at this moment I haven't implemented and I don't currently need it + ) + return messageBuilder.toFrames(msg) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def setTreatmentBloodFlowRate(vFlowSetPt): + frames = buildSetTreatmentBloodFlowRate(vFlowSetPt) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def buildSetTreatmentDialysateFlowRate(vFlowSetPt, vMeasFlow = 0, vRotSpd = 0, vMotSpd = 0, vMCSpd = 0, vMCCurr = 0, vPWM = 0): + msg = messageBuilder.buildMessage( 8, 4 * 7, + utils.toU32(vFlowSetPt ), + utils.toU32(vMeasFlow ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vRotSpd ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vMotSpd ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vMCSpd ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vMCCurr ), # it has to be F32 and at this moment I haven't implemented and I don't currently need it + utils.toU32(vPWM ) # it has to be F32 and at this moment I haven't implemented and I don't currently need it + ) + return messageBuilder.toFrames(msg) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def setTreatmentDialysateFlowRate(vFlowSetPt): + frames = buildSetTreatmentDialysateFlowRate(vFlowSetPt) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '040#{}'.format(frame)]) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def buildTreatmentAdjustBloodDialysateResponse(vAccepted, vReason, vBloodRate, vDialysate): + msg = messageBuilder.buildMessage( 24, 4 * 4, + utils.toU32(vAccepted), + utils.toU32(vReason), + utils.toU32(vBloodRate), + utils.toU32(vDialysate) + ) + return messageBuilder.toFrames(msg) + +def sendTreatmentAdjustBloodDialysateResponse(vAccepted, vReason, vBloodRate, vDialysate): + frames = buildTreatmentAdjustBloodDialysateResponse(vAccepted, vReason, vBloodRate, vDialysate) + frames = messageBuilder.toCandumpFormat(frames) + for frame in frames: + subprocess.call(['cansend', 'can0', '020#{}'.format(frame)]) + + Index: shared/scripts/globals.py =================================================================== diff -u --- shared/scripts/globals.py (revision 0) +++ shared/scripts/globals.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 +# date 2020/02/21 +# author Behrouz NematiPour +# + +def SRSUI(vSRSUI = ""): + return "SRSUI " + "{}".format(vSRSUI).rjust(3, '0') Index: shared/scripts/messageBuilder.py =================================================================== diff -u --- shared/scripts/messageBuilder.py (revision 0) +++ shared/scripts/messageBuilder.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 +# date 2020/04/08 +# author Behrouz NematiPour +# + +import utils +import crc + +syncByte = 'A5' + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def toCandumpFormat(vMsg): + 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): + mLen = 16 + padded = utils.padding(vMsg, mLen) + frames = utils.partition(padded, mLen, False) + return frames + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def addCRC8(vString, vDelimiter = ""): + return vString + vDelimiter + crc.calcCRC8(vString, vDelimiter) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def buildMessage(vMsgID, vLen, *vArgs): + msg = "" + seq = 1 + msg += utils.toU16(seq) # always used seq# 1 (for now) + msg += utils.toU16(vMsgID) + msg += utils.toU08(vLen) + for arg in vArgs: + msg += arg + msg += crc.calcCRC8(msg) + return syncByte + msg + + Index: shared/scripts/names.py =================================================================== diff -u -red536b18e1dc80a79a1988052195fa34f9f010d4 -r40df2a58a855b561c1ca8dabd3b272ac48b8924e --- shared/scripts/names.py (.../names.py) (revision ed536b18e1dc80a79a1988052195fa34f9f010d4) +++ shared/scripts/names.py (.../names.py) (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -1,5 +1,17 @@ # encoding: UTF-8 +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 names.py +# date 2019/10/10 +# author Behrouz NematiPour +# + o_QQuickView = {"type": "QQuickView", "unnamed": 1, "visible": True} # Home Screen @@ -26,11 +38,39 @@ o_Overlay = {"container": o_QQuickView , "type": "Overlay" , "unnamed": 1, "visible": True} o_modalDialog = {"container": o_Overlay , "id": "_backgroundRect", "type": "Rectangle", "unnamed": 1, "visible": True} - # Power off o_poweroffButton = {"container": o_settingsHome, "id": "_poweroffButton", "type": "TouchRect" , "unnamed": 1, "visible": True} o_poweroff_shutdown = {"container": o_QQuickView , "id": "_shutdownRect" , "type": "TouchRect" , "unnamed": 1, "visible": True} o_poweroff_cancel = {"container": o_QQuickView , "id": "_cancelTouch" , "type": "TouchRect" , "unnamed": 1, "visible": True} o_poweroff_notification = {"container": o_Overlay , "id": "_titleText" , "type": "TitleText" , "unnamed": 1, "visible": True, "type": "Text", "text": "System is shutting down"} o_poweroff_rejection = {"container": o_Overlay , "id": "_titleText" , "type": "TitleText" , "unnamed": 1, "visible": True, "type": "Text"} +# Treatment Start Screen +o_treatmentStart_TreatmentStart = {"container": o_QQuickView, "id": "_treatmentStart", "type": "TreatmentStart", "unnamed": 1, "visible": True} +o_treatmentStart_backgroundRect_Rectangle = {"container": o_treatmentStart_TreatmentStart, "id": "_backgroundRect", "type": "Rectangle", "unnamed": 1, "visible": True} +o_treatmentStart_flowsTouchArea_TreatmentFlows = {"container": o_treatmentStart_TreatmentStart, "id": "_flowsTouchArea", "type": "TreatmentFlows", "unnamed": 1, "visible": True} +o_treatmentStart_vitalsTouchArea_TreatmentVitals = {"container": o_treatmentStart_TreatmentStart, "id": "_vitalsTouchArea", "type": "TreatmentVitals", "unnamed": 1, "visible": True} +o_treatmentStart_pressureTouchArea_TreatmentPressure = {"container": o_treatmentStart_TreatmentStart, "id": "_pressureTouchArea", "type": "TreatmentPressure", "unnamed": 1, "visible": True} +o_treatmentStart_shape_Shape = {"container": o_treatmentStart_TreatmentStart, "id": "_shape", "type": "Shape", "unnamed": 1, "visible": True} +o_treatmentStart_ultrafiltrationTouchArea_TreatmentUltrafiltration = {"container": o_treatmentStart_TreatmentStart, "id": "_ultrafiltrationTouchArea", "type": "TreatmentUltrafiltration", "unnamed": 1, "visible": True} +o_treatmentStart_fluidManagementTouchArea_TouchArea = {"container": o_treatmentStart_TreatmentStart, "id": "_fluidManagementTouchArea", "type": "TouchArea", "unnamed": 1, "visible": True} +o_treatmentStart_solutionInfusionTouchArea_TouchArea = {"container": o_treatmentStart_TreatmentStart, "id": "_solutionInfusionTouchArea", "type": "TouchArea", "unnamed": 1, "visible": True} + +# Blood/Dialysate Treatment Section +o_treatmentStart_FLOWS_Text = {"container": o_treatmentStart_TreatmentStart, "text": "FLOWS", "type": "Text", "unnamed": 1, "visible": True} +# Blood +o_treatmentStart_Blood_Text = {"container": o_treatmentStart_TreatmentStart, "text": "Blood", "type": "Text", "unnamed": 1, "visible": True} +o_treatmentStart_0_Text = {"container": o_treatmentStart_TreatmentStart, "text": 0, "type": "Text", "unnamed": 1, "visible": True} +o_treatmentStart_mL_min_Text = {"container": o_treatmentStart_TreatmentStart, "text": "mL/min", "type": "Text", "unnamed": 1, "visible": True} +# Dialysate +o_treatmentStart_Dialysate_Text = {"container": o_treatmentStart_TreatmentStart, "text": "Dialysate", "type": "Text", "unnamed": 1, "visible": True} +o_treatmentStart_0_Text_2 = {"container": o_treatmentStart_TreatmentStart, "occurrence": 2, "text": 0, "type": "Text", "unnamed": 1, "visible": True} +o_treatmentStart_mL_min_Text_2 = {"container": o_treatmentStart_TreatmentStart, "occurrence": 2, "text": "mL/min", "type": "Text", "unnamed": 1, "visible": True} + +# Treatment Parameter Range +o_dialysateFlowSlider_Slider = {"container": o_Overlay, "id": "_dialysateFlowSlider", "type": "Slider", "unnamed": 1, "visible": True} +o_bloodFlowSlider_Slider = {"container": o_Overlay, "id": "_bloodFlowSlider", "type": "Slider", "unnamed": 1, "visible": True} + +o_treatmentStart_225_Text = {"container": o_treatmentStart_TreatmentStart, "text": 225, "type": "Text", "unnamed": 1, "visible": True} +o_treatmentStart_200_Text = {"container": o_treatmentStart_TreatmentStart, "text": 200, "type": "Text", "unnamed": 1, "visible": True} +o_TouchRect = {"container": o_Overlay, "type": "TouchRect", "unnamed": 1, "visible": True} Index: shared/scripts/unittests.py =================================================================== diff -u --- shared/scripts/unittests.py (revision 0) +++ shared/scripts/unittests.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 +# date 2019/11/20 +# author Behrouz NematiPour +# +import test +import sys +import crc + +def testPythonVersion(): + test.compare(sys.version_info.major,3) + test.compare(sys.version_info.minor,6) + test.compare(sys.version_info.micro,4) + +def testcrc8(): + 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') Index: shared/scripts/utils.py =================================================================== diff -u --- shared/scripts/utils.py (revision 0) +++ shared/scripts/utils.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 +# date 2019/11/21 +# author Behrouz NematiPour +# + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def toUXX(vValue, vByteCount, vDelimiter): + x = '{0:0{1}X}'.format(vValue, vByteCount, 'x') + #n = 2 + #bytes = [x[i-n:i] for i in range(len(x),0, -n)] + bytes = partition(x, 2) + return vDelimiter.join(bytes) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def toU32(vValue, vDelimiter = ""): + return toUXX(vValue, 8, vDelimiter) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def toU16(vValue, vDelimiter = ""): + return toUXX(vValue, 4, vDelimiter) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def toU08(vValue, vDelimiter = ""): + return toUXX(vValue, 2, vDelimiter) + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def partition(vString, vPart, vRightDirection = True): + if vRightDirection: + list = [vString[i - vPart : i] for i in range(len(vString), 0, -vPart)] + else: + list = [vString[i : i + vPart] for i in range(0, len(vString), vPart)] + return list + +## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def padding(vString, vLen): + lStr = len(vString) + lPad = int(lStr / vLen) * vLen + ( vLen * (1 if lStr % vLen else 0) ) + return vString.ljust(lPad, "0") + Index: suite.conf =================================================================== diff -u -rb8ec67700eef6b0581a997b75e2bf30460fba0f4 -r40df2a58a855b561c1ca8dabd3b272ac48b8924e --- suite.conf (.../suite.conf) (revision b8ec67700eef6b0581a997b75e2bf30460fba0f4) +++ suite.conf (.../suite.conf) (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -5,6 +5,6 @@ IMPLICITAUTSTART=0 LANGUAGE=Python OBJECTMAPSTYLE=script -TEST_CASES=tst_pythonversion tst_homescreen +TEST_CASES=tst_GlobalTests tst_HomeScreen tst_ServiceShutdown tst_TreatmentScreen tst_Treatment_BloodDialysate_Section tst_Treatment_ParametersRange tst_Treatment_Adjustment_BloodDialysate VERSION=3 WRAPPERS=Qt Index: tst_GlobalTests/test.py =================================================================== diff -u --- tst_GlobalTests/test.py (revision 0) +++ tst_GlobalTests/test.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 tst_GlobalTests +# date 2019/11/20 +# author Behrouz NematiPour +# + +import unittests +#import denaliMessages + +def main(): + unittests.testPythonVersion() + unittests.testcrc8() Index: tst_HomeScreen/test.py =================================================================== diff -u --- tst_HomeScreen/test.py (revision 0) +++ tst_HomeScreen/test.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 tst_HomeScreen +# date 2019/11/21 +# author Behrouz NematiPour +# + +import names + +def main(): + startApplication("denaliSquish") + + test.compare( waitForObjectExists(names.o_treatmentHome).visible, True) + test.compare(str(waitForObjectExists(names.o_treatmentHome_startTreatment ).text.text), "START TREATMENT" , "SRSUI 024") + test.compare(str(waitForObjectExists(names.o_treatmentHome_createTreatment).text.text), "CREATE TREATMENT" , "SRSUI 532") + + test.compare( waitForObjectExists(names.o_mainMenu).visible, True) + test.compare(str(waitForObjectExists(names.o_mainMenu_treatment).text.text), "Treatment" , "SRSUI 534") + test.compare(str(waitForObjectExists(names.o_mainMenu_manager ).text.text), "Manager" , "SRSUI 026") + test.compare(str(waitForObjectExists(names.o_mainMenu_settings ).text.text), "Settings" , "SRSUI 028") + + mouseClick (waitForObjectExists(names.o_mainMenu_manager)) + test.compare(waitForObjectExists(names.o_managerHome ).visible, True , "SRSUI 027") + + mouseClick (waitForObjectExists(names.o_mainMenu_settings )) + test.compare(waitForObjectExists(names.o_settingsHome ).visible, True , "SRSUI 029") + + mouseClick (waitForObjectExists(names.o_mainMenu_treatment)) + test.compare(waitForObjectExists(names.o_treatmentHome).visible, True , "SRSUI 535") + Index: tst_ServiceShutdown/test.py =================================================================== diff -u --- tst_ServiceShutdown/test.py (revision 0) +++ tst_ServiceShutdown/test.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 tst_ServiceShutdown +# date 2019/11/20 +# author Behrouz NematiPour +# + +import names +import time +import globals +import denaliMessages + +################################################################################ +# This test need to be changed when the Service screen has been implemented # +# This is only checking the functionality exists and it's working # +################################################################################ + +def test_MainMenu_CurrentItem(vSRSUI = ""): + #test.compare(waitForObjectExists(names.o_mainMenu).currentIndex, 0) + test.compare(str(waitForObjectExists(names.o_mainMenu).currentTitle), "Treatment", globals.SRSUI(vSRSUI)) + +def gotoScreenNtest_Contains_PowerOffButton(vSRSUI = ""): + mouseClick (waitForObjectExists(names.o_mainMenu_settings )) + test.compare(waitForObjectExists(names.o_settingsHome ).visible, True, globals.SRSUI(vSRSUI)) + +def gotoScreenNtest_Contains_TreatmentHome(vSRSUI = ""): + mouseClick (waitForObjectExists(names.o_mainMenu_treatment)) + test.compare(waitForObjectExists(names.o_treatmentHome).visible, True, globals.SRSUI(vSRSUI)) + +def showNtest_PowerOffDialog(vSRSUI = ""): + denaliMessages.show_PowerOffDialog() + test_PowerOffDialog(vSRSUI) + +def hideNtest_PowerOffDialog(vSRSUI = ""): + denaliMessages.hide_PowerOffDialog() + test_PowerOffButton(vSRSUI) + +def showNtest_PowerOffNotificationDialog(vSRSUI = ""): + mSRSUI = globals.SRSUI(vSRSUI) + denaliMessages.show_PowerOffNotificationDialog() + test.compare(str(waitForObjectExists(names.o_poweroff_notification).baseUrl.path), "/dialogs/AutoHideInfo.qml", mSRSUI + " - Dialog") + constantPartOfTheMessage = "System is shutting down" + test.compare(str(waitForObjectExists(names.o_poweroff_notification).text)[0:len(constantPartOfTheMessage)], constantPartOfTheMessage, mSRSUI + " - Message Text") + time.sleep(5) # dialog timeout + time.sleep(1) # animation transition + + +def showNtest_PowerOffRejectionDialog(vSRSUI = ""): + mSRSUI = globals.SRSUI(vSRSUI) + denaliMessages.show_PowerOffRejectionDialog() + test.compare(str(waitForObjectExists(names.o_poweroff_rejection).baseUrl.path), "/dialogs/AutoHideInfo.qml", mSRSUI + " - Dialog") + constantPartOfTheMessage = "Cannot shutdown during " # there might be the reason, concatenated at the end of the string. + test.compare(str(waitForObjectExists(names.o_poweroff_rejection).text)[0:len(constantPartOfTheMessage)], constantPartOfTheMessage, mSRSUI + " - Message Text") + time.sleep(2) # dialog timeout + time.sleep(1) # animation transition + + +def test_PowerOffButton(vSRSUI = ""): + test.compare(waitForObjectExists(names.o_poweroffButton).visible, True, globals.SRSUI(vSRSUI)) + +def test_PowerOffDialog(vSRSUI = ""): + test.compare(waitForObjectExists(names.o_modalDialog).visible, True, globals.SRSUI(vSRSUI)) + +def testNclick_ShutdownButton_onPowerOffConfirm(vSRSUI = ""): + test.compare(waitForObjectExists(names.o_poweroff_shutdown).visible, True, globals.SRSUI(vSRSUI)) + mouseClick (waitForObjectExists(names.o_poweroff_shutdown)) + time.sleep (1) # Wait for the animation + +def testNclick_CancelButton_onPowerOffConfirm(vSRSUI = ""): + test.compare(waitForObjectExists(names.o_poweroff_cancel).visible, True, globals.SRSUI(vSRSUI)) + mouseClick (waitForObjectExists(names.o_poweroff_cancel)) + time.sleep (1) # Wait for the animation + +def main(): + # Start the Application + startApplication("denaliSquish") + + # 535 : The "Treatment" button shall be selected by default on the Home Screen. + test_MainMenu_CurrentItem(535) + + # 028 : The Home Screen shall display a "Settings" button. + test.compare(str(waitForObjectExists(names.o_mainMenu_settings ).text.text), "Settings", globals.SRSUI(28)) + + # 029 : Upon "Settings" button depress on the Home Screen; the UI shall navigate the user to the Device Settings Screen. + gotoScreenNtest_Contains_PowerOffButton(29) + + # 514 : The UI shall display a "Power Off Confirmation" screen when the HD Device requests power off. + showNtest_PowerOffDialog(514) + # 556 : The UI shall hide the "Power Off Confirmation" screen after 1 minute inactivity, waiting for user interaction (upon HD Device messaging). + hideNtest_PowerOffDialog(556) + + # 015 : The "Power Off Confirmation" screen shall display a "CANCEL" button. + showNtest_PowerOffDialog(514) + testNclick_CancelButton_onPowerOffConfirm(15) + + # 016 : Upon "CANCEL" button depress, the UI shall navigate the user to its previous screen. + test_PowerOffButton(16) + + # 017 : The "Power Off Confirmation" screen shall display a "SHUTDOWN" button. + showNtest_PowerOffDialog(514) + testNclick_ShutdownButton_onPowerOffConfirm(17) + + # 566 : The UI shall display the "Power Off Notification" Dialog when the HD Device confirms power off. + showNtest_PowerOffNotificationDialog(566) + + # 567 : The UI shall display the "Power Off Rejection" Dialog when the HD Device rejects power off. + showNtest_PowerOffRejectionDialog(567) + + # 534 : The "Treatment" button shall be selected by default on the Home Screen. + gotoScreenNtest_Contains_TreatmentHome(534) + Index: tst_TreatmentScreen/test.py =================================================================== diff -u --- tst_TreatmentScreen/test.py (revision 0) +++ tst_TreatmentScreen/test.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 tst_TreatmentScreen +# date 2020/04/06 +# author Behrouz NematiPour +# + +import names + +def main(): + startApplication("denaliSquish") + mouseClick(waitForObject(names.o_treatmentHome_startTreatment)) + + test.compare(waitForObjectExists(names.o_treatmentStart_backgroundRect_Rectangle).visible, True) + + test.compare(waitForObjectExists(names.o_treatmentStart_flowsTouchArea_TreatmentFlows).visible, True) + test.compare(waitForObjectExists(names.o_treatmentStart_vitalsTouchArea_TreatmentVitals).visible, True) + test.compare(waitForObjectExists(names.o_treatmentStart_pressureTouchArea_TreatmentPressure).visible, True) + + test.compare(waitForObjectExists(names.o_treatmentStart_shape_Shape).visible, True) + + test.compare(waitForObjectExists(names.o_treatmentStart_ultrafiltrationTouchArea_TreatmentUltrafiltration).visible, True) + test.compare(waitForObjectExists(names.o_treatmentStart_fluidManagementTouchArea_TouchArea).visible, True) + test.compare(waitForObjectExists(names.o_treatmentStart_solutionInfusionTouchArea_TouchArea).visible, True) + Index: tst_Treatment_Adjustment_BloodDialysate/test.py =================================================================== diff -u --- tst_Treatment_Adjustment_BloodDialysate/test.py (revision 0) +++ tst_Treatment_Adjustment_BloodDialysate/test.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 tst_Treatment_Adjustment_BloodDialysate +# date 2020/04/08 +# author Behrouz NematiPour +# + +import names +import time +import denaliMessages + +def gotoScreenNtest_Contains_FlowsSection(): + mouseClick(waitForObject(names.o_treatmentHome_startTreatment)) + test.compare(waitForObjectExists(names.o_treatmentStart_flowsTouchArea_TreatmentFlows).visible, True) + +def gotoScreenNTest_Contains_Ranges(): + mouseClick(waitForObject(names.o_treatmentStart_flowsTouchArea_TreatmentFlows)) + test.compare(waitForObjectExists(names.o_modalDialog).visible, True) + +def main(): + startApplication("denaliSquish") + + gotoScreenNtest_Contains_FlowsSection() + time.sleep(1) + + denaliMessages.setTreatmentBloodFlowRate(175) + denaliMessages.setTreatmentDialysateFlowRate(250) + + gotoScreenNTest_Contains_Ranges() + time.sleep(1) + + denaliMessages.setTreatmentParamRanges() + denaliMessages.send_acknowledge_UI() + + mouseClick(waitForObject(names.o_bloodFlowSlider_Slider), 190, 4, Qt.LeftButton) + mouseClick(waitForObject(names.o_dialysateFlowSlider_Slider), 79, 5, Qt.LeftButton) + + test.compare(waitForObjectExists(names.o_bloodFlowSlider_Slider).value, 225) + test.compare(waitForObjectExists(names.o_dialysateFlowSlider_Slider).value, 200) + mouseClick(waitForObject(names.o_TouchRect)) + + denaliMessages.sendTreatmentAdjustBloodDialysateResponse(0, 3, 175, 250) + + time.sleep(2) + + mouseClick(waitForObject(names.o_bloodFlowSlider_Slider), 190, 4, Qt.LeftButton) + mouseClick(waitForObject(names.o_dialysateFlowSlider_Slider), 79, 5, Qt.LeftButton) + + test.compare(waitForObjectExists(names.o_bloodFlowSlider_Slider).value, 225) + test.compare(waitForObjectExists(names.o_dialysateFlowSlider_Slider).value, 200) + + denaliMessages.sendTreatmentAdjustBloodDialysateResponse(1, 0, + waitForObjectExists(names.o_bloodFlowSlider_Slider).value, + waitForObjectExists(names.o_dialysateFlowSlider_Slider).value + ) + + time.sleep(1.0) + + denaliMessages.setTreatmentBloodFlowRate(225) + denaliMessages.setTreatmentDialysateFlowRate(200) + + test.compare(str(waitForObjectExists(names.o_treatmentStart_225_Text).text), "225") + test.compare(str(waitForObjectExists(names.o_treatmentStart_200_Text).text), "200") + time.sleep(1.0) + Index: tst_Treatment_BloodDialysate_Section/test.py =================================================================== diff -u --- tst_Treatment_BloodDialysate_Section/test.py (revision 0) +++ tst_Treatment_BloodDialysate_Section/test.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 tst_Treatment_BloodDialysate_Section +# date 2020/04/06 +# author Behrouz NematiPour +# + +import names + +def main(): + startApplication("denaliSquish") + + # Goto Treatment Screen + mouseClick(waitForObject(names.o_treatmentHome_startTreatment)) + + # Flows section is available + test.compare(waitForObjectExists(names.o_treatmentStart_flowsTouchArea_TreatmentFlows).visible, True) + + # Flow title visible + test.compare(waitForObjectExists(names.o_treatmentStart_FLOWS_Text).visible, True) + + #Blood Section + test.compare(waitForObjectExists(names.o_treatmentStart_Blood_Text).visible, True) + test.compare(str(waitForObjectExists(names.o_treatmentStart_Blood_Text).text), "Blood") + test.compare(waitForObjectExists(names.o_treatmentStart_0_Text).visible, True) + test.compare(waitForObjectExists(names.o_treatmentStart_mL_min_Text).visible, True) + test.compare(str(waitForObjectExists(names.o_treatmentStart_mL_min_Text).text), "mL/min") + + # Dialysate Section + test.compare(waitForObjectExists(names.o_treatmentStart_Dialysate_Text).visible, True) + test.compare(str(waitForObjectExists(names.o_treatmentStart_Dialysate_Text).text), "Dialysate") + test.compare(waitForObjectExists(names.o_treatmentStart_0_Text_2).visible, True) + test.compare(waitForObjectExists(names.o_treatmentStart_mL_min_Text_2).visible, True) + test.compare(str(waitForObjectExists(names.o_treatmentStart_mL_min_Text_2).text), "mL/min") + Index: tst_Treatment_ParametersRange/test.py =================================================================== diff -u --- tst_Treatment_ParametersRange/test.py (revision 0) +++ tst_Treatment_ParametersRange/test.py (revision 40df2a58a855b561c1ca8dabd3b272ac48b8924e) @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- + +## +# Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +# copyright +# 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 tst_Treatment_ParametersRange +# date 2020/04/06 +# author Behrouz NematiPour +# + +import names +import time +import denaliMessages + +def gotoScreenNtest_Contains_FlowsSection(): + mouseClick(waitForObject(names.o_treatmentHome_startTreatment)) + test.compare(waitForObjectExists(names.o_treatmentStart_flowsTouchArea_TreatmentFlows).visible, True) + +def gotoScreenNTest_Contains_Ranges(): + mouseClick(waitForObject(names.o_treatmentStart_flowsTouchArea_TreatmentFlows)) + test.compare(waitForObjectExists(names.o_modalDialog).visible, True) + +def test_Dialysate_Ranges(): + test.compare(waitForObjectExists(names.o_dialysateFlowSlider_Slider).minimum, 150) + test.compare(waitForObjectExists(names.o_dialysateFlowSlider_Slider).maximum, 550) + test.compare(str(waitForObjectExists(names.o_dialysateFlowSlider_Slider).minText.text), "150mL/min") + test.compare(str(waitForObjectExists(names.o_dialysateFlowSlider_Slider).maxText.text), "550mL/min") + +def main(): + startApplication("denaliSquish") + + gotoScreenNtest_Contains_FlowsSection() + + gotoScreenNTest_Contains_Ranges() + time.sleep(1) + + denaliMessages.setTreatmentParamRanges() + denaliMessages.send_acknowledge_UI() + + test_Dialysate_Ranges() + Fisheye: Tag 40df2a58a855b561c1ca8dabd3b272ac48b8924e refers to a dead (removed) revision in file `tst_homescreen/test.py'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 40df2a58a855b561c1ca8dabd3b272ac48b8924e refers to a dead (removed) revision in file `tst_pythonversion/test.py'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 40df2a58a855b561c1ca8dabd3b272ac48b8924e refers to a dead (removed) revision in file `tst_serviceshutdown/globals.py'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 40df2a58a855b561c1ca8dabd3b272ac48b8924e refers to a dead (removed) revision in file `tst_serviceshutdown/test.py'. Fisheye: No comparison available. Pass `N' to diff?