Add modbus RTU hardware resource support

This commit is contained in:
Simon Stürz 2021-02-15 12:32:44 +01:00 committed by Michael Zanetti
parent ab65f1a484
commit 64d24d4e74
21 changed files with 2508 additions and 0 deletions

View File

@ -130,6 +130,9 @@
#include "applogcontroller.h"
#include "tagwatcher.h"
#include "appdata.h"
#include "modbus/modbusrtumanager.h"
#include "modbus/modbusrtumasters.h"
#include "types/serialportsproxy.h"
#include <QtQml/qqml.h>
@ -312,6 +315,13 @@ void registerQmlTypes() {
qmlRegisterUncreatableType<ZigbeeNetwork>(uri, 1, 0, "ZigbeeNetwork", "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");
qmlRegisterUncreatableType<NetworkDevices>(uri, 1, 0, "NetworkDevices", "Get it from NetworkManager");
qmlRegisterUncreatableType<WiredNetworkDevices>(uri, 1, 0, "WiredNetworkDevices", "Get it from NetworkManager");

View File

@ -26,6 +26,12 @@ SOURCES += \
$${PWD}/logging.cpp \
$${PWD}/applogcontroller.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}/engine.cpp \
$${PWD}/models/barseriesadapter.cpp \
@ -174,6 +180,12 @@ HEADERS += \
$${PWD}/logging.h \
$${PWD}/applogcontroller.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}/engine.h \
$${PWD}/models/barseriesadapter.h \

View 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 &notification)
{
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 &params)
{
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 &params)
{
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 &params)
{
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 &params)
{
qDebug() << "Remove modbus RTU master response" << commandId << params;
emit removeModbusRtuMasterReply(commandId, params.value("modbusError").toString());
}
void ModbusRtuManager::reconfigureModbusRtuMasterResponse(int commandId, const QVariantMap &params)
{
qDebug() << "Reconfigure modbus RTU master response" << commandId << params;
emit reconfigureModbusRtuMasterReply(commandId, params.value("modbusError").toString());
}

View 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 &notification);
Q_INVOKABLE void getSerialPortsResponse(int commandId, const QVariantMap &params);
Q_INVOKABLE void getModbusRtuMastersResponse(int commandId, const QVariantMap &params);
Q_INVOKABLE void addModbusRtuMasterResponse(int commandId, const QVariantMap &params);
Q_INVOKABLE void removeModbusRtuMasterResponse(int commandId, const QVariantMap &params);
Q_INVOKABLE void reconfigureModbusRtuMasterResponse(int commandId, const QVariantMap &params);
};
#endif // MODBUSRTUMANAGER_H

View 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);
}

View 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

View 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;
}

View 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

View 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;
}

View 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

View 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);
}

View 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

View 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;
}

View 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

View File

@ -259,5 +259,6 @@
<file>ui/images/nymea-splash.svg</file>
<file>ui/images/cleaning-robot.svg</file>
<file>ui/images/chart.svg</file>
<file>ui/images/modbus.svg</file>
</qresource>
</RCC>

View File

@ -246,5 +246,8 @@
<file>ui/mainviews/dashboard/DashboardSceneDelegate.qml</file>
<file>ui/mainviews/dashboard/DashboardWebViewDelegate.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>
</RCC>

View File

@ -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 {
Layout.fillWidth: true
Material.elevation: layout.isGrid ? 1 : 0

View 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

View 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)
}
}
}
}
}

View 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)
}
}
}
}
}

View 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
})
}
}
}
}