171 lines
3.9 KiB
C++
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
|