ZT/sources/Modbus/ModbusBackend.h
2017-09-01 14:17:18 -04:00

199 lines
7.8 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 le parent
//Appelée lorsque de nouvelles données ont été reçues du réseau Modbus et écrites dans le registre
//Master Exception
virtual void ModbusResponseException(quint8 ExceptionCode, quint8 FctCode); //Fonction virtuelle à être implémentée par le parent
//Sert à informer le parent lorsqu'une exception se produit dans la communication Modbus (réponse)
//Slave Exception
virtual void ModbusRequestException(quint8 ExceptionCode, quint8 FctCode); //Fonction virtuelle à être implémentée par le parent
//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