Compare commits
	
		
			10 Commits
		
	
	
		
			57b82094c8
			...
			f52dec9124
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f52dec9124 | |||
| 07942153c3 | |||
| bac848f6be | |||
| ccc1bf2a99 | |||
| c8487a7541 | |||
| dc90705f24 | |||
| c4c503080e | |||
| e2d9c5aa90 | |||
| 60f845aa8d | |||
| fa0c31d9e4 | 
@@ -3,9 +3,11 @@ QT += core
 | 
			
		||||
QT += widgets serialport
 | 
			
		||||
QT += network
 | 
			
		||||
 | 
			
		||||
TARGET = up_dev_ctrl
 | 
			
		||||
TARGET = ATBUpdateDC
 | 
			
		||||
 | 
			
		||||
CONFIG += c++11
 | 
			
		||||
INCLUDEPATH += plugins
 | 
			
		||||
 | 
			
		||||
CONFIG += c++17
 | 
			
		||||
# CONFIG -= app_bundle
 | 
			
		||||
 | 
			
		||||
# DEFINES+=LinuxDesktop
 | 
			
		||||
@@ -18,11 +20,11 @@ QMAKE_CXXFLAGS += -Wno-deprecated-copy
 | 
			
		||||
# subtree.depends =
 | 
			
		||||
# QMAKE_EXTRA_UNIX_TARGETS += subtree
 | 
			
		||||
 | 
			
		||||
! exists(DCPlugin) {
 | 
			
		||||
    $$system("git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash")
 | 
			
		||||
} else {
 | 
			
		||||
# ! exists(DCPlugin) {
 | 
			
		||||
#     $$system("git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash")
 | 
			
		||||
# } else {
 | 
			
		||||
    # $$system("git subtree pull --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash")
 | 
			
		||||
}
 | 
			
		||||
# }
 | 
			
		||||
 | 
			
		||||
# You can make your code fail to compile if it uses deprecated APIs.
 | 
			
		||||
# In order to do so, uncomment the following line.
 | 
			
		||||
@@ -52,20 +54,27 @@ contains( CONFIG, DesktopLinux ) {
 | 
			
		||||
SOURCES += \
 | 
			
		||||
        main.cpp \
 | 
			
		||||
        update.cpp \
 | 
			
		||||
        message_handler.cpp
 | 
			
		||||
        message_handler.cpp \
 | 
			
		||||
        worker.cpp \
 | 
			
		||||
        worker_thread.cpp
 | 
			
		||||
 | 
			
		||||
HEADERS += \
 | 
			
		||||
        update.h \
 | 
			
		||||
        message_handler.h \
 | 
			
		||||
        DCPlugin/include/interfaces.h
 | 
			
		||||
        worker.h \
 | 
			
		||||
        worker_thread.h \
 | 
			
		||||
        plugins/interfaces.h
 | 
			
		||||
 | 
			
		||||
OTHER_FILES += \
 | 
			
		||||
    /opt/app/tools/atbupdate/update_log.csv
 | 
			
		||||
    /opt/app/tools/atbupdate/update_log.csv \
 | 
			
		||||
    main.cpp.bck \
 | 
			
		||||
    main.cpp.bck2 \
 | 
			
		||||
    main.cpp.bck3
 | 
			
		||||
 | 
			
		||||
# https://blog.developer.atlassian.com/the-power-of-git-subtree/?_ga=2-71978451-1385799339-1568044055-1068396449-1567112770
 | 
			
		||||
# git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
 | 
			
		||||
# git subtree pull --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
 | 
			
		||||
include(./DCPlugin/DCPlugin.pri)
 | 
			
		||||
# include(./DCPlugin/DCPlugin.pri)
 | 
			
		||||
 | 
			
		||||
# Default rules for deployment.
 | 
			
		||||
qnx: target.path = /tmp/$${TARGET}/bin
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -2,6 +2,7 @@
 | 
			
		||||
\usepackage{euler}
 | 
			
		||||
\usepackage[english]{babel}
 | 
			
		||||
\usepackage{lipsum}
 | 
			
		||||
\usepackage{multirow}
 | 
			
		||||
\usepackage[colorlinks=true, urlcolor=blue, linkcolor=red]{hyperref}
 | 
			
		||||
\newcounter{Chapcounter}
 | 
			
		||||
\newcommand\showmycounter{\addtocounter{Chapcounter}{1}\themycounter}
 | 
			
		||||
@@ -19,13 +20,15 @@
 | 
			
		||||
 | 
			
		||||
\begin{document}
 | 
			
		||||
\maketitle
 | 
			
		||||
\chapter{Introduction}
 | 
			
		||||
% \chapter{Introduction}
 | 
			
		||||
\section{Motivation}
 | 
			
		||||
 | 
			
		||||
The two main components of a PSA are
 | 
			
		||||
\begin{itemize}
 | 
			
		||||
    \item PTU software.
 | 
			
		||||
    \item Device controller (DC) firmware.
 | 
			
		||||
\end{itemize}
 | 
			
		||||
 | 
			
		||||
While the DC firmware is basically the same for each PSA (even for different
 | 
			
		||||
customers), the PTU software is highly dependent on customer requirements.\par
 | 
			
		||||
Hence, each customer is assigned an own git-repository, which will be loaded
 | 
			
		||||
@@ -36,6 +39,7 @@
 | 
			
		||||
script [{\bf \nameref{UpdateScript}}]), work together to finish a PSA installation.\par 
 | 
			
		||||
    
 | 
			
		||||
\section{PSA: Initial configuration}
 | 
			
		||||
 | 
			
		||||
For the initial configuration, a PSA loads a customer-specific git-repository,
 | 
			
		||||
which structure is detailed below [{\bf \nameref{repostructure}}].\par
 | 
			
		||||
The "git clone" for the repository is done by the UpdateScript [{\bf \nameref{UpdateScript}}].
 | 
			
		||||
@@ -46,17 +50,28 @@
 | 
			
		||||
    }
 | 
			
		||||
\end{center}
 | 
			
		||||
which will be interpreted by the UpdateController [{\bf \nameref{UpdateTool}}].
 | 
			
		||||
        The structure of {\bf update\_log.csv} is detailed below [{\bf \nameref{updatelogcsv}}].\par
 | 
			
		||||
        Each line of {\bf update\_log.csv} represents a command for the UpdateController,
 | 
			
		||||
The structure of [{\bf \nameref{updatelogcsv}}] is detailed below.\par
 | 
			
		||||
Each line of update\_log.csv represents a command for the UpdateController,
 | 
			
		||||
which will either download certain files to the DC or execute some
 | 
			
		||||
\href{https://openwrt.org/docs/guide-user/additional-software/opkg}{opkg}
 | 
			
		||||
commands [{\bf \nameref{opkg}}].
 | 
			
		||||
        
 | 
			
		||||
\section{PSA: Update}
 | 
			
		||||
   
 | 
			
		||||
    \newpage
 | 
			
		||||
The update of a PSA is basically managed by \href{https://git-scm.com/}{git}, a
 | 
			
		||||
free and open source distributed version control system. Like many other Version
 | 
			
		||||
Control Systems, git has a way to fire off custom scripts when certain important
 | 
			
		||||
actions occur, so-called \href{https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks}{hooks}.
 | 
			
		||||
The hooks used for a PSA update are called {\bf post-checkout} and {\bf post-merge}.\par
 | 
			
		||||
The post-checkout hook is called when checking out some branch of the customer-repository
 | 
			
		||||
(for instance when cloning the customer repository for the first time). In contrast,
 | 
			
		||||
the post-merge hook is called when a \href{https://www.git-scm.com/docs/git-pull}{git pull}
 | 
			
		||||
operation has been issued (more precisely, a \href {https://www.git-scm.com/docs/git-fetch}{git-fetch}
 | 
			
		||||
followed by a \href{https://www.git-scm.com/docs/git-merge}{git-merge}).\par
 | 
			
		||||
Both hooks update the file [{\bf \nameref{updatelogcsv}}], which is interpreted
 | 
			
		||||
by the UpdateController in a second step.
 | 
			
		||||
    
 | 
			
		||||
\chapter{Update-Tool "up\_dev\_ctrl"}
 | 
			
		||||
% \chapter{Update-Tool "up\_dev\_ctrl"}
 | 
			
		||||
    \section{up\_dev\_ctrl}
 | 
			
		||||
    \label{UpdateTool}
 | 
			
		||||
 | 
			
		||||
@@ -79,7 +94,7 @@
 | 
			
		||||
 | 
			
		||||
    \newpage
 | 
			
		||||
 | 
			
		||||
\chapter{Update-Script "update\_psa"}
 | 
			
		||||
% \chapter{Update-Script "update\_psa"}
 | 
			
		||||
    \section{update\_psa}
 | 
			
		||||
    \label{UpdateScript}
 | 
			
		||||
 | 
			
		||||
@@ -98,13 +113,60 @@
 | 
			
		||||
        \end{itemize}
 | 
			
		||||
    \newpage
 | 
			
		||||
 | 
			
		||||
\chapter{Annex}
 | 
			
		||||
%\chapter{Annex}
 | 
			
		||||
    \section{Structure of a customer git-repository}
 | 
			
		||||
    \label{repostructure}
 | 
			
		||||
    \subsection{The post-checkout hook}
 | 
			
		||||
TODO: checkout\_history
 | 
			
		||||
    \subsection{The post-merge hook}
 | 
			
		||||
They are both located under the {\bf .githooks}-directory
 | 
			
		||||
    
 | 
			
		||||
    \section{Structure of "update\_log.csv"}
 | 
			
		||||
\section{update\_log.csv}
 | 
			
		||||
\label{updatelogcsv}
 | 
			
		||||
    \begin{table}[h!]
 | 
			
		||||
        \begin{center}
 | 
			
		||||
        \caption{Initial state of update\_log.csv}
 | 
			
		||||
        \label{tab:initial_state}
 | 
			
		||||
        \begin{tabular}{llll}
 | 
			
		||||
            \textbf{Request} & \textbf{Name} & \textbf{Date} & \textbf{Status}\\
 | 
			
		||||
            \hline
 | 
			
		||||
            \multicolumn{4}{c}{}\\
 | 
			
		||||
            DOWNLOAD & /etc/dc/dc2c4.21.bin                & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print01.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print02.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print03.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print04.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print29.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DOWNLOAD & /etc/psa\_config/DC2C\_print32.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            EXECUTE  & opkg update                         & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
        \end{tabular}
 | 
			
		||||
        \end{center}
 | 
			
		||||
    \end{table}    
 | 
			
		||||
 | 
			
		||||
    \begin{table}[h!]
 | 
			
		||||
        \begin{center}
 | 
			
		||||
        \caption{State of update\_log.csv after updating}
 | 
			
		||||
        \label{tab:initial_state}
 | 
			
		||||
        \begin{tabular}{llll}
 | 
			
		||||
            \textbf{Request} & \textbf{Name} & \textbf{Date} & \textbf{Status}\\
 | 
			
		||||
            \hline
 | 
			
		||||
            \multicolumn{4}{c}{}\\
 | 
			
		||||
            DONE & /etc/dc/dc2c4.21.bin                & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print01.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print02.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print03.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print04.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print29.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & /etc/psa\_config/DC2C\_print32.json & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
            DONE & opkg update                         & 2023-05-01T12:00:00 & N/A\\
 | 
			
		||||
        \end{tabular}
 | 
			
		||||
        \end{center}
 | 
			
		||||
    \end{table}    
 | 
			
		||||
 | 
			
		||||
    \newpage
 | 
			
		||||
    
 | 
			
		||||
    \section{The package manager "opkg"}
 | 
			
		||||
    \label{opkg}
 | 
			
		||||
 | 
			
		||||
    \section{Known problems}
 | 
			
		||||
\end{document}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								main.cpp
									
									
									
									
									
								
							@@ -5,8 +5,7 @@
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "interfaces.h"
 | 
			
		||||
#include "DCPlugin/include/hwapi.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
@@ -17,6 +16,10 @@
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "worker_thread.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
 | 
			
		||||
#include <thread>
 | 
			
		||||
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
#define SERIAL_PORT "ttymxc2"
 | 
			
		||||
@@ -24,20 +27,13 @@
 | 
			
		||||
#define SERIAL_PORT "ttyUSB0"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class Work : public QRunnable {
 | 
			
		||||
    QString m_update_ctrl_file;
 | 
			
		||||
    QString m_workingDir;
 | 
			
		||||
public:
 | 
			
		||||
    explicit Work(QString update_ctrl_file, QString workingDir)
 | 
			
		||||
      : m_update_ctrl_file(update_ctrl_file)
 | 
			
		||||
        , m_workingDir(workingDir) {
 | 
			
		||||
static void doWork(QString update_ctrl_file, QString workingDir) {
 | 
			
		||||
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
 | 
			
		||||
    //Update update(update_ctrl_file, workingDir);
 | 
			
		||||
    //update.doUpdate();
 | 
			
		||||
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
 | 
			
		||||
    QCoreApplication::quit();
 | 
			
		||||
}
 | 
			
		||||
    void run() {
 | 
			
		||||
        Update m_update(m_update_ctrl_file, m_workingDir);
 | 
			
		||||
        // if (m_update.doUpdate()) {
 | 
			
		||||
        // }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// argv[1]: file to send to dc
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
@@ -54,15 +50,29 @@ int main(int argc, char *argv[]) {
 | 
			
		||||
        qputenv("XDG_RUNTIME_DIR", "/run/user/0");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString rtPath = QCoreApplication::applicationDirPath();
 | 
			
		||||
    QString plugInDir(rtPath +(rtPath.endsWith("/") ? "" : "/") + "plugins");
 | 
			
		||||
    if (!QDir(plugInDir).exists()) {
 | 
			
		||||
        qCritical() << plugInDir
 | 
			
		||||
                    << "does not exists, but has to contain dc-library";
 | 
			
		||||
        exit(-1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qInfo() << "pwd" << "=" << rtPath;
 | 
			
		||||
    qInfo() << "plugInDir" << "=" << plugInDir;
 | 
			
		||||
 | 
			
		||||
    hwinf *hw = Update::loadDCPlugin(QDir(plugInDir), "libCAmaster.so");
 | 
			
		||||
 | 
			
		||||
    QString const update_ctrl_file = "/opt/app/tools/atbupdate/update_log.csv";
 | 
			
		||||
    QString const workingDir = (argc == 2) ? argv[1] : ".";
 | 
			
		||||
    Update update(hw, update_ctrl_file, workingDir);
 | 
			
		||||
 | 
			
		||||
    Work work(update_ctrl_file, workingDir);
 | 
			
		||||
    work.setAutoDelete(false);
 | 
			
		||||
    QThreadPool *threadPool = QThreadPool::globalInstance();
 | 
			
		||||
    threadPool->start(&work);
 | 
			
		||||
    if (!threadPool->waitForDone()) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
    std::thread t(doWork, update_ctrl_file, workingDir);
 | 
			
		||||
 | 
			
		||||
    int ret = a.exec();
 | 
			
		||||
    t.join();
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										81
									
								
								main.cpp.bck
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								main.cpp.bck
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
#include "DCPlugin/include/hwapi.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
static void updateBinary(std::unique_ptr<hwinf> hw,     // update d2dc*.bin
 | 
			
		||||
                         char const *fileToSendToDC,
 | 
			
		||||
                         char const *baudrate,
 | 
			
		||||
                         char const *serialInterface) {
 | 
			
		||||
    for (int i=0; i < 1;++i) {
 | 
			
		||||
        hw->dc_updateDC(fileToSendToDC, baudrate, serialInterface);
 | 
			
		||||
        std::this_thread::sleep_for(std::chrono::milliseconds(3000));
 | 
			
		||||
    }
 | 
			
		||||
    QCoreApplication::quit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void updatePrinterConf(std::unique_ptr<hwinf> hw, // update printer-file
 | 
			
		||||
                              char const *fileToSendToDC,
 | 
			
		||||
                              char const *baudrate,
 | 
			
		||||
                              char const *serialInterface) {
 | 
			
		||||
    for (int i=0; i < 1;++i) {
 | 
			
		||||
        hw->dc_updateDC(fileToSendToDC, baudrate, serialInterface);
 | 
			
		||||
        std::this_thread::sleep_for(std::chrono::milliseconds(3000));
 | 
			
		||||
    }
 | 
			
		||||
    QCoreApplication::quit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
    QApplication a(argc, argv);
 | 
			
		||||
 | 
			
		||||
    if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
 | 
			
		||||
        atbInstallMessageHandler(atbDebugOutput);
 | 
			
		||||
        setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
        //setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (argc > 2) {
 | 
			
		||||
        qCritical() << "Usage: " << argv[0] << "<file to send to dc>";
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<hwinf> hw(new hwapi());
 | 
			
		||||
    QFileInfo fileInfo(argv[1]);
 | 
			
		||||
    QString fname(fileInfo.fileName());
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
 | 
			
		||||
    if (fname.startsWith("dc") && fname.endsWith(".bin")) {
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
        std::thread t(updateBinary, std::move(hw),
 | 
			
		||||
                      fname.toStdString().c_str(), "115200", "ttymxc2");
 | 
			
		||||
#else
 | 
			
		||||
        std::thread t(updateBinary, std::move(hw),
 | 
			
		||||
                      fname.toStdString().c_str(), "115200", "ttyUSB0");
 | 
			
		||||
#endif
 | 
			
		||||
        ret = a.exec();
 | 
			
		||||
        t.join();
 | 
			
		||||
    } else
 | 
			
		||||
    if (fname.startsWith("DC") && fname.endsWith(".json")) {
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
        std::thread t(updatePrinterConf, std::move(hw),
 | 
			
		||||
                      fname.toStdString().c_str(), "115200", "ttymxc2");
 | 
			
		||||
#else
 | 
			
		||||
        std::thread t(updatePrinterConf, std::move(hw),
 | 
			
		||||
                      fname.toStdString().c_str(), "115200", "ttyUSB0");
 | 
			
		||||
#endif
 | 
			
		||||
        ret = a.exec();
 | 
			
		||||
        t.join();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								main.cpp.bck2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								main.cpp.bck2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "interfaces.h"
 | 
			
		||||
#include "DCPlugin/include/hwapi.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <QSharedMemory>
 | 
			
		||||
#include <QRunnable>
 | 
			
		||||
#include <QThreadPool>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "worker_thread.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
#define SERIAL_PORT "ttymxc2"
 | 
			
		||||
#else
 | 
			
		||||
#define SERIAL_PORT "ttyUSB0"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// argv[1]: file to send to dc
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
    QApplication a(argc, argv);
 | 
			
		||||
 | 
			
		||||
    if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
 | 
			
		||||
        atbInstallMessageHandler(atbDebugOutput);
 | 
			
		||||
        setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
        //setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QByteArray const value = qgetenv("XDG_RUNTIME_DIR");
 | 
			
		||||
    if (value.size() == 0) {
 | 
			
		||||
        qputenv("XDG_RUNTIME_DIR", "/run/user/0");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QString const update_ctrl_file = "/opt/app/tools/atbupdate/update_log.csv";
 | 
			
		||||
    QString const workingDir = (argc == 2) ? argv[1] : ".";
 | 
			
		||||
 | 
			
		||||
    Worker worker(update_ctrl_file, workingDir);
 | 
			
		||||
 | 
			
		||||
    qCritical() << "starting main event loop";
 | 
			
		||||
    int ret = a.exec();
 | 
			
		||||
    qCritical() << "stopping main event loop" << ret;
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								main.cpp.bck3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								main.cpp.bck3
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <QSharedMemory>
 | 
			
		||||
#include <QRunnable>
 | 
			
		||||
#include <QThreadPool>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
 | 
			
		||||
#include "update.h"
 | 
			
		||||
#include "worker_thread.h"
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
 | 
			
		||||
#include <thread>
 | 
			
		||||
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
#define SERIAL_PORT "ttymxc2"
 | 
			
		||||
#else
 | 
			
		||||
#define SERIAL_PORT "ttyUSB0"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void doWork(QString update_ctrl_file, QString workingDir) {
 | 
			
		||||
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
 | 
			
		||||
    Update update(update_ctrl_file, workingDir);
 | 
			
		||||
    update.doUpdate();
 | 
			
		||||
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
 | 
			
		||||
    QCoreApplication::quit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// argv[1]: file to send to dc
 | 
			
		||||
int main(int argc, char *argv[]) {
 | 
			
		||||
    QApplication a(argc, argv);
 | 
			
		||||
 | 
			
		||||
    if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
 | 
			
		||||
        atbInstallMessageHandler(atbDebugOutput);
 | 
			
		||||
        setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
        //setDebugLevel(QtMsgType::QtDebugMsg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QByteArray const value = qgetenv("XDG_RUNTIME_DIR");
 | 
			
		||||
    if (value.size() == 0) {
 | 
			
		||||
        qputenv("XDG_RUNTIME_DIR", "/run/user/0");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // QString const update_ctrl_file = "/opt/app/tools/atbupdate/update_log.csv";
 | 
			
		||||
    // QString const workingDir = (argc == 2) ? argv[1] : ".";
 | 
			
		||||
 | 
			
		||||
    // std::thread t(doWork, update_ctrl_file, workingDir);
 | 
			
		||||
 | 
			
		||||
    int ret = a.exec();
 | 
			
		||||
    // t.join();
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
@@ -3,8 +3,7 @@
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
#define OUTPUT_LEN (20)
 | 
			
		||||
 | 
			
		||||
#define OUTPUT_LEN (512)
 | 
			
		||||
 | 
			
		||||
static bool installedMsgHandler = false;
 | 
			
		||||
static QtMsgType debugLevel = QtInfoMsg;
 | 
			
		||||
@@ -41,49 +40,10 @@ QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler) {
 | 
			
		||||
///     return app.exec();
 | 
			
		||||
///  }
 | 
			
		||||
///
 | 
			
		||||
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
 | 
			
		||||
void atbDebugOutput(QtMsgType type, const char *msg) {
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case QtDebugMsg: {
 | 
			
		||||
            if (debugLevel <= QtDebugMsg) {
 | 
			
		||||
                fprintf(stderr, "%*.*s Debug: %s\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                    QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case QtInfoMsg: {
 | 
			
		||||
            if (debugLevel <= QtInfoMsg) {
 | 
			
		||||
                fprintf(stderr, "%*.*s Info: %s\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                    QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case QtWarningMsg: {
 | 
			
		||||
            if (debugLevel <= QtWarningMsg) {
 | 
			
		||||
                fprintf(stderr, "%*.*s Warning: %s\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                    QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case QtCriticalMsg: {
 | 
			
		||||
            if (debugLevel <= QtCriticalMsg) {
 | 
			
		||||
                fprintf(stderr, "%*.*s Critical: %s\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                    QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case QtFatalMsg: {
 | 
			
		||||
            if (debugLevel <= QtFatalMsg) {
 | 
			
		||||
                fprintf(stderr, "%*.*s Fatal: %s\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                    QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
 | 
			
		||||
            }
 | 
			
		||||
            // abort();
 | 
			
		||||
        } break;
 | 
			
		||||
        default: {
 | 
			
		||||
            fprintf(stderr, "%*.*s No ErrorLevel defined! %s\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                QDateTime::currentDateTime().toString(Qt::ISODate).toStdString().c_str(), msg);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
 | 
			
		||||
#if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
 | 
			
		||||
void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
 | 
			
		||||
    static constexpr const char *format = "dd.MM.yyyy hh:mm:ss";
 | 
			
		||||
    static constexpr const char *format = "hh:mm:ss";
 | 
			
		||||
    // static constexpr const char *format = "dd.MM.yyyy hh:mm:ss";
 | 
			
		||||
    QByteArray localMsg = msg.toLocal8Bit();
 | 
			
		||||
    const char *file = context.file ? context.file : "";
 | 
			
		||||
    const char *function = context.function ? context.function : "";
 | 
			
		||||
@@ -97,54 +57,65 @@ void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QSt
 | 
			
		||||
    }
 | 
			
		||||
    qint64 const currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
 | 
			
		||||
    int const fractional_part = currentMSecsSinceEpoch % 1000;
 | 
			
		||||
    char buf[OUTPUT_LEN]{};
 | 
			
		||||
    memset(buf, 0x00, sizeof(buf));
 | 
			
		||||
    QDateTime const datetime = QDateTime::fromMSecsSinceEpoch(currentMSecsSinceEpoch);
 | 
			
		||||
    switch (type) {
 | 
			
		||||
        case QtDebugMsg: {
 | 
			
		||||
            if (debugLevel <= QtDebugMsg) {
 | 
			
		||||
                // fprintf(stderr, "%*.*s          CTX %s (%s:%u) ->\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                //        "", function, file, context.line);
 | 
			
		||||
                //fprintf(stderr, "%*.*s.%03d DEBG %s\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                //        datetime.toString(format).toStdString().c_str(), fractional_part,
 | 
			
		||||
                //        localMsg.constData());
 | 
			
		||||
                fprintf(stderr, "%*.*s.%03d DEBUG %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                        datetime.toString(format).toStdString().c_str(), fractional_part,
 | 
			
		||||
                        localMsg.constData(), file, context.line);
 | 
			
		||||
            if (debugLevel == QtDebugMsg) {
 | 
			
		||||
                snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d DEBG %s\n",
 | 
			
		||||
                         function, file, context.line,
 | 
			
		||||
                         datetime.time().toString(format).toStdString().c_str(),
 | 
			
		||||
                         fractional_part,
 | 
			
		||||
                         localMsg.constData());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case QtInfoMsg: {
 | 
			
		||||
            if (debugLevel <= QtInfoMsg) {
 | 
			
		||||
                fprintf(stderr, "%*.*s.%03d INFO %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                        datetime.toString(format).toStdString().c_str(), fractional_part,
 | 
			
		||||
                        localMsg.constData(), file, context.line);
 | 
			
		||||
            if (debugLevel == QtInfoMsg || debugLevel == QtDebugMsg) {
 | 
			
		||||
                snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d INFO %s\n",
 | 
			
		||||
                         function, file, context.line,
 | 
			
		||||
                         datetime.time().toString(format).toStdString().c_str(),
 | 
			
		||||
                         fractional_part,
 | 
			
		||||
                         localMsg.constData());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case QtWarningMsg: {
 | 
			
		||||
            if (debugLevel <= QtWarningMsg) {
 | 
			
		||||
                fprintf(stderr, "%*.*s.%03d WARN %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                        datetime.toString(format).toStdString().c_str(), fractional_part,
 | 
			
		||||
                        localMsg.constData(), file, context.line);
 | 
			
		||||
            if (debugLevel == QtInfoMsg || debugLevel == QtDebugMsg || debugLevel == QtWarningMsg) {
 | 
			
		||||
                snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d WARN %s\n",
 | 
			
		||||
                         function, file, context.line,
 | 
			
		||||
                         datetime.time().toString(format).toStdString().c_str(),
 | 
			
		||||
                         fractional_part,
 | 
			
		||||
                         localMsg.constData());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case QtCriticalMsg: {
 | 
			
		||||
            if (debugLevel <= QtCriticalMsg) {
 | 
			
		||||
                fprintf(stderr, "%*.*s.%03d CRIT %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                        datetime.toString(format).toStdString().c_str(), fractional_part,
 | 
			
		||||
                        localMsg.constData(), file, context.line);
 | 
			
		||||
            if (debugLevel == QtInfoMsg || debugLevel == QtDebugMsg
 | 
			
		||||
             || debugLevel == QtWarningMsg || debugLevel == QtCriticalMsg) {
 | 
			
		||||
                snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d CRIT %s\n",
 | 
			
		||||
                         function, file, context.line,
 | 
			
		||||
                         datetime.time().toString(format).toStdString().c_str(),
 | 
			
		||||
                         fractional_part,
 | 
			
		||||
                         localMsg.constData());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case QtFatalMsg: {
 | 
			
		||||
            if (debugLevel <= QtFatalMsg) {
 | 
			
		||||
                fprintf(stderr, "%*.*s.%03d FATAL %s (%s:%u)\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                        datetime.toString(format).toStdString().c_str(), fractional_part,
 | 
			
		||||
                        localMsg.constData(), file, context.line);
 | 
			
		||||
            if (debugLevel == QtInfoMsg || debugLevel == QtDebugMsg
 | 
			
		||||
             || debugLevel == QtWarningMsg || debugLevel == QtCriticalMsg
 | 
			
		||||
             || debugLevel == QtFatalMsg) {
 | 
			
		||||
                snprintf(buf, sizeof(buf)-1, "%30.30s (%20.20s:%04u) %s.%03d FATAL %s\n",
 | 
			
		||||
                         function, file, context.line,
 | 
			
		||||
                         datetime.time().toString(format).toStdString().c_str(),
 | 
			
		||||
                         fractional_part,
 | 
			
		||||
                         localMsg.constData());
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        default: {
 | 
			
		||||
            fprintf(stderr, "%*.*s.%03d No ErrorLevel defined! %s\n", OUTPUT_LEN, OUTPUT_LEN,
 | 
			
		||||
                datetime.toString(format).toStdString().c_str(), fractional_part,
 | 
			
		||||
                datetime.time().toString(format).toStdString().c_str(), fractional_part,
 | 
			
		||||
                msg.toStdString().c_str());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    fprintf(stderr, "%s\n", buf);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1571
									
								
								plugins/interfaces.h
									
									
									
									
									
								
							
							
						
						
									
										1571
									
								
								plugins/interfaces.h
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								plugins/libCAmaster.so
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								plugins/libCAmaster.so
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										319
									
								
								update.cpp
									
									
									
									
									
								
							
							
						
						
									
										319
									
								
								update.cpp
									
									
									
									
									
								
							@@ -8,43 +8,82 @@
 | 
			
		||||
#include <QTextStream>
 | 
			
		||||
#include <QRegularExpression>
 | 
			
		||||
 | 
			
		||||
#include "interfaces.h"
 | 
			
		||||
#include "DCPlugin/include/hwapi.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
#include <QSharedMemory>
 | 
			
		||||
#include <QScopedPointer>
 | 
			
		||||
#include <QProcess>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QThread>
 | 
			
		||||
#include <QDateTime>
 | 
			
		||||
#include <QPluginLoader>
 | 
			
		||||
 | 
			
		||||
#define COLUMN_REQUEST      (0)
 | 
			
		||||
#define COLUMN_NAME         (1)
 | 
			
		||||
#define COLUMN_DATE_TIME    (2)
 | 
			
		||||
#define COLUMN_RESULT       (3)
 | 
			
		||||
 | 
			
		||||
void ScopedPointerCustomDeleter::cleanup(Update *update) {
 | 
			
		||||
    if (update->m_delete) {
 | 
			
		||||
        delete update;
 | 
			
		||||
hwinf *Update::loadDCPlugin(QDir const &plugInDir, QString const &fname) {
 | 
			
		||||
    hwinf *hw = nullptr;
 | 
			
		||||
    if (plugInDir.exists()) {
 | 
			
		||||
        QString pluginLibName(fname);
 | 
			
		||||
        pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
 | 
			
		||||
        QFileInfo info(pluginLibName);
 | 
			
		||||
        if (info.exists()) {
 | 
			
		||||
            pluginLibName = plugInDir.absoluteFilePath(pluginLibName);
 | 
			
		||||
            static QPluginLoader pluginLoader(pluginLibName);
 | 
			
		||||
            if (!pluginLoader.load()) {
 | 
			
		||||
                qCritical() << "in directory" << plugInDir.absolutePath();
 | 
			
		||||
                qCritical() << "cannot load plugin" << pluginLoader.fileName();
 | 
			
		||||
                qCritical() << pluginLoader.errorString();
 | 
			
		||||
                exit(-1);
 | 
			
		||||
            }
 | 
			
		||||
            if (!pluginLoader.isLoaded()) {
 | 
			
		||||
                qCritical() << pluginLoader.errorString();
 | 
			
		||||
                exit(-2);
 | 
			
		||||
            }
 | 
			
		||||
            QObject *plugin = pluginLoader.instance();
 | 
			
		||||
            if (!plugin) {
 | 
			
		||||
                qCritical() << "cannot start instance";
 | 
			
		||||
                exit(-3);
 | 
			
		||||
            }
 | 
			
		||||
            if (! (hw = qobject_cast<hwinf *>(plugin))) {
 | 
			
		||||
                qCritical() << "cannot cast plugin" << plugin << "to hwinf";
 | 
			
		||||
                exit(-4);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            qCritical() << pluginLibName << "does not exist";
 | 
			
		||||
            exit(-5);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        qCritical() << "plugins directory" << plugInDir.absolutePath()
 | 
			
		||||
                    << "does not exist";
 | 
			
		||||
        exit(-6);
 | 
			
		||||
    }
 | 
			
		||||
    return hw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Update::Update(QString update_ctrl_file,
 | 
			
		||||
Update::Update(hwinf *hw,
 | 
			
		||||
               QString update_ctrl_file,
 | 
			
		||||
               QString workingDir,
 | 
			
		||||
               QObject *parent,
 | 
			
		||||
               hwinf *hw,
 | 
			
		||||
               char const *serialInterface,
 | 
			
		||||
               char const *baudrate)
 | 
			
		||||
    : QObject(parent)
 | 
			
		||||
    , m_hw(hw != nullptr ? hw : new hwapi())
 | 
			
		||||
    , m_hw(hw)
 | 
			
		||||
    , m_serialInterface(serialInterface)
 | 
			
		||||
    , m_baudrate(baudrate)
 | 
			
		||||
    , m_update_ctrl_file(update_ctrl_file)
 | 
			
		||||
    , m_update_ctrl_file_copy(update_ctrl_file + ".copy")
 | 
			
		||||
    , m_workingDir(workingDir)
 | 
			
		||||
    , m_init(true)
 | 
			
		||||
    , m_delete(hw == nullptr) {
 | 
			
		||||
    , m_init(true) {
 | 
			
		||||
 | 
			
		||||
    // qCritical() << "workingDir" << m_workingDir;
 | 
			
		||||
 | 
			
		||||
    // m_hw->dc_autoRequest(false);
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
    execUpdateScript();
 | 
			
		||||
 | 
			
		||||
    if (!m_update_ctrl_file.exists()) {
 | 
			
		||||
@@ -67,6 +106,8 @@ Update::Update(QString update_ctrl_file,
 | 
			
		||||
        m_init = false;
 | 
			
		||||
    }
 | 
			
		||||
    qDebug() << "Opened" << m_update_ctrl_file_copy.fileName();
 | 
			
		||||
 | 
			
		||||
    //QApplication::processEvents();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Update::~Update() {
 | 
			
		||||
@@ -78,6 +119,14 @@ bool Update::execUpdateScript() {
 | 
			
		||||
    update_psa += m_workingDir;
 | 
			
		||||
 | 
			
		||||
    qCritical() << "update_psa: " << update_psa;
 | 
			
		||||
    //QApplication::processEvents();
 | 
			
		||||
    //for (int i=0;i<10;++i) {
 | 
			
		||||
    //    QThread::sleep(1);
 | 
			
		||||
    //QApplication::processEvents();
 | 
			
		||||
    //}
 | 
			
		||||
 | 
			
		||||
    // debug
 | 
			
		||||
    return true;
 | 
			
		||||
 | 
			
		||||
    //QStringList const params(QStringList() << "-c" << update_psa);
 | 
			
		||||
 | 
			
		||||
@@ -102,19 +151,248 @@ bool Update::execUpdateScript() {
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Update::DownloadResult Update::sendStatus(int ret) const {
 | 
			
		||||
    switch (ret) {                      // return values of dc are:
 | 
			
		||||
    case 0:                             // 0: no answer by now
 | 
			
		||||
        return DownloadResult::NOP;     // 1: error
 | 
			
		||||
    case 10:                            // 10: success
 | 
			
		||||
        return DownloadResult::OK;
 | 
			
		||||
    default:;
 | 
			
		||||
    }
 | 
			
		||||
    return DownloadResult::ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Update::DownloadResult Update::sendNextAddress(int bNum) const {
 | 
			
		||||
    // sends address only if blockNumber is one of 0, 1024, 2048, 3072, 4096
 | 
			
		||||
    int noAnswerCount = 0;
 | 
			
		||||
    int errorCount = 0;
 | 
			
		||||
    if ( bNum==0 || bNum==1024 || bNum==2048 || bNum==3072 || bNum==4096 ) {
 | 
			
		||||
        qDebug() << "addr-block" << bNum << "...";
 | 
			
		||||
        while (noAnswerCount <= 250) {
 | 
			
		||||
            m_hw->bl_sendAddress(bNum);
 | 
			
		||||
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
 | 
			
		||||
            DownloadResult const res = sendStatus(m_hw->bl_wasSendingAddOK());
 | 
			
		||||
            if (res != DownloadResult::NOP) {
 | 
			
		||||
                if (res == DownloadResult::ERROR) {
 | 
			
		||||
                    if (++errorCount >= 10) {
 | 
			
		||||
                        qCritical() << "addr-block" << bNum << "...FAILED";
 | 
			
		||||
                        return res;
 | 
			
		||||
                    }
 | 
			
		||||
                } else { // res == DownloadResult::OK
 | 
			
		||||
                    qInfo() << "addr-block" << bNum << "...OK";
 | 
			
		||||
                    return res;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                noAnswerCount += 1; // no answer by now
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // wait max. about 3 seconds
 | 
			
		||||
        return DownloadResult::TIMEOUT;
 | 
			
		||||
    }
 | 
			
		||||
    // blockNumber is not one of 0, 1024, 2048, 3072, 4096 -> do nothing
 | 
			
		||||
    return DownloadResult::NOP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Update::DownloadResult Update::sendNextDataBlock(QByteArray const &binary,
 | 
			
		||||
                                                 int bNum) const {
 | 
			
		||||
    uint8_t local[66];
 | 
			
		||||
    int const bAddr = bNum * 64;
 | 
			
		||||
    int noAnswerCount = 0;
 | 
			
		||||
    int errorCount = 0;
 | 
			
		||||
 | 
			
		||||
    memcpy(local, binary.constData() + bAddr, 64);
 | 
			
		||||
    local[64] = local[65] = 0x00;
 | 
			
		||||
 | 
			
		||||
    //for (int i=0; i<4; ++i) {
 | 
			
		||||
    //    printf("%04d ", bNum);
 | 
			
		||||
    //    for (int j=0; j < 16; ++j) {
 | 
			
		||||
    //        printf("%02x ", local[i*16 + j]);
 | 
			
		||||
    //    } printf("\n");
 | 
			
		||||
    //}
 | 
			
		||||
 | 
			
		||||
    while (noAnswerCount <= 250) {
 | 
			
		||||
        m_hw->bl_sendDataBlock(64, local);
 | 
			
		||||
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
			
		||||
        DownloadResult const res = sendStatus(m_hw->bl_wasSendingDataOK());
 | 
			
		||||
        if (res != DownloadResult::NOP) {
 | 
			
		||||
            if (res == DownloadResult::ERROR) {
 | 
			
		||||
                if (++errorCount >= 10) {
 | 
			
		||||
                    qCritical() << "data for block" << bNum << "...FAILED";
 | 
			
		||||
                    return res;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                qInfo() << "data for block" << bNum << "OK";
 | 
			
		||||
                return res;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            noAnswerCount += 1; // no answer by now
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // wait max. about 3 seconds
 | 
			
		||||
    return DownloadResult::TIMEOUT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Update::DownloadResult Update::dc_downloadBinary(QByteArray const &b) const {
 | 
			
		||||
    int const nBlocks = (((b.size())%64)==0) ? (b.size()/64) : (b.size()/64)+1;
 | 
			
		||||
 | 
			
		||||
    qInfo() << "total number of bytes to send to dc" << b.size();
 | 
			
		||||
    qInfo() << "total number of blocks to send to dc" << nBlocks;
 | 
			
		||||
 | 
			
		||||
    int bNum = 0;
 | 
			
		||||
    DownloadResult res = DownloadResult::OK;
 | 
			
		||||
    while (res != DownloadResult::ERROR &&  bNum < nBlocks) {
 | 
			
		||||
        if ((res = sendNextAddress(bNum)) != DownloadResult::ERROR) {
 | 
			
		||||
            if ((res = sendNextDataBlock(b, bNum)) != DownloadResult::ERROR) {
 | 
			
		||||
                bNum += 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    qInfo() << "nBlocks" << nBlocks;
 | 
			
		||||
    //if (res != DownloadResult::ERROR) {
 | 
			
		||||
    // always send last block, even when there are no data !!!
 | 
			
		||||
    int const rest = b.size() % 64;
 | 
			
		||||
    int const offset = b.size() - rest;
 | 
			
		||||
    char const *startAddress = b.constData() + offset;
 | 
			
		||||
 | 
			
		||||
    uint8_t local[66];
 | 
			
		||||
    memset(local, 0x00, sizeof(local));
 | 
			
		||||
    if (rest > 0) {
 | 
			
		||||
        memcpy(local, startAddress, rest);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //for (int i=0; i<4; ++i) {
 | 
			
		||||
    //    printf("*** %04d ", bNum);
 | 
			
		||||
    //    for (int j=0; j < 16; ++j) {
 | 
			
		||||
    //        printf("%02x ", local[i*16 + j]);
 | 
			
		||||
    //    } printf("\n");
 | 
			
		||||
    //}
 | 
			
		||||
 | 
			
		||||
    // bl_sendLastBlock(local);
 | 
			
		||||
    m_hw->bl_sendLastBlock();
 | 
			
		||||
    qInfo() << "last result" << (int)sendStatus(m_hw->bl_wasSendingDataOK());
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::startBootloader() const {
 | 
			
		||||
    qDebug() << "starting bootloader...";
 | 
			
		||||
    int nTry = 5;
 | 
			
		||||
    while (--nTry >= 0) {
 | 
			
		||||
        m_hw->bl_startBL();
 | 
			
		||||
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
 | 
			
		||||
        m_hw->bl_checkBL();
 | 
			
		||||
        if (m_hw->bl_isUp()) {
 | 
			
		||||
            qInfo() << "starting bootloader...OK";
 | 
			
		||||
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    qCritical() << "starting bootloader...FAILED";
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::stopBootloader() const {
 | 
			
		||||
    qDebug() << "stopping bootloader...";
 | 
			
		||||
    int nTry = 5;
 | 
			
		||||
    while (--nTry >= 0) {
 | 
			
		||||
        m_hw->bl_stopBL();
 | 
			
		||||
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
 | 
			
		||||
        if (!m_hw->bl_isUp()) {
 | 
			
		||||
            qInfo() << "stopping bootloader...OK";
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    qCritical() << "stopping bootloader...FAILED";
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// br is a index into a table, used for historical reasons.
 | 
			
		||||
bool Update::openSerial(int br, QString baudrate, QString comPort) const {
 | 
			
		||||
    qDebug() << "opening serial" << br << baudrate << comPort << "...";
 | 
			
		||||
    if (m_hw->dc_openSerial(br, baudrate, comPort, 1)) { // 1 for connect
 | 
			
		||||
        qInfo() << "opening serial" << br << baudrate << comPort << "...OK";
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    qCritical() << "opening serial" << br << baudrate << comPort << "...FAILED";
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Update::closeSerial() const {
 | 
			
		||||
    m_hw->dc_closeSerial();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::resetDeviceController() const {
 | 
			
		||||
    qDebug() << "resetting device controller...";
 | 
			
		||||
    //if (stopBootloader()) { // first stop a (maybe) running bootloader
 | 
			
		||||
    // std::this_thread::sleep_for(std::chrono::milliseconds(1000));
 | 
			
		||||
    m_hw->bl_rebootDC();
 | 
			
		||||
    // wait maximally 3 seconds, before starting bootloader
 | 
			
		||||
    std::this_thread::sleep_for(std::chrono::milliseconds(1500));
 | 
			
		||||
    qInfo() << "resetting device controller...OK";
 | 
			
		||||
    return true;
 | 
			
		||||
    //}
 | 
			
		||||
    //qCritical() << "stopping bootloader...FAILED";
 | 
			
		||||
    //return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QByteArray Update::loadBinaryDCFile(QString filename) const {
 | 
			
		||||
    qDebug() << "loading dc binary" << filename << "...";
 | 
			
		||||
 | 
			
		||||
    QFile file(filename); // closed in destructor call
 | 
			
		||||
    if (!file.exists()) {
 | 
			
		||||
        qCritical() << file.fileName() << "does not exist";
 | 
			
		||||
        return QByteArray();
 | 
			
		||||
    }
 | 
			
		||||
    if (!file.open(QIODevice::ReadOnly)) {
 | 
			
		||||
        qCritical() << "cannot open file" << file.fileName();
 | 
			
		||||
        return QByteArray();
 | 
			
		||||
    }
 | 
			
		||||
    qInfo() << "loading dc binary" << filename << "...OK";
 | 
			
		||||
    return file.readAll();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::downloadBinaryToDC(QString const &bFile) const {
 | 
			
		||||
    qDebug() << "sending" << bFile << "to dc...";
 | 
			
		||||
    QByteArray const dcBinary = loadBinaryDCFile(bFile);
 | 
			
		||||
    if (dcBinary.size() > 0) {
 | 
			
		||||
        if (dc_downloadBinary(dcBinary) != DownloadResult::OK) {
 | 
			
		||||
            qCritical() << "sending" << bFile << "to dc...FAILED";
 | 
			
		||||
            return false;
 | 
			
		||||
        } else {
 | 
			
		||||
            qInfo() << "sending" << bFile << "to dc...OK";
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        qCritical() << "sending" << bFile << "to dc...FAILED";
 | 
			
		||||
        qCritical() << "loading binary" << bFile << "FAILED";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::updateBinary(char const *fileToSendToDC) {
 | 
			
		||||
    // return true; // debug
 | 
			
		||||
    return m_hw->dc_updateDC(fileToSendToDC, m_baudrate, m_serialInterface);
 | 
			
		||||
    QFile fn(fileToSendToDC);
 | 
			
		||||
    bool r;
 | 
			
		||||
    if ((r = fn.exists()) == true) {
 | 
			
		||||
        QString const linkTarget = fn.symLinkTarget();
 | 
			
		||||
        qCritical() << "updating binary (dc): link target" << linkTarget;
 | 
			
		||||
        // debug
 | 
			
		||||
        //r = m_hw->dc_updateDC(linkTarget, m_baudrate, m_serialInterface);
 | 
			
		||||
        qCritical() << "updating binary (dc): "
 | 
			
		||||
                    << linkTarget << ((r == true) ? "OK" : "ERROR");
 | 
			
		||||
    } else {
 | 
			
		||||
        qCritical() << "symlink" << fileToSendToDC << "does not exist";
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Update::updatePrinterConf(int nrOfTemplate, char const *fileToSendToDC) {
 | 
			
		||||
    // return true; // debug
 | 
			
		||||
    qCritical() << "updating printer template: " << fileToSendToDC;
 | 
			
		||||
    return true; // debug
 | 
			
		||||
    QVector<int> printTemplates{ nrOfTemplate };
 | 
			
		||||
    QVector<QString> filesToSend{ fileToSendToDC };
 | 
			
		||||
    return m_hw->dc_updatePrinterTemplate(hwapi::FileTypeJson::PRINTER,
 | 
			
		||||
                                          printTemplates, filesToSend,
 | 
			
		||||
                                          QString(m_baudrate),
 | 
			
		||||
                                          QString(m_serialInterface));
 | 
			
		||||
    //return m_hw->dc_updatePrinterTemplate(hwapi::FileTypeJson::PRINTER,
 | 
			
		||||
    //                                      printTemplates, filesToSend,
 | 
			
		||||
    //                                      QString(m_baudrate),
 | 
			
		||||
    //                                      QString(m_serialInterface));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList Update::getOpenLines() {
 | 
			
		||||
@@ -167,7 +445,6 @@ bool Update::doUpdate() {
 | 
			
		||||
        #
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    // qCritical() << "Device Controller SW-version"  << m_hw->dc_getSWversion();
 | 
			
		||||
 | 
			
		||||
    if (!m_init) {
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -193,19 +470,19 @@ bool Update::doUpdate() {
 | 
			
		||||
        QString const &result = lst[COLUMN_RESULT];
 | 
			
		||||
        if ((!request.contains("DOWNLOAD") && !request.contains("EXECUTE")) ||
 | 
			
		||||
            !result.contains("N/A")) {
 | 
			
		||||
            qCritical() << "Parsing error for" << m_update_ctrl_file.fileName();
 | 
			
		||||
            qCritical() << "parsing error for" << m_update_ctrl_file.fileName();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        if (name.contains("dc2c") && name.endsWith(".bin")) {
 | 
			
		||||
            if ((res = updateBinary(name.toStdString().c_str())) == true) {
 | 
			
		||||
                qInfo() << "Downloaded" << name;
 | 
			
		||||
                qInfo() << "downloaded binary" << name;
 | 
			
		||||
            }
 | 
			
		||||
        } else
 | 
			
		||||
        if (name.contains("DC2C_print") && name.endsWith(".json")) {
 | 
			
		||||
            int i = name.indexOf("DC2C_print");
 | 
			
		||||
            int templateIdx = name.mid(i).midRef(10, 2).toInt();
 | 
			
		||||
            if ((res = updatePrinterConf(templateIdx, name.toStdString().c_str())) == true) {
 | 
			
		||||
                qInfo() << "Downloaded" << name;
 | 
			
		||||
                qInfo() << "downloaded printer template" << name;
 | 
			
		||||
            }
 | 
			
		||||
        } else
 | 
			
		||||
        if (name.contains("opkg")) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								update.h
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								update.h
									
									
									
									
									
								
							@@ -4,9 +4,10 @@
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QByteArray>
 | 
			
		||||
 | 
			
		||||
#include "interfaces.h"
 | 
			
		||||
#include "DCPlugin/include/hwapi.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
#ifdef PTU5
 | 
			
		||||
#define SERIAL_PORT "ttymxc2"
 | 
			
		||||
@@ -15,9 +16,6 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class Update;
 | 
			
		||||
struct ScopedPointerCustomDeleter {
 | 
			
		||||
    static void cleanup(Update *pointer);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TODO: check hardware compatibility
 | 
			
		||||
// TODO: opkg commandos
 | 
			
		||||
@@ -25,7 +23,7 @@ struct ScopedPointerCustomDeleter {
 | 
			
		||||
class Update : public QObject {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    QScopedPointer<hwinf> m_hw;
 | 
			
		||||
    hwinf *m_hw;
 | 
			
		||||
    char const *m_serialInterface;
 | 
			
		||||
    char const *m_baudrate;
 | 
			
		||||
    QFile m_update_ctrl_file;
 | 
			
		||||
@@ -41,16 +39,34 @@ class Update : public QObject {
 | 
			
		||||
    QStringList split(QString line, QChar sep = ',');
 | 
			
		||||
 | 
			
		||||
    bool execUpdateScript();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit Update(QString update_ctrl_file,
 | 
			
		||||
    enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
 | 
			
		||||
 | 
			
		||||
    static hwinf *loadDCPlugin(QDir const &plugInDir, QString const &fn);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    explicit Update(hwinf *hw,
 | 
			
		||||
                    QString update_ctrl_file,
 | 
			
		||||
                    QString workingDir = ".",
 | 
			
		||||
                    QObject *parent = nullptr,
 | 
			
		||||
                    hwinf *hw = nullptr,
 | 
			
		||||
                    char const *serialInterface = SERIAL_PORT,
 | 
			
		||||
                    char const *baudrate = "115200");
 | 
			
		||||
    virtual ~Update() override;
 | 
			
		||||
    bool doUpdate();
 | 
			
		||||
 | 
			
		||||
    bool const m_delete;
 | 
			
		||||
private:
 | 
			
		||||
    DownloadResult sendStatus(int ret) const;
 | 
			
		||||
    DownloadResult sendNextAddress(int bNum) const;
 | 
			
		||||
    DownloadResult sendNextDataBlock(QByteArray const &b, int bNum) const;
 | 
			
		||||
    DownloadResult dc_downloadBinary(QByteArray const &binary) const;
 | 
			
		||||
 | 
			
		||||
    bool startBootloader() const;
 | 
			
		||||
    bool stopBootloader() const;
 | 
			
		||||
    bool openSerial(int br, QString baudrate, QString comPort) const;
 | 
			
		||||
    void closeSerial() const;
 | 
			
		||||
    bool resetDeviceController() const;
 | 
			
		||||
    QByteArray loadBinaryDCFile(QString filename) const;
 | 
			
		||||
    bool downloadBinaryToDC(QString const &bFile) const;
 | 
			
		||||
};
 | 
			
		||||
#endif // UPDATE_H_INCLUDED
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								worker.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								worker.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
#include "worker.h"
 | 
			
		||||
#include "update.h"
 | 
			
		||||
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <QFileInfo>
 | 
			
		||||
#include <QDir>
 | 
			
		||||
#include <QThread>
 | 
			
		||||
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "plugins/interfaces.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Worker::Worker(QString update_ctrl_file, QString workingDir)
 | 
			
		||||
      : m_update_ctrl_file(update_ctrl_file)
 | 
			
		||||
      , m_workingDir(workingDir)
 | 
			
		||||
      , m_workerThread("workerThread") {
 | 
			
		||||
 | 
			
		||||
    this->moveToThread(&m_workerThread);
 | 
			
		||||
    m_workerThread.start();
 | 
			
		||||
    QThread::usleep(100000);
 | 
			
		||||
 | 
			
		||||
    int cnt = 0;
 | 
			
		||||
    while (!m_workerThread.isRunning()) {
 | 
			
		||||
        if (++cnt > 5) {
 | 
			
		||||
            qCritical() << "starting worker thread FAILED";
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        QThread::sleep(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    connect(this, SIGNAL(workNow()), this, SLOT(work()), Qt::QueuedConnection);
 | 
			
		||||
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(update()));
 | 
			
		||||
    m_timer.setSingleShot(true);
 | 
			
		||||
    m_timer.start(1000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Worker::~Worker() {
 | 
			
		||||
    int cnt = 0;
 | 
			
		||||
    m_workerThread.quit();
 | 
			
		||||
    while (!m_workerThread.isFinished()) {
 | 
			
		||||
        if (!m_workerThread.wait(1000)) {
 | 
			
		||||
            if (++cnt > 5) {
 | 
			
		||||
                qCritical() << "stopping worker thread FAILED";
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Worker::update() {
 | 
			
		||||
    qCritical() << __func__ << ":" << __LINE__;
 | 
			
		||||
    emit workNow();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Worker::work() {
 | 
			
		||||
   qCritical() << __func__ << ":" << __LINE__;
 | 
			
		||||
   //Update m_update(m_update_ctrl_file, m_workingDir);
 | 
			
		||||
   QThread::sleep(3);
 | 
			
		||||
   //if (m_update.doUpdate()) {
 | 
			
		||||
   //}
 | 
			
		||||
   m_workerThread.quit();
 | 
			
		||||
   QApplication::quit();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								worker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								worker.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
#ifndef WORKER_H_INCLUDED
 | 
			
		||||
#define WORKER_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
 | 
			
		||||
#include "worker_thread.h"
 | 
			
		||||
 | 
			
		||||
class Worker : public QObject {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
    QString m_update_ctrl_file;
 | 
			
		||||
    QString m_workingDir;
 | 
			
		||||
    WorkerThread m_workerThread;
 | 
			
		||||
    QTimer m_timer;
 | 
			
		||||
public:
 | 
			
		||||
    explicit Worker(QString update_ctrl_file, QString workingDir);
 | 
			
		||||
    ~Worker();
 | 
			
		||||
    void quit() { return m_workerThread.quit(); }
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
    void workNow();
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
    void work();
 | 
			
		||||
    void update();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // WORKER_H_INCLUDED
 | 
			
		||||
							
								
								
									
										13
									
								
								worker_thread.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								worker_thread.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#include "worker_thread.h"
 | 
			
		||||
 | 
			
		||||
WorkerThread::WorkerThread(QString const &name,
 | 
			
		||||
                           QObject *parent) : QThread(parent) {
 | 
			
		||||
    this->setObjectName(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WorkerThread::~WorkerThread() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//void WorkerThread::run() {
 | 
			
		||||
//
 | 
			
		||||
//}
 | 
			
		||||
							
								
								
									
										17
									
								
								worker_thread.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								worker_thread.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
#ifndef WORKER_THREAD_H_INCLUDED
 | 
			
		||||
#define WORKER_THREAD_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <QThread>
 | 
			
		||||
#include <QString>
 | 
			
		||||
 | 
			
		||||
class WorkerThread : public QThread {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
    WorkerThread(QString const &name, QObject *parent = nullptr);
 | 
			
		||||
    virtual ~WorkerThread();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    // virtual void run();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // WORKER_THREAD_H_INCLUDED
 | 
			
		||||
		Reference in New Issue
	
	Block a user