2023-11-24 14:08:11 +03:00
# include "modbushandler.h"
2023-12-12 16:51:50 +03:00
# define REQ_PERIOD 1000 //прериод опроса
2023-11-24 14:08:11 +03:00
2023-12-12 16:51:50 +03:00
# define TIMEOUT 120
2023-11-24 14:08:11 +03:00
ModBusHandler : : ModBusHandler ( QObject * parent ) : QObject ( parent )
{
2023-12-13 14:34:51 +03:00
modbusDevice = new QModbusRtuSerialClient ;
2023-11-24 14:08:11 +03:00
//заводим таймер
tmr = new QTimer ( ) ;
tmr - > start ( REQ_PERIOD ) ;
connect ( tmr , SIGNAL ( timeout ( ) ) , this , SLOT ( requestPriborFromList ( ) ) ) ;
// 2. Если вы находитесь в состоянии соединения, отключите соединение
if ( modbusDevice - > state ( ) = = QModbusDevice : : ConnectedState )
{
// отключимся если вдруг подключено
modbusDevice - > disconnectDevice ( ) ;
}
}
ModBusHandler : : ~ ModBusHandler ( )
{
if ( modbusDevice )
{
modbusDevice - > disconnectDevice ( ) ;
}
delete modbusDevice ;
}
void ModBusHandler : : requestPriborFromList ( ) //слот для истекшего таймера
{
//пробегаемся по листу и опрашиваем выкидываая сигналы
2023-12-12 16:51:50 +03:00
//static uint numForReqest;
2023-12-07 16:57:51 +03:00
//QMap<uint,PrborConnectonAtr>::iterator iteratorPriborMap;
2023-11-24 14:08:11 +03:00
2023-12-07 16:57:51 +03:00
// qDebug()<<"Приборов в списке "<<PriborMap.size();
2023-11-24 14:08:11 +03:00
for ( PrborConnectonAtr atr : PriborMap ) {
getDataFromPribor ( atr ) ;
}
}
void ModBusHandler : : addToReqList ( PrborConnectonAtr pribor )
{
PriborMap . insert ( pribor . adress , pribor ) ;
}
void ModBusHandler : : removeFromReqList ( uint adress )
{
PriborMap . remove ( adress ) ;
}
void ModBusHandler : : getDataFromPribor ( PrborConnectonAtr atr ) //слот для истекшего таймера
{
{
2023-12-12 16:51:50 +03:00
// modbusDevice->disconnectDevice();
2023-12-07 16:57:51 +03:00
2023-11-24 14:08:11 +03:00
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialPortNameParameter , QVariant ( atr . port ) ) ;
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialStopBitsParameter , QSerialPort : : OneStop ) ;
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialDataBitsParameter , QSerialPort : : Data8 ) ;
2023-12-13 14:34:51 +03:00
//modbusDevice->setTimeout(TIMEOUT); //1 таймаута
// modbusDevice->setNumberOfRetries(0);// попытки достучатся
2023-11-24 14:08:11 +03:00
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialBaudRateParameter , atr . speed ) ;
switch ( atr . parity ) { //выставляем парити
case UART_PARITY_NONE :
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialParityParameter , QSerialPort : : NoParity ) ;
break ;
case UART_PARITY_ODD :
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialParityParameter , QSerialPort : : OddParity ) ;
break ;
case UART_PARITY_EVEN :
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialParityParameter , QSerialPort : : EvenParity ) ;
break ;
}
}
modbusDevice - > connectDevice ( ) ; //подключаемся!!!
isConnected = true ;
readCoils ( atr . adress , 5001 , 11 ) ;
2023-12-12 16:51:50 +03:00
readCoils ( atr . adress , 7004 , 2 ) ;
2023-11-24 14:08:11 +03:00
}
void ModBusHandler : : onReadReady ( )
{
auto reply = qobject_cast < QModbusReply * > ( sender ( ) ) ;
if ( nullptr = = reply )
{
return ;
}
// определить, есть ли ошибка
if ( reply - > error ( ) = = QModbusDevice : : NoError )
{
// Читать данные ответа
//qDebug() << "адрес ответа"<<reply->serverAddress();
const QModbusDataUnit responseData = reply - > result ( ) ;
// qDebug() << responseData.values(); //отсюда летит ответ
dataCollector ( reply - > serverAddress ( ) , responseData . values ( ) ) ;
}
else if ( reply - > error ( ) = = QModbusDevice : : ProtocolError )
{
qDebug ( ) < < " Read response Protocol error: " < < reply - > errorString ( ) ;
}
else
{
qDebug ( ) < < " Read response Error: " < < reply - > errorString ( ) ;
}
isWaitingResponse = false ;
reply - > deleteLater ( ) ;
}
void ModBusHandler : : readCoils ( uint16_t adress , uint16_t startCoil , uint16_t numCoil )
{
if ( isWaitingResponse ) {
}
QModbusDataUnit data ( QModbusDataUnit : : HoldingRegisters , startCoil , numCoil ) ;
QModbusReply * reply = modbusDevice - > sendReadRequest ( data , adress ) ; //указатель куда складывать// адрес клиента
if ( nullptr = = reply )
{
qDebug ( ) < < " Отправка данных запроса не удалась: " < < modbusDevice - > errorString ( ) ;
}
else
{
if ( ! reply - > isFinished ( ) ) //если сразу не получилось
{ // то создадим коннект
if ( isWaitingResponse ) {
}
isWaitingResponse = 1 ;
connect ( reply , & QModbusReply : : finished , this , & ModBusHandler : : onReadReady ) ;
}
else
{
if ( reply - > error ( ) = = QModbusDevice : : NoError ) //если без ошибок
{
// Читать данные ответа
qDebug ( ) < < " адрес ответа " < < reply - > serverAddress ( ) ;
const QModbusDataUnit responseData = reply - > result ( ) ;
dataCollector ( reply - > serverAddress ( ) , responseData . values ( ) ) ;
qDebug ( ) < < responseData . values ( ) ;
}
else if ( reply - > error ( ) = = QModbusDevice : : ProtocolError )
{
qDebug ( ) < < " Read response Protocol error: " < < reply - > errorString ( ) ;
}
else
{
qDebug ( ) < < " Read response Error: " < < reply - > errorString ( ) ;
}
//Парсим ответ по структуре или пока выведем в дебаг
isWaitingResponse = false ;
delete reply ;
}
}
}
void ModBusHandler : : dataCollector ( quint16 adress , QVector < quint16 > recivedData )
{
static bool sensIsRecived ;
static bool stateIsRecived ;
static DataStruct data ;
data . adress = adress ;
if ( recivedData . size ( ) = = 2 ) {
usfloat result ;
result . sh [ 0 ] = recivedData [ 1 ] ;
result . sh [ 1 ] = recivedData [ 0 ] ;
data . sens = result . fl ;
sensIsRecived = 1 ;
} ;
if ( recivedData . size ( ) = = 11 ) {
data . in = ( typeIIN ) recivedData [ 0 ] ;
data . fv = ( typeIFV ) recivedData [ 1 ] ;
data . fn = ( typeIFN ) recivedData [ 2 ] ;
data . ku = ( typeIKU ) recivedData [ 3 ] ;
data . unit = ( typeUnit ) recivedData [ 9 ] ;
data . overload = ( typeOverload ) recivedData [ 10 ] ;
data . pz = ( typePlavGround ) recivedData [ 7 ] ;
stateIsRecived = 1 ;
} ;
2023-12-07 16:57:51 +03:00
if ( sensIsRecived & & stateIsRecived ) {
2023-11-24 14:08:11 +03:00
//connect(this,SIGNAL(dataRecivedNotify(DataStruct)),parent(),SLOT(dataSetter(DataStruct)));
emit dataRecivedNotify ( data ) ;
// qDebug()<<"Должен проити эмит";
2023-12-07 16:57:51 +03:00
sensIsRecived = 0 ;
2023-11-24 14:08:11 +03:00
stateIsRecived = 0 ;
}
}
// Входные параметры: startAddress - адрес первого элемента, count - количество элементов (1 или более).
QModbusDataUnit ModBusHandler : : writeRequest ( int startAddress , int count ) const {
return QModbusDataUnit ( QModbusDataUnit : : HoldingRegisters , startAddress , count ) ;
}
// Входные параметры: startAddress - адрес первого элемента, count - количество элементов (1 или более).
void ModBusHandler : : prepareWrite ( uint16_t adress , int startAddress , int count , QVector < uint16_t > values ) {
if ( ! modbusDevice ) return ;
QModbusDataUnit writeUnit = writeRequest ( startAddress , count ) ;
writeUnit . setValues ( values ) ;
if ( auto * lastRequest = modbusDevice - > sendWriteRequest ( writeUnit , adress ) ) {
if ( ! lastRequest - > isFinished ( ) ) {
connect ( lastRequest , & QModbusReply : : finished , this , [ this , lastRequest ] ( ) {
if ( lastRequest - > error ( ) = = QModbusDevice : : ProtocolError ) {
qDebug ( ) < < " ошибка протокола " ;
} else if ( lastRequest - > error ( ) = = QModbusDevice : : TimeoutError ) {
qDebug ( ) < < " таймаут " ;
} else if ( lastRequest - > error ( ) ! = QModbusDevice : : NoError ) {
2023-12-07 16:57:51 +03:00
qDebug ( ) < < " Какая то ошибка " ;
qDebug ( ) < < lastRequest - > rawResult ( ) ;
2023-11-24 14:08:11 +03:00
} else if ( lastRequest - > error ( ) = = QModbusDevice : : NoError ) {
qDebug ( ) < < " успех) " ;
}
emit writeResult ( lastRequest - > error ( ) ) ; // сигналим о завершении операции
lastRequest - > deleteLater ( ) ;
qDebug ( ) < < " первый deleteLater " ;
} ) ;
} else {
lastRequest - > deleteLater ( ) ;
qDebug ( ) < < " второй deleteLater " ;
}
} else {
qDebug ( ) < < " Ошибка записи: " + modbusDevice - > errorString ( ) ;
}
}
2023-12-07 16:57:51 +03:00
2023-11-24 14:08:11 +03:00
void ModBusHandler : : scanAdressSignalChain ( uint16_t adrToScan )
{
if ( adrToScan < = 247 ) { // делаем запрос
{
isConnected = true ;
QModbusDataUnit data ( QModbusDataUnit : : HoldingRegisters , 5001 , 11 ) ; // формируем пакет на отправку
QModbusReply * reply = modbusDevice - > sendReadRequest ( data , adrToScan ) ;
if ( nullptr = = reply )
{
qDebug ( ) < < " Отправка данных запроса не удалась: " ;
}
else
{
if ( ! reply - > isFinished ( ) ) //
{
connect ( reply , & QModbusReply : : finished , this , & ModBusHandler : : ScanPortOnReadReady ) ;
}
}
}
}
else {
scanPort ( ) ; //переделать на сигнал иначе стэк может охуеть с такого фокуса
}
}
2023-12-07 16:57:51 +03:00
2023-11-24 14:08:11 +03:00
void ModBusHandler : : scanPort ( QString port ) {
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialPortNameParameter , QVariant ( port ) ) ;
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialStopBitsParameter , QSerialPort : : OneStop ) ;
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialDataBitsParameter , QSerialPort : : Data8 ) ;
2023-12-07 16:57:51 +03:00
2023-11-24 14:08:11 +03:00
modbusDevice - > setNumberOfRetries ( 0 ) ; // попытки достучатся
scanPort ( ) ;
}
2023-12-07 16:57:51 +03:00
2023-11-24 14:08:11 +03:00
void ModBusHandler : : scanPort ( ) //принимает сигнал о завершенных адресах
{
// static uint s;//статик скорость // перенес в глобальные
// static uint b;//статик бит // перенес в глобальные
if ( isScanning = = 0 ) { s = 0 ; b = 0 ; isScanning = 1 ; } //если новое новое сканирование обнуляем переменные
qDebug ( ) < < " Скорость " < < BAUDRATE [ s ] ;
qDebug ( ) < < " Бит " < < b ;
if ( b > = 3 ) { //если инкрементится некуда
emit priborNotFounded ( ) ;
s = 0 ;
b = 0 ;
isScanning = 0 ;
return ; }
modbusDevice - > disconnectDevice ( ) ; //отключавемся
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialBaudRateParameter , BAUDRATE [ s ] ) ;
2023-12-07 16:57:51 +03:00
switch ( BAUDRATE [ s ] ) { //выставляем парити
case 4800 :
2023-12-12 16:51:50 +03:00
modbusDevice - > setTimeout ( 120 ) ; //1 таймаута
2023-12-07 16:57:51 +03:00
break ;
case 7200 :
modbusDevice - > setTimeout ( 90 ) ; //1 таймаута
break ;
case 9600 :
modbusDevice - > setTimeout ( 80 ) ; //1 таймаута
break ;
case 14400 :
modbusDevice - > setTimeout ( 70 ) ; //1 таймаута
break ;
case 19200 :
modbusDevice - > setTimeout ( 60 ) ; //1 таймаута
break ;
case 38400 :
modbusDevice - > setTimeout ( 50 ) ; //1 таймаута
break ;
case 57600 :
modbusDevice - > setTimeout ( 40 ) ; //1 таймаута
break ;
case 115200 :
modbusDevice - > setTimeout ( 30 ) ; //1 таймаута
break ;
case 128000 :
modbusDevice - > setTimeout ( 30 ) ; //1 таймаута
break ;
default :
qDebug ( ) < < " пролет свитча с таймаутом " ;
break ;
}
2023-11-24 14:08:11 +03:00
switch ( b ) { //выставляем парити
case UART_PARITY_NONE :
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialParityParameter , QSerialPort : : NoParity ) ;
break ;
case UART_PARITY_ODD :
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialParityParameter , QSerialPort : : OddParity ) ;
break ;
case UART_PARITY_EVEN :
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialParityParameter , QSerialPort : : EvenParity ) ;
break ;
}
modbusDevice - > connectDevice ( ) ; //подключаемся
//фор меняем на отдельную функцию-слот работающую по сигналам
//меняем на отдельную функцию вопрошающиую всех по сигналам.
// если вернулся сигнал с о значением 247 она вызывает снова сканпорт
scanAdressSignalChain ( 1 ) ;
//инкрементим скорость и/или бит
if ( s < 9 ) s + + ; //если s меньше крайнего значения индекса массива скоростей
else { s = 0 ; b + + ; }
} //конец функции сканпорт
void ModBusHandler : : ScanPortOnReadReady ( )
{
auto reply = qobject_cast < QModbusReply * > ( sender ( ) ) ;
if ( nullptr = = reply )
{
return ;
}
// определить, есть ли ошибка
if ( reply - > error ( ) = = QModbusDevice : : NoError )
{
//когда нашел прибор
const QModbusDataUnit responseData = reply - > result ( ) ;
qDebug ( ) < < reply - > serverAddress ( ) < < " прибор грит " < < responseData . values ( ) ; //отсюда летит ответ
disconnect ( this , SIGNAL ( scanPlease ( uint16_t ) ) , this , SLOT ( scanAdressSignalChain ( uint16_t ) ) ) ; //рвем коннект цепочки ответ-запрос на всякий
isScanning = 0 ;
emit priborFounded ( reply - > serverAddress ( ) , s , b ) ; // передаем сигнал с настройками прибора в окно
modbusDevice - > disconnectDevice ( ) ;
//не забудь закрыть соединение
}
else {
//Когда не нашел прибор но пытаешься еще
connect ( this , SIGNAL ( scanPlease ( uint16_t ) ) , SLOT ( scanAdressSignalChain ( uint16_t ) ) ) ;
emit scanPlease ( ( reply - > serverAddress ( ) + 1 ) ) ; //
emit progressUpToStatusBar ( 1 ) ;
disconnect ( this , SIGNAL ( scanPlease ( uint16_t ) ) , this , SLOT ( scanAdressSignalChain ( uint16_t ) ) ) ;
}
reply - > deleteLater ( ) ;
}
void ModBusHandler : : writeConnectionAttr ( PrborConnectonAtr oldAtr , PrborConnectonAtr newAtr ) {
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialPortNameParameter , QVariant ( oldAtr . port ) ) ;
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialStopBitsParameter , QSerialPort : : OneStop ) ;
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialDataBitsParameter , QSerialPort : : Data8 ) ;
modbusDevice - > setTimeout ( 100 ) ; //1 таймаута
modbusDevice - > setNumberOfRetries ( 1 ) ; // попытки достучатся
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialBaudRateParameter , oldAtr . speed ) ;
switch ( oldAtr . parity ) { //выставляем парити
case UART_PARITY_NONE :
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialParityParameter , QSerialPort : : NoParity ) ;
break ;
case UART_PARITY_ODD :
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialParityParameter , QSerialPort : : OddParity ) ;
break ;
case UART_PARITY_EVEN :
modbusDevice - > setConnectionParameter ( QModbusDevice : : SerialParityParameter , QSerialPort : : EvenParity ) ;
break ;
}
modbusDevice - > connectDevice ( ) ; //подключаемся!!!
QVector < uint16_t > dataValues ( 3 ) ;
dataValues = {
dataValues [ 0 ] = newAtr . adress ,
dataValues [ 2 ] = newAtr . parity ,
} ;
for ( int i = 0 ; i < 10 ; i + + ) { //todo: выкинуть палки-шишки - скорость в структуре как значениеб а передавать нужно индекс массива. Будь умничкой и сделай всё хорошо.
if ( BAUDRATE [ i ] = = newAtr . speed ) dataValues [ 1 ] = i ; //dataValues[один]
} ;
prepareWrite ( oldAtr . adress , 4001 , 3 , dataValues ) ;
}
2023-12-07 16:57:51 +03:00
void ModBusHandler : : writeDataToPribor ( DataStruct datastruct , typeReq type )
2023-11-24 14:08:11 +03:00
{
2023-12-07 16:57:51 +03:00
if ( type = = SENS_REQ_TYPE ) {
2023-11-24 14:08:11 +03:00
usfloat floated ;
floated . fl = datastruct . sens ;
QVector < uint16_t > floatedQVector ( 2 ) ;
floatedQVector [ 0 ] = floated . sh [ 1 ] ;
floatedQVector [ 1 ] = floated . sh [ 0 ] ;
prepareWrite ( datastruct . adress , 7004 , 2 , floatedQVector ) ; //7004*
2023-12-07 16:57:51 +03:00
}
2023-11-24 14:08:11 +03:00
2023-12-07 16:57:51 +03:00
if ( type = = STATE_REQ_TYPE ) {
QVector < uint16_t > dataValues ( 10 ) ;
2023-11-24 14:08:11 +03:00
dataValues = {
dataValues [ 0 ] = datastruct . in ,
dataValues [ 1 ] = datastruct . fv ,
dataValues [ 2 ] = datastruct . fn ,
dataValues [ 3 ] = datastruct . ku ,
dataValues [ 4 ] = 0 ,
dataValues [ 5 ] = 0 ,
dataValues [ 6 ] = 0 ,
dataValues [ 7 ] = datastruct . pz ,
dataValues [ 8 ] = 0 ,
dataValues [ 9 ] = datastruct . unit ,
// dataValues[10]=datastruct.overload,
2023-12-07 16:57:51 +03:00
} ;
2023-11-24 14:08:11 +03:00
prepareWrite ( datastruct . adress , 5001 , 10 , dataValues ) ;
2023-12-07 16:57:51 +03:00
}
2023-11-24 14:08:11 +03:00
}