Compare commits

...

75 Commits

Author SHA1 Message Date
d5585cda3f
Merge branch 'digitalOutputAbstraction' 2024-11-14 14:47:59 +01:00
2c09402bbb
dCArun: Fix DigitalOutputAbstraction 2024-11-14 14:27:53 +01:00
cd6b1fed00
Remove CCWakelineAbstraction 2024-11-14 14:04:30 +01:00
0ea9ac9af3
dCArun: use DigitalOutputAbstraction 2024-11-14 14:03:13 +01:00
94a95eceb5
dCArun: add DigitalOutputAbstraction 2024-11-14 13:57:52 +01:00
dd29fb0762
datif: command 112: accecpt 40ct coin value ("Stadtmünze" Kirchdorf) 2024-11-06 10:09:12 +01:00
c9e5834e29
Merge branch 'proposal_detect_obsolete_data' 2024-10-22 12:26:40 +02:00
8fa6d40a0c
Merge branch 'proposal_detect_obsolete_data' of git.mimbach49.de:GerhardHoffmann/DCLibraries into proposal_detect_obsolete_data 2024-10-22 12:25:24 +02:00
3e7f71899c loadRecDataFromFrame():
Move coinAttached from error-state to normal debug output.
2024-10-21 16:16:26 +02:00
1cc14e9a4c Add some debug out-put (in error case). 2024-10-17 12:41:31 +02:00
5c9578ebef Minor: debug output (commented out) 2024-10-17 12:40:37 +02:00
b024e34b82 writeToSerial():
Write to serial line in one call as before.
2024-10-16 13:21:33 +02:00
8714071a30 loadRecDataFromFrame():
When reading next message, check readCount + 1 == writeCount. If not, there
	must be something wrong: ignore this message and set readCount <- writeCount.
2024-10-16 13:06:07 +02:00
87bc5b5c1e writeToSerial():
Always write next message. Set writeCount. Clear() serial line before sending.
	Flush() serial line after sending.
2024-10-16 13:03:20 +02:00
ff746a45bc Use readCount to track number of read messages. 2024-10-16 13:02:27 +02:00
d540f1b467 Use writeCount instaed of readCmds. 2024-10-16 13:01:41 +02:00
ca2d9e1b5a Minor: added debug output in error case 2024-10-15 12:45:38 +02:00
4c770349bf removed waitForBytesWritten() 2024-10-15 12:44:56 +02:00
209132054f Added sanity check if there is a command active but no data can be read on the serial line 2024-10-15 10:51:20 +02:00
0f7ab3c71c Minor: adding comments 2024-10-15 10:49:30 +02:00
2b2cd25276 Minor: add waitForTestResponse 2024-10-15 10:08:49 +02:00
08bb513c7b Minor: set recBuf to a definite value 2024-10-15 10:08:11 +02:00
36a8f07069 Pass "this" as parent 2024-10-15 10:07:29 +02:00
900b0ef952 loadRecDataFromFrame():
Read last message if only one command to device controller is active.
	Otherwise assume that the data is obsolete. Trigger the sending
	of a known test-response to find new valid data-stream.
2024-10-15 10:04:40 +02:00
26a11e6c56 writeToSerial():
Only write to serial interface if no current command has been
	sent to DC already.
2024-10-15 10:00:34 +02:00
6321f9068f Add helpers getReadSource() getSerialPort(). 2024-10-15 09:57:49 +02:00
9daa5e17cb Introduce a vector of commands currently sent to device controller. 2024-10-15 09:54:09 +02:00
de61de85f1
Merge branch 'fix_validDataIssue' 2024-09-26 13:26:19 +02:00
4e58fbe4e1
Add plausibility check for inserted coins 2024-09-26 11:48:39 +02:00
647dc9fe4b
Handle: valid data problem while start with coin attached:
Enable command 30 also during sell
2024-09-26 11:45:10 +02:00
433af98de7
Fix: setupStep sequence 2024-07-25 15:34:47 +02:00
492d30aaf0
Fix: T.S.: set DCdataValid 2024-07-24 17:33:38 +02:00
03d21c62b6
Merge branch 'pu/integrationsTS' 2024-07-08 10:19:25 +02:00
b0e55d8ea4
Add collected changes from T.Sax 2024-07-04 14:01:43 +02:00
ab5a343ab2
Merge branch 'carun_wakelineabstraction' 2024-06-10 12:03:08 +02:00
1199dbfd30
Add CCWakelineAbstraction 2024-06-10 11:50:34 +02:00
06d43009ad
Merge branch 'CoinInputFix' 2024-05-22 12:55:32 +02:00
bed98c2c0e
Fix: reset 'lastInsertedAmount' ...
affects direct coin input / cash-payment.
2024-05-22 12:54:00 +02:00
f6cc40c8f9
Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/DCLibraries 2024-03-21 16:07:08 +01:00
6be24fe9ff Merge branch 'master' of https://git.mimbach49.de/GerhardHoffmann/DCLibraries 2024-03-21 15:57:23 +01:00
3612fc28ee bugfix: banknotes have been summed with the coins. Now they are handled separately. 2024-03-21 15:55:50 +01:00
c59de6cad8 bugfix: banknotes have been summed with the coins. Now they are handled separately. 2024-03-21 15:54:58 +01:00
4b0e8ec5f6
Merge branch 'master' of git.mimbach49.de:GerhardHoffmann/DCLibraries 2024-03-14 15:53:44 +01:00
3486c4ccaf Added cash_isCollectionStarted() 2024-03-14 15:17:40 +01:00
ea462ba5c8 call gpi_storeDI_CoinAttach to speed up coin attach detection 2024-03-14 15:16:27 +01:00
961fc6b5dc Fill several struct to align on proper address 2024-03-14 15:14:47 +01:00
6f920604b7 Add cash_isCashCollectionSTarted(). 2024-03-14 15:12:33 +01:00
d5021c8269
Merge branch 'carun_removeWidgets' 2024-03-02 12:16:02 +01:00
7abe8ae419
Libraries: remove dependency to gui/widgets 2024-03-02 12:15:15 +01:00
b8089c443c
CArun: remove dependency to qt gui/widgets 2024-03-02 12:14:02 +01:00
3bbd3e4e19
Proposal: final version for new CArun class 2024-03-02 12:12:49 +01:00
c902bd9a54 Proposal: remove Widgets 2024-03-02 08:36:06 +01:00
25e7bf056b remove unused variable 2024-03-02 07:15:12 +01:00
8f8947482a
Fix: add source-files to project 2024-02-22 08:44:34 +01:00
42c817ddce
Merge branch 'coin-attach' 2024-02-21 16:20:17 +01:00
2c799e1cd2
Merge branch 'coin-attach' of git.mimbach49.de:GerhardHoffmann/DCLibraries into coin-attach 2024-02-21 10:50:41 +01:00
9cac6a6461 Added comment for std::atomic<bool>::exchange() 2024-02-21 10:46:34 +01:00
aa10d3b275 Add atomic<bool> variable m_coinAttached to check for state change:
send signal runProc_coinAttached only if state changes from false true.
2024-02-21 10:39:03 +01:00
790c2fd031 add coin-attach signal 2024-02-19 15:59:41 +01:00
7130d052e7 Merge branch 'SiegfriedSiegert-pu/FixGetDeviceConditions' 2024-02-06 09:55:57 +01:00
ad84464bf4 Merge branch 'pu/FixGetDeviceConditions' of https://git.mimbach49.de/SiegfriedSiegert/DCLibraries into SiegfriedSiegert-pu/FixGetDeviceConditions 2024-02-06 09:55:38 +01:00
Thomas
c5054fe4a0 removed lines for turning so-file into executable binary 2024-02-01 15:01:18 +01:00
02f15421ba Add sources for download/reporting thread 2023-12-20 17:06:37 +01:00
3c9cd16144 Add headers for download/reporting thread 2023-12-20 17:05:47 +01:00
760f4018b5 Merge branch 'master' of https://git.mimbach49.de/GerhardHoffmann/DCLibraries 2023-12-20 16:52:13 +01:00
a344ba1b7d Add implementations for helpers for downloading device controller.
NOTE : They are not called at the moment.
2023-12-20 16:50:50 +01:00
490fdd9209 Minor: add some debug output (versions, build times) 2023-12-20 16:50:23 +01:00
0c417c6940 Add headers for download/reporting thread. 2023-12-20 16:50:00 +01:00
fafea93a62 Add reporting thread and defines for output of versions and build dates/times. 2023-12-20 16:48:57 +01:00
ba99795bf3 Add download thread and define macros to output versions and build times. 2023-12-20 16:47:59 +01:00
135c508320 Add struct DCDownload for downloading the device controller. 2023-12-20 16:46:54 +01:00
f9dfc2b5e7 define git commnds only for linux 2023-12-20 16:46:21 +01:00
fc2abd3e89 Add helers and signals for downloading the device controller. 2023-12-20 16:44:03 +01:00
15671e3a37 Add helpers and signals for downloading the device controller. 2023-12-20 16:42:56 +01:00
54993ac592 Test for commit. 2023-12-18 12:28:43 +01:00
39 changed files with 4463 additions and 1857 deletions

View File

@ -21,14 +21,15 @@ INCLUDEPATH += ../include
win32 {
BUILD_DATE=$$system("date /t")
BUILD_TIME=$$system("time /t")
GIT_COMMIT=""
EXTENDED_VERSION=""
} else {
BUILD_DATE=$$system("date +%d-%m-%y")
BUILD_TIME=$$system("date +%H:%M:%S")
GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1")
EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}"
}
GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1")
EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}"
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\"

View File

@ -1,6 +1,6 @@
CONFIG += plugin
QT -= gui
QT += widgets serialport
QT += serialport
win32 {
@ -90,7 +90,9 @@ HEADERS += \
$${PWD}/include/sendWRcmd.h \
$${PWD}/include/storeINdata.h \
$${PWD}/include/tslib.h \
$${PWD}/include/shared_mem_buffer.h
$${PWD}/include/shared_mem_buffer.h \
$${PWD}/include/reporting_thread.h \
$${PWD}/include/download_thread.h
SOURCES += \
$${PWD}/src/datei.cpp \
@ -101,7 +103,9 @@ SOURCES += \
$${PWD}/src/sendWRcmd.cpp \
$${PWD}/src/storeINdata.cpp \
$${PWD}/src/tslib.cpp \
$${PWD}/src/shared_mem_buffer.cpp
$${PWD}/src/shared_mem_buffer.cpp \
$${PWD}/src/reporting_thread.cpp \
$${PWD}/src/download_thread.cpp
# INTERFACE = DeviceController

178
dCArun/CArun.cpp Normal file
View File

@ -0,0 +1,178 @@
#include "CArun.h"
#include "datei.h"
#include "DigitalOutputAbstraction.h"
CArun::CArun(QObject *parent)
: QObject(parent)
, setupStep(SETUP_STEP::INIT)
{
this->timerChainCtrl = new QTimer(this);
this->connect(timerChainCtrl, SIGNAL(timeout()), this, SLOT(chainControl()));
this->timerChainCtrl->setSingleShot(true);
this->timerChainCtrl->setInterval(100);
loadPlugIn(1);
// Start setup-steps:
qCritical() << "CArun: start setup...";
this->timerChainCtrl->start();
this->digitalOutputAbstraction = new DigitalOutputAbstraction(this->HWaccess, this);
this->digitalOutputAbstraction->addCCWake("/sys/class/leds/wakeupctrl_cc/brightness");
this->digitalOutputAbstraction->addCCPower("/run/powerctrl_cc");
this->digitalOutputAbstraction->addCCModem("/run/powerctrl_modem");
}
char CArun::loadPlugIn(char lade1_entlade2)
{
plugInDir.cd("plugins");
QPluginLoader *pluginLoader = new QPluginLoader();
pluginLoader->setFileName("/usr/lib/libCAmaster.so"); // for ptu5
if (lade1_entlade2==2)
{
pluginLoader->unload();
return 0;
}
if (!pluginLoader->load())
{
qCritical() << "CArun: cannot load plugin";
} else
qCritical() << "CArun: plugin loaded: " << pluginLoader->fileName();
if (!pluginLoader->isLoaded())
{
qCritical() << "CArun: ERROR loading plugin: " << pluginLoader->errorString();;
return 0;
}
QObject *plugin = pluginLoader->instance();
if ( plugin == nullptr)
{
// make instance of the root component (which can hold more then one clases)
// also loads the lib if not yet done
qCritical() << "CArun: ERROR cannot start instance";
return 0;
}
this->HWaccess = qobject_cast<hwinf *>(plugin);
// make instance to class "hwinf" in dll_HWapi.h over "interfaces.h"
return 0;
}
void CArun::openSerialPort()
{
#define FILENAME_COMPORT "../comport.csv" // TODO: use absolute path
// use settings (ini-file)
// comport.csv wird mit installiert in: /opt/app/
// k.A., ob "../comport.csv" gefunden wird.
qCritical() << "CArun: open serial port...";
QString bs, cn;
int br, ci;
// load and use last settings: --------------------
QByteArray myBA;
myBA=datei_readFromFile(FILENAME_COMPORT);
if (myBA.length()>0)
{
bs=csv_getEntryAsString(myBA,0); // read the 's' war 2!??
br=csv_getEntryAsInt(myBA,1); // z.B. 5 (5.Eintrag in der Baud-Liste)
bs=csv_getEntryAsString(myBA,2); // z.B 115200
cn=csv_getEntryAsString(myBA,3); // z.B. COM9
ci=csv_getEntryAsInt(myBA,4); // Eintragsnummer in COM-Fenster
this->HWaccess->dc_openSerial(br,bs,cn,1);
} else
{
// vermutlich wird dies hier ausgeführt?
// open with default settings
qCritical() << "CArun: open serial with default values";
bs="115200";
br=5;
//cn="COM14"; // Windows
cn="ttymxc2"; // PTU5
ci=2;
HWaccess->dc_openSerial(br,bs,cn,1);
}
}
void CArun::chainControl(void)
{
switch (this->setupStep) {
case SETUP_STEP::INIT:
qCritical() << "CArun: SETUP_STEP::INIT";
this->setupStep = SETUP_STEP::OPEN_SERIAL_PORT;
this->timerChainCtrl->start();
break;
case SETUP_STEP::OPEN_SERIAL_PORT:
qCritical() << "CArun: SETUP_STEP::OPEN_SERIAL_PORT";
this->openSerialPort();
this->setupStep = SETUP_STEP::TEST_OPEN_PORT;
this->timerChainCtrl->start();
break;
case SETUP_STEP::TEST_OPEN_PORT:
qCritical() << "CArun: SETUP_STEP::TEST_OPEN_PORT";
if (this->HWaccess->dc_isPortOpen()) {
this->setupStep = SETUP_STEP::TEST_RESPONSE_REQUEST;
}
else {
qCritical() << "CArun: port is still closed, restarting..";
this->setupStep = SETUP_STEP::INIT;
}
this->timerChainCtrl->start();
break;
case SETUP_STEP::TEST_RESPONSE_REQUEST:
qCritical() << "CArun: SETUP_STEP::TEST_RESPONSE_REQUEST";
this->HWaccess->dc_requTestResponse();
this->setupStep = SETUP_STEP::TEST_RESPONSE_CHECK;
this->timerChainCtrl->start();
break;
case SETUP_STEP::TEST_RESPONSE_CHECK:
qCritical() << "CArun: SETUP_STEP::TEST_RESPONSE_CHECK";
if (this->HWaccess->dc_readAnswTestResponse()) {
// response was correct
this->setupStep = SETUP_STEP::SETUP_AUTOREQEUST;
}
else {
qCritical() << "CArun: got no answer from DC, retry..";
this->setupStep = SETUP_STEP::INIT;
}
this->timerChainCtrl->start();
break;
case SETUP_STEP::SETUP_AUTOREQEUST:
qCritical() << "CArun: SETUP_STEP::SETUP_AUTOREQEUST";
this->HWaccess->dc_autoRequest(1);
this->setupStep = SETUP_STEP::CHECK_VALID_DATA;
this->timerChainCtrl->start(2000);
break;
case SETUP_STEP::CHECK_VALID_DATA:
qCritical() << "CArun: SETUP_STEP::CHECK_VALID_DATA";
if (this->HWaccess->sys_areDCdataValid()) {
qCritical() << "CArun: DC is connected";
// do not start timer again
}
else {
qCritical() << "CArun: auto request is not running, retry...";
this->setupStep = SETUP_STEP::INIT;
this->timerChainCtrl->start();
}
break;
default:
qCritical() << "CArun: invalid setup step";
break;
}
}

58
dCArun/CArun.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef CARUN_H
#define CARUN_H
#include <QObject>
#include <QTimer>
#include <QDebug>
#include <QDateTime>
#include <QPluginLoader>
#include <QDir>
#include "plugin.h"
enum class SETUP_STEP {
INIT,
OPEN_SERIAL_PORT,
TEST_OPEN_PORT,
TEST_RESPONSE_REQUEST,
TEST_RESPONSE_CHECK,
SETUP_AUTOREQEUST,
CHECK_VALID_DATA
};
class DigitalOutputAbstraction;
class CArun : public QObject
{
Q_OBJECT
public:
explicit CArun(QObject *parent = nullptr);
QTimer *timerChainCtrl;
char loadPlugIn(char lade1_entlade2);
QDir plugInDir;
private:
hwinf *HWaccess=nullptr; // global pointer to plugin-class
SETUP_STEP setupStep;
void openSerialPort();
DigitalOutputAbstraction* digitalOutputAbstraction;
signals:
private slots:
void chainControl();
};
#endif // CARUN_H

View File

@ -0,0 +1,170 @@
#include <QFileSystemWatcher>
#include <QFile>
#include <QFileInfo>
#include <QTimer>
#include <QDebug>
#include "DigitalOutputAbstraction.h"
#include "plugin.h"
/**
* this is based on a solution from:
* https://embeddeduse.com/2018/09/18/monitoring-sys-files-qfilesystemwatcher/
*
*/
DigitalOutputAbstraction::DigitalOutputAbstraction(hwinf *dc, QObject *parent)
: QObject(parent)
, dc(dc)
{
this->fileMonitor = new QFileSystemWatcher(this);
connect(this->fileMonitor, &QFileSystemWatcher::fileChanged,
this, &DigitalOutputAbstraction::fileChanged);
qCritical() << "... init DigitalOutputAbstraction";
}
bool DigitalOutputAbstraction::addCCWake(const QString file)
{
// on PTU5: "/sys/class/leds/wakeupctrl_cc/brightness"
if (!QFileInfo::exists(file)) {
qCritical() << " ... create file: " << file;
QFile(file).open(QIODevice::ReadWrite | QIODevice::Text);
}
qCritical() << " ... add file: " << file;
this->ccWakePath = file;
return this->fileMonitor->addPath(file);
}
bool DigitalOutputAbstraction::addCCPower(const QString file)
{
if (!QFileInfo::exists(file)) {
qCritical() << " ... create file: " << file;
QFile(file).open(QIODevice::ReadWrite | QIODevice::Text);
}
qCritical() << " ... add file: " << file;
this->ccPowerPath = file;
return this->fileMonitor->addPath(file);
}
bool DigitalOutputAbstraction::addCCModem(const QString file)
{
if (!QFileInfo::exists(file)) {
qCritical() << " ... create file: " << file;
QFile(file).open(QIODevice::ReadWrite | QIODevice::Text);
}
qCritical() << " ... add file: " << file;
this->modemPowerPath = file;
return this->fileMonitor->addPath(file);
}
void DigitalOutputAbstraction::fileChanged(const QString &path)
{
if (path == this->ccPowerPath) this->private_ccPowerChanged();
if (path == this->ccWakePath) this->private_ccWakeChanged();
if (path == this->modemPowerPath) this->private_modemPowerChanged();
}
void DigitalOutputAbstraction::private_modemPowerChanged()
{
QFile modemPowerFile(this->modemPowerPath);
if (!modemPowerFile.open(QIODevice::ReadOnly)) {
qWarning() << "ERROR: Could not open modemPowerFile " << this->modemPowerPath;
return;
}
auto modemPower = modemPowerFile.readAll();
if (!modemPower.isEmpty()) {
int state = modemPower.at(0);
// qCritical() << "INFO: modemPower = " << state;
switch (state) {
case 0x30: // '0'
qCritical() << "INFO: modemPower -> off";
this->dc->mod_switchWake(false);
this->dc->mod_switchPower(false);
break;
case 0x31: // '1'
qCritical() << "INFO: modemPower -> on";
this->dc->mod_switchWake(true);
this->dc->mod_switchPower(true);
break;
}
}
}
void DigitalOutputAbstraction::private_ccPowerChanged()
{
QFile ccPowerFile(this->ccPowerPath);
if (!ccPowerFile.open(QIODevice::ReadOnly)) {
qWarning() << "ERROR: Could not open ccPowerFile file.";
return;
}
auto ccPower = ccPowerFile.readAll();
if (!ccPower.isEmpty()) {
int state = ccPower.at(0);
auto lambdaOn = [this]() -> void
{
this->dc->credit_switchPower(true);
this->dc->credit_switchWake(true);
};
auto lambdaOff = [this]() -> void
{
this->dc->credit_switchPower(false);
this->dc->credit_switchWake(false);
};
//qCritical() << "INFO: ccPower = " << state;
switch (state) {
case 0x30: // '0'
qCritical() << "INFO: ccPower -> off";
lambdaOff();
break;
case 0x31: // '1'
qCritical() << "INFO: ccPower -> on";
lambdaOn();
break;
case 0x32: // '2'
qCritical() << "INFO: ccPower -> on / off";
lambdaOff();
QTimer::singleShot(500, this, lambdaOn);
break;
}
}
}
void DigitalOutputAbstraction::private_ccWakeChanged()
{
QFile ccWakeFile(this->ccWakePath);
if (!ccWakeFile.open(QIODevice::ReadOnly)) {
qWarning() << "ERROR: Could not open ccWakeFile " << this->ccWakePath;
return;
}
auto ccWake = ccWakeFile.readAll();
if (!ccWake.isEmpty()) {
int state = ccWake.at(0);
//qCritical() << "INFO: ccWake = " << state;
switch (state) {
case 0x30: // '0'
qCritical() << "INFO: ccWake -> sleep";
this->dc->credit_switchWake(true); // switch 'sleep'
break;
case 0x31: // '1'
qCritical() << "INFO: ccWake -> wake";
this->dc->credit_switchWake(false); // switch 'wake'
break;
}
}
}

View File

@ -0,0 +1,37 @@
#ifndef DIGITALOUTPUTABSTRACTION_H
#define DIGITALOUTPUTABSTRACTION_H
#include <QObject>
class hwinf;
class QFileSystemWatcher;
class DigitalOutputAbstraction : public QObject
{
Q_OBJECT
public:
DigitalOutputAbstraction(hwinf *dc, QObject *parent = nullptr);
bool addCCWake(const QString file);
bool addCCPower(const QString file);
bool addCCModem(const QString file);
private:
hwinf *dc;
QFileSystemWatcher *fileMonitor;
QString modemPowerPath;
QString ccPowerPath;
QString ccWakePath;
void fileChanged(const QString &path);
void private_modemPowerChanged();
void private_ccPowerChanged();
void private_ccWakeChanged();
};
#endif // DIGITALOUTPUTABSTRACTION_H

View File

@ -1,5 +1,5 @@
QT += core gui
QT +=widgets serialport
QT += core
QT += serialport
QT +=network
# for TCP-IP
@ -11,8 +11,6 @@ VERSION = "1.0.0"
DESTDIR=$${_PRO_FILE_PWD_}/../build
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
CONFIG += PTU5
@ -25,33 +23,33 @@ INCLUDEPATH += ../include
win32 {
BUILD_DATE=$$system("date /t")
BUILD_TIME=$$system("time /t")
GIT_COMMIT=""
EXTENDED_VERSION=""
} else {
BUILD_DATE=$$system("date +%d-%m-%y")
BUILD_TIME=$$system("date +%H:%M:%S")
GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1")
EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}"
}
GIT_COMMIT=$$system("git log -1 --format=oneline | cut -d' ' -f1")
EXTENDED_VERSION="$${VERSION}-$${GIT_COMMIT}"
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\"
DEFINES+=APP_BUILD_TIME=\\\"$$BUILD_TIME\\\"
DEFINES+=APP_EXTENDED_VERSION=\\\"$$EXTENDED_VERSION\\\"
SOURCES += \
CArun.cpp \
DigitalOutputAbstraction.cpp \
main.cpp \
mainwindow.cpp \
tslib.cpp \
win01_com.cpp \
datei.cpp
HEADERS += \
CArun.h \
DigitalOutputAbstraction.h \
guidefs.h \
mainwindow.h \
stepList.h \
tslib.h \
versionHistory.txt \
win01_com.h \
datei.h \
plugin.h

View File

@ -1,15 +1,14 @@
#include "mainwindow.h"
#include "CArun.h"
//#include "message_handler.h"
#include <QApplication>
int thisisglobal;
#include <QCoreApplication>
int main(int argc, char *argv[])
{
int ret;
QApplication myapp(argc, argv);
QApplication::setApplicationName("CArunGui");
QApplication::setApplicationVersion(APP_VERSION);
QCoreApplication myapp(argc, argv);
QCoreApplication::setOrganizationName("ATB");
QCoreApplication::setApplicationName("CArun");
QCoreApplication::setApplicationVersion(APP_VERSION);
/*
if (!messageHandlerInstalled()) { // change internal qt-QDebug-handling
@ -18,16 +17,9 @@ int main(int argc, char *argv[])
//setDebugLevel(QtMsgType::QtDebugMsg);
}
*/
MainWindow myMainWin;
QSize myMainSize={800, 480}; // breite, höhe, PTU: 800x440
myMainWin.setMinimumSize(myMainSize);
myMainWin.setMaximumSize(myMainSize);
myMainWin.setWindowTitle("CArun_V4.2 run cash agent master lib");
//myMainWin.show();
CArun carun;
ret=myapp.exec();
return ret;
return myapp.exec();
}

View File

@ -1,439 +0,0 @@
#include "mainwindow.h"
char MainWindow::loadPlugIn(char lade1_entlade2)
{
plugInDir.cd("plugins");
QPluginLoader *pluginLoader = new QPluginLoader();
// select system:
//pluginLoader->setFileName("../MasterPlug/libCAmaster.so"); // for suse
//pluginLoader->setFileName("../SlavePlug/libCAslave.so"); // for ptu5
//pluginLoader->setFileName("../../MasterPlug/CAmaster.dll"); // for windows
//pluginLoader->setFileName("CAmaster.dll"); // for windows
pluginLoader->setFileName("/usr/lib/libCAmaster.so"); // for ptu5
if (lade1_entlade2==2)
{
pluginLoader->unload();
return 0;
}
if (!pluginLoader->load())
{
qDebug()<<"cannot load plugin";
} else
qDebug() <<"loaded plugin: " << pluginLoader->fileName();
if (!pluginLoader->isLoaded())
{
qDebug()<<pluginLoader->errorString();
return 0;
}
QObject *plugin = pluginLoader->instance();
if ( plugin == nullptr)
{
// make instance of the root component (which can hold more then one clases)
// also loads the lib if not yet done
qDebug()<<"cannot start instance";
return 0;
}
//int rr=hwapi->giveVal(2); funktioniert :))
//qDebug()<<"got value from plugin"<<rr; funktioniert :))
// aber besser globaler pointer:
// im h-file
// hwinf *hwapi=nullptr; // pointer to plugin-class
HWaccess= qobject_cast<hwinf *>(plugin);
// make instance to class "hwinf" in dll_HWapi.h over "interfaces.h"
qDebug()<<"loadPlugIn, HWAccess: " << HWaccess;
return 0;
}
#define WINCTRMIN 0
// 0 is always the home screen
#define WINCTRMAX 30
// number of needed application screens, up to 255
// All screens must be defined below in mainwindow-class first before increasing the nr
// numbers must be consecutively from 0 always, 0 is the home screen always
#define FORMWIDTH 725
//#define FORMWIDTH 690
// this width is the same for ALL windows
#define FORMHEIGHT 440
// this height is the same for ALL windows
#define NAVIBUTTONHEIGHT 70
#define NAVIBUTTONWIDHT 50
#define HOMEPAGE_BACKGROUND_COLOR "background-color: lightgrey"
#define BUTTON_COLOR "background-color: rgb(160,250,190)"
#define ACTIVE_NAVI_COLOR "background-color: rgb(160,250,190)"
#define DISABL_NAVI_COLOR "background-color: grey"
#define APPPAGE_BACKGROUND_COLOR "background-color: lightgrey"
#define UPDATE_PERIOD_MS 100
// period to call chain steps
#define VENDINGTIMEOUT_MS 30000
// after this time without any operation the program returns to idle state
// time in ms, that means 30.000 gives 30seconds
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
loadPlugIn(1);
// define all working moduls (besides gui) here, call ini and working in chainControl() (~Line 1000)
//mifCard = new T_Mifare(HWaccess); // ganz wichtig: HWaccess an sub-Konstruktor übergeben
// sonst crash bei HW-Zugriff!!!!
//diary = new T_lib_diary(); absturz!!!!!!
//conf = new T_lib_config(HWaccess);
timerChainCtrl = new QTimer(this);
connect(timerChainCtrl, SIGNAL(timeout()), this, SLOT(chainControl()));
timerChainCtrl->setSingleShot(0);
timerChainCtrl->start(UPDATE_PERIOD_MS); // 1000: call every 1000ms
timerVendingTimeout = new QTimer(this);
connect(timerVendingTimeout, SIGNAL(timeout()), this, SLOT(vendingTimeout()));
timerVendingTimeout->setSingleShot(true);
timerVendingTimeout->start(VENDINGTIMEOUT_MS); // in ms
// ##########################################################################################
// für jedes anzuzeigende Fenster eine eigene Groupbox mit eigenem Grid anlegen:
frame01 = new QGroupBox;
frame01->setStyleSheet(APPPAGE_BACKGROUND_COLOR);
frame01->setMinimumSize(FORMWIDTH,FORMHEIGHT);
QVBoxLayout *smallLay01 = new QVBoxLayout;
frame01->setLayout(smallLay01);
// Fensterinhalt aus externer Klasse einfügen:
myFenster01 = new T_winComPort(HWaccess); // HWaccess damit auf das HW-Plugin zugegriffen werden kann, sonst crash
smallLay01->addWidget(myFenster01);
// ##########################################################################################
// draw Mainwindow:
bigGroupbox = new QGroupBox;
bigGroupbox->setStyleSheet("background-color: grey");
bigGroupbox->setMinimumSize(800,480);
// bigLayout = new QVBoxLayout; // navi buttons on bottom side
bigLayout = new QHBoxLayout; // navi buttons right hand
// ##########################################################################################
// add all windows (but display only one)
// display only one: then all windows are shown at the same place
// display more then one: the windows are listed in vertical order
bigLayout->addWidget(frame01);
bigGroupbox->setLayout(bigLayout);
switchScreen(1);
//HideAllWindows();
// ##########################################################################################
// Steuer Leiste
//QHBoxLayout *ButtonLayout = new QHBoxLayout();
QVBoxLayout *ButtonLayout = new QVBoxLayout();
QFont myTabFont;
myTabFont.setPixelSize(26);
pBback = new QPushButton("<"); //b\na\nc\nk");
pBback->setFont(myTabFont);
pBback->setStyleSheet(ACTIVE_NAVI_COLOR);
pBback->setMinimumHeight(NAVIBUTTONHEIGHT);
pBback->setMaximumWidth(NAVIBUTTONWIDHT);
connect(pBback, SIGNAL( clicked() ), myFenster01, SLOT( Nav_back()));
myTabFont.setPixelSize(22);
pBhome = new QPushButton("<<"); //h\no\nm\ne");
pBhome->setFont(myTabFont);
pBhome->setStyleSheet(ACTIVE_NAVI_COLOR);
pBhome->setMinimumHeight(NAVIBUTTONHEIGHT);
pBhome->setMaximumWidth(NAVIBUTTONWIDHT);
connect(pBhome, SIGNAL( clicked() ), myFenster01, SLOT( Nav_home()));
myTabFont.setPixelSize(26);
pBforward = new QPushButton(">"); //n\ne\nx\nt");
pBforward->setFont(myTabFont);
pBforward->setStyleSheet(ACTIVE_NAVI_COLOR);
pBforward->setMinimumHeight(NAVIBUTTONHEIGHT);
pBforward->setMaximumWidth(NAVIBUTTONWIDHT);
connect(pBforward, SIGNAL( clicked() ), myFenster01, SLOT( Nav_next()));
QLabel *buttonSpace = new QLabel(" ");
ButtonLayout->addWidget(pBback);
ButtonLayout->addWidget(buttonSpace);
//ButtonLayout->addWidget(buttonSpace);
ButtonLayout->addWidget(pBhome);
ButtonLayout->addWidget(buttonSpace);
//ButtonLayout->addWidget(buttonSpace);
ButtonLayout->addWidget(pBforward);
QLabel *bottomSpace = new QLabel(" ");
ButtonLayout->addWidget(bottomSpace);
bigLayout->addLayout(ButtonLayout);
setCentralWidget(bigGroupbox);
// AUTOSTART serial transmission
//HWaccess->dc_openSerial(5,"115200","ttyS0",1); // my suse computer
//HWaccess->dc_openSerial(1,"9600","COM5",1); // my suse computer
//HWaccess->dc_openSerial(5,"115200","ttymxc2",1); // ptu5
//HWaccess->dc_autoRequest(true);
//myFenster01->setButtons4autoStart();
//HWaccess->alarm_switchSiren(0); // test
enableNaviButtons(BACKBUTTON,true);
enableNaviButtons(HOMEBUTTON,true);
enableNaviButtons(FORWBUTTON,true);
this->chainIni();
//connect(myFenster02, SIGNAL(quitMyApp()), this, SLOT(close()));
}
MainWindow::~MainWindow()
{
loadPlugIn(2);
}
void MainWindow::HideAllWindows()
{
// vorsicht: Fenster muss oben definiert sein sonst Programmabsturz ohne Kommentar
frame01->setEnabled(false);
frame01->setVisible(false);
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Call Windows
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void MainWindow::switchScreen(uint16_t winNr) // 0...30
{
HideAllWindows();
//qDebug()<<"switch screen to " << winNr;
switch (winNr)
{
case 1:
frame01->setEnabled(true);
frame01->setVisible(true);
break;
default:
break;
}
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Navigation buttons
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void MainWindow::enableNaviButtons(uint8_t switchBitwise)
{
// switchBitwise=0: no change
// bit0,1: enable/disable button "next"
// bit2,3: enable/disable button "home"
// bit4,5: enable/disable button "back"
if (switchBitwise &1)
{
pBforward->setStyleSheet(ACTIVE_NAVI_COLOR);
//pBforward->setText("next");
pBforward->setEnabled(true);
} else
if (switchBitwise &2)
{
pBforward->setStyleSheet(DISABL_NAVI_COLOR);
//pBforward->setText(" ");
pBforward->setEnabled(false);
}
if (switchBitwise &4)
{
pBhome->setStyleSheet(ACTIVE_NAVI_COLOR);
//pBhome->setText("home");
pBhome->setEnabled(true);
} else
if (switchBitwise &8)
{
pBhome->setStyleSheet(DISABL_NAVI_COLOR);
//pBhome->setText(" ");
pBhome->setEnabled(false);
}
if (switchBitwise &16)
{
pBback->setStyleSheet(ACTIVE_NAVI_COLOR);
//pBback->setText("back");
pBback->setEnabled(true);
} else
if (switchBitwise &32)
{
pBback->setStyleSheet(DISABL_NAVI_COLOR);
//pBback->setText(" ");
pBback->setEnabled(false);
}
}
void MainWindow::enableNaviButtons(uint8_t buttonNr, bool enabled)
{
if (buttonNr==1)
{
if (enabled)
{
pBback->setStyleSheet(ACTIVE_NAVI_COLOR);
//pBback->setText("back");
pBback->setEnabled(true);
} else
{
pBback->setStyleSheet(DISABL_NAVI_COLOR);
//pBback->setText(" ");
pBback->setEnabled(false);
}
} else
if (buttonNr==2)
{
if (enabled)
{
pBhome->setStyleSheet(ACTIVE_NAVI_COLOR);
//pBhome->setText("home");
pBhome->setEnabled(true);
} else
{
pBhome->setStyleSheet(DISABL_NAVI_COLOR);
//pBhome->setText(" ");
pBhome->setEnabled(false);
}
} else
if (buttonNr==3)
{
if (enabled)
{
pBforward->setStyleSheet(ACTIVE_NAVI_COLOR);
//pBforward->setText("next");
pBforward->setEnabled(true);
} else
{
pBforward->setStyleSheet(DISABL_NAVI_COLOR);
//pBforward->setText(" ");
pBforward->setEnabled(false);
}
}
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// control work flow by Finite state machine
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
static uint16_t chainCurrentStep, chainNextStep;
static bool chain_stepIni;
void MainWindow::chainIni(void)
{
// called once after power-up by constructor
chainCurrentStep=WCS_STARTSCREEN; // start screen
chainNextStep=chainCurrentStep;
switchScreen(chainCurrentStep);
chain_stepIni=true;
//qDebug()<<"chain ini, call step "<<WCS_STARTUP << " " << chainCurrentStep;
}
void MainWindow::chainControl(void)
{
uint16_t nextScreen=0;
uint8_t useNavi=0;
bool busy=false;
// working step chain:
if (chainCurrentStep != chainNextStep)
{
if (chainNextStep!=WCS_STARTSCREEN)
{
timerVendingTimeout->stop();
timerVendingTimeout->start(VENDINGTIMEOUT_MS);
}
//qDebug()<<"found new sreen";
chainCurrentStep=chainNextStep;
switchScreen(chainCurrentStep);
chain_stepIni=true;
}
if (chainCurrentStep==1)
{
if (chain_stepIni)
busy=myFenster01->work_ini(&nextScreen, &useNavi);
else
busy=myFenster01->working(&nextScreen, &useNavi);
} else
{
// error undefined step
qDebug()<<"error main chain control, wrong step ("<<chainCurrentStep<<") selected";
}
if (chain_stepIni)
{
chain_stepIni=false;
switchScreen(chainCurrentStep); // the mainWindow frame has always the same number as the working step
}
if (nextScreen>0)
{
// call next chain step
//qDebug()<<"chain control: new step selected: "<< nextScreen;
chainNextStep=nextScreen;
}
if (useNavi>0)
{
//qDebug()<<"chain control: navi buttons "<< useNavi;
enableNaviButtons(useNavi);
}
if (busy>0)
{
// reset time-out
timerVendingTimeout->start();
}
}
void MainWindow::vendingTimeout(void)
{
// there was no user operation for 30s so return to start screen
// uint16_t nextScreen=WCS_STARTSCREEN;
// chainNextStep=nextScreen; erstmal stilllegen, stört bei IBN
//qDebug()<<"chain control: vending TO";
timerVendingTimeout->stop();
}

View File

@ -1,72 +0,0 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
#include <QGroupBox>
#include <QStyle>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QDebug>
#include <QPushButton>
#include <QDialog>
#include <QWidget>
#include <QApplication>
#include <QObject>
#include <QDateTime>
#include <QDate>
#include <QTime>
#include <QPluginLoader>
#include <QDir>
#include "plugin.h"
#include "stepList.h"
//#include "stepList.h" // define all working chain steps here
#include "win01_com.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
QPushButton *pBback;
QPushButton *pBhome;
QPushButton *pBforward;
QGroupBox *bigGroupbox;
QHBoxLayout *bigLayout;
QTimer *timerChainCtrl;
QTimer *timerVendingTimeout;
QGroupBox *frame01;
T_winComPort *myFenster01;
void HideAllWindows();
void switchScreen(uint16_t winNr);
char loadPlugIn(char lade1_entlade2);
QDir plugInDir;
void chainIni(void);
public:
hwinf *HWaccess=nullptr; // global pointer to plugin-class
MainWindow(QWidget *parent = nullptr);
~MainWindow();
#define BACKBUTTON 1
#define HOMEBUTTON 2
#define FORWBUTTON 3
void enableNaviButtons(uint8_t buttonNr, bool enabled);
void enableNaviButtons(uint8_t switchBitwise);
private slots:
void chainControl();
void vendingTimeout();
};
#endif // MAINWINDOW_H

View File

@ -1,210 +0,0 @@
#ifndef STEPLIST_H
#define STEPLIST_H
// define all working chain steps
// every FSM-Step get's a frame in MainWindow with the same number and a self-designed GUI
// labels are used for switchScreen( label=nr );
// numbers are important: e.g. number 3 calls frame3 and frame3 includes subClass "T_fenster03"
// so best solution: label = same name like class (in example: Fenster03). Label is fixed bound to number, never change!
// numbers are fixed assosiated with the function (e.g. ComPort), can't be changed.
// but screen order can be called in step chain randomly
// Windownumbers for certain function, never change
#define PAGE_COMPORT 1
#define PAGE_SERVICEMAIN 2
#define PAGE_TIMEDATEVERSION 3
#define PAGE_MACHINESTATUS 4
#define PAGE_CHECKDOORS 5
#define PAGE_PRINTER 6
#define PAGE_COINMECHANIC 7
#define PAGE_MIFARE 8
#define PAGE_MODEM 9
#define PAGE_COINPAYMENT 10
#define PAGE_VAULTRECORD 11
#define PAGE_BOOTLOADER 12
#define PAGE_PROG_JSON 13
#define PAGE_COINCHANGER 14
#define PAGE_BILLREADER 15
#define PAGE_NEXT16 16
#define PAGE_NEXT17 17
#define PAGE_NEXT18 18
#define PAGE_NEXT19 19
#define PAGE_NEXT20 20
// fix: customize:
#define WCS_STARTSCREEN PAGE_COMPORT
// PAGE_COMPORT:
#define WCS_WIN01BAK PAGE_COMPORT
#define WCS_WIN01MID PAGE_SERVICEMAIN
#define WCS_WIN01FWD PAGE_SERVICEMAIN
// PAGE_SERVICEMAIN:
#define WCS_WIN02BAK PAGE_COMPORT
#define WCS_WIN02MID PAGE_SERVICEMAIN
#define WCS_WIN02FWD PAGE_TIMEDATEVERSION
// PAGE_TIMEDATEVERSION:
#define WCS_WIN03BAK PAGE_SERVICEMAIN
#define WCS_WIN03MID PAGE_SERVICEMAIN
#define WCS_WIN03FWD PAGE_MACHINESTATUS
// PAGE_MACHINESTATUS:
#define WCS_WIN04BAK PAGE_TIMEDATEVERSION
#define WCS_WIN04MID PAGE_SERVICEMAIN
#define WCS_WIN04FWD PAGE_CHECKDOORS
// PAGE_CHECKDOORS:
#define WCS_WIN05BAK PAGE_MACHINESTATUS
#define WCS_WIN05MID PAGE_SERVICEMAIN
#define WCS_WIN05FWD PAGE_COINMECHANIC
// PAGE_COINMECHANIC:
#define WCS_WIN07BAK PAGE_CHECKDOORS
#define WCS_WIN07MID PAGE_SERVICEMAIN
#define WCS_WIN07FWD PAGE_COINPAYMENT
// PAGE_COINPAYMENT:
#define WCS_WIN10BAK PAGE_COINMECHANIC
#define WCS_WIN10MID PAGE_SERVICEMAIN
#define WCS_WIN10FWD PAGE_COINCHANGER
// PAGE_COINCHANGER:
#define WCS_WIN14BAK PAGE_COINPAYMENT
#define WCS_WIN14MID PAGE_SERVICEMAIN
#define WCS_WIN14FWD PAGE_BILLREADER
// PAGE_BILLREADER:
#define WCS_WIN15BAK PAGE_COINCHANGER
#define WCS_WIN15MID PAGE_SERVICEMAIN
#define WCS_WIN15FWD PAGE_PRINTER
// PAGE_PRINTER:
#define WCS_WIN06BAK PAGE_BILLREADER
#define WCS_WIN06MID PAGE_SERVICEMAIN
#define WCS_WIN06FWD PAGE_MIFARE
// PAGE_MIFARE:
#define WCS_WIN08BAK PAGE_PRINTER
#define WCS_WIN08MID PAGE_SERVICEMAIN
#define WCS_WIN08FWD PAGE_MODEM
// PAGE_MODEM:
#define WCS_WIN09BAK PAGE_MIFARE
#define WCS_WIN09MID PAGE_SERVICEMAIN
#define WCS_WIN09FWD PAGE_VAULTRECORD
// PAGE_VAULTRECORD:
#define WCS_WIN11BAK PAGE_MODEM
#define WCS_WIN11MID PAGE_SERVICEMAIN
#define WCS_WIN11FWD PAGE_PROG_JSON
// PAGE_PROG_JSON:
#define WCS_WIN13BAK PAGE_VAULTRECORD
#define WCS_WIN13MID PAGE_SERVICEMAIN
#define WCS_WIN13FWD PAGE_BOOTLOADER
// PAGE_BOOTLOADER:
#define WCS_WIN12BAK PAGE_PROG_JSON
#define WCS_WIN12MID PAGE_SERVICEMAIN
#define WCS_WIN12FWD PAGE_NEXT16
// PAGE_NEXT16
#define WCS_WIN16BAK PAGE_BOOTLOADER
#define WCS_WIN16MID PAGE_SERVICEMAIN
#define WCS_WIN16FWD PAGE_NEXT17
// PAGE_NEXT17
#define WCS_WIN17BAK PAGE_NEXT16
#define WCS_WIN17MID PAGE_SERVICEMAIN
#define WCS_WIN17FWD PAGE_NEXT18
// PAGE_NEXT18
#define WCS_WIN18BAK PAGE_NEXT17
#define WCS_WIN18MID PAGE_SERVICEMAIN
#define WCS_WIN18FWD PAGE_NEXT19
// PAGE_NEXT19
#define WCS_WIN19BAK PAGE_NEXT18
#define WCS_WIN19MID PAGE_SERVICEMAIN
#define WCS_WIN19FWD PAGE_NEXT20
// PAGE_NEXT20
#define WCS_WIN20BAK PAGE_NEXT19
#define WCS_WIN20MID PAGE_SERVICEMAIN
#define WCS_WIN20FWD PAGE_SERVICEMAIN
// just for Template
#define WCS_WIN99BAK PAGE_SERVICEMAIN
#define WCS_WIN99MID PAGE_SERVICEMAIN
#define WCS_WIN99FWD PAGE_SERVICEMAIN
#define WIN02_LABEL_SHORT01 " Status"
#define WCS_WIN02SHORT01 PAGE_MACHINESTATUS
#define WIN02_LABEL_SHORT02 " Doors "
#define WCS_WIN02SHORT02 PAGE_CHECKDOORS
#define WIN02_LABEL_SHORT03 "Coin mech"
#define WCS_WIN02SHORT03 PAGE_COINMECHANIC
#define WIN02_LABEL_SHORT04 "Payment"
#define WCS_WIN02SHORT04 PAGE_COINPAYMENT
#define WIN02_LABEL_SHORT05 "Changer"
#define WCS_WIN02SHORT05 PAGE_COINCHANGER
#define WIN02_LABEL_SHORT06 " Bill "
#define WCS_WIN02SHORT06 PAGE_BILLREADER
#define WIN02_LABEL_SHORT07 "Printer"
#define WCS_WIN02SHORT07 PAGE_PRINTER
#define WIN02_LABEL_SHORT08 "Program"
#define WCS_WIN02SHORT08 PAGE_VAULTRECORD
#define WIN02_LABEL_SHORT09 " "
#define WCS_WIN02SHORT09 PAGE_SERVICEMAIN
#define WIN02_LABEL_SHORT10 " "
#define WCS_WIN02SHORT10 PAGE_SERVICEMAIN
// set needed navigation buttons, use | to combine more then one:
#define SWITCH_NEXT_ON 1
#define SWITCH_NEXT_OFF 2
#define SWITCH_HOME_ON 4
#define SWITCH_HOME_OFF 8
#define SWITCH_BACK_ON 16
#define SWITCH_BACK_OFF 32
// example: *useNavi=SWITCH_BACK_ON; // change only this one, or set all:
// *useNavi=SWITCH_BACK_OFF | SWITCH_HOME_OFF | SWITCH_NEXT_ON;
// some defines for Widget design:
#define TS_VALUEBOX_FRAMESTYLE 0x0032
#define TS_VALUEBOX_LINEWIDTH 3
//genDatPort->setFrameStyle(QFrame::Panel | QFrame::Sunken ); funktioniert aber gibt unverständliche Warnung
// QFrame::Panel = 0x0002 QFrame::Sunken=0x0030
//genDatPort->setFrameStyle(0x0032); // funktioniert und gibt keine Warnung
//genDatPort->setFrameStyle(TS_VALUEBOX_FRAMESTYLE); // funktioniert und gibt keine Warnung
#define TS_LED_FRAMESTYLE 0x0031
// QFrame::Box | QFrame::Sunken
#endif // STEPLIST_H

View File

@ -1,609 +0,0 @@
#include "win01_com.h"
#include "stepList.h" // define all working chain steps here
#include "datei.h"
//#include "globVars.h"
// %%%%%%%%%%%%%%%%%%%% TabComPort
Console::Console(QWidget *parent) : QPlainTextEdit(parent)
{
document()->setMaximumBlockCount(100);
QPalette p = palette();
p.setColor(QPalette::Base, Qt::black); //geht nicht weil untergrund schon farbig
p.setColor(QPalette::Text, Qt::blue);
setPalette(p);
}
void Console::putData(const QByteArray &data)
{
insertPlainText(data);
insertPlainText("\n");
QScrollBar *bar = verticalScrollBar();
bar->setValue(bar->maximum());
}
void Console::putText(QString text)
{
insertPlainText(text);
insertPlainText("\n");
QScrollBar *bar = verticalScrollBar();
bar->setValue(bar->maximum());
}
void T_winComPort::subPortInfo()
{
// Port Info Anzeige Feld, 2. Zeile links
QStringList myStringList;
QStringList comboPortList;
const auto infos = QSerialPortInfo::availablePorts();
for (const QSerialPortInfo &info : infos)
{
myStringList.append(QObject::tr(" \n Port: ") + info.portName() );
myStringList.append(QObject::tr("Location: ") + info.systemLocation()); // + "\n");
myStringList.append(QObject::tr("Description: ") + info.description() );
myStringList.append(QObject::tr("Manufacturer: ") + info.manufacturer());
myStringList.append(QObject::tr("Serial number: ") + info.serialNumber());
myStringList.append (QObject::tr("Vendor Id: ") + QString::number(info.vendorIdentifier(), 16));
myStringList.append(QObject::tr("Product Id: ") +QString::number(info.productIdentifier(), 16));
//myStringList.append(QObject::tr("Busy: ") + (info.isBusy() ? QObject::tr("Yes") : QObject::tr("No")));
comboPortList.append(info.portName()); // wenn Comport im System vorhanden dann in die Liste eintragen
}
QListWidget *myListWidget = new QListWidget;
myListWidget->insertItems(0, myStringList);
myListWidget->setMaximumWidth(250);
myTabComLayout->addWidget(myListWidget,1,0);
// ComboBox Comport Nr:
CB_portSel = new QComboBox();
CB_portSel->addItems(comboPortList); // string Liste mit addItems (s am Schluss) !
CB_portSel->setMinimumHeight(30);
CB_portSel->setMaximumWidth(150);
QFont myCBfont;
//myCBfont.setBold(true);
myCBfont.setPixelSize(15);
CB_portSel->setFont(myCBfont);
CB_portSel->setCurrentIndex(2); // default 3. Comport in der Liste = ttymxc2 in PTU5
myTabComLayout->addWidget(CB_portSel, 4,0);
}
void T_winComPort::callOpenSerial()
{
// Taste Connect wurde gedrückt, eine Klasse/einen Slot aus einer übergeordneten Klasse:
// openSerialPort();
// kann man nicht aufrufen. deshalb: speichere ComPort, Baudrate und Startbefehl global.
// Von dort wird mit einem zyklischen Timer ausgelesen
int br, ci;
QString bs, cn;
//br=CB_baudSel->currentIndex();
//bs=CB_baudSel->currentText();
br=5;
bs="115200";
cn=CB_portSel->currentText();
ci=CB_portSel->currentIndex();
// aktuell: br=5 bs=115200 cn=0 (=Com5)
//epi_setSerial(5,"115200","COM5",1);
// epi_setSerial(br, bs, cn, 1);
// new: save values for next time
QByteArray myBA, tmpBA;
myBA.clear(); tmpBA.clear();
myBA.append('s'); // start sign, not used
myBA.append(FILESEPERATOR);
tmpBA.setNum(br,10);
myBA.append(tmpBA);
myBA.append(FILESEPERATOR);
myBA.append(bs.toLatin1());
myBA.append(FILESEPERATOR);
myBA.append(cn.toLatin1());
myBA.append(FILESEPERATOR);
tmpBA.clear();
tmpBA.setNum(ci,10);
myBA.append(tmpBA);
myBA.append(FILESEPERATOR);
datei_clearFile(FILENAME_COMPORT);
datei_writeToFile(FILENAME_COMPORT, myBA);
qDebug() << "winComPort opening serial with: " << br << " " << bs << " " << cn;
HWaccess->dc_openSerial(br, bs, cn, 1);// same function with hwapi
// void dc_openSerial(int BaudNr, QString BaudStr, QString ComName, uint8_t connect)
// BaudNr: 0:1200 1:9600 2:19200 3:38400 4:57600 5:115200
// BaudStr: for exapmle "19200"
// ComName: for example "COM48"
// connect: 0, 1
emit connectButtonPressed();
}
void T_winComPort::callCloseSerial()
{
HWaccess->dc_closeSerial();
// epi_closeSerial(); // same function without hwapi
emit closeButtonPressed();
}
void T_winComPort::callAutoSend()
{
if (AutSendButton->isChecked())
{
HWaccess->dc_autoRequest(1);
emit autoSendButtonIsOn();
} else
{
HWaccess->dc_autoRequest(0);
emit autoSendButtonIsOff();
}
}
void T_winComPort::callRefresh(void)
{
subPortInfo();
}
void T_winComPort::callConnectToggle()
{
if (connectButton->isChecked())
{
//qDebug() << "down";
callOpenSerial();
} else
{
//qDebug() << "released";
callCloseSerial();
}
}
void T_winComPort::getDcTestRS232()
{
//qDebug() << "request test response...";
HWaccess->dc_requTestResponse();
}
void T_winComPort::newBaud(void)
{
qDebug() << "new baud selected...";
}
void T_winComPort::setButtons4autoStart()
{
connectButton->setEnabled(true);
connectButton->setDown(true);
connectButton->setChecked(true);
AutSendButton->setEnabled(true);
AutSendButton->setDown(true);
AutSendButton->setChecked(true);
}
T_winComPort::T_winComPort(hwinf *HWaccess, QWidget *parent) : QWidget(parent)
{
this->HWaccess = HWaccess;
myTabComLayout = new QGridLayout;
//QGridLayout *myGridLayout = new QGridLayout();
// Überschrift linke Spalte
QLabel *portListLabel2 = new QLabel(tr("in System available Ports:"));
myTabComLayout->addWidget(portListLabel2, 0,0);
// Überschrift rechte Spalte
QLabel *lab_headlineR = new QLabel(tr("Serial traffic:"));
myTabComLayout->addWidget(lab_headlineR, 0, 1);
subPortInfo();
// sende-empfangs-Rohdaten-Fenster, 2. Zeile rechts
myDiagWindow = new Console();
myDiagWindow->setReadOnly(true);
myDiagWindow->setEnabled(true);
//myDiagWindow->setLocalEchoEnabled(p.localEchoEnabled);
//myDiagWindow->setMinimumWidth(300);
//myDiagWindow->putData("ongoing serial traffic: ");
myTabComLayout->addWidget(myDiagWindow, 1,1);
// links:
// refresh button:
refreshButton = new QPushButton(tr("&refresh"));
refreshButton->setCheckable(false); // true = toggle button
refreshButton->setAutoDefault(false); // beim start aus
//refreshButton->setMaximumWidth(90);
myTabComLayout->addWidget(refreshButton, 2,0);
//connect(refreshButton, &QAbstractButton::clicked, this, &T_fenster01::callRefresh);
connect(refreshButton, SIGNAL(clicked()), this, SLOT(callRefresh()));
QLabel *Label3 = new QLabel(tr("Port:"));
myTabComLayout->addWidget(Label3, 3,0);
QLabel *Label4 = new QLabel(tr("Baud:"));
myTabComLayout->addWidget(Label4, 5,0);
// ComboBox Baudrate:
QFont my2CBfont;
//my2CBfont.setBold(true);
my2CBfont.setPixelSize(15);
/*
CB_baudSel = new QComboBox();
CB_baudSel->addItem(tr("1200"));
CB_baudSel->addItem(tr("9600"));
CB_baudSel->addItem(tr("19200"));
CB_baudSel->addItem(tr("38400"));
CB_baudSel->addItem(tr("57600"));
CB_baudSel->addItem(tr("115200"));
CB_baudSel->setMinimumHeight(30);
CB_baudSel->setMaximumWidth(150);
CB_baudSel->setFont(my2CBfont);
CB_baudSel->setCurrentIndex(5); // default 115k baud
//CB_baudSel->setCurrentIndex(1); // default 9600 baud
myTabComLayout->addWidget(CB_baudSel, 6,0);
//connect(CB_baudSel, SIGNAL(currentIndexChanged(int)), this, SLOT(newBaud()));
connect(CB_baudSel, SIGNAL(currentIndexChanged(int)), this, SLOT(newBaud()));
*/
// Statuszeile COM Port (serial Port)
LabelComState = new QLabel(tr("not connected"));
myTabComLayout->addWidget(LabelComState, 7,0);
// Connect button:
connectButton = new QPushButton(tr("&Connect"));
connectButton->setCheckable(true); // true = toggle button
connectButton->setAutoDefault(true); // beim start ein
connectButton->setMaximumWidth(90);
connectButton->setMinimumHeight(50);
myTabComLayout->addWidget(connectButton, 8,0);
//connect(connectButton, &QAbstractButton::clicked, this, &T_fenster01::callConnectToggle);
connect(connectButton, SIGNAL(clicked()), this, SLOT(callConnectToggle()));
// rechts:
// test serial line:
TestButton = new QPushButton(tr("test Connection"));
TestButton->setMaximumWidth(150);
myTabComLayout->addWidget(TestButton,2,1);
TestButton->setCheckable(false); // true = toggle button
TestButton->setAutoDefault(false); // beim start aus
// connect(TestButton, &QAbstractButton::clicked, this, &T_fenster01::getDcTestRS232);
connect(TestButton, SIGNAL(clicked()), this, SLOT(getDcTestRS232()));
// I Statuszeile Handshakes (serial Control) flow.cpp
// geht überhaupt was raus? kommt überhaupt was zurück?
//LabelHandshakes = new QLabel(tr("control line"));
LabelHandshakes = new QLabel("HS"); // not used
myTabComLayout->addWidget(LabelHandshakes, 3,1);
// II Statuszeile Auswertung der SlaveResponse (serial Frame, CRC usw) (prot.cpp)
LabelRecieveFrame = new QLabel(tr("slave receive"));
myTabComLayout->addWidget(LabelRecieveFrame, 4,1);
// III Anzeige der Slave-Results (Datif)
LabelResults = new QLabel(tr("results line"));
myTabComLayout->addWidget(LabelResults, 5,1);
// IV Statuszeile Sende- und Empfangsdaten brauchbar? (Datif)
LabelDataState = new QLabel(tr("datif line"));
myTabComLayout->addWidget(LabelDataState, 6,1);
// V
LabelDatif = new QLabel(tr("datif line"));
myTabComLayout->addWidget(LabelDatif, 7,1);
// Autosend:
AutSendButton = new QPushButton(tr("&Automatic reading")); // &A --> also keycode Alt-A possible
//AutSendButton->setMaximumWidth(90);
myTabComLayout->addWidget(AutSendButton,8,1);
AutSendButton->setCheckable(true); // true = toggle button
AutSendButton->setAutoDefault(true); // beim start aus
AutSendButton->setMinimumHeight(50);
// connect(AutSendButton, &QAbstractButton::clicked, this, &T_fenster01::callAutoSend);
connect(AutSendButton, SIGNAL(clicked()), this, SLOT(callAutoSend()));
setLayout(myTabComLayout);
myNextStep=0;
myStep=0;
callConnectToggle();
callAutoSend();
myTO = new QTimer();
myTO->setSingleShot(true);
myTO->start(2000);
}
// not needed:
T_winComPort::~T_winComPort()
{
close();
}
void T_winComPort::Nav_back(void)
{
myNextStep=WCS_WIN01BAK;
}
void T_winComPort::Nav_home(void)
{
myNextStep=WCS_WIN01MID;
}
void T_winComPort::Nav_next(void)
{
myNextStep=WCS_WIN01FWD;
}
bool T_winComPort::work_ini(uint16_t *nextScreen, uint8_t *useNavi)
{
// one state of the vending/operating FSM
// called ONE time after selecting this state (initialization)
// useNavi=0: no change
// bit0,1: enable/disable button "next"
// bit2,3: enable/disable button "home"
// bit4,5: enable/disable button "back"
*nextScreen=0; // needed 0=no change
// *useNavi=SWITCH_BACK_OFF | SWITCH_HOME_OFF | SWITCH_NEXT_ON;
*useNavi=SWITCH_BACK_OFF | SWITCH_HOME_OFF | SWITCH_NEXT_OFF; // bei CArun alle aus
return false;
}
bool T_winComPort::working(uint16_t *nextScreen, uint8_t *useNavi)
{
// one state of the vending/operating FSM
// called cyclic until this state changes intentionally to another state
// display informations for human operator, react on operators inputs or wait for payment media
// useNavi=0: no change
// bit0,1: enable/disable button "next"
// bit2,3: enable/disable button "home"
// bit4,5: enable/disable button "back"
QString bs, cn;
int br, ci;
this->updateGui();
*nextScreen=0; // 0=no change
*useNavi=0;
if (myStep==0)
{
// load and use last settings: --------------------
QByteArray myBA;
myBA=datei_readFromFile(FILENAME_COMPORT);
if (myBA.length()>0)
{
bs=csv_getEntryAsString(myBA,0); // read the 's' war 2!??
br=csv_getEntryAsInt(myBA,1); // z.B. 5 (5.Eintrag in der Baud-Liste)
bs=csv_getEntryAsString(myBA,2); // z.B 115200
cn=csv_getEntryAsString(myBA,3); // z.B. COM9
ci=csv_getEntryAsInt(myBA,4); // Eintragsnummer in COM-Fenster
HWaccess->dc_openSerial(br,bs,cn,1);
CB_portSel->setCurrentIndex(ci); // den Port aus der Datei hier vorgeben
connectButton->setChecked(true); // connect Taste "druecken"
} else
{
// open with default settings
qDebug()<<"CArunGui: open serial with default values";
bs="115200";
br=5;
//cn="COM14"; // Windows
cn="ttymxc2"; // PTU5
ci=2;
HWaccess->dc_openSerial(br,bs,cn,1);
}
myTO->start(100); // restart
myStep++;
} else
if (myStep==1)
{
if (!myTO->isActive())
{
if (HWaccess->dc_isPortOpen())
{
myStep++;
} else
{
myStep=6; // 13.12.23: start Autoconnect cycle
qDebug()<<"CArunGui: port is still closed, restarting..";
}
myTO->start(100);
}
} else
if (myStep==2)
{
if (!myTO->isActive())
{
HWaccess->dc_requTestResponse();
myStep++;
myTO->start(100);
}
} else
if (myStep==3)
{
if (!myTO->isActive())
{
if (HWaccess->dc_readAnswTestResponse())
myStep++; // response was correct
else
{
myStep=6; // 13.12.23: start Autoconnect cycle
qDebug()<<"CArunGui: got no answer from DC, retry..";
}
myTO->start(100);
}
} else
if (myStep==4)
{
HWaccess->dc_autoRequest(1);
AutSendButton->setChecked(true); // taste "druecken"
myStep++;
myTO->start(2000);
} else
if (myStep==5)
{
if (!myTO->isActive())
{
if (HWaccess->sys_areDCdataValid())
{
qDebug()<<"CArunGui: DC is connected";
myStep=7; // OK, connection is up and running
} else
{
qDebug()<<"CArunGui: auto request is not running, retry...";
myStep++;
myTO->start(100);
}
}
} else
if (myStep==6)
{
// restart autoconnect cycle
myTO->start(100); // restart
myStep=0;
} else
if (myStep==7)
{
// stay here, DC connection is up and running
} else
{
}
if (myNextStep)
{
*nextScreen=myNextStep;
myNextStep=0;
}
return false;
}
void T_winComPort::updateGui(void)
{
QByteArray myBA;
QString ms;
ms=HWaccess->dc_getTxt4RsDiagWin();
if (ms.length()>1) // sonst ständig scrolling
{
myDiagWindow->putText(ms);
HWaccess->dc_clrTxt4RsDiagWin();
}
ms=HWaccess->dc_get2ndTxt4RsDiagWin();
if (ms.length()>1) // sonst ständig scrolling
{
myDiagWindow->putText(ms);
HWaccess->dc_clr2ndTxt4RsDiagWin();
}
// state of the COM Port (open, closed)
ms=HWaccess->dc_getSerialState();
if (ms.length()>1) // sonst ständig scrolling
{
LabelComState->setText(ms);
}
// --------------------------------------------------------------------------
// I Statuszeile Handshakes (serial Control)
ms=HWaccess->dc_getTxt4HsStateLine();
if (!connectButton->isChecked())
ms="";
if (ms.length()>1) // sonst ständig scrolling
{
LabelHandshakes->setText(ms);
HWaccess->dc_clrTxt4HsStateLine();
// clear to avoid multiple displaying
}
// II Master receive state (empfangenes Telgramm OK? crc? length? )
// Statuszeile Auswertung der SlaveResponse (serial Frame, CRC usw) (prot.cpp)
ms=HWaccess->dc_getTxt4masterStateLine();
if (!connectButton->isChecked())
ms="---";
if (ms.length()>1) // sonst ständig scrolling
{
LabelRecieveFrame->setText(ms);
HWaccess->dc_clrTxt4masterStateLine();
}
// III Slave receive (from Master) OK? if then show results, if not then show errors
// entweder Empfangsfehler anzeigen (crc? length?) oder result OUT-OK, OUT_ERR, IN_OK, IN_ERR
// Hintergrund: wenn der Slave Fehler im Master-Telegramm gefunden hat, dann kann er es auch
// nicht verwenden und nichts ausgeben oder einlesen
ms=HWaccess->dc_getTxt4resultStateLine();
if (!connectButton->isChecked())
ms="---";
if (ms.length()>1) // sonst ständig scrolling
{
LabelResults->setText(ms);
HWaccess->dc_clrTxt4resultStateLine();
}
// IV Statuszeile Empfangsdaten
ms=HWaccess->dc_getdataStateLine();
if (!connectButton->isChecked())
ms="---";
if (ms.length()>1) // sonst ständig scrolling
{
LabelDataState->setText(ms);
HWaccess->dc_clrTxt4dataStateLine();
// clear to avoid multiple displaying
}
// 5. Zeile: Datif Ergebnis, Daten brauchbar?
ms=HWaccess->dc_getdatifLine();
if (!connectButton->isChecked())
ms="---";
if (ms.length()>1) // sonst ständig scrolling
{
LabelDatif->setText(ms);
HWaccess->dc_clrTxt4datifLine();
}
// -----------------------------------------------------------------------------
}

View File

@ -1,107 +0,0 @@
#ifndef WINCOMPORT_H
#define WINCOMPORT_H
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QObject>
#include <QTimer>
#include <QDebug>
#include <QTabWidget>
#include <QScrollBar>
#include <QPlainTextEdit>
#include <QComboBox>
#include <QLabel>
#include <QScrollArea>
#include <QSerialPortInfo>
#include <QWidget>
#include <QListWidget>
#include <QGroupBox>
#include <QPushButton>
#include <QRadioButton>
//#include "tslib.h"
//#include "stepList.h" // define all working chain steps here
//#include "datei.h"
#include "plugin.h"
//#include "globVars.h"
class Console : public QPlainTextEdit
{
Q_OBJECT
public:
explicit Console(QWidget *parent = nullptr);
void putData(const QByteArray &data);
void putText(QString text);
};
class T_winComPort : public QWidget // former TabComport
{
Q_OBJECT
Console *myDiagWindow; // Ausgabefenster
QComboBox *CB_portSel;
//QComboBox *CB_baudSel;
QPushButton *connectButton;
QPushButton *AutSendButton;
QPushButton *TestButton;
QPushButton *refreshButton;
QLabel *LabelComState; // Statusanzeige
QLabel *LabelPort;
QLabel *LabelHandshakes;
QLabel *LabelRecieveFrame;
QLabel *LabelResults;
QLabel *LabelDataState;
QLabel *LabelDatif;
QGridLayout *myTabComLayout;
void subPortInfo();
hwinf *HWaccess;
void updateGui(void);
uint16_t myNextStep;
uint8_t myStep;
QTimer *myTO;
private slots:
void callOpenSerial();
void callCloseSerial();
void callAutoSend();
//void tabComTime100ms();
void callConnectToggle();
void getDcTestRS232();
void callRefresh(void);
public:
explicit T_winComPort(hwinf *HWaccess = nullptr, QWidget *parent = nullptr);
bool work_ini(uint16_t *nextScreen, uint8_t *useNavi);
// useNavi=0: no change
// bit0,1: enable/disable button "next"
// bit2,3: enable/disable button "home"
// bit4,5: enable/disable button "back"
bool working (uint16_t *nextScreen, uint8_t *useNavi);
~T_winComPort();
void writeRSdiagBytes(const QByteArray &bytarray);
void writeRSdiagText(QString text);
void writeComState(const QString text);
void writeDataState(const QString text);
void setButtons4autoStart();
signals:
void connectButtonPressed();
void closeButtonPressed();
void autoSendButtonIsOn();
void autoSendButtonIsOff();
private slots:
void newBaud(void); // just for test
public slots:
void Nav_back(void);
void Nav_home(void);
void Nav_next(void);
};
#endif

View File

@ -3,10 +3,11 @@
#ifndef SER_H
#define SER_H
#include <stdint.h>
#include <QMainWindow>
#include <QObject>
//#include <QString>
#include <QTimer>
#include <QSerialPort>
#include <QVector>
#include "tslib.h"
#include "controlBus.h"
#include "interfaces.h"
@ -32,6 +33,8 @@ class T_com : public QObject //, public QPlainTextEdit
// QSerialPort *CatSerial = nullptr;
QSerialPort *CatSerial;
uint32_t writeCount = 0;
//char oeffneSerialPort();
char open_Serial_Port();
void closeSerialPort();
@ -61,6 +64,8 @@ public:
bool readFromSerial(QByteArray &data, uint16_t &sendLength);
// retval: true: data available
uint32_t getWriteCount() { return writeCount; }
/*
uint8_t getAllPortPins(void);
// rs232pins: all signals bitwise coded in one byte:

View File

@ -161,11 +161,16 @@ class T_datif : public QObject
// blockNr=transmitted in WRITEADDRESS low byte
int datif_noResponseCtr;
int datif_nowNewDyns;
int datif_nowNewStats;
T_prot *myDCIF;
QTimer *datif_trigger;
uint8_t selectedSlaveAddr;
bool waitForTestResponse = false;
uint32_t readCount = 0;
private slots:
char datif_cycleSend();
void StoredRecData();

37
include/download_thread.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef DOWNLOAD_THREAD_H_INCLUDED
#define DOWNLOAD_THREAD_H_INCLUDED
#include <QThread>
#include <QString>
#include <QByteArray>
class hwinf;
class DownloadThread : public QThread {
Q_OBJECT
public:
enum class DownloadResult {OK, ERROR, TIMEOUT, NOP};
DownloadThread(hwinf *hw);
~DownloadThread();
protected:
// download thread does not have a running event queue, and therefore
// no slots. signals work the usual way.
void run() override;
private:
DownloadResult sendStatus(int ret) const;
DownloadResult sendNextAddress(int bNum) const;
DownloadResult sendNextDataBlock(QByteArray const &binary, int bNum) const;
bool startBootloader() const;
bool stopBootloader() const;
QByteArray loadBinaryDCFile(QString dcFileName) const;
bool resetDeviceController() const;
DownloadResult dcDownloadBinary(QByteArray const &b) const;
hwinf *m_hw;
QString m_fileToDownload;
};
#endif // DOWNLOAD_THREAD_H_INCLUDED

92
include/dump.txt Executable file
View File

@ -0,0 +1,92 @@
/*
void incTextBuffer(void)
{
runProc_prnSeqNr++;
runProc_pointPrnTxt=0;
if (runProc_prnSeqNr>127)
runProc_prnSeqNr=127;
runProc_prnCmdSeq[runProc_pointPrnCmd]=1;
runProc_prnCmdPara[runProc_pointPrnCmd++]=runProc_prnSeqNr;
}*/
/*
void T_runProc::subAppendNxtTxt(char *textLine)
{
// append given text to current sequence, respect max. sequ.length
// also send a command "print text buffer nn" ==1 once for each buffer
//static uint8_t runProc_prnCmdSeq[512];
//static uint8_t runProc_prnCmdPara[512];
//static uint16_t runProc_pointPrnCmd;
int sl=strlen(textLine);
if (sl>1024) sl=1024;
textLine[sl]=0;
if (runProc_prnSeqNr==0 && runProc_pointPrnTxt<3)
{
// then this is the very first text entry
// store command to print this buffer
runProc_prnCmdSeq[runProc_pointPrnCmd]=1;
runProc_prnCmdPara[runProc_pointPrnCmd++]=runProc_prnSeqNr;
}
if ( (runProc_pointPrnTxt + sl) > 1023)
{
incTextBuffer();
}
runProc_prnTextSeq[runProc_prnSeqNr].append(textLine);
//for (nn=0; nn<sl; nn++)
//{
//runProc_prnTextSeq[runProc_prnSeqNr][runProc_pointPrnTxt+nn]=textLine[nn];
//}
}*/
// qCritical() << "emitting signal payCancelled";
// emit runProc_payCancelled();
/*
// gabs bei Szeged, jetzt nicht mehr:
if (payInProg==8)
{
// coin checker faulty, cannot start
if (hwapi_paymentStarted==1)
{
hwapi_paymentStarted=90; // stop due to error
qCritical() << "emitting signal coinCollectionAborted 1";
emit runProc_coinCollectionAborted();
//sendFDcmd_set(156, 0,0, 2,0,0,0); // cancel payment
}
return 10; // error cannot start
}*/
/*
static uint8_t Sdata_DeviceParameter[64];
static uint8_t Sdata_DevParaLen;
uint8_t T_runProc::epi_store64BdevParameter(uint8_t length, uint8_t *buf)
{
// HWapi writes data to be stored
uint8_t nn;
for (nn=0; nn<length; nn++)
Sdata_DeviceParameter[nn]=buf[nn];
for (nn=length; nn<64; nn++)
Sdata_DeviceParameter[nn]=0;
Sdata_DevParaLen=length;
return 0;
}
uint8_t T_runProc::epi_restore64BdevParameter(uint8_t *length, uint8_t *buf)
{
for (uint8_t nn=0; nn<Sdata_DevParaLen; nn++)
buf[nn]=Sdata_DeviceParameter[nn];
*length=Sdata_DevParaLen;
return 0;
}
*/

View File

@ -2,6 +2,7 @@
matching interfaces.h:
// History
// 11.10.2021: V1.0 222 functions
// 23.12.2021: V1.1 added block-parameter to function "read mifare data"
// 30.12.2021: V1.2 added function: mif_clearDataBuffer(), mif_isBlockAvailable(uint8_t blkNr) and mif_getAvailableDataBlocks()
@ -14,12 +15,32 @@ matching interfaces.h:
// V3.2 Bootloader improvement
// 12.04.2023: V3.3 new features extended: loading and using Json-files, cash-collection, cash-data-logging
14.7.23TS: patch for correct printer state in line 3364 in sys_getDeviceConditions(struct T_moduleCondition *devCond) const
8.9.2023 two new functions (end of file) for mifare test. Interface version 4.4 DC4.40...4.43
14.09.2023: Verriegelung eingebaut, nur noch gültige Abr.Daten zurückgeben, Suchbegriff: <epi_restoreVaultRecord>
alle Mifare-Funktionen ueberprueft und ggf verbessert
18.09.2023: Signal "Kasse entnommen" und Signale "Tuer auf/zu" ueberprueft
20.9.2023: in datif die Abfrage der DynMachineData massiv beschleunigt
und hier in hwapi die entprellten Werte fuer Tueren und Kasse verwenden.
Problem war: Signal "Kasse entnommen" war zu langsam -> manchmal abr nicht gesendet
14.3.24 new function bool hwapi::cash_isCollectionStarted(void) const
padding three struct to 64 byte to avoid stack overflow when using
//#define HWINF_iid "Atb.Psa2020.software.HWapi/3.1"
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.1"
#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/3.3"
V4.0 6.9.2023: activating DC-Bootloader in slve-lib (SM)
23.5.2024: prn_getHwState() fixed and moved down to runProc with a wrapper in hwapi, current version: 5.5
several new functions for "direct ticket print", without the dueway loading jsons to DC and cmd DC to print
The same rules as before apply to the json, but it can have any arbitrary length
*/
@ -27,7 +48,6 @@ V4.0 6.9.2023: activating DC-Bootloader in slve-lib (SM)
#define hwapi_H
#include <stdint.h>
//#include <QTabWidget>
#include <QtPlugin>
#include <QTimer>
#include <QObject>
@ -80,7 +100,8 @@ V4.0 6.9.2023: activating DC-Bootloader in slve-lib (SM)
class QSharedMemory;
class DownloadThread;
class ReportingThread;
class hwapi : public QObject,
public hwinf
{
@ -92,10 +113,12 @@ private:
void sub_storeSendingText(QByteArray *buf) const;
QTimer *hwapi_TimerPayment;
QSharedMemory *m_sharedMem;
ReportingThread *m_reportingThread;
DownloadThread *m_downloadThread;
//QTimer *hwapi_triggerBL;
public:
explicit hwapi(QWidget *parent = nullptr);
explicit hwapi(QObject *parent = nullptr);
#ifdef THIS_IS_CA_MASTER
@ -567,12 +590,10 @@ public:
// read printer condition and settings
uint8_t prn_getHwState(struct Tprn_hw_state *prn_hw_state) const override;
// retval: status byte
// byte 0 = 0: prnter OK, >0: error
// bit0: paper low 1: no paper 2: temperature error
// 3: head open 4: paper jam in cutter
// 6: no response 7: bad response from printer
// and return struct "Tprn_hw_state"
// return value: =prn_hw_state[0]
// 0:unknown 1: printer OK 100: printer OK but paper near end
// 200: not connected 201: printer on error 202: no paper
bool prn_isUpAndReady(void) const override;
// true: printer is powered, serial is ok, no error, printer is connected and resonding
@ -601,7 +622,7 @@ public:
void prn_movePaper(uint8_t wayInMm, uint8_t direction) const override;
//direction: 1=forward 2=backward
//
void prn_setFonts(uint8_t font, uint8_t size, uint8_t width, uint8_t height) const override;
// font = kind of font 5...11 (0..22)
// size = 6...20, 9..9: too tiny 10: small ...12 = normal size ...20=huge
@ -1035,7 +1056,6 @@ public:
void sys_getDynMachineConditions(struct T_dynamicCondition *dynMachCond) const override;
uint32_t cash_getAmountInVault(void) const override;
uint16_t cash_getNrCoinsInVault(void) const override;
@ -1316,10 +1336,75 @@ public:
// countOfBills: array of up to 16 sums, countOfBills[0]=nr of 5€-bills in stacker
// countOfBills[1] for 10€ and so on
bool cash_isCollectionStarted(void) const override;
// download device controller
bool dcDownloadRequest(QString const &fileToDownload) const override;
bool dcDownloadRequested() const override;
bool dcDownloadResetRequest() const override;
bool dcDownloadRequestAck() const override;
bool dcDownloadRunning() const override;
bool dcDownloadFinished() override;
bool dcDownloadReportStart() const override;
bool dcDownloadReportRunning() const override;
bool dcDownloadReportFinished() override;
bool dcDownloadThreadStart() override;
bool dcDownloadThreadRunning() const override;
void dcDownloadThreadFinalize(DownloadThread *) override;
bool dcDownloadThreadFinished() const override;
bool dcDownloadReportThreadStart() override;
bool dcDownloadReportThreadRunning() const override;
void dcDownloadReportThreadFinalize() override;
void dcDownloadReportThreadQuit() override;
bool dcDownloadReportThreadFinished() const override;
QString dcDownloadFileName() const override;
bool dcDownloadSetRequested(bool) override;
bool dcDownloadSetRunning(bool) override;
bool dcDownloadSetFinished(bool) override;
void dcDownloadSetTotalBlockNumber(uint16_t totalBlockNumber) override;
void dcDownloadSetCurrentBlockNumber(uint16_t currentBlockNumber) override;
bool dcDownloadGetRequested() const override;
bool dcDownloadGetRunning() const override;
bool dcDownloadGetFinished() const override;
uint16_t dcDownloadGetTotalBlockNumber() const override;
uint16_t dcDownloadGetCurrentBlockNumber() const override;
virtual QObject const *getAPI() override;
void mod_switchResetline(void) override;
// 22.5.2024 direct ticket printing
void prn_translateLocalPrinterJson(QByteArray jsonFile2print) const override;
// load, parse, translate and save the file
void prnStoreDynamics(char *bufferDynPrintVars[], uint8_t nrOfDyns) const override;
// store nrOfDyns (up to 16) dynamics before printing
// max length = 16 byte per dynamic
// 16 strings with up to 16bytes each
void prn_printTranslatedTicket(void) const override;
uint8_t prn_waitForDirectTicket(void) const override;
signals:
void hwapi_reportDCDownloadStatus(QString const&) const override;
void hwapi_reportDCDownloadSuccess(QString const&) const override;
void hwapi_reportDCDownloadFailure(QString const&) const override;
void hwapi_templatePrintFinished_OK(void) const override;
void hwapi_templatePrintFinished_Err(void) const override;
@ -1344,7 +1429,7 @@ signals:
void hwapi_doorCBinAndAllDoorsClosed(void) const override;
void hwapi_doorAllDoorsClosed(void) const override;
void hwapi_coinAttached() const override;
@ -1374,8 +1459,7 @@ signals:
void sub_slotCoin15(void);
void sub_slotCoin16(void);
void coinAttached();
};

View File

@ -170,6 +170,7 @@ struct T_vaultRecord
};
// ATTENTION: struct length must be 64 exactly!!!
struct T_moduleCondition
{
// store conditon of all system components, hold in RAM
@ -178,48 +179,64 @@ struct T_moduleCondition
// 50..99 = HINT / Notification
// 100..150 = WARNING
// 200..250 = ERROR
uint8_t ram;
uint8_t intEe;
uint8_t extEe;
uint8_t rtc; // 1: time/date OK 100: time not plausible 200: hardware error
uint8_t boardHw;
uint8_t printer;
uint8_t modem;
uint8_t signal; // 1...99
uint8_t regist; // 100:not 1:reg 2:ping OK 3:gotTime
uint8_t mdbBus;
uint8_t coinChecker; // EMP, OMP or mei-cashflow
uint8_t coinEscrow;
uint8_t mifareReader; // 0: unknown 1=OK 200=no response 201=wrong response 202: Reader reports HW-error
uint8_t creditTerm;
uint8_t coinReject;
uint8_t coinSafe;
uint8_t billSafe;
uint8_t voltage; // 1:11..14V
uint8_t temper;
uint8_t poweronTest;
uint8_t doorState; // 1: alles zu 200: tuer offen + bit1(S) +bit2(CB) + bit3(CB)
uint8_t doorWasOpened; // 1: all doors are closed 200: any door was just opened
uint8_t changer; // can only be tested by usage
uint8_t coinBlocker; // can only be tested by usage
uint8_t billReader; // can only be tested by usage
uint8_t doorState; // 1: alles zu 200: tuer offen + bit1(S) +bit2(CB) + bit3(CB)
uint8_t doorWasOpened; // 1: all doors are closed 200: any door was just opened
uint8_t changer;
uint8_t coinBlocker;
uint8_t billReader;
uint8_t ResetReason;
uint8_t allModulesChecked;
uint8_t alarmState;
uint8_t fuses;
uint8_t res11;
uint8_t res12;
uint8_t res13;
// 31
// 32
uint8_t padd00;
uint8_t padd01;
uint8_t padd02;
uint8_t padd03;
//36
uint32_t padd04;
uint32_t padd05;
uint32_t padd06;
uint32_t padd07;
// 52
uint32_t padd08;
uint32_t padd09;
uint32_t padd10;
// 64
};
struct T_dynamicCondition
{
char allDoorsDebounced;
@ -228,16 +245,17 @@ struct T_dynamicCondition
char upperDoor; // 99: undefined 0:closed 1:open
char middleDoor; // 99: undefined 0:closed 1:open
char lowerDoor; // 99: undefined 0:closed 1:open
char reserve;
char coinAttached;
char billBox;
char modeAbrech;
char onAlarm; // 0:alarm aus 1:alarm 2:alarm mit Sirene 3: Sirenentest
// 10
char nowCardTest;
char nowPayment; // not used, always 0
char lastMifCardType;
uint8_t lastSDoorState;
uint8_t lastVDoorState;
uint8_t lastCBstate;
uint8_t lastCBstate; // =0, not used
char paymentInProgress;
// Version Szeged: aug2023
// 0: stopped by timeout
@ -266,6 +284,7 @@ struct T_dynamicCondition
char res1;
uint16_t U_Batt;
// 20
uint16_t Temperatur;
uint16_t nrCoinsInBox;
uint32_t amountInBox;
@ -275,11 +294,14 @@ struct T_dynamicCondition
char jsonValid_device;
char jsonValid_cash;
char jsonValid_print;
// 40
char jsonValid_serial;
char jsonValid_time;
char lastFileType;
// 44
uint8_t MifCardHolder[8];
// 51
uint8_t resultOfLastTemplPrint;
// 0: unknown or printing in progress
// 1: OK, doc was printed 2: error, doc was not printed
@ -290,9 +312,36 @@ struct T_dynamicCondition
// bit4: paper jam in cutter
// bit6: no response bit7: serial rec. error
// bit5: printer not ready
uint8_t startupTestIsRunning;
uint8_t startupTestIsRunning; // =0, not used
uint16_t empty; // neu 3.7.24, dieser Platz wird vom Compiler im Ram
// freigehalten weil naechster Wert ein Long ist
// 56
// new since 7.5.24
uint32_t totalNrOfCuts;
uint16_t nextAccountNumber;
uint16_t nrOfBillsInBox;
//uint16_t padd07; // raus am 3.7.24
// 64
// rest comes with new cmd:
uint32_t amountInBillbox;
uint16_t UbatAtLastPrint;
uint16_t pad01;
uint32_t reserve01;
uint32_t reserve02;
uint32_t reserve03;
uint32_t reserve04;
uint32_t reserve05;
uint32_t reserve06;
uint32_t reserve07;
uint32_t reserve08;
uint32_t reserve09;
uint32_t reserve10;
uint32_t reserve11;
uint32_t reserve12;
uint32_t reserve13;
uint32_t reserve14;
//54
};
struct T_extTime
@ -329,6 +378,7 @@ struct T_extTime
typedef uint8_t UCHAR;
typedef uint16_t UINT;
// ATTENTION: struct length must be 64 exactly!!!
struct T_devices
{
// set by master, used(1) or notused (0) or type 2....20
@ -337,7 +387,6 @@ struct T_devices
UCHAR kindOfCoinChecker; // 0: without 1=EMP820 2=EMP900 3=currenza Csquare (MW)
UCHAR kindOfMifareReader; // by now only stronglink SL025 =1
UCHAR solarPower; // 1:sleep allowed 0: no sleep
//UCHAR suppressSleepMode; // 0:sleep allowed 1: no sleep
UCHAR kindOfModem; // 0:off 1:Sunlink
UCHAR kindOfCreditcard; // 0:off 1:Feig NFC
@ -346,6 +395,7 @@ struct T_devices
UCHAR CoinShutter;
UCHAR BillAcceptor;
// 10
UCHAR usevaultLock;
UCHAR autoAlarm; // 1: switch on siren for 1min in doors opened unauthorized
@ -356,9 +406,28 @@ struct T_devices
UINT VaultFullWarnLevel;
UINT VaultFullErrorLevel;
// 20
UINT BattEmptyWarnLevel;
UINT BattEmptyErrorLevel;
UCHAR useForeignCharacters;
UCHAR printRefundReceipt;
UINT BillFullWarnLevel;
UINT BillFullErrorLevel;
UCHAR housing;
UCHAR resUc1;
// 32
uint32_t padd01;
uint32_t padd02;
uint32_t padd03;
uint32_t padd04;
uint32_t padd05;
uint32_t padd06;
uint32_t padd07;
uint32_t padd08;
// 64
};
struct T_chg_Tub
@ -390,6 +459,8 @@ struct T_changer
uint8_t paymentRunning; // 1: coins are accepted
uint16_t denomination[16];
uint16_t availableTubes; //bitwise 0,1 1=av. bit0 = lowest coin value
uint16_t pad;
// 64byte
};
struct T_bna
@ -398,22 +469,33 @@ struct T_bna
uint8_t setup; // 0: not 1: got valid parameters from device
uint8_t FeatureLevel;
uint16_t countryCode; // programmed in EMP
uint16_t scalingFactor; // z.B. 5
uint8_t decimalPlace;
uint8_t pad1;
uint16_t stackerCap;
uint16_t billSecureLevel;
// 12
uint8_t hasEscrow;
uint8_t accBillTypes[16]; // programmed in EMP z.B. (bit 0..7): 1 2 4 10 20 40 0 0
uint16_t currentStackerLevel; // requested number of notes in billbox
// 31
// settings from Master
uint16_t intendedAccept; // bit 0 =5€
uint16_t pad2;
uint16_t billDenomination[16];
// 35
uint16_t billDenomination[8];
// 51
uint8_t pad3;
uint32_t pad4;
uint32_t pad5;
uint32_t pad6;
// 8.5.24 reduced, 3 bytes too much.
};
class DownloadThread;
class hwinf
{
@ -1251,16 +1333,17 @@ public:
// read printer condition and settings
virtual uint8_t prn_getHwState(struct Tprn_hw_state *prn_hw_state) const {
virtual uint8_t prn_getHwState(struct Tprn_hw_state *prn_hw_state) const
{
Q_UNUSED(prn_hw_state);
return 0;
}
// retval: status byte
// byte 0 = 0: prnter OK, >0: error
// bit0: paper low 1: no paper 2: temperature error
// 3: head open 4: paper jam in cutter
// 6: no response 7: bad response from printer
// and return struct "Tprn_hw_state"
// return value: =prn_hw_state[0]
// 0:unknown 1: printer OK 100: printer OK but paper near end
// 200: not connected 201: printer on error 202: no paper
virtual bool prn_isUpAndReady(void) const {
return false;
@ -2298,10 +2381,111 @@ public:
// countOfBills: array of up to 16 sums, countOfBills[0]=nr of 5€-bills in stacker
// countOfBills[1] for 10€ and so on
virtual bool cash_isCollectionStarted(void) const {return false;}
// return true is coin collection in DC is running
// download device controller
virtual bool dcDownloadRequest(QString const &fileToDownload) const {
Q_UNUSED(fileToDownload);
return false;
}
virtual bool dcDownloadRequested() const { return false; }
virtual bool dcDownloadResetRequest() const { return false; }
virtual bool dcDownloadRequestAck() const { return false; }
virtual bool dcDownloadRunning() const { return false; }
virtual bool dcDownloadFinished() { return false; }
virtual bool dcDownloadReportStart() const { return false; }
virtual bool dcDownloadReportRunning() const { return true; }
virtual bool dcDownloadReportFinished() { return true; }
virtual bool dcDownloadThreadStart() { return false; }
virtual bool dcDownloadThreadRunning() const { return true; }
virtual void dcDownloadThreadFinalize(DownloadThread *) {}
virtual bool dcDownloadThreadFinished() const { return true; }
virtual bool dcDownloadReportThreadStart() { return false; }
virtual bool dcDownloadReportThreadRunning() const { return true; }
virtual void dcDownloadReportThreadFinalize() {}
virtual void dcDownloadReportThreadQuit() {}
virtual bool dcDownloadReportThreadFinished() const { return true; }
virtual QString dcDownloadFileName() const { return ""; }
virtual bool dcDownloadSetRequested(bool requested) {
Q_UNUSED(requested); return false;
}
virtual bool dcDownloadSetRunning(bool running) {
Q_UNUSED(running); return false;
}
virtual bool dcDownloadSetFinished(bool finished) {
Q_UNUSED(finished); return false;
}
virtual void dcDownloadSetTotalBlockNumber(uint16_t totalBlockNumber) {
Q_UNUSED(totalBlockNumber);
}
virtual void dcDownloadSetCurrentBlockNumber(uint16_t currentBlockNumber) {
Q_UNUSED(currentBlockNumber);
}
virtual bool dcDownloadGetRequested() const { return false; }
virtual bool dcDownloadGetRunning() const { return false; }
virtual bool dcDownloadGetFinished() const { return false; }
virtual uint16_t dcDownloadGetTotalBlockNumber() const { return 0; }
virtual uint16_t dcDownloadGetCurrentBlockNumber() const { return 0; }
virtual QObject const *getAPI() { return nullptr; }
virtual void mod_switchResetline() { }
// direct ticket printing
// new from 22.5.2024, print Json-Printer-Template which
// is stored locally here in PTU memory,
// rather then loading several jsons to DC and tell it to print (until now)
// the local printer-json can have any length using predefined commands
// printing a local printer-json happens like this:
// 1) select a file to be printed from memory
// 2) load, parse, translate and save the file with following function
// 3) set dynamics (values from current transaction)
// 4) send saved file to printer one or several times
// hint: dynamics can be changed at any time without reloading the ticket, just repeat 3) and 4)
virtual void prn_translateLocalPrinterJson(QByteArray jsonFile2print) const
{ Q_UNUSED(jsonFile2print) }
// load, parse, translate and save the file
virtual void prnStoreDynamics(char *bufferDynPrintVars[], uint8_t nrOfDyns) const
{ Q_UNUSED(bufferDynPrintVars); Q_UNUSED(nrOfDyns) }
// store nrOfDyns (up to 16) dynamics before printing
// max length = 16 byte per dynamic
// 16 strings with up to 16bytes each
virtual void prn_printTranslatedTicket(void) const { }
virtual uint8_t prn_waitForDirectTicket(void) const { return 0; }
// return: 0: just printing, wait
// 1: OK - last print was succesful
// 2: error - not printed
// 2: printer error 3: no connection to DC
signals:
/*
NOTE: the difference between a virtual Qt signal and a normal Qt signal:
A Qt virtual signal is a connection that is established using a pointer
or reference and is not connected to an object or data. It is therefore
not bound to a particular object, but to a specific class (object type).
Qt virtual signals are useful because they allow you to create
connections without worrying about whether an object or a specific data
element has been destroyed.
https://www.youtube.com/watch?v=HTH3VFfqsXw
*/
virtual void hwapi_reportDCDownloadStatus(QString const&) const {}
virtual void hwapi_reportDCDownloadSuccess(QString const&) const {}
virtual void hwapi_reportDCDownloadFailure(QString const&) const {}
virtual void hwapi_templatePrintFinished_OK(void) const=0;
virtual void hwapi_templatePrintFinished_Err(void) const=0;
@ -2325,32 +2509,9 @@ signals:
virtual void hwapi_doorCBinAndAllDoorsClosed(void) const=0;
virtual void hwapi_doorAllDoorsClosed(void) const=0;
virtual void hwapi_coinAttached() const = 0;
// NOTE: declaring a "pure virtual" "signal" should be an error and thus not valid.
/* GH Version, bringt Fehler
void hwapi_templatePrintFinished_OK() const;
void hwapi_templatePrintFinished_Err() const;
void hwapi_coinCollectionJustStarted() const;
void hwapi_coinCollectionAborted() const;
void hwapi_gotNewCoin() const;
void hwapi_payStopByMax() const;
void hwapi_payStopByPushbutton() const;
void hwapi_payStopByEscrow() const;
void hwapi_payStopByError() const;
void hwapi_payStopByTimeout() const;
void hwapi_payCancelled() const;
void hwapi_coinProcessJustStopped() const;
void hwapi_doorServiceDoorOpened() const;
void hwapi_doorVaultDoorOpened() const;
void hwapi_doorCoinBoxRemoved() const;
void hwapi_doorCoinBoxInserted() const;
void hwapi_doorCBinAndAllDoorsClosed() const;
void hwapi_doorAllDoorsClosed() const;
*/
};
@ -2413,9 +2574,21 @@ signals:
// hier dazwischen: Umstellung ALLER Prototypen
// hier von =0 auf {} durch Gerhard
#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/5.2"
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/5.2"
// 7.11.2023: bna functions activated
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/5.3"
// 14.3.24:new function bool hwapi::cash_isCollectionStarted(void) const
// padding three struct to 64 byte to avoid stack overflow when using
// signal coin attached is much faster now
//#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/5.4"
// 7.may.2024, matches to DC V6, some structs extended
// new function: modem reset, dyn. data come with two commands now
// released 17.may.2024
#define HWINF_iid "Atb.Psa1256ptu5.software.HWapi/5.5"
// started at 21.5.24, integration of ticket interpreter
// see change log in hwapi.h
Q_DECLARE_INTERFACE(hwinf, HWINF_iid)

View File

@ -1,7 +1,7 @@
#ifndef SERIAL_FRAME_H
#define SERIAL_FRAME_H
#include <QMainWindow>
#include <QObject>
#include <QString>
#include <QTimer>
#include "tslib.h"
@ -43,7 +43,7 @@
#define STARTSIGN_RECEIVE_LONG 0x5D
class T_prot : public QMainWindow
class T_prot : public QObject
{
Q_OBJECT
@ -122,6 +122,9 @@ public:
uint8_t *RdDlen, uint8_t *receivedData);
// retval: data valid, only one time true
uint16_t getReadSource() { return readSource; } // readSource contains last command sent to device controller
T_com *getSerialPort() { return mySerialPort; } // utility function
signals:
void framerecieved(); //bool gotINdata);

View File

@ -0,0 +1,25 @@
#ifndef REPORTING_THREAD_H_INCLUDED
#define REPORTING_THREAD_H_INCLUDED
#include <QThread>
#include <QString>
class hwapi;
class ReportingThread : public QThread {
Q_OBJECT
public:
ReportingThread(hwapi *hw);
~ReportingThread();
protected:
// reporting thread does not have a running event queue, and therefore
// no slots. signals work the usual way.
void run() override;
private:
hwapi *m_hw;
QString m_fileToDownload;
};
#endif // REPORTING_THREAD_H_INCLUDED

View File

@ -3,7 +3,7 @@
#define RUN_PROCESS_H
#include <stdint.h>
#include <QMainWindow>
#include <QObject>
#include <QString>
#include <QTimer>
#include "tslib.h"
@ -15,6 +15,7 @@
#include <QDebug>
#include "datIf.h"
#include <QSharedMemory>
#include <atomic>
#include "sendWRcmd.h"
#include "controlBus.h"
#include "storeINdata.h"
@ -22,7 +23,6 @@
#include "shared_mem_buffer.h"
class T_runProc : public QObject
{
Q_OBJECT
@ -35,6 +35,20 @@ class T_runProc : public QObject
void restoreDeviceParameter(struct T_devices *deviceSettings);
void clearPrnFile(void);
char subFeedPaper(char *valueStr);
bool subGetVariStr(char *valueStr, char *returnStr);
//void subAppendNxtTxt(char *textLine);
void sub_changeStyle(char *valueStr);
void subPrintGrafics(char *valueStr);
char prn_directTicket_cycle(void);
void runProc_subPerformPrintCmds(uint8_t nextCmd, uint8_t nextPara);
uint16_t subStoreTicketText(char *textLine);
#ifndef THIS_IS_CA_MASTER
std::atomic_bool m_coinAttached{false};
#endif
private slots:
void runProc_slotProcess(void);
bool bl_performComplStart(void);
@ -48,6 +62,9 @@ public:
uint8_t epi_restore64BdevParameter(uint8_t *length, uint8_t *buf);
bool doors_supervise(void);
uint8_t prn_getHwState(struct Tprn_hw_state *prn_hw_state);
// byte 0: 0:unknown 1: printer OK 100: printer OK but paper near end
// 200: not connected 201: printer on error 202: no paper
void bl_completeStart(void);
void dc_autoRequest(bool on);
void bl_rebootDC(void);
@ -55,6 +72,48 @@ public:
void bl_checkBL(void);
bool bl_isUp(void);
// new from 21.5.24 ..................................................................
uint16_t sys_getCustomerNumber(void);
uint16_t sys_getMachineNumber(void);
uint16_t sys_getBoroughNumber(void);
uint16_t sys_getZoneNumber(void);
uint16_t sys_getMachineAlias(void);
void sys_getLocation(char *locStr);
void prn_sendText(QByteArray *buf);
void prn_sendPrnSysCmd(uint8_t para1, uint8_t para2, uint32_t para3);
void prn_printBarcode(uint8_t kindOf, uint8_t withText, uint8_t offset, uint8_t rotation, uint8_t dataLeng, uint8_t *data);
bool sys_parseFile(QByteArray jsonFile2print);
// and copy all keys and values to arrays
bool sys_translateKeys(void);
bool sys_interpretPrnCmds(void);
void prn_sendPrnSetup(uint16_t paperSpeed, uint8_t density, uint8_t alignment, uint8_t orientation);
// send 5 byte: byte 0,1: speed 5...250 mm/s
// byte2: density 0....(25)....50
// byte3: alignment 'l', 'c', 'r' = left, center, right
// byte4: orientation 0, 90, 180 = 0°, 90°, 180° rotation (by now not supported!)
void prnStoreDynamics(char *bufferDynPrintVars[], uint8_t nrOfDyns);
// store nrOfDyns (up to 16) dynamics before printing
// max length = 16 byte per dynamic
bool prnRestoreDynamic(uint8_t nrOfDyn, char *bufferOneDyn);
// nrOfDyn = 0...15
// buffer bufferOneDyn[16] needs length of at least 16 byte
bool prn_isUpAndReady(void);
void prnStartDirectPrinting(void);
uint8_t prn_getDirectPrintResult(void);
// return: 0: just printing, wait
// 1: OK - last print was succesful
// 2: error - not printed
// 2: printer error 3: no connection to DC
signals:
//void runProc_templatePrintFinished_OK(void) const override;
@ -80,6 +139,7 @@ signals:
void runProc_doorCBinAndAllDoorsClosed(void);
void runProc_doorAllDoorsClosed(void);
void runProc_coinAttached();
};

2
include/sendWRcmd.h Normal file → Executable file
View File

@ -14,6 +14,8 @@ uint8_t sendWRcmd_getSendBlock160(uint8_t *leng, uint8_t *buf);
void sendWRcmd_INI(void);
uint8_t sendWRcmd_getStackSize(void);
// #define FDCMD_STACKDEPTH 16 / 32
// short and long commands are queued into the same stack to guaranty right order
void sendFDcmd_clrStack(void);

28
include/shared_mem_buffer.h Normal file → Executable file
View File

@ -230,6 +230,9 @@ struct SharedMem
uint8_t store_bnaCollect[8];
uint8_t store_bnaContent[64];
// new, 8.5.24
uint8_t store_machCon2len;
uint8_t store_machCon2[66];
@ -242,7 +245,7 @@ struct SharedMem
// ------------------ Data OUTPUT --------------------------------
// sendWRcmd.cpp
#define CMDSTACKDEPTH 16
#define CMDSTACKDEPTH 32
uint16_t nextAsynchsendCmd0[CMDSTACKDEPTH];
uint8_t nrOfCmdsInQueue;
@ -300,9 +303,26 @@ struct SharedMem
uint8_t p_nextFDcmdsInQueue;
// download of device controller and json files
struct DCDownload {
enum class FILE_INDEX {
DC_BINARY = 0, DC2C_CASH = 1, DC2C_CONF = 2, DC2C_SERIAL=3,
DC2C_PRINT_01, DC2C_PRINT_02, DC2C_PRINT_03, DC2C_PRINT_04,
DC2C_PRINT_05, DC2C_PRINT_06, DC2C_PRINT_07, DC2C_PRINT_08,
DC2C_PRINT_09, DC2C_PRINT_10, DC2C_PRINT_11, DC2C_PRINT_12,
DC2C_PRINT_13, DC2C_PRINT_14, DC2C_PRINT_15, DC2C_PRINT_16,
DC2C_PRINT_17, DC2C_PRINT_18, DC2C_PRINT_19, DC2C_PRINT_20,
DC2C_PRINT_21, DC2C_PRINT_22, DC2C_PRINT_23, DC2C_PRINT_24,
DC2C_PRINT_25, DC2C_PRINT_26, DC2C_PRINT_27, DC2C_PRINT_28,
DC2C_PRINT_29, DC2C_PRINT_30, DC2C_PRINT_31, DC2C_PRINT_32
};
char m_filename[(int)FILE_INDEX::DC2C_PRINT_32][512];
std::atomic_ushort m_totalBlocks;
std::atomic_ushort m_currentblockNumber;
std::atomic_bool m_requested{false};
std::atomic_bool m_running{false};
std::atomic_bool m_finished{false};
} m_downLoadDC;
static QSharedMemory *getShm(std::size_t s = 0);

8
include/storeINdata.h Normal file → Executable file
View File

@ -529,7 +529,7 @@ bool epi_areDcDataValid();
void epi_setDcDataValid(void);
void epi_resetDcDataValid(void);
void epi_resetDcDataValid(char reason);
void epi_clearDynData(void);
@ -626,6 +626,12 @@ void epi_restoreBnaContent(uint8_t *data);
void epi_clearDynMachCond2(void);
void gpi_storeDynMachCond2(uint8_t leng, uint8_t *data);
void epi_restoreDynMachCond2(uint8_t *leng, uint8_t *data);

33
include/tslib.h Normal file → Executable file
View File

@ -1,7 +1,7 @@
#ifndef TSLIB_H
#define TSLIB_H
#include <QByteArray>
#include "stdint.h"
#define LOWBYTE false
#define HIGHBYTE true
@ -87,6 +87,37 @@ void biox_CopyBlock(uint8_t *src, uint16_t srcPos, uint8_t *dest, uint16_t destP
bool tslib_strComp(uint8_t *buf, char *compStr);
uint16_t tslib_StrLen(char *str);
void tslib_itoa(int n, char *str);
// -23456 -> str[0]='-' str[1]='2' ...[5]='6' str[6]=0
// 5 -> str[0]='5' str[1..6]=0
void tslib_uitoa(unsigned int n, char *str);
void tslib_ltoa(long n, char *str);
// -2147483647 -> str[0]='-' str[1]='2' ...[10]='6' str[11]=0
void tslib_ultoa( long n, char *str);
// 0... ->4294967296 str[0]='4' str[1]='2' ...[9]='6' str[10]=0 str[11]=0
void tslib_uitobin( int decval, char *str);
long tslib_atol( char *AscString);
// change ascii string ( of ascii numbers '0'..'9') to number
// AscString must be 0-terminated!
// a leading '-' is ignored, a'.' or a ',' stops calculation
#endif // TSLIB_H

View File

@ -1,6 +1,6 @@
TEMPLATE = lib
TARGET = CAmaster
VERSION="1.0.0"
VERSION="1.0.1"
HEADERS += \
../include/com.h \
@ -14,6 +14,25 @@ SOURCES += \
include(../DCLibraries.pri)
win32 {
BUILD_DATE=$$system("date /t")
BUILD_TIME=$$system("time /t")
GIT_COMMIT=""
EXTENDED_VERSION=""
EXTENDED_VERSION_LIB=""
} else {
BUILD_DATE=$$system("date +%d-%m-%y")
BUILD_TIME=$$system("date +%H:%M:%S")
GIT_COMMIT=$$system("git log -1 --format=oneline . | cut -d' ' -f1")
EXTENDED_VERSION_LIB="libCAmaster-$${VERSION}-$${GIT_COMMIT}"
}
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\"
DEFINES+=APP_BUILD_TIME=\\\"$$BUILD_TIME\\\"
DEFINES+=APP_EXTENDED_VERSION=\\\"$$EXTENDED_VERSION\\\"
DEFINES+=APP_EXTENDED_VERSION_LIB=\\\"$$EXTENDED_VERSION_LIB\\\"
DEFINES+=THIS_IS_CA_MASTER
DESTDIR=$${_PRO_FILE_PWD_}/../build
@ -22,3 +41,6 @@ unix {
system("mkdir -p $${DESTDIR}")
system("cp ../include/interfaces.h $${DESTDIR}")
}
DISTFILES += \
../include/dump.txt

View File

@ -1,9 +1,29 @@
TEMPLATE = lib
TARGET = CAslave
VERSION="1.0.0"
VERSION="1.0.1"
include(../DCLibraries.pri)
win32 {
BUILD_DATE=$$system("date /t")
BUILD_TIME=$$system("time /t")
GIT_COMMIT=""
EXTENDED_VERSION=""
EXTENDED_VERSION_LIB=""
} else {
BUILD_DATE=$$system("date +%d-%m-%y")
BUILD_TIME=$$system("date +%H:%M:%S")
GIT_COMMIT=$$system("git log -1 --format=oneline . | cut -d' ' -f1")
EXTENDED_VERSION_LIB_="libCAslave-$${VERSION}-$${GIT_COMMIT}"
}
DEFINES+=APP_VERSION=\\\"$$VERSION\\\"
DEFINES+=APP_BUILD_DATE=\\\"$$BUILD_DATE\\\"
DEFINES+=APP_BUILD_TIME=\\\"$$BUILD_TIME\\\"
DEFINES+=APP_EXTENDED_VERSION=\\\"$$EXTENDED_VERSION\\\"
DEFINES+=APP_EXTENDED_VERSION_LIB=\\\"$$EXTENDED_VERSION_LIB\\\"
DEFINES+=THIS_IS_CA_SLAVE
DESTDIR=$${_PRO_FILE_PWD_}/../build

View File

@ -1,5 +1,6 @@
#include "com.h"
#include <QDebug>
#include <QDateTime>
//#include "controlBus.h"
//////////////////////////////////////////////////////////////////////////////////
@ -20,13 +21,48 @@ void T_com::writeToSerial(const QByteArray &data, uint16_t sendLength)
{
sendBuffer=data;
sendLen=sendLength;
if (CatSerial->isOpen())
{
//qDebug() << "sending..." << sendBuffer;
CatSerial->write(sendBuffer);
} else
qDebug() << "error sending, port is not open";
// logic: exactly one command is sent to DC. no other command can be sent
// until the respond has been read from the serial line.
if (CatSerial->isOpen()) {
if (CatSerial->error() != QSerialPort::NoError) {
qCritical() << __func__ << "" << __LINE__ << "ERROR on serial line" << CatSerial->errorString();
CatSerial->clearError();
qCritical() << __func__ << "" << __LINE__ << "cleared error on serial line";
}
if (!CatSerial->atEnd()) {
qCritical() << QString("ERROR %1 bytes available on serial line before write").arg(CatSerial->bytesAvailable());
qCritical() << CatSerial->readAll().toHex(':');
CatSerial->clear();
qCritical() << __func__ << "" << __LINE__ << "read all data from serial line";
}
CatSerial->clear();
QByteArray buffer(data);
int bytesWritten = CatSerial->write(buffer);
if (bytesWritten == -1) {
qCritical() << __func__ << ":" << __LINE__
<< QString("ERROR %1 for sending %2").arg(CatSerial->errorString()).arg(data.toHex(':').constData());
CatSerial->clearError();
qCritical() << __func__ << ":" << __LINE__ << "cleared error on serial line. returning ...";
return;
}
CatSerial->flush();
writeCount += 1;
// only for debugging
// if ((unsigned int)data.constData()[2] == 31) { // request dynamic data
// qCritical() << __func__ << ":" << __LINE__ << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs)
// << "write cmd" << (unsigned int)data.constData()[2];
//}
} else {
qCritical() << __func__ << ":" << __LINE__
<< "ERROR sending" << data.toHex(':') << "port is not open";
}
}
@ -82,6 +118,7 @@ T_com::T_com(QObject *parent) : QObject(parent)
ChkConnectTimer->setSingleShot(false);
ChkConnectTimer->start(100); // in ms
com_want2read=0;
writeCount = 0;
}

396
src/datIf.cpp Normal file → Executable file
View File

@ -6,10 +6,12 @@ History:
*/
#include "datIf.h"
#include "hwapi.h"
#include "sendWRcmd.h"
#include "controlBus.h"
#include "storeINdata.h"
#include <QDebug>
#include <QDateTime>
#include <datei.h>
#include <QDir>
@ -88,9 +90,11 @@ T_datif::T_datif(QObject *parent) : QObject(parent)
dif_scanStep=0;
selectedSlaveAddr=FIX_SLAVE_ADDR;
cycl_running=0;
epi_resetDcDataValid(); // data are not yet valid, no response from DC by now
epi_resetDcDataValid(1); // data are not yet valid, no response from DC by now
datif_noResponseCtr=0;
datif_nowNewDyns=0;
datif_nowNewStats=0;
datif_repeatCtr=0;
datif_cmdWasPerformed=0; // 0: no response by now
@ -122,6 +126,7 @@ T_datif::T_datif(QObject *parent) : QObject(parent)
datif_pNextCmd=0;
datif_sendSlowCmd=0;
readCount = 0;
}
void T_datif::resetChain(void)
@ -129,6 +134,11 @@ void T_datif::resetChain(void)
dif_scanStep=0;
}
#define RESPONSEWAITTIME 10
// ab 5 keine timeouts mehr
#define GOTRESP_SENDGAP 20
// Wert egal, muss nur > RESPONSEWAITTIME und <255 sein
char T_datif::datif_cycleSend()
{
// cyclic transmission of INPUT-Requests
@ -145,14 +155,25 @@ char T_datif::datif_cycleSend()
if ( !myDCIF->isPortOpen())
{
//qDebug() << "com port not available"; // wird ununterbrochen ausgegeben
epi_resetDcDataValid(); // DC data not valid
epi_resetDcDataValid(2); // DC data not valid
datif_nowNewDyns=0;
datif_nowNewStats=0;
return 0;
}
// supervise if DC data are valid
datif_noResponseCtr++; // inc every 20ms
if (datif_noResponseCtr>250) // no life sign from device controller (DC) for about 3s
epi_resetDcDataValid(); // DC data has not updated for >=5s -> no longer valid!
if (datif_noResponseCtr>50) // no life sign from device controller (DC) for about a sec
{
epi_resetDcDataValid(3); // DC data has not updated for >=5s -> no longer valid!
datif_nowNewDyns=0;
datif_nowNewStats=0;
}
// 24.7.24 new, data are valid if dynamic machine conditions AND dyn machine states came in
if (datif_nowNewDyns && datif_nowNewStats && !epi_areDcDataValid() )
epi_setDcDataValid();
// Ueberwachung ob ein oder mehrere Commands am Stueck erfolgreich waren
if (gpi_wantToResetSupervision())
@ -171,8 +192,7 @@ char T_datif::datif_cycleSend()
// c) gar keine Antwort, Timeout nach 100ms -> 2x wiederholen (nach einer Luecke von 10ms )
// cycl_running=0: nichts zu tun 1: Mitteilung: Kommando wurde soeben abgesendet, 2,3,4 = Wiederholung
if (cycl_running) // 21.9.23 doRepeat hier raus sonst gehts warten auch nicht mehr (BL)
// if (cycl_running && doRepeat)
if (cycl_running)
{
// request is still running, wait for response before next sending
//qDebug()<< "datif wait for response";
@ -180,28 +200,35 @@ char T_datif::datif_cycleSend()
datif_trigger->start(20); // ruft "this" (datif_cycleSend) erneut in 20ms auf
// mit 10 kein Unterscheid weil Zykluszeit grösser
cycl_running++; // inc every 20...30ms // warte max 100ms auf Antwort
if (cycl_running >80 && cycl_running <95) // neu 13.9.23 mind. 40 damit Templates
// in Folge gedruckt werden koennen
// 95: muss nur kleiner sein als die 100 fuer die Luecke
// 17.10.23: 50--> 80
cycl_running++; // inc every 20ms, warte auf Antwort
if (cycl_running >= GOTRESP_SENDGAP)
{
// 100ms vergangen, bisher keine Antwort, also Kommando wiederholen
qDebug()<< "datif timeout no response for wr/rd cmd "<< keepLastWrCmd << " " << keepLastRdCmd;
// got response, wait just one (this) cycle before next sending
cycl_running=0;
return 0;
}
if (cycl_running >=RESPONSEWAITTIME )
{
// bisher keine Antwort, also Kommando wiederholen
qDebug()<< "datif timeout no response for wr/rd cmd "<< keepLastWrCmd << " " << keepLastRdCmd;
cycl_running = 0; // gleich wiederholen weil ja schon ewig nichts mehr reinkam
datif_cmdWasPerformed=2; // NO :((
gpi_storeLastResult(8);
return 0;
}
if (cycl_running>=101) // 100 + 1
/*
* Unsinn, wird nie durchlaufen
if (cycl_running>=(RESPONSEWAITTIME+6)) // 3.7.24: 101-->110
{
// Antwort ist gekommen, also nach kurzer Luecke naechstes (datif_cmdWasPerformed==1)
// oder nochmal gleiches (datif_cmdWasPerformed==2) Kommando senden
//qDebug()<< "datif got any response";
cycl_running=0;
}
*/
// hier stoppen, weil Antwort des letzten Cmds noch nicht da
return 0;
}
@ -223,6 +250,7 @@ char T_datif::datif_cycleSend()
datif_kindOfCmd=0;
cycl_running=0;
gpi_storeOverallResult(2);
qCritical()<<"datif, error no response to wr/rd "<<keepLastWrCmd<<" "<<keepLastRdCmd;
return 0;
}
@ -249,7 +277,7 @@ char T_datif::datif_cycleSend()
datif_cmdWasPerformed=0;
} else
{
qDebug() << "datif: unknown cmd, stop repeating wr/rd:" << keepLastWrCmd << " " << keepLastRdCmd;
qCritical() << "datif: unknown cmd, stop repeating wr/rd:" << keepLastWrCmd << " " << keepLastRdCmd;
datif_cmdWasPerformed=0;
cycl_running=0;
datif_kindOfCmd=0;
@ -280,8 +308,10 @@ char T_datif::datif_cycleSend()
myDCIF->setUserReadData(nextRdCmd);
myDCIF->sendUserData(selectedSlaveAddr);
//qDebug()<<"Datif send long FD cmd (wr/rd): "<<nextWrCmd<< " / " << nextRdCmd
// << " " << data[0]<< " " << data[1]<< " " << data[2]<< " " << data[3];
qDebug()<<"Datif send long FD cmd (wr/rd): "<<nextWrCmd<< " / " << nextRdCmd << "Dlen:" << length;
// << " data:" << data[0]<< " " << data[1]<< " " << data[2]<< " " << data[3]
// << " " << data[4]<< " " << data[5]<< " " << data[6]<< " " << data[7]
// << " " << data[8]<< " " << data[9]<< " " << data[10]<< " " << data[11];
cycl_running=1; // 1: start transmission
datif_kindOfCmd=2;
@ -308,8 +338,8 @@ char T_datif::datif_cycleSend()
myDCIF->setUserReadData(nextRdCmd);
myDCIF->sendUserData(selectedSlaveAddr);
//qDebug()<<"Datif send short FD cmd (wr/rd): "<<nextWrCmd<< " / " << nextRdCmd << " "
// << blockNum << " " << dat1 << " " << dat2<< " " << dat3<< " " << dat4;
qDebug()<<"Datif send short FD cmd (wr/rd): "<<nextWrCmd<< " / " << nextRdCmd << " ";
// << blockNum << " " << dat1 << " " << dat2<< " " << dat3<< " " << dat4;
cycl_running=1; // 1: start transmission
datif_kindOfCmd=1;
@ -345,7 +375,10 @@ char T_datif::datif_cycleSend()
else
{
dif_scanStep=0; // always start from beginning
epi_resetDcDataValid();
epi_resetDcDataValid(4);
datif_nowNewDyns=0;
datif_nowNewStats=0;
}
datif_cmdWasPerformed=0; // 0: no response by now
@ -363,14 +396,14 @@ char T_datif::sendINrequestsAutomatic(void)
// 114,0,0,0,0,0,0,0,0,0};
// extension 6.12.23, complete list:
uint8_t datif_autoRequCommandList[40]={11, 12, 13, 14, 17, 18, 19, 21, 22, 23,
24, 25, 27, 30, 31, 32, 33, 35, 39, 40,
uint8_t datif_autoRequCommandList[40]={11, 12, 14, 17, 18, 19, 21, 22, 23, 24,
25, 27, 30, 31, 32, 33, 34, 35, 39, 40,
41, 42, 102,103,104,106,107,108,109,110,
112,113,114,115,116,0, 0, 0, 0, 0};
112,113,114,115,116,0, 0, 0, 0, 0};
uint8_t datif_maxNrCommands=35, datif_sendNow;
// send quicker while transaction is ongoing:
uint8_t datif_vendRequCommandList[15]={102,107,108,110,112,115,116,31,32,40,41,42,23,0,0};
uint8_t datif_vendRequCommandList[15]={102,107,108,110,112,115,116,30,31,32,40,41,42,23,0};
uint8_t datif_maxVendingCmds=13;
// special commands:
@ -380,7 +413,8 @@ char T_datif::sendINrequestsAutomatic(void)
// 19: get time and date and Extra values. poll occasionally and if needed
// 107, 22: MDB: poll if needed
doRepeat=true; // 20.9.23 15uhr (after release)
//doRepeat=true; // 20.9.23 15uhr (after release)
doRepeat=false; // 3.7.24 off, is repeated cyclic anyway
if (gpi_getNowCoinPay())
{
@ -449,6 +483,76 @@ void T_datif::StoredRecData()
gpi_storeLastResult(res);
}
static void dump(T_moduleCondition const *modCond) {
qCritical() << QString("modCond->ram %1 (%2)").arg(modCond->ram).arg(modCond->ram, 0, 16);
qCritical() << QString("modCond->intEe %1 (%2)").arg(modCond->intEe).arg(modCond->intEe, 0, 16);
qCritical() << QString("modCond->extEe %1 (%2)").arg(modCond->extEe).arg(modCond->extEe, 0, 16);
qCritical() << QString("modCond->rtc %1 (%2)").arg(modCond->rtc).arg(modCond->rtc, 0, 16);
qCritical() << QString("modCond->boardHw %1 (%2)").arg(modCond->boardHw).arg(modCond->boardHw, 0, 16);
qCritical() << QString("modCond->printer %1 (%2)").arg(modCond->printer).arg(modCond->printer, 0, 16);
qCritical() << QString("modCond->modem %1 (%2)").arg(modCond->modem).arg(modCond->modem, 0, 16);
qCritical() << QString("modCond->signal %1 (%2)").arg(modCond->signal).arg(modCond->signal, 0, 16);
qCritical() << QString("modCond->regist %1 (%2)").arg(modCond->regist).arg(modCond->regist, 0, 16);
qCritical() << QString("modCond->mdbBus %1 (%2)").arg(modCond->mdbBus).arg(modCond->mdbBus, 0, 16);
qCritical() << QString("modCond->coinChecker %1 (%2)").arg(modCond->coinChecker).arg(modCond->coinChecker, 0, 16);
qCritical() << QString("modCond->coinEscrow %1 (%2)").arg(modCond->coinEscrow).arg(modCond->coinEscrow, 0, 16);
qCritical() << QString("modCond->mifareReader %1 (%2)").arg(modCond->mifareReader).arg(modCond->mifareReader, 0, 16);
qCritical() << QString("modCond->creditTerm %1 (%2)").arg(modCond->creditTerm).arg(modCond->creditTerm, 0, 16);
qCritical() << QString("modCond->coinReject %1 (%2)").arg(modCond->coinReject).arg(modCond->coinReject, 0, 16);
qCritical() << QString("modCond->coinSafe %1 (%2)").arg(modCond->coinSafe).arg(modCond->coinSafe, 0, 16);
qCritical() << QString("modCond->billSafe %1 (%2)").arg(modCond->billSafe).arg(modCond->billSafe, 0, 16);
qCritical() << QString("modCond->voltage %1 (%2)").arg(modCond->voltage).arg(modCond->voltage, 0, 16);
qCritical() << QString("modCond->temper %1 (%2)").arg(modCond->temper).arg(modCond->temper, 0, 16);
qCritical() << QString("modCond->poweronTest %1 (%2)").arg(modCond->poweronTest).arg(modCond->poweronTest, 0, 16);
qCritical() << QString("modCond->doorState %1 (%2)").arg(modCond->doorState).arg(modCond->doorState, 0, 16);
qCritical() << QString("modCond->doorWasOpened %1 (%2)").arg(modCond->doorWasOpened).arg(modCond->doorWasOpened, 0, 16);
qCritical() << QString("modCond->changer %1 (%2)").arg(modCond->changer).arg(modCond->changer, 0, 16);
qCritical() << QString("modCond->coinBlocker %1 (%2)").arg(modCond->coinBlocker).arg(modCond->coinBlocker, 0, 16);
qCritical() << QString("modCond->billReader %1 (%2)").arg(modCond->billReader).arg(modCond->billReader, 0, 16);
qCritical() << QString("modCond->ResetReason %1 (%2)").arg(modCond->ResetReason).arg(modCond->ResetReason, 0, 16);
qCritical() << QString("modCond->allModulesChecked %1 (%2)").arg(modCond->allModulesChecked).arg(modCond->allModulesChecked, 0, 16);
qCritical() << QString("modCond->alarmState %1 (%2)").arg(modCond->alarmState).arg(modCond->alarmState, 0, 16);
qCritical() << QString("modCond->fuses %1 (%2)").arg(modCond->fuses).arg(modCond->fuses, 0, 16);
}
static void dump(T_dynamicCondition const *dynCond) {
qCritical() << QString("dynCond->allDoorsDebounced %1 (%2)").arg((unsigned char)dynCond->allDoorsDebounced).arg((unsigned char)dynCond->allDoorsDebounced, 0, 16);
qCritical() << QString("dynCond->openedAuthorized %1 (%2)").arg((unsigned char)dynCond->openedAuthorized).arg((unsigned char)dynCond->openedAuthorized, 0, 16);
qCritical() << QString("dynCond->CBinDebounced %1 (%2)").arg((unsigned char)dynCond->CBinDebounced).arg((unsigned char)dynCond->CBinDebounced, 0, 16);
qCritical() << QString("dynCond->upperDoor %1 (%2)").arg((unsigned char)dynCond->upperDoor).arg((unsigned char)dynCond->upperDoor, 0, 16);
qCritical() << QString("dynCond->middleDoor %1 (%2)").arg((unsigned char)dynCond->middleDoor).arg((unsigned char)dynCond->middleDoor, 0, 16);
qCritical() << QString("dynCond->lowerDoor %1 (%2)").arg((unsigned char)dynCond->lowerDoor).arg((unsigned char)dynCond->lowerDoor, 0, 16);
qCritical() << QString("dynCond->middleDoor %1 (%2)").arg((unsigned char)dynCond->middleDoor).arg((unsigned char)dynCond->middleDoor, 0, 16);
qCritical() << QString("dynCond->coinAttached %1 (%2)").arg((unsigned char)dynCond->coinAttached).arg((unsigned char)dynCond->coinAttached, 0, 16);
qCritical() << QString("dynCond->billBox %1 (%2)").arg((unsigned char)dynCond->billBox).arg((unsigned char)dynCond->billBox, 0, 16);
qCritical() << QString("dynCond->modeAbrech %1 (%2)").arg((unsigned char)dynCond->modeAbrech).arg((unsigned char)dynCond->modeAbrech, 0, 16);
qCritical() << QString("dynCond->onAlarm %1 (%2)").arg((unsigned char)dynCond->onAlarm).arg((unsigned char)dynCond->onAlarm, 0, 16);
qCritical() << QString("dynCond->nowCardTest %1 (%2)").arg((unsigned char)dynCond->nowCardTest).arg((unsigned char)dynCond->nowCardTest, 0, 16);
qCritical() << QString("dynCond->nowPayment %1 (%2)").arg((unsigned char)dynCond->nowPayment).arg((unsigned char)dynCond->nowPayment, 0, 16);
qCritical() << QString("dynCond->lastMifCardType %1 (%2)").arg((unsigned char)dynCond->lastMifCardType).arg((unsigned char)dynCond->lastMifCardType, 0, 16);
qCritical() << QString("dynCond->lastSDoorState %1 (%2)").arg(dynCond->lastSDoorState).arg(dynCond->lastSDoorState, 0, 16);
qCritical() << QString("dynCond->lastVDoorState %1 (%2)").arg(dynCond->lastVDoorState).arg(dynCond->lastVDoorState, 0, 16);
qCritical() << QString("dynCond->lastCBstate %1 (%2)").arg(dynCond->lastCBstate).arg(dynCond->lastCBstate, 0, 16);
qCritical() << QString("dynCond->paymentInProgress %1 (%2)").arg((unsigned char)dynCond->paymentInProgress).arg((unsigned char)dynCond->paymentInProgress, 0, 16);
qCritical() << QString("dynCond->U_Batt %1 (%2)").arg(dynCond->U_Batt).arg(dynCond->U_Batt, 0, 16);
qCritical() << QString("dynCond->nrCoinsInBox %1 (%2)").arg(dynCond->nrCoinsInBox).arg(dynCond->nrCoinsInBox, 0, 16);
qCritical() << QString("dynCond->amountInBox %1 (%2)").arg(dynCond->amountInBox).arg(dynCond->amountInBox, 0, 16);
qCritical() << QString("dynCond->totalTransVolume %1 (%2)").arg(dynCond->totalTransVolume).arg(dynCond->totalTransVolume, 0, 16);
qCritical() << QString("dynCond->totalNrOfVends %1 (%2)").arg(dynCond->totalNrOfVends).arg(dynCond->totalNrOfVends, 0, 16);
qCritical() << QString("dynCond->resultOfLastTemplPrint %1 (%2)").arg((unsigned char)dynCond->resultOfLastTemplPrint).arg((unsigned char)dynCond->resultOfLastTemplPrint, 0, 16);
qCritical() << QString("dynCond->lastPrinterStatus %1 (%2)").arg(dynCond->lastPrinterStatus).arg(dynCond->lastPrinterStatus, 0, 16);
qCritical() << QString("dynCond->startupTestIsRunning %1 (%2)").arg(dynCond->startupTestIsRunning).arg(dynCond->startupTestIsRunning, 0, 16);
qCritical() << QString("dynCond->totalNrOfCuts %1 (%2)").arg(dynCond->totalNrOfCuts).arg(dynCond->totalNrOfCuts, 0, 16);
qCritical() << QString("dynCond->nextAccountNumber %1 (%2)").arg(dynCond->nextAccountNumber).arg(dynCond->nextAccountNumber, 0, 16);
qCritical() << QString("dynCond->nrOfBillsInBox %1 (%2)").arg(dynCond->nrOfBillsInBox).arg(dynCond->nrOfBillsInBox, 0, 16);
qCritical() << QString("dynCond->UbatAtLastPrint %1 (%2)").arg(dynCond->UbatAtLastPrint).arg(dynCond->UbatAtLastPrint, 0, 16);
}
char T_datif::loadRecDataFromFrame()
{
// is called even with wrong received data in order to speed up the process (stop waiting for response)
@ -478,10 +582,12 @@ char T_datif::loadRecDataFromFrame()
if (gpi_getNowIsBootload())
{
datif_cmdWasPerformed=1;
cycl_running=100; // stop waiting for response and wait 1cycle till next sending
cycl_running=GOTRESP_SENDGAP; // stop waiting for response and wait 1cycle till next sending
return 0;
}
memset(receivedData, 0x00, sizeof(receivedData));
ret=myDCIF->getReceivedInData(&SlaveAdr, &readSource, &readAddress, &RdDleng, receivedData);
// nur true wenn CommandState OK und readState OK
@ -504,16 +610,127 @@ char T_datif::loadRecDataFromFrame()
receivedData[12], receivedData[13], receivedData[14], receivedData[15]);
*/
datif_cmdWasPerformed=2; // NO :((
cycl_running=100; // stop waiting for response and wait 1cycle till next sending
cycl_running=GOTRESP_SENDGAP; // stop waiting for response and wait 1cycle till next sending
return 0;
}
datif_cmdWasPerformed=1; // YES :), stop repeating
cycl_running=100; // stop waiting for response
cycl_running=GOTRESP_SENDGAP; // stop waiting for response
//qDebug() << "datif: got valid response ";
gpi_storeRecPayLoad(RdDleng, receivedData); // save for host (user of hwapi)
if (myDCIF && myDCIF->getSerialPort()) {
uint32_t writeCount = myDCIF->getSerialPort()->getWriteCount();
if ((readCount + 1) == writeCount) { // there can be only one command sent to the DC
readCount = writeCount;
if (readSource != myDCIF->getReadSource()) {
qCritical() << __func__ << ":" << __LINE__ << ": ERROR length" << RdDleng << ", ignore data"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
qCritical() << __func__ << ":" << __LINE__ << "would be interpretated as" << readSource << myDCIF->getReadSource();
return 0;
} else {
// only for debugging
// qCritical() << __func__ << ":" << __LINE__ << QDateTime::currentDateTime().time().toString(Qt::ISODateWithMs) << readSource << myDCIF->getReadSource();
if (readSource == 30) {
T_moduleCondition const *modCond = reinterpret_cast<T_moduleCondition const *>(receivedData);
if(modCond->rtc >= 200) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E002 (modCond->rtc >= 200)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (modCond->printer == 200 || modCond->printer == 201) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E020 (modCond->printer == 200 || modCond->printer == 201)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (modCond->printer == 202) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E018 (modCond->printer == 202)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (modCond->coinBlocker >= 200) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E025 (modCond->coinBlocker >= 200)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (modCond->mdbBus >= 200) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E034 (modCond->mdbBus >= 200)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (modCond->intEe >= 200) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E011 (modCond->intEe >= 200)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (modCond->voltage >= 200) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E003 (modCond->voltage >= 200)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (modCond->changer >= 200) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E026 (modCond->changer >= 200)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (modCond->coinSafe == 201) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E007 (modCond->coinSafe == 201)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (modCond->coinSafe == 200) {
dump(modCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E009 (modCond->coinSafe == 200)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
}
if (readSource == 31) {
T_dynamicCondition const *dynCond = reinterpret_cast<T_dynamicCondition const *>(receivedData);
if (dynCond->modeAbrech > 0) {
dump(dynCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E011 (dynCond->modeAbrech > 0)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (dynCond->nowCardTest > 0) {
dump(dynCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E072 (dynCond->nowCardTest > 0)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
if (dynCond->startupTestIsRunning > 0) {
dump(dynCond);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR E073 (dynCond->startupTestIsRunning > 0)"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
}
}
} else {
qCritical() << __func__ << ":" << __LINE__ << QString(": ERROR readCount + 1 != writeCount: %1 != %2").arg(readCount + 1).arg(writeCount);
qCritical() << __func__ << ":" << __LINE__ << ": ERROR length" << RdDleng << ", ignore data"
<< QByteArray((char const *)receivedData, RdDleng).toHex(':');
qCritical() << __func__ << ":" << __LINE__ << "would be interpretated as" << readSource << myDCIF->getReadSource();
if (readSource == 30) {
T_moduleCondition const *modCond = reinterpret_cast<T_moduleCondition const *>(receivedData);
dump(modCond);
}
if (readSource == 31) {
T_dynamicCondition const *dynCond = reinterpret_cast<T_dynamicCondition const *>(receivedData);
dump(dynCond);
if (dynCond->coinAttached > 0) {
qCritical() << __func__ << ":" << __LINE__ << ": dynCond->coinAttached"
<< QByteArray(reinterpret_cast<char const *>(receivedData), RdDleng).toHex(':');
}
}
readCount = writeCount;
return 0;
}
}
// uint8_t nn;
//qDebug() << "\n datif: got valid data, rdsrc:" << readSource << " rdadd:" << readAddress
// << " rdlen:" << RdDleng;
@ -546,6 +763,9 @@ char T_datif::loadRecDataFromFrame()
localStr.append(ctmp);
}
if (readSource==0)
return 0; // done
//qDebug() << "got HW version: " << localStr;
switch (readSource) // = request command
{
@ -924,22 +1144,6 @@ char T_datif::loadRecDataFromFrame()
break;
// ab hier neu: 12.4.23
case CMD2DC_RDBK_DEV_PARA: //14
/*
buf66[0]=devPara.kindOfPrinter;
@ -990,22 +1194,30 @@ char T_datif::loadRecDataFromFrame()
case 112: // get inserted amount in cent in sum
// byte 0..3: amount just paid 4,5:last coin type 6,7: last coin value
newInsertedAmount=uchar2ulong(receivedData[3],receivedData[2],receivedData[1],receivedData[0]);
uitmp=uchar2uint(receivedData[5],receivedData[4]);
uit2=uchar2uint(receivedData[7],receivedData[6]);
//if (uitmp>0) // nur 1x bei neuer Münze 6.10.23 aendern: beim Wechsler hat die kleinste Muenze immer coin type 0!
if (uit2>0)
{
gpi_storeCurrentPayment(newInsertedAmount, uitmp, uit2);
//void gpi_storeCurrentPayment(uint32_t insertedAmount, uint16_t lastCoinType, uint16_t lastCoinValue)
if (newInsertedAmount != lastInsertedAmount)
{
emit datif_gotNewCoin();
//qDebug()<<"emit new coin";
uitmp=uchar2uint(receivedData[5],receivedData[4]); // type of last coin
uit2=uchar2uint(receivedData[7],receivedData[6]); // value of last coin
//if (uitmp>0) // nur 1x bei neuer Münze 6.10.23 aendern:
// beim Wechsler hat die kleinste Muenze immer coin type 0!
lastInsertedAmount=newInsertedAmount;
}
// qDebug()<<"datif store new coin"<<newInsertedAmount<<" "<<uitmp<<" "<<uit2;
if (uitmp>10000 || uit2>10000)
{
uitmp=0;
uit2=0;
}
if (uit2==3 || uit2==5 || uit2==10 || uit2==20 || uit2==40 || uit2==50 || uit2==100 || uit2==200 || uit2==500)
{
// valid coin
if ((newInsertedAmount != lastInsertedAmount) || uit2>0 )
{
gpi_storeCurrentPayment(newInsertedAmount, uitmp, uit2);
emit datif_gotNewCoin(); // OR BILL if (uitmp & 0x8000)>0
//qDebug()<<"emit new coin";
lastInsertedAmount=newInsertedAmount;
//qCritical()<<"datif 112 store and emit new coin "<<newInsertedAmount<<" "<<uitmp<<" "<<uit2;
}
}
break;
case 113: // get wake source, 8byte
@ -1031,33 +1243,24 @@ char T_datif::loadRecDataFromFrame()
if (RdDleng>28)
{
gpi_storeDeviceConditions(RdDleng, receivedData);
datif_nowNewStats=1; // 24.7.24 new
}
break;
case 31: // Get dynamic machine conditions (doors, voltage, alarm….)
if (RdDleng>50)
{
epi_setDcDataValid(); // DC-Data are valid as DC responded.
// Could be set to every response but this (31)
// is a very common and very important request
gpi_storeDynMachineConditions(RdDleng, receivedData);
}
/* funktioniert, ist aber nicht nötig. Signal wird nach dem shared memory erzeugt
prnResult=receivedData[52];
if (prnResult != lastResult)
{
// new result
if (prnResult==1)
{
emit datif_templatePrintFinished_OK();
} else
if (prnResult==2)
{
emit datif_templatePrintFinished_Err();
}
// first 64 bytes, rest comes with cmd 34
lastResult=prnResult;
}*/
if (RdDleng>60)
{
//epi_setDcDataValid(); // 24.7.24 remove here
datif_nowNewDyns=1; // 24.7.24 new
gpi_storeDynMachineConditions(RdDleng, receivedData);
gpi_storeDI_CoinAttach(receivedData[6]); // new, 14.2.24 needed for direct coin insertion
} else
qDebug()<<"datif received cmd31 with "<<RdDleng<<" bytes only";
break;
@ -1073,24 +1276,22 @@ char T_datif::loadRecDataFromFrame()
gpi_storeDCbackupAccNr(RdDleng, receivedData);
break;
case 34: // Get dynamic machine conditions part 2
if (RdDleng>5)
{
gpi_storeDynMachCond2(RdDleng, receivedData);
//qDebug()<<"datif rec. cmd34: ";
//for (int nn=0; nn<64; nn++)
// qDebug() << nn << " : " << receivedData[nn] << " ";
}
break;
case 35:
gpi_storeMifCardType(RdDleng, receivedData);
break;
case 38: // Get stored account record backup
// readAddress, &RdDleng, receivedData
//if (RdDleng>50) // 1.8.23 nach Verlängerung des Datensatzes um 20byte falsch!!!
//{
gpi_storeVaultRecord(readAddress, receivedData ); // always/max 64byte
/*
qDebug()<<"datif cmd38 got vault data. blockNr: "<<readAddress;
if (readAddress==0)
for (nn=0; nn<64; nn+=8)
{
qDebug()<<receivedData[nn]<<" "<<receivedData[nn+1]<<" "<<receivedData[nn+2]<<" "<<receivedData[nn+3]<<" "
<<receivedData[nn+4]<<" "<<receivedData[nn+5]<<" "<<receivedData[nn+6]<<" "<<receivedData[nn+7];
}
*/
//}
break;
case 39:
@ -1136,6 +1337,9 @@ char T_datif::loadRecDataFromFrame()
}
break;
default:
qCritical()<<"datif, error received unknown cmd "<< readSource;
}
readSource=0; // 17.05.2023: to avoid multiple recording

320
src/download_thread.cpp Normal file
View File

@ -0,0 +1,320 @@
#include "download_thread.h"
#include "shared_mem_buffer.h"
#include "hwapi.h"
#include <QDebug>
#include <QDateTime>
DownloadThread::DownloadThread(hwinf *hw)
: m_hw(hw)
, m_fileToDownload(m_hw->dcDownloadFileName()) {
// connect(this, &QThread::finished,
// dynamic_cast<QObject const *>(m_hw), &QThread::deleteLater);
}
DownloadThread::~DownloadThread() {
}
/*
///////////////////////////////////////////////////////////////////////////////
//
// USING THE DC BOOTLOADER
//
///////////////////////////////////////////////////////////////////////////////
1 : bl_reboot() // send to application, want DC2 to reset (in order to
// start the bootloader)
//
// NOTE: this function is NOT reliable !!! Sometimes it
// simply does not work, in which case bl_startBL,
// bl_checkBL and bl_isUp do not work as well.
// Alas, there is no feedback if bl_reboot worked!
//
// NOTE: this function can be called only once per
// minute, because once called again, the controller
// performs some self-checks consuming some time.
//
// NOTE: after a successful bl_reboot(), the device is
// waiting about 4 seconds in the bootloader. To stay in
// the bootloader, we have to send the command
// bl_startBL(), which is kind of a misnomer, as it
// should be bl_doNotLeaveBL().
//
2 : bl_startBL(): // send within 4s after DC power-on, otherwise
// bootloader is left.
//
// NOTE: a running bootloader is a MUST for the download
// process of a device controller firmware as it does
// the actual writing of the memory (the bl_reboot()
// from above erases the available memory).
//
3 : bl_check(): // send command to verify if bl is up
//
// NOTE: this command is kind of a request that we want
// to check if the bootloader is up. The device
// (actually the bootloader) responds with its version.
//
4 : bl_isUp(): // returns true if bl is up and running
//
// NOTE: we know what the bootloader version actually is
// as the bootloader does not change. By comparing the
// string received in the previous step with this known
// version string we know if the bootloader is up.
//
// NOTE FOR ALL PREVIOUS STEPS: execute them in their
// own slots each to be sure to receive any possible
// responds from the device.
//
5 : bl_sendAddress(blockNumber)
// send start address, nr of 64-byte block, start with 0
// will be sent only for following block-numbers:
// 0, 1024, 2048, 3072 and 4096, so basically every
// 64kByte.
// for other addresses nothing happens
6 : bl_wasSendingAddOK()
// return val: 0: no response by now
// 1: error
// 10: OK
7 : bl_sendDataBlock()
// send 64 byte from bin file
8 : bl_sendLastBlock()
// send this command after all data are transferred
9 : bl_wasSendingDataOK()
// return val: 0: no response by now
// 1: error
// 10: OK
10 : bl_stopBL() // leave bl and start (the new) application
//
// NOTE: this function MUST work under all conditions.
// Alas, there is no direct result for this command, so
// the only way of knowing it was successful is to ask
// the device if the bootloader is still running.
// There is no problem to repeat this command until the
// bootloader is really not running anymore.
*/
void DownloadThread::run() {
// download thread running in ca-master sends the dc-file down to firmware
// TODO: send the json files as well
m_hw->dcDownloadRequestAck();
qCritical() << "DownloadThread::run(): DOWNLOAD THREAD STARTED";
// load binary device controller file into memory
QByteArray ba = loadBinaryDCFile(m_hw->dcDownloadFileName());
if (ba.size() > 0) {
uint16_t const totalBlocks = (((ba.size())%64)==0) ? (ba.size()/64) : (ba.size()/64)+1;
m_hw->dcDownloadSetTotalBlockNumber(totalBlocks);
// fill last block of data to be sent with 0xFF
ba = ba.leftJustified(totalBlocks*64, (char)(0xFF));
resetDeviceController();
if (startBootloader()) {
qCritical() << "DownloadThread::run(): TOTAL NUMBER OF BYTES TO SEND TO DC" << ba.size();
qCritical() << "DownloadThread::run(): TOTAL NUMBER OF BLOCKS" << totalBlocks;
int currentBlock = 0;
DownloadResult res = DownloadResult::OK;
qCritical() << "64-byte block " << currentBlock;
while (res != DownloadResult::ERROR && currentBlock < totalBlocks) {
if ((res = sendNextAddress(currentBlock)) != DownloadResult::ERROR) {
if ((res = sendNextDataBlock(ba, currentBlock)) != DownloadResult::ERROR) {
m_hw->dcDownloadSetCurrentBlockNumber(currentBlock);
currentBlock += 1;
}
}
}
qCritical() << "DownloadThread::run(): last 64-byte block %04d" << currentBlock;
int const rest = ba.size() % 64;
int const offset = ba.size() - rest;
char const *startAddress = ba.constData() + offset;
if (rest > 0) {
// SHOULD NEVER HAPPEN !!!
uint8_t local[66];
memset(local, 0xFF, sizeof(local));
memcpy(local, startAddress, rest);
qCritical() << "DownloadThread::run(): ERROR SEND REMAINING" << rest << "BYTES";
m_hw->bl_sendDataBlock(64, local);
} else {
m_hw->bl_sendLastBlock();
m_hw->dcDownloadSetCurrentBlockNumber(currentBlock);
}
qCritical() << "DownloadThread::run(): last result" << (int)sendStatus(m_hw->bl_wasSendingDataOK());
}
stopBootloader(); // there is no harm in stopping the bootloader even
} // if it was not started at all
#if 0
// test code:
uint16_t const totalBlocks = 100;
m_hw->dcDownloadSetTotalBlockNumber(totalBlocks);
for (uint16_t currentBlock = 0; currentBlock <= totalBlocks; ++currentBlock) {
m_hw->dcDownloadSetCurrentBlockNumber(currentBlock);
QThread::msleep(100);
}
#endif
m_hw->dcDownloadSetRunning(false);
m_hw->dcDownloadSetFinished(true);
qCritical() << QDateTime::currentDateTime().toString(Qt::ISODate) + "DOWNLOAD THREAD FINISHED";
// the object deletes itself ! This is the last line in run().
// Never touch the object after this statement
// m_hw->dcDownloadThreadFinalize(this);
}
DownloadThread::DownloadResult DownloadThread::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;
}
DownloadThread::DownloadResult
DownloadThread::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);
QThread::msleep(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";
// TODO: hier ins shared-mem schreiben
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;
}
DownloadThread::DownloadResult
DownloadThread::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;
// QByteArray b((const char *)(&local[0]), 64);
// qCritical() << "SNDB" << bNum << b.size() << b.toHex();
while (noAnswerCount <= 250) {
m_hw->bl_sendDataBlock(64, local);
QThread::msleep(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";
// TODO: hier ins shared mem schreiben
return res;
}
} else {
noAnswerCount += 1; // no answer by now
}
}
// wait max. about 3 seconds
return DownloadResult::TIMEOUT;
}
bool DownloadThread::startBootloader() const {
qDebug() << "starting bootloader...";
int nTry = 5;
while (--nTry >= 0) {
m_hw->bl_startBL();
QThread::msleep(5000);
m_hw->bl_checkBL();
if (m_hw->bl_isUp()) {
qInfo() << "starting bootloader...OK";
QThread::msleep(5000);
return true;
} else {
qCritical() << "bootloader not up (" << nTry << ")";
}
}
qCritical() << "starting bootloader...FAILED";
return false;
}
bool DownloadThread::stopBootloader() const {
qDebug() << "stopping bootloader...";
int nTry = 5;
while (--nTry >= 0) {
m_hw->bl_stopBL();
QThread::msleep(500);
if (!m_hw->bl_isUp()) {
qInfo() << "stopping bootloader...OK";
return true;
}
}
qCritical() << "stopping bootloader...FAILED";
return false;
}
bool DownloadThread::resetDeviceController() const {
qDebug() << "resetting device controller...";
m_hw->bl_rebootDC();
// wait maximally 3 seconds, before starting bootloader
QThread::sleep(1);
qInfo() << "resetting device controller...OK";
return true;
}
QByteArray DownloadThread::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();
}

470
src/hwapi.cpp Normal file → Executable file
View File

@ -5,21 +5,17 @@
* This api uses stored data and returns them in the following functions
* created: Q1/2020 TS until Q2/21
14.7.23TS: patch for correct printer state in line 3364 in sys_getDeviceConditions(struct T_moduleCondition *devCond) const
8.9.2023 two new functions (end of file) for mifare test. Interface version 4.4 DC4.40...4.43
14.09.2023: Verriegelung eingebaut, nur noch gültige Abr.Daten zurückgeben, Suchbegriff: <epi_restoreVaultRecord>
alle Mifare-Funktionen ueberprueft und ggf verbessert
18.09.2023: Signal "Kasse entnommen" und Signale "Tuer auf/zu" ueberprueft
20.9.2023: in datif die Abfrage der DynMachineData massiv beschleunigt
und hier in hwapi die entprellten Werte fuer Tueren und Kasse verwenden.
Problem war: Signal "Kasse entnommen" war zu langsam -> manchmal abr nicht gesendet
see history in hwapi.h
*/
#include "hwapi.h"
#include "download_thread.h"
#include "reporting_thread.h"
#include <cstring>
#include <QThread>
#include <QDebug>
static uint32_t hwapi_lastStartAmount;
static uint32_t hwapi_lastTotalAmount;
@ -30,9 +26,15 @@ static uint8_t bl_startupStep;
hwapi::hwapi(QWidget *parent) : QObject(parent)
hwapi::hwapi(QObject *parent) : QObject(parent)
{
// constructor
qCritical() << " hwapi::hwapi() APP_VERSION:" << APP_VERSION;
qCritical() << " hwapi::hwapi() APP_BUILD_DATE:" << APP_BUILD_DATE;
qCritical() << " hwapi::hwapi() APP_BUILD_TIME:" << APP_BUILD_TIME;
qCritical() << " hwapi::hwapi() APP_EXTENDED_VERSION:" << APP_EXTENDED_VERSION;
qCritical() << "hwapi::hwapi() APP_EXTENDED_VERSION_LIB:" << APP_EXTENDED_VERSION_LIB;
// create or attach shared memory segment
m_sharedMem = SharedMem::getShm(sizeof(SharedMem));
@ -54,7 +56,7 @@ hwapi::hwapi(QWidget *parent) : QObject(parent)
#error "SLAVE LIB COMPILED INTO MASTER"
#endif
myDatif = new T_datif(); // für die CAslave-Lib auskommentieren!
myDatif = new T_datif(this); // für die CAslave-Lib auskommentieren!
#endif
@ -115,8 +117,7 @@ hwapi::hwapi(QWidget *parent) : QObject(parent)
connect(runProcess, SIGNAL(runProc_doorCoinBoxInserted()), this, SLOT(sub_slotCoin14())); // hwapi_doorCoinBoxInserted()));
connect(runProcess, SIGNAL(runProc_doorCBinAndAllDoorsClosed()), this, SLOT(sub_slotCoin15())); // hwapi_doorCBinAndAllDoorsClosed()));
connect(runProcess, SIGNAL(runProc_doorAllDoorsClosed()), this, SLOT(sub_slotCoin16())); // hwapi_doorAllDoorsClosed()));
connect(runProcess, SIGNAL(runProc_coinAttached()), this, SLOT(coinAttached()));
}
void hwapi::hwapi_slotPayProc(void)
@ -214,6 +215,9 @@ void hwapi::sub_slotCoin16(void)
emit hwapi_doorAllDoorsClosed();
}
void hwapi::coinAttached() {
emit hwapi_coinAttached();
}
/*
@ -1752,8 +1756,10 @@ QString hwapi::mif_getCardDataStr(uint8_t blockNumber) const
uint8_t hwapi::prn_getHwState(struct Tprn_hw_state *prn_hw_state) const
{
// return printer hardware state: power is on? rs-driver on? rs_switch ok? hw-ready-line ok?
// printer on error or ok?
// return value:
// 0: unknown 1: printer OK
// 100: printer OK but paper near end
// 200: not connected 201: printer on error 202: no paper
return runProcess->prn_getHwState(prn_hw_state);
@ -1761,13 +1767,8 @@ uint8_t hwapi::prn_getHwState(struct Tprn_hw_state *prn_hw_state) const
bool hwapi::prn_isUpAndReady(void) const
{
// 25.5.2023: geht nicht richtig :( bringt immer false obwohl Drucker OK
struct Tprn_hw_state prnHwNow;
prn_getHwState(&prnHwNow);
if (prnHwNow.inIdle && prnHwNow.rsSwOk && prnHwNow.rsDrvOk && prnHwNow.powerRdBk )
return true;
return false;
// gefixt am 24.5.2024
return runProcess->prn_isUpAndReady();
}
void hwapi::prn_getCurrentFontSetting(struct Tprn_currentSettings *prn_fonts) const
@ -1791,46 +1792,10 @@ void hwapi::prn_getCurrentFontSetting(struct Tprn_currentSettings *prn_fonts) co
void hwapi::prn_sendText(QByteArray *buf) const
{
uint16_t nn, pp, mm, leng_byt, leng_blk, llb, freeStak;
uint8_t tmp66[66];
qCritical() << __PRETTY_FUNCTION__ << "RESET DC DATA VALID";
epi_clearDynMachineConditions(); // 24.6.23
gpi_storeDcDataValid(0);
// komplett aendern 11.9.23
memset(tmp66,0,66);
leng_byt=buf->size();
freeStak=check4freeFDstack();
freeStak<<=6;
if ( leng_byt > freeStak)
{
leng_byt=freeStak; // shorten the buffer as we cannot return an error (void function)
}
llb=leng_byt % 64; // length of last block, >0 if not dividable by 64
leng_blk=leng_byt / 64;
pp=0;
for (nn=0; nn<leng_blk; nn++)
{
for (mm=0; mm<64; mm++)
tmp66[mm]=buf->at(pp++);
longFDcmd_set(CMD2DC_PRI_PRINT_TXT, 0,0,64, tmp66);
}
if (llb>0)
{
//leng_blk++; // z.B. 200 = 3 volle blocks und ein block mit nur 8byte
memset(tmp66,0,66);
for (mm=0; mm<llb; mm++)
tmp66[mm]=buf->at(pp++);
for (mm=llb; mm<64; mm++)
tmp66[mm]=0;
longFDcmd_set(CMD2DC_PRI_PRINT_TXT, 0,0,64, tmp66);
}
runProcess->prn_sendText(buf);
// 23.5.2024TS: moved function down to runProc in order to have it available there.
// here in hwapi only a wrapper left
// ( this also supports the idea to keep hwapi short :)
}
@ -1839,6 +1804,8 @@ void hwapi::prn_sendPrnSysCmd(uint8_t para1, uint8_t para2, uint32_t para3) cons
// send three byte through to printer, see printers manual
//sendWRcmd _setSendCommand8(SENDDIRCMD_PRN_SYS_CMD, para1, para2, 0, para3); hat gar nicht funktioniert
runProcess->prn_sendPrnSysCmd(para1, para2, para3);
/*
uint8_t data[64];
uint32_t ultmp=para3;
memset(data, 0,64);
@ -1852,6 +1819,7 @@ void hwapi::prn_sendPrnSysCmd(uint8_t para1, uint8_t para2, uint32_t para3) cons
data[7]=uint8_t(ultmp);
longFDcmd_set(CMD2DC_PRI_SYS_CMD, 0, 0, 8, data);
*/
// getestet auf richtige uebertragung am 11.9.23TS
}
@ -1869,7 +1837,7 @@ void hwapi::prn_sendPrnSetup(uint16_t paperSpeed, uint8_t density, uint8_t alig
// byte3: alignment 'l', 'c', 'r' = left, center, right
// byte4: orientation 0, 90, 180 = 0°, 90°, 180° rotation (by now not supported!)
// not batched! don't use twice within 100ms
/*
uint8_t buf[10];
uint16_t uitmp;
@ -1882,7 +1850,8 @@ void hwapi::prn_sendPrnSetup(uint16_t paperSpeed, uint8_t density, uint8_t alig
buf[4]=orientation;
buf[5]=0;
longFDcmd_set(CMD2DC_PRI_SETUP,0,0,5, buf);
*/
runProcess->prn_sendPrnSetup(paperSpeed, density, alignment, orientation);
}
void hwapi::prn_movePaper(uint8_t wayInMm, uint8_t direction) const
@ -2788,6 +2757,7 @@ bool hwapi::rtc_getExtendedTime(struct T_extTime *exTime) const
epi_restoreExtendedTime(&len, buf);
// Puffer in struct eintragen:
LL=sizeof(struct T_extTime);
if (LL>64) LL=64;
start = &(exTime->Hours);
nn=0;
do
@ -3168,10 +3138,11 @@ void hwapi::sys_getDeviceConditions(struct T_moduleCondition *devCond) const
uint8_t *start;
uint8_t buf[70], leng;
epi_restoreDeviceConditions(&leng, buf);
epi_restoreDeviceConditions(&leng, buf); // leng is less then 64
// Puffer in struct eintragen:
LL=sizeof(struct T_moduleCondition);
if (LL>64) LL=64;
start = &devCond->ram;
nn=0;
do
@ -3213,26 +3184,27 @@ void hwapi::sys_getDeviceConditions(struct T_moduleCondition *devCond) const
void hwapi::sys_getDynMachineConditions(uint8_t *leng, uint8_t *data) const
{
// not complete anymore
epi_restoreDynMachineConditions(leng, data);
}
void hwapi::sys_getDynMachineConditions(struct T_dynamicCondition *dynMachCond) const
{
uint16_t LL, nn;
char *start;
uint8_t buf[70], leng;
uint8_t buf[130], leng;
epi_restoreDynMachineConditions(&leng, buf);
// Puffer in struct eintragen:
LL=sizeof(struct T_dynamicCondition);
start = &dynMachCond->allDoorsDebounced;
nn=0;
do
{
*start = buf[nn];
start++;
} while(++nn<LL);
memcpy(dynMachCond, buf, sizeof(*dynMachCond)); // copy 64byte to the struct
// 3.7.24: stimmt nicht mehr weil struct im Ram die word grenzen einhaelt
// also ab hier einzeln uebertragen
dynMachCond->totalNrOfCuts = uchar2ulong(buf[57],buf[56],buf[55],buf[54]);
dynMachCond->nextAccountNumber = uchar2uint(buf[59], buf[58]);
dynMachCond->nrOfBillsInBox = uchar2uint(buf[61], buf[60]);
// 8.5.24TS, as the DC struct is >64byte now, it comes in two parts:
epi_restoreDynMachCond2(&leng, buf);
dynMachCond->amountInBillbox = uchar2ulong(buf[3], buf[2],buf[1],buf[0]);
dynMachCond->UbatAtLastPrint = uchar2uint(buf[5], buf[4]);
memcpy(&dynMachCond->reserve01, &buf[8], 56); // rest reserve
}
@ -3316,14 +3288,11 @@ void hwapi::sys_sendDeviceParameter(struct T_devices *deviceSettings) const
void hwapi::sys_restoreDeviceParameter(struct T_devices *deviceSettings) const
{
// attention: only applies if function "sys_sendDeviceParameter()" was used to send this settings before
// cannot be used to see settings programmed by JsonFile
uint8_t buf[64];
uint8_t LL;
tslib_strclr(buf,0,64);
//runProcess->epi_restore64BdevParameter(&LL, buf); // wozu die???
epi_restoreRbDeviceSettings(&LL, buf); // viel besser, stimmt immer
epi_restoreRbDeviceSettings(&LL, buf);
Q_STATIC_ASSERT(sizeof(*deviceSettings) <= sizeof(buf));
@ -3398,6 +3367,7 @@ void hwapi::prn_requestCurrentDynData(void) const
{
sendFDcmd_set(0,39,0,0,0,0,0); // rd data dynData
epi_clearDynData();
epi_clearDynMachCond2();
}
bool hwapi::prn_getCurrentDynamicPrnValuesFromDC(uint8_t *dynPrnVal ) const
@ -4077,8 +4047,8 @@ int8_t hwapi::bl_blockAutoResponse(void) const
void hwapi::sys_requestJsonVersions(uint8_t jsonNr) const
{
// send one request for every single version
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4=res.
// 5=printer template 1 ..... 36= template 32
// jsonNr=1...36, 1=config file (cust.Nr) 2=devices 3=cash 4,5=empty
// 6=printer template 1 ..... 37= template 32
sendFDcmd_set(0, 21, jsonNr,0,0,0,0);
}
@ -4283,7 +4253,7 @@ bool hwapi::bna_getAllParameters(struct T_bna *bna) const
bna->intendedAccept = uchar2uint(buf[31], buf[30]);
bna->pad2=0;
pp=32;
for (nn=0; nn<16; nn++)
for (nn=0; nn<8; nn++) // was 16!!! // 8.5.24 reduced
{
bna->billDenomination[nn] = uchar2uint(buf[pp+1], buf[pp]);
pp+=2;
@ -4388,3 +4358,327 @@ uint16_t hwapi::bna_getStackerLevel(uint32_t *amountInStacker, uint16_t *countOf
}
// new, 14.3.24TS
bool hwapi::cash_isCollectionStarted(void) const
{
struct T_dynamicCondition myDynMachCond;
sys_getDynMachineConditions(&myDynMachCond);
if (myDynMachCond.paymentInProgress >=2)
return true;
return false;
}
QObject const *hwapi::getAPI() {
return this;
}
bool hwapi::dcDownloadRequest(QString const &dcFileToDownload) const {
SharedMem *data = SharedMem::getData();
if (!data) {
return false;
}
char *fNameBuffer = data->m_downLoadDC.m_filename[(int)SharedMem::DCDownload::FILE_INDEX::DC_BINARY];
size_t const size = sizeof(data->m_downLoadDC.m_filename);
std::memset(fNameBuffer, 0x00, size);
std::memcpy(fNameBuffer, dcFileToDownload.toStdString().c_str(),
std::min(size, strlen(fNameBuffer)-1));
data->m_downLoadDC.m_totalBlocks = 0;
data->m_downLoadDC.m_currentblockNumber = 0;
data->m_downLoadDC.m_requested = true;
data->m_downLoadDC.m_running = false; // download thread is not running
data->m_downLoadDC.m_finished = true;
return true;
}
bool hwapi::dcDownloadRequested() const {
SharedMem const *data = SharedMem::getData();
// should be false at entry
return data ? data->m_downLoadDC.m_requested.load() : false;
}
bool hwapi::dcDownloadResetRequest() const {
SharedMem *data = SharedMem::getData();
if (data) {
data->m_downLoadDC.m_requested = false;
}
return true;
}
bool hwapi::dcDownloadRequestAck() const {
SharedMem *data = SharedMem::getData();
if (data) {
if (data->m_downLoadDC.m_requested) {
data->m_downLoadDC.m_requested = false;
data->m_downLoadDC.m_running = true;
data->m_downLoadDC.m_finished = false;
}
}
return false;
}
bool hwapi::dcDownloadRunning() const {
SharedMem const *data = SharedMem::getDataConst();
if (data) {
int cnt = 10;
while (--cnt > 0) {
bool running = data->m_downLoadDC.m_running.load();
bool finished = data->m_downLoadDC.m_finished.load();
if (!running || finished) {
if (cnt < 3) {
qCritical() << "DOWNLOAD THREAD NOT RUNNING" << running << finished;
}
QThread::msleep(500);
} else break;
}
// qCritical() << "DOWNLOAD RUNNING" << cnt << (cnt > 0);
return (cnt > 0);
}
return false;
}
void hwapi::dcDownloadThreadFinalize(DownloadThread *dthread) {
delete dthread;
m_downloadThread = nullptr;
}
bool hwapi::dcDownloadFinished() {
SharedMem const *data = SharedMem::getDataConst();
if (data) {
int cnt = 10;
while ((--cnt > 0) &&
((data->m_downLoadDC.m_running.load() == true) &&
(data->m_downLoadDC.m_finished.load() == false))) {
QThread::sleep(1);
}
//if (cnt > 0) {
// delete m_downloadThread;
// m_downloadThread = nullptr;
// return true;
//}
}
return false;
}
// download thread
bool hwapi::dcDownloadThreadStart() {
m_downloadThread = new DownloadThread(this);
if (m_downloadThread) {
m_downloadThread->start();
int cnt = 10;
while (--cnt > 0 && !dcDownloadThreadRunning()) {
QThread::msleep(200);
}
return (cnt > 0);
}
return false;
}
bool hwapi::dcDownloadThreadRunning() const {
return (dcDownloadGetRunning() == true)
&& (dcDownloadGetFinished() == false);
}
bool hwapi::dcDownloadThreadFinished() const {
return (dcDownloadThreadRunning() == false);
}
// report thread
bool hwapi::dcDownloadReportThreadStart() { // only start reporting thread
int cnt = 10; // if download thread is running
while (--cnt > 0 && !dcDownloadRunning()) {
QThread::msleep(500);
}
if (cnt > 0) {
m_reportingThread = new ReportingThread(this);
if (m_reportingThread) {
m_reportingThread->start();
cnt = 10;
while (--cnt > 0 && !dcDownloadReportThreadRunning()) {
QThread::msleep(200);
}
return (cnt > 0);
}
}
return false;
}
bool hwapi::dcDownloadReportThreadRunning() const {
return m_reportingThread ? m_reportingThread->isRunning() : false;
}
void hwapi::dcDownloadReportThreadFinalize() {
if (m_reportingThread) {
if (m_reportingThread->isFinished()) {
delete m_reportingThread;
m_reportingThread = nullptr;
}
}
}
void hwapi::dcDownloadReportThreadQuit() {
if (m_reportingThread) {
m_reportingThread->quit();
}
}
bool hwapi::dcDownloadReportThreadFinished() const {
return m_reportingThread ? m_reportingThread->isFinished() : false;
}
bool hwapi::dcDownloadReportStart() const {
int cnt = 10;
while (--cnt > 0 && !dcDownloadRunning()) {
QThread::msleep(200);
}
return (cnt == 0);
}
bool hwapi::dcDownloadReportRunning() const {
return dcDownloadReportThreadRunning();
}
bool hwapi::dcDownloadReportFinished() {
int cnt = 10;
while (--cnt > 0 && !dcDownloadReportThreadFinished()) {
QThread::sleep(1);
}
if (cnt == 0 && !dcDownloadReportThreadFinished()) {
return false;
}
if (dcDownloadReportThreadFinished()) {
delete m_reportingThread;
m_reportingThread = nullptr;
}
return true;
}
QString hwapi::dcDownloadFileName() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_filename[(int)SharedMem::DCDownload::FILE_INDEX::DC_BINARY] : "";
}
bool hwapi::dcDownloadSetRequested(bool requested) {
SharedMem *data = SharedMem::getData();
if (data) {
data->m_downLoadDC.m_requested = requested;
return true;
}
return false;
}
bool hwapi::dcDownloadSetRunning(bool running) {
SharedMem *data = SharedMem::getData();
if (data) {
data->m_downLoadDC.m_running = running;
return true;
}
return false;
}
bool hwapi::dcDownloadSetFinished(bool finished) {
SharedMem *data = SharedMem::getData();
if (data) {
data->m_downLoadDC.m_finished = finished;
return true;
}
return false;
}
void hwapi::dcDownloadSetTotalBlockNumber(uint16_t totalBlockNumber) {
SharedMem::getData()->m_downLoadDC.m_totalBlocks = totalBlockNumber;
}
void hwapi::dcDownloadSetCurrentBlockNumber(uint16_t currentBlockNumber) {
SharedMem::getData()->m_downLoadDC.m_currentblockNumber = currentBlockNumber;
}
uint16_t hwapi::dcDownloadGetTotalBlockNumber() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_totalBlocks.load() : 0;
}
uint16_t hwapi::dcDownloadGetCurrentBlockNumber() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_currentblockNumber.load() : 0;
}
bool hwapi::dcDownloadGetRequested() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_requested.load() : 0;
}
bool hwapi::dcDownloadGetRunning() const {
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_running.load() : 0;
}
bool hwapi::dcDownloadGetFinished() const
{
SharedMem const *data = SharedMem::getDataConst();
return data ? data->m_downLoadDC.m_running.load() : 0;
}
//uint16_t dcDownloadGetTotalBlockNumber() const override;
//uint16_t dcDownloadGetCurrentBlockNumber() const override;
//virtual QObject const *getAPI() override;
void hwapi::mod_switchResetline(void)
{
sendFDcmd_set(171,0,0, 2,0,0,0);
}
// new from 22.5.2024, print Json-Printer-Template which
// is stored locally here in PTU memory,
// rather then loading several jsons to DC and tell it to print (until now)
// the local printer-json can have any length using predefined commands
// printing a local printer-json happens like this:
// 1) select a file to be printed from memory
// 2) load, parse, translate and save the file with following function
// 3) set dynamics (values from current transaction)
// 4) send saved file to printer one or several times
// hint: dynamics can be changed at any time without reloading the ticket, just repeat 3) and 4)
void hwapi::prn_translateLocalPrinterJson(QByteArray jsonFile2print) const
{
runProcess->sys_parseFile( jsonFile2print);
runProcess->sys_translateKeys();
}
void hwapi::prnStoreDynamics(char *bufferDynPrintVars[], uint8_t nrOfDyns) const
{
runProcess->prnStoreDynamics(bufferDynPrintVars, nrOfDyns);
// store nrOfDyns (up to 16) dynamics before printing
// max length = 16 byte per dynamic
}
void hwapi::prn_printTranslatedTicket(void) const
{
runProcess->prnStartDirectPrinting();
}
uint8_t hwapi::prn_waitForDirectTicket(void) const
{
return runProcess->prn_getDirectPrintResult();
// return: 0: just printing, wait
// 1: OK - last print was succesful
// 2: error - not printed
// 2: printer error 3: no connection to DC
}

View File

@ -18,11 +18,11 @@ int main(int argc, char *argv[])
#include <stdio.h>
// Must define the interpreter to be the dynamic linker
#ifdef __LP64__
#error "__LP64__ not defined for PTU5"
#else
const char service_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux-armhf.so.3";
#endif
//#ifdef __LP64__
//#error "__LP64__ not defined for PTU5"
//#else
//const char service_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux-armhf.so.3";
//#endif
int main(int argc, char *argv[]) {

13
src/prot.cpp Normal file → Executable file
View File

@ -97,14 +97,22 @@ void T_prot::setRecLen(uint16_t ReadCmd)
void T_prot::setUserWriteData(uint16_t WriteCmd, uint16_t WrAddr, uint8_t WrDatLen, uint8_t *data)
{
int nn;
WriteCommand=WriteCmd;
WriteAddr=WrAddr;
WrDataLength=WrDatLen;
if (WrDataLength>FRAME_DATALEN)
WrDataLength=FRAME_DATALEN;
for (int nn=0; nn<WrDataLength; nn++)
// ui8BLsendData[BL_DATA_LEN];
for (nn=0; nn<WrDataLength; nn++)
ui8OutputData[nn]=data[nn];
// clear the rest. added at 26.6.2024TS. important for printer text
for (nn=WrDataLength; nn<FRAME_DATALEN; nn++)
ui8OutputData[nn]=0;
SendDataValid=1; // always set WR first
kindOfData=0; // 0: binaries, 1:text
this->setRecLen(100); // default: short response
@ -360,6 +368,9 @@ uint8_t recBuffer[FRAME_MAXLEN];
// read from "VCP":
mySerialPort->readFromSerial(Indata, recLength);
//qDebug()<<"prot: got data " << recLength;
memset(recBuffer, 0x00, sizeof(recBuffer));
if (recLength>FRAME_MAXLEN)
recLength=FRAME_MAXLEN;
for (int nn=0; nn<recLength; nn++)

155
src/reporting_thread.cpp Normal file
View File

@ -0,0 +1,155 @@
#include "reporting_thread.h"
#include "shared_mem_buffer.h"
#include "hwapi.h"
#include <QDateTime>
#include <QDebug>
ReportingThread::ReportingThread(hwapi *hw)
: m_hw(hw)
, m_fileToDownload(m_hw->dcDownloadFileName()) {
}
ReportingThread::~ReportingThread() {
}
// download thread running in ca-slave sends reports of download process to
// each component which has connects for the corresponding signals.
void ReportingThread::run() {
qCritical() << QDateTime::currentDateTime() << "START DOWNLOAD THREAD";
static QString report("");
int cnt = 5;
while (!m_hw->dcDownloadGetRunning()) {
if (--cnt > 0) {
report = QString("%1 waiting for download to start %2")
.arg(QDateTime::currentDateTime().toString(Qt::ISODate))
.arg(cnt);
qCritical() << __LINE__ << "STATUS" << report;
emit m_hw->hwapi_reportDCDownloadStatus(report);
QThread::sleep(1);
} else break;
}
#if 0
if (cnt == 0) {
m_hw->dcDownloadResetRequest();
status = QString("%1 reset download request")
.arg(QDateTime::currentDateTime().toString(Qt::ISODate));
qCritical() << __LINE__ << "STATUS" << status;
emit m_hw->hwapi_reportDCDownloadStatus(status);
cnt = 5;
while (!m_hw->dcDownloadRunning()) {
if (--cnt > 0) {
QThread::sleep(1);
} else break;
}
if (cnt == 0) {
status = QString("%1 download request failure")
.arg(QDateTime::currentDateTime().toString(Qt::ISODate));
qCritical() << __LINE__ << "STATUS" << status;
emit m_hw->hwapi_reportDCDownloadFailure(status);
return;
}
}
uint16_t const tnr = 1750;
uint16_t cnr = 0;
while (cnr <= tnr) {
QThread::msleep(100);
QString report("");
if (cnr > 0) {
double percent = ((double)cnr / (double)tnr) * 100.0;
report = QString(": total blocks %1, current block %2 [%3]")
.arg(tnr).arg(cnr).arg(percent, 0, 'f', 2);
} else {
report = QString(": total blocks %1, current block %2 [0]")
.arg(tnr).arg(cnr);
}
status = QDateTime::currentDateTime().toString(Qt::ISODate) + report;
qCritical() << "STATUS" << status;
emit m_hw->hwapi_reportDCDownloadStatus(status);
cnr += 1;
}
if (tnr == cnr) {
m_hw->hwapi_reportDCDownloadSuccess(
QString("SUCCESS DOWNLOADING") + m_fileToDownload);
} else {
m_hw->hwapi_reportDCDownloadFailure(
QString("ERROR DOWNLOADING %1 (total blocks=%2, sent blocks=%3)")
.arg(m_fileToDownload).arg(tnr).arg(cnr));
}
#endif
uint16_t const totalBlocks = m_hw->dcDownloadGetTotalBlockNumber();
qCritical() << QDateTime::currentDateTime() << "TOTAL BLOCKS" << totalBlocks;
if (totalBlocks) {
qint64 const start = QDateTime::currentMSecsSinceEpoch();
double durationMillis = 0;
uint16_t currentBlockNumber = 0;
while (m_hw->dcDownloadGetRunning()) {
currentBlockNumber = m_hw->dcDownloadGetCurrentBlockNumber();
durationMillis += QDateTime::currentMSecsSinceEpoch() - start;
double const timeAveragePerBlock = (currentBlockNumber > 0) ? (durationMillis / currentBlockNumber) : durationMillis;
double const estimatedSecondsLeft = (timeAveragePerBlock * (totalBlocks - currentBlockNumber)) / 1000.0;
double percent = ((double)currentBlockNumber / (double)totalBlocks) * 100.0;
report = QString(": total blocks %1, current block %2 [%3] (est. time left: %4s)")
.arg(totalBlocks)
.arg(currentBlockNumber)
.arg(percent, 0, 'f', 2)
.arg(estimatedSecondsLeft, 0, 'f', 2);
qCritical() << "RT report" << report;
emit m_hw->hwapi_reportDCDownloadStatus(report);
QThread::msleep(100);
}
QThread::msleep(100);
if (totalBlocks == currentBlockNumber) {
m_hw->hwapi_reportDCDownloadSuccess(
QString("SUCCESS DOWNLOADING") + m_fileToDownload);
} else {
m_hw->hwapi_reportDCDownloadFailure(
QString("ERROR DOWNLOADING %1 (total blocks=%2, sent blocks=%3)")
.arg(m_fileToDownload).arg(totalBlocks).arg(currentBlockNumber));
}
}
qCritical() << QDateTime::currentDateTime() << __PRETTY_FUNCTION__
<< QString("line=%1 REPORT THREAD ABOUT TO FINISH").arg(__LINE__);
cnt = 10;
bool running = m_hw->dcDownloadGetRunning();
bool finished = m_hw->dcDownloadGetFinished();
while (--cnt > 0 && (running && !finished)) {
qCritical() << QDateTime::currentDateTime() << __PRETTY_FUNCTION__
<< QString("line=%1 REPORT THREAD: WAIT FOR END OF DOWNLOAD THREAD %2 %3 (%4)")
.arg(__LINE__).arg(running).arg(finished).arg(cnt);
QThread::sleep(1);
running = m_hw->dcDownloadGetRunning();
finished = m_hw->dcDownloadGetFinished();
}
qCritical() << QDateTime::currentDateTime() << __PRETTY_FUNCTION__
<< QString("line=%1 FINISH REPORT THREAD").arg(__LINE__);
}

1737
src/runProc.cpp Normal file → Executable file

File diff suppressed because it is too large Load Diff

6
src/sendWRcmd.cpp Normal file → Executable file
View File

@ -19,7 +19,11 @@ void sendWRcmd_INI(void)
}
// Command Stack for commands without parameters
uint8_t sendWRcmd_getStackSize(void)
{
return CMDSTACKDEPTH; // defined in shared_mem_buffer.h
}
//static uint16_t nextAsynchsendCmd0[CMDSTACKDEPTH];

99
src/storeINdata.cpp Normal file → Executable file
View File

@ -9,6 +9,7 @@
// gpi: grafical access to PI: access from external devices over device controller FOR GUI
// epi: external access from GUI to PI: FOR external devices (DC)
// Change log: 8.5.24TS: clear all oversize buffers (if only 32 of 64bytes are used then fill the rest with 0)
@ -1001,6 +1002,8 @@ bool epi_getDI_auxPwr(void)
void gpi_storeDI_GsmPowerIsOn(bool di_gsm_PwrOn)
{
SharedMem::write()->di_gsmPwrOn=di_gsm_PwrOn;
//qDebug()<<"store In Data Gsm Pwr = "<< di_gsm_PwrOn;
}
bool epi_getDI_gsmPwr(void)
@ -1540,6 +1543,8 @@ void gpi_storeMdbResponse(uint8_t leng, uint8_t *data)
//tslib_strcpy(data, SharedMem::write()->Sdata_RecBuff, uint16_t(Sdata_mdbNrOfRecData));
for (nn=0; nn<leng; nn++)
SharedMem::write()->Sdata_RecBuff[nn] = data[nn];
for (nn=leng; nn<40; nn++)
SharedMem::write()->Sdata_RecBuff[nn] = 0;
}
@ -1566,6 +1571,8 @@ void gpi_storeEmpSettings(uint8_t leng, uint8_t *data)
//tslib_strcpy(data, SharedMem::write()->Sdata_emp_settingsBuff, leng);
for (nn=0; nn<leng; nn++)
SharedMem::write()->Sdata_emp_settingsBuff[nn] = data[nn];
for (nn=leng; nn<64; nn++)
SharedMem::write()->Sdata_emp_settingsBuff[nn] = 0;
}
@ -1671,6 +1678,9 @@ void gpi_storeRbDeviceSettings(uint8_t leng, uint8_t *data) // getestet am
//tslib_strcpy(data, SharedMem::write()->Sdata_DeviceSettingBuff, leng);
for (nn=0; nn<leng; nn++)
SharedMem::write()->Sdata_DeviceSettingBuff[nn] = data[nn];
for (nn=leng; nn<64; nn++)
SharedMem::write()->Sdata_DeviceSettingBuff[nn] = 0;
}
@ -1772,15 +1782,25 @@ void epi_clearCurrentPayment(void)
void gpi_storeCurrentPayment(uint32_t insertedAmount, uint16_t lastCoinType, uint16_t lastCoinValue)
{
uint8_t pLC=SharedMem::read()->p_lastCoin;
SharedMem::write()->store_insertedAmount=insertedAmount;
SharedMem::write()->store_lastCoinType[pLC]=lastCoinType;
SharedMem::write()->store_lastCoinValue[pLC]=lastCoinValue;
pLC++;
SharedMem::write()->p_lastCoin=pLC;
SharedMem::write()->store_curPayNewCoin++;
uint8_t pLC;
// 21.3.24 attention: if bit 15 in lastCoinType is set then we got a bill not a coin
SharedMem::write()->store_insertedAmount=insertedAmount;
if (lastCoinType & 0x8000)
{
// then it's a banknote
//qCritical()<<"gpi_storeCurrentPayment got banknote, total: "<<insertedAmount;
} else
{
//qCritical()<<"gpi_storeCurrentPayment "<<insertedAmount<<" " << lastCoinType<<" " << lastCoinValue;
pLC=SharedMem::read()->p_lastCoin;
SharedMem::write()->store_lastCoinType[pLC]=lastCoinType;
SharedMem::write()->store_lastCoinValue[pLC]=lastCoinValue;
pLC++;
SharedMem::write()->p_lastCoin=pLC;
SharedMem::write()->store_curPayNewCoin++;
}
//qDebug()<<"gpi_storeCurrentPayment "<<insertedAmount<<" " << lastCoinType<<" " << lastCoinValue;
}
uint32_t epi_CurrentPaymentGetAmount(void)
@ -1818,6 +1838,13 @@ bool epi_CurrentPaymentGetAllCoins(uint16_t *types, uint16_t *values)
return true;
}
/*
int nn;
for (nn=0; nn<8; nn++)
{
data[nn]=SharedMem::read()->store_bnaCollect[nn];
}
*/
//uint64_t stor_wakSrc;
//uint8_t stor_reason;
@ -1894,6 +1921,10 @@ void gpi_storeDeviceConditions(uint8_t leng, uint8_t *data)
//tslib_strcpy(data, SharedMem::write()->store_deviceCond, leng);
for (nn=0; nn<leng; nn++)
SharedMem::write()->store_deviceCond[nn]=data[nn];
// clear the rest
for (nn=leng; nn<64; nn++)
SharedMem::write()->store_deviceCond[nn]=0;
}
void epi_restoreDeviceConditions(uint8_t *leng, uint8_t *data)
@ -1929,6 +1960,8 @@ void gpi_storeDynMachineConditions(uint8_t leng, uint8_t *data)
// tslib_strcpy(data, SharedMem::write()->store_machCond, leng);
for (nn=0; nn<leng; nn++)
SharedMem::write()->store_machCond[nn] = data[nn];
for (nn=leng; nn<64; nn++)
SharedMem::write()->store_machCond[nn] = 0;
}
@ -2080,16 +2113,26 @@ void epi_setDcDataValid(void)
}
}
void epi_resetDcDataValid(void)
void epi_resetDcDataValid(char reason)
{
bool now=SharedMem::read()->store_DcDataAreValid;
if (now==true)
{
SharedMem::write()->store_DcDataAreValid = false;
#ifdef THIS_IS_CA_MASTER
qDebug()<<"master lib RESET DcDataValid";
switch (reason)
{
case 1: qDebug()<<"master lib RESET DcDataValid startup"; break;
case 2: qDebug()<<"master lib RESET DcDataValid port closed"; break;
case 3: qDebug()<<"master lib RESET DcDataValid no more data"; break;
case 4: qDebug()<<"master lib RESET DcDataValid manuell"; break;
default: qDebug()<<"master lib RESET DcDataValid ---"; break;
}
#else
qDebug()<<"slave lib RESET DcDataValid";
Q_UNUSED(reason);
#endif
}
}
@ -2328,6 +2371,7 @@ void epi_getJsonVersion(uint8_t jsonNr, char *versionString)
versionString[nn] = SharedMem::read()->store_jsonVersion[nn][lrd];
}
// korrektur 8.5.24: printer versionen auf 6...37 (nicht 5..36)
}
@ -2434,7 +2478,40 @@ void epi_restoreBnaContent(uint8_t *data)
// new, 8.5.24
//uint8_t store_machCon2len;
//uint8_t store_machCon2[66];
void epi_clearDynMachCond2(void)
{
uint8_t nn;
SharedMem::write()->store_machCon2len=0;
for (nn=0; nn<64; nn++)
SharedMem::write()->store_machCon2[nn] = 0;
}
void gpi_storeDynMachCond2(uint8_t leng, uint8_t *data)
{
uint8_t nn;
if (leng>64) leng=64;
SharedMem::write()->store_machCon2len=leng;
for (nn=0; nn<leng; nn++)
SharedMem::write()->store_machCon2[nn] = data[nn];
for (nn=leng; nn<64; nn++)
SharedMem::write()->store_machCon2[nn] = 0;
}
void epi_restoreDynMachCond2(uint8_t *leng, uint8_t *data)
{
uint8_t nn, LL;
LL=SharedMem::read()->store_machCon2len;
*leng=LL;
for (nn=0; nn<LL; nn++)
data[nn] = SharedMem::read()->store_machCon2[nn];
}

371
src/tslib.cpp Normal file → Executable file
View File

@ -610,3 +610,374 @@ bool tslib_strComp(uint8_t *buf, char *compStr)
return true;
}
char biox_StrComp(char *S1, char *S2, int len)
{
// retval=1 wenn gleich; ? in S2 =Jokerzeichen
int ii;
for (ii=0; ii<len; ii++)
{
if ((S1[ii] != S2[ii]) && (S2[ii] != '?') )
return (0);
}
return(1);
}
// *****************************************************************************************
uint16_t tslib_StrLen(char *str)
{
uint16_t zz;
for (zz=0; zz<0xF000; zz++)
if (str[zz]==0)
return(zz);
return(0);
}
// *****************************************************************************************
uint16_t biox_StrLenInt(uint16_t *str)
{
uint16_t zz;
for (zz=0; zz<0xF000; zz++)
if (str[zz]==0)
return(zz);
return(0);
}
// *****************************************************************************************
void biox_MemCpy(uint8_t *src, uint8_t *dest, uint16_t Len)
{
// copy "Len" bytes from target to destination
// if Len==0 then copy until first NULL in targ
uint16_t zz=0;
if (Len==0)
{
while(src[zz]>0)
{
dest[zz]=src[zz];
zz++;
}
dest[zz]=0; // termination
} else
{
// Len>0 --> copy "Len" bytes
for (zz=0; zz<Len; zz++)
dest[zz]=src[zz];
dest[zz]=0; // termination
}
}
void tslib_itoa(int n, char *str)
{
// -23456 -> str[0]='-' str[1]='2' ...[5]='6' str[6]=0
// 5 -> str[0]='5' str[1..6]=0
uint8_t pp, zi[7];
int itmp, pi=0;
for (pp=0;pp<7;pp++)
{
str[pp]=0;
zi[pp]=0;
}
itmp=n;
pp=0;
if (itmp==0)
str[pp++]=0x30;
if (itmp<0)
{
str[pp++]='-';
itmp*=-1;
}
while(itmp>0)
{
zi[pi++]=itmp%10;
itmp/=10;
}
// now: zi[0]=6 zi[1]=5 zi[2]=4 zi[3]=3 zi[4]=2 zi[5]=0 zi[6]=0 pi=4
while (pi>0)
str[pp++]=zi[--pi]+0x30;
//str[0]='-'; str[1]='1'; str[3]='3'; // Test
}
// ***********************************************************************************************
void tslib_uitoa(unsigned int n, char *str)
{
uint8_t pp, zi[6];
unsigned int itmp;
int pi=0;
for (pp=0;pp<6;pp++)
{
str[pp]=0;
zi[pp]=0;
}
itmp=n;
pp=0;
if (itmp==0)
str[pp++]=0x30;
while(itmp>0)
{
zi[pi++]=itmp%10;
itmp/=10;
}
// now: zi[0]=6 zi[1]=5 zi[2]=4 zi[3]=3 zi[4]=2 zi[5]=0 pi=4
while (pi>0)
str[pp++]=zi[--pi]+0x30;
//str[0]='-'; str[1]='1'; str[3]='3'; // Test
}
// ***********************************************************************************************
void tslib_ltoa(long n, char *str)
{
// -2147483647 -> str[0]='-' str[1]='2' ...[10]='6' str[11]=0
uint8_t pp, zi[12];
int pi=0;
long ltmp;
for (pp=0;pp<12;pp++)
{
str[pp]=0;
zi[pp]=0;
}
ltmp=n;
pp=0;
if (ltmp==0)
str[pp++]=0x30;
if (ltmp<0)
{
str[pp++]='-';
ltmp*=-1;
}
while(ltmp>0)
{
zi[pi++]=ltmp%10;
ltmp/=10;
}
while (pi>0)
str[pp++]=zi[--pi]+0x30;
}
// ***********************************************************************************************
void tslib_ultoa(unsigned long n, char *str)
{
// 0... ->4294967296 str[0]='4' str[1]='2' ...[9]='6' str[10]=0 str[11]=0
uint8_t pp, zi[12];
int pi=0;
unsigned long ltmp;
for (pp=0;pp<12;pp++)
{
str[pp]=0;
zi[pp]=0;
}
ltmp=n;
pp=0;
if (ltmp==0)
str[pp++]=0x30;
while(ltmp>0)
{
zi[pi++]=ltmp%10;
ltmp/=10;
}
while (pi>0)
str[pp++]=zi[--pi]+0x30;
}
// ***********************************************************************************************
void tslib_uitobin(unsigned int decval, char *str)
{
uint16_t dv, bb;
int ll;
dv=decval;
ll=8; // show 8 bit
if (dv>255) ll=16; // show 16 bit
str[ll--]=0; // terminierung
bb=0;
do
{
if (dv & (1<<bb) ) str[ll]=0x31; else str[ll]=0x30;
bb++; ll--;
} while(ll>=0);
}
// ***********************************************************************************************
long tslib_atol( char *AscString)
{
// change ascii string ( of ascii numbers '0'..'9') to number
// AscString must be 0-terminated!
// a leading '-' is ignored, a'.' or a ',' stops calculation
//aufruf mit ("1234")
// aus IDE: ucatmp[0]='1' ucatmp[3]='4' ucatmp[4]='0' sl=4
unsigned long ultmp;
unsigned char uctmp1, minus=0;
unsigned int sl, zz;
sl=tslib_StrLen(AscString);
if (sl>10) sl=10; // mehr passt im ULONG nicht rein!
ultmp=0;
for (zz=0; zz<sl; zz++)
{
uctmp1=AscString[zz];
if (zz==0 && uctmp1=='-')
minus=1;
else
if (uctmp1>0x2F && uctmp1<0x3A)
{
ultmp*=10; // nur wenn eine neue Ziffer dazukommt und vor der addition!
uctmp1-=0x30;
ultmp+=(uint32_t)uctmp1;
} else
if (uctmp1=='.' || uctmp1==',' || uctmp1==0 )
{
if (minus)
ultmp*=(-1);
return(ultmp);
}
}
if (minus)
ultmp*=(-1);
return(ultmp);
}
// *****************************************************************************************
unsigned long tslib_atoul( char *AscString)
{
// change ascii string ( of ascii numbers '0'..'9') to number
// AscString must be 0-terminated!
// a leading '-' is ignored, a'.' or a ',' stops calculation
//aufruf mit ("1234")
// aus IDE: ucatmp[0]='1' ucatmp[3]='4' ucatmp[4]='0' sl=4
unsigned long ultmp;
unsigned char uctmp1;
unsigned int sl, zz;
sl=tslib_StrLen(AscString);
if (sl>10) sl=10; // mehr passt im ULONG nicht rein!
ultmp=0;
for (zz=0; zz<sl; zz++)
{
uctmp1=AscString[zz];
if (uctmp1>0x2F && uctmp1<0x3A)
{
ultmp*=10; // nur wenn eine neue Ziffer dazukommt und vor der addition!
uctmp1-=0x30;
ultmp+=(uint32_t)uctmp1;
} else
if (uctmp1=='.' || uctmp1==',' || uctmp1==0 )
return(ultmp);
}
return(ultmp);
}
// *****************************************************************************************
unsigned int tslib_ah2ui( char *AscString)
{
// change hex ascii string ( of ascii numbers '0'..'9', 'A' or 'a' ...'F','f') to number
// AscString must be 0-terminated!
// Example: "1A0C" = 6668
//unsigned long ultmp;
unsigned char uctmp1;
unsigned int sl, zz, uitmp;
sl=tslib_StrLen(AscString);
if (sl>4) sl=4;
uitmp=0;
for (zz=0; zz<sl; zz++)
{
uctmp1=AscString[zz];
if (uctmp1>=0x30 && uctmp1<=0x39)
{
uitmp<<=4; // nur wenn eine neue Ziffer dazukommt und vor der addition!
uctmp1-=0x30;
uitmp+=(uint16_t)uctmp1;
} else
if (uctmp1>='A' && uctmp1<='F')
{
uitmp<<=4;
uctmp1-=0x37;
uitmp+=(uint16_t)uctmp1;
} else
if (uctmp1>='a' && uctmp1<='f')
{
uitmp<<=4;
uctmp1-=0x57;
uitmp+=(uint16_t)uctmp1;
}
}
return(uitmp);
}