Add modbus RTU hardware resource support
This commit is contained in:
parent
ab65f1a484
commit
64d24d4e74
@ -130,6 +130,9 @@
|
|||||||
#include "applogcontroller.h"
|
#include "applogcontroller.h"
|
||||||
#include "tagwatcher.h"
|
#include "tagwatcher.h"
|
||||||
#include "appdata.h"
|
#include "appdata.h"
|
||||||
|
#include "modbus/modbusrtumanager.h"
|
||||||
|
#include "modbus/modbusrtumasters.h"
|
||||||
|
#include "types/serialportsproxy.h"
|
||||||
|
|
||||||
#include <QtQml/qqml.h>
|
#include <QtQml/qqml.h>
|
||||||
|
|
||||||
@ -312,6 +315,13 @@ void registerQmlTypes() {
|
|||||||
qmlRegisterUncreatableType<ZigbeeNetwork>(uri, 1, 0, "ZigbeeNetwork", "Get it from the ZigbeeManager");
|
qmlRegisterUncreatableType<ZigbeeNetwork>(uri, 1, 0, "ZigbeeNetwork", "Get it from the ZigbeeManager");
|
||||||
qmlRegisterUncreatableType<ZigbeeNetworks>(uri, 1, 0, "ZigbeeNetworks", "Get it from the ZigbeeManager");
|
qmlRegisterUncreatableType<ZigbeeNetworks>(uri, 1, 0, "ZigbeeNetworks", "Get it from the ZigbeeManager");
|
||||||
|
|
||||||
|
qmlRegisterType<ModbusRtuManager>(uri, 1, 0, "ModbusRtuManager");
|
||||||
|
qmlRegisterUncreatableType<ModbusRtuMaster>(uri, 1, 0, "ModbusRtuMaster", "Get it from the ModbusRtuMasters");
|
||||||
|
qmlRegisterUncreatableType<ModbusRtuMasters>(uri, 1, 0, "ModbusRtuMasters", "Get it from the ModbusRtuManager");
|
||||||
|
qmlRegisterUncreatableType<SerialPort>(uri, 1, 0, "SerialPort", "Get it from the SerialPorts");
|
||||||
|
qmlRegisterUncreatableType<SerialPorts>(uri, 1, 0, "SerialPorts", "Get it from the apropriate manager object.");
|
||||||
|
qmlRegisterType<SerialPortsProxy>(uri, 1, 0, "SerialPortsProxy");
|
||||||
|
|
||||||
qmlRegisterType<NetworkManager>(uri, 1, 0, "NetworkManager");
|
qmlRegisterType<NetworkManager>(uri, 1, 0, "NetworkManager");
|
||||||
qmlRegisterUncreatableType<NetworkDevices>(uri, 1, 0, "NetworkDevices", "Get it from NetworkManager");
|
qmlRegisterUncreatableType<NetworkDevices>(uri, 1, 0, "NetworkDevices", "Get it from NetworkManager");
|
||||||
qmlRegisterUncreatableType<WiredNetworkDevices>(uri, 1, 0, "WiredNetworkDevices", "Get it from NetworkManager");
|
qmlRegisterUncreatableType<WiredNetworkDevices>(uri, 1, 0, "WiredNetworkDevices", "Get it from NetworkManager");
|
||||||
|
|||||||
@ -26,6 +26,12 @@ SOURCES += \
|
|||||||
$${PWD}/logging.cpp \
|
$${PWD}/logging.cpp \
|
||||||
$${PWD}/applogcontroller.cpp \
|
$${PWD}/applogcontroller.cpp \
|
||||||
$${PWD}/wifisetup/btwifisetup.cpp \
|
$${PWD}/wifisetup/btwifisetup.cpp \
|
||||||
|
$$PWD/modbus/modbusrtumanager.cpp \
|
||||||
|
$$PWD/modbus/modbusrtumaster.cpp \
|
||||||
|
$$PWD/modbus/modbusrtumasters.cpp \
|
||||||
|
$$PWD/types/serialport.cpp \
|
||||||
|
$$PWD/types/serialports.cpp \
|
||||||
|
$$PWD/types/serialportsproxy.cpp \
|
||||||
$${PWD}/configuration/networkmanager.cpp \
|
$${PWD}/configuration/networkmanager.cpp \
|
||||||
$${PWD}/engine.cpp \
|
$${PWD}/engine.cpp \
|
||||||
$${PWD}/models/barseriesadapter.cpp \
|
$${PWD}/models/barseriesadapter.cpp \
|
||||||
@ -174,6 +180,12 @@ HEADERS += \
|
|||||||
$${PWD}/logging.h \
|
$${PWD}/logging.h \
|
||||||
$${PWD}/applogcontroller.h \
|
$${PWD}/applogcontroller.h \
|
||||||
$${PWD}/wifisetup/btwifisetup.h \
|
$${PWD}/wifisetup/btwifisetup.h \
|
||||||
|
$$PWD/modbus/modbusrtumanager.h \
|
||||||
|
$$PWD/modbus/modbusrtumaster.h \
|
||||||
|
$$PWD/modbus/modbusrtumasters.h \
|
||||||
|
$$PWD/types/serialport.h \
|
||||||
|
$$PWD/types/serialports.h \
|
||||||
|
$$PWD/types/serialportsproxy.h \
|
||||||
$${PWD}/configuration/networkmanager.h \
|
$${PWD}/configuration/networkmanager.h \
|
||||||
$${PWD}/engine.h \
|
$${PWD}/engine.h \
|
||||||
$${PWD}/models/barseriesadapter.h \
|
$${PWD}/models/barseriesadapter.h \
|
||||||
|
|||||||
251
libnymea-app/modbus/modbusrtumanager.cpp
Normal file
251
libnymea-app/modbus/modbusrtumanager.cpp
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "modbusrtumanager.h"
|
||||||
|
#include "engine.h"
|
||||||
|
#include "modbusrtumaster.h"
|
||||||
|
#include "modbusrtumasters.h"
|
||||||
|
|
||||||
|
#include "jsonrpc/jsonrpcclient.h"
|
||||||
|
|
||||||
|
#include <QMetaEnum>
|
||||||
|
|
||||||
|
ModbusRtuManager::ModbusRtuManager(QObject *parent) :
|
||||||
|
JsonHandler(parent),
|
||||||
|
m_serialPorts(new SerialPorts(this)),
|
||||||
|
m_modbusRtuMasters(new ModbusRtuMasters(this))
|
||||||
|
{
|
||||||
|
qRegisterMetaType<SerialPort::SerialPortParity>();
|
||||||
|
qRegisterMetaType<SerialPort::SerialPortDataBits>();
|
||||||
|
qRegisterMetaType<SerialPort::SerialPortStopBits>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuManager::~ModbusRtuManager()
|
||||||
|
{
|
||||||
|
if (m_engine) {
|
||||||
|
m_engine->jsonRpcClient()->unregisterNotificationHandler(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ModbusRtuManager::nameSpace() const
|
||||||
|
{
|
||||||
|
return "ModbusRtu";
|
||||||
|
}
|
||||||
|
|
||||||
|
Engine *ModbusRtuManager::engine() const
|
||||||
|
{
|
||||||
|
return m_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::setEngine(Engine *engine)
|
||||||
|
{
|
||||||
|
if (m_engine == engine)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_engine) {
|
||||||
|
m_engine->jsonRpcClient()->unregisterNotificationHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_engine = engine;
|
||||||
|
emit engineChanged();
|
||||||
|
|
||||||
|
if (m_engine) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuManager::supported() const
|
||||||
|
{
|
||||||
|
return m_supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPorts *ModbusRtuManager::serialPorts() const
|
||||||
|
{
|
||||||
|
return m_serialPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuMasters *ModbusRtuManager::modbusRtuMasters() const
|
||||||
|
{
|
||||||
|
return m_modbusRtuMasters;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModbusRtuManager::addModbusRtuMaster(const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits)
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("serialPort", serialPort);
|
||||||
|
params.insert("baudrate", baudrate);
|
||||||
|
params.insert("parity", QMetaEnum::fromType<SerialPort::SerialPortParity>().valueToKey(parity));
|
||||||
|
params.insert("dataBits", QMetaEnum::fromType<SerialPort::SerialPortDataBits>().valueToKey(dataBits));
|
||||||
|
params.insert("stopBits", QMetaEnum::fromType<SerialPort::SerialPortStopBits>().valueToKey(stopBits));
|
||||||
|
return m_engine->jsonRpcClient()->sendCommand("ModbusRtu.AddModbusRtuMaster", params, this, "addModbusRtuMasterResponse");
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModbusRtuManager::removeModbusRtuMaster(const QUuid &modbusUuid)
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("modbusUuid", modbusUuid);
|
||||||
|
return m_engine->jsonRpcClient()->sendCommand("ModbusRtu.RemoveModbusRtuMaster", params, this, "removeModbusRtuMasterResponse");
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModbusRtuManager::reconfigureModbusRtuMaster(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits)
|
||||||
|
{
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("modbusUuid", modbusUuid);
|
||||||
|
params.insert("serialPort", serialPort);
|
||||||
|
params.insert("baudrate", baudrate);
|
||||||
|
params.insert("parity", QMetaEnum::fromType<SerialPort::SerialPortParity>().valueToKey(parity));
|
||||||
|
params.insert("dataBits", QMetaEnum::fromType<SerialPort::SerialPortDataBits>().valueToKey(dataBits));
|
||||||
|
params.insert("stopBits", QMetaEnum::fromType<SerialPort::SerialPortStopBits>().valueToKey(stopBits));
|
||||||
|
return m_engine->jsonRpcClient()->sendCommand("ModbusRtu.ReconfigureModbusRtuMaster", params, this, "reconfigureModbusRtuMasterResponse");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::init()
|
||||||
|
{
|
||||||
|
m_serialPorts->clear();
|
||||||
|
m_modbusRtuMasters->clear();
|
||||||
|
|
||||||
|
m_engine->jsonRpcClient()->registerNotificationHandler(this, "notificationReceived");
|
||||||
|
m_engine->jsonRpcClient()->sendCommand("ModbusRtu.GetModbusRtuMasters", this, "getModbusRtuMastersResponse");
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuMaster *ModbusRtuManager::unpackModbusRtuMaster(const QVariantMap &modbusRtuMasterMap)
|
||||||
|
{
|
||||||
|
ModbusRtuMaster *modbusMaster = new ModbusRtuMaster(this);
|
||||||
|
modbusMaster->setModbusUuid(modbusRtuMasterMap.value("modbusUuid").toUuid());
|
||||||
|
modbusMaster->setConnected(modbusRtuMasterMap.value("connected").toBool());
|
||||||
|
modbusMaster->setSerialPort(modbusRtuMasterMap.value("serialPort").toString());
|
||||||
|
modbusMaster->setBaudrate(modbusRtuMasterMap.value("baudrate").toInt());
|
||||||
|
modbusMaster->setParity(SerialPort::stringToSerialPortParity(modbusRtuMasterMap.value("parity").toString()));
|
||||||
|
modbusMaster->setStopBits(SerialPort::stringToSerialPortStopBits(modbusRtuMasterMap.value("stopBits").toString()));
|
||||||
|
modbusMaster->setDataBits(SerialPort::stringToSerialPortDataBits(modbusRtuMasterMap.value("dataBits").toString()));
|
||||||
|
return modbusMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::notificationReceived(const QVariantMap ¬ification)
|
||||||
|
{
|
||||||
|
QString notificationString = notification.value("notification").toString();
|
||||||
|
qDebug() << "Received notification" << notificationString << endl << notification;
|
||||||
|
if (notificationString == "ModbusRtu.SerialPortAdded") {
|
||||||
|
QVariantMap serialPortMap = notification.value("params").toMap().value("serialPort").toMap();
|
||||||
|
m_serialPorts->addSerialPort(SerialPort::unpackSerialPort(serialPortMap, m_serialPorts));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationString == "ModbusRtu.SerialPortRemoved") {
|
||||||
|
QVariantMap serialPortMap = notification.value("params").toMap().value("serialPort").toMap();
|
||||||
|
SerialPort *serialPort = SerialPort::unpackSerialPort(serialPortMap, this);
|
||||||
|
m_serialPorts->removeSerialPort(serialPort->systemLocation());
|
||||||
|
serialPort->deleteLater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationString == "ModbusRtu.ModbusRtuMasterAdded") {
|
||||||
|
QVariantMap modbusRtuMasterMap = notification.value("params").toMap().value("modbusRtuMaster").toMap();
|
||||||
|
ModbusRtuMaster *modbusRtuMaster = unpackModbusRtuMaster(modbusRtuMasterMap);
|
||||||
|
m_modbusRtuMasters->addModbusRtuMaster(modbusRtuMaster);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationString == "ModbusRtu.ModbusRtuMasterRemoved") {
|
||||||
|
QUuid modbusUuid = notification.value("params").toMap().value("modbusUuid").toUuid();
|
||||||
|
m_modbusRtuMasters->removeModbusRtuMaster(modbusUuid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationString == "ModbusRtu.ModbusRtuMasterChanged") {
|
||||||
|
QVariantMap modbusRtuMasterMap = notification.value("params").toMap().value("modbusRtuMaster").toMap();
|
||||||
|
ModbusRtuMaster *modbusRtuMaster = unpackModbusRtuMaster(modbusRtuMasterMap);
|
||||||
|
qDebug() << "Modbus master changed" << modbusRtuMaster;
|
||||||
|
ModbusRtuMaster *currentModbusRtuMaster = m_modbusRtuMasters->getModbusRtuMaster(modbusRtuMaster->modbusUuid());
|
||||||
|
if (!currentModbusRtuMaster) {
|
||||||
|
qWarning() << "Got modbus changed signal but there is no such modbus interface. Ignoring notification";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Update modbus values" << currentModbusRtuMaster;
|
||||||
|
currentModbusRtuMaster->setSerialPort(modbusRtuMaster->serialPort());
|
||||||
|
currentModbusRtuMaster->setBaudrate(modbusRtuMaster->baudrate());
|
||||||
|
currentModbusRtuMaster->setParity(modbusRtuMaster->parity());
|
||||||
|
currentModbusRtuMaster->setDataBits(modbusRtuMaster->dataBits());
|
||||||
|
currentModbusRtuMaster->setStopBits(modbusRtuMaster->stopBits());
|
||||||
|
currentModbusRtuMaster->setConnected(modbusRtuMaster->connected());
|
||||||
|
modbusRtuMaster->deleteLater();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::getSerialPortsResponse(int commandId, const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
qDebug() << "Get serial ports response" << commandId << params;
|
||||||
|
m_serialPorts->clear();
|
||||||
|
|
||||||
|
foreach (const QVariant &serialPortVariant, params.value("serialPorts").toList()) {
|
||||||
|
m_serialPorts->addSerialPort(SerialPort::unpackSerialPort(serialPortVariant.toMap(), m_serialPorts));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::getModbusRtuMastersResponse(int commandId, const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
qDebug() << "Get modbus RTU masters response" << commandId << params;
|
||||||
|
|
||||||
|
QString error = params.value("modbusError").toString();
|
||||||
|
if (error == "ModbusRtuErrorNoError") {
|
||||||
|
m_supported = true;
|
||||||
|
emit supportedChanged(m_supported);
|
||||||
|
|
||||||
|
m_modbusRtuMasters->clear();
|
||||||
|
foreach (const QVariant &modbusRtuMasterVariant, params.value("modbusRtuMasters").toList()) {
|
||||||
|
m_modbusRtuMasters->addModbusRtuMaster(unpackModbusRtuMaster(modbusRtuMasterVariant.toMap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_engine->jsonRpcClient()->sendCommand("ModbusRtu.GetSerialPorts", this, "getSerialPortsResponse");
|
||||||
|
} else {
|
||||||
|
qWarning() << "Modbus is not supported on this platform";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::addModbusRtuMasterResponse(int commandId, const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
qDebug() << "Add modbus RTU master response" << commandId << params;
|
||||||
|
emit addModbusRtuMasterReply(commandId, params.value("modbusError").toString(), params.value("modbusUuid").toUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::removeModbusRtuMasterResponse(int commandId, const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
qDebug() << "Remove modbus RTU master response" << commandId << params;
|
||||||
|
emit removeModbusRtuMasterReply(commandId, params.value("modbusError").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::reconfigureModbusRtuMasterResponse(int commandId, const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
qDebug() << "Reconfigure modbus RTU master response" << commandId << params;
|
||||||
|
emit reconfigureModbusRtuMasterReply(commandId, params.value("modbusError").toString());
|
||||||
|
}
|
||||||
98
libnymea-app/modbus/modbusrtumanager.h
Normal file
98
libnymea-app/modbus/modbusrtumanager.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef MODBUSRTUMANAGER_H
|
||||||
|
#define MODBUSRTUMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "types/serialports.h"
|
||||||
|
#include "jsonrpc/jsonhandler.h"
|
||||||
|
|
||||||
|
class Engine;
|
||||||
|
class JsonRpcClient;
|
||||||
|
class ModbusRtuMaster;
|
||||||
|
class ModbusRtuMasters;
|
||||||
|
|
||||||
|
class ModbusRtuManager : public JsonHandler
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(Engine *engine READ engine WRITE setEngine NOTIFY engineChanged)
|
||||||
|
Q_PROPERTY(SerialPorts *serialPorts READ serialPorts CONSTANT)
|
||||||
|
Q_PROPERTY(ModbusRtuMasters *modbusRtuMasters READ modbusRtuMasters CONSTANT)
|
||||||
|
Q_PROPERTY(bool supported READ supported NOTIFY supportedChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ModbusRtuManager(QObject *parent = nullptr);
|
||||||
|
~ModbusRtuManager();
|
||||||
|
|
||||||
|
QString nameSpace() const override;
|
||||||
|
|
||||||
|
Engine *engine() const;
|
||||||
|
void setEngine(Engine *engine);
|
||||||
|
|
||||||
|
bool supported() const;
|
||||||
|
|
||||||
|
SerialPorts *serialPorts() const;
|
||||||
|
ModbusRtuMasters *modbusRtuMasters() const;
|
||||||
|
|
||||||
|
Q_INVOKABLE int addModbusRtuMaster(const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits);
|
||||||
|
Q_INVOKABLE int removeModbusRtuMaster(const QUuid &modbusUuid);
|
||||||
|
Q_INVOKABLE int reconfigureModbusRtuMaster(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, SerialPort::SerialPortParity parity, SerialPort::SerialPortDataBits dataBits, SerialPort::SerialPortStopBits stopBits);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void engineChanged();
|
||||||
|
void supportedChanged(bool supported);
|
||||||
|
void addModbusRtuMasterReply(int commandId, const QString &error, const QUuid &modbusUuid);
|
||||||
|
void removeModbusRtuMasterReply(int commandId, const QString &error);
|
||||||
|
void reconfigureModbusRtuMasterReply(int commandId, const QString &error);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Engine* m_engine = nullptr;
|
||||||
|
SerialPorts *m_serialPorts = nullptr;
|
||||||
|
ModbusRtuMasters *m_modbusRtuMasters = nullptr;
|
||||||
|
bool m_supported = false;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
ModbusRtuMaster *unpackModbusRtuMaster(const QVariantMap &modbusRtuMasterMap);
|
||||||
|
|
||||||
|
Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification);
|
||||||
|
|
||||||
|
Q_INVOKABLE void getSerialPortsResponse(int commandId, const QVariantMap ¶ms);
|
||||||
|
Q_INVOKABLE void getModbusRtuMastersResponse(int commandId, const QVariantMap ¶ms);
|
||||||
|
Q_INVOKABLE void addModbusRtuMasterResponse(int commandId, const QVariantMap ¶ms);
|
||||||
|
Q_INVOKABLE void removeModbusRtuMasterResponse(int commandId, const QVariantMap ¶ms);
|
||||||
|
Q_INVOKABLE void reconfigureModbusRtuMasterResponse(int commandId, const QVariantMap ¶ms);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MODBUSRTUMANAGER_H
|
||||||
130
libnymea-app/modbus/modbusrtumaster.cpp
Normal file
130
libnymea-app/modbus/modbusrtumaster.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "modbusrtumaster.h"
|
||||||
|
|
||||||
|
ModbusRtuMaster::ModbusRtuMaster(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid ModbusRtuMaster::modbusUuid() const
|
||||||
|
{
|
||||||
|
return m_modbusUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMaster::setModbusUuid(const QUuid &modbusUuid)
|
||||||
|
{
|
||||||
|
m_modbusUuid = modbusUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ModbusRtuMaster::serialPort() const
|
||||||
|
{
|
||||||
|
return m_serialPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMaster::setSerialPort(const QString &serialPort)
|
||||||
|
{
|
||||||
|
if (m_serialPort == serialPort)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_serialPort = serialPort;
|
||||||
|
emit serialPortChanged(m_serialPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint32 ModbusRtuMaster::baudrate() const
|
||||||
|
{
|
||||||
|
return m_baudrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMaster::setBaudrate(qint32 baudrate)
|
||||||
|
{
|
||||||
|
if (m_baudrate == baudrate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_baudrate = baudrate;
|
||||||
|
emit baudrateChanged(m_baudrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPort::SerialPortParity ModbusRtuMaster::parity() const
|
||||||
|
{
|
||||||
|
return m_parity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMaster::setParity(SerialPort::SerialPortParity parity)
|
||||||
|
{
|
||||||
|
if (m_parity == parity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_parity = parity;
|
||||||
|
emit parityChanged(m_parity);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPort::SerialPortDataBits ModbusRtuMaster::dataBits() const
|
||||||
|
{
|
||||||
|
return m_dataBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMaster::setDataBits(SerialPort::SerialPortDataBits dataBits)
|
||||||
|
{
|
||||||
|
if (m_dataBits == dataBits)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_dataBits = dataBits;
|
||||||
|
emit dataBitsChanged(m_dataBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPort::SerialPortStopBits ModbusRtuMaster::stopBits() const
|
||||||
|
{
|
||||||
|
return m_stopBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMaster::setStopBits(SerialPort::SerialPortStopBits stopBits)
|
||||||
|
{
|
||||||
|
if (m_stopBits == stopBits)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_stopBits = stopBits;
|
||||||
|
emit stopBitsChanged(m_stopBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuMaster::connected() const
|
||||||
|
{
|
||||||
|
return m_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMaster::setConnected(bool connected)
|
||||||
|
{
|
||||||
|
if (m_connected == connected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_connected = connected;
|
||||||
|
emit connectedChanged(m_connected);
|
||||||
|
}
|
||||||
93
libnymea-app/modbus/modbusrtumaster.h
Normal file
93
libnymea-app/modbus/modbusrtumaster.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef MODBUSRTUMASTER_H
|
||||||
|
#define MODBUSRTUMASTER_H
|
||||||
|
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "types/serialport.h"
|
||||||
|
|
||||||
|
class ModbusRtuMaster : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QUuid modbusUuid READ modbusUuid CONSTANT)
|
||||||
|
Q_PROPERTY(QString serialPort READ serialPort NOTIFY serialPortChanged)
|
||||||
|
Q_PROPERTY(qint32 baudrate READ baudrate NOTIFY baudrateChanged)
|
||||||
|
Q_PROPERTY(SerialPort::SerialPortParity parity READ parity NOTIFY parityChanged)
|
||||||
|
Q_PROPERTY(SerialPort::SerialPortDataBits dataBits READ dataBits NOTIFY dataBitsChanged)
|
||||||
|
Q_PROPERTY(SerialPort::SerialPortStopBits stopBits READ stopBits NOTIFY stopBitsChanged)
|
||||||
|
Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ModbusRtuMaster(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QUuid modbusUuid() const;
|
||||||
|
void setModbusUuid(const QUuid &modbusUuid);
|
||||||
|
|
||||||
|
QString serialPort() const;
|
||||||
|
void setSerialPort(const QString &serialPort);
|
||||||
|
|
||||||
|
qint32 baudrate() const;
|
||||||
|
void setBaudrate(qint32 baudrate);
|
||||||
|
|
||||||
|
SerialPort::SerialPortParity parity() const;
|
||||||
|
void setParity(SerialPort::SerialPortParity parity);
|
||||||
|
|
||||||
|
SerialPort::SerialPortDataBits dataBits() const;
|
||||||
|
void setDataBits(SerialPort::SerialPortDataBits dataBits);
|
||||||
|
|
||||||
|
SerialPort::SerialPortStopBits stopBits() const;
|
||||||
|
void setStopBits(SerialPort::SerialPortStopBits stopBits);
|
||||||
|
|
||||||
|
bool connected() const;
|
||||||
|
void setConnected(bool connected);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void connectedChanged(bool connected);
|
||||||
|
void serialPortChanged(const QString &serialPort);
|
||||||
|
void baudrateChanged(quint32 baudrate);
|
||||||
|
void parityChanged(SerialPort::SerialPortParity parity);
|
||||||
|
void dataBitsChanged(SerialPort::SerialPortDataBits dataBits);
|
||||||
|
void stopBitsChanged(SerialPort::SerialPortStopBits stopBits);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QUuid m_modbusUuid;
|
||||||
|
QString m_serialPort;
|
||||||
|
qint32 m_baudrate;
|
||||||
|
SerialPort::SerialPortParity m_parity;
|
||||||
|
SerialPort::SerialPortDataBits m_dataBits;
|
||||||
|
SerialPort::SerialPortStopBits m_stopBits;
|
||||||
|
bool m_connected = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MODBUSRTUMASTER_H
|
||||||
169
libnymea-app/modbus/modbusrtumasters.cpp
Normal file
169
libnymea-app/modbus/modbusrtumasters.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "modbusrtumasters.h"
|
||||||
|
|
||||||
|
ModbusRtuMasters::ModbusRtuMasters(QObject *parent) : QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ModbusRtuMaster *> ModbusRtuMasters::modbusRtuMasters() const
|
||||||
|
{
|
||||||
|
return m_modbusRtuMasters;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModbusRtuMasters::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return m_modbusRtuMasters.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant ModbusRtuMasters::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case RoleUuid:
|
||||||
|
return m_modbusRtuMasters.at(index.row())->modbusUuid();
|
||||||
|
case RoleSerialPort:
|
||||||
|
return m_modbusRtuMasters.at(index.row())->serialPort();
|
||||||
|
case RoleBaudrate:
|
||||||
|
return m_modbusRtuMasters.at(index.row())->baudrate();
|
||||||
|
case RoleParity:
|
||||||
|
return m_modbusRtuMasters.at(index.row())->parity();
|
||||||
|
case RoleDataBits:
|
||||||
|
return m_modbusRtuMasters.at(index.row())->dataBits();
|
||||||
|
case RoleStopBits:
|
||||||
|
return m_modbusRtuMasters.at(index.row())->stopBits();
|
||||||
|
case RoleConnected:
|
||||||
|
return m_modbusRtuMasters.at(index.row())->connected();
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> ModbusRtuMasters::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles.insert(RoleUuid, "modbusUuid");
|
||||||
|
roles.insert(RoleSerialPort, "serialPort");
|
||||||
|
roles.insert(RoleBaudrate, "baudrate");
|
||||||
|
roles.insert(RoleParity, "parity");
|
||||||
|
roles.insert(RoleDataBits, "dataBits");
|
||||||
|
roles.insert(RoleStopBits, "stopBits");
|
||||||
|
roles.insert(RoleConnected, "connected");
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasters::addModbusRtuMaster(ModbusRtuMaster *modbusRtuMaster)
|
||||||
|
{
|
||||||
|
modbusRtuMaster->setParent(this);
|
||||||
|
|
||||||
|
connect(modbusRtuMaster, &ModbusRtuMaster::serialPortChanged, this, [=](const QString &serialPort) {
|
||||||
|
Q_UNUSED(serialPort)
|
||||||
|
QModelIndex idx = index(m_modbusRtuMasters.indexOf(modbusRtuMaster), 0);
|
||||||
|
emit dataChanged(idx, idx, {RoleSerialPort});
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusRtuMaster, &ModbusRtuMaster::baudrateChanged, this, [=](qint32 baudrate) {
|
||||||
|
Q_UNUSED(baudrate)
|
||||||
|
QModelIndex idx = index(m_modbusRtuMasters.indexOf(modbusRtuMaster), 0);
|
||||||
|
emit dataChanged(idx, idx, {RoleBaudrate});
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusRtuMaster, &ModbusRtuMaster::parityChanged, this, [=](SerialPort::SerialPortParity parity) {
|
||||||
|
Q_UNUSED(parity)
|
||||||
|
QModelIndex idx = index(m_modbusRtuMasters.indexOf(modbusRtuMaster), 0);
|
||||||
|
emit dataChanged(idx, idx, {RoleParity});
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusRtuMaster, &ModbusRtuMaster::dataBitsChanged, this, [=](SerialPort::SerialPortDataBits dataBits) {
|
||||||
|
Q_UNUSED(dataBits)
|
||||||
|
QModelIndex idx = index(m_modbusRtuMasters.indexOf(modbusRtuMaster), 0);
|
||||||
|
emit dataChanged(idx, idx, {RoleDataBits});
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusRtuMaster, &ModbusRtuMaster::stopBitsChanged, this, [=](SerialPort::SerialPortStopBits stopBites) {
|
||||||
|
Q_UNUSED(stopBites)
|
||||||
|
QModelIndex idx = index(m_modbusRtuMasters.indexOf(modbusRtuMaster), 0);
|
||||||
|
emit dataChanged(idx, idx, {RoleStopBits});
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusRtuMaster, &ModbusRtuMaster::connectedChanged, this, [=](bool connected) {
|
||||||
|
Q_UNUSED(connected)
|
||||||
|
QModelIndex idx = index(m_modbusRtuMasters.indexOf(modbusRtuMaster), 0);
|
||||||
|
emit dataChanged(idx, idx, {RoleConnected});
|
||||||
|
});
|
||||||
|
|
||||||
|
beginInsertRows(QModelIndex(), m_modbusRtuMasters.count(), m_modbusRtuMasters.count());
|
||||||
|
m_modbusRtuMasters.append(modbusRtuMaster);
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasters::removeModbusRtuMaster(const QUuid &modbusUuid)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_modbusRtuMasters.count(); i++) {
|
||||||
|
if (m_modbusRtuMasters.at(i)->modbusUuid() == modbusUuid) {
|
||||||
|
beginRemoveRows(QModelIndex(), i, i);
|
||||||
|
m_modbusRtuMasters.takeAt(i)->deleteLater();
|
||||||
|
endRemoveRows();
|
||||||
|
emit countChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasters::clear()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
qDeleteAll(m_modbusRtuMasters);
|
||||||
|
m_modbusRtuMasters.clear();
|
||||||
|
endResetModel();
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuMaster *ModbusRtuMasters::get(int index) const
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= m_modbusRtuMasters.count()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return m_modbusRtuMasters.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuMaster *ModbusRtuMasters::getModbusRtuMaster(const QUuid &modbusUuid) const
|
||||||
|
{
|
||||||
|
foreach (ModbusRtuMaster *modbusRtuMaster, m_modbusRtuMasters) {
|
||||||
|
if (modbusRtuMaster->modbusUuid() == modbusUuid) {
|
||||||
|
return modbusRtuMaster;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
81
libnymea-app/modbus/modbusrtumasters.h
Normal file
81
libnymea-app/modbus/modbusrtumasters.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef MODBUSRTUMASTERS_H
|
||||||
|
#define MODBUSRTUMASTERS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
|
#include "modbusrtumaster.h"
|
||||||
|
|
||||||
|
class ModbusRtuMasters : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Roles {
|
||||||
|
RoleUuid,
|
||||||
|
RoleSerialPort,
|
||||||
|
RoleBaudrate,
|
||||||
|
RoleParity,
|
||||||
|
RoleDataBits,
|
||||||
|
RoleStopBits,
|
||||||
|
RoleConnected
|
||||||
|
};
|
||||||
|
Q_ENUM(Roles)
|
||||||
|
|
||||||
|
explicit ModbusRtuMasters(QObject *parent = nullptr);
|
||||||
|
virtual ~ModbusRtuMasters() override = default;
|
||||||
|
|
||||||
|
QList<ModbusRtuMaster *> modbusRtuMasters() const;
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
void addModbusRtuMaster(ModbusRtuMaster *modbusRtuMaster);
|
||||||
|
void removeModbusRtuMaster(const QUuid &modbusUuid);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
Q_INVOKABLE virtual ModbusRtuMaster *get(int index) const;
|
||||||
|
Q_INVOKABLE ModbusRtuMaster *getModbusRtuMaster(const QUuid &modbusUuid) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void countChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<ModbusRtuMaster *> m_modbusRtuMasters;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MODBUSRTUMASTERS_H
|
||||||
114
libnymea-app/types/serialport.cpp
Normal file
114
libnymea-app/types/serialport.cpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "serialport.h"
|
||||||
|
|
||||||
|
SerialPort::SerialPort(const QString &systemLocation, const QString &manufacturer, const QString &description, const QString &serialNumber, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_systemLocation(systemLocation),
|
||||||
|
m_manufacturer(manufacturer),
|
||||||
|
m_description(description),
|
||||||
|
m_serialNumber(serialNumber)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SerialPort::systemLocation() const
|
||||||
|
{
|
||||||
|
return m_systemLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SerialPort::manufacturer() const
|
||||||
|
{
|
||||||
|
return m_manufacturer;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SerialPort::description() const
|
||||||
|
{
|
||||||
|
return m_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SerialPort::serialNumber() const
|
||||||
|
{
|
||||||
|
return m_serialNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPort *SerialPort::unpackSerialPort(const QVariantMap &serialPortMap, QObject *parent)
|
||||||
|
{
|
||||||
|
return new SerialPort(serialPortMap.value("systemLocation").toString(),
|
||||||
|
serialPortMap.value("manufacturer").toString(),
|
||||||
|
serialPortMap.value("description").toString(),
|
||||||
|
serialPortMap.value("serialNumber").toString(), parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPort::SerialPortParity SerialPort::stringToSerialPortParity(const QString &parityString)
|
||||||
|
{
|
||||||
|
if (parityString == "SerialPortParityNoParity") {
|
||||||
|
return SerialPort::SerialPortParityNoParity;
|
||||||
|
} else if (parityString == "SerialPortParityEvenParity") {
|
||||||
|
return SerialPort::SerialPortParityEvenParity;
|
||||||
|
} else if (parityString == "SerialPortParityOddParity") {
|
||||||
|
return SerialPort::SerialPortParityOddParity;
|
||||||
|
} else if (parityString == "SerialPortParitySpaceParity") {
|
||||||
|
return SerialPort::SerialPortParitySpaceParity;
|
||||||
|
} else if (parityString == "SerialPortParityMarkParity") {
|
||||||
|
return SerialPort::SerialPortParityMarkParity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SerialPort::SerialPortParityUnknownParity;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPort::SerialPortDataBits SerialPort::stringToSerialPortDataBits(const QString &dataBitsString)
|
||||||
|
{
|
||||||
|
if (dataBitsString == "SerialPortDataBitsData5") {
|
||||||
|
return SerialPort::SerialPortDataBitsData5;
|
||||||
|
} else if (dataBitsString == "SerialPortDataBitsData6") {
|
||||||
|
return SerialPort::SerialPortDataBitsData6;
|
||||||
|
} else if (dataBitsString == "SerialPortDataBitsData7") {
|
||||||
|
return SerialPort::SerialPortDataBitsData7;
|
||||||
|
} else if (dataBitsString == "SerialPortDataBitsData8") {
|
||||||
|
return SerialPort::SerialPortDataBitsData7;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SerialPort::SerialPortDataBitsUnknownDataBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPort::SerialPortStopBits SerialPort::stringToSerialPortStopBits(const QString &stopBitsString)
|
||||||
|
{
|
||||||
|
if (stopBitsString == "SerialPortStopBitsOneStop") {
|
||||||
|
return SerialPort::SerialPortStopBitsOneStop;
|
||||||
|
} else if (stopBitsString == "SerialPortStopBitsOneAndHalfStop") {
|
||||||
|
return SerialPort::SerialPortStopBitsOneAndHalfStop;
|
||||||
|
} else if (stopBitsString == "SerialPortStopBitsTwoStop") {
|
||||||
|
return SerialPort::SerialPortStopBitsTwoStop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SerialPort::SerialPortStopBitsUnknownStopBits;
|
||||||
|
}
|
||||||
93
libnymea-app/types/serialport.h
Normal file
93
libnymea-app/types/serialport.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef SERIALPORT_H
|
||||||
|
#define SERIALPORT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
class SerialPort : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString systemLocation READ systemLocation CONSTANT)
|
||||||
|
Q_PROPERTY(QString manufacturer READ manufacturer CONSTANT)
|
||||||
|
Q_PROPERTY(QString description READ description CONSTANT)
|
||||||
|
Q_PROPERTY(QString serialNumber READ serialNumber CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum SerialPortParity {
|
||||||
|
SerialPortParityNoParity = 0,
|
||||||
|
SerialPortParityEvenParity = 2,
|
||||||
|
SerialPortParityOddParity = 3,
|
||||||
|
SerialPortParitySpaceParity = 4,
|
||||||
|
SerialPortParityMarkParity = 5,
|
||||||
|
SerialPortParityUnknownParity = -1
|
||||||
|
};
|
||||||
|
Q_ENUM(SerialPortParity)
|
||||||
|
|
||||||
|
enum SerialPortDataBits {
|
||||||
|
SerialPortDataBitsData5 = 5,
|
||||||
|
SerialPortDataBitsData6 = 6,
|
||||||
|
SerialPortDataBitsData7 = 7,
|
||||||
|
SerialPortDataBitsData8 = 8,
|
||||||
|
SerialPortDataBitsUnknownDataBits = -1
|
||||||
|
};
|
||||||
|
Q_ENUM(SerialPortDataBits)
|
||||||
|
|
||||||
|
enum SerialPortStopBits {
|
||||||
|
SerialPortStopBitsOneStop = 1,
|
||||||
|
SerialPortStopBitsOneAndHalfStop = 3,
|
||||||
|
SerialPortStopBitsTwoStop = 2,
|
||||||
|
SerialPortStopBitsUnknownStopBits = -1
|
||||||
|
};
|
||||||
|
Q_ENUM(SerialPortStopBits)
|
||||||
|
|
||||||
|
explicit SerialPort(const QString &systemLocation, const QString &manufacturer, const QString &description, const QString &serialNumber, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QString systemLocation() const;
|
||||||
|
QString manufacturer() const;
|
||||||
|
QString description() const;
|
||||||
|
QString serialNumber() const;
|
||||||
|
|
||||||
|
static SerialPort *unpackSerialPort(const QVariantMap &serialPortMap, QObject *parent);
|
||||||
|
static SerialPort::SerialPortParity stringToSerialPortParity(const QString &parityString);
|
||||||
|
static SerialPort::SerialPortDataBits stringToSerialPortDataBits(const QString &dataBitsString);
|
||||||
|
static SerialPort::SerialPortStopBits stringToSerialPortStopBits(const QString &stopBitsString);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_systemLocation;
|
||||||
|
QString m_manufacturer;
|
||||||
|
QString m_description;
|
||||||
|
QString m_serialNumber;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SERIALPORT_H
|
||||||
109
libnymea-app/types/serialports.cpp
Normal file
109
libnymea-app/types/serialports.cpp
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "serialports.h"
|
||||||
|
|
||||||
|
SerialPorts::SerialPorts(QObject *parent) : QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SerialPorts::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return m_serialPorts.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant SerialPorts::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case RoleSystmLocation:
|
||||||
|
return m_serialPorts.at(index.row())->systemLocation();
|
||||||
|
case RoleManufacturer:
|
||||||
|
return m_serialPorts.at(index.row())->manufacturer();
|
||||||
|
case RoleDescription:
|
||||||
|
return m_serialPorts.at(index.row())->description();
|
||||||
|
case RoleSerialNumber:
|
||||||
|
return m_serialPorts.at(index.row())->serialNumber();
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> SerialPorts::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles.insert(RoleSystmLocation, "systemLocation");
|
||||||
|
roles.insert(RoleManufacturer, "manufacturer");
|
||||||
|
roles.insert(RoleDescription, "description");
|
||||||
|
roles.insert(RoleSerialNumber, "serialNumber");
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialPorts::addSerialPort(SerialPort *serialPort)
|
||||||
|
{
|
||||||
|
serialPort->setParent(this);
|
||||||
|
|
||||||
|
beginInsertRows(QModelIndex(), m_serialPorts.count(), m_serialPorts.count());
|
||||||
|
m_serialPorts.append(serialPort);
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialPorts::removeSerialPort(const QString &systemLocation)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_serialPorts.count(); i++) {
|
||||||
|
if (m_serialPorts.at(i)->systemLocation() == systemLocation) {
|
||||||
|
beginRemoveRows(QModelIndex(), i, i);
|
||||||
|
m_serialPorts.takeAt(i)->deleteLater();
|
||||||
|
endRemoveRows();
|
||||||
|
emit countChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialPorts::clear()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
qDeleteAll(m_serialPorts);
|
||||||
|
m_serialPorts.clear();
|
||||||
|
endResetModel();
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPort *SerialPorts::get(int index) const
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= m_serialPorts.count()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_serialPorts.at(index);
|
||||||
|
}
|
||||||
74
libnymea-app/types/serialports.h
Normal file
74
libnymea-app/types/serialports.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef SERIALPORTS_H
|
||||||
|
#define SERIALPORTS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
|
#include "serialport.h"
|
||||||
|
|
||||||
|
class SerialPorts : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Roles {
|
||||||
|
RoleSystmLocation,
|
||||||
|
RoleManufacturer,
|
||||||
|
RoleDescription,
|
||||||
|
RoleSerialNumber
|
||||||
|
};
|
||||||
|
Q_ENUM(Roles)
|
||||||
|
|
||||||
|
explicit SerialPorts(QObject *parent = nullptr);
|
||||||
|
virtual ~SerialPorts() override = default;
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
void addSerialPort(SerialPort *serialPort);
|
||||||
|
void removeSerialPort(const QString &systemLocation);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
Q_INVOKABLE virtual SerialPort *get(int index) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void countChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QList<SerialPort *> m_serialPorts;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SERIALPORTS_H
|
||||||
69
libnymea-app/types/serialportsproxy.cpp
Normal file
69
libnymea-app/types/serialportsproxy.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "serialportsproxy.h"
|
||||||
|
|
||||||
|
SerialPortsProxy::SerialPortsProxy(QObject *parent) : QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPorts *SerialPortsProxy::serialPorts() const
|
||||||
|
{
|
||||||
|
return m_serialPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialPortsProxy::setSerialPorts(SerialPorts *serialPorts)
|
||||||
|
{
|
||||||
|
if (m_serialPorts == serialPorts)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_serialPorts = serialPorts;
|
||||||
|
connect(m_serialPorts, &SerialPorts::countChanged, this, [this](){
|
||||||
|
emit countChanged();
|
||||||
|
});
|
||||||
|
connect(m_serialPorts, &SerialPorts::countChanged, this, [this]() {
|
||||||
|
sort(0, Qt::DescendingOrder);
|
||||||
|
});
|
||||||
|
|
||||||
|
setSourceModel(serialPorts);
|
||||||
|
setSortRole(SerialPorts::RoleSystmLocation);
|
||||||
|
sort(0, Qt::DescendingOrder);
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPort *SerialPortsProxy::get(int index) const
|
||||||
|
{
|
||||||
|
if (index >= 0 && index < m_serialPorts->rowCount()) {
|
||||||
|
return m_serialPorts->get(mapToSource(this->index(index, 0)).row());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
61
libnymea-app/types/serialportsproxy.h
Normal file
61
libnymea-app/types/serialportsproxy.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef SERIALPORTSPROXY_H
|
||||||
|
#define SERIALPORTSPROXY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
#include "serialports.h"
|
||||||
|
|
||||||
|
class SerialPortsProxy : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SerialPortsProxy(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
SerialPorts *serialPorts() const;
|
||||||
|
void setSerialPorts(SerialPorts *serialPorts);
|
||||||
|
|
||||||
|
Q_INVOKABLE SerialPort* get(int index) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void countChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SerialPorts *m_serialPorts = nullptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SERIALPORTSPROXY_H
|
||||||
@ -259,5 +259,6 @@
|
|||||||
<file>ui/images/nymea-splash.svg</file>
|
<file>ui/images/nymea-splash.svg</file>
|
||||||
<file>ui/images/cleaning-robot.svg</file>
|
<file>ui/images/cleaning-robot.svg</file>
|
||||||
<file>ui/images/chart.svg</file>
|
<file>ui/images/chart.svg</file>
|
||||||
|
<file>ui/images/modbus.svg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -246,5 +246,8 @@
|
|||||||
<file>ui/mainviews/dashboard/DashboardSceneDelegate.qml</file>
|
<file>ui/mainviews/dashboard/DashboardSceneDelegate.qml</file>
|
||||||
<file>ui/mainviews/dashboard/DashboardWebViewDelegate.qml</file>
|
<file>ui/mainviews/dashboard/DashboardWebViewDelegate.qml</file>
|
||||||
<file>ui/components/SelectionTabs.qml</file>
|
<file>ui/components/SelectionTabs.qml</file>
|
||||||
|
<file>ui/system/ModbusRtuSettingsPage.qml</file>
|
||||||
|
<file>ui/system/ModbusRtuAddMasterPage.qml</file>
|
||||||
|
<file>ui/system/ModbusRtuReconfigureMasterPage.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -186,6 +186,23 @@ Page {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pane {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Material.elevation: layout.isGrid ? 1 : 0
|
||||||
|
visible: engine.jsonRpcClient.ensureServerVersion("5.4")
|
||||||
|
|
||||||
|
padding: 0
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
width: parent.width
|
||||||
|
iconName: "../images/modbus.svg"
|
||||||
|
text: qsTr("Modbus RTU")
|
||||||
|
subText: qsTr("Configure Modbus RTU master interfaces")
|
||||||
|
prominentSubText: false
|
||||||
|
wrapTexts: false
|
||||||
|
onClicked: pageStack.push(Qt.resolvedUrl("system/ModbusRtuSettingsPage.qml"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Pane {
|
Pane {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Material.elevation: layout.isGrid ? 1 : 0
|
Material.elevation: layout.isGrid ? 1 : 0
|
||||||
|
|||||||
224
nymea-app/ui/images/modbus.svg
Normal file
224
nymea-app/ui/images/modbus.svg
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="96"
|
||||||
|
height="96"
|
||||||
|
id="svg4874"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||||
|
viewBox="0 0 96 96.000001"
|
||||||
|
sodipodi:docname="modbus.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4876" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.805916"
|
||||||
|
inkscape:cx="32.313164"
|
||||||
|
inkscape:cy="51.899226"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="g4780"
|
||||||
|
showgrid="true"
|
||||||
|
showborder="true"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:object-nodes="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="2880"
|
||||||
|
inkscape:window-height="1663"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="76"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid5451"
|
||||||
|
empspacing="8" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="8,-8.0000001"
|
||||||
|
id="guide4063"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="4,-8.0000001"
|
||||||
|
id="guide4065"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,88.000001"
|
||||||
|
id="guide4067"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,92.000001"
|
||||||
|
id="guide4069"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="104,4"
|
||||||
|
id="guide4071"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-5,8.0000001"
|
||||||
|
id="guide4073"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="92,-8.0000001"
|
||||||
|
id="guide4075"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="88,-8.0000001"
|
||||||
|
id="guide4077"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,84.000001"
|
||||||
|
id="guide4074"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="12,-8.0000001"
|
||||||
|
id="guide4076"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-5,12"
|
||||||
|
id="guide4078"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="84,-9.0000001"
|
||||||
|
id="guide4080"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="48,83.568528"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide4170"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata4879">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(67.857146,-78.50504)">
|
||||||
|
<g
|
||||||
|
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
|
||||||
|
id="g4845"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="90"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-filename="next01.png"
|
||||||
|
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
|
||||||
|
id="g4778"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<g
|
||||||
|
transform="matrix(-1,0,0,1,575.99999,611)"
|
||||||
|
id="g4780"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
|
||||||
|
id="rect4782"
|
||||||
|
width="96.037987"
|
||||||
|
height="96"
|
||||||
|
x="-438.00244"
|
||||||
|
y="345.36221"
|
||||||
|
transform="scale(-1,1)" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#808080;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 395.98583,366.36222 v 54"
|
||||||
|
id="path837-3"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#808080;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 393.98504,368.36261 -16.00633,-3.9e-4"
|
||||||
|
id="path837-7"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#808080;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 393.98504,418.36222 -16.00633,0"
|
||||||
|
id="path837-7-5"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<rect
|
||||||
|
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:4.06083727;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="rect899-3"
|
||||||
|
width="17.93956"
|
||||||
|
height="11.945124"
|
||||||
|
x="-402.332"
|
||||||
|
y="-371.97635"
|
||||||
|
transform="matrix(0,-1,-1,0,0,0)" />
|
||||||
|
<rect
|
||||||
|
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:4.06083727;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="rect899-3-6"
|
||||||
|
width="17.93956"
|
||||||
|
height="11.945124"
|
||||||
|
x="-427.30176"
|
||||||
|
y="-371.97635"
|
||||||
|
transform="matrix(0,-1,-1,0,0,0)" />
|
||||||
|
<rect
|
||||||
|
style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#808080;stroke-width:4.06083727;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="rect899-3-6-2"
|
||||||
|
width="17.93956"
|
||||||
|
height="11.945124"
|
||||||
|
x="-377.332"
|
||||||
|
y="-371.97635"
|
||||||
|
transform="matrix(0,-1,-1,0,0,0)" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#808080;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 421.99612,393.36222 -44.01741,0"
|
||||||
|
id="path837-7-5-9"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 8.0 KiB |
249
nymea-app/ui/system/ModbusRtuAddMasterPage.qml
Normal file
249
nymea-app/ui/system/ModbusRtuAddMasterPage.qml
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
import QtQuick 2.8
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Controls.Material 2.1
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import "../components"
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
|
SettingsPageBase {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property ModbusRtuManager modbusRtuManager
|
||||||
|
property ListModel serialPortBaudrateModel
|
||||||
|
property ListModel serialPortParityModel
|
||||||
|
property ListModel serialPortDataBitsModel
|
||||||
|
property ListModel serialPortStopBitsModel
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Add a new Modbus RTU master")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPageSectionHeader {
|
||||||
|
text: qsTr("Serial ports")
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: app.margins
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: modbusRtuManager.serialPorts.count !== 0 ? qsTr("Please select one of the following serial ports detected on the system.") : qsTr("There are no serial ports available.\n\nPlease make sure the modbus RTU interface is connected to the system.")
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: modbusRtuManager.serialPorts
|
||||||
|
delegate: NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
iconName: "../images/stock_usb.svg"
|
||||||
|
text: model.description + (model.manufacturer === "" ? "" : " - " + model.manufacturer)
|
||||||
|
subText: model.systemLocation + (model.serialNumber === "" ? "" : " - " + model.serialNumber)
|
||||||
|
onClicked: pageStack.push(configureNewModbusRtuMasterPage, { modbusRtuManager: modbusRtuManager, serialPort: modbusRtuManager.serialPorts.get(index) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: configureNewModbusRtuMasterPage
|
||||||
|
|
||||||
|
SettingsPageBase {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property ModbusRtuManager modbusRtuManager
|
||||||
|
property SerialPort serialPort
|
||||||
|
busy: d.pendingCommandId != -1
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Configure modbus RTU master")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
property int pendingCommandId: -1
|
||||||
|
|
||||||
|
function addModbusRtuMaster(serialPort, baudRate, parity, dataBits, stopBits) {
|
||||||
|
d.pendingCommandId = root.modbusRtuManager.addModbusRtuMaster(serialPort, baudRate, parity, dataBits, stopBits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.modbusRtuManager
|
||||||
|
onAddModbusRtuMasterReply: {
|
||||||
|
if (commandId === d.pendingCommandId) {
|
||||||
|
d.pendingCommandId = -1
|
||||||
|
if (modbusRtuManager.handleModbusError(error)) {
|
||||||
|
pageStack.pop();
|
||||||
|
pageStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SettingsPageSectionHeader {
|
||||||
|
text: qsTr("Serial port")
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("System location")
|
||||||
|
subText: serialPort.systemLocation
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Description")
|
||||||
|
subText: serialPort.description
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Manufacturer")
|
||||||
|
subText: serialPort.manufacturer
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
visible: serialPort.manufacturer !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Serialnumber")
|
||||||
|
subText: serialPort.serialNumber
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
visible: serialPort.serialNumber !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPageSectionHeader {
|
||||||
|
text: qsTr("Configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
Label {
|
||||||
|
text: qsTr("Baud rate")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: baudRateComboBox
|
||||||
|
Layout.minimumWidth: 250
|
||||||
|
textRole: "text"
|
||||||
|
enabled: !root.busy
|
||||||
|
onActivated: console.log("Selected baud rate", currentText, model.get(currentIndex).value)
|
||||||
|
model: serialPortBaudrateModel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Parity")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: parityComboBox
|
||||||
|
textRole: "text"
|
||||||
|
enabled: !root.busy
|
||||||
|
Layout.minimumWidth: 250
|
||||||
|
onActivated: console.log("Selected parity", currentText, model.get(currentIndex).value)
|
||||||
|
model: serialPortParityModel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Data bits")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: dataBitsComboBox
|
||||||
|
textRole: "text"
|
||||||
|
enabled: !root.busy
|
||||||
|
Layout.minimumWidth: 250
|
||||||
|
onActivated: console.log("Selected data bits", currentText, model.get(currentIndex).value)
|
||||||
|
model: serialPortDataBitsModel
|
||||||
|
Component.onCompleted: {
|
||||||
|
currentIndex = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Stop bits")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: stopBitsComboBox
|
||||||
|
textRole: "text"
|
||||||
|
enabled: !root.busy
|
||||||
|
Layout.minimumWidth: 250
|
||||||
|
onActivated: console.log("Selected stop bits", currentText, model.get(currentIndex).value)
|
||||||
|
model: serialPortStopBitsModel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: app.margins
|
||||||
|
Layout.rightMargin: app.margins
|
||||||
|
text: qsTr("Add")
|
||||||
|
enabled: !root.busy
|
||||||
|
onClicked: {
|
||||||
|
var baudrate = serialPortBaudrateModel.get(baudRateComboBox.currentIndex).value
|
||||||
|
var parity = serialPortParityModel.get(parityComboBox.currentIndex).value
|
||||||
|
var dataBits = serialPortDataBitsModel.get(dataBitsComboBox.currentIndex).value
|
||||||
|
var stopBits = serialPortStopBitsModel.get(stopBitsComboBox.currentIndex).value
|
||||||
|
console.log("Adding modbus RTU with", serialPort.systemLocation, baudrate, parity, dataBits, stopBits)
|
||||||
|
|
||||||
|
d.addModbusRtuMaster(serialPort.systemLocation, baudrate, parity, dataBits, stopBits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
284
nymea-app/ui/system/ModbusRtuReconfigureMasterPage.qml
Normal file
284
nymea-app/ui/system/ModbusRtuReconfigureMasterPage.qml
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
import QtQuick 2.8
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Controls.Material 2.1
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import "../components"
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
|
SettingsPageBase {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property ModbusRtuManager modbusRtuManager
|
||||||
|
property ModbusRtuMaster modbusRtuMaster
|
||||||
|
property ListModel serialPortBaudrateModel
|
||||||
|
property ListModel serialPortParityModel
|
||||||
|
property ListModel serialPortDataBitsModel
|
||||||
|
property ListModel serialPortStopBitsModel
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Reconfigure modbus RTU master")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPageSectionHeader {
|
||||||
|
text: qsTr("Serial ports")
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: app.margins
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: modbusRtuManager.serialPorts.count !== 0 ? qsTr("Please select one of the following serial ports detected on the system.") : qsTr("There are no serial ports available.\n\nPlease make sure the modbus RTU interface is connected to the system.")
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: modbusRtuManager.serialPorts
|
||||||
|
delegate: NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
iconName: "../images/stock_usb.svg"
|
||||||
|
text: model.description + (model.manufacturer === "" ? "" : " - " + model.manufacturer)
|
||||||
|
subText: model.systemLocation + (model.serialNumber === "" ? "" : " - " + model.serialNumber)
|
||||||
|
onClicked: pageStack.push(reconfigureNewModbusRtuMasterPage, { modbusRtuManager: modbusRtuManager, serialPort: modbusRtuManager.serialPorts.get(index), modbusRtuMaster: modbusRtuMaster })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: reconfigureNewModbusRtuMasterPage
|
||||||
|
|
||||||
|
SettingsPageBase {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property ModbusRtuManager modbusRtuManager
|
||||||
|
property SerialPort serialPort
|
||||||
|
property ModbusRtuMaster modbusRtuMaster
|
||||||
|
|
||||||
|
busy: d.pendingCommandId != -1
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Reconfigure modbus RTU master")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
property int pendingCommandId: -1
|
||||||
|
|
||||||
|
function reconfigureModbusRtuMaster(modbusUuid, serialPort, baudRate, parity, dataBits, stopBits) {
|
||||||
|
d.pendingCommandId = root.modbusRtuManager.reconfigureModbusRtuMaster(modbusUuid, serialPort, baudRate, parity, dataBits, stopBits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.modbusRtuManager
|
||||||
|
onReconfigureModbusRtuMasterReply: {
|
||||||
|
if (commandId === d.pendingCommandId) {
|
||||||
|
d.pendingCommandId = -1
|
||||||
|
if (modbusRtuManager.handleModbusError(error)) {
|
||||||
|
pageStack.pop();
|
||||||
|
pageStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("UUID")
|
||||||
|
subText: modbusRtuMaster.modbusUuid
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPageSectionHeader {
|
||||||
|
text: qsTr("Serial port")
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("System location")
|
||||||
|
subText: serialPort.systemLocation
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Description")
|
||||||
|
subText: serialPort.description
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Manufacturer")
|
||||||
|
subText: serialPort.manufacturer
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
visible: serialPort.manufacturer !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Serialnumber")
|
||||||
|
subText: serialPort.serialNumber
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
visible: serialPort.serialNumber !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPageSectionHeader {
|
||||||
|
text: qsTr("Configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
Label {
|
||||||
|
text: qsTr("Baud rate")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: baudRateComboBox
|
||||||
|
Layout.minimumWidth: 250
|
||||||
|
enabled: !root.busy
|
||||||
|
textRole: "text"
|
||||||
|
model: serialPortBaudrateModel
|
||||||
|
onActivated: console.log("Selected baudrate", currentText, model.get(currentIndex).value)
|
||||||
|
Component.onCompleted: {
|
||||||
|
for (var i = 0; i < serialPortBaudrateModel.count; i++) {
|
||||||
|
if (serialPortBaudrateModel.get(i).value === modbusRtuMaster.baudrate) {
|
||||||
|
currentIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Parity")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: parityComboBox
|
||||||
|
textRole: "text"
|
||||||
|
enabled: !root.busy
|
||||||
|
Layout.minimumWidth: 250
|
||||||
|
onActivated: console.log("Selected parity", currentText, model.get(currentIndex).value)
|
||||||
|
model: serialPortParityModel
|
||||||
|
Component.onCompleted: {
|
||||||
|
for (var i = 0; i < serialPortParityModel.count; i++) {
|
||||||
|
if (serialPortParityModel.get(i).value === modbusRtuMaster.parity) {
|
||||||
|
currentIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Data bits")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: dataBitsComboBox
|
||||||
|
textRole: "text"
|
||||||
|
enabled: !root.busy
|
||||||
|
Layout.minimumWidth: 250
|
||||||
|
onActivated: console.log("Selected data bits", currentText, model.get(currentIndex).value)
|
||||||
|
model: serialPortDataBitsModel
|
||||||
|
Component.onCompleted: {
|
||||||
|
for (var i = 0; i < serialPortDataBitsModel.count; i++) {
|
||||||
|
if (serialPortDataBitsModel.get(i).value === modbusRtuMaster.dataBits) {
|
||||||
|
currentIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Stop bits")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: stopBitsComboBox
|
||||||
|
textRole: "text"
|
||||||
|
enabled: !root.busy
|
||||||
|
Layout.minimumWidth: 250
|
||||||
|
onActivated: console.log("Selected stop bits", currentText, model.get(currentIndex).value)
|
||||||
|
model: serialPortStopBitsModel
|
||||||
|
Component.onCompleted: {
|
||||||
|
for (var i = 0; i < serialPortStopBitsModel.count; i++) {
|
||||||
|
if (serialPortStopBitsModel.get(i).value === modbusRtuMaster.stopBits) {
|
||||||
|
currentIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: app.margins
|
||||||
|
Layout.rightMargin: app.margins
|
||||||
|
text: qsTr("Apply")
|
||||||
|
enabled: !root.busy
|
||||||
|
onClicked: {
|
||||||
|
var baudrate = serialPortBaudrateModel.get(baudRateComboBox.currentIndex).value
|
||||||
|
var parity = serialPortParityModel.get(parityComboBox.currentIndex).value
|
||||||
|
var dataBits = serialPortDataBitsModel.get(dataBitsComboBox.currentIndex).value
|
||||||
|
var stopBits = serialPortStopBitsModel.get(stopBitsComboBox.currentIndex).value
|
||||||
|
|
||||||
|
console.log("Reconfigure modbus RTU", modbusRtuMaster.modbusUuid, "with", serialPort.systemLocation, baudrate, parity, dataBits, stopBits)
|
||||||
|
d.reconfigureModbusRtuMaster(modbusRtuMaster.modbusUuid, serialPort.systemLocation, baudrate, parity, dataBits, stopBits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
366
nymea-app/ui/system/ModbusRtuSettingsPage.qml
Normal file
366
nymea-app/ui/system/ModbusRtuSettingsPage.qml
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2021, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
import QtQuick 2.8
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Controls.Material 2.1
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import "../components"
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
|
SettingsPageBase {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Modbus RTU")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
|
||||||
|
HeaderButton {
|
||||||
|
imageSource: "../images/add.svg"
|
||||||
|
text: qsTr("Add Modbus RTU master")
|
||||||
|
onClicked: pageStack.push(Qt.resolvedUrl("ModbusRtuAddMasterPage.qml"), {
|
||||||
|
modbusRtuManager: modbusRtuManager,
|
||||||
|
serialPortBaudrateModel: serialPortBaudrateModel,
|
||||||
|
serialPortParityModel: serialPortParityModel,
|
||||||
|
serialPortDataBitsModel: serialPortDataBitsModel,
|
||||||
|
serialPortStopBitsModel: serialPortStopBitsModel
|
||||||
|
})
|
||||||
|
enabled: modbusRtuManager.supported
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuManager {
|
||||||
|
id: modbusRtuManager
|
||||||
|
engine: _engine
|
||||||
|
|
||||||
|
function handleModbusError(error) {
|
||||||
|
var props = {};
|
||||||
|
switch (error) {
|
||||||
|
case "ModbusRtuErrorNoError":
|
||||||
|
return true;
|
||||||
|
case "ModbusRtuErrorNotAvailable":
|
||||||
|
props.text = qsTr("The serial port is not available any more.");
|
||||||
|
break;
|
||||||
|
case "ModbusRtuErrorNotSupported":
|
||||||
|
props.text = qsTr("Modbus is not supported on this platform.");
|
||||||
|
break;
|
||||||
|
case "ModbusRtuErrorHardwareNotFound":
|
||||||
|
props.text = qsTr("The modbus RTU hardware could not be found.");
|
||||||
|
break;
|
||||||
|
case "ModbusRtuErrorUuidNotFound":
|
||||||
|
props.text = qsTr("The selected modbus RTU master does not exist any more.");
|
||||||
|
break;
|
||||||
|
case "ModbusRtuErrorConnectionFailed":
|
||||||
|
props.text = qsTr("Unable to connect to the modbus RTU master.\n\nMaybe the hardware is already in use.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
props.errorCode = error;
|
||||||
|
}
|
||||||
|
var comp = Qt.createComponent("../components/ErrorDialog.qml")
|
||||||
|
var popup = comp.createObject(app, props)
|
||||||
|
popup.open();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPageSectionHeader {
|
||||||
|
text: qsTr("Modbus RTU masters")
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: serialPortBaudrateModel
|
||||||
|
ListElement { value: 9600; text: qsTr("9600 Bd") }
|
||||||
|
ListElement { value: 14400; text: qsTr("14400 Bd") }
|
||||||
|
ListElement { value: 19200; text: qsTr("19200 Bd") }
|
||||||
|
ListElement { value: 38400; text: qsTr("38400 Bd") }
|
||||||
|
ListElement { value: 57600; text: qsTr("57600 Bd") }
|
||||||
|
ListElement { value: 115200; text: qsTr("115200 Bd") }
|
||||||
|
ListElement { value: 128000; text: qsTr("128000 Bd") }
|
||||||
|
ListElement { value: 230400; text: qsTr("230400 Bd") }
|
||||||
|
ListElement { value: 256000; text: qsTr("256000 Bd") }
|
||||||
|
|
||||||
|
function getText(baudrate) {
|
||||||
|
for (var index = 0; index < serialPortBaudrateModel.count; index++) {
|
||||||
|
if (serialPortBaudrateModel.get(index).value === baudrate) {
|
||||||
|
return serialPortBaudrateModel.get(index).text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qsTr("Unknown baud rate")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: serialPortParityModel
|
||||||
|
ListElement { value: SerialPort.SerialPortParityNoParity; text: qsTr("No parity") }
|
||||||
|
ListElement { value: SerialPort.SerialPortParityEvenParity; text: qsTr("Even parity") }
|
||||||
|
ListElement { value: SerialPort.SerialPortParityOddParity; text: qsTr("Odd parity") }
|
||||||
|
ListElement { value: SerialPort.SerialPortParitySpaceParity; text: qsTr("Space parity") }
|
||||||
|
ListElement { value: SerialPort.SerialPortParityMarkParity; text: qsTr("Mark parity") }
|
||||||
|
|
||||||
|
function getText(parity) {
|
||||||
|
for (var index = 0; index < serialPortParityModel.count; index++) {
|
||||||
|
if (serialPortParityModel.get(index).value === parity) {
|
||||||
|
return serialPortParityModel.get(index).text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qsTr("Unknown parity")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: serialPortDataBitsModel
|
||||||
|
ListElement { value: SerialPort.SerialPortDataBitsData5; text: qsTr("5 data bits") }
|
||||||
|
ListElement { value: SerialPort.SerialPortDataBitsData6; text: qsTr("6 data bits") }
|
||||||
|
ListElement { value: SerialPort.SerialPortDataBitsData7; text: qsTr("7 data bits") }
|
||||||
|
ListElement { value: SerialPort.SerialPortDataBitsData8; text: qsTr("8 data bits") }
|
||||||
|
|
||||||
|
function getText(dataBits) {
|
||||||
|
for (var index = 0; index < serialPortDataBitsModel.count; index++) {
|
||||||
|
if (serialPortDataBitsModel.get(index).value === dataBits) {
|
||||||
|
return serialPortDataBitsModel.get(index).text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qsTr("Unknown data bits")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: serialPortStopBitsModel
|
||||||
|
ListElement { value: SerialPort.SerialPortStopBitsOneStop; text: qsTr("One stop bit") }
|
||||||
|
ListElement { value: SerialPort.SerialPortStopBitsOneAndHalfStop; text: qsTr("One and a half stop bits") }
|
||||||
|
ListElement { value: SerialPort.SerialPortStopBitsTwoStop; text: qsTr("Two stop bits") }
|
||||||
|
|
||||||
|
function getText(stopBits) {
|
||||||
|
for (var index = 0; index < serialPortStopBitsModel.count; index++) {
|
||||||
|
if (serialPortStopBitsModel.get(index).value === stopBits) {
|
||||||
|
return serialPortStopBitsModel.get(index).text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qsTr("Unknown stop bits")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: qsTr("In this section you can configure system wide modbus RTU master connections which can be used in different plugins.")
|
||||||
|
visible: modbusRtuManager.supported
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: qsTr("There are no modbus RTU masters set up yet.")
|
||||||
|
visible: modbusRtuManager.modbusRtuMasters.count === 0 && modbusRtuManager.supported
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: app.margins; Layout.rightMargin: app.margins
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: qsTr("Modbus RTU is not supported on this platorm.")
|
||||||
|
visible: !modbusRtuManager.supported
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modbus RTU masters
|
||||||
|
Repeater {
|
||||||
|
enabled: modbusRtuManager.supported
|
||||||
|
model: modbusRtuManager.modbusRtuMasters
|
||||||
|
delegate: NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
iconName: "../images/modbus.svg"
|
||||||
|
text: model.serialPort + " " + model.baudrate
|
||||||
|
subText: model.connected ? qsTr("Connected") : qsTr("Disconnected")
|
||||||
|
onClicked: pageStack.push(modbusDetailsComponent, { modbusRtuManager: modbusRtuManager, modbusRtuMaster: modbusRtuManager.modbusRtuMasters.get(index) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: modbusDetailsComponent
|
||||||
|
|
||||||
|
SettingsPageBase {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property ModbusRtuManager modbusRtuManager
|
||||||
|
property ModbusRtuMaster modbusRtuMaster
|
||||||
|
|
||||||
|
busy: d.pendingCommandId !== -1
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Modbus RTU master")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
|
||||||
|
HeaderButton {
|
||||||
|
imageSource: "../images/delete.svg"
|
||||||
|
text: qsTr("Remove modbus RTU master")
|
||||||
|
enabled: modbusRtuManager.supported
|
||||||
|
onClicked: {
|
||||||
|
var dialog = removeModbusMasterDialogComponent.createObject(app, {modbusRtuMaster: root.modbusRtuMaster})
|
||||||
|
dialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: removeModbusMasterDialogComponent
|
||||||
|
|
||||||
|
MeaDialog {
|
||||||
|
id: removeModbusMasterDialog
|
||||||
|
|
||||||
|
property ModbusRtuMaster modbusRtuMaster
|
||||||
|
|
||||||
|
headerIcon: "../images/modbus.svg"
|
||||||
|
title: qsTr("Remove modbus RTU master")
|
||||||
|
text: qsTr("Are you sure you want to remove this modbus RTU master?")
|
||||||
|
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Please note that all related things will stop working until you assign a new modbus RTU master to them.")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
d.removeModbusRtuMaster(modbusRtuMaster.modbusUuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
property int pendingCommandId: -1
|
||||||
|
|
||||||
|
function removeModbusRtuMaster(modbusUuid) {
|
||||||
|
d.pendingCommandId = root.modbusRtuManager.removeModbusRtuMaster(modbusUuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root.modbusRtuManager
|
||||||
|
onRemoveModbusRtuMasterReply: {
|
||||||
|
if (commandId === d.pendingCommandId) {
|
||||||
|
d.pendingCommandId = -1
|
||||||
|
if (modbusRtuManager.handleModbusError(error)) {
|
||||||
|
// FIXME: the page does not work if I pop the page here
|
||||||
|
//pageStack.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsPageSectionHeader {
|
||||||
|
text: qsTr("Information")
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("UUID")
|
||||||
|
subText: modbusRtuMaster ? modbusRtuMaster.modbusUuid : ""
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("System location")
|
||||||
|
subText: modbusRtuMaster ? modbusRtuMaster.serialPort : ""
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Connection status")
|
||||||
|
subText: modbusRtuMaster && modbusRtuMaster.connected ? qsTr("Connected") : qsTr("Disconnected")
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Baud rate")
|
||||||
|
subText: modbusRtuMaster ? serialPortBaudrateModel.getText(modbusRtuMaster.baudrate) : ""
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Parity")
|
||||||
|
subText: modbusRtuMaster ? serialPortParityModel.getText(modbusRtuMaster.parity) : ""
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Data bits")
|
||||||
|
subText: modbusRtuMaster ? serialPortDataBitsModel.getText(modbusRtuMaster.dataBits) : ""
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Stop bits")
|
||||||
|
subText: modbusRtuMaster ? serialPortStopBitsModel.getText(modbusRtuMaster.stopBits) : ""
|
||||||
|
progressive: false
|
||||||
|
prominentSubText: false
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: reconfigureButton
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: app.margins
|
||||||
|
Layout.rightMargin: app.margins
|
||||||
|
text: qsTr("Reconfigure")
|
||||||
|
enabled: !root.busy
|
||||||
|
onClicked: pageStack.push(Qt.resolvedUrl("ModbusRtuReconfigureMasterPage.qml"), {
|
||||||
|
modbusRtuManager: modbusRtuManager,
|
||||||
|
modbusRtuMaster: root.modbusRtuMaster,
|
||||||
|
serialPortBaudrateModel: serialPortBaudrateModel,
|
||||||
|
serialPortParityModel: serialPortParityModel,
|
||||||
|
serialPortDataBitsModel: serialPortDataBitsModel,
|
||||||
|
serialPortStopBitsModel: serialPortStopBitsModel
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user