Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `denali.pro'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `denali.pro.user'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `denali.qrc'. Fisheye: No comparison available. Pass `N' to diff? Index: leahi.pro =================================================================== diff -u --- leahi.pro (revision 0) +++ leahi.pro (revision 9363dbc93c2be5d664c0ca2a565d8206679d9bf3) @@ -0,0 +1,688 @@ +QT += qml quick serialbus concurrent charts bluetooth +CONFIG += c++17 warn_on +# CONFIG += disable-desktop +# QMAKE_CXX = clazy +QMAKE_CXXFLAGS += -Wall -Werror -Wextra -Wimplicit-fallthrough=3 # -save-temps # see .ii +# -Wpedantic -Wconversion -Wshadow # these can't always be used, since it gives errors in Qt library. + +# Leahi Digi Board +DEFINES += LEAHI_DIGI_BOARD + +TRANSLATIONS += \ + resources/translations/translation_es.ts \ + resources/translations/translation_de.ts + +#CONFIG += disable_crc +disable_crc { + message( *** IMPORTANT : DISABLED CRC CHECK *** ) + DEFINES += DISABLE_CRC +} + +#CONFIG += disable_keepalive +disable_keepalive { + message( *** IMPORTANT : DISABLED KEEP ALIVE *** ) + DEFINES += DISABLE_KEEP_ALIVE +} + +# added this section to detect which compiler is running +# to decide device dependent decisions +# by defining a MACRO +# and use that MACRO for conditional build +message($$QMAKESPEC) +linux-g++ { + message("Building for desktop") + DEFINES += BUILD_FOR_DESKTOP +} + +linux-oe-generic-g++ { + message("Building for target") + DEFINES += BUILD_FOR_TARGET +} + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Refer to the documentation for the +# deprecated API to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +INCLUDEPATH += \ + common \ + sources \ + sources/device \ + sources/storage \ + sources/gui \ + sources/canbus \ + sources/utility \ + sources/wifi \ + sources/bluetooth \ + sources/cloudsync \ + sources/abstract \ + sources/model \ + sources/model/confirm \ + sources/model/settings \ + sources/model/ui/data \ + sources/model/hd/adjustment \ + sources/model/hd/adjustment/disinfect \ + sources/model/hd/adjustment/settings \ + sources/model/hd/adjustment/pretreatment \ + sources/model/hd/adjustment/treatment \ + sources/model/hd/adjustment/posttreatment \ + sources/model/hd/alarm \ + sources/model/hd/data \ + sources/model/hd/data/post \ + sources/model/hd/data/pretreatment \ + sources/model/hd/data/treatment \ + sources/model/hd/data/posttreatment \ + sources/model/hd/data/treatmentlog \ + sources/model/dg/data \ + sources/model/dg/data/post \ + sources/model/dg/data/pretreatment \ + sources/model/dg/data/disinfect \ + sources/model/dg/adjustment \ + sources/model/dg/adjustment/settings \ + sources/view \ + sources/view/confirm \ + sources/view/settings \ + sources/view/pretreatment \ + sources/view/ui/data \ + sources/view/hd/adjustment/common \ + sources/view/hd/adjustment \ + sources/view/hd/adjustment/pretreatment \ + sources/view/hd/adjustment/treatment \ + sources/view/hd/adjustment/posttreatment \ + sources/view/hd/adjustment/disinfect \ + sources/view/hd/alarm \ + sources/view/hd/data \ + sources/view/hd/data/post \ + sources/view/hd/data/pretreatment \ + sources/view/hd/data/treatment \ + sources/view/hd/data/posttreatment \ + sources/view/dg/data \ + sources/view/dg/data/post \ + sources/view/dg/data/pretreatment \ + sources/view/dg/data/disinfect + +HEADERS += \ + \ # common + common/AlarmDefs.h \ + common/Compatible.h \ + common/DGDefs.h \ + common/HDDefs.h \ + common/MsgDefs.h \ + \ # Main + sources/main.h \ + sources/Threads.h \ + sources/MainTimer.h \ + sources/AlarmGenerator.h \ + sources/ApplicationPost.h \ + sources/device/DeviceGlobals.h \ + sources/device/DeviceError.h \ + \ # Controllers + sources/ApplicationController.h \ + sources/device/DeviceController.h \ + sources/storage/Settings.h \ + sources/storage/TreatmentLog.h \ + sources/wifi/WifiInterface.h \ + sources/bluetooth/BluetoothInterface.h \ + sources/cloudsync/CloudSyncController.h \ + \ # ---------- Models ---------- + sources/model/MModel.h \ + sources/model/MAbstract.h \ + sources/model/MAbstractDynamic.h \ + sources/device/DeviceModels.h \ + \ # ---------- Models - confirm + sources/model/confirm/MDuetConfirmHDi.h \ + \ # ---------- Models - POST + sources/model/dg/data/post/MDGPostFinalResultData.h \ + sources/model/dg/data/post/MDGPostSingleResultData.h \ + sources/model/hd/data/post/MHDPostFinalResultData.h \ + sources/model/hd/data/post/MHDPostSingleResultData.h \ + sources/model/hd/data/post/MUIPostFinalResultHDRequest.h \ + \ # ---------- Models - settings + sources/model/settings/MSettings.h \ + sources/model/settings/MWifiNetwork.h \ + sources/model/settings/MBluetooth.h \ + sources/model/ui/data/MUIBloodPressureData.h \ + sources/model/hd/adjustment/settings/MAdjustHDServiceModeResponse.h \ + sources/model/dg/adjustment/settings/MAdjustDGSerialNumberResponse.h \ + sources/model/hd/adjustment/settings/MAdjustHDSerialNumberResponse.h \ + sources/model/dg/adjustment/settings/MAdjustDGServiceDatesResponse.h \ + sources/model/hd/adjustment/settings/MAdjustHDServiceDatesResponse.h \ + sources/model/hd/adjustment/settings/MAdjustHDInstitutionalRecordResponse.h \ + sources/model/dg/adjustment/settings/MDuetRoWaterDG.h \ + \ # ---------- Models - Alarm + sources/model/hd/alarm/MAlarmStatusData.h \ + sources/model/hd/alarm/MAlarmTriggered.h \ + sources/model/hd/alarm/MAlarmCleared.h \ + sources/model/hd/alarm/MAlarmClearedCondition.h \ + sources/model/hd/alarm/MAlarmActiveList.h \ + \ # ---------- Models - States Data + sources/model/hd/data/MHDOperationModeData.h \ + sources/model/hd/data/pretreatment/MPreTreatmentStatesData.h \ + sources/model/hd/data/treatment/MTreatmentStatesData.h \ + sources/model/hd/data/posttreatment/MPostTreatmentStatesData.h \ + \ # ---------- Models - HD - Adjustment + sources/model/hd/adjustment/MAdjustRequestsBase.h \ + sources/model/hd/adjustment/MAdjustPowerOff.h \ + sources/model/hd/adjustment/settings/MAdjustHDRequests.h \ + \ # ---------- Models - HD - Adjustment - Settings + sources/model/hd/adjustment/settings/MAdjustHDVersionsRequest.h \ + sources/model/hd/adjustment/settings/MAdjustHDVersionsResponse.h \ + sources/model/hd/adjustment/settings/MAdjustHDDateTimeResponse.h \ + sources/model/hd/adjustment/settings/MAdjustHDAlarmVolumeResponse.h \ + \ # ---------- Models - HD - Adjustment - Pre-Treatment + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustRequests.h \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustInitTreatmentResponse.h \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustParametersValidationResponse.h \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustWaterSampleResponse.h \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustDisposablesConfirmResponse.h \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustDisposablesPrimeResponse.h \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustPatientConnectionBeginResponse.h \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustUltrafiltrationInitResponse.h \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustPatientConnectionConfirmResponse.h \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustStartTreatmentResponse.h \ + \ # ---------- Models - HD - Adjustment - In-Treatment + sources/model/hd/adjustment/treatment/MTreatmentAdjustRequests.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustDurationResponse.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustBloodDialysateResponse.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustUltrafiltrationStateResponse.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustUltrafiltrationEditResponse.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustUltrafiltrationConfirmResponse.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustSalineResponse.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustHeparinResponse.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustPressuresLimitsResponse.h \ + \ # ---------- Models - HD - Adjustment - End-Treatment + sources/model/hd/adjustment/treatment/MTreatmentAdjustRinsebackResponse.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustRecirculateResponse.h \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustEndResponse.h \ + \ # ---------- Models - HD - Adjustment - Post-Treatment + sources/model/hd/adjustment/posttreatment/MPostTreatmentAdjustRequests.h \ + sources/model/hd/adjustment/posttreatment/MPostTreatmentAdjustTreatmentLogResponse.h \ + sources/model/hd/adjustment/posttreatment/MPostTreatmentAdjustDisposablesRemovalConfirmResponse.h \ + sources/model/hd/adjustment/posttreatment/MPostTreatmentAdjustPatientDisconnectionConfirmResponse.h \ + \ # ---------- Models - HD - Adjustment - Disinfeection + sources/model/hd/adjustment/disinfect/MDisinfectAdjustModeRequests.h \ + sources/model/hd/adjustment/disinfect/MDisinfectAdjustModeResponse.h \ + sources/model/hd/adjustment/disinfect/MDisinfectAdjustStartResponse.h \ + sources/model/hd/adjustment/disinfect/MDisinfectAdjustStartRequests.h \ + \ # ---------- Models - HD - Data - Pre-Treatment - Progress + sources/model/hd/data/pretreatment/MPreTreatmentSelfTestNoCartridgeData.h \ + sources/model/hd/data/pretreatment/MPreTreatmentSelfTestDryData.h \ + sources/model/hd/data/pretreatment/MPreTreatmentDisposablesPrimeData.h \ + \ # ---------- Models - HD - Data + sources/model/hd/data/MHDDebugText.h \ + sources/model/hd/data/MHDGeneralEvent.h \ + sources/model/hd/data/MHDAccelerometerData.h \ + sources/model/hd/data/MHDSyringePumpData.h \ + sources/model/hd/data/MHDAirBubbleData.h \ + sources/model/hd/data/MHDAirTrapData.h \ + sources/model/hd/data/MHDBloodLeakData.h \ + sources/model/hd/data/MTreatmentRangesData.h \ + sources/model/hd/data/treatment/MTreatmentTimeData.h \ + sources/model/hd/data/treatment/MTreatmentBloodFlowData.h \ + sources/model/hd/data/treatment/MTreatmentDialysateFlowData.h \ + sources/model/hd/data/treatment/MTreatmentOutletFlowData.h \ + sources/model/hd/data/treatment/MTreatmentPressureOcclusionData.h \ + sources/model/hd/data/treatment/MTreatmentSalineData.h \ + sources/model/hd/data/treatment/MTreatmentHeparinData.h \ + sources/model/hd/data/treatment/MTreatmentRinsebackData.h \ + sources/model/hd/data/treatment/MTreatmentRecirculateData.h \ + sources/model/hd/data/treatment/MTreatmentBloodPrimeData.h \ + sources/model/hd/data/treatment/MTreatmentStopData.h \ + sources/model/hd/data/post/MHDRTCEpochData.h \ + sources/model/hd/data/MHDUsageInfoResponse.h \ + \ # ---------- Models - HD - Data - Treatment Log + sources/model/hd/data/treatmentlog/MTreatmentLogAlarmData.h \ + sources/model/hd/data/treatmentlog/MTreatmentLogAvrgeData.h \ + sources/model/hd/data/treatmentlog/MTreatmentLogEventData.h \ + \ # ---------- Models - DG - Adjustment + sources/model/dg/adjustment/settings/MAdjustDGRequests.h \ + sources/model/dg/adjustment/settings/MAdjustDGCleaningUsageResponse.h \ + \ # ---------- Models - DG - Adjustment - Settings + sources/model/dg/adjustment/settings/MAdjustDGVersionsResponse.h \ + sources/model/dg/adjustment/settings/MAdjustDGDateTimeResponse.h \ + \ # ---------- Models - DG - Data - Pre-Treatment - Progress + sources/model/dg/data/pretreatment/MDGFilterFlushData.h \ + \ # ---------- Models - DG - Data - Disinfect - Progress + \ # ---------- Models - DG - Data + sources/model/dg/data/MDGDebugText.h \ + sources/model/dg/data/MDGGeneralEvent.h \ + sources/model/dg/data/MDGDrainPumpData.h \ + sources/model/dg/data/MDGHeatersData.h \ + sources/model/dg/data/MDGLoadCellReadingsData.h \ + sources/model/dg/data/MDGOperationModeData.h \ + sources/model/dg/data/MDGPressuresData.h \ + sources/model/dg/data/MDGReservoirData.h \ + sources/model/dg/data/MDGROPumpData.h \ + sources/model/dg/data/MDGTemperaturesData.h \ + sources/model/dg/data/MDGValvesStatesData.h \ + sources/model/dg/data/MDGAccelerometerData.h \ + sources/model/dg/data/MDGConductivityData.h \ + \ # CANBus + sources/canbus/CanInterface.h \ + sources/canbus/FrameInterface.h \ + \ # Denali Message + sources/canbus/MessageGlobals.h \ + sources/canbus/MessageAcknowModel.h \ + sources/canbus/MessageBuilder.h \ + sources/canbus/MessageInterpreter.h \ + sources/canbus/MessageDispatcher.h \ + \ # Gui + sources/gui/GuiGlobals.h \ + sources/gui/GuiView.h \ + sources/gui/GuiController.h \ + \ # ---------- Views ---------- + sources/view/VTreatmentCreate.h \ + sources/view/VEventSpy.h \ + sources/view/VView.h \ + sources/view/VGeneralEvent.h \ + sources/device/DeviceView.h \ + \ # ---------- Views - CONFIRM + sources/view/confirm/VConfirm.h \ + \ # ---------- Views - POST + sources/view/dg/data/post/VDGPOSTData.h \ + \ # ---------- Views - Settings + sources/view/settings/VDateTime.h \ + sources/view/settings/VSettings.h \ + sources/view/settings/VBluetooth.h \ + sources/view/settings/VNetworkModel.h \ + sources/view/settings/VAdjustmentVersions.h \ + sources/view/settings/VAdjustmentAlarmVolume.h \ + sources/view/settings/VAdjustmentServiceMode.h \ + sources/view/settings/VAdjustmentServiceDates.h \ + sources/view/settings/VAdjustmentDGCleaningUsage.h \ + sources/view/settings/VDuetRoWaterDG.h \ + sources/view/settings/VCloudSync.h \ + sources/view/settings/VHDUsageInfo.h \ + sources/view/settings/VAdjustmentInstitutionalRecord.h \ + \ # ---------- Views - Alarm + sources/view/hd/alarm/VAlarmStatus.h \ + sources/view/hd/alarm/VAlarmActiveList.h \ + \ # ---------- Views - HD - Adjustment + sources/view/VAdjustmentResponseBase.h \ + \ # ---------- Views - HD - Adjustment - common + sources/view/hd/adjustment/common/VCommonAdjustmentVitals.h \ + \ # ---------- Views - HD - Adjustment - Pre-Treatment + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentInitTreatment.h \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentWaterSample.h \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentConsumablesConfirm.h \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentDisposablesConfirm.h \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentDisposablesPrime.h \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentPatientConnectionBegin.h \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentUltrafiltrationInit.h \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentPatientConnectionConfirm.h \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentStartTreatment.h \ + \ # ---------- Views - HD - Adjustment - In-Treatment + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentDuration.h \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentFlows.h \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentUltrafiltrationState.h \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentUltrafiltrationEdit.h \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentUltrafiltrationConfirm.h \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentSaline.h \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentHeparin.h \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentPressuresLimits.h \ + \ # ---------- Views - HD - Adjustment - End-Treatment + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentRinseback.h \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentRecirculate.h \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentEnd.h \ + \ # ---------- Views - HD - Adjustment - Post-Treatment + sources/view/hd/adjustment/posttreatment/VPostTreatmentAdjustPatientDisconnectionConfirm.h \ + sources/view/hd/adjustment/posttreatment/VPostTreatmentAdjustTreatmentLog.h \ + sources/view/hd/adjustment/posttreatment/VPostTreatmentAdjustDisposablesRemovalConfirm.h \ + \ # ---------- Views - HD - Adjustment - Disinfection + sources/view/hd/adjustment/disinfect/VDisinfectAdjustDisinfect.h \ + \ # ---------- Views - HD - Data - States + sources/view/hd/data/VHDOperationModeData.h \ + sources/view/hd/data/pretreatment/VPreTreatmentStatesData.h \ + sources/view/hd/data/treatment/VHDTreatmentStatesData.h \ + sources/view/hd/data/posttreatment/VPostTreatmentStatesData.h \ + \ # ---------- Views - HD - Data - Pre-Treatment - Progress + sources/view/hd/data/pretreatment/VPreTreatmentSelfTestNoCartridgeData.h \ + sources/view/hd/data/pretreatment/VPreTreatmentSelfTestDryData.h \ + sources/view/hd/data/pretreatment/VPreTreatmentDisposablesPrimeData.h \ + \ # ---------- Views - HD - Data + sources/view/hd/data/post/VHDPOSTData.h \ + sources/view/hd/data/VHDAccelerometerData.h \ + sources/view/hd/data/VHDSyringePumpData.h \ + sources/view/hd/data/VHDAirBubbleData.h \ + sources/view/hd/data/VHDAirTrapData.h \ + sources/view/hd/data/VHDBloodLeakData.h \ + sources/view/hd/data/VTreatmentRanges.h \ + sources/view/hd/data/treatment/VTreatmentTime.h \ + sources/view/hd/data/treatment/VTreatmentBloodFlow.h \ + sources/view/hd/data/treatment/VTreatmentDialysateFlow.h \ + sources/view/hd/data/treatment/VTreatmentUltrafiltration.h \ + sources/view/hd/data/treatment/VTreatmentPressureOcclusion.h \ + sources/view/hd/data/treatment/VTreatmentSalineData.h \ + sources/view/hd/data/treatment/VTreatmentHeparinData.h \ + sources/view/hd/data/treatment/VTreatmentRinsebackData.h \ + sources/view/hd/data/treatment/VTreatmentRecirculateData.h \ + sources/view/hd/data/treatment/VTreatmentBloodPrimeData.h \ + sources/view/hd/data/treatment/VTreatmentStopData.h \ + \ # ---------- Views - DG - Data - Pre-Treatment - Progress + sources/view/dg/data/pretreatment/VDGFilterFlushData.h \ + \ # ---------- Views - DG - Data - Disinfection - Progress + \ # ---------- Views - DG - States + \ # ---------- Views - DG - Data + sources/view/dg/data/VDGOperationModeData.h \ + sources/view/dg/data/VDGDrainPumpData.h \ + sources/view/dg/data/VDGHeatersData.h \ + sources/view/dg/data/VDGLoadCellReadingsData.h \ + sources/view/dg/data/VDGPressuresData.h \ + sources/view/dg/data/VDGROPumpData.h \ + sources/view/dg/data/VDGReservoirData.h \ + sources/view/dg/data/VDGTemperaturesData.h \ + sources/view/dg/data/VDGValvesStatesData.h \ + sources/view/dg/data/VDGAccelerometerData.h \ + sources/view/dg/data/VDGConductivityData.h \ + \ # Storage + sources/storage/StorageGlobals.h \ + sources/storage/Logger.h \ + sources/storage/FileHandler.h \ + \ # Utility + sources/utility/crc.h \ + sources/utility/format.h \ + sources/utility/types.h \ + sources/utility/encryption.h \ + sources/utility/qrcodegen.h + +SOURCES += \ + \ # common + \ # Main + main.cpp \ + sources/Threads.cpp \ + sources/MainTimer.cpp \ + sources/AlarmGenerator.cpp \ + sources/ApplicationPost.cpp \ + sources/device/DeviceError.cpp \ + \ # Controllers + sources/ApplicationController.cpp \ + sources/device/DeviceController.cpp \ + sources/model/ui/data/MUIBloodPressureData.cpp \ + sources/storage/Settings.cpp \ + sources/storage/TreatmentLog.cpp \ + sources/view/hd/data/post/VHDPOSTData.cpp \ + sources/wifi/WifiInterface.cpp \ + sources/bluetooth/BluetoothInterface.cpp \ + sources/cloudsync/CloudSyncController.cpp \ + \ # ---------- Models ---------- + sources/model/MAbstract.cpp \ + sources/model/MAbstractDynamic.cpp \ + sources/device/DeviceModels.cpp \ + \ # ---------- Models - CONFIRM + sources/model/confirm/MDuetConfirmHDi.cpp \ + \ # ---------- Models - POST + sources/model/dg/data/post/MDGPostFinalResultData.cpp \ + sources/model/dg/data/post/MDGPostSingleResultData.cpp \ + sources/model/hd/data/post/MHDPostFinalResultData.cpp \ + sources/model/hd/data/post/MHDPostSingleResultData.cpp \ + sources/model/hd/data/post/MUIPostFinalResultHDRequest.cpp \ + \ # ---------- Models - settings + sources/model/settings/MSettings.cpp \ + sources/model/settings/MBluetooth.cpp \ + sources/model/hd/adjustment/settings/MAdjustHDServiceModeResponse.cpp \ + sources/model/dg/adjustment/settings/MAdjustDGSerialNumberResponse.cpp \ + sources/model/hd/adjustment/settings/MAdjustHDSerialNumberResponse.cpp \ + sources/model/dg/adjustment/settings/MAdjustDGServiceDatesResponse.cpp \ + sources/model/hd/adjustment/settings/MAdjustHDServiceDatesResponse.cpp \ + sources/model/hd/adjustment/settings/MAdjustHDInstitutionalRecordResponse.cpp \ + sources/model/dg/adjustment/settings/MDuetRoWaterDG.cpp \ + \ # ---------- Models - Alarm + sources/model/hd/alarm/MAlarmStatusData.cpp \ + sources/model/hd/alarm/MAlarmMapping.cpp \ + sources/model/hd/alarm/MAlarmTriggered.cpp \ + sources/model/hd/alarm/MAlarmCleared.cpp \ + sources/model/hd/alarm/MAlarmClearedCondition.cpp \ + sources/model/hd/alarm/MAlarmActiveList.cpp \ + \ # ---------- Models - Data - States + sources/model/hd/data/MHDOperationModeData.cpp \ + sources/model/hd/data/pretreatment/MPreTreatmentStatesData.cpp \ + sources/model/hd/data/treatment/MTreatmentStatesData.cpp \ + sources/model/hd/data/posttreatment/MPostTreatmentStatesData.cpp \ + \ # ---------- Models - HD - Adjustment + sources/model/hd/adjustment/MAdjustPowerOff.cpp \ + \ # ---------- Models - HD - Adjustment - Settings + sources/model/hd/adjustment/settings/MAdjustHDVersionsRequest.cpp \ + sources/model/hd/adjustment/settings/MAdjustHDVersionsResponse.cpp \ + sources/model/hd/adjustment/settings/MAdjustHDDateTimeResponse.cpp \ + sources/model/hd/adjustment/settings/MAdjustHDAlarmVolumeResponse.cpp \ + \ # ---------- Models - HD - Adjustment - Pre-Treatment + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustInitTreatmentResponse.cpp \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustParametersValidationResponse.cpp \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustWaterSampleResponse.cpp \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustDisposablesConfirmResponse.cpp \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustDisposablesPrimeResponse.cpp \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustPatientConnectionBeginResponse.cpp \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustUltrafiltrationInitResponse.cpp \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustPatientConnectionConfirmResponse.cpp \ + sources/model/hd/adjustment/pretreatment/MPreTreatmentAdjustStartTreatmentResponse.cpp \ + \ # ---------- Models - HD - Adjustment - In-Treatment + sources/model/hd/adjustment/treatment/MTreatmentAdjustDurationResponse.cpp \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustBloodDialysateResponse.cpp \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustUltrafiltrationStateResponse.cpp \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustUltrafiltrationEditResponse.cpp \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustUltrafiltrationConfirmResponse.cpp \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustSalineResponse.cpp \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustHeparinResponse.cpp \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustPressuresLimitsResponse.cpp \ + \ # ---------- Models - HD - Adjustment - End-Treatment + sources/model/hd/adjustment/treatment/MTreatmentAdjustRinsebackResponse.cpp \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustRecirculateResponse.cpp \ + sources/model/hd/adjustment/treatment/MTreatmentAdjustEndResponse.cpp \ + \ # ---------- Models - HD - Adjustment - Post-Treatment + sources/model/hd/adjustment/posttreatment/MPostTreatmentAdjustTreatmentLogResponse.cpp \ + sources/model/hd/adjustment/posttreatment/MPostTreatmentAdjustDisposablesRemovalConfirmResponse.cpp \ + sources/model/hd/adjustment/posttreatment/MPostTreatmentAdjustPatientDisconnectionConfirmResponse.cpp \ + \ # ---------- Models - HD - Adjustment - Disinfection + sources/model/hd/adjustment/disinfect/MDisinfectAdjustModeResponse.cpp \ + sources/model/hd/adjustment/disinfect/MDisinfectAdjustStartResponse.cpp \ + \ # ---------- Models - HD - Data + sources/model/hd/data/MHDDebugText.cpp \ + sources/model/hd/data/MHDGeneralEvent.cpp \ + sources/model/hd/data/MHDAccelerometerData.cpp \ + sources/model/hd/data/MHDSyringePumpData.cpp \ + sources/model/hd/data/MHDAirBubbleData.cpp \ + sources/model/hd/data/MHDAirTrapData.cpp \ + sources/model/hd/data/MHDBloodLeakData.cpp \ + sources/model/hd/data/MTreatmentRangesData.cpp \ + sources/model/hd/data/treatment/MTreatmentTimeData.cpp \ + sources/model/hd/data/treatment/MTreatmentBloodFlowData.cpp \ + sources/model/hd/data/treatment/MTreatmentDialysateFlowData.cpp \ + sources/model/hd/data/treatment/MTreatmentOutletFlowData.cpp \ + sources/model/hd/data/treatment/MTreatmentPressureOcclusionData.cpp \ + sources/model/hd/data/treatment/MTreatmentSalineData.cpp \ + sources/model/hd/data/treatment/MTreatmentHeparinData.cpp \ + sources/model/hd/data/treatment/MTreatmentRinsebackData.cpp \ + sources/model/hd/data/treatment/MTreatmentRecirculateData.cpp \ + sources/model/hd/data/treatment/MTreatmentBloodPrimeData.cpp \ + sources/model/hd/data/treatment/MTreatmentStopData.cpp \ + sources/model/hd/data/post/MHDRTCEpochData.cpp \ + sources/model/hd/data/MHDUsageInfoResponse.cpp \ + \ # ---------- Models - HD - Data - Pre-Treatment + sources/model/hd/data/pretreatment/MPreTreatmentDisposablesPrimeData.cpp \ + sources/model/hd/data/pretreatment/MPreTreatmentSelfTestNoCartridgeData.cpp \ + sources/model/hd/data/pretreatment/MPreTreatmentSelfTestDryData.cpp \ + \ # ---------- Models - HD - Data - Treatment Log + sources/model/hd/data/treatmentlog/MTreatmentLogAlarmData.cpp \ + sources/model/hd/data/treatmentlog/MTreatmentLogAvrgeData.cpp \ + sources/model/hd/data/treatmentlog/MTreatmentLogEventData.cpp \ + \ # ---------- Models - DG - Adjustment + \ # ---------- Models - DG - Adjustment - Settings + sources/model/dg/adjustment/settings/MAdjustDGVersionsResponse.cpp \ + sources/model/dg/adjustment/settings/MAdjustDGDateTimeResponse.cpp \ + sources/model/dg/adjustment/settings/MAdjustDGCleaningUsageResponse.cpp \ + \ # ---------- Models - DG - Data - Pre-Treatment - Progress + sources/model/dg/data/pretreatment/MDGFilterFlushData.cpp \ + \ # ---------- Models - DG - Data - Disinfection - Progress + \ # ---------- Models - DG - Data + sources/model/dg/data/MDGDebugText.cpp \ + sources/model/dg/data/MDGGeneralEvent.cpp \ + sources/model/dg/data/MDGDrainPumpData.cpp \ + sources/model/dg/data/MDGHeatersData.cpp \ + sources/model/dg/data/MDGLoadCellReadingsData.cpp \ + sources/model/dg/data/MDGOperationModeData.cpp \ + sources/model/dg/data/MDGPressuresData.cpp \ + sources/model/dg/data/MDGReservoirData.cpp \ + sources/model/dg/data/MDGROPumpData.cpp \ + sources/model/dg/data/MDGTemperaturesData.cpp \ + sources/model/dg/data/MDGValvesStatesData.cpp \ + sources/model/dg/data/MDGAccelerometerData.cpp \ + sources/model/dg/data/MDGConductivityData.cpp \ + \ # CANBus + sources/canbus/CanInterface.cpp \ + sources/canbus/FrameInterface.cpp \ + \ # Denali Message + sources/canbus/MessageAcknowModel.cpp \ + sources/canbus/MessageBuilder.cpp \ + sources/canbus/MessageDispatcher.cpp \ + sources/canbus/MessageInterpreter.cpp \ + \ # Gui + sources/gui/GuiGlobals.cpp \ + sources/gui/GuiView.cpp \ + sources/gui/GuiController.cpp \ + \ # ---------- Views ---------- + sources/view/VTreatmentCreate.cpp \ + sources/view/VEventSpy.cpp \ + sources/view/VGeneralEvent.cpp \ + sources/device/DeviceView.cpp \ + \ # ---------- Views - CONFIRM + sources/view/confirm/VConfirm.cpp \ + \ # ---------- Views - POST + sources/view/dg/data/post/VDGPOSTData.cpp \ + \ # ---------- Views - Alarm + sources/view/hd/alarm/VAlarmStatus.cpp \ + sources/view/hd/alarm/VAlarmActiveList.cpp \ + \ # ---------- Views - Settings + sources/view/settings/VSettings.cpp \ + sources/view/settings/VDateTime.cpp \ + sources/view/settings/VBluetooth.cpp \ + sources/view/settings/VNetworkModel.cpp \ + sources/view/settings/VAdjustmentVersions.cpp \ + sources/view/settings/VAdjustmentAlarmVolume.cpp \ + sources/view/settings/VAdjustmentServiceMode.cpp \ + sources/view/settings/VAdjustmentServiceDates.cpp \ + sources/view/settings/VDuetRoWaterDG.cpp \ + sources/view/settings/VCloudSync.cpp \ + sources/view/settings/VAdjustmentDGCleaningUsage.cpp \ + sources/view/settings/VHDUsageInfo.cpp \ + sources/view/settings/VAdjustmentInstitutionalRecord.cpp \ + \ # ---------- Views - HD - Adjustment + sources/view/VAdjustmentResponseBase.cpp \ + \ # ---------- Views - HD - Adjustment - common + sources/view/hd/adjustment/common/VCommonAdjustmentVitals.cpp \ + \ # ---------- Views - HD - Adjustment - Pre-Treatment + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentInitTreatment.cpp \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentWaterSample.cpp \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentConsumablesConfirm.cpp \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentDisposablesConfirm.cpp \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentDisposablesPrime.cpp \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentPatientConnectionBegin.cpp \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentUltrafiltrationInit.cpp \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentPatientConnectionConfirm.cpp \ + sources/view/hd/adjustment/pretreatment/VPreTreatmentAdjustmentStartTreatment.cpp \ + \ # ---------- Views - HD - Adjustment - In-Treatment + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentDuration.cpp \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentFlows.cpp \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentUltrafiltrationState.cpp \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentUltrafiltrationEdit.cpp \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentUltrafiltrationConfirm.cpp \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentSaline.cpp \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentHeparin.cpp \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentPressuresLimits.cpp \ + \ # ---------- Views - HD - Adjustment - End-Treatment + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentRinseback.cpp \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentRecirculate.cpp \ + sources/view/hd/adjustment/treatment/VTreatmentAdjustmentEnd.cpp \ + \ # ---------- Views - HD - Adjustment - Post-Treatment + sources/view/hd/adjustment/posttreatment/VPostTreatmentAdjustDisposablesRemovalConfirm.cpp \ + sources/view/hd/adjustment/posttreatment/VPostTreatmentAdjustTreatmentLog.cpp \ + sources/view/hd/adjustment/posttreatment/VPostTreatmentAdjustPatientDisconnectionConfirm.cpp \ + \ # ---------- Views - HD - Adjustment - Disinfection + sources/view/hd/adjustment/disinfect/VDisinfectAdjustDisinfect.cpp \ + \ # ---------- Views - HD - States Data + sources/view/hd/data/VHDOperationModeData.cpp \ + sources/view/hd/data/pretreatment/VPreTreatmentStatesData.cpp \ + sources/view/hd/data/treatment/VHDTreatmentStatesData.cpp \ + sources/view/hd/data/posttreatment/VPostTreatmentStatesData.cpp \ + \ # ---------- Views - HD - Data + sources/view/hd/data/VHDAccelerometerData.cpp \ + sources/view/hd/data/VHDSyringePumpData.cpp \ + sources/view/hd/data/VHDAirBubbleData.cpp \ + sources/view/hd/data/VHDAirTrapData.cpp \ + sources/view/hd/data/VHDBloodLeakData.cpp \ + \ # ---------- Views - HD - Data - Pre-Treatment + sources/view/hd/data/pretreatment/VPreTreatmentSelfTestNoCartridgeData.cpp \ + sources/view/hd/data/pretreatment/VPreTreatmentSelfTestDryData.cpp \ + sources/view/hd/data/pretreatment/VPreTreatmentDisposablesPrimeData.cpp \ + \ # ---------- Views - HD - Data - In-Treatment + sources/view/hd/data/VTreatmentRanges.cpp \ + sources/view/hd/data/treatment/VTreatmentTime.cpp \ + sources/view/hd/data/treatment/VTreatmentBloodFlow.cpp \ + sources/view/hd/data/treatment/VTreatmentDialysateFlow.cpp \ + sources/view/hd/data/treatment/VTreatmentUltrafiltration.cpp \ + sources/view/hd/data/treatment/VTreatmentPressureOcclusion.cpp \ + sources/view/hd/data/treatment/VTreatmentSalineData.cpp \ + sources/view/hd/data/treatment/VTreatmentHeparinData.cpp \ + \ # ---------- Views - HD - Data - End-Treatment + sources/view/hd/data/treatment/VTreatmentBloodPrimeData.cpp \ + sources/view/hd/data/treatment/VTreatmentRinsebackData.cpp \ + sources/view/hd/data/treatment/VTreatmentRecirculateData.cpp \ + sources/view/hd/data/treatment/VTreatmentStopData.cpp \ + \ # ---------- Views - DG - Data - Pre-Treatment - Progress + sources/view/dg/data/pretreatment/VDGFilterFlushData.cpp \ + \ # ---------- Views - DG - Data - Disinfect - Progress + \ # ---------- Views - DG - States + \ # ---------- Views - DG - Data + sources/view/dg/data/VDGDrainPumpData.cpp \ + sources/view/dg/data/VDGHeatersData.cpp \ + sources/view/dg/data/VDGLoadCellReadingsData.cpp \ + sources/view/dg/data/VDGOperationModeData.cpp \ + sources/view/dg/data/VDGPressuresData.cpp \ + sources/view/dg/data/VDGROPumpData.cpp \ + sources/view/dg/data/VDGReservoirData.cpp \ + sources/view/dg/data/VDGTemperaturesData.cpp \ + sources/view/dg/data/VDGValvesStatesData.cpp \ + sources/view/dg/data/VDGAccelerometerData.cpp \ + sources/view/dg/data/VDGConductivityData.cpp \ + \ # Storage + sources/storage/StorageGlobals.cpp \ + sources/storage/FileHandler.cpp \ + sources/storage/Logger.cpp \ + \ # Utility + sources/utility/crc.cpp \ + sources/utility/format.cpp \ + sources/utility/types.cpp \ + sources/utility/encryption.cpp \ + sources/utility/qrcodegen.cpp + +RESOURCES += \ + leahi.qrc + +DEFINES += \ + VER_MAJOR="\\\"${majorVersion}\\\"" \ + VER_MINOR="\\\"${minorVersion}\\\"" \ + VER_MICRO="\\\"${microVersion}\\\"" \ + VER_REVIS="\\\"${buildNumber}\\\"" \ + VER_REVIS_DEV=\\\"$$system( date "+%m%d%H%M" )\\\" \ + VER_APPLY=\\\"$$system( touch -m main.cpp )\\\" \ + VER_BRANCH=\\\"$$system( git rev-parse --abbrev-ref HEAD )\\\" + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +# Additional import path used to resolve QML modules just for Qt Quick Designer +QML_DESIGNER_IMPORT_PATH = + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /home/root +!isEmpty(target.path): INSTALLS += target + +DISTFILES += \ + README.md \ + ui_build_history.log Index: leahi.pro.user =================================================================== diff -u --- leahi.pro.user (revision 0) +++ leahi.pro.user (revision 9363dbc93c2be5d664c0ca2a565d8206679d9bf3) @@ -0,0 +1,651 @@ + + + + + + EnvironmentId + {d3e165e0-350b-4c5e-a5f5-6e3e06ca0990} + + + ProjectExplorer.Project.ActiveTarget + 1 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + 0 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + false + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 1 + false + + + + true + + + true + + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop Qt 5.15.10 GCC 64bit + Desktop Qt 5.15.10 GCC 64bit + qt.qt5.51510.gcc_64_kit + 0 + 0 + 0 + + 0 + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_GCC-Debug + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_GCC-Debug + + + true + "" 0 + /home/denali/Projects/application/imake.sh + %{sourceDir} + ProjectExplorer.ProcessStep + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + + true + -b --tag denali >> denali + + sha256sum + %{buildDir} + ProjectExplorer.ProcessStep + + 4 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + 0 + + + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_GCC-Release + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_GCC-Release + + + true + /home/denali/Projects/application/imake.sh + %{sourceDir} + ProjectExplorer.ProcessStep + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + + true + -b --tag denali >> denali + + sha256sum + %{buildDir} + ProjectExplorer.ProcessStep + + 4 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_GCC-Profile + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_GCC-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + + 2 + + false + + Qt4ProjectManager.Qt4RunConfiguration:/home/denali/Projects/application/leahi.pro + /home/denali/Projects/application/leahi.pro + false + true + true + true + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_GCC-Debug + + 1 + + + + ProjectExplorer.Project.Target.1 + + GenericLinuxOsType + Qt 5.15.10 (iMX8) + Qt 5.15.10 (iMX8) + {ada4083c-13b6-4ac8-a486-71ff00b060da} + 1 + 0 + 0 + + 0 + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_iMX8-Debug + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_iMX8-Debug + + + true + /home/denali/Projects/application/imake.sh + %{sourceDir} + ProjectExplorer.ProcessStep + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + + true + -b --tag denali >> denali + sha256sum + %{buildDir} + ProjectExplorer.ProcessStep + + 4 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + 0 + + + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_iMX8-Release + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_iMX8-Release + + + true + 0 0 + /home/denali/Projects/application/imake.sh + %{sourceDir} + ProjectExplorer.ProcessStep + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + + true + -b --tag denali >> denali + sha256sum + %{buildDir} + ProjectExplorer.ProcessStep + + 4 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_iMX8-Profile + /home/denali/Projects/tmp/build/leahi-Qt_5_15_10_iMX8-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + + true + RemoteLinux.KillAppStep + + + + + + + + + true + RemoteLinux.DirectUploadStep + + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Release/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Release/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Release/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Release/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + /home/denali/Projects/tmp/build/build-denali-Qt_5_15_10_iMX8-Debug/denali + + + 192.168.10.186 + 192.168.137.24 + 192.168.40.23 + 192.168.137.26 + 192.168.137.170 + 192.168.137.3 + 192.168.137.247 + 192.168.137.36 + 192.168.137.125 + 192.168.137.202 + 192.168.10.138 + 192.168.10.228 + 192.168.10.228 + 192.168.10.159 + 192.168.137.210 + 192.168.137.170 + 192.168.10.186 + 192.168.10.167 + 192.168.137.25 + 192.168.137.30 + + + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + /home/root + + + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots/x86_64-pokysdk-linux + /opt/b2qt/3.1.18/sysroots/x86_64-pokysdk-linux + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots/x86_64-pokysdk-linux + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + /opt/b2qt/3.1.18/sysroots + + + 2023-01-18T20:13:36.296 + 2023-02-02T02:05:29.947 + 2023-01-24T17:29:54.849 + 2023-02-01T05:00:56.449 + 2023-01-27T09:45:11.898 + 2023-02-02T02:40:56.627 + 2023-02-02T02:26:33.738 + 2023-02-01T03:23:15.710 + 2023-02-02T02:07:25.922 + 2023-02-02T01:46:50.167 + 2023-02-02T09:06:00.862 + 2023-01-17T18:06:25.579 + 2023-01-17T18:18:03.749 + 2023-01-24T18:19:13.179 + 2023-02-02T01:52:20.307 + 2023-01-27T10:15:15.423 + 2023-01-18T17:47:08.797 + 2023-02-02T19:40:15.813 + 2023-02-02T02:13:54.596 + 2023-02-02T02:30:48.337 + + + 2023-01-18T20:13:33.000 + 2023-02-02T02:05:42.000 + 2023-01-24T17:30:03.000 + 2023-02-01T05:00:51.000 + 2023-01-27T09:44:58.000 + 2023-02-02T02:41:10.000 + 2023-02-02T02:26:46.000 + 2023-02-01T03:23:28.000 + 2023-02-02T02:07:21.000 + 2023-02-02T01:47:02.000 + 2023-02-02T09:05:22.000 + 2023-01-17T18:05:42.000 + 2023-01-17T18:17:25.000 + 2023-01-24T18:18:58.000 + 2023-02-02T01:52:16.000 + 2023-01-27T10:15:08.000 + 2023-01-18T17:47:04.000 + 2023-02-02T19:39:36.000 + 2023-02-02T02:14:08.000 + 2023-02-02T02:31:01.000 + + + 2 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + DeployToGenericLinux + + 1 + + true + + 2 + + false + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + true + + + true + + 1 + + false + + RemoteLinux.CustomRunConfig + + false + 1 + true + true + :0 + + 2 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + Index: leahi.qrc =================================================================== diff -u --- leahi.qrc (revision 0) +++ leahi.qrc (revision 9363dbc93c2be5d664c0ca2a565d8206679d9bf3) @@ -0,0 +1,257 @@ + + + sources/gui/qml/pages/MainStack.qml + sources/gui/qml/pages/MainHome.qml + sources/gui/qml/pages/ManagerStack.qml + sources/gui/qml/pages/UserConfirmation.qml + sources/gui/qml/pages/TreatmentFlowBase.qml + + + sources/gui/qml/pages/settings/SettingsBase.qml + sources/gui/qml/pages/settings/SettingsStack.qml + sources/gui/qml/pages/settings/SettingsHome.qml + sources/gui/qml/pages/settings/SettingsDateTime.qml + sources/gui/qml/pages/settings/SettingsWiFi.qml + sources/gui/qml/pages/settings/SettingsDGCleaning.qml + sources/gui/qml/pages/settings/SettingsDGScheduling.qml + sources/gui/qml/pages/settings/SettingsVolumeBrightness.qml + sources/gui/qml/pages/settings/SettingsBluetoothCuff.qml + sources/gui/qml/pages/settings/SettingsExportLogs.qml + sources/gui/qml/pages/settings/SettingsDeviceRegistration.qml + sources/gui/qml/pages/settings/SettingsInformation.qml + sources/gui/qml/pages/settings/SettingsROInput.qml + sources/gui/qml/pages/settings/SettingsRootSSHAccess.qml + sources/gui/qml/pages/settings/SettingsServicePassword.qml + sources/gui/qml/pages/settings/SettingsManufacturingSetup.qml + sources/gui/qml/pages/settings/SettingsFactoryReset.qml + sources/gui/qml/pages/settings/SettingsDecommission.qml + sources/gui/qml/pages/settings/SettingsInstitutionalRecord.qml + + + sources/gui/qml/dialogs/ConfirmDialog.qml + sources/gui/qml/dialogs/AutoHideInfo.qml + sources/gui/qml/dialogs/NotificationDialog.qml + sources/gui/qml/dialogs/AlarmListDialog.qml + sources/gui/qml/dialogs/DiagnosticsDialog.qml + + + resources/images/Logo d.png + resources/images/Logo DialityT.png + resources/images/splash.png + resources/images/ArrowRight.png + resources/images/ArrowLeft.png + resources/images/logo d Dark Transparent.png + resources/images/Close.png + resources/images/bell-on.png + resources/images/bell-off.png + resources/images/Back.png + resources/images/PauseDarkBlue.png + resources/images/PauseLightBlue.png + resources/images/PauseGray.png + resources/images/Resume.png + resources/images/Clock-Minus.png + resources/images/Clock-Plus.png + resources/images/Wave-Minus.png + resources/images/Wave-Plus.png + resources/images/check.png + resources/images/chevron-down.png + resources/images/chevron-up.png + resources/images/list.png + resources/images/End.png + resources/images/Accelerate.png + resources/images/Decelerate.png + resources/images/Busy.png + resources/images/BusyDone.png + resources/images/BusyFail.png + resources/images/EjectEnabled.png + resources/images/EjectDisabled.png + resources/images/eye.png + resources/images/Omron-bp7000.png + resources/images/chevron-left.png + resources/images/chevron-right.png + resources/images/DenaliDevice.png + + + sources/gui/qml/components/MainMenu.qml + sources/gui/qml/components/TouchRect.qml + sources/gui/qml/components/TitleText.qml + sources/gui/qml/components/ImageLogoD.qml + sources/gui/qml/components/ScreenItem.qml + sources/gui/qml/components/StackItem.qml + sources/gui/qml/components/ModalDialog.qml + sources/gui/qml/components/BackButton.qml + sources/gui/qml/components/USBButton.qml + sources/gui/qml/components/ExportButton.qml + sources/gui/qml/components/TouchArea.qml + sources/gui/qml/components/TextRect.qml + sources/gui/qml/components/Background.qml + sources/gui/qml/components/Line.qml + sources/gui/qml/components/PlaceHolderText.qml + sources/gui/qml/components/ProgressBar.qml + sources/gui/qml/components/RangeMarker.qml + sources/gui/qml/components/ProgressRect.qml + sources/gui/qml/components/RangeRect.qml + sources/gui/qml/components/RangeBar.qml + sources/gui/qml/components/Circle.qml + sources/gui/qml/components/StepBullet.qml + sources/gui/qml/components/StepIndicator.qml + sources/gui/qml/components/TimeText.qml + sources/gui/qml/components/ProgressCircle.qml + sources/gui/qml/components/Slider.qml + sources/gui/qml/components/SliderCreateTreatment.qml + sources/gui/qml/components/ConfirmTreatmentTable.qml + sources/gui/qml/components/ConfirmTreatmentSubTable.qml + sources/gui/qml/components/GridSelection.qml + sources/gui/qml/components/ProgressBarEx.qml + sources/gui/qml/components/CloseButton.qml + sources/gui/qml/components/ConfirmButton.qml + sources/gui/qml/components/TickMarks.qml + sources/gui/qml/components/NotificationBar.qml + sources/gui/qml/components/NotificationBarSmall.qml + sources/gui/qml/components/UltrafiltrationButton.qml + sources/gui/qml/components/ImageWave.qml + sources/gui/qml/components/ImageClock.qml + sources/gui/qml/components/ImageLogoDDarkTransparent.qml + sources/gui/qml/components/ConfirmTreatmentTableEntry.qml + sources/gui/qml/components/DebugDataColumn.qml + sources/gui/qml/components/RangeSlider.qml + sources/gui/qml/components/MuteButton.qml + sources/gui/qml/components/UpDownButton.qml + sources/gui/qml/components/ImageText.qml + sources/gui/qml/components/WaitDone.qml + sources/gui/qml/components/TimeCircle.qml + sources/gui/qml/components/Footer.qml + sources/gui/qml/components/TextEntry.qml + sources/gui/qml/components/ScrollBar.qml + sources/gui/qml/compounds/Fader.qml + sources/gui/qml/components/FooterStatic.qml + sources/gui/qml/components/TimeEntry.qml + sources/gui/qml/components/Label.qml + sources/gui/qml/components/EntryDialog.qml + sources/gui/qml/components/SliderArrows.qml + sources/gui/qml/components/QRCode.qml + + + sources/gui/qml/compounds/PressureRangeSlider.qml + sources/gui/qml/compounds/StepNavigationTitleBar.qml + sources/gui/qml/compounds/InstructionView.qml + sources/gui/qml/compounds/CheckListView.qml + sources/gui/qml/compounds/TouchGrid.qml + sources/gui/qml/compounds/BPHREntry.qml + + + qtquickcontrols2.conf + sources/gui/qml/main.qml + sources/gui/qml/AlarmItem.qml + sources/gui/qml/PowerItem.qml + sources/gui/qml/KeyboardItem.qml + sources/gui/qml/SDCProgressItem.qml + sources/gui/qml/USBProgressItem.qml + + + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/backspace.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/check.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/enter.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/globe.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/handwriting.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/hidekeyboard.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/search.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/selectionhandle.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/shift-normal.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/shift-active.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/shift-capslock.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/images/textmode.svg + sources/gui/qml/plugins/virtualkeyboard/styles/denali/style.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_GB/dialpad.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_GB/digits.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_GB/handwriting.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_GB/main.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_GB/numbers.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_GB/symbols.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_US/dialpad.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_US/digits.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_US/handwriting.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_US/main.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_US/numbers.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/en_US/symbols.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/fallback/dialpad.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/fallback/digits.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/fallback/handwriting.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/fallback/main.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/fallback/numbers.qml + sources/gui/qml/plugins/virtualkeyboard/layouts/fallback/symbols.qml + + + sources/gui/qml/globals/Variables.qml + sources/gui/qml/globals/Colors.qml + sources/gui/qml/globals/qmldir + sources/gui/qml/globals/Fonts.qml + + + sources/gui/qml/pages/disinfect/DisinfectBase.qml + sources/gui/qml/pages/disinfect/DisinfectStack.qml + + + sources/gui/qml/pages/pretreatment/PreTreatmentBase.qml + sources/gui/qml/pages/pretreatment/PreTreatmentStack.qml + sources/gui/qml/pages/pretreatment/PreTreatmentWaterSampleStack.qml + sources/gui/qml/pages/pretreatment/PreTreatmentConsumablesStack.qml + sources/gui/qml/pages/pretreatment/PreTreatmentDisposablesStack.qml + sources/gui/qml/pages/pretreatment/PreTreatmentPrimeStack.qml + + + sources/gui/qml/pages/pretreatment/create/PreTreatmentCreateStack.qml + sources/gui/qml/pages/pretreatment/create/PreTreatmentCreate.qml + sources/gui/qml/pages/pretreatment/create/PreTreatmentConfirm.qml + + + sources/gui/qml/pages/pretreatment/connection/PreTreatmentUltrafiltration.qml + sources/gui/qml/pages/pretreatment/connection/PreTreatmentConnectionStack.qml + + + sources/gui/qml/pages/treatment/TreatmentStack.qml + sources/gui/qml/pages/treatment/TreatmentHome.qml + sources/gui/qml/pages/treatment/TreatmentBloodPrime.qml + sources/gui/qml/pages/treatment/TreatmentUltrafiltrationItem.qml + + + sources/gui/qml/pages/treatment/sections/TreatmentFlows.qml + sources/gui/qml/pages/treatment/sections/TreatmentVitals.qml + sources/gui/qml/pages/treatment/sections/TreatmentPressures.qml + sources/gui/qml/pages/treatment/sections/TreatmentUltrafiltration.qml + sources/gui/qml/pages/treatment/sections/TreatmentFluid.qml + sources/gui/qml/pages/treatment/sections/TreatmentTime.qml + sources/gui/qml/pages/treatment/sections/TreatmentSaline.qml + sources/gui/qml/pages/treatment/sections/TreatmentHeparin.qml + + + sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentFlow.qml + sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentBase.qml + sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentDuration.qml + sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentUltrafiltrationStart.qml + sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentUltrafiltrationPaused.qml + sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentUltrafiltrationEdit.qml + sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentUltrafiltrationConfirm.qml + sources/gui/qml/pages/treatment/adjustments/TreatmentAdjustmentPressuresLimits.qml + + + sources/gui/qml/pages/endtreatment/EndTreatmentRinsebackStack.qml + sources/gui/qml/pages/endtreatment/EndTreatmentRecirculateStack.qml + sources/gui/qml/pages/endtreatment/EndTreatmentEndStack.qml + sources/gui/qml/pages/endtreatment/EndTreatmentBase.qml + + + sources/gui/qml/pages/endtreatment/rinseback/EndTreatmentRinsebackInit.qml + sources/gui/qml/pages/endtreatment/rinseback/EndTreatmentRinseback.qml + sources/gui/qml/pages/endtreatment/rinseback/EndTreatmentRinsebackComplete.qml + sources/gui/qml/pages/endtreatment/rinseback/EndTreatmentAdditional.qml + sources/gui/qml/pages/endtreatment/rinseback/EndTreatmentRinsebackReconnect.qml + + + + + sources/gui/qml/pages/posttreatment/PostTreatmentBase.qml + sources/gui/qml/pages/posttreatment/PostTreatmentStack.qml + sources/gui/qml/pages/posttreatment/PostTreatmentReview.qml + + Index: sources/ApplicationPost.cpp =================================================================== diff -u -r5687815256ae070a9a207107088e3f72dd464da0 -r9363dbc93c2be5d664c0ca2a565d8206679d9bf3 --- sources/ApplicationPost.cpp (.../ApplicationPost.cpp) (revision 5687815256ae070a9a207107088e3f72dd464da0) +++ sources/ApplicationPost.cpp (.../ApplicationPost.cpp) (revision 9363dbc93c2be5d664c0ca2a565d8206679d9bf3) @@ -12,309 +12,309 @@ * \date (original) 26-Aug-2020 * */ -#include "ApplicationPost.h" -// Qt -#include -#include -#include - -// Project -#include "Logger.h" -#include "FileHandler.h" - -/*! - * \brief ApplicationPost::ApplicationPost - * \details Constructor - * \param parent - QObject parent owner object. - * Qt handles the children destruction by their parent objects life-cycle. - */ -ApplicationPost::ApplicationPost(QObject *parent) : QObject(parent) { } - -/*! - * \brief ApplicationPost::start - * \details Starting the post application initialization - * \return - */ -void ApplicationPost::start() -{ - QString postLogFileName = QDir::tempPath() + "/" + Storage::POST_LOG; - if (Storage::FileHandler::read(postLogFileName, _content)) { - - _isOSVersion = checkOSVersion (); - _isShaSum = checkShaSum (); - _isCANBus = checkCANBus (); - _isDisplay = checkDisplay (); - _isTouch = checkTouch (); - _isSDCard = checkSDCard (); - _isRtc = checkRtc (); - _isWiFi = checkWiFi (); // is not mandatory and the device can still be used without it. Alarm will be triggered to notify user in Active Alarm List. - _isBluetooth = checkBluetooth (); // is not mandatory and the device can still be used without it. Alarm will be triggered to notify user in Active Alarm List. - _isCloudSync = checkCloudSync (); // is not mandatory and the device can still be used without it. Alarm will be triggered to notify user in Active Alarm List. - _isEthernet = checkEthernet (); // this is not a Fault and not required the application to stop. No Alarm will be triggered. - _isSound = checkSound (); // this is not a Fault and not required the application to stop. No Alarm will be triggered. - _isYearCheck = checkYear (); - // WARNING: - // all of the checks have to be done, - // although some are not failing the final result, - // so they need to be assigned to a variable and then, AND(&&) them, - // otherwise on the first fail rest of the checks will not run by compiler optimization. - _isDone = - isOSVersion () && - isShaSum () && - isCANBus () && - isDisplay () && - isTouch () && - isSDCard () && - isRtc () && - isWiFi () && - isBluetooth () && - isCloudSync () && - // isEthernet () && // it is being executed to get the information but is not part of the POST failure. - // isSound () && - isYearCheck () - ; - } - else { - // TODO: Ignored for now but this could be a FileSystem check failure, and the post.log has to always exist. - // _done = false; - LOG_APPED_UI(tr("The POST log file could not be read.")); - } - emit didDone(_isDone); -} - -/*! - * \brief ApplicationPost::checkOSVersion - * \details Checks the OS version - * \return false if the OS version is lower than 0.0.40 which is released for the Cybersecurity.. - */ -bool ApplicationPost::checkOSVersion() -{ - QString exrVer("%1\\s*\"\\d+\\.\\d+\\.\\d+\""); - QString exrBld("%1\\s*\"\\d+\""); - - QRegExp regVer(exrVer.arg(_postmsg_osversion)); - QRegExp regBld(exrBld.arg(_postmsg_osbuild )); - QString version; - QString build; - QStringList versions; - quint16 major; - quint16 minor; - quint16 micro; - - // check the statement exists in the long - int rowVer = _content.indexOf (regVer); - int rowBld = _content.indexOf (regBld); Q_UNUSED(rowBld); - bool ok = rowVer >= 0; // found - if ( ! ok ) goto lOut; - - // check the Os version is compatible - version = regVer.cap(0).replace(_postmsg_osversion,"").replace("\"",""); // 0 is the first captured and next if any are the subsets. - build = regBld.cap(0).replace(_postmsg_osbuild ,"").replace("\"",""); // 0 is the first captured and next if any are the subsets. - versions = version.split("."); - major = versions[0].toUInt(); // type, existance, count has been already tested by regex, and was rejected in first check section. - minor = versions[1].toUInt(); // type, existance, count has been already tested by regex, and was rejected in first check section. - micro = versions[2].toUInt(); // type, existance, count has been already tested by regex, and was rejected in first check section. - ok = major >= Storage::OS_VERSION_MAJOR && - minor >= Storage::OS_VERSION_MINOR && - micro >= Storage::OS_VERSION_MICRO ; - if ( ! ok ) goto lOut; - - _osVersion = version + "." + build; - -lOut: - if ( !ok ) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_OS_VERSION); - emit didOSVersion(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkOSInfo - * \details Checks if the - * \return it is false if the - */ -bool ApplicationPost::checkShaSum() -{ - bool ok = _content.contains(_postmsg_shasum + _postmsg_postfix_passed); - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_SHASUM); - emit didShaSum(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkCANBus - * \details Checks the CANBus driver is loaded and the bus is functional - * \return false if there is an issue. - */ -bool ApplicationPost::checkCANBus() -{ - bool ok = _content.contains(_postmsg_canbus + _postmsg_postfix_passed); - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_CANBUS); - emit didCANBus(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkDisplay - * \details Checks the display driver is loaded - * \return false if there is an issue [No Implementation yet (always true)]. - */ -bool ApplicationPost::checkDisplay() -{ - bool ok = true; - //TODO: do the test : not a good test has been found yet. - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_DISPLAY); - emit didDisplay(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkTouchScreen - * \details Checks the touch driver is loaded - * \return false if there is an issue. - */ -bool ApplicationPost::checkTouch() -{ - bool ok = _content.contains(_postmsg_touch + _postmsg_postfix_passed); - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_TOUCH); - emit didTouch(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkSDCard - * \details Checks the SD-Card drive is loaded and functional - * \return false if there is an issue. - */ -bool ApplicationPost::checkSDCard() -{ - bool ok = _content.contains(_postmsg_sdcard + _postmsg_postfix_passed); - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_SDCARD); - emit didSDCard(ok); - return ok; -} - -/*! - * \brief ApplicationPost::CRC - * \details Checks the RTC driver is loaded and functional - * \return false if there is an issue - */ -bool ApplicationPost::checkRtc() -{ - bool ok = _content.contains(_postmsg_rtc + _postmsg_postfix_passed); - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_RTC); - emit didRtc(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkEthernet - * \details Checks the Ethernet driver is loaded and functional. - * \return false if there is an issue [Removed from the PRS (always true)]. - */ -bool ApplicationPost::checkEthernet() -{ - bool ok = false; - int posDev = -1; - int posMac = -1; - QString section = ""; - posDev = _content.indexOf( _devEthernet ); if ( posDev < 0 ) goto lOut; - section = _content.mid(posDev, _macAppearLen); - posMac = section.indexOf(_macEthernetLabel); if ( posMac < 0 ) goto lOut; - _macEthernet = section.mid(posMac + _macEthernetLabel.length(), _macAddrssLen).toUpper(); if ( _macEthernet.isEmpty() ) goto lOut; - ok = true; - -lOut: - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_ETHERNET); - emit didEthernet(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkWiFi - * \details Checks the WiFi driver is loaded and functional - * \return false if there is an issue. - */ -bool ApplicationPost::checkWiFi() -{ - bool ok = false; - int posDev = -1; - int posMac = -1; - QString section = ""; - posDev = _content.indexOf( _devWireless ); if ( posDev < 0 ) goto lOut; - section = _content.mid(posDev, _macAppearLen); - posMac = section.indexOf(_macWirelessLabel); if ( posMac < 0 ) goto lOut; - _macWireless = section.mid(posMac + _macWirelessLabel.length(), _macAddrssLen).toUpper(); if ( _macWireless.isEmpty() ) goto lOut; - ok = _content.contains(_postmsg_wifi + _postmsg_postfix_passed); - -lOut: - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_WIFI); - emit didWiFi(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkBluetooth - * \details Checks the Bluetooth driver is loaded and functional - * \return false if there is an issue. - */ -bool ApplicationPost::checkBluetooth() -{ - bool ok = false; - int posDev = -1; - int posMac = -1; - QString section = ""; - posDev = _content.indexOf( _devBluetooth ); if ( posDev < 0 ) goto lOut; - section = _content.mid(posDev, _macAppearLen); - posMac = section.indexOf(_macBluetoothLabel); if ( posMac < 0 ) goto lOut; - _macBluetooth = section.mid(posMac + _macBluetoothLabel.length(), _macAddrssLen).toUpper(); if ( _macBluetooth.isEmpty() ) goto lOut; - ok = _content.contains(_postmsg_bluetooth + _postmsg_postfix_passed); - -lOut: - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_BLUETOOTH); - emit didBluetooth(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkCloudSync - * \details Checks the CloudSync service is loaded and functional - * \return false if there is an issue. - */ -bool ApplicationPost::checkCloudSync() -{ - bool ok = true; - if (! gDisableCloudSyncFailStop ) { - ok = _content.contains(_postmsg_cloudsync + _postmsg_postfix_passed); - } - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_CLOUDSYNC); - emit didCloudSync(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkSound - * \details Checks the sound driver is loaded. - * \return false if there is an issue [No Implementation yet (always true)]. - */ -bool ApplicationPost::checkSound() -{ - bool ok = true; - // do the test - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_SOUND); - emit didSound(ok); - return ok; -} - -/*! - * \brief ApplicationPost::checkYear - * \details Checks if the year is greater than or equal to 2022. - * \return false if there is an issue. - */ -bool ApplicationPost::checkYear() -{ - QDate currentDate = QDate::currentDate(); - bool ok = currentDate.year() >= _yearMinimum; - if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_INVALID_YEAR); - emit didYearCheck(ok); - return ok; -} +#include "ApplicationPost.h" +// Qt +#include +#include +#include + +// Project +#include "Logger.h" +#include "FileHandler.h" + +/*! + * \brief ApplicationPost::ApplicationPost + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +ApplicationPost::ApplicationPost(QObject *parent) : QObject(parent) { } + +/*! + * \brief ApplicationPost::start + * \details Starting the post application initialization + * \return + */ +void ApplicationPost::start() +{ + QString postLogFileName = QDir::tempPath() + "/" + Storage::POST_LOG; + if (Storage::FileHandler::read(postLogFileName, _content)) { + + _isOSVersion = checkOSVersion (); + _isShaSum = checkShaSum (); + _isCANBus = checkCANBus (); + _isDisplay = checkDisplay (); + _isTouch = checkTouch (); + _isSDCard = checkSDCard (); + _isRtc = checkRtc (); + _isWiFi = checkWiFi (); // is not mandatory and the device can still be used without it. Alarm will be triggered to notify user in Active Alarm List. + _isBluetooth = checkBluetooth (); // is not mandatory and the device can still be used without it. Alarm will be triggered to notify user in Active Alarm List. + _isCloudSync = checkCloudSync (); // is not mandatory and the device can still be used without it. Alarm will be triggered to notify user in Active Alarm List. + _isEthernet = checkEthernet (); // this is not a Fault and not required the application to stop. No Alarm will be triggered. + _isSound = checkSound (); // this is not a Fault and not required the application to stop. No Alarm will be triggered. + _isYearCheck = checkYear (); + // WARNING: + // all of the checks have to be done, + // although some are not failing the final result, + // so they need to be assigned to a variable and then, AND(&&) them, + // otherwise on the first fail rest of the checks will not run by compiler optimization. + _isDone = + isOSVersion () && + isShaSum () && + isCANBus () && + isDisplay () && + isTouch () && + isSDCard () && + isRtc () && + isWiFi () && + isBluetooth () && + isCloudSync () && + // isEthernet () && // it is being executed to get the information but is not part of the POST failure. + // isSound () && + isYearCheck () + ; + } + else { + // TODO: Ignored for now but this could be a FileSystem check failure, and the post.log has to always exist. + // _done = false; + LOG_APPED_UI(tr("The POST log file could not be read.")); + } + emit didDone(_isDone); +} + +/*! + * \brief ApplicationPost::checkOSVersion + * \details Checks the OS version + * \return false if the OS version is lower than 0.0.40 which is released for the Cybersecurity.. + */ +bool ApplicationPost::checkOSVersion() +{ + QString exrVer("%1\\s*\"\\d+\\.\\d+\\.\\d+\""); + QString exrBld("%1\\s*\"\\d+\""); + + QRegExp regVer(exrVer.arg(_postmsg_osversion)); + QRegExp regBld(exrBld.arg(_postmsg_osbuild )); + QString version; + QString build; + QStringList versions; + quint16 major; + quint16 minor; + quint16 micro; + + // check the statement exists in the long + int rowVer = _content.indexOf (regVer); + int rowBld = _content.indexOf (regBld); Q_UNUSED(rowBld); + bool ok = rowVer >= 0; // found + if ( ! ok ) goto lOut; + + // check the Os version is compatible + version = regVer.cap(0).replace(_postmsg_osversion,"").replace("\"",""); // 0 is the first captured and next if any are the subsets. + build = regBld.cap(0).replace(_postmsg_osbuild ,"").replace("\"",""); // 0 is the first captured and next if any are the subsets. + versions = version.split("."); + major = versions[0].toUInt(); // type, existance, count has been already tested by regex, and was rejected in first check section. + minor = versions[1].toUInt(); // type, existance, count has been already tested by regex, and was rejected in first check section. + micro = versions[2].toUInt(); // type, existance, count has been already tested by regex, and was rejected in first check section. + ok = major >= Storage::OS_VERSION_MAJOR && + minor >= Storage::OS_VERSION_MINOR && + micro >= Storage::OS_VERSION_MICRO ; + if ( ! ok ) goto lOut; + + _osVersion = version + "." + build; + +lOut: + if ( !ok ) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_OS_VERSION); + emit didOSVersion(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkOSInfo + * \details Checks if the + * \return it is false if the + */ +bool ApplicationPost::checkShaSum() +{ + bool ok = _content.contains(_postmsg_shasum + _postmsg_postfix_passed); + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_SHASUM); + emit didShaSum(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkCANBus + * \details Checks the CANBus driver is loaded and the bus is functional + * \return false if there is an issue. + */ +bool ApplicationPost::checkCANBus() +{ + bool ok = _content.contains(_postmsg_canbus + _postmsg_postfix_passed); + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_CANBUS); + emit didCANBus(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkDisplay + * \details Checks the display driver is loaded + * \return false if there is an issue [No Implementation yet (always true)]. + */ +bool ApplicationPost::checkDisplay() +{ + bool ok = true; + //TODO: do the test : not a good test has been found yet. + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_DISPLAY); + emit didDisplay(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkTouchScreen + * \details Checks the touch driver is loaded + * \return false if there is an issue. + */ +bool ApplicationPost::checkTouch() +{ + bool ok = _content.contains(_postmsg_touch + _postmsg_postfix_passed); + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_TOUCH); + emit didTouch(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkSDCard + * \details Checks the SD-Card drive is loaded and functional + * \return false if there is an issue. + */ +bool ApplicationPost::checkSDCard() +{ + bool ok = _content.contains(_postmsg_sdcard + _postmsg_postfix_passed); + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_SDCARD); + emit didSDCard(ok); + return ok; +} + +/*! + * \brief ApplicationPost::CRC + * \details Checks the RTC driver is loaded and functional + * \return false if there is an issue + */ +bool ApplicationPost::checkRtc() +{ + bool ok = _content.contains(_postmsg_rtc + _postmsg_postfix_passed); + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_RTC); + emit didRtc(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkEthernet + * \details Checks the Ethernet driver is loaded and functional. + * \return false if there is an issue [Removed from the PRS (always true)]. + */ +bool ApplicationPost::checkEthernet() +{ + bool ok = false; + int posDev = -1; + int posMac = -1; + QString section = ""; + posDev = _content.indexOf( _devEthernet ); if ( posDev < 0 ) goto lOut; + section = _content.mid(posDev, _macAppearLen); + posMac = section.indexOf(_macEthernetLabel); if ( posMac < 0 ) goto lOut; + _macEthernet = section.mid(posMac + _macEthernetLabel.length(), _macAddrssLen).toUpper(); if ( _macEthernet.isEmpty() ) goto lOut; + ok = true; + +lOut: + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_ETHERNET); + emit didEthernet(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkWiFi + * \details Checks the WiFi driver is loaded and functional + * \return false if there is an issue. + */ +bool ApplicationPost::checkWiFi() +{ + bool ok = false; + int posDev = -1; + int posMac = -1; + QString section = ""; + posDev = _content.indexOf( _devWireless ); if ( posDev < 0 ) goto lOut; + section = _content.mid(posDev, _macAppearLen); + posMac = section.indexOf(_macWirelessLabel); if ( posMac < 0 ) goto lOut; + _macWireless = section.mid(posMac + _macWirelessLabel.length(), _macAddrssLen).toUpper(); if ( _macWireless.isEmpty() ) goto lOut; + ok = _content.contains(_postmsg_wifi + _postmsg_postfix_passed); + +lOut: + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_WIFI); + emit didWiFi(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkBluetooth + * \details Checks the Bluetooth driver is loaded and functional + * \return false if there is an issue. + */ +bool ApplicationPost::checkBluetooth() +{ + bool ok = false; + int posDev = -1; + int posMac = -1; + QString section = ""; + posDev = _content.indexOf( _devBluetooth ); if ( posDev < 0 ) goto lOut; + section = _content.mid(posDev, _macAppearLen); + posMac = section.indexOf(_macBluetoothLabel); if ( posMac < 0 ) goto lOut; + _macBluetooth = section.mid(posMac + _macBluetoothLabel.length(), _macAddrssLen).toUpper(); if ( _macBluetooth.isEmpty() ) goto lOut; + ok = _content.contains(_postmsg_bluetooth + _postmsg_postfix_passed); + +lOut: + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_BLUETOOTH); + emit didBluetooth(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkCloudSync + * \details Checks the CloudSync service is loaded and functional + * \return false if there is an issue. + */ +bool ApplicationPost::checkCloudSync() +{ + bool ok = true; + if (! gDisableCloudSyncFailStop ) { + ok = _content.contains(_postmsg_cloudsync + _postmsg_postfix_passed); + } + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_CLOUDSYNC); + emit didCloudSync(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkSound + * \details Checks the sound driver is loaded. + * \return false if there is an issue [No Implementation yet (always true)]. + */ +bool ApplicationPost::checkSound() +{ + bool ok = true; + // do the test + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_SOUND); + emit didSound(ok); + return ok; +} + +/*! + * \brief ApplicationPost::checkYear + * \details Checks if the year is greater than or equal to 2022. + * \return false if there is an issue. + */ +bool ApplicationPost::checkYear() +{ + QDate currentDate = QDate::currentDate(); + bool ok = currentDate.year() >= _yearMinimum; + if (! ok) emit didFail(Gui::GuiAlarmID::ALARM_ID_HD_UI_POST_FAILURE_INVALID_YEAR); + emit didYearCheck(ok); + return ok; +} Index: sources/cloudsync/CloudSyncController.h =================================================================== diff -u -r5687815256ae070a9a207107088e3f72dd464da0 -r9363dbc93c2be5d664c0ca2a565d8206679d9bf3 --- sources/cloudsync/CloudSyncController.h (.../CloudSyncController.h) (revision 5687815256ae070a9a207107088e3f72dd464da0) +++ sources/cloudsync/CloudSyncController.h (.../CloudSyncController.h) (revision 9363dbc93c2be5d664c0ca2a565d8206679d9bf3) @@ -12,334 +12,334 @@ * \date (original) 14-Oct-2021 * */ -#pragma once - -// Qt -#include -#include - -// Project -#include "main.h" // Doxygen : do not remove -#include "GuiController.h" - -// define -#define _CloudSyncController CloudSyncController::I() - -// forward declarations -class tst_initializations; - -// namespace - -/*! - * \brief The CloudSyncController class - * \details Singleton class which is the main gateway of CloudSync signal/slots. - */ -class CloudSyncController : public QObject { - Q_OBJECT - - // Singleton - SINGLETON(CloudSyncController) - - // friends - friend class ::tst_initializations; - - QThread *_thread = nullptr; - bool _init = false; - - const int _interval = 1000; // 1s - const QString _location = QString(Storage::SDCard_Base_Path_Name) + "cloudsync/"; - const char* _out_File = "out.buf"; // The base file name : CloudSync puts its output to this file - const char* _inp_File = "inp.buf"; // The base file name : UI Software puts the input data for the CloudSync in this file - - QString _date_out_File = ""; // The dated/actual filename : CloudSync puts its output to this file - QString _date_inp_File = ""; // The dated/actual filename : UI Software puts the input data for the CloudSync in this file - QDateTime _datetime ; - qint64 _secSinceEpoch ; - - QString _dateFormatted ; - QString _timeFormatted ; - - const char* _dateFormat = "yyyy_MM_dd" ; // date used in the file name - const char* _timeFormat = "HH:mm:ss.zzz"; // timestamp in the file - - const char _dateSeparator = '_'; // used in filename - const char _separator = ','; - - quint64 _seq = 0; - - bool _deviceInfoStop = true; - const qint8 _deviceInfoSecs = 1; // in seconds is used for the DG serial response message, if DG is detached UI will timeout after a second and will send the message regardless. - qint8 _deviceInfoWait = 0; - QString _deviceInfoHD = ""; - QString _deviceInfoDG = ""; - QString _deviceInfoUI = ""; - - const quint8 _checkinIntervalSend = 60; // count down for check-in error if not responded back - regarding the _interval it will be 60s - const quint8 _checkinIntervalTest = 5; // count down for check-in error if not responded back - regarding the _interval it will be 5s - bool _checkinRcvd = false; // id check-in received will set to true. - - bool _postPass = false; - bool _isWatching = false; - - enum Errors_Enum { - // CS : 900 - 949 - // UI : 950 - 999 - eError_Unknown = 900, // Unknown error, initial error before error check - - // CS to UI Error start - eError_Registration = 901, // CS_REQ_REGISTRATION_ERROR = 901 - eError_DeviceState = 906, // CS_SEND_DEVICE_STATE_ERROR = 906 - eError_TxReport = 907, // CS_SEND_TREATMENT_REPORT_ERROR = 907 - eError_CheckIn = 908, // CS_REQ_CHECKIN_ERROR = 908 - eError_Decommission = 909, // CS_REQ_DECOMMISSION_ERROR = 909 - eError_UICRC = 910, // CS_BAD_CRC_ERROR = 910 - eError_DeviceValidation = 920, // CS_DEVICE_VALIDATION_RESULT_ERROR = 920 - eError_PatientAssociation = 921, // CS_SET_PATIENT_DEVICE_ASSOCIATION_ERROR = 921 - eError_GetNewTokenCert = 922, // CS_GET_NEW_TOKEN_WITH_CERT_ERROR = 922 - eError_VerifyToken = 923, // CS_VERIFY_TOKEN_ERROR = 923 - eError_ValidateDevice = 924, // CS_VALIDATE_DEVICE_ERROR = 924 - eError_PatientIdExists = 925, // CS_CHECK_IF_PATIENT_WITH_EMR_ID_EXISTS_ERROR = 925 - eError_TemporaryPatient = 926, // CS_CREATE_TEMPORARY_PATIENT_ERROR = 926 - eError_SaveCredentials = 927, // CS_SAVE_CREDENTIALS_ERROR = 927 - eError_UnknownDeviceState = 928, // CS_UNKNOWN_DEVICE_STATE_ERROR = 928 - eError_ConfigSave = 929, // CS_SAVE_CONFIG_ERROR = 929 - eError_DeviceLog = 930, // CS_DEVICE_LOG_ERROR = 930 - eError_Logging = 931, // CS_LOG_ERROR = 931 - eError_FactoryReset = 932, // CS_FACTORY_RESET_ERROR = 932 - eError_Retention = 933, // CS_LOG_RETENTION_ERROR = 933 - - // UI to CS Error start - // eError_UI_Base = 950, // Base, not used - eError_HeaderCount = 951, - eError_Timestamp = 952, - eError_Sequence = 953, - eError_CSCRC = 954, - eError_MessageID = 955, - eError_InvalidID = 956, - eError_ParamCount = 957, - eError_ParamMismatch = 958, - eError_ParamMissing = 959, - - eError_NoHistory = 960, - eError_Duplicate = 961, - - eError_LogFolder = 962, - eError_LogFileInp = 963, - - eError_CredentialPath = 964, // the UI vault folder for cloudsync credentials is not what is expected. - eError_CredentialFile = 965, // the credential files sent to UI can't be find or read or doesn't exist.. - eError_CredentialCount = 966, // No credential file sent to UI in the message. - eError_CredentialEmpty = 967, // the UI folder doesn't have credential files. - - eError_TxCodeNoParam = 969, // the received Tx Code not provided - eError_TxCodeEmpty = 970, // the received Tx Code is empty - - eError_OutFileExist = 971, // Out file does not exist. - eError_OutFileEmpty = 972, // Out file has changed from CS2UI but the content is empty. - - eError_NotRegistered = 973, // avoid sending any message other than the device registration, when device is not registered. - - eError_LogNameNoParam = 974, // the received Log Name not provided - eError_LogNameEmpty = 975, // the received Log Name is empty - - eError_LogRetentionNoParam = 976, // the received Log retention payload parameters not provided - - }; - - typedef QHash MessageList; - MessageList _uiHistory ; // sent message history for later send upon request. - - enum Message_Enum { - eMessage_Timestamp , - eMessage_Sequence , - eMessage_CRC , - eMessage_MessageID , - eMessage_ParamCount , - eMessage_Count , - }; - - typedef QStringList Params; - struct Message { - quint64 timestamp = 0; - quint32 sequence = 0; - quint8 crc = 0; - qint32 id = 0; - quint32 paramCount = 0; - Params params { }; - }; - - enum Entity_Start_Index { - eUI = 1000, - eCS = 2000, - }; - - enum MessageID_Enum { - eMessageID_Start = 0, - // // [ #1( ID ) <-> #2( ID ) ] Description ( #1 Requests and #2 responses ) - - eMessageID_DeviceRegister = 1, // [ UI(1001) -> CS( ) ] Device Registration Request - eMessageID_DeviceInfo = 2, // [ CS(2002) <-> UI(1002) ] Device information Request - eMessageID_CredentialsSave = 3, // [ CS(2003) <-> UI(1003) ] Save Credentials Request/Response - eMessageID_CheckIn = 4, // [ CS(2004) <-> UI(1004) ] CheckIn/HeartBeat Request/Response - eMessageID_UIFactoryReset = 5, // [ CS(2005) <-> UI(1005) ] Factory Reset Request - // Deployment - eMessageID_DeviceState = 6, // [ CS(2006) <-> UI(1006) ] Device State Request - // Tx Report - eMessageID_TxReport = 7, // [ UI(1007) -> CS(2007) ] TxReport Notify - // Tx Code - eMessageID_TxCodeDisplay = 8, // [ CS(2008) -> UI( ) ] Display TxCode Request - // Decommissioning - eMessageID_CSDecommissioning= 9, // [ UI(1009) <-> CS(2009) ] Decommissioning Request - // Log Upload - eMessageID_SendLogUpload = 10, // [ UI(1010) <-> CS(2010) ] Log Upload Request/Response - // CloudSync Log Retention - eMessageID_SendLogRetention = 11, // [ UI(1011) <-> CS(2011) ] Log Retention Request/Response - // Factory Reset - eMessageID_CSFactoryReset = 99, // [ UI(1009) <-> CS(2009) ] Factory Reset Request // NOT IMPLEMENTED - - // - // Subject to change so has been commented out for now - // - // eMessageID_PatientID = 202, // [No CS req defined] UI sends the patient ID - // eMessageID_DeviceReport = 204, // [No CS req defined] UI sends the device report - // eMessageID_HeartBeat = 900, // CS sends the periodic Hb and UI can set the interval - - eMessageID_Error = 999, // [ CS(2000) <-> UI(1000) ] Error Report - - eMessageID_Count - }; - - QHash paramCount { // Received message length - { eMessageID_CredentialsSave , 3 }, - { eMessageID_TxCodeDisplay , 1 }, - { eMessageID_Error , 2 }, - { eMessageID_SendLogUpload , 1 }, - { eMessageID_SendLogRetention , 2 }, - }; - - enum DeviceInfo_Enum { - eDeviceInfo_Ix = 0, // received message data index of each HD, DG. Data index 0 is always the info. - eDeviceInfo_HD = 0, // stored index in the UI history. - eDeviceInfo_DG = 1, // stored index in the UI history. - eDeviceInfo_UI = 2, // stored index in the UI history. - }; - -protected: - void timerEvent(QTimerEvent *event) override; - bool event(QEvent* vEvent) override; - -public slots: - bool init(); - bool init(QThread &vThread); - void quit(); - - void doRegister (); - -private slots: - void onWatchFileChange (const QString &vFile); - void onActionReceive (GuiActionType vAction, const QVariantList &vData); - void onPendingTxr (const QString &vFileName ); - void onPendingLog (const QString &vFileName, const QString vChecksum ); - void onRetentionLog (quint8 vMaxUsePercent); - - void onInitComplete (); - void onPOSTCloudSync (bool vPass ); - void onCryptSetupMount (bool vPass ); - void onFactoryReset (bool vPass ); - void onDecommissioning (bool vPass ); - -signals: - void didInitComplete (); - void didTxCodeReceive (const QString &vTxCode ); - void didLogUpload (const QString &vFileName ); - void didLogRetention (quint16 vLogsCount, quint32 vLogsSize); - - void didRegisterStart (bool vOK ); - void didRegisterDone (bool vOK ); - void didCloudSyncStatus (bool vReady ); - void didCheckInReceive (); - -private: - void initConnections(); - - void initThread(QThread &vThread); - void quitThread(); - - quint8 generateCRC (quint64 vSecSinceEpoch, quint64 vSeq, const QStringList &vDataList); - bool validateCRC () { return true; } // has not been implemented/decided yet - - void testWatchBuffDate (); - bool interpret (const QString &vContent, Message &vMessage); - - bool addCSBuffWatch (); - - QStringList makeUIBuff (const qint32 vMessageID , const QStringList &vPrm = {}); - - bool isDuplicate (const qint32 vMessageID , const QStringList &vData); - - bool sendUIResponse (const QString &vContent ); - bool sendUIBuff (const QStringList &vData ); - bool saveUIHistory (const qint32 vAction , const QVariantList &vData); - bool sendUIHistory (const qint32 vAction ); - bool sendMessage (const Message &vMessage ); - - bool writeInpFile (const QString &vInpBuff ); - - QString toText (Errors_Enum vErrorID); - QString toInfo (Errors_Enum vErrorID, const QVariantList &vInfoItems); - void toLog (Errors_Enum vErrorID, const QVariantList &vInfoItems); - void errorOut (Errors_Enum vErrorID, const QVariantList &vInfoItems); - - qint32 UI2CS (qint32 vID) { return vID + eUI ; } - qint32 CS2UI (qint32 vID) { return abs(vID - eCS); } - - // error - bool sendError (); // eMessageID_Error - bool errorHandler ( const Message &vMessage ); // eMessageID_Error - - // device information - bool saveDeviceInfo (GuiActionType vAction, const QVariantList &vData); // eMessageID_DeviceInfo - bool saveDeviceInfoTimeOut (); // eMessageID_DeviceInfo - bool sendDeviceInfo (); // eMessageID_DeviceInfo - void testDeviceInfoWait (); - void stopDeviceInfoWait (); - void initDeviceInfoWait (); - - // device registration request - bool sendDeviceRegister (); // eMessageID_DeviceRegister - bool isRegistered (); - void testReady(); - - // device state report - bool saveDeviceState (const QVariantList &vData); - bool sendDeviceState (); // eMessageID_DeviceState - - - // Factory Reset - bool csDecommissioning (); // eMessageID_CSDecommissioning - bool csFactoryReset (); // eMessageID_CSFactoryReset - bool uiFactoryReset (); // eMessageID_FactoryReset - bool sendFactoryReset (); // eMessageID_FactoryReset - - - // credentials - bool sendCredentialsSave (const Message &vMessage ); // eMessageID_SaveCredentials - bool sendCredentialsResponse(); - - // check-in - bool sendCheckIn (); - void testCheckIn (); - bool takeCheckIn (); - - // pending Treatment log - void sendPendingTxr ( const QString &vFileName ); // eMessageID_TxReport - bool sendTxCodeDisplay ( const Message &vMessage ); // eMessageID_TxCodeDisplay - - // pending Treatment log - void sendPendingLog (const QString &vFileName , const QString vChecksum); // eMessageID_SendLogUpload - bool rcvdPendingLog (const Message &vMessage ); // eMessageID_SendLogUpload - - // CloudSync log retention - void sendRetentionLog ( quint8 vMaxUsePercent ); // eMessageID_SendLogRetention - bool rcvdRetentionLog (const Message &vMessage ); // eMessageID_SendLogRetention -}; +#pragma once + +// Qt +#include +#include + +// Project +#include "main.h" // Doxygen : do not remove +#include "GuiController.h" + +// define +#define _CloudSyncController CloudSyncController::I() + +// forward declarations +class tst_initializations; + +// namespace + +/*! + * \brief The CloudSyncController class + * \details Singleton class which is the main gateway of CloudSync signal/slots. + */ +class CloudSyncController : public QObject { + Q_OBJECT + + // Singleton + SINGLETON(CloudSyncController) + + // friends + friend class ::tst_initializations; + + QThread *_thread = nullptr; + bool _init = false; + + const int _interval = 1000; // 1s + const QString _location = QString(Storage::SDCard_Base_Path_Name) + "cloudsync/"; + const char* _out_File = "out.buf"; // The base file name : CloudSync puts its output to this file + const char* _inp_File = "inp.buf"; // The base file name : UI Software puts the input data for the CloudSync in this file + + QString _date_out_File = ""; // The dated/actual filename : CloudSync puts its output to this file + QString _date_inp_File = ""; // The dated/actual filename : UI Software puts the input data for the CloudSync in this file + QDateTime _datetime ; + qint64 _secSinceEpoch ; + + QString _dateFormatted ; + QString _timeFormatted ; + + const char* _dateFormat = "yyyy_MM_dd" ; // date used in the file name + const char* _timeFormat = "HH:mm:ss.zzz"; // timestamp in the file + + const char _dateSeparator = '_'; // used in filename + const char _separator = ','; + + quint64 _seq = 0; + + bool _deviceInfoStop = true; + const qint8 _deviceInfoSecs = 1; // in seconds is used for the DG serial response message, if DG is detached UI will timeout after a second and will send the message regardless. + qint8 _deviceInfoWait = 0; + QString _deviceInfoHD = ""; + QString _deviceInfoDG = ""; + QString _deviceInfoUI = ""; + + const quint8 _checkinIntervalSend = 60; // count down for check-in error if not responded back - regarding the _interval it will be 60s + const quint8 _checkinIntervalTest = 5; // count down for check-in error if not responded back - regarding the _interval it will be 5s + bool _checkinRcvd = false; // id check-in received will set to true. + + bool _postPass = false; + bool _isWatching = false; + + enum Errors_Enum { + // CS : 900 - 949 + // UI : 950 - 999 + eError_Unknown = 900, // Unknown error, initial error before error check + + // CS to UI Error start + eError_Registration = 901, // CS_REQ_REGISTRATION_ERROR = 901 + eError_DeviceState = 906, // CS_SEND_DEVICE_STATE_ERROR = 906 + eError_TxReport = 907, // CS_SEND_TREATMENT_REPORT_ERROR = 907 + eError_CheckIn = 908, // CS_REQ_CHECKIN_ERROR = 908 + eError_Decommission = 909, // CS_REQ_DECOMMISSION_ERROR = 909 + eError_UICRC = 910, // CS_BAD_CRC_ERROR = 910 + eError_DeviceValidation = 920, // CS_DEVICE_VALIDATION_RESULT_ERROR = 920 + eError_PatientAssociation = 921, // CS_SET_PATIENT_DEVICE_ASSOCIATION_ERROR = 921 + eError_GetNewTokenCert = 922, // CS_GET_NEW_TOKEN_WITH_CERT_ERROR = 922 + eError_VerifyToken = 923, // CS_VERIFY_TOKEN_ERROR = 923 + eError_ValidateDevice = 924, // CS_VALIDATE_DEVICE_ERROR = 924 + eError_PatientIdExists = 925, // CS_CHECK_IF_PATIENT_WITH_EMR_ID_EXISTS_ERROR = 925 + eError_TemporaryPatient = 926, // CS_CREATE_TEMPORARY_PATIENT_ERROR = 926 + eError_SaveCredentials = 927, // CS_SAVE_CREDENTIALS_ERROR = 927 + eError_UnknownDeviceState = 928, // CS_UNKNOWN_DEVICE_STATE_ERROR = 928 + eError_ConfigSave = 929, // CS_SAVE_CONFIG_ERROR = 929 + eError_DeviceLog = 930, // CS_DEVICE_LOG_ERROR = 930 + eError_Logging = 931, // CS_LOG_ERROR = 931 + eError_FactoryReset = 932, // CS_FACTORY_RESET_ERROR = 932 + eError_Retention = 933, // CS_LOG_RETENTION_ERROR = 933 + + // UI to CS Error start + // eError_UI_Base = 950, // Base, not used + eError_HeaderCount = 951, + eError_Timestamp = 952, + eError_Sequence = 953, + eError_CSCRC = 954, + eError_MessageID = 955, + eError_InvalidID = 956, + eError_ParamCount = 957, + eError_ParamMismatch = 958, + eError_ParamMissing = 959, + + eError_NoHistory = 960, + eError_Duplicate = 961, + + eError_LogFolder = 962, + eError_LogFileInp = 963, + + eError_CredentialPath = 964, // the UI vault folder for cloudsync credentials is not what is expected. + eError_CredentialFile = 965, // the credential files sent to UI can't be find or read or doesn't exist.. + eError_CredentialCount = 966, // No credential file sent to UI in the message. + eError_CredentialEmpty = 967, // the UI folder doesn't have credential files. + + eError_TxCodeNoParam = 969, // the received Tx Code not provided + eError_TxCodeEmpty = 970, // the received Tx Code is empty + + eError_OutFileExist = 971, // Out file does not exist. + eError_OutFileEmpty = 972, // Out file has changed from CS2UI but the content is empty. + + eError_NotRegistered = 973, // avoid sending any message other than the device registration, when device is not registered. + + eError_LogNameNoParam = 974, // the received Log Name not provided + eError_LogNameEmpty = 975, // the received Log Name is empty + + eError_LogRetentionNoParam = 976, // the received Log retention payload parameters not provided + + }; + + typedef QHash MessageList; + MessageList _uiHistory ; // sent message history for later send upon request. + + enum Message_Enum { + eMessage_Timestamp , + eMessage_Sequence , + eMessage_CRC , + eMessage_MessageID , + eMessage_ParamCount , + eMessage_Count , + }; + + typedef QStringList Params; + struct Message { + quint64 timestamp = 0; + quint32 sequence = 0; + quint8 crc = 0; + qint32 id = 0; + quint32 paramCount = 0; + Params params { }; + }; + + enum Entity_Start_Index { + eUI = 1000, + eCS = 2000, + }; + + enum MessageID_Enum { + eMessageID_Start = 0, + // // [ #1( ID ) <-> #2( ID ) ] Description ( #1 Requests and #2 responses ) + + eMessageID_DeviceRegister = 1, // [ UI(1001) -> CS( ) ] Device Registration Request + eMessageID_DeviceInfo = 2, // [ CS(2002) <-> UI(1002) ] Device information Request + eMessageID_CredentialsSave = 3, // [ CS(2003) <-> UI(1003) ] Save Credentials Request/Response + eMessageID_CheckIn = 4, // [ CS(2004) <-> UI(1004) ] CheckIn/HeartBeat Request/Response + eMessageID_UIFactoryReset = 5, // [ CS(2005) <-> UI(1005) ] Factory Reset Request + // Deployment + eMessageID_DeviceState = 6, // [ CS(2006) <-> UI(1006) ] Device State Request + // Tx Report + eMessageID_TxReport = 7, // [ UI(1007) -> CS(2007) ] TxReport Notify + // Tx Code + eMessageID_TxCodeDisplay = 8, // [ CS(2008) -> UI( ) ] Display TxCode Request + // Decommissioning + eMessageID_CSDecommissioning= 9, // [ UI(1009) <-> CS(2009) ] Decommissioning Request + // Log Upload + eMessageID_SendLogUpload = 10, // [ UI(1010) <-> CS(2010) ] Log Upload Request/Response + // CloudSync Log Retention + eMessageID_SendLogRetention = 11, // [ UI(1011) <-> CS(2011) ] Log Retention Request/Response + // Factory Reset + eMessageID_CSFactoryReset = 99, // [ UI(1009) <-> CS(2009) ] Factory Reset Request // NOT IMPLEMENTED + + // + // Subject to change so has been commented out for now + // + // eMessageID_PatientID = 202, // [No CS req defined] UI sends the patient ID + // eMessageID_DeviceReport = 204, // [No CS req defined] UI sends the device report + // eMessageID_HeartBeat = 900, // CS sends the periodic Hb and UI can set the interval + + eMessageID_Error = 999, // [ CS(2000) <-> UI(1000) ] Error Report + + eMessageID_Count + }; + + QHash paramCount { // Received message length + { eMessageID_CredentialsSave , 3 }, + { eMessageID_TxCodeDisplay , 1 }, + { eMessageID_Error , 2 }, + { eMessageID_SendLogUpload , 1 }, + { eMessageID_SendLogRetention , 2 }, + }; + + enum DeviceInfo_Enum { + eDeviceInfo_Ix = 0, // received message data index of each HD, DG. Data index 0 is always the info. + eDeviceInfo_HD = 0, // stored index in the UI history. + eDeviceInfo_DG = 1, // stored index in the UI history. + eDeviceInfo_UI = 2, // stored index in the UI history. + }; + +protected: + void timerEvent(QTimerEvent *event) override; + bool event(QEvent* vEvent) override; + +public slots: + bool init(); + bool init(QThread &vThread); + void quit(); + + void doRegister (); + +private slots: + void onWatchFileChange (const QString &vFile); + void onActionReceive (GuiActionType vAction, const QVariantList &vData); + void onPendingTxr (const QString &vFileName ); + void onPendingLog (const QString &vFileName, const QString vChecksum ); + void onRetentionLog (quint8 vMaxUsePercent); + + void onInitComplete (); + void onPOSTCloudSync (bool vPass ); + void onCryptSetupMount (bool vPass ); + void onFactoryReset (bool vPass ); + void onDecommissioning (bool vPass ); + +signals: + void didInitComplete (); + void didTxCodeReceive (const QString &vTxCode ); + void didLogUpload (const QString &vFileName ); + void didLogRetention (quint16 vLogsCount, quint32 vLogsSize); + + void didRegisterStart (bool vOK ); + void didRegisterDone (bool vOK ); + void didCloudSyncStatus (bool vReady ); + void didCheckInReceive (); + +private: + void initConnections(); + + void initThread(QThread &vThread); + void quitThread(); + + quint8 generateCRC (quint64 vSecSinceEpoch, quint64 vSeq, const QStringList &vDataList); + bool validateCRC () { return true; } // has not been implemented/decided yet + + void testWatchBuffDate (); + bool interpret (const QString &vContent, Message &vMessage); + + bool addCSBuffWatch (); + + QStringList makeUIBuff (const qint32 vMessageID , const QStringList &vPrm = {}); + + bool isDuplicate (const qint32 vMessageID , const QStringList &vData); + + bool sendUIResponse (const QString &vContent ); + bool sendUIBuff (const QStringList &vData ); + bool saveUIHistory (const qint32 vAction , const QVariantList &vData); + bool sendUIHistory (const qint32 vAction ); + bool sendMessage (const Message &vMessage ); + + bool writeInpFile (const QString &vInpBuff ); + + QString toText (Errors_Enum vErrorID); + QString toInfo (Errors_Enum vErrorID, const QVariantList &vInfoItems); + void toLog (Errors_Enum vErrorID, const QVariantList &vInfoItems); + void errorOut (Errors_Enum vErrorID, const QVariantList &vInfoItems); + + qint32 UI2CS (qint32 vID) { return vID + eUI ; } + qint32 CS2UI (qint32 vID) { return abs(vID - eCS); } + + // error + bool sendError (); // eMessageID_Error + bool errorHandler ( const Message &vMessage ); // eMessageID_Error + + // device information + bool saveDeviceInfo (GuiActionType vAction, const QVariantList &vData); // eMessageID_DeviceInfo + bool saveDeviceInfoTimeOut (); // eMessageID_DeviceInfo + bool sendDeviceInfo (); // eMessageID_DeviceInfo + void testDeviceInfoWait (); + void stopDeviceInfoWait (); + void initDeviceInfoWait (); + + // device registration request + bool sendDeviceRegister (); // eMessageID_DeviceRegister + bool isRegistered (); + void testReady(); + + // device state report + bool saveDeviceState (const QVariantList &vData); + bool sendDeviceState (); // eMessageID_DeviceState + + + // Factory Reset + bool csDecommissioning (); // eMessageID_CSDecommissioning + bool csFactoryReset (); // eMessageID_CSFactoryReset + bool uiFactoryReset (); // eMessageID_FactoryReset + bool sendFactoryReset (); // eMessageID_FactoryReset + + + // credentials + bool sendCredentialsSave (const Message &vMessage ); // eMessageID_SaveCredentials + bool sendCredentialsResponse(); + + // check-in + bool sendCheckIn (); + void testCheckIn (); + bool takeCheckIn (); + + // pending Treatment log + void sendPendingTxr ( const QString &vFileName ); // eMessageID_TxReport + bool sendTxCodeDisplay ( const Message &vMessage ); // eMessageID_TxCodeDisplay + + // pending Treatment log + void sendPendingLog (const QString &vFileName , const QString vChecksum); // eMessageID_SendLogUpload + bool rcvdPendingLog (const Message &vMessage ); // eMessageID_SendLogUpload + + // CloudSync log retention + void sendRetentionLog ( quint8 vMaxUsePercent ); // eMessageID_SendLogRetention + bool rcvdRetentionLog (const Message &vMessage ); // eMessageID_SendLogRetention +}; Index: sources/device/DeviceController.cpp =================================================================== diff -u -r5687815256ae070a9a207107088e3f72dd464da0 -r9363dbc93c2be5d664c0ca2a565d8206679d9bf3 --- sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision 5687815256ae070a9a207107088e3f72dd464da0) +++ sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision 9363dbc93c2be5d664c0ca2a565d8206679d9bf3) @@ -12,1305 +12,1305 @@ * \date (original) 03-Jun-2021 * */ -#include "DeviceController.h" - -// Linux -#include -#include - -// Qt -#include -#include -#include - -// Project -#include "Threads.h" -#include "StorageGlobals.h" -#include "Logger.h" -#include "CloudSyncController.h" -#include "ApplicationController.h" -#include "FileHandler.h" -#include "DeviceModels.h" -#include "Settings.h" -#include "encryption.h" - -// namespace -using namespace Model; -using namespace Device; -using namespace Storage; - -/*! - * \brief DeviceController::DeviceController - * \details Constructor - * \param parent - QObject parent owner object. - * Qt handles the children destruction by their parent objects life-cycle. - */ -DeviceController::DeviceController(QObject *parent) : QObject(parent) { - _fileSystemWatcher.setParent(this); - DEVICE_DEV_PARENT_LIST -} - -/*! - * \brief DeviceController::init - * \details Initializes the class by setting the connections and starting the timer - * \return False if it has been called before. - */ -bool DeviceController::init() -{ - if ( _init ) return false; - _init = true; - - // runs in DeviceController thread - initConnections(); - startTimer(_interval); - - return true; -} - -/*! - * \brief DeviceController::init - * \details Initialized the Class by calling the init() method first - * And initializes the thread vThread by calling initThread - * on success init(). - * \param vThread - the thread - * \return returns the return value of the init() method - */ -bool DeviceController::init(QThread &vThread) -{ - if ( ! init() ) return false; - initThread(vThread); - return true; -} - -/*! - * \brief DeviceController::quit - * \details quits the class - * Calls quitThread - */ -void DeviceController::quit() -{ - quitThread(); -} - - -/*! - * \brief DeviceController::initConnections - * \details Initializes the required signal/slot connection between this class and other objects - * to be able to communicate. - */ -void DeviceController::initConnections() -{ - connect(&_ApplicationController , SIGNAL(didUSBDriveUmount()), - this , SLOT( onUSBDriveUmount())); - - connect(this , SIGNAL(didScreenshot(const QImage &, const QString &)), - this , SLOT( onScreenshot(const QImage &, const QString &))); - - connect(&_fileSystemWatcher , SIGNAL( fileChanged(const QString &)), - this , SLOT( onWatchFileChanged(const QString &))); - - connect(&_ApplicationController , SIGNAL(didPOSTOSVersionData (const QString &)), - this , SLOT( onPOSTOSVersionData (const QString &))); - connect(&_ApplicationController , SIGNAL(didPOSTEthernetData (const QString &)), - this , SLOT( onPOSTEthernetData (const QString &))); - connect(&_ApplicationController , SIGNAL(didPOSTWirelessData (const QString &)), - this , SLOT( onPOSTWirelessData (const QString &))); - connect(&_ApplicationController , SIGNAL(didPOSTBluetoothData (const QString &)), - this , SLOT( onPOSTBluetoothData (const QString &))); - connect(&_ApplicationController , SIGNAL(didPOSTCloudSyncData (const QString &)), - this , SLOT( onPOSTCloudSyncData (const QString &))); - - connect(&_Logger , SIGNAL(didLogBackup (const QString &)), - this , SLOT( onLogBackup (const QString &))); - connect(&_CloudSyncController , SIGNAL(didLogUpload (const QString &)), - this , SLOT( onLogUpload (const QString &))); - - DEVICE_DEV_INIT_CONNECTIONS_LIST - - connect(this, SIGNAL(didEventThreadChange()), - this, SLOT( onEventThreadChange())); - -} - -/*! - * \brief ApplicationController::initThread - * \details Moves this object into the thread vThread. - * And checks that this method is called from main thread. - * Also connects quitThread to application aboutToQuit. - * \param vThread - the thread - */ -void DeviceController::initThread(QThread &vThread) -{ - // runs in main thread - Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); - _thread = &vThread; - _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); - connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); - _thread->start(); - moveToThread(_thread); - - emit didEventThreadChange( QPrivateSignal() ); -} - -/*! - * \brief DeviceController::quitThread - * \details Moves this object to main thread to be handled by QApplication - * And to be destroyed there. - */ -void DeviceController::quitThread() -{ - // disabled coco begin validated: Application termination is not correctly done in coco!!! - // it has been tested and works perfectly fine in normal run. - - if ( ! _thread ) return; - - // runs in thread - moveToThread(qApp->thread()); // validated -} -// disabled coco end - -/*! - * \brief DeviceController::usbSeek - * \details Tries to look for the available USB devices - * Starts from sda1 to sdz1. - * \note will only look for the first partition if there is any - * \param vDevice - Found device (/dev/sda1) - * \return true if a device found - */ -bool DeviceController::usbSeek(QString &vDevice) -{ - // disabled coco begin validated: Needed User Interaction so tested manually - // This function cannot be tested on any device other than target - // because only on device the usb is /dev/sdX# and others are mmcblk___ - // but on VM and normal Linuxes all drives are /dev/sdX# and cannot be identified as USB. - // And the difference between how USB is detected and sd-card is that - // for the USB we need to look into /dev/sdX# - // but for the sd-card we look for the mounted path which is much easier. - // That's why indication of the sd-card is more accurate than USB at least on VM. - QString dev = "/dev/sd"; - QString device = ""; - for (char a = 'a'; a <= 'z'; a++) { - device = dev + a + '1'; - if (QFileInfo::exists(device)) { - vDevice = device; - return true; // application is deciding on the first existing drive - } - } - vDevice = device; - return false; - // disabled coco end -} - -/*! - * \brief DeviceController::driveSpaceCheck - * \param vPath - Device mount point - * \param vTotalBytes - Total volume size in bytes - * \param vAvailableBytes - Size (in bytes) available for the current user - * \param vPercent - The percentage of available space - * \return - The drive mounted and ready - * \note if device ejected manually system assumes it's still ready. - */ -bool DeviceController::driveSpaceCheck(const QString &vPath, qint64 &vTotalBytes, qint64 &vAvailableBytes, bool *vIsReadOnly) -{ - QStorageInfo storage(vPath); - bool isReady = storage.isReady (); - bool isReadOnly = storage.isReadOnly(); - bool isMounted = FileHandler::isMounted(vPath); - - if ( vIsReadOnly ) *vIsReadOnly = isReadOnly; - - if ( isReady ) { - vTotalBytes = storage.bytesTotal(); - vAvailableBytes = storage.bytesAvailable(); - } - - if ( ! isMounted || ! isReady ) { - isReady = false; - vTotalBytes = 0; - vAvailableBytes = 0; - } - return isReady; -} - -/*! - * \brief DeviceController::timerEvent - * \details This event handler has been re-implemented in here - * to receive timer events for the object - * for the timer which has been set to _checkInterval - * Runs the usbCheck on interval - */ -void DeviceController::timerEvent(QTimerEvent *) -{ -#ifdef BUILD_FOR_TARGET - usbCheck(); - sdcardSpaceCheck(); - - // The treatment logs are held in a separate partition from the unencrypted - // logs and need a separate disk space usage check - settingsPartitionSpaceCheck(); -#endif - findPendingLogs(); -} - -/*! - * \brief DeviceController::usbCheck - * \details Runs usbSeek to mount or umount or remove it - * regarding the state it's in. - */ -void DeviceController::usbCheck() -{ - QString device = ""; - usbSpaceCheck(); - if (usbSeek(device)) { - if (! _umounted ) { // avoid to mount the USB which has just been unmounted - if (! _mounted ) { // avoid to mount the USB which has just been mounted - usbMount(device); - } - } else { // the umount is requested? - usbUmount(USB_Mount_Point); - } - } else { - if ( ! _removed ) { - usbRemove(); - } - } -} - -/*! - * \brief DeviceController::sdcardSpaceCheck - * \details Checks for the SD-Card drive space. - */ -void DeviceController::sdcardSpaceCheck() -{ - static bool mInitialized = false; - // Old Info ; // Current info - static bool mOIsReady = false; bool mCIsReady = false; - static bool mOIsReadOnly = false; bool mCIsReadOnly = false; - static qint64 mOAvailable = 0; qint64 mCAvailable = 0; - static quint8 mOPercent = 0; quint8 mCPercent = 0; - - qint64 mCTotal = 0; - - bool isMounted = FileHandler::isMounted(Storage::SDCard_Base_Path_Name); - QString pathToCheckSpace = isMounted ? Storage::SDCard_Base_Path_Name : gStandard_tmp; - mCIsReady = driveSpaceCheck(pathToCheckSpace, mCTotal, mCAvailable, &mCIsReadOnly); - - //DEBUG: qDebug()<< "Checking space for path of : " << pathToCheckSpace << " mCTotal " << mCTotal << " available " << mCAvailable; - - if (mOIsReadOnly != mCIsReadOnly || mOIsReady != mCIsReady || ! mInitialized ) { - mOIsReadOnly = mCIsReadOnly; - mOIsReady = mCIsReady; - mInitialized = true; - //DEBUG:0: qDebug() << " ~~~~~~~~~~ " << __FUNCTION__ << mInitialized << mCIsReady << mOIsReady << mCIsReadOnly << mOIsReadOnly; - emit didSDCardStateChange(mCIsReady, mCIsReadOnly); - } - //NOTE: this if block has to be independent of the mOIsReady != mCIsReady - // because current and old may be the same all the time and then this if block will not execute - // and reaches to the log and fills the log unnecessarily. - if (! mCIsReady ) { - mOPercent = 0; - mOAvailable = 0; - emit didSDCardSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); - return; - } - - mCPercent = mCTotal ? ((100 * mCAvailable) / mCTotal) : 0; - if (mCPercent < _minRequiredAvailableSpacePercent) { - LOG_DEBUG(QString("SD-CARD space lower than %1%").arg(_minRequiredAvailableSpacePercent)); - emit didSDCardSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); - emit didSDCardSpaceTooLow(_minRequiredAvailableSpacePercent); - } - - //DEBUG: qDebug() << Storage::SDCard_Base_Path_Name << mCIsReady << mCTotal << mOAvailable << mCAvailable << (mOAvailable == mCAvailable) << mOPercent << mCPercent << mCIsReadOnly; - if (mOPercent != mCPercent || mOAvailable != mCAvailable ) { - mOPercent = mCPercent ; - mOAvailable = mCAvailable ; - emit didSDCardSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); - /// DEBUG: qDebug() << Storage::SDCard_Base_Path_Name << mCIsReady << mCTotal << mCAvailable << mPercent ; - } -} - -/*! - * \brief DeviceController::usbSpaceCheck - * \details Checks for the USB drive space. - */ -void DeviceController::usbSpaceCheck() -{ - static bool mInitialized = false; - // Old Info ; // Current info - static bool mOIsReady = false; bool mCIsReady = false; - static bool mOIsReadOnly = false; bool mCIsReadOnly = false; - static qint64 mOTotal = 0; qint64 mCTotal = 0; - static qint64 mOAvailable = 0; qint64 mCAvailable = 0; - - quint8 mPercent = 0; - - mCIsReady = driveSpaceCheck(Storage::USB_Mount_Point, mCTotal, mCAvailable, &mCIsReadOnly); -#if BUILD_FOR_DESKTOP - mCIsReady = true; // it is set to always true since on desktop a local folder is used for the USB folder which doesn't need (un)mount. -#endif - if (mOIsReadOnly != mCIsReadOnly || mOIsReady != mCIsReady || ! mInitialized ) { - mOIsReadOnly = mCIsReadOnly; - mOIsReady = mCIsReady; - mInitialized = true; - emit didUSBStateChange(mCIsReady, mCIsReadOnly); - - if (! mCIsReady ) { - mOTotal = 0; - mOAvailable = 0; - emit didUSBSpaceChange(mCIsReady, mCTotal, mCAvailable, mPercent); - return; - } - } - - mPercent = mCTotal ? ((100 * mCAvailable) / mCTotal) : 0; - if (mOTotal != mCTotal || mOAvailable != mCAvailable) { - mOTotal = mCTotal ; - mOAvailable = mCAvailable ; - emit didUSBSpaceChange(mCIsReady, mCTotal, mCAvailable, mPercent); - } - - // DEBUG: qDebug() << "DeviceController::usbSpaceCheck" - // << mCIsReady - // << mCIsReadOnly - // << mCTotal - // << mCAvailable ; -} - -/*! - * \brief DeviceController::settingsPartitionSpaceCheck - * \details Checks the disk space of the encrypted partition - */ -void DeviceController::settingsPartitionSpaceCheck() -{ - static bool mInitialized = false; - // Old Info ; // Current info - static bool mOIsReady = false; bool mCIsReady = false; - static bool mOIsReadOnly = false; bool mCIsReadOnly = false; - static qint64 mOAvailable = 0; qint64 mCAvailable = 0; - static quint8 mOPercent = 0; quint8 mCPercent = 0; - - qint64 mCTotal = 0; - mCIsReady = driveSpaceCheck(Storage::Settings_Path(), mCTotal, mCAvailable, &mCIsReadOnly); - - //DEBUG: qDebug()<< "Checking space for path of : " << Storage::Settings_Path() << " mCTotal " << mCTotal << " available " << mCAvailable; - - if (mOIsReadOnly != mCIsReadOnly || mOIsReady != mCIsReady || ! mInitialized ) { - mOIsReadOnly = mCIsReadOnly; - mOIsReady = mCIsReady; - mInitialized = true; - //DEBUG:0: qDebug() << " ~~~~~~~~~~ " << __FUNCTION__ << mInitialized << mCIsReady << mOIsReady << mCIsReadOnly << mOIsReadOnly; - emit didSettingsPartitionStateChange(mCIsReady, mCIsReadOnly); - } - //NOTE: this if block has to be independent of the mOIsReady != mCIsReady - // because current and old may be the same all the time and then this if block will not execute - // and reaches to the log and fills the log unnecessarily. - if (! mCIsReady ) { - mOPercent = 0; - mOAvailable = 0; - emit didSettingsPartitionSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); - return; - } - - mCPercent = mCTotal ? ((100 * mCAvailable) / mCTotal) : 0; - if (mCPercent < _minRequiredAvailableSpacePercent) { - LOG_DEBUG(QString("Settings partition space lower than %1%").arg(_minRequiredAvailableSpacePercent)); - emit didSettingsPartitionSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); - emit didSDCardSpaceTooLow(_minRequiredAvailableSpacePercent); - } - - /// DEBUG: qDebug() << Storage::SDCard_Base_Path_Name << mCIsReady << mOTotal << mCTotal << (mOTotal == mCTotal) << mOAvailable << mCAvailable << (mOAvailable == mCAvailable) << mPercent << mCIsReadOnly; - if (mOPercent != mCPercent && mOAvailable != mCAvailable ) { - mOPercent = mCPercent ; - mOAvailable = mCAvailable ; - emit didSettingsPartitionSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); - /// DEBUG: qDebug() << Storage::SDCard_Base_Path_Name << mCIsReady << mCTotal << mCAvailable << mPercent ; - } -} - - -/*! - * \brief DeviceController::usbError - * \details Logs any error which has been happened - * On USB device vDevice - * \note When this method has been called error number will be read from errno variable, - * Which has been set by umount or mount. - * \param vDevice - */ -void DeviceController::usbError(const QString &vDevice) -{ - // disabled coco begin validated: This needs user interaction to plug-in/out the USB device - // has been tested manually - QString error; - static QString lastError; - switch (errno) { - case EBUSY: - error = tr("%1 - Device or resource busy (%2)").arg(errno).arg(vDevice); - _mounted = true; - break; - - default: - error = tr("%1 - %2 (%3 , %4)").arg(errno).arg(strerror(errno)).arg(vDevice).arg(USB_Mount_Point); - break; - - } - if (error != lastError) { - LOG_DEBUG("USB: " + error); - lastError = error; - } -} -// disabled coco end - -/*! - * \brief DeviceController::onUSBDriveUmount - * \details This is the slot connected to the _ApplicationController's didUSBDriveUmount SIGNAL, - * To notify the USB drive detach. - */ -void DeviceController::onUSBDriveUmount() -{ - // disabled coco begin validated: This needs user interaction to plug-in/out the USB device - // has been tested manually - _umounted = true; -} -// disabled coco end - -/*! - * \brief DeviceController::usbMount - * \details Mounts the USB device vDevice - * \note Emits didUSBDriveMount signal - * \param vDevice - USB device to be mounted (e.g. /dev/sda1) - * \return true on successful mount - */ -void DeviceController::usbMount(const QString &vDevice) -{ - usbMountReq(vDevice); -} - -/*! - * \brief DeviceController::usbUmount - * \details Unmounts the USB device vDevice - * \note Emits didUSBDriveUmount signal - * \param vDevice - USB device to be unmounted (e.g. /dev/sda1) - * \return true on successful unmount - */ -void DeviceController::usbUmount(const QString &vDevice) -{ - usbMountReq(vDevice, false); -} - -/*! - * \brief DeviceController::usbRemove - * \details Removed the USB mount point - * So next time it is not mounted as next device. - * \note Emits didUSBDriveRemove signal - */ -void DeviceController::usbRemove() -{ - // disabled coco begin validated: This needs user interaction to plug-out the USB device - // has been tested manually - usbUmount(USB_Mount_Point); - _umounted = false; - _removed = true; - LOG_DEBUG("USB drive removed"); - emit didUSBDriveRemove(); -} -// disabled coco end - -/*! - * \brief DeviceController::checkError - * \details check if has error, then sets the base model accept to false and the reason to the error. - * in that case logs the error message and emit the didAttributeResponse to notify the GUI. - * \param vError - the error code, this can be the Gui enum or system number - * \param vExtraLogInfo - any extra information to be logged. Not display to user. - * \return - */ -template -bool DeviceController::checkError(DeviceError::Scripts_Error_Enum vError, TModel &vModel, QString vExtraLogInfo) -{ - if ( vError ) { - QString src = (vError > DeviceError::eDevice_Scripts_Error_Start ? MAbstract::unitText(MAbstract::Unit_Enum::eUI) : MAbstract::unitText(MAbstract::Unit_Enum::eDV)) + ","; - vModel._data.mAccepted = false ; - vModel._data.mReason = vError ; - vModel._data.mMessage = DeviceError::deviceErrorText(vError, vError); - LOG_APPED(" ," + src + vModel._data.mMessage + " " + vExtraLogInfo); - emit didAttributeResponse(vModel._data); - return true; - } - return false; -} - -///////////////////////////////////////////// DeviceBrightness -/*! - * \brief DeviceController::onAttributeRequest - * \details Sets the brightness level - * \param vBrightness - */ -void DeviceController::onAttributeRequest(const DeviceBrightnessRequestData &vData) -{ - // ----- initializing the member variable models - _deviceBrightnessRequest ._data = vData; - - - // ----- extract the required data - _deviceBrightnessRequest.setBrightnessSysVal(); - LOG_APPED( _deviceBrightnessRequest.toString()); - - // ----- check that script exists. - QString script; - if ( checkError( DeviceError::checkScript(script, vData.mRead ? Brightness_Get : Brightness_Set), _deviceBrightnessResponse, script) ) - return; - - // ----- check if the process is not running - if ( _processBrightness.state() != QProcess::NotRunning ) { - checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceBrightnessResponse); - return; - } - - // ----- run the process - int timeout_ms = 10000; - QStringList params; - params << QString::number(_deviceBrightnessRequest._data.mBrightness_val); - TimedProcess *timedProcess = new TimedProcess(&_processBrightness, script, timeout_ms, params); - timedProcess->start(); - -} - -/*! - * \brief DeviceController::onProcessBrightnessFinished - * \details Called when the process to set the brightness has finished - * \param vExitCode (int) the exit code - * \note exit code -> 0 : set Accept [MBase] -> Log -> emit - * !0 : set Attrib [MBrgh] -> Log -> emit - * 1 - get an error when in onAttributeRequest : scriptErrorText([Gui Enum ]) - * 2 - get an error when in onProcessBrightnessExitCode : scriptErrorText([vExitCode]) - * 3 - get no error when in onProcessBrightnessExitCode : MDeviceResponse.toString() - * - in case 3 the specific model _data has to be filled prior to the toString to have it in the log. - */ -void DeviceController::onProcessBrightnessExitCode(int vExitCode, QProcess::ExitStatus) -{ - if ( ! checkError(static_cast(vExitCode), _deviceBrightnessResponse, _deviceBrightnessResponse.toString()) ) { // has no error - if (_deviceBrightnessRequest._data.mRead) { - bool ok = false; - int brightness = _processBrightness.readLine().toInt(&ok); - if (ok) { - _deviceBrightnessResponse.setBrightnessPercent(brightness); - } - else { - checkError(DeviceError::eDevice_Scripts_Error_Incorrect_Rsp,_deviceBrightnessResponse, _deviceBrightnessResponse.toString()); - return; - } - } - else { - _deviceBrightnessResponse.setBrightnessPercent(_deviceBrightnessRequest._data.mBrightness_val); - _deviceBrightnessResponse._data.mMessage = _deviceBrightnessResponse.toString(); - } - LOG_APPED(_deviceBrightnessResponse._data.mMessage); - emit didAttributeResponse(_deviceBrightnessResponse._data); - } -} - - -///////////////////////////////////////////// DeviceRootSSHAccess -/*! - * \brief DeviceController::onAttributeRequest - * \details Sets the RootSSHAccess - * \param vRootSSHAccess - */ -void DeviceController::onAttributeRequest(const DeviceRootSSHAccessRequestData &vData) -{ - // ----- initializing the member variable models - _deviceRootSSHAccessRequest._data = vData; - LOG_APPED( _deviceRootSSHAccessRequest.toString()); - - // ----- check that script exists. - QString script; - if ( checkError( DeviceError::checkScript(script, RootSSHAccess), _deviceRootSSHAccessResponse, script) ) - return; - - // ----- check if the process is not running - if ( _processRootSSHAccess.state() != QProcess::NotRunning ) { - checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceRootSSHAccessResponse); - return; - } - - // ----- run the process - int timeout_ms = 10000; - QStringList params; - if ( ! _deviceRootSSHAccessRequest._data.mIsGet ) params << FSN(_deviceRootSSHAccessRequest._data.mRootSSHAccess); - TimedProcess *timedProcess = new TimedProcess(&_processRootSSHAccess, script, timeout_ms, params); - timedProcess->start(); -} - -/*! - * \brief DeviceController::onProcessRootSSHAccessExitCode - * \details Called when the process to set the RootSSHAccess has finished - * \param vExitCode (int) the exit code - * \note exit code -> 0 : set Accept [MBase] -> Log -> emit - * !0 : set Attrib [MBrgh] -> Log -> emit - * 1 - get an error when in onAttributeRequest : scriptErrorText([Gui Enum ]) - * 2 - get an error when in onProcessRootSSHAccessExitCode : scriptErrorText([vExitCode]) - * 3 - get no error when in onProcessRootSSHAccessExitCode : MDeviceResponse.toString() - * - in case 3 the specific model _data has to be filled prior to the toString to have it in the log. - */ -void DeviceController::onProcessRootSSHAccessExitCode(int vExitCode, QProcess::ExitStatus) -{ - if ( ! checkError(static_cast(vExitCode), _deviceRootSSHAccessResponse, _deviceRootSSHAccessResponse.toString()) ) { // has no error - if (_deviceRootSSHAccessRequest._data.mIsGet) { - bool ok = true; - Qt::CheckState rootSSHAccess = Qt:: Unchecked; - uint value = _processRootSSHAccess.readLine().toUInt(&ok); - if ( ! ok ) goto lError; - - switch (value) { - case 0 : rootSSHAccess = Qt:: Unchecked; break; - case 1 : rootSSHAccess = Qt::PartiallyChecked; break; - case 2 : rootSSHAccess = Qt:: Checked; break; - default : ok = false; - } - - if ( ! ok ) goto lError; - - _deviceRootSSHAccessResponse._data.mMessage = _deviceRootSSHAccessResponse.toString(); - _deviceRootSSHAccessResponse._data.mRootSSHAccess = rootSSHAccess; - } - else { - _deviceRootSSHAccessResponse._data.mMessage = _deviceRootSSHAccessResponse.toString(); - _deviceRootSSHAccessResponse._data.mRootSSHAccess = _deviceRootSSHAccessRequest._data.mRootSSHAccess; - } - - LOG_APPED(_deviceRootSSHAccessResponse._data.mMessage); - emit didAttributeResponse(_deviceRootSSHAccessResponse._data); - } - else { - // the error in this case is handled in the checkError - } - return; - -lError: - checkError(DeviceError::eDevice_Scripts_Error_Incorrect_Rsp, _deviceRootSSHAccessResponse, _deviceRootSSHAccessResponse.toString()); -} - -///////////////////////////////////////////// DeviceCryptSetup -/*! - * \brief DeviceController::onAttributeRequest - * \details Calls the CryptSetup script with the model data DeviceCryptSetupRequestData - * \param vData - the model data - */ -void DeviceController::onAttributeRequest(const DeviceCryptSetupRequestData &vData) -{ - //DEBUG qDebug() << " ---------- " << vData.mCommand << vData.mPassword; - - _deviceCryptSetupRequest._data = vData; - - // ----- check that script exists. - QString script; - if ( checkError( DeviceError::checkScript(script, Crypt_Setup), _deviceCryptSetupResponse, script) ) - return; - - // ----- check if the process is not running - if ( _processCryptSetup.state() != QProcess::NotRunning ) { - checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceCryptSetupResponse); - return; - } - - - // ----- run the process - int timeout = 10000; - TimedProcess *timedProcess = new TimedProcess(&_processCryptSetup, script, timeout, { _deviceCryptSetupRequest._data.mCommand }); - _processCryptSetup.setEnvironment(QProcess::systemEnvironment() << QString("PASSWORD=%1").arg(_deviceCryptSetupRequest._data.mPassword)); - timedProcess->start(); - - // Update UI with a response - MDeviceCryptSetupResponse model; - model._data.mAccepted = false; - model._data.mMessage = tr("Encrypted Partition %1 started.").arg(_deviceCryptSetupRequest._data.mCommand); - emit didAttributeResponse(model.data()); -} - -/*! - * \brief DeviceController::onProcessCryptSetupExitCode - * \param vExitCode - * \param vStatus - */ -void DeviceController::onProcessCryptSetupExitCode(int vExitCode, QProcess::ExitStatus vStatus) -{ - const int ERR_CRYPTSETUP_MOUNT_ISMOUNT=134; // is used in crypt_setup.sh do not modify - - // The Exit code in this script is not used. - // any other checking is done by UI Software at the moment this script is called. - // The only thing matters is the pared device info in text and it will be empty string if error happens. - MDeviceCryptSetupResponse model; - QByteArray deviceInfo; - if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; - else deviceInfo = _processCryptSetup.readAll(); - model.fromByteArray( deviceInfo, &vExitCode ); - // DEBUG: qDebug() << model._data.mEchoInfo; - emit didAttributeResponse(model.data()); - LOG_APPED_UI(model.data().mMessage); - - bool isSetup = _deviceCryptSetupRequest._data.mCommand == "setup"; - bool isMount = _deviceCryptSetupRequest._data.mCommand == "mount"; - bool isMounted = isMount && ( - vExitCode == ERR_CRYPTSETUP_MOUNT_ISMOUNT || // is already mounted - vExitCode == 0 // successful mount - ); - bool isUpdate = gEnableUpdating && isMounted; - - if ( isMount ) emit didCryptSetupMount(model._data.mAccepted); - - QString msg = ""; - int err = 0 ; - //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. - Storage::Settings settings; - // moving the configuration files if the encrypted partition creation was successful. - if ( isUpdate ) goto lMove; // if it is gEnableUpdating, bypass the mAccepted for already mounted. - if ( ! model._data.mAccepted ) goto lErr ; // any other case goto error - if ( ! isSetup ) goto lOut ; // if not setup do NOT continue to move configurations - -lMove: - err = settings.configurationsMove(&msg, isUpdate); - if ( err ) { - model._data.mAccepted = false ; - model._data.mReason = err ; - model._data.mMessage = msg ; - emit didAttributeResponse(model.data()); - LOG_APPED_UI(model.data().mMessage); - } - -lOut: - return; - -lErr: - LOG_DEBUG(QString("Encrypted Partition %1 failed").arg(_deviceCryptSetupRequest._data.mCommand)); -} - -///////////////////////////////////////////// DeviceBluetoothPaired -void DeviceController::onAttributeRequest(const DeviceBluetoothPairedResetRequestData &) -{ - // ----- check that script exists. - QString script; - if ( checkError( DeviceError::checkScript(script, Bluetooth_Paired_Reset), _deviceBluetoothPairedResetResponse, script) ) - return; - - // ----- check if the process is not running - if ( _processBluetoothPairedReset.state() != QProcess::NotRunning ) { - checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceBluetoothPairedResetResponse); - return; - } - - // ----- run the process - int timeout_ms = 10000; - TimedProcess *timedProcess = new TimedProcess(&_processBluetoothPairedReset, script, timeout_ms); - timedProcess->start(); -} - -void DeviceController::onProcessBluetoothPairedResetExitCode(int vExitCode, QProcess::ExitStatus vStatus) -{ - // TODO: review the usage and definition of this object _deviceBluetoothPairedResetResponse. do we need it any more? - MDeviceBluetoothPairedResetResponse model; - QByteArray deviceInfo; - if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; - else deviceInfo = _processBluetoothPairedReset.readAll(); - model.fromByteArray( deviceInfo, &vExitCode ); - LOG_APPED_UI(model.data().mMessage); - emit didAttributeResponse(model.data()); -} - -///////////////////////////////////////////// DeviceBluetoothPairedQuery -void DeviceController::onAttributeRequest(const DeviceBluetoothPairedQueryRequestData &) -{ - // ----- check that script exists. - QString script; - if ( checkError( DeviceError::checkScript(script, Bluetooth_Paired_Query), _deviceBluetoothPairedQueryResponse, script) ) - return; - - // ----- check if the process is not running - if ( _processBluetoothPairedQuery.state() != QProcess::NotRunning ) { - checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceBluetoothPairedQueryResponse); - return; - } - - // ----- run the process - int timeout_ms = 10000; - TimedProcess *timedProcess = new TimedProcess(&_processBluetoothPairedQuery, script, timeout_ms); - timedProcess->start(); -} - -void DeviceController::onProcessBluetoothPairedQueryExitCode(int vExitCode, QProcess::ExitStatus vStatus) -{ - // The Exit code in this script is not used. - // any other checking is done by UI Software at the moment this script is called. - // The only thing matters is the pared device info in text and it will be empty string if error happens. - MDeviceBluetoothPairedQueryResponse model; - QByteArray deviceInfo; - if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; - else deviceInfo = _processBluetoothPairedQuery.readAll(); - model.fromByteArray( deviceInfo, &vExitCode ); - emit didAttributeResponse(model.data()); - LOG_APPED_UI(model.data().mMessage); -} - -/*! - * \brief DeviceController::doScreenshot - * \details emit the screenshot signal to run that in Device controller thread - * \param vCurrentDateTime - */ -void DeviceController::doScreenshot(const QImage &vImage, const QString &vFileName) { - emit didScreenshot(vImage, vFileName); -} - -/*! - * \brief DeviceController::onScreenshot - * \details The function to save the image vImage in the file vFileName - * \param vImage - The image source object - * \param vFileName - The filename to same the image to - */ -void DeviceController::onScreenshot(const QImage &vImage, const QString &vFileName) { - vImage.save(vFileName); - LOG_DEBUG("Screenshot saved in " + vFileName); -} - -/*! - * \brief DeviceController::ondoAddWatch - * \details The thread safe add file watch method - * \param vFile - The file to add to watch. - */ -void DeviceController::ondoAddWatch(const QString &vFile, bool vCreate) -{ - DeviceError::Scripts_Error_Enum err = DeviceError::eDevice_OK; - if ( vCreate ) { - if ( ! FileHandler::write ( vFile, "", false) ) { err = DeviceError::eDevice_Watch_Error_NotCreate; goto lErr; }} - else { - if ( ! QFileInfo::exists ( vFile ) ) { err = DeviceError::eDevice_Watch_Error_NotFound ; goto lErr; }} - if ( ! _fileSystemWatcher.removePath ( vFile ) ) { LOG_APPED_UI(QString("Device NOT watching %1").arg(vFile)); } - else { LOG_APPED_UI(QString("Device watch removed %1").arg(vFile)); } - if ( ! _fileSystemWatcher.addPath ( vFile ) ) { err = DeviceError::eDevice_Watch_Error_NotAdded ; goto lErr; } - - LOG_APPED_UI(QString("Device watch %1").arg(vFile)); - return; -lErr: - LOG_DEBUG(DeviceError::deviceErrorText(err, 0)); -} - -/*! - * \brief DeviceController::onWatchFileChanged - * \details This slot is called once the files being watched is updated. - * \param vFile - the file name. - */ -void DeviceController::onWatchFileChanged(const QString &vFile) -{ - emit didWatchFileChange(vFile); -} - -/*! - * \brief DeviceController::onEventThreadChange - * \details The signal handler for the DeviceController(this)::didEventThreadChange - * to start checking for the Encrypted partition readiness. - */ -void DeviceController::onEventThreadChange() -{ - //DEBUG qDebug() << " ---------- " << __FUNCTION__ << QThread::currentThread()->objectName() << QThread::currentThread() << qApp->thread(); - if ( QThread::currentThread() != &Threads::_DeviceController_Thread ) { - qCritical() << " ***** Device controller thread not initialized correctly ***** "; - return; - } - _hasThread = true; - checkConfugurationMountReady(); -} - -/*! - * \brief DeviceController::onPOSTOSVersionData - * \details Collects the OS Version - * when it is ready after the POST is done reading OS Version - * \param vMacAddress - The Ethernet MAC address - */ -void DeviceController::onPOSTOSVersionData(const QString &vOSVersion) { - _osVersion = vOSVersion; - emit didPOSTOSVersionData (vOSVersion); -} - -/*! - * \brief DeviceController::onPOSTEthernetData - * \details Collects the ethernet mac address - * when it is ready after the POST is done for the Ethernet - * \param vMacAddress - The Ethernet MAC address - */ -void DeviceController::onPOSTEthernetData(const QString &vMacAddress) { - _macEthernet = vMacAddress; - emit didPOSTEthernetData (vMacAddress); -} - -/*! - * \brief DeviceController::onPOSTWirelessData - * \details Collects the wireless mac address - * when it is ready after the POST is done for the Wireless connection - * \param vMacAddress - The Wireless MAC address - */ -void DeviceController::onPOSTWirelessData(const QString &vMacAddress) { - _macWireless = vMacAddress; - - encryption::varSalt(vMacAddress); - _hasSalt = ! vMacAddress.trimmed().isEmpty(); - checkConfugurationMountReady(); - - emit didPOSTWirelessData (vMacAddress); -} - -/*! - * \brief DeviceController::onPOSTBluetoothData - * \details Collects the bluetooth mac address - * when it is ready after the POST is done for the Bluetooth - * \param vMacAddress - The Bluetooth MAC address - */ -void DeviceController::onPOSTBluetoothData(const QString &vMacAddress) { - _macBluetooth = vMacAddress; - emit didPOSTBluetoothData (vMacAddress); -} - -/*! - * \brief DeviceController::onPOSTCloudSyncData - * \details Collects the CloudSync Network Address - * when it is ready after the POST is done for the CloudSync - * \param vNetAddress - *** Not defined yet and is a placeholder for later use *** - */ -void DeviceController::onPOSTCloudSyncData(const QString &vNetAddress) { - _netCloudSync = vNetAddress; - emit didPOSTCloudSyncData (vNetAddress); -} - -bool DeviceController::logBackup(const QString &vFileName) -{ - if ( ! gLogUpload ) return false; // no log backup - - bool ok = true; - QString fileSrc = vFileName; - QFileInfo fileInfo(vFileName); - QString filePath(fileInfo.absolutePath()); - QString fileBase(fileInfo.baseName()); - QString fileSufx(fileInfo.completeSuffix().prepend(_Logger.logFileNamePendingSubExt())); - QString fileDest(QString("%1/%2.%3").arg(filePath, fileBase, fileSufx)); - // DEBUG qDebug() << __FUNCTION__ << "\n" << vFileName << "\n" << fileDest; - if ( gLogCompress ) { - fileSrc += _Logger.logFileNameCompressExt(); - fileDest += _Logger.logFileNameCompressExt(); - ok = FileHandler::backupFile(vFileName); - } - ok = QFile::rename(fileSrc, fileDest); - return ok; -} - -void DeviceController::onLogBackup(const QString &vFileName) -{ - if ( ! gLogUpload ) return; // no log backup ( slot ) - - bool ok = true; - ok = logBackup( vFileName); - emit didLogBackup(ok, vFileName); -} - -bool DeviceController::logUpload(const QString &vFileName) -{ - if ( ! gLogUpload ) return false; // no log Uploaded rename - - bool ok = true; - QFileInfo fileInfo(vFileName); - QString filePath; - QString fileBase(fileInfo.baseName()); - QString ext = _Logger.logFileNamePendingSubExt(); - QString fileSufx(fileInfo.completeSuffix().remove(ext)); - QString fileDest = QString("%1.%2").arg(fileBase, fileSufx); - - Logger::LogType logType = _Logger.logFileLogType(vFileName, filePath); - ok = logType != Logger::eLogNone; - if ( ! ok ) { LOG_APPED_UI(QString("CS Incorrect log upload type [%1]").arg(fileSufx)); goto lOut; } - // DEBUG qDebug() << __FUNCTION__ << "\n" << vFileName << "\n" << fileDest; - - ok = QFile::rename(filePath + vFileName, filePath + fileDest); -lOut: - return ok; -} - -void DeviceController::onLogUpload(const QString &vFileName) -{ - if ( ! gLogUpload ) return; // no log uploaded rename ( slot ) - - bool ok = true; - ok = logUpload( vFileName); - emit didLogUpload(ok, vFileName); -} - -/*! - * \brief DeviceController::checkConfugurationMountReady - * \details Cheks if the system is ready to mount the encrypted partition. - * The object has to be on its own thread and the salt for the decryption has to be ready. - */ -void DeviceController::checkConfugurationMountReady() -{ - /// in manufacturing or updating the system is logged with root and configurations are in /home/root - /// therefore no need to mount the cononfiguraiton partition. - /// also for manufacturing the partition is being set up - /// and is less steps for setup if the partition is not mounted. - if ( gEnableManufacturing ) return; // it should do the mount when gEnableUpdating, therefore here should not add gEnableUpdating. - if ( ! ( _hasThread && _hasSalt ) ) return; - - DeviceCryptSetupRequestData data; - data.mCommand = "mount"; - bool ok = false; - data.mPassword = encryption::configurationsPassword( ok ); - if ( ! ok ) { // not enough infromation to create a secure passowrd - // status(tr("Not enough secure information provided")); - } - else { - onAttributeRequest(data); - } - - // I_AM_HERE - // HERE move the settings read from ApplicationController to here - // here is when the DeviceController is moved to its thread - // and now can start mounting the encrypted partition - // and then read the settings. - // TODO don't forget to check for the required configurations files and parameters in the settings class. - // and take care of the security flag in the Storage class. -} - -/*! - * \brief DeviceController::findPendingLogs - * \details this function counts downs for the _pendingInterval - * when the _pendingCounter reaches 0 will search for the files - * and if there is any will get the recent file in the list - */ -void DeviceController::findPendingLogs() -{ - if ( ! gLogUpload ) return; // no log upload pending detection - - static QString pendingLog = ""; - if( _pendingCounter ) { - _pendingCounter -- ; - return; - } - else { - _pendingCounter = _pendingInterval; // every minute - } - - QFileInfoList pendingFiles; - QString logLoc = Log_Folder_Base; - QString logExt = QString("*.%1*").arg(_Logger.logFileNamePendingSubExt()); // "*.u.*"; - for( auto logFolder : { Log_Folder_Application, Log_Folder_Service/*, Log_Folder_CloudSync*/ } ) { - pendingFiles = Storage::FileHandler::find( logLoc + logFolder, { logExt } ); - // look into the list. - // if there are pending files, - // send a request only for the top on the list - /// Note I thought it makes sense to send the oldest on the application and service logs - /// but there are some conversation about the situation if something happens on the device, - /// and it would be a critical situation to get the recent/top log and won't wait for the old ones to upload. - // * When gets uploaded, moves from pending then next one comes to top - // the process repeats until there is no file in pending - - bool uploadOldestFirst = true; //TODO: make if configurable(cfg, or cli) - - if ( pendingFiles.count() ) { - // the most recent/first log file, to first ask for the current log which has just been saved as pending - if ( uploadOldestFirst ) { - _pendingLog = pendingFiles.last().absoluteFilePath(); - } else { - _pendingLog = pendingFiles.first().absoluteFilePath(); - } - QString message = pendingLog; - LOG_DEBUG(message); - emit didPendingLog( _pendingLog, FileHandler::sha256sum( _pendingLog ) ); - // when a pending file found in the first log folder stop - // until there is none in first one (log) - // then continue to the next log folder (service) ... - goto lOut; - } - } -lOut: - return; -} - -///////////////////////////////////////////// DeviceFactoryReset -void DeviceController::onAttributeRequest(const DeviceFactoryResetRequestData &vData) -{ - _deviceFactoryResetRequest._data = vData; - - // ----- check that script exists. - QString script; - if ( checkError( DeviceError::checkScript(script, Factory_Reset), _deviceFactoryResetResponse, script) ) - return; - - // ----- check if the process is not running - if ( _processFactoryReset.state() != QProcess::NotRunning ) { - checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceFactoryResetResponse); - return; - } - - - // ----- run the process - int timeout_ms = 10000; - TimedProcess *timedProcess = new TimedProcess(&_processFactoryReset, script, timeout_ms); - timedProcess->start(); - - MDeviceFactoryResetResponse model; - model._data.mAccepted = false; // will indirectly set the property factoryResetEnabled - model._data.mMessage = tr("Factory Reset started."); - emit didAttributeResponse(model.data()); -} - -/*! - * \brief DeviceController::onProcessFactoryResetExitCode - * \param vExitCode - the script exit code. - * \param vStatus - the script echoed message. - */ -void DeviceController::onProcessFactoryResetExitCode(int vExitCode, QProcess::ExitStatus vStatus) -{ - // The Exit code in this script is not used. - // any other checking is done by UI Software at the moment this script is called. - // The only thing matters is the paired device info in text and it will be empty string if error happens. - MDeviceFactoryResetResponse model; - QByteArray deviceInfo; - if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; - else deviceInfo = _processFactoryReset.readAll(); - model.fromByteArray( deviceInfo, &vExitCode ); - // DEBUG: qDebug() << model._data.mMessage << deviceInfo; - emit didAttributeResponse (model.data()); - emit didFactoryReset (model._data.mAccepted); - - LOG_APPED_UI(model.data().mMessage); -} - -///////////////////////////////////////////// DeviceDecommission -void DeviceController::onAttributeRequest(const DeviceDecommissionRequestData &vData) -{ - _deviceDecommissionRequest._data = vData; - - // ----- check that script exists. - QString script; - if ( checkError( DeviceError::checkScript(script, Device_Decommission), _deviceDecommissionResponse, script) ) - return; - - // ----- check if the process is not running - if ( _processDecommission.state() != QProcess::NotRunning ) { - checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceDecommissionResponse); - return; - } - - - // ----- run the process - int timeout_ms = 10000; - TimedProcess *timedProcess = new TimedProcess(&_processDecommission, script, timeout_ms, { CloudSyncPath }); - _processDecommission.setEnvironment(QProcess::systemEnvironment() << QString("PASSWORD=%1").arg(_deviceDecommissionRequest._data.mPassword)); - timedProcess->start(); - - MDeviceDecommissionResponse model; - model._data.mAccepted = false; // will indirectly set the property decommissionEnabled - model._data.mMessage = tr("Decommissioning started."); - emit didAttributeResponse(model.data()); -} - -/*! - * \brief DeviceController::onProcessDecommissionExitCode - * \param vExitCode - * \param vStatus - */ -void DeviceController::onProcessDecommissionExitCode(int vExitCode, QProcess::ExitStatus vStatus) -{ - // The Exit code in this script is not used. - // any other checking is done by UI Software at the moment this script is called. - // The only thing matters is the paired device info in text and it will be empty string if error happens. - MDeviceDecommissionResponse model; - QByteArray deviceInfo; - if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; - else deviceInfo = _processDecommission.readAll(); - model.fromByteArray( deviceInfo, &vExitCode ); - // DEBUG: qDebug() << model._data.mMessage << deviceInfo; - emit didAttributeResponse (model.data()); - emit didDecommissioning (model._data.mAccepted); - - LOG_APPED_UI(model.data().mMessage); -} - -///////////////////////////////////////////// DeviceUSBMounting -void DeviceController::onAttributeRequest(const DeviceUSBMountRequestData &vData) -{ - Q_UNUSED(vData) - usbMountReq(vData.usbDevice, vData.isMountRequest); -} - -/*! - * \brief DeviceController::usbMountReq - * \details Calls the Usb unmount/mount script - * \param vIsMount - indicate if the request is for mounting or unmounting - * \param vDevice - the path to the USB device - */ -void DeviceController::usbMountReq(const QString &vDevice, bool vIsMount) -{ - qDebug() << __FUNCTION__ << vDevice << vIsMount; - _deviceUSBMountRequest._data.isMountRequest = vIsMount ; - _deviceUSBMountRequest._data.usbDevice = vDevice ; // not necessary, but to be consistent - - // ----- check that script exists. - QString script; - if ( checkError( DeviceError::checkScript(script, (vIsMount ? USB_Mount : USB_Unmount )), _deviceUSBMountResponse, script) ) - return; - - // ----- check if the process is not running - if ( _processUSBMount.state() != QProcess::NotRunning ) { - checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceUSBMountResponse); - return; - } - - // ----- run the process - int timeout_ms = 5000; - TimedProcess *timedProcess = new TimedProcess(&_processUSBMount, script, timeout_ms, {vDevice, USB_Mount_Point, USB_File_System}); - timedProcess->start(); - - MDeviceUSBMountResponse model; - model._data.mAccepted = false; - model._data.mMessage = vIsMount ? tr("USB unmount started.") : tr("USB mount started"); - emit didAttributeResponse(model.data()); -} - -/*! - * \brief DeviceController::onProcessUSBMountExitCode - * \param vExitCode - * \param vStatus - */ -void DeviceController::onProcessUSBMountExitCode(int vExitCode, QProcess::ExitStatus vStatus) -{ - MDeviceUSBMountResponse model; - QByteArray deviceInfo; - if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; - else deviceInfo = _processUSBMount.readAll(); - model.fromByteArray( deviceInfo, &vExitCode ); - emit didAttributeResponse(model.data()); - - // Re-evaluate the USB space available - need to call this here to avoid - // visual lag caused by waiting to call this function on the timer timeout - usbSpaceCheck(); - - bool ok = ! vStatus; - QString usbDevice = _deviceUSBMountRequest._data.usbDevice; - if(_deviceUSBMountRequest._data.isMountRequest) { // *** USB Mount - if ( ok && ! _mounted ) { - _mounted = true; - _removed = false; - LOG_DEBUG(QString("USB flash drive %1 has been mounted on %2").arg(usbDevice).arg(USB_Mount_Point)); - emit didUSBDriveMount(); - } else { - usbError(usbDevice); - } - } else { // *** USB Unmount - if ( ok && _mounted ) { - _mounted = false; - // _umounted = true; // I think it might be needed, but needs more testing. - LOG_DEBUG(QString("USB drive %2 unmounted").arg(usbDevice)); - emit didUSBDriveUmount(); - } else { - // the error is irrelevant, commented out for now - // usbError(usbDrive); - } - } - - // log error and exit - return; -} +#include "DeviceController.h" + +// Linux +#include +#include + +// Qt +#include +#include +#include + +// Project +#include "Threads.h" +#include "StorageGlobals.h" +#include "Logger.h" +#include "CloudSyncController.h" +#include "ApplicationController.h" +#include "FileHandler.h" +#include "DeviceModels.h" +#include "Settings.h" +#include "encryption.h" + +// namespace +using namespace Model; +using namespace Device; +using namespace Storage; + +/*! + * \brief DeviceController::DeviceController + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +DeviceController::DeviceController(QObject *parent) : QObject(parent) { + _fileSystemWatcher.setParent(this); + DEVICE_DEV_PARENT_LIST +} + +/*! + * \brief DeviceController::init + * \details Initializes the class by setting the connections and starting the timer + * \return False if it has been called before. + */ +bool DeviceController::init() +{ + if ( _init ) return false; + _init = true; + + // runs in DeviceController thread + initConnections(); + startTimer(_interval); + + return true; +} + +/*! + * \brief DeviceController::init + * \details Initialized the Class by calling the init() method first + * And initializes the thread vThread by calling initThread + * on success init(). + * \param vThread - the thread + * \return returns the return value of the init() method + */ +bool DeviceController::init(QThread &vThread) +{ + if ( ! init() ) return false; + initThread(vThread); + return true; +} + +/*! + * \brief DeviceController::quit + * \details quits the class + * Calls quitThread + */ +void DeviceController::quit() +{ + quitThread(); +} + + +/*! + * \brief DeviceController::initConnections + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + */ +void DeviceController::initConnections() +{ + connect(&_ApplicationController , SIGNAL(didUSBDriveUmount()), + this , SLOT( onUSBDriveUmount())); + + connect(this , SIGNAL(didScreenshot(const QImage &, const QString &)), + this , SLOT( onScreenshot(const QImage &, const QString &))); + + connect(&_fileSystemWatcher , SIGNAL( fileChanged(const QString &)), + this , SLOT( onWatchFileChanged(const QString &))); + + connect(&_ApplicationController , SIGNAL(didPOSTOSVersionData (const QString &)), + this , SLOT( onPOSTOSVersionData (const QString &))); + connect(&_ApplicationController , SIGNAL(didPOSTEthernetData (const QString &)), + this , SLOT( onPOSTEthernetData (const QString &))); + connect(&_ApplicationController , SIGNAL(didPOSTWirelessData (const QString &)), + this , SLOT( onPOSTWirelessData (const QString &))); + connect(&_ApplicationController , SIGNAL(didPOSTBluetoothData (const QString &)), + this , SLOT( onPOSTBluetoothData (const QString &))); + connect(&_ApplicationController , SIGNAL(didPOSTCloudSyncData (const QString &)), + this , SLOT( onPOSTCloudSyncData (const QString &))); + + connect(&_Logger , SIGNAL(didLogBackup (const QString &)), + this , SLOT( onLogBackup (const QString &))); + connect(&_CloudSyncController , SIGNAL(didLogUpload (const QString &)), + this , SLOT( onLogUpload (const QString &))); + + DEVICE_DEV_INIT_CONNECTIONS_LIST + + connect(this, SIGNAL(didEventThreadChange()), + this, SLOT( onEventThreadChange())); + +} + +/*! + * \brief ApplicationController::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void DeviceController::initThread(QThread &vThread) +{ + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); + + emit didEventThreadChange( QPrivateSignal() ); +} + +/*! + * \brief DeviceController::quitThread + * \details Moves this object to main thread to be handled by QApplication + * And to be destroyed there. + */ +void DeviceController::quitThread() +{ + // disabled coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + + if ( ! _thread ) return; + + // runs in thread + moveToThread(qApp->thread()); // validated +} +// disabled coco end + +/*! + * \brief DeviceController::usbSeek + * \details Tries to look for the available USB devices + * Starts from sda1 to sdz1. + * \note will only look for the first partition if there is any + * \param vDevice - Found device (/dev/sda1) + * \return true if a device found + */ +bool DeviceController::usbSeek(QString &vDevice) +{ + // disabled coco begin validated: Needed User Interaction so tested manually + // This function cannot be tested on any device other than target + // because only on device the usb is /dev/sdX# and others are mmcblk___ + // but on VM and normal Linuxes all drives are /dev/sdX# and cannot be identified as USB. + // And the difference between how USB is detected and sd-card is that + // for the USB we need to look into /dev/sdX# + // but for the sd-card we look for the mounted path which is much easier. + // That's why indication of the sd-card is more accurate than USB at least on VM. + QString dev = "/dev/sd"; + QString device = ""; + for (char a = 'a'; a <= 'z'; a++) { + device = dev + a + '1'; + if (QFileInfo::exists(device)) { + vDevice = device; + return true; // application is deciding on the first existing drive + } + } + vDevice = device; + return false; + // disabled coco end +} + +/*! + * \brief DeviceController::driveSpaceCheck + * \param vPath - Device mount point + * \param vTotalBytes - Total volume size in bytes + * \param vAvailableBytes - Size (in bytes) available for the current user + * \param vPercent - The percentage of available space + * \return - The drive mounted and ready + * \note if device ejected manually system assumes it's still ready. + */ +bool DeviceController::driveSpaceCheck(const QString &vPath, qint64 &vTotalBytes, qint64 &vAvailableBytes, bool *vIsReadOnly) +{ + QStorageInfo storage(vPath); + bool isReady = storage.isReady (); + bool isReadOnly = storage.isReadOnly(); + bool isMounted = FileHandler::isMounted(vPath); + + if ( vIsReadOnly ) *vIsReadOnly = isReadOnly; + + if ( isReady ) { + vTotalBytes = storage.bytesTotal(); + vAvailableBytes = storage.bytesAvailable(); + } + + if ( ! isMounted || ! isReady ) { + isReady = false; + vTotalBytes = 0; + vAvailableBytes = 0; + } + return isReady; +} + +/*! + * \brief DeviceController::timerEvent + * \details This event handler has been re-implemented in here + * to receive timer events for the object + * for the timer which has been set to _checkInterval + * Runs the usbCheck on interval + */ +void DeviceController::timerEvent(QTimerEvent *) +{ +#ifdef BUILD_FOR_TARGET + usbCheck(); + sdcardSpaceCheck(); + + // The treatment logs are held in a separate partition from the unencrypted + // logs and need a separate disk space usage check + settingsPartitionSpaceCheck(); +#endif + findPendingLogs(); +} + +/*! + * \brief DeviceController::usbCheck + * \details Runs usbSeek to mount or umount or remove it + * regarding the state it's in. + */ +void DeviceController::usbCheck() +{ + QString device = ""; + usbSpaceCheck(); + if (usbSeek(device)) { + if (! _umounted ) { // avoid to mount the USB which has just been unmounted + if (! _mounted ) { // avoid to mount the USB which has just been mounted + usbMount(device); + } + } else { // the umount is requested? + usbUmount(USB_Mount_Point); + } + } else { + if ( ! _removed ) { + usbRemove(); + } + } +} + +/*! + * \brief DeviceController::sdcardSpaceCheck + * \details Checks for the SD-Card drive space. + */ +void DeviceController::sdcardSpaceCheck() +{ + static bool mInitialized = false; + // Old Info ; // Current info + static bool mOIsReady = false; bool mCIsReady = false; + static bool mOIsReadOnly = false; bool mCIsReadOnly = false; + static qint64 mOAvailable = 0; qint64 mCAvailable = 0; + static quint8 mOPercent = 0; quint8 mCPercent = 0; + + qint64 mCTotal = 0; + + bool isMounted = FileHandler::isMounted(Storage::SDCard_Base_Path_Name); + QString pathToCheckSpace = isMounted ? Storage::SDCard_Base_Path_Name : gStandard_tmp; + mCIsReady = driveSpaceCheck(pathToCheckSpace, mCTotal, mCAvailable, &mCIsReadOnly); + + //DEBUG: qDebug()<< "Checking space for path of : " << pathToCheckSpace << " mCTotal " << mCTotal << " available " << mCAvailable; + + if (mOIsReadOnly != mCIsReadOnly || mOIsReady != mCIsReady || ! mInitialized ) { + mOIsReadOnly = mCIsReadOnly; + mOIsReady = mCIsReady; + mInitialized = true; + //DEBUG:0: qDebug() << " ~~~~~~~~~~ " << __FUNCTION__ << mInitialized << mCIsReady << mOIsReady << mCIsReadOnly << mOIsReadOnly; + emit didSDCardStateChange(mCIsReady, mCIsReadOnly); + } + //NOTE: this if block has to be independent of the mOIsReady != mCIsReady + // because current and old may be the same all the time and then this if block will not execute + // and reaches to the log and fills the log unnecessarily. + if (! mCIsReady ) { + mOPercent = 0; + mOAvailable = 0; + emit didSDCardSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); + return; + } + + mCPercent = mCTotal ? ((100 * mCAvailable) / mCTotal) : 0; + if (mCPercent < _minRequiredAvailableSpacePercent) { + LOG_DEBUG(QString("SD-CARD space lower than %1%").arg(_minRequiredAvailableSpacePercent)); + emit didSDCardSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); + emit didSDCardSpaceTooLow(_minRequiredAvailableSpacePercent); + } + + //DEBUG: qDebug() << Storage::SDCard_Base_Path_Name << mCIsReady << mCTotal << mOAvailable << mCAvailable << (mOAvailable == mCAvailable) << mOPercent << mCPercent << mCIsReadOnly; + if (mOPercent != mCPercent || mOAvailable != mCAvailable ) { + mOPercent = mCPercent ; + mOAvailable = mCAvailable ; + emit didSDCardSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); + /// DEBUG: qDebug() << Storage::SDCard_Base_Path_Name << mCIsReady << mCTotal << mCAvailable << mPercent ; + } +} + +/*! + * \brief DeviceController::usbSpaceCheck + * \details Checks for the USB drive space. + */ +void DeviceController::usbSpaceCheck() +{ + static bool mInitialized = false; + // Old Info ; // Current info + static bool mOIsReady = false; bool mCIsReady = false; + static bool mOIsReadOnly = false; bool mCIsReadOnly = false; + static qint64 mOTotal = 0; qint64 mCTotal = 0; + static qint64 mOAvailable = 0; qint64 mCAvailable = 0; + + quint8 mPercent = 0; + + mCIsReady = driveSpaceCheck(Storage::USB_Mount_Point, mCTotal, mCAvailable, &mCIsReadOnly); +#if BUILD_FOR_DESKTOP + mCIsReady = true; // it is set to always true since on desktop a local folder is used for the USB folder which doesn't need (un)mount. +#endif + if (mOIsReadOnly != mCIsReadOnly || mOIsReady != mCIsReady || ! mInitialized ) { + mOIsReadOnly = mCIsReadOnly; + mOIsReady = mCIsReady; + mInitialized = true; + emit didUSBStateChange(mCIsReady, mCIsReadOnly); + + if (! mCIsReady ) { + mOTotal = 0; + mOAvailable = 0; + emit didUSBSpaceChange(mCIsReady, mCTotal, mCAvailable, mPercent); + return; + } + } + + mPercent = mCTotal ? ((100 * mCAvailable) / mCTotal) : 0; + if (mOTotal != mCTotal || mOAvailable != mCAvailable) { + mOTotal = mCTotal ; + mOAvailable = mCAvailable ; + emit didUSBSpaceChange(mCIsReady, mCTotal, mCAvailable, mPercent); + } + + // DEBUG: qDebug() << "DeviceController::usbSpaceCheck" + // << mCIsReady + // << mCIsReadOnly + // << mCTotal + // << mCAvailable ; +} + +/*! + * \brief DeviceController::settingsPartitionSpaceCheck + * \details Checks the disk space of the encrypted partition + */ +void DeviceController::settingsPartitionSpaceCheck() +{ + static bool mInitialized = false; + // Old Info ; // Current info + static bool mOIsReady = false; bool mCIsReady = false; + static bool mOIsReadOnly = false; bool mCIsReadOnly = false; + static qint64 mOAvailable = 0; qint64 mCAvailable = 0; + static quint8 mOPercent = 0; quint8 mCPercent = 0; + + qint64 mCTotal = 0; + mCIsReady = driveSpaceCheck(Storage::Settings_Path(), mCTotal, mCAvailable, &mCIsReadOnly); + + //DEBUG: qDebug()<< "Checking space for path of : " << Storage::Settings_Path() << " mCTotal " << mCTotal << " available " << mCAvailable; + + if (mOIsReadOnly != mCIsReadOnly || mOIsReady != mCIsReady || ! mInitialized ) { + mOIsReadOnly = mCIsReadOnly; + mOIsReady = mCIsReady; + mInitialized = true; + //DEBUG:0: qDebug() << " ~~~~~~~~~~ " << __FUNCTION__ << mInitialized << mCIsReady << mOIsReady << mCIsReadOnly << mOIsReadOnly; + emit didSettingsPartitionStateChange(mCIsReady, mCIsReadOnly); + } + //NOTE: this if block has to be independent of the mOIsReady != mCIsReady + // because current and old may be the same all the time and then this if block will not execute + // and reaches to the log and fills the log unnecessarily. + if (! mCIsReady ) { + mOPercent = 0; + mOAvailable = 0; + emit didSettingsPartitionSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); + return; + } + + mCPercent = mCTotal ? ((100 * mCAvailable) / mCTotal) : 0; + if (mCPercent < _minRequiredAvailableSpacePercent) { + LOG_DEBUG(QString("Settings partition space lower than %1%").arg(_minRequiredAvailableSpacePercent)); + emit didSettingsPartitionSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); + emit didSDCardSpaceTooLow(_minRequiredAvailableSpacePercent); + } + + /// DEBUG: qDebug() << Storage::SDCard_Base_Path_Name << mCIsReady << mOTotal << mCTotal << (mOTotal == mCTotal) << mOAvailable << mCAvailable << (mOAvailable == mCAvailable) << mPercent << mCIsReadOnly; + if (mOPercent != mCPercent && mOAvailable != mCAvailable ) { + mOPercent = mCPercent ; + mOAvailable = mCAvailable ; + emit didSettingsPartitionSpaceChange(mCIsReady, mCTotal, mCAvailable, mCPercent); + /// DEBUG: qDebug() << Storage::SDCard_Base_Path_Name << mCIsReady << mCTotal << mCAvailable << mPercent ; + } +} + + +/*! + * \brief DeviceController::usbError + * \details Logs any error which has been happened + * On USB device vDevice + * \note When this method has been called error number will be read from errno variable, + * Which has been set by umount or mount. + * \param vDevice + */ +void DeviceController::usbError(const QString &vDevice) +{ + // disabled coco begin validated: This needs user interaction to plug-in/out the USB device + // has been tested manually + QString error; + static QString lastError; + switch (errno) { + case EBUSY: + error = tr("%1 - Device or resource busy (%2)").arg(errno).arg(vDevice); + _mounted = true; + break; + + default: + error = tr("%1 - %2 (%3 , %4)").arg(errno).arg(strerror(errno)).arg(vDevice).arg(USB_Mount_Point); + break; + + } + if (error != lastError) { + LOG_DEBUG("USB: " + error); + lastError = error; + } +} +// disabled coco end + +/*! + * \brief DeviceController::onUSBDriveUmount + * \details This is the slot connected to the _ApplicationController's didUSBDriveUmount SIGNAL, + * To notify the USB drive detach. + */ +void DeviceController::onUSBDriveUmount() +{ + // disabled coco begin validated: This needs user interaction to plug-in/out the USB device + // has been tested manually + _umounted = true; +} +// disabled coco end + +/*! + * \brief DeviceController::usbMount + * \details Mounts the USB device vDevice + * \note Emits didUSBDriveMount signal + * \param vDevice - USB device to be mounted (e.g. /dev/sda1) + * \return true on successful mount + */ +void DeviceController::usbMount(const QString &vDevice) +{ + usbMountReq(vDevice); +} + +/*! + * \brief DeviceController::usbUmount + * \details Unmounts the USB device vDevice + * \note Emits didUSBDriveUmount signal + * \param vDevice - USB device to be unmounted (e.g. /dev/sda1) + * \return true on successful unmount + */ +void DeviceController::usbUmount(const QString &vDevice) +{ + usbMountReq(vDevice, false); +} + +/*! + * \brief DeviceController::usbRemove + * \details Removed the USB mount point + * So next time it is not mounted as next device. + * \note Emits didUSBDriveRemove signal + */ +void DeviceController::usbRemove() +{ + // disabled coco begin validated: This needs user interaction to plug-out the USB device + // has been tested manually + usbUmount(USB_Mount_Point); + _umounted = false; + _removed = true; + LOG_DEBUG("USB drive removed"); + emit didUSBDriveRemove(); +} +// disabled coco end + +/*! + * \brief DeviceController::checkError + * \details check if has error, then sets the base model accept to false and the reason to the error. + * in that case logs the error message and emit the didAttributeResponse to notify the GUI. + * \param vError - the error code, this can be the Gui enum or system number + * \param vExtraLogInfo - any extra information to be logged. Not display to user. + * \return + */ +template +bool DeviceController::checkError(DeviceError::Scripts_Error_Enum vError, TModel &vModel, QString vExtraLogInfo) +{ + if ( vError ) { + QString src = (vError > DeviceError::eDevice_Scripts_Error_Start ? MAbstract::unitText(MAbstract::Unit_Enum::eUI) : MAbstract::unitText(MAbstract::Unit_Enum::eDV)) + ","; + vModel._data.mAccepted = false ; + vModel._data.mReason = vError ; + vModel._data.mMessage = DeviceError::deviceErrorText(vError, vError); + LOG_APPED(" ," + src + vModel._data.mMessage + " " + vExtraLogInfo); + emit didAttributeResponse(vModel._data); + return true; + } + return false; +} + +///////////////////////////////////////////// DeviceBrightness +/*! + * \brief DeviceController::onAttributeRequest + * \details Sets the brightness level + * \param vBrightness + */ +void DeviceController::onAttributeRequest(const DeviceBrightnessRequestData &vData) +{ + // ----- initializing the member variable models + _deviceBrightnessRequest ._data = vData; + + + // ----- extract the required data + _deviceBrightnessRequest.setBrightnessSysVal(); + LOG_APPED( _deviceBrightnessRequest.toString()); + + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, vData.mRead ? Brightness_Get : Brightness_Set), _deviceBrightnessResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processBrightness.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceBrightnessResponse); + return; + } + + // ----- run the process + int timeout_ms = 10000; + QStringList params; + params << QString::number(_deviceBrightnessRequest._data.mBrightness_val); + TimedProcess *timedProcess = new TimedProcess(&_processBrightness, script, timeout_ms, params); + timedProcess->start(); + +} + +/*! + * \brief DeviceController::onProcessBrightnessFinished + * \details Called when the process to set the brightness has finished + * \param vExitCode (int) the exit code + * \note exit code -> 0 : set Accept [MBase] -> Log -> emit + * !0 : set Attrib [MBrgh] -> Log -> emit + * 1 - get an error when in onAttributeRequest : scriptErrorText([Gui Enum ]) + * 2 - get an error when in onProcessBrightnessExitCode : scriptErrorText([vExitCode]) + * 3 - get no error when in onProcessBrightnessExitCode : MDeviceResponse.toString() + * - in case 3 the specific model _data has to be filled prior to the toString to have it in the log. + */ +void DeviceController::onProcessBrightnessExitCode(int vExitCode, QProcess::ExitStatus) +{ + if ( ! checkError(static_cast(vExitCode), _deviceBrightnessResponse, _deviceBrightnessResponse.toString()) ) { // has no error + if (_deviceBrightnessRequest._data.mRead) { + bool ok = false; + int brightness = _processBrightness.readLine().toInt(&ok); + if (ok) { + _deviceBrightnessResponse.setBrightnessPercent(brightness); + } + else { + checkError(DeviceError::eDevice_Scripts_Error_Incorrect_Rsp,_deviceBrightnessResponse, _deviceBrightnessResponse.toString()); + return; + } + } + else { + _deviceBrightnessResponse.setBrightnessPercent(_deviceBrightnessRequest._data.mBrightness_val); + _deviceBrightnessResponse._data.mMessage = _deviceBrightnessResponse.toString(); + } + LOG_APPED(_deviceBrightnessResponse._data.mMessage); + emit didAttributeResponse(_deviceBrightnessResponse._data); + } +} + + +///////////////////////////////////////////// DeviceRootSSHAccess +/*! + * \brief DeviceController::onAttributeRequest + * \details Sets the RootSSHAccess + * \param vRootSSHAccess + */ +void DeviceController::onAttributeRequest(const DeviceRootSSHAccessRequestData &vData) +{ + // ----- initializing the member variable models + _deviceRootSSHAccessRequest._data = vData; + LOG_APPED( _deviceRootSSHAccessRequest.toString()); + + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, RootSSHAccess), _deviceRootSSHAccessResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processRootSSHAccess.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceRootSSHAccessResponse); + return; + } + + // ----- run the process + int timeout_ms = 10000; + QStringList params; + if ( ! _deviceRootSSHAccessRequest._data.mIsGet ) params << FSN(_deviceRootSSHAccessRequest._data.mRootSSHAccess); + TimedProcess *timedProcess = new TimedProcess(&_processRootSSHAccess, script, timeout_ms, params); + timedProcess->start(); +} + +/*! + * \brief DeviceController::onProcessRootSSHAccessExitCode + * \details Called when the process to set the RootSSHAccess has finished + * \param vExitCode (int) the exit code + * \note exit code -> 0 : set Accept [MBase] -> Log -> emit + * !0 : set Attrib [MBrgh] -> Log -> emit + * 1 - get an error when in onAttributeRequest : scriptErrorText([Gui Enum ]) + * 2 - get an error when in onProcessRootSSHAccessExitCode : scriptErrorText([vExitCode]) + * 3 - get no error when in onProcessRootSSHAccessExitCode : MDeviceResponse.toString() + * - in case 3 the specific model _data has to be filled prior to the toString to have it in the log. + */ +void DeviceController::onProcessRootSSHAccessExitCode(int vExitCode, QProcess::ExitStatus) +{ + if ( ! checkError(static_cast(vExitCode), _deviceRootSSHAccessResponse, _deviceRootSSHAccessResponse.toString()) ) { // has no error + if (_deviceRootSSHAccessRequest._data.mIsGet) { + bool ok = true; + Qt::CheckState rootSSHAccess = Qt:: Unchecked; + uint value = _processRootSSHAccess.readLine().toUInt(&ok); + if ( ! ok ) goto lError; + + switch (value) { + case 0 : rootSSHAccess = Qt:: Unchecked; break; + case 1 : rootSSHAccess = Qt::PartiallyChecked; break; + case 2 : rootSSHAccess = Qt:: Checked; break; + default : ok = false; + } + + if ( ! ok ) goto lError; + + _deviceRootSSHAccessResponse._data.mMessage = _deviceRootSSHAccessResponse.toString(); + _deviceRootSSHAccessResponse._data.mRootSSHAccess = rootSSHAccess; + } + else { + _deviceRootSSHAccessResponse._data.mMessage = _deviceRootSSHAccessResponse.toString(); + _deviceRootSSHAccessResponse._data.mRootSSHAccess = _deviceRootSSHAccessRequest._data.mRootSSHAccess; + } + + LOG_APPED(_deviceRootSSHAccessResponse._data.mMessage); + emit didAttributeResponse(_deviceRootSSHAccessResponse._data); + } + else { + // the error in this case is handled in the checkError + } + return; + +lError: + checkError(DeviceError::eDevice_Scripts_Error_Incorrect_Rsp, _deviceRootSSHAccessResponse, _deviceRootSSHAccessResponse.toString()); +} + +///////////////////////////////////////////// DeviceCryptSetup +/*! + * \brief DeviceController::onAttributeRequest + * \details Calls the CryptSetup script with the model data DeviceCryptSetupRequestData + * \param vData - the model data + */ +void DeviceController::onAttributeRequest(const DeviceCryptSetupRequestData &vData) +{ + //DEBUG qDebug() << " ---------- " << vData.mCommand << vData.mPassword; + + _deviceCryptSetupRequest._data = vData; + + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, Crypt_Setup), _deviceCryptSetupResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processCryptSetup.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceCryptSetupResponse); + return; + } + + + // ----- run the process + int timeout = 10000; + TimedProcess *timedProcess = new TimedProcess(&_processCryptSetup, script, timeout, { _deviceCryptSetupRequest._data.mCommand }); + _processCryptSetup.setEnvironment(QProcess::systemEnvironment() << QString("PASSWORD=%1").arg(_deviceCryptSetupRequest._data.mPassword)); + timedProcess->start(); + + // Update UI with a response + MDeviceCryptSetupResponse model; + model._data.mAccepted = false; + model._data.mMessage = tr("Encrypted Partition %1 started.").arg(_deviceCryptSetupRequest._data.mCommand); + emit didAttributeResponse(model.data()); +} + +/*! + * \brief DeviceController::onProcessCryptSetupExitCode + * \param vExitCode + * \param vStatus + */ +void DeviceController::onProcessCryptSetupExitCode(int vExitCode, QProcess::ExitStatus vStatus) +{ + const int ERR_CRYPTSETUP_MOUNT_ISMOUNT=134; // is used in crypt_setup.sh do not modify + + // The Exit code in this script is not used. + // any other checking is done by UI Software at the moment this script is called. + // The only thing matters is the pared device info in text and it will be empty string if error happens. + MDeviceCryptSetupResponse model; + QByteArray deviceInfo; + if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; + else deviceInfo = _processCryptSetup.readAll(); + model.fromByteArray( deviceInfo, &vExitCode ); + // DEBUG: qDebug() << model._data.mEchoInfo; + emit didAttributeResponse(model.data()); + LOG_APPED_UI(model.data().mMessage); + + bool isSetup = _deviceCryptSetupRequest._data.mCommand == "setup"; + bool isMount = _deviceCryptSetupRequest._data.mCommand == "mount"; + bool isMounted = isMount && ( + vExitCode == ERR_CRYPTSETUP_MOUNT_ISMOUNT || // is already mounted + vExitCode == 0 // successful mount + ); + bool isUpdate = gEnableUpdating && isMounted; + + if ( isMount ) emit didCryptSetupMount(model._data.mAccepted); + + QString msg = ""; + int err = 0 ; + //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. + Storage::Settings settings; + // moving the configuration files if the encrypted partition creation was successful. + if ( isUpdate ) goto lMove; // if it is gEnableUpdating, bypass the mAccepted for already mounted. + if ( ! model._data.mAccepted ) goto lErr ; // any other case goto error + if ( ! isSetup ) goto lOut ; // if not setup do NOT continue to move configurations + +lMove: + err = settings.configurationsMove(&msg, isUpdate); + if ( err ) { + model._data.mAccepted = false ; + model._data.mReason = err ; + model._data.mMessage = msg ; + emit didAttributeResponse(model.data()); + LOG_APPED_UI(model.data().mMessage); + } + +lOut: + return; + +lErr: + LOG_DEBUG(QString("Encrypted Partition %1 failed").arg(_deviceCryptSetupRequest._data.mCommand)); +} + +///////////////////////////////////////////// DeviceBluetoothPaired +void DeviceController::onAttributeRequest(const DeviceBluetoothPairedResetRequestData &) +{ + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, Bluetooth_Paired_Reset), _deviceBluetoothPairedResetResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processBluetoothPairedReset.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceBluetoothPairedResetResponse); + return; + } + + // ----- run the process + int timeout_ms = 10000; + TimedProcess *timedProcess = new TimedProcess(&_processBluetoothPairedReset, script, timeout_ms); + timedProcess->start(); +} + +void DeviceController::onProcessBluetoothPairedResetExitCode(int vExitCode, QProcess::ExitStatus vStatus) +{ + // TODO: review the usage and definition of this object _deviceBluetoothPairedResetResponse. do we need it any more? + MDeviceBluetoothPairedResetResponse model; + QByteArray deviceInfo; + if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; + else deviceInfo = _processBluetoothPairedReset.readAll(); + model.fromByteArray( deviceInfo, &vExitCode ); + LOG_APPED_UI(model.data().mMessage); + emit didAttributeResponse(model.data()); +} + +///////////////////////////////////////////// DeviceBluetoothPairedQuery +void DeviceController::onAttributeRequest(const DeviceBluetoothPairedQueryRequestData &) +{ + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, Bluetooth_Paired_Query), _deviceBluetoothPairedQueryResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processBluetoothPairedQuery.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceBluetoothPairedQueryResponse); + return; + } + + // ----- run the process + int timeout_ms = 10000; + TimedProcess *timedProcess = new TimedProcess(&_processBluetoothPairedQuery, script, timeout_ms); + timedProcess->start(); +} + +void DeviceController::onProcessBluetoothPairedQueryExitCode(int vExitCode, QProcess::ExitStatus vStatus) +{ + // The Exit code in this script is not used. + // any other checking is done by UI Software at the moment this script is called. + // The only thing matters is the pared device info in text and it will be empty string if error happens. + MDeviceBluetoothPairedQueryResponse model; + QByteArray deviceInfo; + if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; + else deviceInfo = _processBluetoothPairedQuery.readAll(); + model.fromByteArray( deviceInfo, &vExitCode ); + emit didAttributeResponse(model.data()); + LOG_APPED_UI(model.data().mMessage); +} + +/*! + * \brief DeviceController::doScreenshot + * \details emit the screenshot signal to run that in Device controller thread + * \param vCurrentDateTime + */ +void DeviceController::doScreenshot(const QImage &vImage, const QString &vFileName) { + emit didScreenshot(vImage, vFileName); +} + +/*! + * \brief DeviceController::onScreenshot + * \details The function to save the image vImage in the file vFileName + * \param vImage - The image source object + * \param vFileName - The filename to same the image to + */ +void DeviceController::onScreenshot(const QImage &vImage, const QString &vFileName) { + vImage.save(vFileName); + LOG_DEBUG("Screenshot saved in " + vFileName); +} + +/*! + * \brief DeviceController::ondoAddWatch + * \details The thread safe add file watch method + * \param vFile - The file to add to watch. + */ +void DeviceController::ondoAddWatch(const QString &vFile, bool vCreate) +{ + DeviceError::Scripts_Error_Enum err = DeviceError::eDevice_OK; + if ( vCreate ) { + if ( ! FileHandler::write ( vFile, "", false) ) { err = DeviceError::eDevice_Watch_Error_NotCreate; goto lErr; }} + else { + if ( ! QFileInfo::exists ( vFile ) ) { err = DeviceError::eDevice_Watch_Error_NotFound ; goto lErr; }} + if ( ! _fileSystemWatcher.removePath ( vFile ) ) { LOG_APPED_UI(QString("Device NOT watching %1").arg(vFile)); } + else { LOG_APPED_UI(QString("Device watch removed %1").arg(vFile)); } + if ( ! _fileSystemWatcher.addPath ( vFile ) ) { err = DeviceError::eDevice_Watch_Error_NotAdded ; goto lErr; } + + LOG_APPED_UI(QString("Device watch %1").arg(vFile)); + return; +lErr: + LOG_DEBUG(DeviceError::deviceErrorText(err, 0)); +} + +/*! + * \brief DeviceController::onWatchFileChanged + * \details This slot is called once the files being watched is updated. + * \param vFile - the file name. + */ +void DeviceController::onWatchFileChanged(const QString &vFile) +{ + emit didWatchFileChange(vFile); +} + +/*! + * \brief DeviceController::onEventThreadChange + * \details The signal handler for the DeviceController(this)::didEventThreadChange + * to start checking for the Encrypted partition readiness. + */ +void DeviceController::onEventThreadChange() +{ + //DEBUG qDebug() << " ---------- " << __FUNCTION__ << QThread::currentThread()->objectName() << QThread::currentThread() << qApp->thread(); + if ( QThread::currentThread() != &Threads::_DeviceController_Thread ) { + qCritical() << " ***** Device controller thread not initialized correctly ***** "; + return; + } + _hasThread = true; + checkConfugurationMountReady(); +} + +/*! + * \brief DeviceController::onPOSTOSVersionData + * \details Collects the OS Version + * when it is ready after the POST is done reading OS Version + * \param vMacAddress - The Ethernet MAC address + */ +void DeviceController::onPOSTOSVersionData(const QString &vOSVersion) { + _osVersion = vOSVersion; + emit didPOSTOSVersionData (vOSVersion); +} + +/*! + * \brief DeviceController::onPOSTEthernetData + * \details Collects the ethernet mac address + * when it is ready after the POST is done for the Ethernet + * \param vMacAddress - The Ethernet MAC address + */ +void DeviceController::onPOSTEthernetData(const QString &vMacAddress) { + _macEthernet = vMacAddress; + emit didPOSTEthernetData (vMacAddress); +} + +/*! + * \brief DeviceController::onPOSTWirelessData + * \details Collects the wireless mac address + * when it is ready after the POST is done for the Wireless connection + * \param vMacAddress - The Wireless MAC address + */ +void DeviceController::onPOSTWirelessData(const QString &vMacAddress) { + _macWireless = vMacAddress; + + encryption::varSalt(vMacAddress); + _hasSalt = ! vMacAddress.trimmed().isEmpty(); + checkConfugurationMountReady(); + + emit didPOSTWirelessData (vMacAddress); +} + +/*! + * \brief DeviceController::onPOSTBluetoothData + * \details Collects the bluetooth mac address + * when it is ready after the POST is done for the Bluetooth + * \param vMacAddress - The Bluetooth MAC address + */ +void DeviceController::onPOSTBluetoothData(const QString &vMacAddress) { + _macBluetooth = vMacAddress; + emit didPOSTBluetoothData (vMacAddress); +} + +/*! + * \brief DeviceController::onPOSTCloudSyncData + * \details Collects the CloudSync Network Address + * when it is ready after the POST is done for the CloudSync + * \param vNetAddress - *** Not defined yet and is a placeholder for later use *** + */ +void DeviceController::onPOSTCloudSyncData(const QString &vNetAddress) { + _netCloudSync = vNetAddress; + emit didPOSTCloudSyncData (vNetAddress); +} + +bool DeviceController::logBackup(const QString &vFileName) +{ + if ( ! gLogUpload ) return false; // no log backup + + bool ok = true; + QString fileSrc = vFileName; + QFileInfo fileInfo(vFileName); + QString filePath(fileInfo.absolutePath()); + QString fileBase(fileInfo.baseName()); + QString fileSufx(fileInfo.completeSuffix().prepend(_Logger.logFileNamePendingSubExt())); + QString fileDest(QString("%1/%2.%3").arg(filePath, fileBase, fileSufx)); + // DEBUG qDebug() << __FUNCTION__ << "\n" << vFileName << "\n" << fileDest; + if ( gLogCompress ) { + fileSrc += _Logger.logFileNameCompressExt(); + fileDest += _Logger.logFileNameCompressExt(); + ok = FileHandler::backupFile(vFileName); + } + ok = QFile::rename(fileSrc, fileDest); + return ok; +} + +void DeviceController::onLogBackup(const QString &vFileName) +{ + if ( ! gLogUpload ) return; // no log backup ( slot ) + + bool ok = true; + ok = logBackup( vFileName); + emit didLogBackup(ok, vFileName); +} + +bool DeviceController::logUpload(const QString &vFileName) +{ + if ( ! gLogUpload ) return false; // no log Uploaded rename + + bool ok = true; + QFileInfo fileInfo(vFileName); + QString filePath; + QString fileBase(fileInfo.baseName()); + QString ext = _Logger.logFileNamePendingSubExt(); + QString fileSufx(fileInfo.completeSuffix().remove(ext)); + QString fileDest = QString("%1.%2").arg(fileBase, fileSufx); + + Logger::LogType logType = _Logger.logFileLogType(vFileName, filePath); + ok = logType != Logger::eLogNone; + if ( ! ok ) { LOG_APPED_UI(QString("CS Incorrect log upload type [%1]").arg(fileSufx)); goto lOut; } + // DEBUG qDebug() << __FUNCTION__ << "\n" << vFileName << "\n" << fileDest; + + ok = QFile::rename(filePath + vFileName, filePath + fileDest); +lOut: + return ok; +} + +void DeviceController::onLogUpload(const QString &vFileName) +{ + if ( ! gLogUpload ) return; // no log uploaded rename ( slot ) + + bool ok = true; + ok = logUpload( vFileName); + emit didLogUpload(ok, vFileName); +} + +/*! + * \brief DeviceController::checkConfugurationMountReady + * \details Cheks if the system is ready to mount the encrypted partition. + * The object has to be on its own thread and the salt for the decryption has to be ready. + */ +void DeviceController::checkConfugurationMountReady() +{ + /// in manufacturing or updating the system is logged with root and configurations are in /home/root + /// therefore no need to mount the cononfiguraiton partition. + /// also for manufacturing the partition is being set up + /// and is less steps for setup if the partition is not mounted. + if ( gEnableManufacturing ) return; // it should do the mount when gEnableUpdating, therefore here should not add gEnableUpdating. + if ( ! ( _hasThread && _hasSalt ) ) return; + + DeviceCryptSetupRequestData data; + data.mCommand = "mount"; + bool ok = false; + data.mPassword = encryption::configurationsPassword( ok ); + if ( ! ok ) { // not enough infromation to create a secure passowrd + // status(tr("Not enough secure information provided")); + } + else { + onAttributeRequest(data); + } + + // I_AM_HERE + // HERE move the settings read from ApplicationController to here + // here is when the DeviceController is moved to its thread + // and now can start mounting the encrypted partition + // and then read the settings. + // TODO don't forget to check for the required configurations files and parameters in the settings class. + // and take care of the security flag in the Storage class. +} + +/*! + * \brief DeviceController::findPendingLogs + * \details this function counts downs for the _pendingInterval + * when the _pendingCounter reaches 0 will search for the files + * and if there is any will get the recent file in the list + */ +void DeviceController::findPendingLogs() +{ + if ( ! gLogUpload ) return; // no log upload pending detection + + static QString pendingLog = ""; + if( _pendingCounter ) { + _pendingCounter -- ; + return; + } + else { + _pendingCounter = _pendingInterval; // every minute + } + + QFileInfoList pendingFiles; + QString logLoc = Log_Folder_Base; + QString logExt = QString("*.%1*").arg(_Logger.logFileNamePendingSubExt()); // "*.u.*"; + for( auto logFolder : { Log_Folder_Application, Log_Folder_Service/*, Log_Folder_CloudSync*/ } ) { + pendingFiles = Storage::FileHandler::find( logLoc + logFolder, { logExt } ); + // look into the list. + // if there are pending files, + // send a request only for the top on the list + /// Note I thought it makes sense to send the oldest on the application and service logs + /// but there are some conversation about the situation if something happens on the device, + /// and it would be a critical situation to get the recent/top log and won't wait for the old ones to upload. + // * When gets uploaded, moves from pending then next one comes to top + // the process repeats until there is no file in pending + + bool uploadOldestFirst = true; //TODO: make if configurable(cfg, or cli) + + if ( pendingFiles.count() ) { + // the most recent/first log file, to first ask for the current log which has just been saved as pending + if ( uploadOldestFirst ) { + _pendingLog = pendingFiles.last().absoluteFilePath(); + } else { + _pendingLog = pendingFiles.first().absoluteFilePath(); + } + QString message = pendingLog; + LOG_DEBUG(message); + emit didPendingLog( _pendingLog, FileHandler::sha256sum( _pendingLog ) ); + // when a pending file found in the first log folder stop + // until there is none in first one (log) + // then continue to the next log folder (service) ... + goto lOut; + } + } +lOut: + return; +} + +///////////////////////////////////////////// DeviceFactoryReset +void DeviceController::onAttributeRequest(const DeviceFactoryResetRequestData &vData) +{ + _deviceFactoryResetRequest._data = vData; + + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, Factory_Reset), _deviceFactoryResetResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processFactoryReset.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceFactoryResetResponse); + return; + } + + + // ----- run the process + int timeout_ms = 10000; + TimedProcess *timedProcess = new TimedProcess(&_processFactoryReset, script, timeout_ms); + timedProcess->start(); + + MDeviceFactoryResetResponse model; + model._data.mAccepted = false; // will indirectly set the property factoryResetEnabled + model._data.mMessage = tr("Factory Reset started."); + emit didAttributeResponse(model.data()); +} + +/*! + * \brief DeviceController::onProcessFactoryResetExitCode + * \param vExitCode - the script exit code. + * \param vStatus - the script echoed message. + */ +void DeviceController::onProcessFactoryResetExitCode(int vExitCode, QProcess::ExitStatus vStatus) +{ + // The Exit code in this script is not used. + // any other checking is done by UI Software at the moment this script is called. + // The only thing matters is the paired device info in text and it will be empty string if error happens. + MDeviceFactoryResetResponse model; + QByteArray deviceInfo; + if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; + else deviceInfo = _processFactoryReset.readAll(); + model.fromByteArray( deviceInfo, &vExitCode ); + // DEBUG: qDebug() << model._data.mMessage << deviceInfo; + emit didAttributeResponse (model.data()); + emit didFactoryReset (model._data.mAccepted); + + LOG_APPED_UI(model.data().mMessage); +} + +///////////////////////////////////////////// DeviceDecommission +void DeviceController::onAttributeRequest(const DeviceDecommissionRequestData &vData) +{ + _deviceDecommissionRequest._data = vData; + + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, Device_Decommission), _deviceDecommissionResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processDecommission.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceDecommissionResponse); + return; + } + + + // ----- run the process + int timeout_ms = 10000; + TimedProcess *timedProcess = new TimedProcess(&_processDecommission, script, timeout_ms, { CloudSyncPath }); + _processDecommission.setEnvironment(QProcess::systemEnvironment() << QString("PASSWORD=%1").arg(_deviceDecommissionRequest._data.mPassword)); + timedProcess->start(); + + MDeviceDecommissionResponse model; + model._data.mAccepted = false; // will indirectly set the property decommissionEnabled + model._data.mMessage = tr("Decommissioning started."); + emit didAttributeResponse(model.data()); +} + +/*! + * \brief DeviceController::onProcessDecommissionExitCode + * \param vExitCode + * \param vStatus + */ +void DeviceController::onProcessDecommissionExitCode(int vExitCode, QProcess::ExitStatus vStatus) +{ + // The Exit code in this script is not used. + // any other checking is done by UI Software at the moment this script is called. + // The only thing matters is the paired device info in text and it will be empty string if error happens. + MDeviceDecommissionResponse model; + QByteArray deviceInfo; + if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; + else deviceInfo = _processDecommission.readAll(); + model.fromByteArray( deviceInfo, &vExitCode ); + // DEBUG: qDebug() << model._data.mMessage << deviceInfo; + emit didAttributeResponse (model.data()); + emit didDecommissioning (model._data.mAccepted); + + LOG_APPED_UI(model.data().mMessage); +} + +///////////////////////////////////////////// DeviceUSBMounting +void DeviceController::onAttributeRequest(const DeviceUSBMountRequestData &vData) +{ + Q_UNUSED(vData) + usbMountReq(vData.usbDevice, vData.isMountRequest); +} + +/*! + * \brief DeviceController::usbMountReq + * \details Calls the Usb unmount/mount script + * \param vIsMount - indicate if the request is for mounting or unmounting + * \param vDevice - the path to the USB device + */ +void DeviceController::usbMountReq(const QString &vDevice, bool vIsMount) +{ + qDebug() << __FUNCTION__ << vDevice << vIsMount; + _deviceUSBMountRequest._data.isMountRequest = vIsMount ; + _deviceUSBMountRequest._data.usbDevice = vDevice ; // not necessary, but to be consistent + + // ----- check that script exists. + QString script; + if ( checkError( DeviceError::checkScript(script, (vIsMount ? USB_Mount : USB_Unmount )), _deviceUSBMountResponse, script) ) + return; + + // ----- check if the process is not running + if ( _processUSBMount.state() != QProcess::NotRunning ) { + checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceUSBMountResponse); + return; + } + + // ----- run the process + int timeout_ms = 5000; + TimedProcess *timedProcess = new TimedProcess(&_processUSBMount, script, timeout_ms, {vDevice, USB_Mount_Point, USB_File_System}); + timedProcess->start(); + + MDeviceUSBMountResponse model; + model._data.mAccepted = false; + model._data.mMessage = vIsMount ? tr("USB unmount started.") : tr("USB mount started"); + emit didAttributeResponse(model.data()); +} + +/*! + * \brief DeviceController::onProcessUSBMountExitCode + * \param vExitCode + * \param vStatus + */ +void DeviceController::onProcessUSBMountExitCode(int vExitCode, QProcess::ExitStatus vStatus) +{ + MDeviceUSBMountResponse model; + QByteArray deviceInfo; + if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status; + else deviceInfo = _processUSBMount.readAll(); + model.fromByteArray( deviceInfo, &vExitCode ); + emit didAttributeResponse(model.data()); + + // Re-evaluate the USB space available - need to call this here to avoid + // visual lag caused by waiting to call this function on the timer timeout + usbSpaceCheck(); + + bool ok = ! vStatus; + QString usbDevice = _deviceUSBMountRequest._data.usbDevice; + if(_deviceUSBMountRequest._data.isMountRequest) { // *** USB Mount + if ( ok && ! _mounted ) { + _mounted = true; + _removed = false; + LOG_DEBUG(QString("USB flash drive %1 has been mounted on %2").arg(usbDevice).arg(USB_Mount_Point)); + emit didUSBDriveMount(); + } else { + usbError(usbDevice); + } + } else { // *** USB Unmount + if ( ok && _mounted ) { + _mounted = false; + // _umounted = true; // I think it might be needed, but needs more testing. + LOG_DEBUG(QString("USB drive %2 unmounted").arg(usbDevice)); + emit didUSBDriveUmount(); + } else { + // the error is irrelevant, commented out for now + // usbError(usbDrive); + } + } + + // log error and exit + return; +} Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_acknow.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_acknow.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_canbus.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_canbus.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_fileHandler.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_fileHandler.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_initializations.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_initializations.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_logging.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_logging.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_messaging.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_messaging.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_models.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_models.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_threads.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_threads.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_utilities.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_utilities.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_views.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 9363dbc93c2be5d664c0ca2a565d8206679d9bf3 refers to a dead (removed) revision in file `unittests/tst_views.h'. Fisheye: No comparison available. Pass `N' to diff?