Compare commits
No commits in common. "35d40e3b3c84472157f9542feb5a800af89d58da" and "2b5fca73a269422bcf0f9470f9bb5a010e02d978" have entirely different histories.
35d40e3b3c
...
2b5fca73a2
@ -1,73 +0,0 @@
|
||||
# QT -= gui
|
||||
QT += core
|
||||
QT += widgets serialport
|
||||
QT += network
|
||||
|
||||
TARGET = up_dev_ctrl
|
||||
|
||||
CONFIG += c++11
|
||||
# CONFIG -= app_bundle
|
||||
|
||||
# DEFINES+=LinuxDesktop
|
||||
|
||||
QMAKE_CXXFLAGS += -Wno-deprecated-copy
|
||||
|
||||
# custom target for 'git subtree'
|
||||
# subtree.target = subtree
|
||||
# subtree.commands = git subtree add --prefix DCPlugin https://git.mimbach49.de/GerhardHoffmann/DCPlugin.git master --squash
|
||||
# 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 {
|
||||
# $$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.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
contains( CONFIG, PTU5 ) {
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
|
||||
CONFIG += link_pkgconfig
|
||||
lessThan(QT_MAJOR_VERSION, 5): PKGCONFIG += qextserialport
|
||||
QMAKE_CXXFLAGS += -std=c++11 # for GCC >= 4.7
|
||||
QMAKE_CXXFLAGS += -Wno-deprecated-copy
|
||||
ARCH = PTU5
|
||||
DEFINES+=PTU5
|
||||
}
|
||||
contains( CONFIG, DesktopLinux ) {
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += serialport
|
||||
lessThan(QT_MAJOR_VERSION, 5): CONFIG += extserialport
|
||||
# QMAKE_CC = ccache $$QMAKE_CC
|
||||
# QMAKE_CXX = ccache $$QMAKE_CXX
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
QMAKE_CXXFLAGS += -Wno-deprecated-copy
|
||||
linux-clang { QMAKE_CXXFLAGS += -Qunused-arguments }
|
||||
ARCH = DesktopLinux
|
||||
DEFINES+=DesktopLinux
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
update.cpp \
|
||||
message_handler.cpp
|
||||
|
||||
HEADERS += \
|
||||
update.h \
|
||||
message_handler.h \
|
||||
DCPlugin/include/interfaces.h
|
||||
|
||||
OTHER_FILES += \
|
||||
/opt/app/tools/atbupdate/update_log.csv
|
||||
|
||||
# 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)
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
Binary file not shown.
@ -1,110 +0,0 @@
|
||||
\documentclass[12pt]{article}
|
||||
\usepackage{euler}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{lipsum}
|
||||
\usepackage[colorlinks=true, urlcolor=blue, linkcolor=red]{hyperref}
|
||||
\newcounter{Chapcounter}
|
||||
\newcommand\showmycounter{\addtocounter{Chapcounter}{1}\themycounter}
|
||||
\newcommand{\chapter}[1]
|
||||
{{\centering
|
||||
\addtocounter{Chapcounter}{1} \Large \underline{\textbf{ \color{blue} Chapter \theChapcounter: ~#1}} }
|
||||
\addcontentsline{toc}{section}{ \color{blue} Chapter:~\theChapcounter~~ #1}
|
||||
}
|
||||
\hypersetup{colorlinks=true}
|
||||
\hypersetup{linkcolor=black}
|
||||
|
||||
\title{Update PTU}
|
||||
\author{Gerhard Hoffmann}
|
||||
\date{\today}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
\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
|
||||
("cloned") on the PSA when configuring the machine for the first time.\par
|
||||
Two special tools, the {\bf UpdateController} (a \href{https://doc.qt.io/qt-5/}{Qt}
|
||||
binary [{\bf \nameref{UpdateTool}}]) and the {\bf UpdateScript}
|
||||
(a \href{https://www.gnu.org/software/bash/manual/bash.html}{bash}
|
||||
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}}].
|
||||
It updates the file
|
||||
\begin{center}
|
||||
\fbox{
|
||||
/opt/app/tools/atbupdate/update\_log.csv
|
||||
}
|
||||
\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,
|
||||
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
|
||||
|
||||
\chapter{Update-Tool "up\_dev\_ctrl"}
|
||||
\section{up\_dev\_ctrl}
|
||||
\label{UpdateTool}
|
||||
|
||||
The update-tool is a Qt binary ("up\_dev\_ctrl") and called by the
|
||||
system-controller application. It is installed under
|
||||
\begin{center}
|
||||
\fbox{
|
||||
/opt/app/tools/atbupdate/up\_dev\_ctrl
|
||||
}
|
||||
\end{center}
|
||||
|
||||
and has two responsibilities:
|
||||
\begin{itemize}
|
||||
\item Call update-script "update\_psa".
|
||||
\item Update the device controller firmware.
|
||||
\end{itemize}
|
||||
\subsection{Calling the update-script "update\_psa"}
|
||||
The update-script "update\_psa" is about executing all git-commands
|
||||
necessary to clone and pull a customer repository.
|
||||
|
||||
\newpage
|
||||
|
||||
\chapter{Update-Script "update\_psa"}
|
||||
\section{update\_psa}
|
||||
\label{UpdateScript}
|
||||
|
||||
Inside of such a
|
||||
repository, there are at least the following directories:
|
||||
\begin{itemize}
|
||||
\item {\bf etc}
|
||||
\item {\bf etc/dc}\newline
|
||||
Contains the device controller firmware as binary file.
|
||||
\item {\bf etc/psa\_config}\newline
|
||||
Contains the printer template files (JSON).
|
||||
\item {\bf etc/psa\_tariff}\newline
|
||||
Contains the tariff files (JSON).
|
||||
\item {\bf etc/psa\_update}\newline
|
||||
Contains a single file for opkg-commands.
|
||||
\end{itemize}
|
||||
\newpage
|
||||
|
||||
\chapter{Annex}
|
||||
\section{Structure of a customer git-repository}
|
||||
\label{repostructure}
|
||||
|
||||
\section{Structure of "update\_log.csv"}
|
||||
\label{updatelogcsv}
|
||||
|
||||
\section{The package manager "opkg"}
|
||||
\label{opkg}
|
||||
\end{document}
|
26
main.cpp
26
main.cpp
@ -5,6 +5,7 @@
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "message_handler.h"
|
||||
|
||||
#include "interfaces.h"
|
||||
#include "DCPlugin/include/hwapi.h"
|
||||
|
||||
@ -14,7 +15,6 @@
|
||||
#include <QSharedMemory>
|
||||
#include <QRunnable>
|
||||
#include <QThreadPool>
|
||||
#include <QDir>
|
||||
|
||||
#include "update.h"
|
||||
|
||||
@ -26,16 +26,12 @@
|
||||
|
||||
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) {
|
||||
}
|
||||
explicit Work(QString update_ctrl_file)
|
||||
: m_update_ctrl_file(update_ctrl_file) {}
|
||||
void run() {
|
||||
Update m_update(m_update_ctrl_file, m_workingDir);
|
||||
// if (m_update.doUpdate()) {
|
||||
// }
|
||||
Update m_update(m_update_ctrl_file);
|
||||
m_update.doUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
@ -49,15 +45,13 @@ int main(int argc, char *argv[]) {
|
||||
//setDebugLevel(QtMsgType::QtDebugMsg);
|
||||
}
|
||||
|
||||
QByteArray const value = qgetenv("XDG_RUNTIME_DIR");
|
||||
if (value.size() == 0) {
|
||||
qputenv("XDG_RUNTIME_DIR", "/run/user/0");
|
||||
QString update_ctrl_file = "/opt/app/tools/atbupdate/update_log.csv";
|
||||
if (argc == 2) {
|
||||
update_ctrl_file = argv[1];
|
||||
}
|
||||
qInfo() << "Using" << update_ctrl_file << "as update logfile";
|
||||
|
||||
QString const update_ctrl_file = "/opt/app/tools/atbupdate/update_log.csv";
|
||||
QString const workingDir = (argc == 2) ? argv[1] : ".";
|
||||
|
||||
Work work(update_ctrl_file, workingDir);
|
||||
Work work(update_ctrl_file);
|
||||
work.setAutoDelete(false);
|
||||
QThreadPool *threadPool = QThreadPool::globalInstance();
|
||||
threadPool->start(&work);
|
||||
|
34
update.cpp
34
update.cpp
@ -6,7 +6,6 @@
|
||||
#include <QTemporaryFile>
|
||||
#include <QDebug>
|
||||
#include <QTextStream>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include "interfaces.h"
|
||||
#include "DCPlugin/include/hwapi.h"
|
||||
@ -14,7 +13,6 @@
|
||||
#include <QSharedMemory>
|
||||
#include <QScopedPointer>
|
||||
#include <QProcess>
|
||||
#include <QDir>
|
||||
|
||||
#define COLUMN_REQUEST (0)
|
||||
#define COLUMN_NAME (1)
|
||||
@ -28,7 +26,6 @@ void ScopedPointerCustomDeleter::cleanup(Update *update) {
|
||||
}
|
||||
|
||||
Update::Update(QString update_ctrl_file,
|
||||
QString workingDir,
|
||||
QObject *parent,
|
||||
hwinf *hw,
|
||||
char const *serialInterface,
|
||||
@ -39,12 +36,9 @@ Update::Update(QString update_ctrl_file,
|
||||
, 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) {
|
||||
|
||||
execUpdateScript();
|
||||
|
||||
if (!m_update_ctrl_file.exists()) {
|
||||
qCritical() << "Update-file" << m_update_ctrl_file.fileName()
|
||||
<< "does not exist";
|
||||
@ -70,34 +64,6 @@ Update::Update(QString update_ctrl_file,
|
||||
Update::~Update() {
|
||||
}
|
||||
|
||||
bool Update::execUpdateScript() {
|
||||
// path of update-script 'update_psa'
|
||||
QString update_psa("/opt/app/tools/atbupdate/update_psa --wdir ");
|
||||
update_psa += m_workingDir;
|
||||
|
||||
//QStringList const params(QStringList() << "-c" << update_psa);
|
||||
|
||||
QScopedPointer<QProcess> p(new QProcess(this));
|
||||
p->setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
p->start(update_psa);
|
||||
if (p->waitForStarted(1000)) {
|
||||
if (p->state() == QProcess::ProcessState::Running) {
|
||||
if (p->waitForFinished(60000)) {
|
||||
QString output = p->readAllStandardOutput().toStdString().c_str();
|
||||
QStringList lst = output.split('\n');
|
||||
for (int i = 0; i < lst.size(); ++i) {
|
||||
qDebug() << lst[i];
|
||||
}
|
||||
qInfo() << "EXECUTED" << update_psa;
|
||||
return ((p->exitStatus() == QProcess::NormalExit)
|
||||
&& (p->exitCode() == 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Update::updateBinary(char const *fileToSendToDC) {
|
||||
return m_hw->dc_updateDC(fileToSendToDC, m_baudrate, m_serialInterface);
|
||||
}
|
||||
|
57
update.h
57
update.h
@ -1,57 +0,0 @@
|
||||
#ifndef UPDATE_H_INCLUDED
|
||||
#define UPDATE_H_INCLUDED
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
|
||||
#include "interfaces.h"
|
||||
#include "DCPlugin/include/hwapi.h"
|
||||
|
||||
#ifdef PTU5
|
||||
#define SERIAL_PORT "ttymxc2"
|
||||
#else
|
||||
#define SERIAL_PORT "ttyUSB0"
|
||||
#endif
|
||||
|
||||
class Update;
|
||||
struct ScopedPointerCustomDeleter {
|
||||
static void cleanup(Update *pointer);
|
||||
};
|
||||
|
||||
// TODO: check hardware compatibility
|
||||
// TODO: opkg commandos
|
||||
|
||||
class Update : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
QScopedPointer<hwinf> m_hw;
|
||||
char const *m_serialInterface;
|
||||
char const *m_baudrate;
|
||||
QFile m_update_ctrl_file;
|
||||
QFile m_update_ctrl_file_copy;
|
||||
QString m_workingDir;
|
||||
|
||||
bool m_init;
|
||||
|
||||
bool updateBinary(char const *fileToSendToDC);
|
||||
bool updatePrinterConf(int nrOfTemplate, char const *fileToSendToDC);
|
||||
bool finishUpdate(bool finish);
|
||||
QStringList getOpenLines();
|
||||
QStringList split(QString line);
|
||||
static constexpr QChar SEPARATOR = QChar(',');
|
||||
|
||||
bool execUpdateScript();
|
||||
public:
|
||||
explicit Update(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;
|
||||
};
|
||||
#endif // UPDATE_H_INCLUDED
|
Loading…
x
Reference in New Issue
Block a user