#include "modbushandler.h" #define REQ_PERIOD 50 //прериод опроса ModBusHandler::ModBusHandler(QObject *parent) : QObject(parent) { modbusDevice = new QModbusRtuSerialMaster; //заводим таймер 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() //слот для истекшего таймера { //пробегаемся по листу и опрашиваем выкидываая сигналы static uint numForReqest; qDebug()<<"Приборов в списке "<setConnectionParameter(QModbusDevice::SerialPortNameParameter, QVariant(atr.port)); modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop); modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8); modbusDevice->setTimeout(100); //1 таймаута modbusDevice->setNumberOfRetries(1);// попытки достучатся 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); readCoils(atr.adress, 7004, 2); } void ModBusHandler::onReadReady() { auto reply = qobject_cast(sender()); if (nullptr == reply) { return; } // определить, есть ли ошибка if (reply->error() == QModbusDevice::NoError) { // Читать данные ответа //qDebug() << "адрес ответа"<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() << "адрес ответа"<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, QVectorrecivedData) { 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; }; if(stateIsRecived&&stateIsRecived){ //connect(this,SIGNAL(dataRecivedNotify(DataStruct)),parent(),SLOT(dataSetter(DataStruct))); emit dataRecivedNotify(data); // qDebug()<<"Должен проити эмит"; stateIsRecived=0; 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 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) { qDebug() << "уууууууу"; } else if(lastRequest->error() == QModbusDevice::NoError) { qDebug() << "успех)"; } emit writeResult(lastRequest->error()); // сигналим о завершении операции lastRequest->deleteLater(); qDebug() << "первый deleteLater"; }); } else { lastRequest->deleteLater(); qDebug() << "второй deleteLater"; } } else { qDebug()<<"Ошибка записи: " + modbusDevice->errorString(); } } 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();//переделать на сигнал иначе стэк может охуеть с такого фокуса } } void ModBusHandler::scanPort(QString port){ modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, QVariant(port)); modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop); modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8); modbusDevice->setTimeout(30); //1 таймаута modbusDevice->setNumberOfRetries(0);// попытки достучатся scanPort(); } void ModBusHandler::scanPort() //принимает сигнал о завершенных адресах { // static uint s;//статик скорость // перенес в глобальные // static uint b;//статик бит // перенес в глобальные if(isScanning==0){s=0; b=0; isScanning=1;}//если новое новое сканирование обнуляем переменные qDebug()<<"Скорость"<=3){ //если инкрементится некуда emit priborNotFounded(); s=0; b=0; isScanning=0; return;} modbusDevice->disconnectDevice();//отключавемся modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, BAUDRATE[s]); 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(sender()); if (nullptr == reply) { return; } // определить, есть ли ошибка if (reply->error() == QModbusDevice::NoError) { //когда нашел прибор const QModbusDataUnit responseData = reply->result(); qDebug() <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 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); } void ModBusHandler::writeDataToPribor(DataStruct datastruct) { usfloat floated; floated.fl = datastruct.sens; QVector floatedQVector(2); floatedQVector[0]=floated.sh[1]; floatedQVector[1]=floated.sh[0]; prepareWrite(datastruct.adress, 7004, 2, floatedQVector);//7004* QVector dataValues(10); 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, }; prepareWrite(datastruct.adress, 5001, 10, dataValues); }