204 lines
8.3 KiB
C++
204 lines
8.3 KiB
C++
/*******************************************************************************/
|
|
/*
|
|
Description:
|
|
Classe qui implémente le protocole Modbus.
|
|
Cette classe est héritée par la classe serveur (CModbusCCMgr) ou client (CModbusMaster).
|
|
Elle sert à interpréter ou formatter des paquets Modbus provenant ou destinés au partenaire.
|
|
Elle peut être héritée soit un parent qui implémente une instance maître ou client mais pas les deux à la fois.
|
|
sur le réseau.
|
|
|
|
*/
|
|
|
|
/* ************************************************************************** */
|
|
/* Revision:
|
|
### YYYMMDD JFM
|
|
Verision d'origine.
|
|
|
|
### YYYYMMDD Description du besoin ou du bug
|
|
Description du changement.
|
|
*/
|
|
|
|
/* ************************************************************************** */
|
|
|
|
#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
|
|
};
|
|
|
|
//Énumération des différents modes possibles
|
|
enum eModbusModes
|
|
{
|
|
MODBUS_MASTER_MODE,
|
|
MODBUS_SLAVE_MODE,
|
|
MODBUS_INVALID_MODE
|
|
};
|
|
|
|
class CModbusException
|
|
{
|
|
public:
|
|
|
|
};
|
|
|
|
class CModbusPDU
|
|
{
|
|
public:
|
|
qint8 mFunctionCode; //Type de transaction (voir structure eModbusFunctions) pour les fonctions implémentées par le présent module
|
|
QByteArray mData; //Les données de la transaction
|
|
};
|
|
|
|
class CModbusHeader //Objet contenant les données d'un header Modbus (selon la spécification)
|
|
{
|
|
public:
|
|
qint16 mTransactionID;
|
|
qint16 mProtocolID;
|
|
qint16 mMessageLength;
|
|
qint8 mUnitID;
|
|
};
|
|
|
|
class CModbusTransaction //Objet contenant les données d'une transaction Modbus
|
|
{
|
|
public:
|
|
CModbusHeader mHeader; //Le header de la transaction
|
|
CModbusPDU mPDU; //Le PDU (fonction & données) de la transaction (voir classe CModbusPDU)
|
|
};
|
|
|
|
class CModbusRequest : public CModbusTransaction //Objet représentant une transaction (mode maître)
|
|
{
|
|
public:
|
|
CModbusRequest();
|
|
~CModbusRequest();
|
|
int mRetries; //nombre de fois que la transaction a été retransmise
|
|
QTimer *mRequestTimer; //Timer servant à retransmettre la requête si aucune réponse ne survient
|
|
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); //Le pointeur vers le registre des données est obligatoire.
|
|
virtual ~CModbusBackend();
|
|
QTcpSocket *mModbusTCPSocketHandle; //Pointeur vers le Socket TCP du réseau Modbus.
|
|
CModbusRepository *mModbusRepo; //Pointeur vers le registre de données Modbus
|
|
|
|
bool mDataLinkValid; //Flag indiquant si le lien de communication est en santé
|
|
int mModbusMode; //Indique si le lien modbus de cette instance est exploitée en "slave" (serveur) ou un "master" (client) (voir struct eModbusModes ci-haut).
|
|
qint8 mDeviceID; //Le device ID Modbus de cette instance.
|
|
void ModbusLinkDisconnected(); //Fonction appelée par le parent lors d'une perte de la connection.
|
|
void SetDeviceID(qint8 ID){mDeviceID = ID;}
|
|
|
|
//Master (client)
|
|
int SendReadHoldingRegistersRequest(quint16 StartAddress, quint16 RegisterCount); //Fonction servant à transmettre la fonction modbus "Read HR" au partenaire
|
|
int SendWriteHoldingRegistersRequest(quint16 StartAddress, quint16 RegisterCount); //Fonction servant à transmettre la fonction modbus "Write HR" au partenaire
|
|
int SendWriteSingleRegisterRequest(quint16 Address); //Fonction servant à transmettre la fonction modbus "Write Single Register" au partenaire
|
|
|
|
|
|
|
|
|
|
virtual void RegistersDatabaseUpdated(quint16 StartAdderss, quint16 Length) = 0; //Fonction virtuelle à être implémentée par la classe dérivée
|
|
//Appelée lorsque de nouvelles données ont été reçues du réseau Modbus et écrites dans le registre
|
|
|
|
|
|
|
|
//Master virtual functions
|
|
virtual void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode); //Fonction virtuelle à être implémentée par la classe dérivée
|
|
virtual void ModbusWriteMultipleRegsSuccess(); //Fonction virtuelle à être implémentée par la classe dérivée (Modbus Master seulement). Appelée suite à la réception d'une réponse à une requête d'écriture multiple.
|
|
virtual void ModbusWriteSingleRegsSuccess(); //Fonction virtuelle à être implémentée par la classe dérivée (Modbus Master seulement). Appelée suite à la réception d'une réponse à une requête d'écriture simple.
|
|
virtual void ModbusRequestMaxRetryReached(); //Fonction virtuelle à être implémentée par la classe dérivée (Modbus Master seulement). Appelée lors de l'atteinte du nombre maximal d'essai de transmission d'une requête.
|
|
//Sert à informer la classe dérivée lorsqu'une exception se produit dans la communication Modbus (réponse)
|
|
|
|
|
|
//Slave virtual function
|
|
virtual void ModbusRequestException(quint8 ExceptionCode, quint8 FctCode); //Fonction virtuelle à être implémentée par la classe dérivée
|
|
//Sert à informer le parent lorsqu'une exception se produit dans la communication Modbus (requête)
|
|
|
|
|
|
private:
|
|
|
|
|
|
//Sur un réseau Modbus, l'eslcave (slave) est un serveur et le maître (master) est un client.
|
|
|
|
|
|
//Slave (server)
|
|
int AnalyzeModbusRequest(CModbusTransaction Transaction); //Exécute l'analyse des données reçues d'une requête Modbus
|
|
int SendModbusResponse(CModbusTransaction RequestTransaction, QByteArray Data); //Fonction servant à composer et transmettre une réponse à une requête.
|
|
int SendErrorResponse(CModbusTransaction RequestTransaction, quint8 ErrorCode); //Fonction servant à composer et transmettre une réponse d'erreur à une requête.
|
|
|
|
//Master (client)
|
|
QList<CModbusRequest*> mRequestsList; //Liste des requêtes courantes en attente d'une réponse du serveur
|
|
int SendModbusRequest(CModbusRequest *Request); //Construit et transmet une nouvelle requête Modbus au partenaire.
|
|
quint16 GetNewTransactionID(); //Fonction (helper) servant à générer un nouvel ID de transaction nécessaire pour transmettre une nouvelle requête.
|
|
int AnalyzeModbusResponse(CModbusTransaction Transaction); //Exécute l'analyse des données reçues d'une réponse Modbus
|
|
|
|
quint16 mTransactionIDCounter; //Compteur interne des ID de transactions Modbus
|
|
int mModbusRequestTimeout; //Valeur du délai d'attente maximal avant de recevoir une réponse à une requête. À l'expiration du timer, la requête est renvoyée.
|
|
int mModbusMaxRetry; //Valeur du nombre maximal de renvoi d'une requête avant d'invalider la requête.
|
|
|
|
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(); //Slot indiquant au module que des données sont arrivées et sont attente dans le Socket.
|
|
|
|
void RequestTimerExpired(); //Slot indiquant qu'un timer de requête a expiré.
|
|
|
|
|
|
};
|
|
|
|
|
|
QDataStream &operator<<(QDataStream &out, const CModbusHeader &source);
|
|
QDataStream &operator>>(QDataStream &in, CModbusHeader &dest);
|
|
|
|
#endif // CMODBUSBACKEND_H
|