A1210_Desktop/modbushandler.cpp

476 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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()<<"Приборов в списке "<<PriborMap.size();
for(PrborConnectonAtr atr:PriborMap){
getDataFromPribor(atr);
}
/////это всё тлен и плюсы
//делаем итератор где то наверху
//обновляем количество элементов
//проверяем, если элемент последний, то в начало
//если нет то ++
//делаем запрос. - он у нас раз в 300 мс, типа успеет отработать. Ну должен успеть
}
void ModBusHandler::addToReqList(PrborConnectonAtr pribor)
{
PriborMap.insert(pribor.adress, pribor);
}
void ModBusHandler::removeFromReqList(uint adress)
{
PriborMap.remove(adress);
}
void ModBusHandler::getDataFromPribor(PrborConnectonAtr atr) //слот для истекшего таймера
{
{
modbusDevice->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<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;
};
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<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) {
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()<<"Скорость"<<BAUDRATE[s];
qDebug()<<"Бит"<<b;
if(b>=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<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);
}
void ModBusHandler::writeDataToPribor(DataStruct datastruct)
{
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*
QVector <uint16_t> 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);
}