Add first version which at least complies.

This commit is contained in:
2023-11-10 11:59:00 +01:00
parent a21fa5fce9
commit 26c1f0143e
35 changed files with 11235 additions and 0 deletions

17
src/ATBAPP/ATBAPPplugin.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef ATBAPPPLUGIN_H
#define ATBAPPPLUGIN_H
/***********************************************************
* a simple class with only one method for plugin info
*/
#include <QObject>
#include <QString>
class ATBAPPplugin {
public:
virtual const QString & getPluginInfo() = 0;
};
Q_DECLARE_INTERFACE(ATBAPPplugin, "eu.atb.ptu.plugin.ATBAPPplugin/0.9")
#endif // ATBAPPPLUGIN_H

View File

@@ -0,0 +1,91 @@
#include "src/ATBAPP/ATBVMCPlugin.h"
#include <QTimer>
#include <QThread>
#include <QTextCodec>
#include <QDebug>
#include <QPluginLoader>
#include <QDateTime>
#include <QFileInfo>
#include <QCoreApplication>
#include <QUuid>
#include <cstdlib>
ATBVMCPlugin::ATBVMCPlugin(QObject *parent)
: m_errorCode("")
, m_errorDescription("")
, m_pluginInfo("")
, m_serialPortName("")
, m_useDebug(false)
, m_pluginState(PLUGIN_STATE::NOT_INITIALIZED)
, m_eventReceiver(nullptr) {
this->setParent(parent);
}
ATBVMCPlugin::~ATBVMCPlugin() {
}
PLUGIN_STATE ATBVMCPlugin::initVMCPlugin(QObject *eventReceiver,
QSettings const &settings) {
Q_UNUSED(eventReceiver);
Q_UNUSED(settings);
return PLUGIN_STATE::NOT_INITIALIZED;
}
// mandantory ATBAPP plugin methods: ------------------------------------------
PLUGIN_STATE ATBVMCPlugin::getState() {
return PLUGIN_STATE::NOT_INITIALIZED;
}
QString ATBVMCPlugin::getLastError() {
return "";
}
QString ATBVMCPlugin::getLastErrorDescription() {
return "";
}
QString const &ATBVMCPlugin::getPluginInfo() {
static QString info;
return info;
}
// helpers e.g. for debug / log
QString ATBVMCPlugin::getString(RESULT_STATE /*resultState*/) {
return "";
}
void ATBVMCPlugin::onChangedProgramModeToSELL() {
}
void ATBVMCPlugin::onChangedProgramModeToSERVICE() {
}
void ATBVMCPlugin::onChangedProgramModeToIDLE() {
}
void ATBVMCPlugin::onChangedProgramModeToOOO() {
}
void ATBVMCPlugin::startPhysicalLayer() {
}
void ATBVMCPlugin::stopPhysicalLayer() {
}
void ATBVMCPlugin::reboot() {
}
void ATBVMCPlugin::reset() {
}

61
src/ATBAPP/ATBVMCPlugin.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef ATBVMCPLUGIN_H
#define ATBVMCPLUGIN_H
#include <QObject>
#include "src/ATBAPP/VMCInterface.h"
#include "src/ATBAPP/ATBAPPplugin.h"
#include "version.h"
#include "include/interfaces.h"
class ATBVMCPlugin : public VMCInterface {
Q_OBJECT
Q_INTERFACES(ATBAPPplugin)
Q_INTERFACES(UnifiedDCVMCInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA( IID "ATBVMCPlugin" )
#endif
public:
explicit ATBVMCPlugin(QObject *parent = nullptr);
~ATBVMCPlugin();
// ----------------------------------------------------------------------------
// interface:
PLUGIN_STATE initVMCPlugin(QObject *eventReceiver, QSettings const &settings);
// mandantory ATBAPP plugin methods: ------------------------------------------
PLUGIN_STATE getState() override;
QString getLastError() override;
QString getLastErrorDescription() override;
virtual const QString & getPluginInfo() override;
// helpers e.g. for debug / log
virtual QString getString(RESULT_STATE resultState) override;
public slots:
virtual void onChangedProgramModeToSELL() override;
virtual void onChangedProgramModeToSERVICE() override;
virtual void onChangedProgramModeToIDLE() override;
virtual void onChangedProgramModeToOOO() override;
virtual void startPhysicalLayer() override;
virtual void stopPhysicalLayer() override;
virtual void reboot() override;
virtual void reset() override;
private:
QString m_errorCode;
QString m_errorDescription;
QString m_pluginInfo;
QString m_serialPortName;
bool m_useDebug;
PLUGIN_STATE m_pluginState;
QObject* m_eventReceiver;
};
#endif // ATBDEVICECONTROLLERPLUGIN_H

View File

@@ -0,0 +1,143 @@
#ifndef UNIFIED_DCVMC_INTERFACE_H_INCLUDED
#define UNIFIED_DCVMC_INTERFACE_H_INCLUDED
#include <QObject>
#include <QSettings>
#include <QtPlugin>
#include <QSettings>
#include <QString>
#include "ATBAPPplugin.h"
class UnifiedDCVMCInterface : public QObject, public ATBAPPplugin {
Q_OBJECT
Q_INTERFACES(ATBAPPplugin)
public:
enum class PLUGIN_STATE : quint8 {
NOT_INITIALIZED = 0,
INITIALIZED = 1
};
enum class RESULT_STATE : quint8 {
SUCCESS = 1, // operation was successfull
ERROR_BACKEND, // error from backend (e.g. backend replies with error)
ERROR_TIMEOUT, // the operation timed out
ERROR_PROCESS, // internal plugin error, should not occur (this is a bug in implementation)
ERROR_RETRY, // retry operation
INFO // informational (e.g. display a message, log something etc.)
};
enum class CASH_STATE : quint8 {
CACHE_EMPTY, // Cache still empty, default state
CACHE_INPUT, // Coins are in Cache
OVERPAYED,
/* t.b.d. */
};
enum class TICKET_VARIANT : quint8 {
PARKING_TICKET,
RECEIPT,
ERROR_RECEIPT,
START_RECEIPT, // e.g. Szeged Start
STOP_RECEIPT, // e.g. Szeged Stop
};
explicit UnifiedDCVMCInterface() = default;
virtual ~UnifiedDCVMCInterface() {}
virtual PLUGIN_STATE initPlugin(QObject *eventReceiver, QSettings const &settings) = 0;
// mandantory ATBAPP plugin methods:
virtual PLUGIN_STATE getState() = 0;
virtual QString getLastError() = 0;
virtual QString getLastErrorDescription() = 0;
virtual QString getString(RESULT_STATE resultState) = 0;
public slots:
virtual void onChangedProgramModeToSELL() = 0;
virtual void onChangedProgramModeToSERVICE() = 0;
virtual void onChangedProgramModeToIDLE() = 0;
virtual void onChangedProgramModeToOOO() = 0;
virtual void startPhysicalLayer() = 0;
virtual void stopPhysicalLayer() = 0;
virtual void reboot() = 0;
virtual void reset() = 0;
signals:
void printTicketFinished(RESULT_STATE resultState,
const QString & errorCode,
const QString & errorDescription);
void printReceiptFinished(RESULT_STATE resultState,
const QString & errorCode,
const QString & errorDescription);
/**
* emitted on e.g. a coin input
*/
void cashInputEvent(RESULT_STATE resultState,
CASH_STATE cashState,
const QString & newCashValue,
/* additional variables? */
const QString & errorCode,
const QString & errorDescription);
/**
* emitted if cashInput has been stopped, e.g. in result to task requestStopCashInput():
* -> shutter is blocked
* -> no cash input is possible
* -> coins are in cache
*/
void cashInputFinished(RESULT_STATE resultState,
const QString & newCashValue,
/* additional variables? */
const QString & errorCode,
const QString & errorDescription);
/**
* emitted e.g. if service door is opened
*/
void requestModeSERVICE();
/**
* emitted e.g. if doors are closed
*/
void requestModeIDLE();
/**
* emitted e.g. on severe errors
*/
void requestModeOOO();
/**
* emitted e.g. if service door is opened
*/
void requestAccountResponse(const QHash<QString, QVariant> & accountData);
/**
* emitted on error
* depending on errorCode:
* -> interrupt selling process
* -> machine can go to state OOO
* -> send error event to ISMAS
* -> ...
*/
void Error(
/* additional variables? */
const QString & errorCode,
const QString & errorDescription);
};
Q_DECLARE_INTERFACE(UnifiedDCVMCInterface,
"eu.atb.ptu.plugin.UnifiedDCVMCInterface/1.0")
using PLUGIN_STATE = UnifiedDCVMCInterface::PLUGIN_STATE;
using RESULT_STATE = UnifiedDCVMCInterface::RESULT_STATE;
using CASH_STATE = UnifiedDCVMCInterface::CASH_STATE;
using TICKET_VARIANT = UnifiedDCVMCInterface::TICKET_VARIANT;
#endif // UNIFIED_DCVMC_INTERFACE_H_INCLUDED

42
src/ATBAPP/VMCInterface.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef VMCINTERFACE_H
#define VMCINTERFACE_H
#include <QtPlugin>
#include <QSettings>
#include <QString>
#include "ATBAPPplugin.h"
#include "UnifiedDCVMCInterface.h"
namespace nsVMCInterface {
using PLUGIN_STATE = UnifiedDCVMCInterface::PLUGIN_STATE;
using RESULT_STATE = UnifiedDCVMCInterface::RESULT_STATE;
using CASH_STATE = UnifiedDCVMCInterface::CASH_STATE;
using TICKET_VARIANT = UnifiedDCVMCInterface::TICKET_VARIANT;
}
class VMCInterface : public UnifiedDCVMCInterface {
Q_OBJECT
Q_INTERFACES(ATBAPPplugin)
Q_INTERFACES(UnifiedDCVMCInterface)
public:
virtual PLUGIN_STATE initPlugin(QObject *eventReceiver, QSettings const &settings) override {
return initVMCPlugin(eventReceiver, settings);
}
virtual ~VMCInterface() {}
/**
* @brief initDCPlugin
* @param eventReceiver - QObject to receive ATBMachineEvents or HealthEvents
* @param settings
* @return
*/
virtual PLUGIN_STATE initVMCPlugin(QObject *eventReceiver, const QSettings & settings) = 0;
};
#endif // VMCINTERFACE_H

View File

@@ -0,0 +1,244 @@
#include <QTimer>
#include "ReceiveBuffer.h"
#include "vmc.h"
#include <QDebug>
ReceiveBuffer::ReceiveBuffer(COM_interface *cinterface, QObject *parent) :
QObject(parent)
{
qRegisterMetaType<RECEIVE_ERROR>("RECEIVE_ERROR");
this->vmc = (VMC*)parent;
this->interface = cinterface;
connect(interface, SIGNAL(ReadData(QByteArray*)), this, SLOT(getData(QByteArray*)));
connect(vmc, SIGNAL(CommandProcessed()), this, SLOT(removeCommand()));
connect(this, SIGNAL(CommandAvailiable(QByteArray)), vmc, SLOT(CommandAvaliable(QByteArray)));
currentMessage.clear();
receiveIdleTimer = new QTimer(this);
receiveIdleTimer->setInterval(2000); // clear possible wrong data in receive buffer after 2s
receiveIdleTimer->setSingleShot(false);
connect(receiveIdleTimer, SIGNAL(timeout()), this, SLOT(onReceiveIdleTimerTimeout()));
}
ReceiveBuffer::~ReceiveBuffer()
{
delete(this->receiveIdleTimer);
}
int ReceiveBuffer::size()
{
return messageQueue.size();
}
void ReceiveBuffer::removeCommand()
{
if (messageQueue.size() > 0) {
messageQueue.removeFirst();
}
else {
qDebug() << "ReceiveBuffer::removeCommand(): no message to remove!";
}
}
void ReceiveBuffer::onReceiveIdleTimerTimeout()
{
this->currentMessage.clear();
this->receiveIdleTimer->stop();
}
void ReceiveBuffer::getData(QByteArray *data)
{
int CRCindex;
int COMMAND_IN_PROGRESS = 1;
// do nothing, if there is no data
if (data->size() == 0) { return; }
// DEBUG
/*
qDebug() << "ReceiveBuffer::getData(): messageQueue.size = " << messageQueue.size();
qDebug() << "ReceiveBuffer::getData(): data = " << data;
qDebug() << "ReceiveBuffer::getData(): data->size() = " << data->size();
qDebug() << "ReceiveBuffer::getData(): &currentMessage = " << &currentMessage;
qDebug() << "ReceiveBuffer::getData(): currentMessage.capacity = " << currentMessage.capacity();
qDebug() << "ReceiveBuffer::getData(): currentMessage.size() = " << currentMessage.size();
*/
this->receiveIdleTimer->start();
// for safety: prevent currentMessage to grow infinitely in size.
if (currentMessage.size() > 0xFF) {
emit ReceiveError(RECEIVE_ERROR::INVALID_COMMAND);
currentMessage.clear();
}
// we use append because data can be an interrupted command:
currentMessage.append(data->data(), data->size());
//qDebug() << "ReceiveBuffer::getData(): currentMessage = " << QString(currentMessage);
// process commands:
while (COMMAND_IN_PROGRESS) {
int startindex = currentMessage.indexOf(0x3e); // find start of command
// detect ACK/NACK response messages from vmc:
if (startindex != 0) {
int forEnd = -1;
if (startindex > 0) forEnd = startindex; // if ACK/NACK is before command ...
if (startindex == -1) forEnd = currentMessage.size(); // if ACK/NACK is the only data
for (int i = 0; i != forEnd; i++) {
switch (currentMessage.at(i)) {
case ACK: emit ReceiveResponse(ACK);
break;
case NACK: emit ReceiveResponse(NACK);
break;
}
}
}
if(startindex == -1) {
currentMessage.clear();
COMMAND_IN_PROGRESS = 0;
return;
}
else {
currentMessage.remove(0,startindex);
}
// now, we have at least a beginning message
CRCindex = checkMessageForCRC();
if (CRCindex == 0) {
// exit this methode and message part is still in currentMessage.
break;
}
if (CRCindex < 0) {
//qCriticalBAMessage(currentMessage);
emit ReceiveError(RECEIVE_ERROR::INVALID_COMMAND);
currentMessage.clear();
COMMAND_IN_PROGRESS = 0;
break;
}
//qDebug() << "ReceiveBuffer::getData(): startindex = " << startindex;
//qDebug() << "ReceiveBuffer::getData(): currentMessage = " << currentMessage;
//qDebug() << "ReceiveBuffer::getData(): CRCindex = " << CRCindex;
if (CRCindex) {
// found a complete message
if (checkCRC(currentMessage.at(CRCindex), CRCindex)) {
messageQueue << currentMessage.left(CRCindex + 1);
emit CommandAvailiable(messageQueue.first());
}
else {
emit ReceiveError(RECEIVE_ERROR::CRC);
}
if (currentMessage.size() > (CRCindex + 1)) {
currentMessage.remove(0,(CRCindex + 1));
}
else {
currentMessage.clear();
COMMAND_IN_PROGRESS = 0;
}
}
}
}
int ReceiveBuffer::checkMessageForCRC()
{
int CRCindex;
int DataLengthIndex;
// qDebug() << "ReceiveBuffer::checkMessageForCRC(): currentMessage.size = " << currentMessage.size();
// for (int i = 0; i < currentMessage.size(); i++)
// qDebug() << " currentMessage.at(" << i << ") = " << currentMessage.at(i);
if (currentMessage.size() <= 1)
return 0;
switch (currentMessage.at(1)) {
case 0x60: DataLengthIndex = 5; break;
case 0x61: DataLengthIndex = 6; break;
default: DataLengthIndex = 2; break;
}
if (currentMessage.size() <= DataLengthIndex)
return 0;
if (( (static_cast<quint8>(currentMessage.at(DataLengthIndex)) - 0x30)) <= 0 )
return -1;
CRCindex = DataLengthIndex + ( static_cast<quint8>(currentMessage.at(DataLengthIndex)) - 0x30) + 1;
if (currentMessage.size() <= CRCindex)
return 0;
else
return CRCindex;
}
bool ReceiveBuffer::checkCRC(quint8 CRC, int index)
{
quint8 cCRC = 0;
for (int i = 0; i < index; i++) {
cCRC += static_cast<quint8>(currentMessage.at(i));
//qDebug() << "ReceiveBuffer::checkCRC(): currentMessage.at(i) = " << currentMessage.at(i);
}
//qDebug() << "ReceiveBuffer::checkCRC(): cCRC = " << cCRC;
//qDebug() << "ReceiveBuffer::checkCRC(): CRC = " << CRC;
if (cCRC == CRC) return true;
else return false;
}
/**
* @brief ReceiveBuffer::qCriticalBAMessage
* @param message
*
* This is for test and debugging only.
*/
void ReceiveBuffer::qCriticalBAMessage(QByteArray message)
{
QString hexString = "received: ";
qint64 i;
for (i=0; i < message.size(); i++) {
hexString.append((QString(message.at(i))).toLatin1().toHex());
hexString.append(' ');
}
hexString.chop(1);
//qCritical() << "VMC::CommandAvaliable(): message.size(): " << message.size() << "";
qCritical() << "VMC::qCriticalBAMessage(): message: " << hexString << "";
}

View File

@@ -0,0 +1,72 @@
#ifndef RECEIVEBUFFER_H
#define RECEIVEBUFFER_H
#include <QObject>
#include <QByteArray>
#include <QList>
#include "com_interface.h"
class QTimer;
class VMC;
enum class RECEIVE_ERROR : quint8;
class ReceiveBuffer : public QObject
{
Q_OBJECT
private:
VMC *vmc;
COM_interface *interface;
QList<QByteArray> messageQueue;
QByteArray currentMessage;
int checkMessageForCRC();
bool checkCRC(quint8 CRC, int index);
/* the receiveIdleTimer clears the receive buffer (currentMessag), if for
* a certain time no data was received.
* This is for improve speed for responding on vmc messages because possible
* wrong data is removed from queue.
*/
QTimer *receiveIdleTimer;
// for debug:
void qCriticalBAMessage(QByteArray message);
public:
explicit ReceiveBuffer(COM_interface *cinterface, QObject *parent = nullptr);
~ReceiveBuffer();
int size();
signals:
void CommandAvailiable(QByteArray command);
void ReceiveError(RECEIVE_ERROR error);
void ReceiveResponse(quint8 response);
private slots:
void removeCommand();
void getData(QByteArray *data);
void onReceiveIdleTimerTimeout();
};
enum class RECEIVE_ERROR : quint8 {
NO_ERROR = 0,
CRC,
NO_COMMAND,
INVALID_COMMAND
};
#endif // RECEIVEBUFFER_H

View File

@@ -0,0 +1,206 @@
#include <QTimer>
#include "SendBuffer.h"
#include "vmc.h"
#include <QDebug>
#include "version.h"
SendBuffer::SendBuffer(COM_interface *cinterface, QObject *parent) :
QObject(parent)
{
qRegisterMetaType<SEND_ERROR>("SEND_ERROR");
this->vmc = (VMC*)parent;
this->interface = cinterface;
this->responseTimeoutTimer = new QTimer(this);
this->responseTimeoutTimer->setInterval(1000); // resend message to vmc after 1s without response
this->responseTimeoutTimer->setSingleShot(false);
connect(this->responseTimeoutTimer, SIGNAL(timeout()), this, SLOT(onResponseTimeoutTimerTimeout()));
responseTimerTimeoutCounter = 0;
resendCounter = 0;
}
SendBuffer::~SendBuffer()
{
delete(this->responseTimeoutTimer);
}
/****************************************************************
* public interface
*
****************************************************************/
/**
* from vmc: sendMessage / insert Message in Message-Queue
*
* interactiveFlag: (default = true)
* Interactive commands are commands resulting from user input (e.g. button clicks).
* This commands are enqueued only if responseTimeoutTimer is not active.
* This ensures, that such messages are sent in sequence and only, if an answer
* from vmc was received.
* Non-interactive commands are data messages which are sent to vmc, caused e.g. by
* an internal status change.
*
*/
int SendBuffer::SendMessage(QByteArray & ba, bool enqueue)
{
// prevent queue for growing endlessly:
// check size of queue
// if queue-size is greater than SB_MAX_SENDQUEUESIZE, remove oldest (first) element
qDebug() << "SendBuffer::SendMessage() messageQueue.size() = " << this->messageQueue.size();
if (this->messageQueue.size() > SB_MAX_SENDQUEUESIZE) {
messageQueue.removeFirst();
this->resendCounter = 0;
}
// put message in queue
if (enqueue)
this->messageQueue.enqueue(ba);
/* interactive messages are sent only, if the response timer is not active.
* this should prevent successive sending of the same message during waiting
* for an answer from vmc.
*/
if (! this->responseTimeoutTimer->isActive()) {
if(!enqueue)
this->messageQueue.enqueue(ba);
// try to send message
this->PrivateSendMessage();
}
return 0;
}
/****************************************************************
* private interface
*
*/
/****************************************************************
* handle ACK/NACK response from vmc
*
*/
void SendBuffer::onReceiveResponse(quint8 response)
{
if (this->messageQueue.size() == 0) return;
// reset counter:
this->responseTimerTimeoutCounter = 0;
//if (response == NACK) qDebug() << "onReceiveResponse() NACK";
//if (response == ACK) qDebug() << "onReceiveResponse() ACK";
qDebug() << "--- onReceiveResponse() messageQueue.size() = " << this->messageQueue.size();
/* resend command on NACK */
if (response == NACK) {
// stop timeoutTimer
this->responseTimeoutTimer->stop();
if (this->resendCounter > SB_MAX_RESEND) {
// command could not be processed on peer: remove it from message queue
this->messageQueue.removeFirst();
this->resendCounter = 0;
}
else {
// else: resend command
if (this->messageQueue.size() != 0) this->PrivateSendMessage();
}
}
/* send next command on ACK */
if (response == ACK) {
// stop timeoutTimer
this->responseTimeoutTimer->stop();
// remove old message from message-queue
this->messageQueue.removeFirst();
this->resendCounter = 0;
if (this->messageQueue.size() != 0) this->PrivateSendMessage();
}
}
/* this timeout-handler is called, if no response (ACK/NACK) was received from vmc
*/
void SendBuffer::onResponseTimeoutTimerTimeout()
{
qDebug() << "onResponseTimeoutTimerTimeout() messageQueue.size() = " << this->messageQueue.size();
if (this->messageQueue.size() == 0) {
return;
}
// wakeup vmc
emit this->sendError(SEND_ERROR::RESPONSE);
if (this->resendCounter > SB_MAX_RESEND) {
this->messageQueue.removeFirst();
this->resendCounter = 0;
this->responseTimerTimeoutCounter++;
this->responseTimeoutTimer->stop();
emit this->sendError(SEND_ERROR::RESPONSE_TIMER_TIMEOUT);
if (this->responseTimerTimeoutCounter > 10) {
// switch to self out-of-order mode ...
emit this->sendError(SEND_ERROR::MULTIPLE_RESPONSE_TIMER_TIMEOUT);
}
// try to send an possible next message in order
// to empty queue:
if (!this->messageQueue.isEmpty()) {
PrivateSendMessage();
}
}
// send next message
else {
PrivateSendMessage();
}
}
/* send first message in Message-Queue
*
* preconditon: at least one message is in queue!
*/
void SendBuffer::PrivateSendMessage()
{
// take message from queue
QByteArray ba = this->messageQueue.head();
// put bytes on serial line
for (int i = 0; i < ba.size(); i++) {
this->interface->putChar(ba.at(i));
}
// do logging here
emit this->writeLogSent(ba);
this->resendCounter++;
// start timeoutTimer
this->responseTimeoutTimer->start();
}

View File

@@ -0,0 +1,59 @@
#ifndef SENDBUFFER_H
#define SENDBUFFER_H
#include <QObject>
#include <QByteArray>
#include <QQueue>
#include "com_interface.h"
class QTimer;
class VMC;
enum class SEND_ERROR : quint8;
#define SB_MAX_RESEND 3
#define SB_MAX_SENDQUEUESIZE 10
class SendBuffer : public QObject
{
Q_OBJECT
private:
VMC *vmc;
COM_interface *interface;
QQueue<QByteArray> messageQueue;
quint8 resendCounter;
/* timer for resending messages to vmc, if no valid response is resent from vmc
*/
QTimer *responseTimeoutTimer;
quint8 responseTimerTimeoutCounter;
void PrivateSendMessage();
public:
explicit SendBuffer(COM_interface *cinterface, QObject *parent = nullptr);
~SendBuffer();
int SendMessage(QByteArray & ba, bool enqueue = false);
signals:
void writeLogSent(QByteArray ba);
void sendError(SEND_ERROR error);
public slots:
void onReceiveResponse(quint8 response);
void onResponseTimeoutTimerTimeout();
};
enum class SEND_ERROR : quint8 {
NO_ERROR = 0,
RESPONSE,
RESPONSE_TIMER_TIMEOUT,
MULTIPLE_RESPONSE_TIMER_TIMEOUT
};
#endif // SENDBUFFER_H

View File

@@ -0,0 +1,303 @@
#include "com_interface.h"
#include <QtDebug>
#if QT_VERSION >=0x050000
#include <QSerialPort>
#else
#include "qextserialport.h"
#endif
COM_interface::COM_interface(QObject *parent) :
QObject(parent)
{
#if QT_VERSION >=0x050000
port = new QSerialPort(this);
#else
port = new QextSerialPort(QextSerialPort::EventDriven, this);
#endif
buffer = new QByteArray();
}
COM_interface::~COM_interface()
{
delete buffer;
delete port;
}
/***************************************************************************
* *************************************************************************
*
* QT5 ( = QSerialPort) specific methodes
*
***************************************************************************
***************************************************************************/
#if QT_VERSION >=0x050000
int COM_interface::open(const QString & portname, int baudrate)
{
QSerialPort::BaudRate br = QSerialPort::Baud115200;
switch (baudrate) {
case 9600: br = QSerialPort::Baud9600;
break;
case 57600: br = QSerialPort::Baud57600;
break;
default: br = QSerialPort::Baud115200;
break;
}
qDebug() << "COM_interface::open(): baudrate = " << baudrate;
qDebug() << "COM_interface::open(): br = " << br;
port->setPortName(portname);
port->setBaudRate(br);
port->setStopBits(QSerialPort::OneStop);
port->setParity(QSerialPort::NoParity);
port->setDataBits(QSerialPort::Data8);
if (port->open(QIODevice::ReadWrite) == true) {
connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
qDebug() << "listening for data on" << port->portName();
emit connected();
return 1;
}
else {
qDebug() << "device failed to open:";
qDebug() << " device:" << portname;
qDebug() << " errorstring:" << port->errorString();
return -1;
}
}
int COM_interface::open(const QString & portname, int baudrate, int dataBits, int stopBits, int parity)
{
QSerialPort::BaudRate br = QSerialPort::Baud115200;
QSerialPort::DataBits db = QSerialPort::Data8;
QSerialPort::StopBits sb = QSerialPort::OneStop;
QSerialPort::Parity par = QSerialPort::NoParity;
switch (baudrate) {
case 9600: br = QSerialPort::Baud9600;
break;
case 57600: br = QSerialPort::Baud57600;
break;
default: br = QSerialPort::Baud115200;
break;
}
//TODO Add if needed!
switch (dataBits) {
default: db = QSerialPort::Data8;
break;
}
switch (stopBits) {
case 2: sb = QSerialPort::TwoStop;
break;
default: sb = QSerialPort::OneStop;
break;
}
switch (parity) {
default: par = QSerialPort::NoParity;
break;
}
qDebug() << "COM_interface::open(): baudrate = " << baudrate;
qDebug() << "COM_interface::open(): br = " << br;
qDebug() << "COM_interface::open(): databits = " << dataBits;
qDebug() << "COM_interface::open(): db = " << db;
qDebug() << "COM_interface::open(): stopbits = " << stopBits;
qDebug() << "COM_interface::open(): sb = " << sb;
qDebug() << "COM_interface::open(): parity = " << parity;
qDebug() << "COM_interface::open(): par = " << par;
port->setPortName(portname);
port->setBaudRate(br);
port->setStopBits(sb);
//port->setFlowControl(FLOW_OFF);
port->setParity(par);
port->setDataBits(db);
if (port->open(QIODevice::ReadWrite) == true) {
connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
qDebug() << "listening for data on" << port->portName();
emit connected();
return 1;
}
else {
qDebug() << "device failed to open:";
qDebug() << " device:" << portname;
qDebug() << " errorstring:" << port->errorString();
return -1;
}
}
/***************************************************************************
* *************************************************************************
*
* QT4 ( = QextSerialPort) specific methodes
*
***************************************************************************
***************************************************************************/
#else
int COM_interface::open(const QString & portname, int baudrate)
{
BaudRateType br = BAUD115200;
switch (baudrate) {
case 9600: br = BAUD9600;
break;
case 57600: br = BAUD57600;
break;
default: br = BAUD115200;
break;
}
qDebug() << "COM_interface::open(): baudrate = " << baudrate;
qDebug() << "COM_interface::open(): br = " << br;
port->setPortName(portname);
port->setBaudRate(br);
port->setStopBits(STOP_1);
//port->setFlowControl(FLOW_OFF);
port->setParity(PAR_NONE);
port->setDataBits(DATA_8);
port->setTimeout(0);
if (port->open(QIODevice::ReadWrite) == true) {
connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
connect(port, SIGNAL(dsrChanged(bool)), this, SLOT(onDsrChanged(bool)));
if (!(port->lineStatus() & LS_DSR))
qDebug() << "warning: device is not turned on";
qDebug() << "listening for data on" << port->portName();
emit connected();
return 1;
}
else {
qDebug() << "device failed to open:";
qDebug() << " device:" << portname;
qDebug() << " errorstring:" << port->errorString();
return -1;
}
}
int COM_interface::open(const QString & portname, int baudrate, int dataBits, int stopBits, int parity)
{
BaudRateType br = BAUD115200;
DataBitsType db = DATA_8;
StopBitsType sb = STOP_1;
ParityType par = PAR_NONE;
switch (baudrate) {
case 9600: br = BAUD9600;
break;
case 57600: br = BAUD57600;
break;
default: br = BAUD115200;
break;
}
//TODO Add if needed!
switch (dataBits) {
default: db = DATA_8;
break;
}
switch (stopBits) {
case 2: sb = STOP_2;
break;
default: sb = STOP_1;
break;
}
switch (parity) {
default: par = PAR_NONE;
break;
}
qDebug() << "COM_interface::open(): baudrate = " << baudrate;
qDebug() << "COM_interface::open(): br = " << br;
qDebug() << "COM_interface::open(): databits = " << dataBits;
qDebug() << "COM_interface::open(): db = " << db;
qDebug() << "COM_interface::open(): stopbits = " << stopBits;
qDebug() << "COM_interface::open(): sb = " << sb;
qDebug() << "COM_interface::open(): parity = " << parity;
qDebug() << "COM_interface::open(): par = " << par;
port->setPortName(portname);
port->setBaudRate(br);
port->setStopBits(sb);
//port->setFlowControl(FLOW_OFF);
port->setParity(par);
port->setDataBits(db);
port->setTimeout(0);
if (port->open(QIODevice::ReadWrite) == true) {
connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
connect(port, SIGNAL(dsrChanged(bool)), this, SLOT(onDsrChanged(bool)));
if (!(port->lineStatus() & LS_DSR))
qDebug() << "warning: device is not turned on";
qDebug() << "listening for data on" << port->portName();
emit connected();
return 1;
}
else {
qDebug() << "device failed to open:";
qDebug() << " device:" << portname;
qDebug() << " errorstring:" << port->errorString();
return -1;
}
}
#endif
int COM_interface::close(void)
{
if (port->isOpen()) {
port->flush();
//port->reset();
port->close();
port->reset();
}
emit disconnected();
return 0;
}
void COM_interface::onReadyRead(void) {
qint64 i;
i = 0;
buffer->clear();
while (1) {
char c;
if (port->read(& c, 1) <= 0)
break;
qDebug() << "com_interface::onReadyRead(): buffer[" << i << "]: '" << c << "'";
buffer->insert(i++,c);
}
emit ReadData(buffer);
}
void COM_interface::onDsrChanged(bool state) {
// DSR-line is not used with CLR200 reader
// so we do nothing on this signal.
qDebug() << "onDsrChanged(): state is " << state;
}
void COM_interface::putChar(const char c) {
port->putChar(c);
}

View File

@@ -0,0 +1,53 @@
#ifndef COM_INTERFACE_H
#define COM_INTERFACE_H
#include <QObject>
#if QT_VERSION >=0x050000
class QSerialPort;
#else
class QextSerialPort;
#endif
class COM_interface : public QObject
{
Q_OBJECT
private:
#if QT_VERSION >=0x050000
QSerialPort *port;
#else
QextSerialPort *port;
#endif
QByteArray *buffer;
public:
explicit COM_interface(QObject *parent = nullptr);
~COM_interface();
int open(const QString & portname, int baudrate);
int open(const QString & portname, int baudrate, int dataBits, int stopBits, int parity);
int close(void);
void putChar(const char c);
int isOpen(void);
signals:
void ReadData(QByteArray *buffer);
void connected(void);
void disconnected(void);
public slots:
private slots:
void onReadyRead(void);
void onDsrChanged(bool state);
};
#endif // COM_INTERFACE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,394 @@
#ifndef VMC_H
#define VMC_H
#include "com_interface.h"
#include "VMC/ReceiveBuffer.h"
#include "SendBuffer.h"
#include "support/VendingData.h"
#include <QObject>
#include <QByteArray>
#include <QStateMachine>
#include <QDebug>
#include <QTimer>
#include <QList>
#include "version.h"
#define VMC_RECEIVE_TIMEOUT 1000
#define VMC_CMD_SW_VERSION 0x10
#define VMC_CMD_STATUS_REQUEST 0x11
#define VMC_CMD_SCREEN 0x44
#define VMC_CMD_LANGUAGE 0x46
#define VMC_CMD_DISP_LICENCE_PLATE 0x48
#define VMC_CMD_DISP_PRODUCT 0x49
#define VMC_CMD_DISP_PARKTIME_END 0x50
#define VMC_CMD_DISP_PRICE 0x51
#define VMC_CMD_DATE_TIME 0x52
#define VMC_CMD_DISP_LINE1 0x53
#define VMC_CMD_DISP_LINE2 0x54
#define VMC_CMD_USER_MESSAGE 0x55
#define VMC_CMD_DISP_AMOUNT_TO_PAY 0x56
#define VMC_CMD_TEXT 0x60
#define VMC_CMD_TEXT_ENC 0x61
#define VMC_CMD_MACHINE_NR 0x62
#define VMC_CMD_SYSTEM 0x63
#define VMC_CMD_PSA_CONFIG 0x64
#define VMC_CMD_BUSY 0x66
#define VMC_CMD_MESSAGE_BOX 0x67
#define VMC_CMD_END_PRG 0x70 // kill ATBQT
#define VMC_CMD_SHUTDOWN_SYSTEM 0x71 // 'halt'
#define VMC_CMD_RESTART_PRG 0x72 // restart ATBQT
#define VMC_CMD_RESTART_SYSTEM 0x73 // reboot ptu
#define VMC_CMD_SCREEN_CFG 0x90
#define VMC_CMD_FORMATED_STRING 0xD0
#define VMC_CMD_VMC_SYSTEM 0xE0
#define VMC_CMD_SCREEN_INVALID 0x00
#define VMC_CMD_SCREEN_START 0x30
#define VMC_CMD_SCREEN_LICPLT 0x31
#define VMC_CMD_SCREEN_PRODUCT 0x32
#define VMC_CMD_SCREEN_PARKEND 0x33
#define VMC_CMD_SCREEN_PAYMETH 0x34
#define VMC_CMD_SCREEN_CREDITCARD 0x35
#define VMC_CMD_SCREEN_WAIT_FOR 0x36
#define VMC_CMD_SCREEN_GOODBYE 0x37
#define VMC_CMD_SCREEN_CASHPAY 0x38
#define VMC_CMD_SCREEN_PIN 0x39
#define VMC_CMD_SCREEN_RESIDENT 0x3A
#define VMC_CMD_SCREEN_GOODBYE2 0x3B
#define VMC_CMD_SCREEN_RECEIPT 0x3C
#define VMC_CMD_SCREEN_FREEPARK 0x3D
#define VMC_CMD_SCREEN_DEFBUTTONS 0x3E
#define VMC_CMD_SCREEN_PAYMETHODE1 0x3F
#define VMC_CMD_SCREEN_PAYMETHODE2 0x40
#define VMC_CMD_SCREEN_PAYMETHODE3 0x41
#define VMC_CMD_SCREEN_PAYMETHODE4 0x42
#define VMC_CMD_SCREEN_CARDSTATUS 0x43
#define VMC_CMD_SCREEN_PAYMETHODE5 0x44
#define VMC_CMD_SCREEN_PAYMETHODE6 0x45
#define VMC_CMD_SCREEN_PAYMETHODE7 0x46
#define VMC_CMD_SCREEN_CREDITCARDABORT 0x47
#define VMC_CMD_SCREEN_PAYMETHODE8 0x48
#define VMC_CMD_SCREEN_REMOVECARD 0x49
#define VMC_CMD_SCREEN_GOODBYE3 0x4A
#define VMC_CMD_SCREEN_GENERALABORT 0x4B
#define VMC_CMD_SCREEN_ABORT2 0x4C
#define VMC_CMD_SCREEN_ABORT3 0x4D
#define VMC_CMD_SCREEN_GOODBYE4 0x4E
#define VMC_CMD_SCREEN_GOODBYE5 0x4F
// note: SCREEN_COMMON is 0x50
#define VMC_CMD_SCREEN_FINEPAYMENT 0x51
#define VMC_CMD_SCREEN_CREDITCARD2 0x52
#define VMC_CMD_SCREEN_CREDITCARD3 0x53
#define VMC_CMD_SCREEN_RECEIPT2 0x54
#define VMC_CMD_SCREEN_CREDITCARD4 0x55
#define VMC_CMD_SCREEN_TWO_PRODUCTS1 0x56
#define VMC_CMD_SCREEN_TWO_PRODUCTS2 0x57
#define VMC_CMD_SCREEN_PARKTIME1 0x5a
#define VMC_CMD_SCREEN_PARKTIME2 0x5b
#define VMC_CMD_SCREEN_DATETIME1 0x5c
#define VMC_CMD_SCREEN_DATETIME2 0x5d
#define VMC_CMD_SCREEN_DIAG 0x60
#define VMC_CMD_SCREEN_WELCOME1 0x61
#define VMC_CMD_SCREEN_WELCOME2 0x62
#define VMC_CMD_SCREEN_WELCOME3 0x63
#define VMC_CMD_SCREEN_WELCOME4 0x64
#define VMC_CMD_SCREEN_OOO 0x65
#define VMC_CMD_SCREEN_WAIT1 0x6A
#define VMC_CMD_SCREEN_WAIT2 0x6B
#define VMC_CMD_SCREEN_WAIT3 0x6C
#define VMC_CMD_SCREEN_WAIT4 0x6D
#define VMC_CMD_SCREEN_TARIF 0x70
#define VMC_CMD_SCREEN_HELP1 0x71
#define VMC_CMD_SCREEN_HELP2 0x72
#define VMC_CMD_SCREEN_HELP3 0x73
#define VMC_CMD_SCREEN_HELP4 0x74
#define VMC_CMD_SCREEN_HELP5 0x75
#define VMC_CMD_SCREEN_ABORT4 0x80
#define VMC_CMD_SCREEN_ABORT5 0x81
#define VMC_CMD_SCREEN_BARCODE 0x82
#define VMC_CMD_SCREEN_AGEVERIFICATION 0x83
#define VMC_CMD_SCREEN_DEFBUTTONS2 0x84
#define VMC_CMD_SCREEN_DEFBUTTONS3 0x85
#define VMC_CMD_SCREEN_PRINT2 0x86
#define VMC_CMD_SCREEN_PRINT3 0x87
#define VMC_CMD_SCREEN_QRCODE_RECEIPT 0x88
#define VMC_CMD_SCREEN_LICPLT2 0x90
#define VMC_CMD_SCREEN_LICPLT3 0x91
#define VMC_CMD_SCREEN_LICPLT4 0x92
#define VMC_CMD_SCREEN_ABORT6 0x93
#define VMC_CMD_SCREEN_ABORT7 0x94
#define VMC_CMD_SCREEN_PARKEND2 0xA0
#define VMC_CMD_SCREEN_PARKEND3 0xA1
#define VMC_CMD_SCREEN_COMMON 0x50
#define VMC_CMD_SCREEN_MESSAGE_BOX 0xF1
// CARD_SERVICE_ERROR_TEXTS 0xFA
#define ACK 0x06
#define NACK 0x15
class AppControl;
class ReceiveBuffer;
class SendBuffer;
class HMI;
class ATBHMIconfig;
class VMC : public QObject
{
Q_OBJECT
private:
AppControl *main;
COM_interface *com_interface;
ReceiveBuffer *receiveBuffer;
SendBuffer *sendBuffer;
ATBHMIconfig *config;
// internal: write a ByteArray to com-port:
int SendMessage(QByteArray ba, bool enqueue = false);
quint16 parseSystemCommand(QByteArray & cmd);
quint8 parseTextCommand(QByteArray & cmd);
quint8 parseTextCommandEnc(QByteArray & cmd);
quint8 parseDataDisplayCommand(QByteArray & cmd);
quint8 parseDateCommand(QByteArray & cmd);
quint8 parseUserMessageCommand(QByteArray & cmd);
quint8 parseLanguageCommand(QByteArray & cmd);
quint8 parseBusyCommand(QByteArray & cmd);
quint8 parseScreenConfigCommand(QByteArray & cmd);
quint8 parsePSAConfigCommand(QByteArray & cmd);
quint8 parseShowMessageBoxCommand(QByteArray & cmd);
quint8 parseVMCSystemMessage(QByteArray & cmd);
quint8 parseVMCFormatedString(QByteArray & cmd);
QString & privateHandleDataCommand_Amount(quint8 data, QString & dataString);
QString & privateHandleDataCommand_AmountToPay(quint8 data, QString & dataString);
QTimer *sendDelayTimer;
QString delayedMessage;
quint8 flag_blockVMCScreen;
quint16 currentCachedScreen;
private slots:
void onDelayedMessageTimerTimeout();
void skipDiscount();
public:
explicit VMC(QObject *parent = nullptr);
VMC(AppControl *main, ATBHMIconfig *config, QObject *parent = nullptr);
~VMC();
int SendMessage(QString msg);
int SendMessageDelayed(QString msg, int delay);
int SendACK();
int SendNACK();
int sendButtonChar(QChar c);
int SendButton0(); // 0 - 3E 45 31 30 E4
int SendButton1(); // 1 - 3E 45 31 31 E5
int SendButton2(); // 2 - 3E 45 31 32 E6
int SendButton3(); // 3 - 3E 45 31 33 E7
int SendButton4(); // 4 - 3E 45 31 34 E8
int SendButton5(); // 5 - 3E 45 31 35 E9
int SendButton6(); // 6 - 3E 45 31 36 EA
int SendButton7(); // 7 - 3E 45 31 37 EB
int SendButton8(); // 8 - 3E 45 31 38 EC
int SendButton9(); // 9 - 3E 45 31 39 ED
int SendButtonNext(); // 10 - 3E 45 31 3A EE
int SendButtonBack(); // 11 - 3E 45 31 3B EF
int SendButtonCancel(); // 12 - 3E 45 31 3C F0
int SendButtonStart(); // 13 - 3E 45 31 3D F1
int SendButtonHelp(); // 14 - 3E 45 31 3E F2
int SendButtonTarif(); // 15 - 3E 45 31 3F F3
int SendButtonStart2(); // - 3E 45 31 A0 cs
int SendButtonStart3(); // - 3E 45 31 A1 cs
int SendButtonStart4(); // - 3E 45 31 A2 cs
int SendButtonArrowLeft(); // 16 - 3E 45 31 83 cs
int SendButtonArrowRight(); // 17 - 3E 45 31 84 cs -
int SendButtonArrowUp(); // 18 - 3E 45 31 85 cs -
int SendButtonArrowDown(); // 19 - 3E 45 31 86 cs -
int SendButtonCardTypeLeft(); // 20 - 3E 45 31 87 cs -
int SendButtonCardTypeRight(); // 21 - 3E 45 31 88 cs -
int SendButtonA(); // 'A' - 3E 45 31 41 F5
int SendButtonB(); // 'B' - 3E 45 31 42 F6
int SendButtonC(); // 'C' - 3E 45 31 43 F7
int SendButtonD(); // 'D' - 3E 45 31 44 F8
int SendButtonE(); // 'E' - 3E 45 31 45 F9
int SendButtonF(); // 'F' - 3E 45 31 46 FA
int SendButtonG(); // 'G' - 3E 45 31 47 FB
int SendButtonH(); // 'H' - 3E 45 31 48 FC
int SendButtonI(); // 'I' - 3E 45 31 49 FD
int SendButtonJ(); // 'J' - 3E 45 31 4A FE
int SendButtonK(); // 'K' - 3E 45 31 4B FF
int SendButtonL(); // 'L' - 3E 45 31 4C 00
int SendButtonM(); // 'M' - 3E 45 31 4D 01
int SendButtonN(); // 'N' - 3E 45 31 4E 02
int SendButtonO(); // 'O' - 3E 45 31 4F 03
int SendButtonP(); // 'P' - 3E 45 31 50 04
int SendButtonQ(); // 'Q' - 3E 45 31 51 05
int SendButtonR(); // 'R' - 3E 45 31 52 06
int SendButtonS(); // 'S' - 3E 45 31 53 07
int SendButtonT(); // 'T' - 3E 45 31 54 08
int SendButtonU(); // 'U' - 3E 45 31 55 09
int SendButtonV(); // 'V' - 3E 45 31 56 0A
int SendButtonW(); // 'W' - 3E 45 31 57 0B
int SendButtonX(); // 'X' - 3E 45 31 58 0C
int SendButtonY(); // 'Y' - 3E 45 31 59 0D
int SendButtonZ(); // 'Z' - 3E 45 31 5A 0E
int SendButtonUE(); // 'Ü' - 3E 45 31 DC - ISO 8859-1 (Latin-1): 'Ü'
int SendButtonOE(); // 'Ö' - 3E 45 31 D6 - ISO 8859-1 (Latin-1): 'Ö'
int SendButtonAE(); // 'Ä' - 3E 45 31 C4 - ISO 8859-1 (Latin-1): 'Ä'
int SendButtonDEL(); // DELL - 3E 45 31 7F 33
int SendButtonDash(); // '-' - 3E 45 31 2D E1
int SendButtonSpace(); // ' ' - 3E 45 31 20 D4
int SendButtonClose(); // - 3E 45 31 80 cs
int SendButtonYes(); // - 3E 45 31 81 cs
int SendButtonNo(); // - 3E 45 31 82 cs
int SendButtonVehicleDefintion1(); // 0x90 - 3E 45 31 90 cs
int SendButtonVehicleDefintion2(); // 0x91 - 3E 45 31 91 cs
int SendButtonVehicleDefintion3(); // 0x92 - 3E 45 31 92 cs
int SendButtonVehicleDefintion4(); // 0x93 - 3E 45 31 93 cs
int SendButtonVehicleDefintion5(); // 0x94 - 3E 45 31 94 cs
int SendButtonVehicleDefintion6(); // 0x95 - 3E 45 31 95 cs
int SendButtonVehicleDefintion7(); // 0x96 - 3E 45 31 96 cs
int SendButtonVehicleDefintion8(); // 0x97 - 3E 45 31 97 cs
int SendButtonPaymethode1(); // 0x98 - 3E 45 31 98 cs
int SendButtonPaymethode2(); // 0x99 - 3E 45 31 99 cs
int SendButtonPaymethode3(); // 0x9a - 3E 45 31 9a cs
int SendButtonPaymethode4(); // 0x9b - 3E 45 31 9b cs
int SendSystemMessage(quint8 nr); // 0xF0 - 3E F0 31 nr cs
int SendSystemMessageStart(); // 0xF0 - 3E F0 31 31 cs
int SendSystemMessageTimeout(); // 0xF0 - 3E F0 31 32 cs
int SendButtonServiceOK(QString MessageString);
// deprecated:
int SendLicPlate(QString licplate);
int SendBarcode(QString barcode);
int SendAmountDueTax(QString amount);
int SendAmountDueNet(QString amount);
int SendAmountDuePeriodStart(QString startTime);
int SendAmountDuePeriodEnd(QString endTime);
int SendCracePeriod(QString minute);
int SendGeneratedPinNumber(QString pin);
// from former "Bewonerscode": send code and id
int SendId(QString id);
int SendCode(QString code);
int SendFormatedString(QString formatString);
int SendFormatedStringError(QString errorString);
int SendLangSwitch(quint8 nr);
int SendVersion(QString VersionString); // 3E 10 14 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. CRC
int SendCurrentState();
void blockScreenSwitch(quint8 mode);
quint16 getCurrentCachedScreen();
signals:
void CommandProcessed(); // sent to ReceiveBuffer if a command is processed
void retriggerModeSell();
void setBusy();
void resetBusy();
void showMessageBox(quint8 type, quint8 text);
void sysCommand(quint16 cmd, QByteArray data);
//void PSAconfig(quint16 cust_nr, quint16 group_nr, quint16 zone_nr, quint16 machine_nr);
void setCustNr(const QString & cust_nr);
void setGroupNr(const QString & group_nr);
void setZoneNr(const QString & zone_nr);
void setMachineNr(const QString & machine_nr);
void displayData(quint8 infoFild, QString text);
void newDateTime(const QString & dateTimeString);
void setLanguage(quint8 lang);
void setDefaultLanguage(quint8 lang);
void userMessage(quint8 messagenr, quint8 action);
void writeLog(QString str);
void writeLogReceived(QByteArray ba);
void writeLogSent(QByteArray ba);
void wakeVMC();
void ccStartTransaction();
void ccConfirmTransaction();
void ccCancelTransaction();
void ccStartPreauthorisation();
void ccConfirmPreauthorisation();
void ccCancelPreauthorisation();
void ccStartReadCard();
void ccWakup();
void ccSleep();
#ifdef USE_BARCODESCANNER
void requestNewBarcode();
#endif
void VMCSystemSellingProcessStart();
void VMCSystemSellingProcessStop();
void VMCSystemTransactionSuccess();
void VMCFormatedString(FormatedStringList);
void setVendingData(QString key, QByteArray value);
public slots:
void CommandAvaliable(QByteArray message); // called when a message is in receive buffer
void onReceiveError(RECEIVE_ERROR error); // for response on wrong vmc commands
void onSendError(SEND_ERROR error); // for react on e.g. a non answering vmc
int SendLongFormatedString(QString formatString);
int SendLongFormatedStringReference(QString & formatedString);
void ccStartTransactionRequest(); // called to start/restart a CC transaction
void ccStartConfirmTransaction(); // called to start confirmation
void ccPrintReceipt(QString receipt); // called to send receipt to vmc
};
#endif // VMC_H

View File

@@ -0,0 +1,76 @@
#include "VendingData.h"
#include <QDebug>
#include "ATBAPP.h"
#include "version.h"
VendingData::VendingData(QObject *parent) : QObject(parent)
{
qRegisterMetaType<FormatedStringList>("FormatedStringList");
}
QVariant VendingData::getParameter(const QString & key)
{
#if defined (ARCH_DesktopLinux)
// note: QVariant.toString() returns empty string for custom types
if (QString::compare(hash.value(key).typeName(), "APP_ACTION") == 0) {
APP_ACTION action = hash.value(key).value<APP_ACTION>();
qDebug() << "VendingData::getParameter() key = " << key << " value = " << action;
}
else {
qDebug() << "VendingData::getParameter() key = " << key << " value = " << hash.value(key).toString();
}
#endif
return hash.value(key);
}
void VendingData::setParameter(const QString & key, QVariant value)
{
#if defined (ARCH_DesktopLinux)
// note: QVariant.toString() returns empty string for custom types
if (QString::compare(value.typeName(), "APP_ACTION") == 0) {
APP_ACTION action = value.value<APP_ACTION>();
qDebug() << "VendingData::setParameter() key = " << key << " value = " << action;
}
else {
qDebug() << "VendingData::setParameter() key = " << key << " value = " << value.toString();
}
#endif
this->hash.insert(key, value);
}
void VendingData::clearParameter(const QString & key)
{
this->hash.remove(key);
}
bool VendingData::hasParameter(const QString & key)
{
return hash.contains(key);
}
void VendingData::clear()
{
this->hash.clear();
}
uint VendingData::getUintParameter(const QString & key)
{
qDebug() << "VendingData::getUintParameter() key = " << key << " value = " << hash.value(key).toString();
uint returnValue = 0;
bool ok;
returnValue = hash.value(key).toString().toUInt(&ok);
if (!ok) returnValue = 0;
return returnValue;
}

View File

@@ -0,0 +1,37 @@
#ifndef VENDINGDATA_H
#define VENDINGDATA_H
#include <QObject>
#include <QHash>
#include <QVariant>
typedef QList<QByteArray> FormatedStringList;
class VendingData : public QObject
{
Q_OBJECT
private:
QHash<QString, QVariant> hash;
public:
explicit VendingData(QObject *parent = nullptr);
QVariant getParameter(const QString & key);
void setParameter(const QString & key, QVariant value);
void clearParameter(const QString & key);
bool hasParameter(const QString & key);
uint getUintParameter(const QString & key);
signals:
public slots:
void clear();
};
#endif // VENDINGDATA_H