first commit, correct read, correct config ini
This commit is contained in:
20
Src/main.cpp
Normal file
20
Src/main.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
#include <QStyleFactory>
|
||||
#include <QDebug>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication give_me_a_name(argc, argv);
|
||||
//app->setStyle(QStyleFactory::create("Fusion"));
|
||||
//app->setStyle(QStyleFactory::create("windowsvista"));
|
||||
QApplication::setStyle("windowsvista");
|
||||
//app->setStyle(QStyleFactory::create("Windows"));
|
||||
//app->setStyle(QStyleFactory::create("Plastique"));
|
||||
|
||||
qDebug() << QApplication::style();
|
||||
|
||||
auto *window = new Mainwindows();
|
||||
window->show();
|
||||
//window->init();
|
||||
QApplication::exec();
|
||||
}
|
||||
276
Src/mainwindow.cpp
Normal file
276
Src/mainwindow.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
#include <QTableWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QTextCodec>
|
||||
#include <QVBoxLayout>
|
||||
#include <QThread>
|
||||
#include <QPainter>
|
||||
#include <QSettings>
|
||||
#include "mainwindow.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QModbusTcpClient>
|
||||
#include <QModbusDataUnit>
|
||||
#include <QUrl>
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
|
||||
ColoredSquare::ColoredSquare(QWidget *parent) : QWidget(parent), m_color(Qt::gray) {
|
||||
}
|
||||
|
||||
void ColoredSquare::setColor(const QColor& color) {
|
||||
m_color = color;
|
||||
update();
|
||||
}
|
||||
|
||||
void ColoredSquare::paintEvent(QPaintEvent *) {
|
||||
QPainter painter(this);
|
||||
painter.fillRect(rect(), m_color);
|
||||
}
|
||||
|
||||
Mainwindows::Mainwindows(QWidget *parent)
|
||||
: QWidget(parent), m_modbusClient(nullptr), m_connected(false) {
|
||||
|
||||
loadConfiguration();
|
||||
createUIElements();
|
||||
initModbusConnection();
|
||||
}
|
||||
|
||||
void Mainwindows::loadConfiguration() {
|
||||
const QString filePath = QCoreApplication::applicationDirPath() + "/config.ini";
|
||||
QSettings settings(filePath, QSettings::IniFormat);
|
||||
|
||||
settings.beginGroup("Connection");
|
||||
m_ipAddress = settings.value("ip", "127.0.0.1").toString();
|
||||
m_port = settings.value("port", 502).toInt();
|
||||
m_responseTimeout = settings.value("responseTimeout", 1000).toInt();
|
||||
m_connectTimeout = settings.value("connectTimeout", 3000).toInt();
|
||||
m_pollInterval = settings.value("timeBetweenPolls", 100).toInt();
|
||||
settings.endGroup();
|
||||
|
||||
qDebug() << "ip: " << m_ipAddress << "port: " << m_port;
|
||||
qDebug() << "responseTimeout: " << m_responseTimeout;
|
||||
qDebug() << "connectTimeout: " << m_connectTimeout;
|
||||
qDebug() << "poolInterval: " << m_pollInterval;
|
||||
|
||||
// Read registers configuration
|
||||
settings.beginGroup("Registers");
|
||||
m_buttonCount = settings.value("buttonCount", 0).toInt();
|
||||
m_indicatorCount = settings.value("indicatorCount", 0).toInt();
|
||||
|
||||
m_buttonRegisters.clear();
|
||||
m_indicatorRegisters.clear();
|
||||
|
||||
// Load button registers
|
||||
for(int i = 1; i <= m_buttonCount; ++i) {
|
||||
QString buttonKey = QString("button_reg%1").arg(i);
|
||||
int buttonReg = settings.value(buttonKey, 0).toInt();
|
||||
if(buttonReg > 0) {
|
||||
m_buttonRegisters.append(buttonReg);
|
||||
}
|
||||
}
|
||||
|
||||
// Load indicator registers
|
||||
for(int i = 1; i <= m_indicatorCount; ++i) {
|
||||
QString indicatorKey = QString("indicator_reg%1").arg(i);
|
||||
int indicatorReg = settings.value(indicatorKey, 0).toInt();
|
||||
if(indicatorReg > 0) {
|
||||
m_indicatorRegisters.append(indicatorReg);
|
||||
}
|
||||
}
|
||||
settings.endGroup();
|
||||
|
||||
qDebug() << "Loaded" << m_buttonCount << "buttons and" << m_indicatorCount << "indicators";
|
||||
qDebug() << "Button registers:" << m_buttonRegisters;
|
||||
qDebug() << "Indicator registers:" << m_indicatorRegisters;
|
||||
}
|
||||
|
||||
void Mainwindows::initModbusConnection() {
|
||||
m_modbusClient = new QModbusTcpClient(this);
|
||||
|
||||
// Set timeouts
|
||||
m_modbusClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, m_ipAddress);
|
||||
m_modbusClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, m_port);
|
||||
m_modbusClient->setTimeout(m_responseTimeout);
|
||||
m_modbusClient->setNumberOfRetries(1);
|
||||
|
||||
connect(m_modbusClient, &QModbusClient::stateChanged,
|
||||
this, &Mainwindows::onStateChanged);
|
||||
|
||||
// Initialize poll timer
|
||||
m_pollTimer = new QTimer(this);
|
||||
m_pollTimer->setInterval(m_pollInterval);
|
||||
connect(m_pollTimer, &QTimer::timeout, this, &Mainwindows::onPollTimer);
|
||||
}
|
||||
|
||||
void Mainwindows::onStateChanged(QModbusDevice::State state) {
|
||||
if (state == QModbusDevice::ConnectedState) {
|
||||
m_connected = true;
|
||||
m_connectButton->setText("Disconnect");
|
||||
readRegisters();
|
||||
m_pollTimer->start(); // Start polling when connected
|
||||
} else if (state == QModbusDevice::UnconnectedState) {
|
||||
m_connected = false;
|
||||
m_connectButton->setText("Connect");
|
||||
m_pollTimer->stop(); // Stop polling when disconnected
|
||||
}
|
||||
}
|
||||
|
||||
void Mainwindows::onConnectButtonClicked() {
|
||||
if (!m_connected) {
|
||||
if (!m_modbusClient->connectDevice()) {
|
||||
QMessageBox::critical(this, tr("Connection Error"),
|
||||
tr("Could not connect to the Modbus device!"));
|
||||
}
|
||||
// Start connection timeout timer
|
||||
QTimer::singleShot(m_connectTimeout, this, [this]() {
|
||||
if (!m_connected) {
|
||||
m_modbusClient->disconnectDevice();
|
||||
QMessageBox::warning(this, tr("Connection Timeout"),
|
||||
tr("Connection attempt timed out!"));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
m_modbusClient->disconnectDevice();
|
||||
}
|
||||
}
|
||||
|
||||
void Mainwindows::onPollTimer() {
|
||||
if (m_connected) {
|
||||
readRegisters();
|
||||
}
|
||||
}
|
||||
|
||||
void Mainwindows::writeRegister(int index) {
|
||||
if (!m_connected) return;
|
||||
|
||||
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, m_buttonRegisters[index], 1);
|
||||
|
||||
if (auto *reply = m_modbusClient->sendWriteRequest(writeUnit, 1)) {
|
||||
if (!reply->isFinished())
|
||||
connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);
|
||||
else
|
||||
delete reply;
|
||||
}
|
||||
}
|
||||
|
||||
void Mainwindows::readRegisters() {
|
||||
if (!m_connected) return;
|
||||
|
||||
// Read indicator registers
|
||||
for (int i = 0; i < m_indicatorCount; ++i) {
|
||||
if (i < m_indicatorRegisters.size()) {
|
||||
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, m_indicatorRegisters[i], 1);
|
||||
if (auto *reply = m_modbusClient->sendReadRequest(readUnit, 1)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, this, &Mainwindows::onReadReady);
|
||||
} else {
|
||||
delete reply;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read button registers
|
||||
for (int i = 0; i < m_buttonCount; ++i) {
|
||||
if (i < m_buttonRegisters.size()) {
|
||||
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, m_buttonRegisters[i], 1);
|
||||
if (auto *reply = m_modbusClient->sendReadRequest(readUnit, 1)) {
|
||||
if (!reply->isFinished()) {
|
||||
connect(reply, &QModbusReply::finished, this, &Mainwindows::onReadReady);
|
||||
} else {
|
||||
delete reply;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mainwindows::onReadReady() {
|
||||
auto reply = qobject_cast<QModbusReply *>(sender());
|
||||
if (!reply) return;
|
||||
|
||||
if (reply->error() == QModbusDevice::NoError) {
|
||||
const QModbusDataUnit unit = reply->result();
|
||||
int address = unit.startAddress();
|
||||
int value = unit.value(0);
|
||||
|
||||
// Handle indicators
|
||||
for (int i = 0; i < m_indicatorRegisters.size(); ++i) {
|
||||
if (address == m_indicatorRegisters[i]) {
|
||||
static const QColor colors[] = {Qt::gray, Qt::black, Qt::green};
|
||||
m_colorIndices[i] = value % 3;
|
||||
m_squares[i]->setColor(colors[m_colorIndices[i]]);
|
||||
qDebug() << "Indicator" << i << "address:" << address << "value:" << value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle buttons
|
||||
for (int i = 0; i < m_buttonRegisters.size(); ++i) {
|
||||
if (address == m_buttonRegisters[i]) {
|
||||
QStringList bName = {"Открыть", "Закрыть"};
|
||||
m_buttons[i]->setText(bName[value & 1]);
|
||||
qDebug() << "Button" << i << "address:" << address << "value:" << value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void Mainwindows::createUIElements() {
|
||||
auto* mainLayout = new QVBoxLayout(this);
|
||||
|
||||
// Add connect button at the top
|
||||
m_connectButton = new QPushButton("Connect", this);
|
||||
connect(m_connectButton, &QPushButton::clicked, this, &Mainwindows::onConnectButtonClicked);
|
||||
mainLayout->addWidget(m_connectButton);
|
||||
|
||||
// Create table with maximum of buttons or indicators
|
||||
int rowCount = qMax(m_buttonCount, m_indicatorCount);
|
||||
m_table = new QTableWidget(rowCount, 2, this);
|
||||
|
||||
// Setup table properties
|
||||
m_table->verticalHeader()->setVisible(false);
|
||||
m_table->horizontalHeader()->setVisible(false);
|
||||
m_table->setShowGrid(false);
|
||||
m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
m_table->setSelectionMode(QAbstractItemView::NoSelection);
|
||||
|
||||
// Create UI elements
|
||||
for(int i = 0; i < rowCount; ++i) {
|
||||
if (i < m_buttonCount) {
|
||||
auto* button = new QPushButton(QString("Register %1").arg(m_buttonRegisters[i]), this);
|
||||
m_buttons.append(button);
|
||||
m_table->setCellWidget(i, 0, button);
|
||||
connect(button, &QPushButton::clicked, [this, i]() {
|
||||
writeRegister(i);
|
||||
});
|
||||
}
|
||||
|
||||
if (i < m_indicatorCount) {
|
||||
auto* square = new ColoredSquare(this);
|
||||
square->setFixedSize(m_table->rowHeight(i), m_table->rowHeight(i));
|
||||
m_squares.append(square);
|
||||
m_colorIndices.append(0);
|
||||
m_table->setCellWidget(i, 1, square);
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust column sizes
|
||||
m_table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||
m_table->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed);
|
||||
m_table->setColumnWidth(0, 100);
|
||||
m_table->setColumnWidth(1, 100);
|
||||
|
||||
mainLayout->addWidget(m_table);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
Mainwindows::~Mainwindows() {
|
||||
if (m_pollTimer) {
|
||||
m_pollTimer->stop();
|
||||
}
|
||||
if (m_modbusClient && m_modbusClient->state() != QModbusDevice::UnconnectedState) {
|
||||
m_modbusClient->disconnectDevice();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user