#include "ModbusSEIMgr.h" #include #include "ModbusCCDefs.h" #include "ModbusSEIDefs.h" #include "GlobalDefine.h" #include CModbusSEIMgr::CModbusSEIMgr(CModbusRepository *SEIRepo, CModbusRepository *CCRepo, QHostAddress ServerIP, int ModbusPort, int DevID): CModbusBackend(SEIRepo) { // connect(mModbusTCPSocketHandle,SIGNAL(readyRead()),this,SLOT(ModbusDataReady())); mModbusMode = MODBUS_MASTER_MODE; mModbusPort = ModbusPort; mDeviceID = DevID; mSEIIPAddress = ServerIP; mCCRepoHandle = CCRepo; mZTWatchdog = false; mConnectionTimer = new QTimer(); mConnectionTimer->setInterval(SEI_CLIENT_RECONNECT_TIMEOUT); mConnectionTimer->setSingleShot(false); mConnectionTimer->stop(); mSEIModbusUpdateTimer = new QTimer(); mSEIModbusUpdateTimer->setInterval(1000); mSEIModbusUpdateTimer->setSingleShot(false); mSEIModbusUpdateTimer->stop(); mModbusTCPSocketHandle = new QTcpSocket(); connect(mModbusTCPSocketHandle,SIGNAL(readyRead()),this,SLOT(ModbusDataReady())); connect(mModbusTCPSocketHandle,SIGNAL(disconnected()),this,SLOT(SocketDisconnected())); connect(mModbusTCPSocketHandle,SIGNAL(connected()),this,SLOT(SocketConnected())); connect(mConnectionTimer,SIGNAL(timeout()),this,SLOT(ConnectionTimerExpired())); connect(mSEIModbusUpdateTimer,SIGNAL(timeout()),this,SLOT(SEIModbusUpdateTimerExpired())); } CModbusSEIMgr::~CModbusSEIMgr() { if(mModbusTCPSocketHandle->state() != QAbstractSocket::UnconnectedState) { mModbusTCPSocketHandle->disconnectFromHost(); mModbusTCPSocketHandle->waitForDisconnected(1000); } delete mModbusTCPSocketHandle; if(mConnectionTimer) delete mConnectionTimer; if(mSEIModbusUpdateTimer) delete mSEIModbusUpdateTimer; } int CModbusSEIMgr::StartSEICommunication() { mConnectionTimer->start(); return RET_OK; } int CModbusSEIMgr::ConnectToSlave(QHostAddress SlaveIP, int SlavePort) { if(mModbusTCPSocketHandle->state() != QAbstractSocket::UnconnectedState) { return RET_ERROR; } mModbusTCPSocketHandle->connectToHost(SlaveIP,SlavePort); return RET_OK; } int CModbusSEIMgr::DisconnectFromSlave() { mModbusTCPSocketHandle->disconnectFromHost(); mConnectionTimer->start(); return 1; } void CModbusSEIMgr::SocketConnected() { emit ModbusMasterConnected(mModbusTCPSocketHandle->localAddress().toIPv4Address(),mModbusTCPSocketHandle->peerAddress().toIPv4Address()); // qDebug("Master: Connection established with NetTrac"); CZTLog::instance()->AddLogString("Connection Modbus (Ethernet) avec NetTrac établi",true); mConnectionTimer->stop(); mSEIModbusUpdateTimer->start(); } void CModbusSEIMgr::SocketDisconnected() { ModbusLinkDisconnected(); emit ModbusMasterDisconnected(); mConnectionTimer->start(); mSEIModbusUpdateTimer->stop(); // qDebug("Disconnected from NetTrac"); // CZTLog::instance()->AddLogString("Connexion avec NetTrac établi",true); CZTLog::instance()->AddLogString("Connection Modbus (Ethernet) avec NetTrac rompue",true); } int CModbusSEIMgr::ReadModbusRegisters() { //return SendReadHoldingRegistersRequest(ZT_DATA_BASE_REGISTER_ADDRESS,4); //Read all 3 registers from ZT (2000 - 2003) return RET_OK; } void CModbusSEIMgr::ConnectionTimerExpired() { //Establish connection only if not connected if(mModbusTCPSocketHandle->state() == QAbstractSocket::UnconnectedState) { ConnectToSlave(mSEIIPAddress,mModbusPort); } } int CModbusSEIMgr::SEISettingsChanged(QHostAddress ServerIP, int ModbusPort, int DevID) { if(DevID > 255) { return RET_ERROR; } mSEIIPAddress = ServerIP; mModbusPort = ModbusPort; mDeviceID = DevID; //Make shure we are disconnected. Connection timer will do the reconnection. DisconnectFromSlave(); return RET_OK; } void CModbusSEIMgr::SEIModbusUpdateTimerExpired() { //The SEI Modbus table is updated on event, triggered by the TKTransport object (see ZTTKUpdated()). //Just update the watchdog and send the current table. mZTWatchdog = !mZTWatchdog; if(mZTWatchdog) { mModbusRepo->WriteSingleReg(SEI_MODBUS_ZT_WATCHDOG_REG,0x01); } else { mModbusRepo->WriteSingleReg(SEI_MODBUS_ZT_WATCHDOG_REG,0); } SendWriteHoldingRegistersRequest(SEI_MODBUS_ZT_DATA_BASE_REG,SEI_MODBUS_ZT_TABLE_DATA_SIZE); } //This signal is emitted by TKTransport when a changed happened in the TK after the CC modbus table has been updated. //We just need to copy the relevant info from the CC repo... //As per specification, we must also send an update on change to the SEI void CModbusSEIMgr::ZTTKUpdated() { //Copy data from CC modbus table to SEI modbus table. mModbusRepo->WriteHRData(SEI_MODBUS_ZT_DATA_BASE_REG,SEI_MODBUS_ZT_TABLE_DATA_SIZE,mCCRepoHandle->GetHRData(MODBUS_ZT_DATA_BASE_REG,SEI_MODBUS_ZT_TABLE_DATA_SIZE)); //Keep our actual watchdog value.. if(mZTWatchdog) { mModbusRepo->WriteSingleReg(SEI_MODBUS_ZT_WATCHDOG_REG,0x01); } else { mModbusRepo->WriteSingleReg(SEI_MODBUS_ZT_WATCHDOG_REG,0); } //Send the data now to NetTrac SendWriteHoldingRegistersRequest(SEI_MODBUS_ZT_WATCHDOG_REG,SEI_MODBUS_ZT_TABLE_DATA_SIZE); } void CModbusSEIMgr::RegistersDatabaseUpdated(quint16 StartAddress, quint16 Length) { Q_UNUSED(StartAddress) Q_UNUSED(Length) emit ModbusMasterRepositoryUpdated(); } void CModbusSEIMgr::ModbusResponseException(quint8 ExceptionCode, quint8 FctCode) { qDebug("Modbus MASTER exception: code:%d Fct:%d",ExceptionCode,FctCode); }