/*! * * Copyright (c) 2019-2023 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file main.cpp * \author (last) Behrouz NematiPour * \date (last) 28-Feb-2023 * \author (original) Behrouz NematiPour * \date (original) 24-Sep-2019 * */ /*! * \mainpage UI Software Design Description * \details Detailed Description.\n * This document has been generated by Doxygen.\n * This document describes the detail description of the UI Application Software design.\n * UI Application starts by Application Initialization which happens in \ref main() "Application Initialization".\n * For information please see : * - \ref main() * - \subpage CommandLineSwitches * - \subpage DenaliMessageStructure * - \subpage MessageFlow * - \subpage GeneralModelsDescription * - \subpage MessageView */ // Qt #include #include #include #include #include #include #include // FW #include "Compatible.h" // Project #include "MainTimer.h" #include "CanInterface.h" #include "FrameInterface.h" #include "MessageAcknowModel.h" #include "MessageDispatcher.h" #include "ApplicationController.h" #include "GuiController.h" #include "Logger.h" #include "DeviceController.h" #include "WifiInterface.h" #include "BluetoothInterface.h" #include "CloudSyncController.h" #include "Threads.h" // kernel #include /*! * \brief signalhandler * \details When application terminates it quits gracefully. * \param sig - The Linux signal causes the termination. */ void signalhandler(int sig) { if (sig == SIGINT) { qDebug() << QObject::tr("Application terminated by SIGINT"); qApp->quit(); } else if (sig == SIGTERM) { qDebug() << QObject::tr("Application terminated by SIGTERM"); qApp->quit(); } } int gFakeInterval = 0 ; QByteArray gFakeData = "" ; const char *gFakeData_default = "00" ; bool gSendEmptyKeepAwake = false ; bool gFakeSeqAtBegin = false ; bool gDisableUnhandledReport = false ; bool gDisableDialinUnhandled = false ; bool gDisableTimeout = false ; bool gDisableAlarmNoMinimize = false ; bool gDisableSDCFailLogStop = false ; bool gDisableCloudSyncFailStop = false ; bool gEnableCheckInLog = false ; bool gEnableAcknowLog = false ; bool gConsoleoutLogs = false ; bool gConsoleoutFrameInterface = false ; bool gConsoleoutCanInterface = false ; bool gEnableDryDemo = false ; QString gActiveCANBus = "can0"; /*! * \page CommandLineSwitches Denali Command Line Switches * \verbatim * Usage: ./denali [options] * Denali * * Options: * -h, --help Displays this help. * -v, --version Displays version information. * -c, --canOut Show the Can Frame Output * -m, --msgOut Show the Message Output * -l, --logOut Show the Logs Output * -0, --enable-keep-awake Enable send low priority, empty message * on the CANBus just to keep UI board CAN * driver awake * -i, --fake-interval Test fake message interval(ms) * -f, --fake-message Test fake message data * will use default sequenced long fake * message if set to 00(default) * will used only if correct integer value * assigned for interval option * -b, --fake-message-seq-at-begin Test fake message sequence at the * beginning of the frame * -u, --disable-unhandled-report Disable unhandled messages report as an * error in the log * -d, --disable-dialin-unhandled Disable the Dialin messages logged as * unhandled * -q, --disable-timeout Disables HD communication timeout * -a, --disable-alarm-no-minimize Disables alarm no minimize * -S, --disable-sd-card-fail-log-stop disable-sd-card-fail-log-stop * -C, --disable-cloudsync-fail-stop disable-cloudsync-fail-stop * -k, --enable-check-in-log Enables Check-In Log * -K, --enable-acknow-log Enables Acknowledgment Log * \endverbatim */ /*! * \brief commandlineParse * \details parses the command line arguments * \ref CommandLineSwitches */ void commandlineParse() { QCommandLineParser parser; parser.setApplicationDescription(QApplication::applicationName()); parser.addHelpOption(); parser.addVersionOption(); // --- -c : canOut QCommandLineOption optionConsoleoutCanInterface( QStringList() << "c" << "canOut", QCoreApplication::translate("main", "Show the Can Frame Output")); parser.addOption(optionConsoleoutCanInterface); // --- -m : msgOut QCommandLineOption optionConsoleoutFrameInterface( QStringList() << "m" << "msgOut", QCoreApplication::translate("main", "Show the Message Output")); parser.addOption(optionConsoleoutFrameInterface); // --- -l : logOut QCommandLineOption optionConsoleoutLogs( QStringList() << "l" << "logOut", QCoreApplication::translate("main", "Show the Logs Output")); parser.addOption(optionConsoleoutLogs); // --- -0 : enable-keep-awake (the fast mode) QCommandLineOption optionSendEmptyKeepAwake(QStringList() << "0" << "enable-keep-awake", QCoreApplication::translate("main", "Enable send low priority, empty message on the CANBus just to keep UI board CAN driver awake")); parser.addOption(optionSendEmptyKeepAwake); // --- -i : fake-interval QCommandLineOption optionFakeInterval( QStringList() << "i" << "fake-interval", QCoreApplication::translate("main", "Test fake message interval(ms)"), QCoreApplication::translate("main", "interval")); parser.addOption(optionFakeInterval); // --- -f : fake-message QCommandLineOption optionFakeData( QStringList() << "f" << "fake-message", QCoreApplication::translate("main", "Test fake message data\n" "will use default sequenced long fake message if set to 00(default)\n" "will used only if correct integer value assigned for interval option"), QCoreApplication::translate("main", "data")); parser.addOption(optionFakeData); // --- -b : fake-message-seq-at-begin QCommandLineOption optionFakeSeqAtBegin( QStringList() << "b" << "fake-message-seq-at-begin", QCoreApplication::translate("main", "Test fake message sequence at the beginning of the frame")); parser.addOption(optionFakeSeqAtBegin); // --- -u : disable-unhandled-report QCommandLineOption optionDisableUnhandledReport( QStringList() << "u" << "disable-unhandled-report", QCoreApplication::translate("main", "Disable unhandled messages report as an error in the log")); parser.addOption(optionDisableUnhandledReport); // --- -d : enable-dialin-unhandled QCommandLineOption optionDisableDialinUnhandled( QStringList() << "d" << "disable-dialin-unhandled", QCoreApplication::translate("main", "Disable the Dialin messages logged as unhandled")); parser.addOption(optionDisableDialinUnhandled); // --- -q : disable-timeout QCommandLineOption optionDisableTimeout( QStringList() << "q" << "disable-timeout", QCoreApplication::translate("main", "Disables HD communication timeout")); parser.addOption(optionDisableTimeout); // --- -a : disable-alarm-no-minimize QCommandLineOption optionDisableAlarmMoMinimize(QStringList() << "a" << "disable-alarm-no-minimize", QCoreApplication::translate("main", "Disables alarm no minimize")); parser.addOption(optionDisableAlarmMoMinimize); // --- -S : disable-sd-card-fail-log-stop QCommandLineOption optionDisableSDCardFailLogStop(QStringList() << "S" << "disable-sd-card-fail-log-stop", QCoreApplication::translate("main", "disable-sd-card-fail-log-stop")); parser.addOption(optionDisableSDCardFailLogStop); // --- -C : disable-cloudsync-fail-stop QCommandLineOption optionDisableCloudSyncFailStop(QStringList() << "C" << "disable-cloudsync-fail-stop", QCoreApplication::translate("main", "disable-cloudsync-fail-stop")); parser.addOption(optionDisableCloudSyncFailStop); // --- -k : enable-Check-in-log (keep-alive) QCommandLineOption optionEnableCheckInLog(QStringList() << "k" << "enable-check-in-log", QCoreApplication::translate("main", "Enables Check-In Log")); parser.addOption(optionEnableCheckInLog); // --- -K : enable-acknow-log (Acknowledge) QCommandLineOption optionEnableAcknowLog(QStringList() << "K" << "enable-acknow-log", QCoreApplication::translate("main", "Enables Acknowledgment Log")); parser.addOption(optionEnableAcknowLog); // --- -D : enable-dry-demo QCommandLineOption optionEnableDryDemo(QStringList() << "D" << "enable-dry-demo", QCoreApplication::translate("main", "Enables Dry-Demo Mode")); parser.addOption(optionEnableDryDemo); // --- -A : active-can-bus QCommandLineOption optionActiveCANBus(QStringList() << "A" << "active-can-bus", QCoreApplication::translate("main", "Sets the Active CANBus [Shall start with 'can' or 'vcan]"), QCoreApplication::translate("main", "CANBus")); parser.addOption(optionActiveCANBus); // --- parse command lines parser.process(*qApp); gConsoleoutCanInterface = parser.isSet(optionConsoleoutCanInterface ); gConsoleoutFrameInterface = parser.isSet(optionConsoleoutFrameInterface ); gConsoleoutLogs = parser.isSet(optionConsoleoutLogs ); gDisableUnhandledReport = parser.isSet(optionDisableUnhandledReport ); gDisableDialinUnhandled = parser.isSet(optionDisableDialinUnhandled ); gDisableTimeout = parser.isSet(optionDisableTimeout ); gDisableAlarmNoMinimize = parser.isSet(optionDisableAlarmMoMinimize ); gDisableSDCFailLogStop = parser.isSet(optionDisableSDCardFailLogStop ); gDisableCloudSyncFailStop = parser.isSet(optionDisableCloudSyncFailStop ); gEnableCheckInLog = parser.isSet(optionEnableCheckInLog ); gEnableAcknowLog = parser.isSet(optionEnableAcknowLog ); gEnableDryDemo = parser.isSet(optionEnableDryDemo ); if ( parser.isSet(optionActiveCANBus ) ) { QString value = parser.value(optionActiveCANBus); if ( ! value.startsWith("-") && // if a value is not given for the switch then the next switch becomes the value of the previous one ( value.startsWith("can") || value.startsWith("vcan") ) ) { // to be more precise gActiveCANBus = value; } } if (parser.isSet(optionSendEmptyKeepAwake)) gSendEmptyKeepAwake = true; bool ok = false; if (parser.isSet(optionFakeInterval)) { int interval = parser.value(optionFakeInterval).toInt(&ok); if (ok) { gFakeInterval = interval; if (parser.isSet(optionFakeData)) { gFakeData = parser.value(optionFakeData).toLatin1(); } else { gFakeData = gFakeData_default; } if (parser.isSet(optionFakeSeqAtBegin)) { gFakeSeqAtBegin = true; } gFakeData = QByteArray::fromHex(gFakeData); } } } /*! * \brief setApplicationVersion * \details sets up the application version regarding the environment variables * which are set by bamboo and if those are not set value of 0 will be used * and revision(build) version will be set to current date/time. */ void setApplicationVersion() { bool isOnServer = true; QString ver_major = QString("%1").arg(VER_MAJOR ); QString ver_minor = QString("%1").arg(VER_MINOR ); QString ver_micro = QString("%1").arg(VER_MICRO ); QString ver_revis = QString("%1").arg(VER_REVIS ); QString ver_branch = QString("%1").arg(VER_BRANCH ); QString ver_comp = QString("%1").arg(SW_COMPATIBILITY_REV ); if (ver_revis.isEmpty()) { ver_revis = VER_REVIS_DEV; isOnServer = false; } bool isOnMaster = ver_branch == "master"; bool isNotStory = isOnMaster || ver_branch == "staging" || ver_branch == "develop"; if (isNotStory) { if (isOnServer) { if (isOnMaster ) { ver_branch = ""; // if only is built on server master branch do not show branch } ver_major += '.'; ver_minor += '.'; ver_micro += '.'; } } if ( ! ver_branch.isEmpty()) ver_branch += '.'; ver_comp = "." + ver_comp; QString version = ""; version += ver_branch ; version += ver_major ; version += ver_minor ; version += ver_micro ; version += ver_revis ; // build number version += ver_comp ; QCoreApplication::setApplicationVersion(version); } #ifdef UNIT_TEST #include TEST_CLASS_INCLUDE QTEST_MAIN(TEST_CLASS_NAME) #else /*! * \brief Application Initialization * \details Some part of the application need to be initialized out of any thread. * So is initialized here to be initialized in the main thread. * this section also includes: */ int main(int argc, char *argv[]) { #ifndef SQUISH_COCO_BULD signal(SIGINT , signalhandler); signal(SIGTERM, signalhandler); #endif // setting the environment for the keyboard. qputenv("QT_IM_MODULE" , QByteArray("qtvirtualkeyboard" )); qputenv("QT_VIRTUALKEYBOARD_STYLE" , QByteArray("denali" )); qputenv("QT_VIRTUALKEYBOARD_LAYOUT_PATH", QByteArray(":/plugins/QtQuick/VirtualKeyboard/Layouts" )); //! - Qt Application initialization and parameters settings // Qt Core Application parameters settings QApplication::setApplicationName(QLatin1String("Denali")); QApplication::setOrganizationName(QLatin1String("Diality Inc.")); //! - Check the required font(s) present and can be loaded QApplication::setFont(QFont("Barlow")); // Qt Core Application Initialization QApplication app(argc, argv); app.thread()->setObjectName("Main Thread"); //! - Setting the application version regarding the Bamboo build number. setApplicationVersion(); //! - Parse the command line arguments commandlineParse(); // SYSTEM TEST FOR INSTRUCTIONS WHEN THERE IS NO PORT AVAILABLE // Storage::FileHandler::copyFolder(QString(Storage::USB_Mount_Point) + "Instructions", QString(Storage::Settings_Path_Name)); //! - Translation initialization QTranslator translator; bool trLoaded = translator.load(QLocale(), app.applicationName(), QLatin1String("_"), QLatin1String(":/translations")); if (trLoaded) { app.installTranslator(&translator); } //! - Initializing required thread types Threads::registerTypes(); bool guiStarted = startGui(); //! - Initializing Logger if(_Logger.init(Threads::_Logger_Thread)) { _Logger.enableConsoleOut(gConsoleoutLogs); } _Logger.postInit(); if (gFakeInterval) { QString msg = " ~~ !!!!! APPLICATION RUNNING IN THE TEST MODE !!!!! ~~ "; qDebug() << msg; LOG_APPED(" \n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " " \n " + msg + " \n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "); } //! - Initializing the Device Controller _DeviceController.init(Threads::_DeviceController_Thread); //! - Initializing the CANBus Interface if (_CanInterface.init(Threads::_CanFrame_Thread)) { _CanInterface.enableConsoleOut(gConsoleoutCanInterface); } //! - Initializing the CANBus Message Handler _FrameInterface.init(Threads::_CanFrame_Thread); //! - Initializing the CANBus Message Acknowledgment Model _MessageAcknowModel.init(Threads::_CanAcknow_Thread); //! - Initializing the CANBus Message Dispatcher if (_MessageDispatcher.init(Threads::_CanMessage_Thread)) { _MessageDispatcher.enableConsoleOut(gConsoleoutFrameInterface); } //! - Initializing Application Controller _ApplicationController.init(Threads::_Application_Thread); _ApplicationController.initSettings(); ////! - Initializing GUI Controller _GuiController.init(Threads::_Gui_Thread); //! - Initializing Main Timer _MainTimer.init(); //! - Initializing WiFi Interface _WifiInterface.init(Threads::_Wifi_Thread); //! - Initializing Bluetooth Interface _BluetoothInterface.init(Threads::_Bluetooth_Thread); //! - Initializing the CloudSync controller _CloudSyncController.init(Threads::_CloudSync_Thread); //! - Initialize the QML Viewer and starts GUI int app_exec = -1; LOG_DEBUG("UI Initializing"); if ( guiStarted /*startGui()*/ ) { LOG_DEBUG("UI Initialized"); _ApplicationController .startPOST(); app_exec = app.exec(); } // Due to Qt Error the CAN Device cannot be disable/enable from withing another thread // (other than main thread which is the owner of the CanDevice). // So it needs to be done here in main thread. _CanInterface.quitDevice(); Threads::quitThreads(); Gui::_viewer->deleteLater(); return app_exec; } #endif