#include "lineringer.h" #include "ui_lineringer.h" QWidget* init(QWidget *parent) { return new LineRinger(parent); } LineRinger::LineRinger(QWidget *parent) : QWidget(parent), ui(new Ui::LineRinger) { ui->setupUi(this); father = parent; const auto listPorts = QSerialPortInfo::availablePorts(); for (const auto& port: listPorts) { ui->comBox->addItem(QString(port.portName() + ": " + port.manufacturer()), QVariant(port.portName())); } ui->parityControlBox->addItem("No", QVariant(QSerialPort::NoParity)); ui->parityControlBox->addItem("Even", QVariant(QSerialPort::EvenParity)); ui->parityControlBox->addItem("Odd", QVariant(QSerialPort::OddParity)); ui->parityControlBox->addItem("Space", QVariant(QSerialPort::SpaceParity)); ui->parityControlBox->addItem("Mark", QVariant(QSerialPort::MarkParity)); ui->dataBox->addItem("Data5", QVariant(QSerialPort::Data5)); ui->dataBox->addItem("Data6", QVariant(QSerialPort::Data6)); ui->dataBox->addItem("Data7", QVariant(QSerialPort::Data7)); ui->dataBox->addItem("Data8", QVariant(QSerialPort::Data8)); ui->dataBox->setCurrentIndex(3); ui->stopBox->addItem("One", QVariant(QSerialPort::OneStop)); ui->stopBox->addItem("OneAndHalf", QVariant(QSerialPort::OneAndHalfStop)); ui->stopBox->addItem("Two", QVariant(QSerialPort::TwoStop)); ui->deviceOnlineView->horizontalHeader()->setVisible(true); syncColumnHeaders(); ui->deviceOnlineView->setColumnHidden(1, true); ui->ringButton->setEnabled(false); modbusDevice = new QModbusRtuSerialMaster(this); } LineRinger::~LineRinger() { if (modbusDevice->state() == QModbusDevice::ConnectedState) on_connectButton_clicked(); delete ui; } void LineRinger::syncColumnHeaders() { QStringList headers; headers << "ID" << "BaudRate" << "Vendor Name" << "Product Code" << "Major Minor Revision" << "Vendor Url" << "Product Name" << "Model Name" << "User Application Name" << "Примечание"; ui->deviceOnlineView->setHorizontalHeaderLabels(headers); ui->deviceOnlineView->resizeColumnsToContents(); } void LineRinger::on_connectButton_clicked() { if (!modbusDevice) return; if (modbusDevice->state() != QModbusDevice::ConnectedState) { modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, ui->comBox->currentData().toString()); #if QT_CONFIG(modbus_serialport) modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, ui->parityControlBox->currentData().toInt()); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, ui->baudRateBox->currentText().toInt(nullptr, 10)); modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, ui->dataBox->currentData().toInt()); modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, ui->stopBox->currentData().toInt()); #endif modbusDevice->setTimeout(50); modbusDevice->setNumberOfRetries(0); if (!modbusDevice->connectDevice()) { QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения."); } else { ui->connectButton->setText(tr("Отключить")); ui->ringButton->setEnabled(true); currentBaudRate = ui->baudRateBox->currentText().toUInt(nullptr, 10); } } else { modbusDevice->disconnectDevice(); ui->connectButton->setText(tr("Подключить")); ui->ringButton->setEnabled(false); } } LineRinger::callStatus LineRinger::lineCall() { QModbusRequest readDeviceBasicIdentification(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0100")); QModbusRequest readDeviceRegularIdentification(QModbusRequest::EncapsulatedInterfaceTransport, QByteArray::fromHex("0E0200")); bool isRun = false; bool *tmp_isRun = &isRun; uint tmp_adr = 1; auto bar = new QProgressDialog(this); connect(bar, &QProgressDialog::canceled, this, [this, tmp_isRun]() { *tmp_isRun = true; }); connect(this, &LineRinger::stopLineCall, this, [this, tmp_isRun]() { *tmp_isRun = true; }); bar->setLabelText(tr("Поиск устройств... Текущий адрес: %1").arg(tmp_adr)); bar->setCancelButton(nullptr); bar->setRange(1, 247); bar->setMinimumDuration(100); for(tmp_adr = 1; tmp_adr<248; tmp_adr++) { bar->setValue(tmp_adr); bar->setLabelText(tr("Поиск устройств... Текущий адрес: %1/247").arg(tmp_adr)); auto *reply = modbusDevice->sendRawRequest(readDeviceBasicIdentification, tmp_adr); //auto *reply = modbusDevice->sendReadRequest(*_unit, tmp_adr); //Запрос типа устройства. if(reply == nullptr) { QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1").arg(modbusDevice->errorString())); bar->close(); bar->deleteLater(); return callStatus::ERROR; } while(!reply->isFinished()) { if(isRun) { bar->close(); bar->deleteLater(); return callStatus::INTERRUPT; } QCoreApplication::processEvents(); } if(isRun) { bar->close(); bar->deleteLater(); return callStatus::INTERRUPT; } else if (!isRun) { //Нужна проверка типа устройства if(reply->error()!=QModbusDevice::TimeoutError) { deviceOnLine currentDevice; currentDevice.adr = tmp_adr; currentDevice.baudRate = currentBaudRate; bool regularReplyError = false; QString regularReplyErrorString; if(reply->error()==QModbusDevice::NoError) { QModbusResponse resp = reply->rawResult(); uint8_t numOfObject = resp.data().at(5); QByteArray result = resp.data().remove(0, 6); for(int tmp_obj = 0; tmp_obj < numOfObject; tmp_obj++) { uint8_t objectID = result.at(0); uint8_t lengthOfObject = result.at(1); if(lengthOfObject>0) { currentDevice.fields[objectID].clear(); } for(int i = 0; i < lengthOfObject; i++) { currentDevice.fields[objectID] += QString(result.at(2+i)); } result.remove(0, lengthOfObject+2); } auto *regularReply = modbusDevice->sendRawRequest(readDeviceRegularIdentification, tmp_adr); if(regularReply == nullptr) { QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1: %2").arg(modbusDevice->error()).arg(modbusDevice->errorString())); bar->close(); bar->deleteLater(); return callStatus::ERROR; } while(!regularReply->isFinished()) { if(isRun) { bar->close(); bar->deleteLater(); return callStatus::INTERRUPT; } QCoreApplication::processEvents(); } if(isRun) { bar->close(); bar->deleteLater(); return callStatus::INTERRUPT; } else if(!isRun) { if(regularReply->error()!=QModbusDevice::NoError) { // QMessageBox::warning(this, "Ошибка при сканировании.", QString("%1: %2").arg(regularReply->error()).arg(regularReply->errorString())); // bar->close(); // bar->deleteLater(); // return callStatus::ERROR; regularReplyError = true; regularReplyErrorString = QString("%1: %2").arg(regularReply->error()).arg(regularReply->errorString()); } QModbusResponse regularResp = regularReply->rawResult(); uint8_t numOfRegularObject = regularResp.data().at(5); QByteArray regularResult = regularResp.data().remove(0, 6); for(int tmp_obj = 0; tmp_obj < numOfRegularObject; tmp_obj++) { uint8_t objectID = regularResult.at(0); if(objectID > 0x06) continue; uint8_t lengthOfObject = regularResult.at(1); if(lengthOfObject>0) { currentDevice.fields[objectID].clear(); } for (int i = 0; i < lengthOfObject; i++) { currentDevice.fields[objectID] += QString(regularResult.at(2+i)); } regularResult.remove(0, lengthOfObject+2); } } } if(!isRun) { devicesList.append(currentDevice); unsigned newRow = ui->deviceOnlineView->rowCount(); ui->deviceOnlineView->insertRow(newRow); ui->deviceOnlineView->setItem(newRow, 0, new QTableWidgetItem(QString::number(currentDevice.adr))); ui->deviceOnlineView->setItem(newRow, 1, new QTableWidgetItem(QString::number(currentDevice.baudRate))); for (int i = 0; i < 7; i++) { ui->deviceOnlineView->setItem(newRow, i+2, new QTableWidgetItem(currentDevice.fields[i])); } if(reply->error()!=QModbusDevice::NoError) { ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(QString("%1: %2").arg(reply->error()).arg(reply->errorString()))); } else if(regularReplyError) { ui->deviceOnlineView->setItem(newRow, 9, new QTableWidgetItem(regularReplyErrorString)); } ui->deviceOnlineView->resizeColumnsToContents(); syncColumnHeaders(); } } } } return callStatus::NOERROR; } void LineRinger::on_ringButton_clicked() { ui->deviceOnlineView->clear(); devicesList.clear(); syncColumnHeaders(); while(ui->deviceOnlineView->rowCount()!=0) ui->deviceOnlineView->removeRow(ui->deviceOnlineView->rowCount()-1); if(isAutoBaud) { auto bar = new QProgressDialog(this); bar->setLabelText(tr("Поиск устройств... Текущая скорость: %1").arg(currentBaudRate)); bar->setRange(0, ui->baudRateBox->count()); bar->setAutoClose(true); bar->setMinimumDuration(0); bar->setCancelButton(nullptr); connect(bar, &QProgressDialog::canceled, this, [this]() { emit stopLineCall(); }); bar->setValue(0); ui->deviceOnlineView->setColumnHidden(1, false); modbusDevice->disconnectDevice(); for (int i = 0; i < ui->baudRateBox->count(); i++) { bar->setValue(i+1); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, ui->baudRateBox->itemText(i).toInt(nullptr, 10)); if (!modbusDevice->connectDevice()) { QMessageBox::warning(this, "Ошибка", "Произошла ошибка при попытке подключения."); on_connectButton_clicked(); break; } currentBaudRate = ui->baudRateBox->itemText(i).toUInt(nullptr, 10); if(lineCall() == callStatus::INTERRUPT) { QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); modbusDevice->disconnectDevice(); on_connectButton_clicked(); bar->close(); bar->deleteLater(); ui->timer->setTime(QTime::currentTime()); ui->timer->setDate(QDate::currentDate()); return; } modbusDevice->disconnectDevice(); } on_connectButton_clicked(); } else { ui->deviceOnlineView->setColumnHidden(1, true); if(lineCall() == callStatus::INTERRUPT) { QMessageBox::warning(this, "Уведомление", QString("Досрочное завершение опроса. Найдено %1 устройств.").arg(devicesList.count())); truthSeaker* HeraldOfTrue = new truthSeaker(); QCoreApplication::postEvent(father, HeraldOfTrue); } } ui->timer->setTime(QTime::currentTime()); ui->timer->setDate(QDate::currentDate()); } void LineRinger::on_checkAutoBaud_stateChanged(int arg1) { isAutoBaud = (bool)arg1; }