#ifndef CMODBUSBACKEND_H #define CMODBUSBACKEND_H #include #include #include "ModbusRepository.h" #include #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 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