ZT/sources/Modbus/ModbusBackend.h

171 lines
3.9 KiB
C++

#ifndef CMODBUSBACKEND_H
#define CMODBUSBACKEND_H
#include <QObject>
#include <QTcpSocket>
#include "ModbusRepository.h"
#include <QTimer>
#define MODBUS_EXCEPTION_FCT_MASK 0x80
#define MODBUS_RETRY_DELAY 2000 //millisecs
#define MODBUS_RETRY_MAX_COUNT 2 //resend an unanswered request this many times
#define MODBUS_MAX_NB_REGISTERS 0x7D
enum eModbusFunctions
{
MODBUS_FCT_READ_HOLDING_REGISTERS = 3,
MODBUS_WRITE_SINGLE_REGISTER = 6,
MODBUS_FCT_WRITE_MULTIPLE_REGISTERS = 16
};
enum eModbusExceptionCodes
{
MODBUS_EXCEPTION_ILLEGAL_FCT = 1,
MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS = 2,
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE = 3,
MODBUS_EXCEPTION_SERVER_DEVICE_FAILURE = 4,
MODBUS_EXCEPTION_ACKNOWLEDGE = 5,
MODBUS_EXCEPTION_SERVER_DEVICE_BUSY = 6,
MODBUS_EXCEPTION_MEMORY_PARITY_ERROR = 8,
MODBUS_EXCEPTION_GATEWAY_PATH_UNAVAILABLE = 10,
MODBUS_EXCEPTION_GATEWAY_TARGET_DEV_NOT_RESPONDING = 11
};
enum eModbusModes
{
MODBUS_MASTER_MODE,
MODBUS_SLAVE_MODE,
MODBUS_INVALID_MODE
};
class CModbusException
{
public:
};
class CModbusPDU
{
public:
qint8 mFunctionCode;
QByteArray mData;
};
class CModbusHeader
{
public:
qint16 mTransactionID;
qint16 mProtocolID;
qint16 mMessageLength;
qint8 mUnitID;
};
class CModbusTransaction
{
public:
CModbusHeader mHeader;
CModbusPDU mPDU;
};
class CModbusRequest : public CModbusTransaction
{
public:
CModbusRequest();
~CModbusRequest();
int mRetries;
QTimer *mRequestTimer;
quint16 mStartAddress, mNbRegisters; //For convinience...
};
class CModbusBackend : public QObject
{
Q_OBJECT
private:
enum eModbusMasterSMStates
{
MODBUS_SM_WAIT_FOR__STATE
};
enum eModbusSlaveSMStates
{
};
public:
CModbusBackend(CModbusRepository *Repo);
virtual ~CModbusBackend();
QTcpSocket *mModbusTCPSocketHandle;
CModbusRepository *mModbusRepo;
bool mDataLinkValid;
int mModbusMode;
qint8 mDeviceID;
void ModbusLinkDisconnected();
void SetDeviceID(qint8 ID){mDeviceID = ID;}
//Master (client)
int SendReadHoldingRegistersRequest(quint16 StartAddress, quint16 RegisterCount);
int SendWriteHoldingRegistersRequest(quint16 StartAddress, quint16 RegisterCount);
int SendWriteSingleRegisterRequest(quint16 Address);
virtual void RegistersDatabaseUpdated(quint16 StartAdderss, quint16 Length) = 0;
//Master Exception
virtual void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode);
//Slave Exception
virtual void ModbusRequestException(quint8 ExceptionCode, quint8 FctCode);
private:
//Slave (server)
int AnalyzeModbusRequest(CModbusTransaction Transaction);
int ModbusStateMachine(int Event, QByteArray Data);
int SendModbusResponse(CModbusTransaction RequestTransaction, QByteArray Data);
int SendErrorResponse(CModbusTransaction RequestTransaction, quint8 ErrorCode);
//Master (client)
QList<CModbusRequest*> mRequestsList;
int SendModbusRequest(CModbusRequest *Request);
quint16 GetNewTransactionID();
int AnalyzeModbusResponse(CModbusTransaction Transaction);
quint16 mTransactionIDCounter;
int mModbusRequestTimeout;
int mModbusMaxRetry;
signals:
// void RegistersDatabaseUpdated(quint16 StartAdderss, quint16 Length);
// //Master signals
// void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode);
//// //Slave signals
// void ModbusRequestException(quint8 ExceptionCode, quint8 FctCode);
public slots:
void ModbusDataReady();
void RequestTimerExpired();
};
QDataStream &operator<<(QDataStream &out, const CModbusHeader &source);
QDataStream &operator>>(QDataStream &in, CModbusHeader &dest);
#endif // CMODBUSBACKEND_H