Merge PR #390: Modbus RTU hardware resource
This commit is contained in:
commit
8ff3d8766c
2
debian/control
vendored
2
debian/control
vendored
@ -26,6 +26,8 @@ Build-Depends: debhelper (>= 9.0.0),
|
|||||||
qttools5-dev-tools,
|
qttools5-dev-tools,
|
||||||
qtconnectivity5-dev,
|
qtconnectivity5-dev,
|
||||||
qtdeclarative5-dev,
|
qtdeclarative5-dev,
|
||||||
|
libqt5serialport5-dev,
|
||||||
|
libqt5serialbus5-dev
|
||||||
|
|
||||||
Package: nymea
|
Package: nymea
|
||||||
Architecture: any
|
Architecture: any
|
||||||
|
|||||||
@ -0,0 +1,124 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 "modbusrtuhardwareresourceimplementation.h"
|
||||||
|
#include "loggingcategories.h"
|
||||||
|
#include "nymeasettings.h"
|
||||||
|
#include "hardware/modbus/modbusrtumanager.h"
|
||||||
|
|
||||||
|
NYMEA_LOGGING_CATEGORY(dcModbusRtuResource, "ModbusRtuResource")
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
ModbusRtuHardwareResourceImplementation::ModbusRtuHardwareResourceImplementation(ModbusRtuManager *modbusRtuManager, QObject *parent) :
|
||||||
|
ModbusRtuHardwareResource(parent),
|
||||||
|
m_modbusRtuManager(modbusRtuManager)
|
||||||
|
{
|
||||||
|
connect(m_modbusRtuManager, &ModbusRtuManager::modbusRtuMasterAdded, this, [=](ModbusRtuMaster *modbusRtuMaster){
|
||||||
|
emit modbusRtuMasterAdded(modbusRtuMaster->modbusUuid());
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_modbusRtuManager, &ModbusRtuManager::modbusRtuMasterRemoved, this, [=](ModbusRtuMaster *modbusRtuMaster){
|
||||||
|
emit modbusRtuMasterRemoved(modbusRtuMaster->modbusUuid());
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_modbusRtuManager, &ModbusRtuManager::modbusRtuMasterChanged, this, [=](ModbusRtuMaster *modbusRtuMaster){
|
||||||
|
emit modbusRtuMasterChanged(modbusRtuMaster->modbusUuid());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ModbusRtuMaster *> ModbusRtuHardwareResourceImplementation::modbusRtuMasters() const
|
||||||
|
{
|
||||||
|
return m_modbusRtuManager->modbusRtuMasters();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuHardwareResourceImplementation::hasModbusRtuMaster(const QUuid &modbusUuid) const
|
||||||
|
{
|
||||||
|
return m_modbusRtuManager->hasModbusRtuMaster(modbusUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuMaster *ModbusRtuHardwareResourceImplementation::getModbusRtuMaster(const QUuid &modbusUuid) const
|
||||||
|
{
|
||||||
|
return m_modbusRtuManager->getModbusRtuMaster(modbusUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuHardwareResourceImplementation::available() const
|
||||||
|
{
|
||||||
|
return m_modbusRtuManager->supported();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuHardwareResourceImplementation::enabled() const
|
||||||
|
{
|
||||||
|
return m_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuHardwareResourceImplementation::enable()
|
||||||
|
{
|
||||||
|
qCWarning(dcModbusRtuResource()) << "Enable hardware resource. Not implemented yet.";
|
||||||
|
|
||||||
|
// TODO: enable all modbus clients
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuHardwareResourceImplementation::disable()
|
||||||
|
{
|
||||||
|
qCWarning(dcModbusRtuResource()) << "Disable hardware resource. Not implemented yet.";
|
||||||
|
|
||||||
|
// TODO: disable all modbus clients
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuHardwareResourceImplementation::setEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
qCDebug(dcModbusRtuResource()) << "Set" << (enabled ? "enabled" : "disabled");
|
||||||
|
if (m_enabled && enabled) {
|
||||||
|
qCDebug(dcModbusRtuResource()) << "Already enabled.";
|
||||||
|
return;
|
||||||
|
} else if (!m_enabled && !enabled) {
|
||||||
|
qCDebug(dcModbusRtuResource()) << "Already disabled.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
if (enabled) {
|
||||||
|
success = enable();
|
||||||
|
} else {
|
||||||
|
success = disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
m_enabled = enabled;
|
||||||
|
emit enabledChanged(m_enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 MODBUSRTUHARDWARERESOURCEIMPLEMENTATION_H
|
||||||
|
#define MODBUSRTUHARDWARERESOURCEIMPLEMENTATION_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "hardware/modbus/modbusrtumanager.h"
|
||||||
|
#include "hardware/modbus/modbusrtumaster.h"
|
||||||
|
#include "hardware/modbus/modbusrtuhardwareresource.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
class ModbusRtuHardwareResourceImplementation : public ModbusRtuHardwareResource
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ModbusRtuHardwareResourceImplementation(ModbusRtuManager *modbusRtuManager, QObject *parent = nullptr);
|
||||||
|
~ModbusRtuHardwareResourceImplementation() override = default;
|
||||||
|
|
||||||
|
QList<ModbusRtuMaster *> modbusRtuMasters() const override;
|
||||||
|
bool hasModbusRtuMaster(const QUuid &modbusUuid) const override;
|
||||||
|
ModbusRtuMaster *getModbusRtuMaster(const QUuid &modbusUuid) const override;
|
||||||
|
|
||||||
|
bool available() const override;
|
||||||
|
bool enabled() const override;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
bool enable();
|
||||||
|
bool disable();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setEnabled(bool enabled) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ModbusRtuManager *m_modbusRtuManager = nullptr;
|
||||||
|
bool m_available = false;
|
||||||
|
bool m_enabled = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MODBUSRTUHARDWARERESOURCEIMPLEMENTATION_H
|
||||||
270
libnymea-core/hardware/modbus/modbusrtumanager.cpp
Normal file
270
libnymea-core/hardware/modbus/modbusrtumanager.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 "nymeasettings.h"
|
||||||
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
|
#include "modbusrtumasterimpl.h"
|
||||||
|
#include "hardware/serialport/serialportmonitor.h"
|
||||||
|
|
||||||
|
NYMEA_LOGGING_CATEGORY(dcModbusRtu, "ModbusRtu")
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
ModbusRtuManager::ModbusRtuManager(SerialPortMonitor *serialPortMonitor, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_serialPortMonitor(serialPortMonitor)
|
||||||
|
{
|
||||||
|
// Load uart configurations
|
||||||
|
loadRtuMasters();
|
||||||
|
|
||||||
|
connect(m_serialPortMonitor, &SerialPortMonitor::serialPortAdded, this, [=](const QSerialPortInfo &serialPortInfo){
|
||||||
|
qCDebug(dcModbusRtu()) << "Serial port added. Verify modbus RTU masters...";
|
||||||
|
|
||||||
|
// Check if we have to reconnect any modbus RTU masters
|
||||||
|
foreach (ModbusRtuMaster *modbusMaster, m_modbusRtuMasters.values()) {
|
||||||
|
ModbusRtuMasterImpl *modbusMasterImpl = qobject_cast<ModbusRtuMasterImpl *>(modbusMaster);
|
||||||
|
|
||||||
|
// Try only to reconnect if the added serial port matches a disconnected modbus RTU master
|
||||||
|
if (!modbusMasterImpl->connected() && modbusMasterImpl->serialPort() == serialPortInfo.systemLocation()) {
|
||||||
|
if (!modbusMasterImpl->connectDevice()) {
|
||||||
|
qCDebug(dcModbusRtu()) << "Reconnect" << modbusMaster << "failed.";
|
||||||
|
} else {
|
||||||
|
qCDebug(dcModbusRtu()) << "Reconnected" << modbusMaster << "successfully.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Try to connect the modbus rtu masters
|
||||||
|
foreach (ModbusRtuMaster *modbusMaster, m_modbusRtuMasters.values()) {
|
||||||
|
ModbusRtuMasterImpl *modbusMasterImpl = qobject_cast<ModbusRtuMasterImpl *>(modbusMaster);
|
||||||
|
if (!modbusMasterImpl->connectDevice()) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Failed to connect modbus RTU master. Could not connect to" << modbusMaster;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPortMonitor *ModbusRtuManager::serialPortMonitor() const
|
||||||
|
{
|
||||||
|
return m_serialPortMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuManager::supported() const
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ModbusRtuMaster *> ModbusRtuManager::modbusRtuMasters() const
|
||||||
|
{
|
||||||
|
return m_modbusRtuMasters.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuManager::hasModbusRtuMaster(const QUuid &modbusUuid) const
|
||||||
|
{
|
||||||
|
return m_modbusRtuMasters.value(modbusUuid) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuMaster *ModbusRtuManager::getModbusRtuMaster(const QUuid &modbusUuid)
|
||||||
|
{
|
||||||
|
if (hasModbusRtuMaster(modbusUuid)) {
|
||||||
|
return m_modbusRtuMasters.value(modbusUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<ModbusRtuManager::ModbusRtuError, QUuid> ModbusRtuManager::addNewModbusRtuMaster(const QString &serialPort, qint32 baudrate, QSerialPort::Parity parity, QSerialPort::DataBits dataBits, QSerialPort::StopBits stopBits, int numberOfRetries, int timeout)
|
||||||
|
{
|
||||||
|
if (!supported()) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Cannot add new modbus RTU master because serialbus is not suppoerted on this platform.";
|
||||||
|
return QPair<ModbusRtuManager::ModbusRtuError, QUuid>(ModbusRtuErrorNotSupported, QUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the serial port exists
|
||||||
|
if (!m_serialPortMonitor->serialPortAvailable(serialPort)) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Cannot add new modbus RTU master because the serial port" << serialPort << "is not available any more";
|
||||||
|
return QPair<ModbusRtuManager::ModbusRtuError, QUuid>(ModbusRtuErrorHardwareNotFound, QUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid modbusUuid = QUuid::createUuid();
|
||||||
|
ModbusRtuMasterImpl *modbusMaster = new ModbusRtuMasterImpl(modbusUuid, serialPort, baudrate, parity, dataBits, stopBits, numberOfRetries, timeout, this);
|
||||||
|
ModbusRtuMaster *modbus = qobject_cast<ModbusRtuMaster *>(modbusMaster);
|
||||||
|
qCDebug(dcModbusRtu()) << "Adding new" << modbus << parity << dataBits << stopBits;
|
||||||
|
|
||||||
|
// Note: We could add the modbus master event if a connection is currently not possible...not sure yet
|
||||||
|
if (!modbusMaster->connectDevice()) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Failed to add new modbus RTU master. Could not connect to" << modbus << parity << dataBits << stopBits;
|
||||||
|
|
||||||
|
modbusMaster->deleteLater();
|
||||||
|
return QPair<ModbusRtuError, QUuid>(ModbusRtuErrorConnectionFailed, QUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
addModbusRtuMasterInternally(modbusMaster);
|
||||||
|
saveModbusRtuMaster(modbus);
|
||||||
|
|
||||||
|
return QPair<ModbusRtuError, QUuid>(ModbusRtuErrorNoError, modbusUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuManager::ModbusRtuError ModbusRtuManager::reconfigureModbusRtuMaster(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, QSerialPort::Parity parity, QSerialPort::DataBits dataBits, QSerialPort::StopBits stopBits, int numberOfRetries, int timeout)
|
||||||
|
{
|
||||||
|
if (!supported()) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Cannot reconfigure modbus RTU master because serialbus is not suppoerted on this platform.";
|
||||||
|
return ModbusRtuErrorNotSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_modbusRtuMasters.contains(modbusUuid)) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Could not reconfigure modbus RTU master because no resource could be found with uuid" << modbusUuid.toString();
|
||||||
|
return ModbusRtuErrorUuidNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take the modbus masters
|
||||||
|
ModbusRtuMasterImpl *modbusMaster = qobject_cast<ModbusRtuMasterImpl *>(m_modbusRtuMasters.value(modbusUuid));
|
||||||
|
|
||||||
|
// Disconnect
|
||||||
|
modbusMaster->disconnectDevice();
|
||||||
|
|
||||||
|
// Reconfigure
|
||||||
|
modbusMaster->setSerialPort(serialPort);
|
||||||
|
modbusMaster->setBaudrate(baudrate);
|
||||||
|
modbusMaster->setParity(parity);
|
||||||
|
modbusMaster->setDataBits(dataBits);
|
||||||
|
modbusMaster->setStopBits(stopBits);
|
||||||
|
modbusMaster->setNumberOfRetries(numberOfRetries);
|
||||||
|
modbusMaster->setTimeout(timeout);
|
||||||
|
|
||||||
|
// Connect again
|
||||||
|
if (!modbusMaster->connectDevice()) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Failed to connect to" << m_modbusRtuMasters.value(modbusUuid);
|
||||||
|
// FIXME: check if we should reload the old configuration
|
||||||
|
emit modbusRtuMasterChanged(m_modbusRtuMasters.value(modbusUuid));
|
||||||
|
return ModbusRtuErrorConnectionFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit modbusRtuMasterChanged(m_modbusRtuMasters.value(modbusUuid));
|
||||||
|
|
||||||
|
qCDebug(dcModbusRtu()) << "Reconfigured successfully" << m_modbusRtuMasters.value(modbusUuid);
|
||||||
|
saveModbusRtuMaster(modbusMaster);
|
||||||
|
return ModbusRtuErrorNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuManager::ModbusRtuError ModbusRtuManager::removeModbusRtuMaster(const QUuid &modbusUuid)
|
||||||
|
{
|
||||||
|
if (!supported()) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Cannot remove modbus RTU master because serialbus is not suppoerted on this platform.";
|
||||||
|
return ModbusRtuErrorNotSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_modbusRtuMasters.contains(modbusUuid)) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Could not remove modbus RTU master because no resource could be found with uuid" << modbusUuid.toString();
|
||||||
|
return ModbusRtuErrorUuidNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuMasterImpl *modbusMaster = qobject_cast<ModbusRtuMasterImpl *>(m_modbusRtuMasters.take(modbusUuid));
|
||||||
|
qCDebug(dcModbusRtu()) << "Removing modbus RTU master" << qobject_cast<ModbusRtuMaster *>(modbusMaster);
|
||||||
|
modbusMaster->disconnectDevice();
|
||||||
|
modbusMaster->deleteLater();
|
||||||
|
|
||||||
|
// Remove from settings
|
||||||
|
NymeaSettings settings(NymeaSettings::SettingsRoleModbusRtu);
|
||||||
|
settings.beginGroup("ModbusRtuMasters");
|
||||||
|
settings.beginGroup(modbusUuid.toString());
|
||||||
|
settings.remove("");
|
||||||
|
settings.endGroup(); // modbusUuid
|
||||||
|
settings.endGroup(); // ModbusRtuMasters
|
||||||
|
|
||||||
|
emit modbusRtuMasterRemoved(modbusMaster);
|
||||||
|
|
||||||
|
return ModbusRtuErrorNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::loadRtuMasters()
|
||||||
|
{
|
||||||
|
if (!supported())
|
||||||
|
return;
|
||||||
|
|
||||||
|
NymeaSettings settings(NymeaSettings::SettingsRoleModbusRtu);
|
||||||
|
qCDebug(dcModbusRtu()) << "Loading modbus RTU resources from" << settings.fileName();
|
||||||
|
settings.beginGroup("ModbusRtuMasters");
|
||||||
|
foreach (const QString &uuidString, settings.childGroups()) {
|
||||||
|
settings.beginGroup(uuidString);
|
||||||
|
QString serialPort = settings.value("serialPort").toString();
|
||||||
|
quint32 baudrate = settings.value("baudrate").toUInt();
|
||||||
|
QSerialPort::Parity parity = static_cast<QSerialPort::Parity>(settings.value("parity").toInt());
|
||||||
|
QSerialPort::DataBits dataBits = static_cast<QSerialPort::DataBits>(settings.value("dataBits").toInt());
|
||||||
|
QSerialPort::StopBits stopBits = static_cast<QSerialPort::StopBits>(settings.value("stopBits").toInt());
|
||||||
|
int numberOfRetries = settings.value("numberOfRetries").toInt();
|
||||||
|
int timeout = settings.value("timeout").toInt();
|
||||||
|
settings.endGroup(); // uuid
|
||||||
|
|
||||||
|
addModbusRtuMasterInternally(new ModbusRtuMasterImpl(QUuid(uuidString), serialPort, baudrate, parity, dataBits, stopBits, numberOfRetries, timeout, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.endGroup(); // ModbusRtuMasters
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::saveModbusRtuMaster(ModbusRtuMaster *modbusRtuMaster)
|
||||||
|
{
|
||||||
|
NymeaSettings settings(NymeaSettings::SettingsRoleModbusRtu);
|
||||||
|
qCDebug(dcModbusRtu()) << "Saving" << modbusRtuMaster << "to" << settings.fileName();
|
||||||
|
settings.beginGroup("ModbusRtuMasters");
|
||||||
|
settings.beginGroup(modbusRtuMaster->modbusUuid().toString());
|
||||||
|
settings.setValue("serialPort", modbusRtuMaster->serialPort());
|
||||||
|
settings.setValue("baudrate", modbusRtuMaster->baudrate());
|
||||||
|
settings.setValue("parity", static_cast<int>(modbusRtuMaster->parity()));
|
||||||
|
settings.setValue("dataBits", static_cast<int>(modbusRtuMaster->dataBits()));
|
||||||
|
settings.setValue("stopBits", static_cast<int>(modbusRtuMaster->stopBits()));
|
||||||
|
settings.setValue("numberOfRetries", modbusRtuMaster->numberOfRetries());
|
||||||
|
settings.setValue("timeout", modbusRtuMaster->timeout());
|
||||||
|
settings.endGroup(); // uuid
|
||||||
|
settings.endGroup(); // ModbusRtuMasters
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuManager::addModbusRtuMasterInternally(ModbusRtuMasterImpl *modbusRtuMaster)
|
||||||
|
{
|
||||||
|
ModbusRtuMaster *modbusMaster = qobject_cast<ModbusRtuMaster *>(modbusRtuMaster);
|
||||||
|
qCDebug(dcModbusRtu()) << "Adding" << modbusMaster;
|
||||||
|
m_modbusRtuMasters.insert(modbusMaster->modbusUuid(), modbusMaster);
|
||||||
|
|
||||||
|
connect(modbusMaster, &ModbusRtuMaster::connectedChanged, this, [=](bool connected){
|
||||||
|
qCDebug(dcModbusRtu()) << modbusMaster << (connected ? "connected" : "disconnected");
|
||||||
|
emit modbusRtuMasterChanged(modbusMaster);
|
||||||
|
});
|
||||||
|
|
||||||
|
emit modbusRtuMasterAdded(modbusMaster);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
95
libnymea-core/hardware/modbus/modbusrtumanager.h
Normal file
95
libnymea-core/hardware/modbus/modbusrtumanager.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 <QHash>
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "hardware/modbus/modbusrtumaster.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
class SerialPortMonitor;
|
||||||
|
class ModbusRtuMasterImpl;
|
||||||
|
|
||||||
|
class ModbusRtuManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum ModbusRtuError {
|
||||||
|
ModbusRtuErrorNoError,
|
||||||
|
ModbusRtuErrorNotAvailable,
|
||||||
|
ModbusRtuErrorUuidNotFound,
|
||||||
|
ModbusRtuErrorHardwareNotFound,
|
||||||
|
ModbusRtuErrorResourceBusy,
|
||||||
|
ModbusRtuErrorNotSupported,
|
||||||
|
ModbusRtuErrorInvalidTimeoutValue,
|
||||||
|
ModbusRtuErrorConnectionFailed
|
||||||
|
};
|
||||||
|
Q_ENUM(ModbusRtuError)
|
||||||
|
|
||||||
|
explicit ModbusRtuManager(SerialPortMonitor *serialPortMonitor, QObject *parent = nullptr);
|
||||||
|
~ModbusRtuManager() = default;
|
||||||
|
|
||||||
|
SerialPortMonitor *serialPortMonitor() const;
|
||||||
|
|
||||||
|
bool supported() const;
|
||||||
|
|
||||||
|
QList<ModbusRtuMaster *> modbusRtuMasters() const;
|
||||||
|
bool hasModbusRtuMaster(const QUuid &modbusUuid) const;
|
||||||
|
ModbusRtuMaster *getModbusRtuMaster(const QUuid &modbusUuid);
|
||||||
|
|
||||||
|
QPair<ModbusRtuError, QUuid> addNewModbusRtuMaster(const QString &serialPort, qint32 baudrate, QSerialPort::Parity parity, QSerialPort::DataBits dataBits, QSerialPort::StopBits stopBits, int numberOfRetries, int timeout);
|
||||||
|
ModbusRtuError reconfigureModbusRtuMaster(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, QSerialPort::Parity parity, QSerialPort::DataBits dataBits, QSerialPort::StopBits stopBits, int numberOfRetries, int timeout);
|
||||||
|
ModbusRtuError removeModbusRtuMaster(const QUuid &modbusUuid);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void modbusRtuMasterAdded(ModbusRtuMaster *modbusRtuMaster);
|
||||||
|
void modbusRtuMasterRemoved(ModbusRtuMaster *modbusRtuMaster);
|
||||||
|
void modbusRtuMasterChanged(ModbusRtuMaster *modbusRtuMaster);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHash<QUuid, ModbusRtuMaster *> m_modbusRtuMasters;
|
||||||
|
SerialPortMonitor *m_serialPortMonitor = nullptr;
|
||||||
|
|
||||||
|
void loadRtuMasters();
|
||||||
|
void saveModbusRtuMaster(ModbusRtuMaster *modbusRtuMaster);
|
||||||
|
|
||||||
|
void addModbusRtuMasterInternally(ModbusRtuMasterImpl *modbusRtuMaster);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MODBUSRTUMANAGER_H
|
||||||
553
libnymea-core/hardware/modbus/modbusrtumasterimpl.cpp
Normal file
553
libnymea-core/hardware/modbus/modbusrtumasterimpl.cpp
Normal file
@ -0,0 +1,553 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 "modbusrtumasterimpl.h"
|
||||||
|
#include "modbusrtureplyimpl.h"
|
||||||
|
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
#include <QtSerialBus/QModbusReply>
|
||||||
|
#include <QtSerialBus/QModbusDataUnit>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcModbusRtu)
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
ModbusRtuMasterImpl::ModbusRtuMasterImpl(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, QSerialPort::Parity parity, QSerialPort::DataBits dataBits, QSerialPort::StopBits stopBits, int numberOfRetries, int timeout, QObject *parent) :
|
||||||
|
ModbusRtuMaster(parent),
|
||||||
|
m_modbusUuid(modbusUuid),
|
||||||
|
m_serialPort(serialPort),
|
||||||
|
m_baudrate(baudrate),
|
||||||
|
m_parity(parity),
|
||||||
|
m_dataBits(dataBits),
|
||||||
|
m_stopBits(stopBits),
|
||||||
|
m_numberOfRetries(numberOfRetries),
|
||||||
|
m_timeout(timeout)
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
m_modbus = new QModbusRtuSerialMaster(this);
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialPortNameParameter, m_serialPort);
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baudrate);
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, m_dataBits);
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, m_stopBits);
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialParityParameter, m_parity);
|
||||||
|
m_modbus->setNumberOfRetries(m_numberOfRetries);
|
||||||
|
m_modbus->setTimeout(m_timeout);
|
||||||
|
|
||||||
|
connect(m_modbus, &QModbusTcpClient::stateChanged, this, [=](QModbusDevice::State state){
|
||||||
|
qCDebug(dcModbusRtu()) << "Connection state changed" << m_modbusUuid.toString() << m_serialPort << state;
|
||||||
|
if (state == QModbusDevice::ConnectedState) {
|
||||||
|
if (m_connected != true) {
|
||||||
|
m_connected = true;
|
||||||
|
emit connectedChanged(m_connected);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (m_connected != false) {
|
||||||
|
m_connected = false;
|
||||||
|
emit connectedChanged(m_connected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_modbus, &QModbusRtuSerialMaster::errorOccurred, this, [=](QModbusDevice::Error error){
|
||||||
|
qCWarning(dcModbusRtu()) << "Error occured for modbus RTU master" << m_modbusUuid.toString() << m_serialPort << error << m_modbus->errorString();
|
||||||
|
if (error != QModbusDevice::NoError) {
|
||||||
|
disconnectDevice();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid ModbusRtuMasterImpl::modbusUuid() const
|
||||||
|
{
|
||||||
|
return m_modbusUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ModbusRtuMasterImpl::serialPort() const
|
||||||
|
{
|
||||||
|
return m_serialPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasterImpl::setSerialPort(const QString &serialPort)
|
||||||
|
{
|
||||||
|
if (m_serialPort == serialPort)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_serialPort = serialPort;
|
||||||
|
emit serialPortChanged(m_serialPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint32 ModbusRtuMasterImpl::baudrate() const
|
||||||
|
{
|
||||||
|
return m_baudrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasterImpl::setBaudrate(qint32 baudrate)
|
||||||
|
{
|
||||||
|
if (m_baudrate == baudrate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_baudrate = baudrate;
|
||||||
|
emit baudrateChanged(m_baudrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSerialPort::Parity ModbusRtuMasterImpl::parity() const
|
||||||
|
{
|
||||||
|
return m_parity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasterImpl::setParity(QSerialPort::Parity parity)
|
||||||
|
{
|
||||||
|
if (m_parity == parity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_parity = parity;
|
||||||
|
emit parityChanged(m_parity);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSerialPort::DataBits ModbusRtuMasterImpl::dataBits() const
|
||||||
|
{
|
||||||
|
return m_dataBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasterImpl::setDataBits(QSerialPort::DataBits dataBits)
|
||||||
|
{
|
||||||
|
if (m_dataBits == dataBits)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_dataBits = dataBits;
|
||||||
|
emit dataBitsChanged(m_dataBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSerialPort::StopBits ModbusRtuMasterImpl::stopBits()
|
||||||
|
{
|
||||||
|
return m_stopBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasterImpl::setStopBits(QSerialPort::StopBits stopBits)
|
||||||
|
{
|
||||||
|
if (m_stopBits == stopBits)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_stopBits = stopBits;
|
||||||
|
emit stopBitsChanged(m_stopBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuMasterImpl::connected() const
|
||||||
|
{
|
||||||
|
return m_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuMasterImpl::connectDevice()
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialPortNameParameter, m_serialPort);
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_baudrate);
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, m_dataBits);
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, m_stopBits);
|
||||||
|
m_modbus->setConnectionParameter(QModbusDevice::SerialParityParameter, m_parity);
|
||||||
|
m_modbus->setNumberOfRetries(m_numberOfRetries);
|
||||||
|
m_modbus->setTimeout(m_timeout);
|
||||||
|
return m_modbus->connectDevice();
|
||||||
|
#else
|
||||||
|
qCWarning(dcModbusRtu()) << "Modbus is not available on this platform.";
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasterImpl::disconnectDevice()
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
m_modbus->disconnectDevice();
|
||||||
|
#else
|
||||||
|
qCWarning(dcModbusRtu()) << "Modbus is not available on this platform.";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModbusRtuMasterImpl::numberOfRetries() const
|
||||||
|
{
|
||||||
|
return m_numberOfRetries;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasterImpl::setNumberOfRetries(int numberOfRetries)
|
||||||
|
{
|
||||||
|
if (m_numberOfRetries == numberOfRetries)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_numberOfRetries = numberOfRetries;
|
||||||
|
emit numberOfRetriesChanged(m_numberOfRetries);
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
m_modbus->setNumberOfRetries(m_numberOfRetries);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModbusRtuMasterImpl::timeout() const
|
||||||
|
{
|
||||||
|
return m_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuMasterImpl::setTimeout(int timeout)
|
||||||
|
{
|
||||||
|
if (m_timeout == timeout)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_timeout = timeout;
|
||||||
|
emit timeoutChanged(m_timeout);
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
m_modbus->setTimeout(m_timeout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuReply *ModbusRtuMasterImpl::readCoil(int slaveAddress, int registerAddress, quint16 size)
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
// Create the reply for the plugin
|
||||||
|
ModbusRtuReplyImpl *reply = new ModbusRtuReplyImpl(slaveAddress, registerAddress, this);
|
||||||
|
connect(reply, &ModbusRtuReplyImpl::finished, reply, &ModbusRtuReplyImpl::deleteLater);
|
||||||
|
|
||||||
|
// Create the actual modbus lib reply
|
||||||
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, registerAddress, size);
|
||||||
|
QModbusReply *modbusReply = m_modbus->sendReadRequest(request, slaveAddress);
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::finished, modbusReply, [=](){
|
||||||
|
modbusReply->deleteLater();
|
||||||
|
|
||||||
|
// Fill common reply data
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
|
||||||
|
// Check if the reply finished with an error
|
||||||
|
if (modbusReply->error() != QModbusDevice::NoError) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Read coil request finished with error" << modbusReply->error() << modbusReply->errorString();
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the data unit and set reply result
|
||||||
|
const QModbusDataUnit unit = modbusReply->result();
|
||||||
|
reply->setResult(unit.values());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::errorOccurred, modbusReply, [=](QModbusDevice::Error error){
|
||||||
|
qCWarning(dcModbusRtu()) << "Read coil request finished with error" << error << modbusReply->errorString();
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
return qobject_cast<ModbusRtuReply *>(reply);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(slaveAddress)
|
||||||
|
Q_UNUSED(registerAddress)
|
||||||
|
Q_UNUSED(size)
|
||||||
|
qCWarning(dcModbusRtu()) << "Modbus is not available on this platform.";
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuReply *ModbusRtuMasterImpl::readDiscreteInput(int slaveAddress, int registerAddress, quint16 size)
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
// Create the reply for the plugin
|
||||||
|
ModbusRtuReplyImpl *reply = new ModbusRtuReplyImpl(slaveAddress, registerAddress, this);
|
||||||
|
connect(reply, &ModbusRtuReplyImpl::finished, reply, &ModbusRtuReplyImpl::deleteLater);
|
||||||
|
|
||||||
|
// Create the actual modbus lib reply
|
||||||
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::DiscreteInputs, registerAddress, size);
|
||||||
|
QModbusReply *modbusReply = m_modbus->sendReadRequest(request, slaveAddress);
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::finished, modbusReply, [=](){
|
||||||
|
modbusReply->deleteLater();
|
||||||
|
|
||||||
|
// Fill common reply data
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
|
||||||
|
// Check if the reply finished with an error
|
||||||
|
if (modbusReply->error() != QModbusDevice::NoError) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Read descrete inputs request finished with error" << modbusReply->error() << modbusReply->errorString();
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the data unit and set reply result
|
||||||
|
const QModbusDataUnit unit = modbusReply->result();
|
||||||
|
reply->setResult(unit.values());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::errorOccurred, modbusReply, [=](QModbusDevice::Error error){
|
||||||
|
qCWarning(dcModbusRtu()) << "Read descrete inputs request finished with error" << error << modbusReply->errorString();
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
return qobject_cast<ModbusRtuReply *>(reply);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(slaveAddress)
|
||||||
|
Q_UNUSED(registerAddress)
|
||||||
|
Q_UNUSED(size)
|
||||||
|
qCWarning(dcModbusRtu()) << "Modbus is not available on this platform.";
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuReply *ModbusRtuMasterImpl::readInputRegister(int slaveAddress, int registerAddress, quint16 size)
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
// Create the reply for the plugin
|
||||||
|
ModbusRtuReplyImpl *reply = new ModbusRtuReplyImpl(slaveAddress, registerAddress, this);
|
||||||
|
connect(reply, &ModbusRtuReplyImpl::finished, reply, &ModbusRtuReplyImpl::deleteLater);
|
||||||
|
|
||||||
|
// Create the actual modbus lib reply
|
||||||
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::InputRegisters, registerAddress, size);
|
||||||
|
QModbusReply *modbusReply = m_modbus->sendReadRequest(request, slaveAddress);
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::finished, modbusReply, [=](){
|
||||||
|
modbusReply->deleteLater();
|
||||||
|
|
||||||
|
// Fill common reply data
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
|
||||||
|
// Check if the reply finished with an error
|
||||||
|
if (modbusReply->error() != QModbusDevice::NoError) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Read input registers request finished with error" << modbusReply->error() << modbusReply->errorString();
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the data unit and set reply result
|
||||||
|
const QModbusDataUnit unit = modbusReply->result();
|
||||||
|
reply->setResult(unit.values());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::errorOccurred, modbusReply, [=](QModbusDevice::Error error){
|
||||||
|
qCWarning(dcModbusRtu()) << "Read input registers request finished with error" << error << modbusReply->errorString();
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
return qobject_cast<ModbusRtuReply *>(reply);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(slaveAddress)
|
||||||
|
Q_UNUSED(registerAddress)
|
||||||
|
Q_UNUSED(size)
|
||||||
|
qCWarning(dcModbusRtu()) << "Modbus is not available on this platform.";
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuReply *ModbusRtuMasterImpl::readHoldingRegister(int slaveAddress, int registerAddress, quint16 size)
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
// Create the reply for the plugin
|
||||||
|
ModbusRtuReplyImpl *reply = new ModbusRtuReplyImpl(slaveAddress, registerAddress, this);
|
||||||
|
connect(reply, &ModbusRtuReplyImpl::finished, reply, &ModbusRtuReplyImpl::deleteLater);
|
||||||
|
|
||||||
|
// Create the actual modbus lib reply
|
||||||
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, registerAddress, size);
|
||||||
|
QModbusReply *modbusReply = m_modbus->sendReadRequest(request, slaveAddress);
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::finished, modbusReply, [=](){
|
||||||
|
modbusReply->deleteLater();
|
||||||
|
|
||||||
|
// Fill common reply data
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
|
||||||
|
// Check if the reply finished with an error
|
||||||
|
if (modbusReply->error() != QModbusDevice::NoError) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Read holding registers request finished with error" << modbusReply->error() << modbusReply->errorString();
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the data unit and set reply result
|
||||||
|
const QModbusDataUnit unit = modbusReply->result();
|
||||||
|
reply->setResult(unit.values());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::errorOccurred, modbusReply, [=](QModbusDevice::Error error){
|
||||||
|
qCWarning(dcModbusRtu()) << "Read holding registers request finished with error" << error << modbusReply->errorString();
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
return qobject_cast<ModbusRtuReply *>(reply);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(slaveAddress)
|
||||||
|
Q_UNUSED(registerAddress)
|
||||||
|
Q_UNUSED(size)
|
||||||
|
qCWarning(dcModbusRtu()) << "Modbus is not available on this platform.";
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuReply *ModbusRtuMasterImpl::writeCoils(int slaveAddress, int registerAddress, const QVector<quint16> &values)
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
// Create the reply for the plugin
|
||||||
|
ModbusRtuReplyImpl *reply = new ModbusRtuReplyImpl(slaveAddress, registerAddress, this);
|
||||||
|
connect(reply, &ModbusRtuReplyImpl::finished, reply, &ModbusRtuReplyImpl::deleteLater);
|
||||||
|
|
||||||
|
// Create the actual modbus lib reply
|
||||||
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::Coils, registerAddress, values.length());
|
||||||
|
request.setValues(values);
|
||||||
|
|
||||||
|
QModbusReply *modbusReply = m_modbus->sendWriteRequest(request, slaveAddress);
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::finished, modbusReply, [=](){
|
||||||
|
modbusReply->deleteLater();
|
||||||
|
|
||||||
|
// Fill common reply data
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
|
||||||
|
// Check if the reply finished with an error
|
||||||
|
if (modbusReply->error() != QModbusDevice::NoError) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Read coil request finished with error" << modbusReply->error() << modbusReply->errorString();
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the data unit and set reply result
|
||||||
|
const QModbusDataUnit unit = modbusReply->result();
|
||||||
|
reply->setResult(unit.values());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::errorOccurred, modbusReply, [=](QModbusDevice::Error error){
|
||||||
|
qCWarning(dcModbusRtu()) << "Read coil request finished with error" << error << modbusReply->errorString();
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
return qobject_cast<ModbusRtuReply *>(reply);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(slaveAddress)
|
||||||
|
Q_UNUSED(registerAddress)
|
||||||
|
Q_UNUSED(values)
|
||||||
|
qCWarning(dcModbusRtu()) << "Modbus is not available on this platform.";
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModbusRtuReply *ModbusRtuMasterImpl::writeHoldingRegisters(int slaveAddress, int registerAddress, const QVector<quint16> &values)
|
||||||
|
{
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
// Create the reply for the plugin
|
||||||
|
ModbusRtuReplyImpl *reply = new ModbusRtuReplyImpl(slaveAddress, registerAddress, this);
|
||||||
|
connect(reply, &ModbusRtuReplyImpl::finished, reply, &ModbusRtuReplyImpl::deleteLater);
|
||||||
|
|
||||||
|
// Create the actual modbus lib reply
|
||||||
|
QModbusDataUnit request = QModbusDataUnit(QModbusDataUnit::RegisterType::HoldingRegisters, registerAddress, values.length());
|
||||||
|
request.setValues(values);
|
||||||
|
|
||||||
|
QModbusReply *modbusReply = m_modbus->sendWriteRequest(request, slaveAddress);
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::finished, modbusReply, [=](){
|
||||||
|
modbusReply->deleteLater();
|
||||||
|
|
||||||
|
// Fill common reply data
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
|
||||||
|
// Check if the reply finished with an error
|
||||||
|
if (modbusReply->error() != QModbusDevice::NoError) {
|
||||||
|
qCWarning(dcModbusRtu()) << "Read coil request finished with error" << modbusReply->error() << modbusReply->errorString();
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the data unit and set reply result
|
||||||
|
const QModbusDataUnit unit = modbusReply->result();
|
||||||
|
reply->setResult(unit.values());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusReply, &QModbusReply::errorOccurred, modbusReply, [=](QModbusDevice::Error error){
|
||||||
|
qCWarning(dcModbusRtu()) << "Read coil request finished with error" << error << modbusReply->errorString();
|
||||||
|
reply->setFinished(true);
|
||||||
|
reply->setError(static_cast<ModbusRtuReply::Error>(modbusReply->error()));
|
||||||
|
reply->setErrorString(modbusReply->errorString());
|
||||||
|
emit reply->errorOccurred(reply->error());
|
||||||
|
emit reply->finished();
|
||||||
|
});
|
||||||
|
|
||||||
|
return qobject_cast<ModbusRtuReply *>(reply);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(slaveAddress)
|
||||||
|
Q_UNUSED(registerAddress)
|
||||||
|
Q_UNUSED(values)
|
||||||
|
qCWarning(dcModbusRtu()) << "Modbus is not available on this platform.";
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
108
libnymea-core/hardware/modbus/modbusrtumasterimpl.h
Normal file
108
libnymea-core/hardware/modbus/modbusrtumasterimpl.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 MODBUSRTUMASTERIMPL_H
|
||||||
|
#define MODBUSRTUMASTERIMPL_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSerialPort>
|
||||||
|
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
#include <QtSerialBus/QtSerialBus>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "hardware/modbus/modbusrtumaster.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
class ModbusRtuMasterImpl : public ModbusRtuMaster
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ModbusRtuMasterImpl(const QUuid &modbusUuid, const QString &serialPort, qint32 baudrate, QSerialPort::Parity parity, QSerialPort::DataBits dataBits, QSerialPort::StopBits stopBits, int numberOfRetries, int timeout, QObject *parent = nullptr);
|
||||||
|
~ModbusRtuMasterImpl() override = default;
|
||||||
|
|
||||||
|
QUuid modbusUuid() const override;
|
||||||
|
|
||||||
|
QString serialPort() const override;
|
||||||
|
void setSerialPort(const QString &serialPort);
|
||||||
|
|
||||||
|
qint32 baudrate() const override;
|
||||||
|
void setBaudrate(qint32 baudrate);
|
||||||
|
|
||||||
|
QSerialPort::Parity parity() const override;
|
||||||
|
void setParity(QSerialPort::Parity parity);
|
||||||
|
|
||||||
|
QSerialPort::DataBits dataBits() const override;
|
||||||
|
void setDataBits(QSerialPort::DataBits dataBits);
|
||||||
|
|
||||||
|
QSerialPort::StopBits stopBits() override;
|
||||||
|
void setStopBits(QSerialPort::StopBits stopBits);
|
||||||
|
|
||||||
|
bool connected() const override;
|
||||||
|
|
||||||
|
bool connectDevice();
|
||||||
|
void disconnectDevice();
|
||||||
|
|
||||||
|
int numberOfRetries() const override;
|
||||||
|
void setNumberOfRetries(int numberOfRetries);
|
||||||
|
|
||||||
|
int timeout() const override;
|
||||||
|
void setTimeout(int timeout);
|
||||||
|
|
||||||
|
// Requests
|
||||||
|
ModbusRtuReply *readCoil(int slaveAddress, int registerAddress, quint16 size = 1) override;
|
||||||
|
ModbusRtuReply *readDiscreteInput(int slaveAddress, int registerAddress, quint16 size = 1) override;
|
||||||
|
ModbusRtuReply *readInputRegister(int slaveAddress, int registerAddress, quint16 size = 1) override;
|
||||||
|
ModbusRtuReply *readHoldingRegister(int slaveAddress, int registerAddress, quint16 size = 1) override;
|
||||||
|
|
||||||
|
ModbusRtuReply *writeCoils(int slaveAddress, int registerAddress, const QVector<quint16> &values) override;
|
||||||
|
ModbusRtuReply *writeHoldingRegisters(int slaveAddress, int registerAddress, const QVector<quint16> &values) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QUuid m_modbusUuid;
|
||||||
|
bool m_connected = false;
|
||||||
|
|
||||||
|
#ifdef WITH_QTSERIALBUS
|
||||||
|
QModbusRtuSerialMaster *m_modbus = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QString m_serialPort;
|
||||||
|
qint32 m_baudrate;
|
||||||
|
QSerialPort::Parity m_parity;
|
||||||
|
QSerialPort::DataBits m_dataBits;
|
||||||
|
QSerialPort::StopBits m_stopBits;
|
||||||
|
int m_numberOfRetries = 3;
|
||||||
|
int m_timeout = 100;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MODBUSRTUMASTERIMPL_H
|
||||||
93
libnymea-core/hardware/modbus/modbusrtureplyimpl.cpp
Normal file
93
libnymea-core/hardware/modbus/modbusrtureplyimpl.cpp
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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 "modbusrtureplyimpl.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
ModbusRtuReplyImpl::ModbusRtuReplyImpl(int slaveAddress, int registerAddress, QObject *parent) :
|
||||||
|
ModbusRtuReply(parent),
|
||||||
|
m_slaveAddress(slaveAddress),
|
||||||
|
m_registerAddress(registerAddress)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModbusRtuReplyImpl::isFinished() const
|
||||||
|
{
|
||||||
|
return m_finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuReplyImpl::setFinished(bool finished)
|
||||||
|
{
|
||||||
|
m_finished = finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModbusRtuReplyImpl::slaveAddress() const
|
||||||
|
{
|
||||||
|
return m_slaveAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModbusRtuReplyImpl::registerAddress() const
|
||||||
|
{
|
||||||
|
return m_registerAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ModbusRtuReplyImpl::errorString() const
|
||||||
|
{
|
||||||
|
return m_errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuReplyImpl::setErrorString(const QString &errorString)
|
||||||
|
{
|
||||||
|
m_errorString = errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuReply::Error ModbusRtuReplyImpl::error() const
|
||||||
|
{
|
||||||
|
return m_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuReplyImpl::setError(ModbusRtuReply::Error error)
|
||||||
|
{
|
||||||
|
m_error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<quint16> ModbusRtuReplyImpl::result() const
|
||||||
|
{
|
||||||
|
return m_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModbusRtuReplyImpl::setResult(const QVector<quint16> &result)
|
||||||
|
{
|
||||||
|
m_result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
73
libnymea-core/hardware/modbus/modbusrtureplyimpl.h
Normal file
73
libnymea-core/hardware/modbus/modbusrtureplyimpl.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 MODBUSRTUREPLYIMPL_H
|
||||||
|
#define MODBUSRTUREPLYIMPL_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "hardware/modbus/modbusrtureply.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
class ModbusRtuReplyImpl : public ModbusRtuReply
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ModbusRtuReplyImpl(int slaveAddress, int registerAddress, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
bool isFinished() const override;
|
||||||
|
void setFinished(bool finished);
|
||||||
|
|
||||||
|
int slaveAddress() const override;
|
||||||
|
int registerAddress() const override;
|
||||||
|
|
||||||
|
QString errorString() const override;
|
||||||
|
void setErrorString(const QString &errorString);
|
||||||
|
|
||||||
|
ModbusRtuReply::Error error() const override;
|
||||||
|
void setError(ModbusRtuReply::Error error);
|
||||||
|
|
||||||
|
QVector<quint16> result() const override;
|
||||||
|
void setResult(const QVector<quint16> &result);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_finished = false;
|
||||||
|
int m_slaveAddress;
|
||||||
|
int m_registerAddress;
|
||||||
|
Error m_error = UnknownError;
|
||||||
|
QString m_errorString;
|
||||||
|
QVector<quint16> m_result;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MODBUSRTUREPLYIMPL_H
|
||||||
189
libnymea-core/hardware/serialport/serialportmonitor.cpp
Normal file
189
libnymea-core/hardware/serialport/serialportmonitor.cpp
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 "serialportmonitor.h"
|
||||||
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
NYMEA_LOGGING_CATEGORY(dcSerialPortMonitor, "SerialPortMonitor")
|
||||||
|
|
||||||
|
SerialPortMonitor::SerialPortMonitor(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
// Read initially all tty devices
|
||||||
|
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
|
||||||
|
m_serialPorts.insert(serialPortInfo.systemLocation(), SerialPort(serialPortInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_UDEV
|
||||||
|
// Init udev
|
||||||
|
m_udev = udev_new();
|
||||||
|
if (!m_udev) {
|
||||||
|
qCWarning(dcSerialPortMonitor()) << "Could not initialize udev for the adapter monitor";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create udev monitor
|
||||||
|
m_monitor = udev_monitor_new_from_netlink(m_udev, "udev");
|
||||||
|
if (!m_monitor) {
|
||||||
|
qCWarning(dcSerialPortMonitor()) << "Could not initialize udev monitor.";
|
||||||
|
udev_unref(m_udev);
|
||||||
|
m_udev = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set monitor filter to tty subsystem
|
||||||
|
if (udev_monitor_filter_add_match_subsystem_devtype(m_monitor, "tty", nullptr) < 0) {
|
||||||
|
qCWarning(dcSerialPortMonitor()) << "Could not set subsystem device type filter to tty.";
|
||||||
|
udev_monitor_unref(m_monitor);
|
||||||
|
m_monitor = nullptr;
|
||||||
|
udev_unref(m_udev);
|
||||||
|
m_udev = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable the monitor
|
||||||
|
if (udev_monitor_enable_receiving(m_monitor) < 0) {
|
||||||
|
qCWarning(dcSerialPortMonitor()) << "Could not enable udev monitor.";
|
||||||
|
udev_monitor_unref(m_monitor);
|
||||||
|
m_monitor = nullptr;
|
||||||
|
udev_unref(m_udev);
|
||||||
|
m_udev = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create socket notifier for read
|
||||||
|
int socketDescriptor = udev_monitor_get_fd(m_monitor);
|
||||||
|
m_notifier = new QSocketNotifier(socketDescriptor, QSocketNotifier::Read, this);
|
||||||
|
connect(m_notifier, &QSocketNotifier::activated, this, [this, socketDescriptor](int socket){
|
||||||
|
// Make sure the socket matches
|
||||||
|
if (socketDescriptor != socket) {
|
||||||
|
qCWarning(dcSerialPortMonitor()) << "Socket handles do not match. socket != socketdescriptor";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create udev device
|
||||||
|
udev_device *device = udev_monitor_receive_device(m_monitor);
|
||||||
|
if (!device) {
|
||||||
|
qCWarning(dcSerialPortMonitor()) << "Got socket sotification but could not read device information.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString actionString = QString::fromLatin1(udev_device_get_action(device));
|
||||||
|
QString systemPath = QString::fromLatin1(udev_device_get_property_value(device,"DEVNAME"));
|
||||||
|
QString manufacturerString = QString::fromLatin1(udev_device_get_property_value(device,"ID_VENDOR_ENC"));
|
||||||
|
QString descriptionString = QString::fromLatin1(udev_device_get_property_value(device,"ID_MODEL_ENC"));
|
||||||
|
QString serialNumberString = QString::fromLatin1(udev_device_get_property_value(device, "ID_SERIAL_SHORT"));
|
||||||
|
|
||||||
|
// Clean udev device
|
||||||
|
udev_device_unref(device);
|
||||||
|
|
||||||
|
// Make sure we know the action
|
||||||
|
if (actionString.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (actionString == "add") {
|
||||||
|
qCDebug(dcSerialPortMonitor()) << "[+]" << systemPath << serialNumberString << manufacturerString << descriptionString;
|
||||||
|
if (!m_serialPorts.contains(systemPath)) {
|
||||||
|
// Get the serial port info and add it internally
|
||||||
|
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
|
||||||
|
if (serialPortInfo.systemLocation() == systemPath) {
|
||||||
|
addSerialPortInternally(SerialPort(serialPortInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionString == "remove") {
|
||||||
|
qCDebug(dcSerialPortMonitor()) << "[-]" << systemPath << serialNumberString << manufacturerString << descriptionString;
|
||||||
|
if (m_serialPorts.contains(systemPath)) {
|
||||||
|
SerialPort serialPort = m_serialPorts.take(systemPath);
|
||||||
|
qCDebug(dcSerialPortMonitor()) << "Removed" << serialPort.systemLocation();
|
||||||
|
emit serialPortRemoved(serialPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
qCDebug(dcSerialPortMonitor()) << "Serial port monitor enabled successfully";
|
||||||
|
foreach (const SerialPort &serialPort, m_serialPorts) {
|
||||||
|
qCDebug(dcSerialPortMonitor()) << "-" << serialPort.systemLocation() << serialPort.description();
|
||||||
|
}
|
||||||
|
m_notifier->setEnabled(true);
|
||||||
|
#else
|
||||||
|
m_timer = new QTimer(this);
|
||||||
|
m_timer->setInterval(5000);
|
||||||
|
m_timer->setSingleShot(false);
|
||||||
|
connect(m_timer, &QTimer::timeout, this, [=](){
|
||||||
|
QStringList availablePorts;
|
||||||
|
// Add a new adapter if not in the list already
|
||||||
|
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
|
||||||
|
availablePorts.append(serialPortInfo.systemLocation());
|
||||||
|
if (!m_serialPorts.keys().contains(serialPortInfo.systemLocation())) {
|
||||||
|
qCDebug(dcSerialPortMonitor()) << "[+]" << serialPortInfo.systemLocation() << serialPortInfo.manufacturer() << serialPortInfo.description();
|
||||||
|
addSerialPortInternally(SerialPort(serialPortInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove adapters no longer available
|
||||||
|
foreach (const QString &systemLocation, m_serialPorts.keys()) {
|
||||||
|
if (!availablePorts.contains(systemLocation)) {
|
||||||
|
SerialPort serialPortInfo = m_serialPorts.take(systemLocation);
|
||||||
|
qCDebug(dcSerialPortMonitor()) << "[-]" << serialPortInfo.systemLocation() << serialPortInfo.manufacturer() << serialPortInfo.description();
|
||||||
|
emit serialPortRemoved(serialPortInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_timer->start();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SerialPorts SerialPortMonitor::serialPorts() const
|
||||||
|
{
|
||||||
|
return m_serialPorts.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SerialPortMonitor::serialPortAvailable(const QString &systemLocation) const
|
||||||
|
{
|
||||||
|
return m_serialPorts.keys().contains(systemLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerialPortMonitor::addSerialPortInternally(const SerialPort &serialPort)
|
||||||
|
{
|
||||||
|
if (m_serialPorts.keys().contains(serialPort.systemLocation())) {
|
||||||
|
qCWarning(dcSerialPortMonitor()) << "Tried to add serial port but the port has alrady been added.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_serialPorts.insert(serialPort.systemLocation(), serialPort);
|
||||||
|
emit serialPortAdded(serialPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
145
libnymea-core/hardware/serialport/serialportmonitor.h
Normal file
145
libnymea-core/hardware/serialport/serialportmonitor.h
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 SERIALPORTMONITOR_H
|
||||||
|
#define SERIALPORTMONITOR_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QSerialPortInfo>
|
||||||
|
|
||||||
|
#ifdef WITH_UDEV
|
||||||
|
#include <QSocketNotifier>
|
||||||
|
#include <libudev.h>
|
||||||
|
#else
|
||||||
|
#include <QTimer>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
class SerialPort : public QSerialPortInfo {
|
||||||
|
Q_GADGET
|
||||||
|
Q_PROPERTY(QString systemLocation READ systemLocation)
|
||||||
|
Q_PROPERTY(QString manufacturer READ manufacturer)
|
||||||
|
Q_PROPERTY(QString description READ description)
|
||||||
|
Q_PROPERTY(QString serialNumber READ serialNumber)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
SerialPort() : QSerialPortInfo() { };
|
||||||
|
explicit SerialPort(const QSerialPortInfo &other) : QSerialPortInfo(other) { };
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class SerialPorts : public QList<SerialPort>
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
Q_PROPERTY(int count READ count)
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline SerialPorts() = default;
|
||||||
|
inline SerialPorts(const QList<SerialPort> &other) : QList<SerialPort>(other) { };
|
||||||
|
inline bool hasSerialPort(const QString &serialPort) {
|
||||||
|
for (int i = 0; i < count(); i++) {
|
||||||
|
if (at(i).systemLocation() == serialPort) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Q_INVOKABLE QVariant get(int index) const { return QVariant::fromValue(at(index)); };
|
||||||
|
inline Q_INVOKABLE void put(const QVariant &variant) { append(variant.value<SerialPort>()); };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SerialPortMonitor : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SerialPortMonitor(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
SerialPorts serialPorts() const;
|
||||||
|
bool serialPortAvailable(const QString &systemLocation) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void serialPortAdded(const SerialPort &serialPort);
|
||||||
|
void serialPortRemoved(const SerialPort &serialPort);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHash<QString, SerialPort> m_serialPorts;
|
||||||
|
|
||||||
|
void addSerialPortInternally(const SerialPort &serialPort);
|
||||||
|
|
||||||
|
#ifdef WITH_UDEV
|
||||||
|
struct udev *m_udev = nullptr;
|
||||||
|
struct udev_monitor *m_monitor = nullptr;
|
||||||
|
QSocketNotifier *m_notifier = nullptr;
|
||||||
|
#else
|
||||||
|
QTimer *m_timer = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(nymeaserver::SerialPort)
|
||||||
|
Q_DECLARE_METATYPE(nymeaserver::SerialPorts)
|
||||||
|
|
||||||
|
#endif // SERIALPORTMONITOR_H
|
||||||
@ -44,9 +44,12 @@
|
|||||||
#include "hardware/i2c/i2cmanagerimplementation.h"
|
#include "hardware/i2c/i2cmanagerimplementation.h"
|
||||||
#include "hardware/zigbee/zigbeehardwareresourceimplementation.h"
|
#include "hardware/zigbee/zigbeehardwareresourceimplementation.h"
|
||||||
|
|
||||||
|
#include "hardware/modbus/modbusrtumanager.h"
|
||||||
|
#include "hardware/modbus/modbusrtuhardwareresourceimplementation.h"
|
||||||
|
|
||||||
namespace nymeaserver {
|
namespace nymeaserver {
|
||||||
|
|
||||||
HardwareManagerImplementation::HardwareManagerImplementation(Platform *platform, MqttBroker *mqttBroker, ZigbeeManager *zigbeeManager, QObject *parent) :
|
HardwareManagerImplementation::HardwareManagerImplementation(Platform *platform, MqttBroker *mqttBroker, ZigbeeManager *zigbeeManager, ModbusRtuManager *modbusRtuManager, QObject *parent) :
|
||||||
HardwareManager(parent),
|
HardwareManager(parent),
|
||||||
m_platform(platform)
|
m_platform(platform)
|
||||||
{
|
{
|
||||||
@ -73,6 +76,8 @@ HardwareManagerImplementation::HardwareManagerImplementation(Platform *platform,
|
|||||||
|
|
||||||
m_zigbeeResource = new ZigbeeHardwareResourceImplementation(zigbeeManager, this);
|
m_zigbeeResource = new ZigbeeHardwareResourceImplementation(zigbeeManager, this);
|
||||||
|
|
||||||
|
m_modbusRtuResource = new ModbusRtuHardwareResourceImplementation(modbusRtuManager, this);
|
||||||
|
|
||||||
// Enable all the resources
|
// Enable all the resources
|
||||||
setResourceEnabled(m_pluginTimerManager, true);
|
setResourceEnabled(m_pluginTimerManager, true);
|
||||||
setResourceEnabled(m_radio433, true);
|
setResourceEnabled(m_radio433, true);
|
||||||
@ -142,6 +147,11 @@ ZigbeeHardwareResource *HardwareManagerImplementation::zigbeeResource()
|
|||||||
return m_zigbeeResource;
|
return m_zigbeeResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModbusRtuHardwareResource *HardwareManagerImplementation::modbusRtuResource()
|
||||||
|
{
|
||||||
|
return m_modbusRtuResource;
|
||||||
|
}
|
||||||
|
|
||||||
void HardwareManagerImplementation::thingsLoaded()
|
void HardwareManagerImplementation::thingsLoaded()
|
||||||
{
|
{
|
||||||
m_zigbeeResource->thingsLoaded();
|
m_zigbeeResource->thingsLoaded();
|
||||||
|
|||||||
@ -43,13 +43,15 @@ class Platform;
|
|||||||
class MqttBroker;
|
class MqttBroker;
|
||||||
class ZigbeeManager;
|
class ZigbeeManager;
|
||||||
class ZigbeeHardwareResourceImplementation;
|
class ZigbeeHardwareResourceImplementation;
|
||||||
|
class ModbusRtuManager;
|
||||||
|
class ModbusRtuHardwareResourceImplementation;
|
||||||
|
|
||||||
class HardwareManagerImplementation : public HardwareManager
|
class HardwareManagerImplementation : public HardwareManager
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit HardwareManagerImplementation(Platform *platform, MqttBroker *mqttBroker, ZigbeeManager *zigbeeManager, QObject *parent = nullptr);
|
explicit HardwareManagerImplementation(Platform *platform, MqttBroker *mqttBroker, ZigbeeManager *zigbeeManager, ModbusRtuManager *modbusRtuManager, QObject *parent = nullptr);
|
||||||
~HardwareManagerImplementation() override;
|
~HardwareManagerImplementation() override;
|
||||||
|
|
||||||
Radio433 *radio433() override;
|
Radio433 *radio433() override;
|
||||||
@ -61,6 +63,7 @@ public:
|
|||||||
MqttProvider *mqttProvider() override;
|
MqttProvider *mqttProvider() override;
|
||||||
I2CManager *i2cManager() override;
|
I2CManager *i2cManager() override;
|
||||||
ZigbeeHardwareResource *zigbeeResource() override;
|
ZigbeeHardwareResource *zigbeeResource() override;
|
||||||
|
ModbusRtuHardwareResource *modbusRtuResource() override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void thingsLoaded();
|
void thingsLoaded();
|
||||||
@ -79,6 +82,7 @@ private:
|
|||||||
MqttProvider *m_mqttProvider = nullptr;
|
MqttProvider *m_mqttProvider = nullptr;
|
||||||
I2CManager *m_i2cManager = nullptr;
|
I2CManager *m_i2cManager = nullptr;
|
||||||
ZigbeeHardwareResourceImplementation *m_zigbeeResource = nullptr;
|
ZigbeeHardwareResourceImplementation *m_zigbeeResource = nullptr;
|
||||||
|
ModbusRtuHardwareResourceImplementation *m_modbusRtuResource = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,6 +75,7 @@
|
|||||||
#include "systemhandler.h"
|
#include "systemhandler.h"
|
||||||
#include "usershandler.h"
|
#include "usershandler.h"
|
||||||
#include "zigbeehandler.h"
|
#include "zigbeehandler.h"
|
||||||
|
#include "modbusrtuhandler.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@ -599,6 +600,7 @@ void JsonRPCServerImplementation::setup()
|
|||||||
registerHandler(new SystemHandler(NymeaCore::instance()->platform(), this));
|
registerHandler(new SystemHandler(NymeaCore::instance()->platform(), this));
|
||||||
registerHandler(new UsersHandler(NymeaCore::instance()->userManager(), this));
|
registerHandler(new UsersHandler(NymeaCore::instance()->userManager(), this));
|
||||||
registerHandler(new ZigbeeHandler(NymeaCore::instance()->zigbeeManager(), this));
|
registerHandler(new ZigbeeHandler(NymeaCore::instance()->zigbeeManager(), this));
|
||||||
|
registerHandler(new ModbusRtuHandler(NymeaCore::instance()->modbusRtuManager(), this));
|
||||||
|
|
||||||
connect(NymeaCore::instance()->cloudManager(), &CloudManager::pairingReply, this, &JsonRPCServerImplementation::pairingFinished);
|
connect(NymeaCore::instance()->cloudManager(), &CloudManager::pairingReply, this, &JsonRPCServerImplementation::pairingFinished);
|
||||||
connect(NymeaCore::instance()->cloudManager(), &CloudManager::connectionStateChanged, this, &JsonRPCServerImplementation::onCloudConnectionStateChanged);
|
connect(NymeaCore::instance()->cloudManager(), &CloudManager::connectionStateChanged, this, &JsonRPCServerImplementation::onCloudConnectionStateChanged);
|
||||||
|
|||||||
286
libnymea-core/jsonrpc/modbusrtuhandler.cpp
Normal file
286
libnymea-core/jsonrpc/modbusrtuhandler.cpp
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 "modbusrtuhandler.h"
|
||||||
|
#include "hardware/modbus/modbusrtumanager.h"
|
||||||
|
#include "hardware/serialport/serialportmonitor.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
ModbusRtuHandler::ModbusRtuHandler(ModbusRtuManager *modbusRtuManager, QObject *parent) :
|
||||||
|
JsonHandler(parent),
|
||||||
|
m_modbusRtuManager(modbusRtuManager)
|
||||||
|
{
|
||||||
|
qRegisterMetaType<nymeaserver::SerialPort>();
|
||||||
|
registerEnum<ModbusRtuManager::ModbusRtuError>();
|
||||||
|
registerEnum<SerialPort::SerialPortParity>();
|
||||||
|
registerEnum<SerialPort::SerialPortStopBits>();
|
||||||
|
registerEnum<SerialPort::SerialPortDataBits>();
|
||||||
|
registerObject<SerialPort, SerialPorts>();
|
||||||
|
|
||||||
|
QVariantMap modbusRtuMasterDescription;
|
||||||
|
modbusRtuMasterDescription.insert("modbusUuid", enumValueName(Uuid));
|
||||||
|
modbusRtuMasterDescription.insert("connected", enumValueName(Bool));
|
||||||
|
modbusRtuMasterDescription.insert("serialPort", enumValueName(String));
|
||||||
|
modbusRtuMasterDescription.insert("baudrate", enumValueName(Uint));
|
||||||
|
modbusRtuMasterDescription.insert("parity", enumRef<SerialPort::SerialPortParity>());
|
||||||
|
modbusRtuMasterDescription.insert("stopBits", enumRef<SerialPort::SerialPortStopBits>());
|
||||||
|
modbusRtuMasterDescription.insert("dataBits", enumRef<SerialPort::SerialPortDataBits>());
|
||||||
|
modbusRtuMasterDescription.insert("numberOfRetries", enumValueName(Uint));
|
||||||
|
modbusRtuMasterDescription.insert("timeout", enumValueName(Uint));
|
||||||
|
|
||||||
|
registerObject("ModbusRtuMaster", modbusRtuMasterDescription);
|
||||||
|
|
||||||
|
QVariantMap params, returns;
|
||||||
|
QString description;
|
||||||
|
|
||||||
|
// GetSerialPorts
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
description = "Get the list of available serial ports from the host system.";
|
||||||
|
returns.insert("serialPorts", objectRef<SerialPorts>());
|
||||||
|
registerMethod("GetSerialPorts", description, params, returns);
|
||||||
|
|
||||||
|
// SerialPortAdded notification
|
||||||
|
params.clear();
|
||||||
|
description = "Emitted whenever a serial port has been added to the system.";
|
||||||
|
params.insert("serialPort", objectRef<SerialPort>());
|
||||||
|
registerNotification("SerialPortAdded", description, params);
|
||||||
|
|
||||||
|
// SerialPortRemoved notification
|
||||||
|
params.clear();
|
||||||
|
description = "Emitted whenever a serial port has been removed from the system.";
|
||||||
|
params.insert("serialPort", objectRef<SerialPort>());
|
||||||
|
registerNotification("SerialPortRemoved", description, params);
|
||||||
|
|
||||||
|
// GetModbusRtuMasters
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
description = "Get the list of configured modbus RTU masters.";
|
||||||
|
returns.insert("o:modbusRtuMasters", QVariantList() << objectRef("ModbusRtuMaster"));
|
||||||
|
returns.insert("modbusError", enumRef<ModbusRtuManager::ModbusRtuError>());
|
||||||
|
registerMethod("GetModbusRtuMasters", description, params, returns);
|
||||||
|
|
||||||
|
// ModbusRtuMasterAdded notification
|
||||||
|
params.clear();
|
||||||
|
description = "Emitted whenever a new modbus RTU master has been added to the system.";
|
||||||
|
params.insert("modbusRtuMaster", objectRef("ModbusRtuMaster"));
|
||||||
|
registerNotification("ModbusRtuMasterAdded", description, params);
|
||||||
|
|
||||||
|
// ModbusRtuMasterRemoved notification
|
||||||
|
params.clear();
|
||||||
|
description = "Emitted whenever a modbus RTU master has been removed from the system.";
|
||||||
|
params.insert("modbusUuid", enumValueName(Uuid));
|
||||||
|
registerNotification("ModbusRtuMasterRemoved", description, params);
|
||||||
|
|
||||||
|
// ModbusRtuMasterChanged notification
|
||||||
|
params.clear();
|
||||||
|
description = "Emitted whenever a modbus RTU master has been changed in the system.";
|
||||||
|
params.insert("modbusRtuMaster", objectRef("ModbusRtuMaster"));
|
||||||
|
registerNotification("ModbusRtuMasterChanged", description, params);
|
||||||
|
|
||||||
|
// AddModbusRtuMaster
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
description = "Add a new modbus RTU master with the given configuration. The timeout value is in milli seconds and the minimum value is 10 ms.";
|
||||||
|
params.insert("serialPort", enumValueName(String));
|
||||||
|
params.insert("baudrate", enumValueName(Uint));
|
||||||
|
params.insert("parity", enumRef<SerialPort::SerialPortParity>());
|
||||||
|
params.insert("dataBits", enumRef<SerialPort::SerialPortDataBits>());
|
||||||
|
params.insert("stopBits", enumRef<SerialPort::SerialPortStopBits>());
|
||||||
|
params.insert("numberOfRetries", enumValueName(Uint));
|
||||||
|
params.insert("timeout", enumValueName(Uint));
|
||||||
|
returns.insert("o:modbusUuid", enumValueName(Uuid));
|
||||||
|
returns.insert("modbusError", enumRef<ModbusRtuManager::ModbusRtuError>());
|
||||||
|
registerMethod("AddModbusRtuMaster", description, params, returns);
|
||||||
|
|
||||||
|
// RemoveModbusRtuMaster
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
description = "Remove the modbus RTU master with the given modbus UUID.";
|
||||||
|
params.insert("modbusUuid", enumValueName(Uuid));
|
||||||
|
returns.insert("modbusError", enumRef<ModbusRtuManager::ModbusRtuError>());
|
||||||
|
registerMethod("RemoveModbusRtuMaster", description, params, returns);
|
||||||
|
|
||||||
|
// ReconfigureModbusRtuMaster
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
description = "Reconfigure the modbus RTU master with the given UUID and configuration.";
|
||||||
|
params.insert("modbusUuid", enumValueName(Uuid));
|
||||||
|
params.insert("serialPort", enumValueName(String));
|
||||||
|
params.insert("baudrate", enumValueName(Uint));
|
||||||
|
params.insert("parity", enumRef<SerialPort::SerialPortParity>());
|
||||||
|
params.insert("dataBits", enumRef<SerialPort::SerialPortDataBits>());
|
||||||
|
params.insert("stopBits", enumRef<SerialPort::SerialPortStopBits>());
|
||||||
|
params.insert("numberOfRetries", enumValueName(Uint));
|
||||||
|
params.insert("timeout", enumValueName(Uint));
|
||||||
|
returns.insert("modbusError", enumRef<ModbusRtuManager::ModbusRtuError>());
|
||||||
|
registerMethod("ReconfigureModbusRtuMaster", description, params, returns);
|
||||||
|
|
||||||
|
// Serial port monitor
|
||||||
|
connect(modbusRtuManager->serialPortMonitor(), &SerialPortMonitor::serialPortAdded, this, [=](const SerialPort &serialPort){
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("serialPort", pack(serialPort));
|
||||||
|
emit SerialPortAdded(params);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusRtuManager->serialPortMonitor(), &SerialPortMonitor::serialPortRemoved, this, [=](const SerialPort &serialPort){
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("serialPort", pack(serialPort));
|
||||||
|
emit SerialPortRemoved(params);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modbus manager
|
||||||
|
connect(modbusRtuManager, &ModbusRtuManager::modbusRtuMasterAdded, this, [=](ModbusRtuMaster *modbusRtuMaster){
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("modbusRtuMaster", packModbusRtuMaster(modbusRtuMaster));
|
||||||
|
emit ModbusRtuMasterAdded(params);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusRtuManager, &ModbusRtuManager::modbusRtuMasterChanged, this, [=](ModbusRtuMaster *modbusRtuMaster){
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("modbusRtuMaster", packModbusRtuMaster(modbusRtuMaster));
|
||||||
|
emit ModbusRtuMasterChanged(params);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(modbusRtuManager, &ModbusRtuManager::modbusRtuMasterRemoved, this, [=](ModbusRtuMaster *modbusRtuMaster){
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert("modbusUuid", modbusRtuMaster->modbusUuid());
|
||||||
|
emit ModbusRtuMasterRemoved(params);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ModbusRtuHandler::name() const
|
||||||
|
{
|
||||||
|
return "ModbusRtu";
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonReply *ModbusRtuHandler::GetSerialPorts(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
Q_UNUSED(params)
|
||||||
|
|
||||||
|
QVariantMap returnMap;
|
||||||
|
QVariantList portList;
|
||||||
|
foreach (const SerialPort &serialPort, m_modbusRtuManager->serialPortMonitor()->serialPorts()) {
|
||||||
|
portList << pack(serialPort);
|
||||||
|
}
|
||||||
|
returnMap.insert("serialPorts", portList);
|
||||||
|
return createReply(returnMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonReply *ModbusRtuHandler::GetModbusRtuMasters(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
Q_UNUSED(params)
|
||||||
|
|
||||||
|
QVariantMap returnMap;
|
||||||
|
|
||||||
|
if (m_modbusRtuManager->supported()) {
|
||||||
|
QVariantList modbusList;
|
||||||
|
foreach (ModbusRtuMaster *modbusMaster, m_modbusRtuManager->modbusRtuMasters()) {
|
||||||
|
modbusList << packModbusRtuMaster(modbusMaster);
|
||||||
|
}
|
||||||
|
returnMap.insert("modbusRtuMasters", modbusList);
|
||||||
|
returnMap.insert("modbusError", enumValueName<ModbusRtuManager::ModbusRtuError>(ModbusRtuManager::ModbusRtuErrorNoError));
|
||||||
|
} else {
|
||||||
|
returnMap.insert("modbusError", enumValueName<ModbusRtuManager::ModbusRtuError>(ModbusRtuManager::ModbusRtuErrorNotSupported));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return createReply(returnMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonReply *ModbusRtuHandler::AddModbusRtuMaster(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
QString serialPort = params.value("serialPort").toString();
|
||||||
|
qint32 baudrate = params.value("baudrate").toUInt();
|
||||||
|
QSerialPort::Parity parity = static_cast<QSerialPort::Parity>(enumNameToValue<SerialPort::SerialPortParity>(params.value("parity").toString()));
|
||||||
|
QSerialPort::StopBits stopBits = static_cast<QSerialPort::StopBits>(enumNameToValue<SerialPort::SerialPortStopBits>(params.value("stopBits").toString()));
|
||||||
|
QSerialPort::DataBits dataBits = static_cast<QSerialPort::DataBits>(enumNameToValue<SerialPort::SerialPortDataBits>(params.value("dataBits").toString()));
|
||||||
|
uint numberOfRetries = params.value("numberOfRetries").toUInt();
|
||||||
|
uint timeout = params.value("timeout").toUInt();
|
||||||
|
|
||||||
|
QVariantMap returnMap;
|
||||||
|
if (timeout < 10) {
|
||||||
|
returnMap.insert("modbusError", enumValueName<ModbusRtuManager::ModbusRtuError>(ModbusRtuManager::ModbusRtuErrorInvalidTimeoutValue));
|
||||||
|
return createReply(returnMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<ModbusRtuManager::ModbusRtuError, QUuid> result = m_modbusRtuManager->addNewModbusRtuMaster(serialPort, baudrate, parity, dataBits, stopBits, numberOfRetries, timeout);
|
||||||
|
returnMap.insert("modbusError", enumValueName<ModbusRtuManager::ModbusRtuError>(result.first));
|
||||||
|
if (result.first == ModbusRtuManager::ModbusRtuErrorNoError) {
|
||||||
|
returnMap.insert("modbusUuid", result.second);
|
||||||
|
}
|
||||||
|
return createReply(returnMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonReply *ModbusRtuHandler::RemoveModbusRtuMaster(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
QUuid modbusUuid = params.value("modbusUuid").toUuid();
|
||||||
|
|
||||||
|
ModbusRtuManager::ModbusRtuError result = m_modbusRtuManager->removeModbusRtuMaster(modbusUuid);
|
||||||
|
QVariantMap returnMap;
|
||||||
|
returnMap.insert("modbusError", enumValueName<ModbusRtuManager::ModbusRtuError>(result));
|
||||||
|
return createReply(returnMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonReply *ModbusRtuHandler::ReconfigureModbusRtuMaster(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
QUuid modbusUuid = params.value("modbusUuid").toUuid();
|
||||||
|
QString serialPort = params.value("serialPort").toString();
|
||||||
|
qint32 baudrate = params.value("baudrate").toUInt();
|
||||||
|
QSerialPort::Parity parity = static_cast<QSerialPort::Parity>(enumNameToValue<SerialPort::SerialPortParity>(params.value("parity").toString()));
|
||||||
|
QSerialPort::StopBits stopBits = static_cast<QSerialPort::StopBits>(enumNameToValue<SerialPort::SerialPortStopBits>(params.value("stopBits").toString()));
|
||||||
|
QSerialPort::DataBits dataBits = static_cast<QSerialPort::DataBits>(enumNameToValue<SerialPort::SerialPortDataBits>(params.value("dataBits").toString()));
|
||||||
|
uint numberOfRetries = params.value("numberOfRetries").toUInt();
|
||||||
|
uint timeout = params.value("timeout").toUInt();
|
||||||
|
|
||||||
|
QVariantMap returnMap;
|
||||||
|
if (timeout < 10) {
|
||||||
|
returnMap.insert("modbusError", enumValueName<ModbusRtuManager::ModbusRtuError>(ModbusRtuManager::ModbusRtuErrorInvalidTimeoutValue));
|
||||||
|
return createReply(returnMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModbusRtuManager::ModbusRtuError result = m_modbusRtuManager->reconfigureModbusRtuMaster(modbusUuid, serialPort, baudrate, parity, dataBits, stopBits, numberOfRetries, timeout);
|
||||||
|
returnMap.insert("modbusError", enumValueName<ModbusRtuManager::ModbusRtuError>(result));
|
||||||
|
return createReply(returnMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariantMap ModbusRtuHandler::packModbusRtuMaster(ModbusRtuMaster *modbusRtuMaster)
|
||||||
|
{
|
||||||
|
QVariantMap modbusRtuMasterMap;
|
||||||
|
modbusRtuMasterMap.insert("modbusUuid", modbusRtuMaster->modbusUuid());
|
||||||
|
modbusRtuMasterMap.insert("connected", modbusRtuMaster->connected());
|
||||||
|
modbusRtuMasterMap.insert("serialPort", modbusRtuMaster->serialPort());
|
||||||
|
modbusRtuMasterMap.insert("baudrate", modbusRtuMaster->baudrate());
|
||||||
|
modbusRtuMasterMap.insert("parity", enumValueName<SerialPort::SerialPortParity>(static_cast<SerialPort::SerialPortParity>(modbusRtuMaster->parity())));
|
||||||
|
modbusRtuMasterMap.insert("stopBits", enumValueName<SerialPort::SerialPortStopBits>(static_cast<SerialPort::SerialPortStopBits>(modbusRtuMaster->stopBits())));
|
||||||
|
modbusRtuMasterMap.insert("dataBits", enumValueName<SerialPort::SerialPortDataBits>(static_cast<SerialPort::SerialPortDataBits>(modbusRtuMaster->dataBits())));
|
||||||
|
modbusRtuMasterMap.insert("numberOfRetries", modbusRtuMaster->numberOfRetries());
|
||||||
|
modbusRtuMasterMap.insert("timeout", modbusRtuMaster->timeout());
|
||||||
|
return modbusRtuMasterMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
74
libnymea-core/jsonrpc/modbusrtuhandler.h
Normal file
74
libnymea-core/jsonrpc/modbusrtuhandler.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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 MODBUSRTUHANDLER_H
|
||||||
|
#define MODBUSRTUHANDLER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "jsonrpc/jsonhandler.h"
|
||||||
|
#include "hardware/modbus/modbusrtumaster.h"
|
||||||
|
|
||||||
|
namespace nymeaserver {
|
||||||
|
|
||||||
|
class ModbusRtuManager;
|
||||||
|
|
||||||
|
class ModbusRtuHandler : public JsonHandler
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ModbusRtuHandler(ModbusRtuManager *modbusRtuManager, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QString name() const override;
|
||||||
|
|
||||||
|
Q_INVOKABLE JsonReply *GetSerialPorts(const QVariantMap ¶ms);
|
||||||
|
Q_INVOKABLE JsonReply *GetModbusRtuMasters(const QVariantMap ¶ms);
|
||||||
|
|
||||||
|
Q_INVOKABLE JsonReply *AddModbusRtuMaster(const QVariantMap ¶ms);
|
||||||
|
Q_INVOKABLE JsonReply *RemoveModbusRtuMaster(const QVariantMap ¶ms);
|
||||||
|
Q_INVOKABLE JsonReply *ReconfigureModbusRtuMaster(const QVariantMap ¶ms);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void SerialPortAdded(const QVariantMap ¶ms);
|
||||||
|
void SerialPortRemoved(const QVariantMap ¶ms);
|
||||||
|
|
||||||
|
void ModbusRtuMasterAdded(const QVariantMap ¶ms);
|
||||||
|
void ModbusRtuMasterRemoved(const QVariantMap ¶ms);
|
||||||
|
void ModbusRtuMasterChanged(const QVariantMap ¶ms);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ModbusRtuManager *m_modbusRtuManager = nullptr;
|
||||||
|
|
||||||
|
QVariantMap packModbusRtuMaster(ModbusRtuMaster *modbusRtuMaster);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MODBUSRTUHANDLER_H
|
||||||
@ -3,7 +3,7 @@ TARGET = nymea-core
|
|||||||
|
|
||||||
include(../nymea.pri)
|
include(../nymea.pri)
|
||||||
|
|
||||||
QT += bluetooth dbus qml sql websockets
|
QT += bluetooth dbus qml sql websockets serialport
|
||||||
INCLUDEPATH += $$top_srcdir/libnymea $$top_builddir
|
INCLUDEPATH += $$top_srcdir/libnymea $$top_builddir
|
||||||
LIBS += -L$$top_builddir/libnymea/ -lnymea -lssl -lcrypto
|
LIBS += -L$$top_builddir/libnymea/ -lnymea -lssl -lcrypto
|
||||||
|
|
||||||
@ -35,6 +35,27 @@ CONFIG(withoutpython) {
|
|||||||
CONFIG -= python
|
CONFIG -= python
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Qt serial bus module is officially available since Qt 5.8
|
||||||
|
# but not all platforms host the qt serialbus package.
|
||||||
|
# Let's check if the package exists, not the qt version
|
||||||
|
packagesExist(Qt5SerialBus) {
|
||||||
|
message("Building with QtSerialBus support.")
|
||||||
|
# Qt += serialbus
|
||||||
|
PKGCONFIG += Qt5SerialBus
|
||||||
|
DEFINES += WITH_QTSERIALBUS
|
||||||
|
} else {
|
||||||
|
message("Qt5SerialBus package not found. Building without QtSerialBus support.")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Note: udev is not available on all platforms
|
||||||
|
packagesExist(libudev) {
|
||||||
|
message("Building with udev support")
|
||||||
|
PKGCONFIG += libudev
|
||||||
|
DEFINES += WITH_UDEV
|
||||||
|
} else {
|
||||||
|
message("Building without udev support.")
|
||||||
|
}
|
||||||
|
|
||||||
target.path = $$[QT_INSTALL_LIBS]
|
target.path = $$[QT_INSTALL_LIBS]
|
||||||
INSTALLS += target
|
INSTALLS += target
|
||||||
|
|
||||||
@ -44,6 +65,7 @@ RESOURCES += $$top_srcdir/icons.qrc \
|
|||||||
|
|
||||||
|
|
||||||
HEADERS += nymeacore.h \
|
HEADERS += nymeacore.h \
|
||||||
|
hardware/serialport/serialportmonitor.h \
|
||||||
integrations/apikeysprovidersloader.h \
|
integrations/apikeysprovidersloader.h \
|
||||||
integrations/plugininfocache.h \
|
integrations/plugininfocache.h \
|
||||||
integrations/python/pyapikeystorage.h \
|
integrations/python/pyapikeystorage.h \
|
||||||
@ -55,6 +77,7 @@ HEADERS += nymeacore.h \
|
|||||||
integrations/thingmanagerimplementation.h \
|
integrations/thingmanagerimplementation.h \
|
||||||
integrations/translator.h \
|
integrations/translator.h \
|
||||||
experiences/experiencemanager.h \
|
experiences/experiencemanager.h \
|
||||||
|
jsonrpc/modbusrtuhandler.h \
|
||||||
jsonrpc/zigbeehandler.h \
|
jsonrpc/zigbeehandler.h \
|
||||||
ruleengine/ruleengine.h \
|
ruleengine/ruleengine.h \
|
||||||
ruleengine/rule.h \
|
ruleengine/rule.h \
|
||||||
@ -118,6 +141,10 @@ HEADERS += nymeacore.h \
|
|||||||
hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h \
|
hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h \
|
||||||
hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h \
|
hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h \
|
||||||
hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h \
|
hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h \
|
||||||
|
hardware/modbus/modbusrtuhardwareresourceimplementation.h \
|
||||||
|
hardware/modbus/modbusrtumanager.h \
|
||||||
|
hardware/modbus/modbusrtumasterimpl.h \
|
||||||
|
hardware/modbus/modbusrtureplyimpl.h \
|
||||||
hardware/network/networkaccessmanagerimpl.h \
|
hardware/network/networkaccessmanagerimpl.h \
|
||||||
hardware/network/upnp/upnpdiscoveryimplementation.h \
|
hardware/network/upnp/upnpdiscoveryimplementation.h \
|
||||||
hardware/network/upnp/upnpdiscoveryrequest.h \
|
hardware/network/upnp/upnpdiscoveryrequest.h \
|
||||||
@ -138,11 +165,13 @@ HEADERS += nymeacore.h \
|
|||||||
|
|
||||||
|
|
||||||
SOURCES += nymeacore.cpp \
|
SOURCES += nymeacore.cpp \
|
||||||
|
hardware/serialport/serialportmonitor.cpp \
|
||||||
integrations/apikeysprovidersloader.cpp \
|
integrations/apikeysprovidersloader.cpp \
|
||||||
integrations/plugininfocache.cpp \
|
integrations/plugininfocache.cpp \
|
||||||
integrations/thingmanagerimplementation.cpp \
|
integrations/thingmanagerimplementation.cpp \
|
||||||
integrations/translator.cpp \
|
integrations/translator.cpp \
|
||||||
experiences/experiencemanager.cpp \
|
experiences/experiencemanager.cpp \
|
||||||
|
jsonrpc/modbusrtuhandler.cpp \
|
||||||
jsonrpc/zigbeehandler.cpp \
|
jsonrpc/zigbeehandler.cpp \
|
||||||
ruleengine/ruleengine.cpp \
|
ruleengine/ruleengine.cpp \
|
||||||
ruleengine/rule.cpp \
|
ruleengine/rule.cpp \
|
||||||
@ -205,6 +234,10 @@ SOURCES += nymeacore.cpp \
|
|||||||
hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp \
|
hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp \
|
||||||
hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp \
|
hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp \
|
||||||
hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp \
|
hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp \
|
||||||
|
hardware/modbus/modbusrtuhardwareresourceimplementation.cpp \
|
||||||
|
hardware/modbus/modbusrtumanager.cpp \
|
||||||
|
hardware/modbus/modbusrtumasterimpl.cpp \
|
||||||
|
hardware/modbus/modbusrtureplyimpl.cpp \
|
||||||
hardware/network/networkaccessmanagerimpl.cpp \
|
hardware/network/networkaccessmanagerimpl.cpp \
|
||||||
hardware/network/upnp/upnpdiscoveryimplementation.cpp \
|
hardware/network/upnp/upnpdiscoveryimplementation.cpp \
|
||||||
hardware/network/upnp/upnpdiscoveryrequest.cpp \
|
hardware/network/upnp/upnpdiscoveryrequest.cpp \
|
||||||
|
|||||||
@ -53,6 +53,9 @@
|
|||||||
|
|
||||||
#include "zigbee/zigbeemanager.h"
|
#include "zigbee/zigbeemanager.h"
|
||||||
|
|
||||||
|
#include "hardware/modbus/modbusrtumanager.h"
|
||||||
|
#include "hardware/serialport/serialportmonitor.h"
|
||||||
|
|
||||||
#include <networkmanager.h>
|
#include <networkmanager.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@ -108,8 +111,14 @@ void NymeaCore::init(const QStringList &additionalInterfaces) {
|
|||||||
qCDebug(dcCore()) << "Create Zigbee Manager";
|
qCDebug(dcCore()) << "Create Zigbee Manager";
|
||||||
m_zigbeeManager = new ZigbeeManager(this);
|
m_zigbeeManager = new ZigbeeManager(this);
|
||||||
|
|
||||||
|
qCDebug(dcCore()) << "Create Serial Port Monitor";
|
||||||
|
m_serialPortMonitor = new SerialPortMonitor(this);
|
||||||
|
|
||||||
|
qCDebug(dcCore()) << "Create Modbus RTU Manager";
|
||||||
|
m_modbusRtuManager = new ModbusRtuManager(m_serialPortMonitor, this);
|
||||||
|
|
||||||
qCDebug(dcCore) << "Creating Hardware Manager";
|
qCDebug(dcCore) << "Creating Hardware Manager";
|
||||||
m_hardwareManager = new HardwareManagerImplementation(m_platform, m_serverManager->mqttBroker(), m_zigbeeManager, this);
|
m_hardwareManager = new HardwareManagerImplementation(m_platform, m_serverManager->mqttBroker(), m_zigbeeManager, m_modbusRtuManager, this);
|
||||||
|
|
||||||
qCDebug(dcCore) << "Creating Thing Manager (locale:" << m_configuration->locale() << ")";
|
qCDebug(dcCore) << "Creating Thing Manager (locale:" << m_configuration->locale() << ")";
|
||||||
m_thingManager = new ThingManagerImplementation(m_hardwareManager, m_configuration->locale(), this);
|
m_thingManager = new ThingManagerImplementation(m_hardwareManager, m_configuration->locale(), this);
|
||||||
@ -645,6 +654,11 @@ ZigbeeManager *NymeaCore::zigbeeManager() const
|
|||||||
return m_zigbeeManager;
|
return m_zigbeeManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModbusRtuManager *NymeaCore::modbusRtuManager() const
|
||||||
|
{
|
||||||
|
return m_modbusRtuManager;
|
||||||
|
}
|
||||||
|
|
||||||
void NymeaCore::gotEvent(const Event &event)
|
void NymeaCore::gotEvent(const Event &event)
|
||||||
{
|
{
|
||||||
emit eventTriggered(event);
|
emit eventTriggered(event);
|
||||||
|
|||||||
@ -67,6 +67,8 @@ class ExperienceManager;
|
|||||||
class ScriptEngine;
|
class ScriptEngine;
|
||||||
class CloudManager;
|
class CloudManager;
|
||||||
class ZigbeeManager;
|
class ZigbeeManager;
|
||||||
|
class ModbusRtuManager;
|
||||||
|
class SerialPortMonitor;
|
||||||
|
|
||||||
class NymeaCore : public QObject
|
class NymeaCore : public QObject
|
||||||
{
|
{
|
||||||
@ -107,6 +109,7 @@ public:
|
|||||||
TagsStorage *tagsStorage() const;
|
TagsStorage *tagsStorage() const;
|
||||||
Platform *platform() const;
|
Platform *platform() const;
|
||||||
ZigbeeManager *zigbeeManager() const;
|
ZigbeeManager *zigbeeManager() const;
|
||||||
|
ModbusRtuManager *modbusRtuManager() const;
|
||||||
|
|
||||||
static QStringList getAvailableLanguages();
|
static QStringList getAvailableLanguages();
|
||||||
static QStringList loggingFilters();
|
static QStringList loggingFilters();
|
||||||
@ -151,6 +154,8 @@ private:
|
|||||||
System *m_system;
|
System *m_system;
|
||||||
ExperienceManager *m_experienceManager;
|
ExperienceManager *m_experienceManager;
|
||||||
ZigbeeManager *m_zigbeeManager;
|
ZigbeeManager *m_zigbeeManager;
|
||||||
|
SerialPortMonitor *m_serialPortMonitor;
|
||||||
|
ModbusRtuManager *m_modbusRtuManager;
|
||||||
|
|
||||||
QList<RuleId> m_executingRules;
|
QList<RuleId> m_executingRules;
|
||||||
|
|
||||||
|
|||||||
38
libnymea/hardware/modbus/modbusrtuhardwareresource.cpp
Normal file
38
libnymea/hardware/modbus/modbusrtuhardwareresource.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 "modbusrtuhardwareresource.h"
|
||||||
|
#include "modbusrtumaster.h"
|
||||||
|
|
||||||
|
ModbusRtuHardwareResource::ModbusRtuHardwareResource(QObject *parent) :
|
||||||
|
HardwareResource("Modbus RTU resource", parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
59
libnymea/hardware/modbus/modbusrtuhardwareresource.h
Normal file
59
libnymea/hardware/modbus/modbusrtuhardwareresource.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 MODBUSRTUHARDWARERESOURCE_H
|
||||||
|
#define MODBUSRTUHARDWARERESOURCE_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "hardwareresource.h"
|
||||||
|
#include "modbusrtumaster.h"
|
||||||
|
|
||||||
|
class ModbusRtuHardwareResource : public HardwareResource
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
virtual QList<ModbusRtuMaster *> modbusRtuMasters() const = 0;
|
||||||
|
virtual bool hasModbusRtuMaster(const QUuid &modbusUuid) const = 0;
|
||||||
|
virtual ModbusRtuMaster *getModbusRtuMaster(const QUuid &modbusUuid) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit ModbusRtuHardwareResource(QObject *parent = nullptr);
|
||||||
|
virtual ~ModbusRtuHardwareResource() = default;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void modbusRtuMasterAdded(const QUuid &modbusUuid);
|
||||||
|
void modbusRtuMasterRemoved(const QUuid &modbusUuid);
|
||||||
|
void modbusRtuMasterChanged(const QUuid &modbusUuid);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MODBUSRTUHARDWARERESOURCE_H
|
||||||
95
libnymea/hardware/modbus/modbusrtumaster.h
Normal file
95
libnymea/hardware/modbus/modbusrtumaster.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* 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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 <QSerialPort>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "modbusrtureply.h"
|
||||||
|
|
||||||
|
class ModbusRtuMaster : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
// Properties
|
||||||
|
virtual QUuid modbusUuid() const = 0;
|
||||||
|
virtual QString serialPort() const = 0;
|
||||||
|
virtual qint32 baudrate() const = 0;
|
||||||
|
virtual QSerialPort::Parity parity() const = 0;
|
||||||
|
virtual QSerialPort::DataBits dataBits() const = 0;
|
||||||
|
virtual QSerialPort::StopBits stopBits() = 0;
|
||||||
|
virtual int numberOfRetries() const = 0;
|
||||||
|
virtual int timeout() const = 0;
|
||||||
|
|
||||||
|
virtual bool connected() const = 0;
|
||||||
|
|
||||||
|
// Requests
|
||||||
|
virtual ModbusRtuReply *readCoil(int slaveAddress, int registerAddress, quint16 size = 1) = 0;
|
||||||
|
virtual ModbusRtuReply *readDiscreteInput(int slaveAddress, int registerAddress, quint16 size = 1) = 0;
|
||||||
|
virtual ModbusRtuReply *readInputRegister(int slaveAddress, int registerAddress, quint16 size = 1) = 0;
|
||||||
|
virtual ModbusRtuReply *readHoldingRegister(int slaveAddress, int registerAddress, quint16 size = 1) = 0;
|
||||||
|
|
||||||
|
virtual ModbusRtuReply *writeCoils(int slaveAddress, int registerAddress, const QVector<quint16> &values) = 0;
|
||||||
|
virtual ModbusRtuReply *writeHoldingRegisters(int slaveAddress, int registerAddress, const QVector<quint16> &values) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit ModbusRtuMaster(QObject *parent = nullptr) : QObject(parent) { };
|
||||||
|
virtual ~ModbusRtuMaster() = default;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void connectedChanged(bool connected);
|
||||||
|
void serialPortChanged(const QString &serialPort);
|
||||||
|
void baudrateChanged(quint32 baudrate);
|
||||||
|
void parityChanged(QSerialPort::Parity parity);
|
||||||
|
void dataBitsChanged(QSerialPort::DataBits dataBits);
|
||||||
|
void stopBitsChanged(QSerialPort::StopBits stopBits);
|
||||||
|
void numberOfRetriesChanged(int numberOfRetries);
|
||||||
|
void timeoutChanged(int timeout);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QDebug operator<<(QDebug debug, ModbusRtuMaster *modbusRtuMaster) {
|
||||||
|
debug.nospace() << "ModbusRtuMaster(" << modbusRtuMaster->modbusUuid().toString();
|
||||||
|
debug.nospace() << ", " << modbusRtuMaster->serialPort();
|
||||||
|
debug.nospace() << ", BaudRate: " << modbusRtuMaster->baudrate();
|
||||||
|
debug.nospace() << ", " << modbusRtuMaster->dataBits();
|
||||||
|
debug.nospace() << ", " << modbusRtuMaster->stopBits();
|
||||||
|
debug.nospace() << ", " << modbusRtuMaster->parity();
|
||||||
|
debug.nospace() << ", Retries: " << modbusRtuMaster->numberOfRetries();
|
||||||
|
debug.nospace() << ", Timeout: " << modbusRtuMaster->timeout() << "ms)";
|
||||||
|
return debug.space();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MODBUSRTUMASTER_H
|
||||||
74
libnymea/hardware/modbus/modbusrtureply.h
Normal file
74
libnymea/hardware/modbus/modbusrtureply.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 Lesser General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU Lesser General Public License as published by the Free
|
||||||
|
* Software Foundation; 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser 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 MODBUSRTUREPLY_H
|
||||||
|
#define MODBUSRTUREPLY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
class ModbusRtuReply : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum Error {
|
||||||
|
NoError,
|
||||||
|
ReadError,
|
||||||
|
WriteError,
|
||||||
|
ConnectionError,
|
||||||
|
ConfigurationError,
|
||||||
|
TimeoutError,
|
||||||
|
ProtocolError,
|
||||||
|
ReplyAbortedError,
|
||||||
|
UnknownError
|
||||||
|
};
|
||||||
|
Q_ENUM(Error)
|
||||||
|
|
||||||
|
virtual bool isFinished() const = 0;
|
||||||
|
|
||||||
|
virtual int slaveAddress() const = 0;
|
||||||
|
virtual int registerAddress() const = 0;
|
||||||
|
|
||||||
|
virtual QString errorString() const = 0;
|
||||||
|
virtual ModbusRtuReply::Error error() const = 0;
|
||||||
|
|
||||||
|
virtual QVector<quint16> result() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit ModbusRtuReply(QObject *parent = nullptr) : QObject(parent) { };
|
||||||
|
virtual ~ModbusRtuReply() = default;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
void errorOccurred(ModbusRtuReply::Error error);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MODBUSRTUREPLY_H
|
||||||
@ -44,6 +44,7 @@ class MqttProvider;
|
|||||||
class I2CManager;
|
class I2CManager;
|
||||||
class ZigbeeHardwareResource;
|
class ZigbeeHardwareResource;
|
||||||
class HardwareResource;
|
class HardwareResource;
|
||||||
|
class ModbusRtuHardwareResource;
|
||||||
|
|
||||||
class HardwareManager : public QObject
|
class HardwareManager : public QObject
|
||||||
{
|
{
|
||||||
@ -63,6 +64,7 @@ public:
|
|||||||
virtual MqttProvider *mqttProvider() = 0;
|
virtual MqttProvider *mqttProvider() = 0;
|
||||||
virtual I2CManager *i2cManager() = 0;
|
virtual I2CManager *i2cManager() = 0;
|
||||||
virtual ZigbeeHardwareResource *zigbeeResource() = 0;
|
virtual ZigbeeHardwareResource *zigbeeResource() = 0;
|
||||||
|
virtual ModbusRtuHardwareResource *modbusRtuResource() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setResourceEnabled(HardwareResource* resource, bool enabled);
|
void setResourceEnabled(HardwareResource* resource, bool enabled);
|
||||||
|
|||||||
@ -3,7 +3,7 @@ include(../nymea.pri)
|
|||||||
TARGET = nymea
|
TARGET = nymea
|
||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
|
|
||||||
QT += network bluetooth dbus
|
QT += network bluetooth dbus serialport
|
||||||
QT -= gui
|
QT -= gui
|
||||||
DEFINES += LIBNYMEA_LIBRARY
|
DEFINES += LIBNYMEA_LIBRARY
|
||||||
|
|
||||||
@ -13,6 +13,9 @@ PKGCONFIG += nymea-zigbee nymea-mqtt
|
|||||||
QMAKE_LFLAGS += -fPIC
|
QMAKE_LFLAGS += -fPIC
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
hardware/modbus/modbusrtuhardwareresource.h \
|
||||||
|
hardware/modbus/modbusrtumaster.h \
|
||||||
|
hardware/modbus/modbusrtureply.h \
|
||||||
hardware/zigbee/zigbeehandler.h \
|
hardware/zigbee/zigbeehandler.h \
|
||||||
hardware/zigbee/zigbeehardwareresource.h \
|
hardware/zigbee/zigbeehardwareresource.h \
|
||||||
integrations/browseractioninfo.h \
|
integrations/browseractioninfo.h \
|
||||||
@ -108,6 +111,7 @@ HEADERS += \
|
|||||||
experiences/experienceplugin.h \
|
experiences/experienceplugin.h \
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
hardware/modbus/modbusrtuhardwareresource.cpp \
|
||||||
hardware/zigbee/zigbeehandler.cpp \
|
hardware/zigbee/zigbeehandler.cpp \
|
||||||
hardware/zigbee/zigbeehardwareresource.cpp \
|
hardware/zigbee/zigbeehardwareresource.cpp \
|
||||||
integrations/browseractioninfo.cpp \
|
integrations/browseractioninfo.cpp \
|
||||||
|
|||||||
@ -64,6 +64,10 @@
|
|||||||
This role will create the \b{mqttpolicies.conf} file and is used to store the \l{MqttPolicy}{MqttPolicies}.
|
This role will create the \b{mqttpolicies.conf} file and is used to store the \l{MqttPolicy}{MqttPolicies}.
|
||||||
\value SettingsRoleIOConnections
|
\value SettingsRoleIOConnections
|
||||||
This role will create the \b{ioconnections.conf} file and is used to store the \l{IOConnection}{IOConnections}.
|
This role will create the \b{ioconnections.conf} file and is used to store the \l{IOConnection}{IOConnections}.
|
||||||
|
\value SettingsRoleZigbee
|
||||||
|
This role will create the \b{zigbee.conf} file and is used to store the Zigbee networks.
|
||||||
|
\value SettingsRoleModbusRtu
|
||||||
|
This role will create the \b{modbusrtu.conf} file and is used to store the modbus RTU resources.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -83,7 +87,7 @@ NymeaSettings::NymeaSettings(const SettingsRole &role, QObject *parent):
|
|||||||
QString settingsPrefix = QCoreApplication::instance()->organizationName() + "/";
|
QString settingsPrefix = QCoreApplication::instance()->organizationName() + "/";
|
||||||
|
|
||||||
QString basePath;
|
QString basePath;
|
||||||
if (!qgetenv("SNAP").isEmpty()) {
|
if (!qEnvironmentVariableIsEmpty("SNAP")) {
|
||||||
basePath = QString(qgetenv("SNAP_DATA")) + "/";
|
basePath = QString(qgetenv("SNAP_DATA")) + "/";
|
||||||
settingsPrefix.clear(); // We don't want that in the snappy case...
|
settingsPrefix.clear(); // We don't want that in the snappy case...
|
||||||
} else if (settingsPrefix == "nymea-test/") {
|
} else if (settingsPrefix == "nymea-test/") {
|
||||||
@ -125,6 +129,9 @@ NymeaSettings::NymeaSettings(const SettingsRole &role, QObject *parent):
|
|||||||
case SettingsRoleZigbee:
|
case SettingsRoleZigbee:
|
||||||
fileName = "zigbee.conf";
|
fileName = "zigbee.conf";
|
||||||
break;
|
break;
|
||||||
|
case SettingsRoleModbusRtu:
|
||||||
|
fileName = "modbusrtu.conf";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
m_settings = new QSettings(basePath + settingsPrefix + fileName, QSettings::IniFormat, this);
|
m_settings = new QSettings(basePath + settingsPrefix + fileName, QSettings::IniFormat, this);
|
||||||
}
|
}
|
||||||
@ -157,7 +164,7 @@ QString NymeaSettings::settingsPath()
|
|||||||
QString path;
|
QString path;
|
||||||
QString organisationName = QCoreApplication::instance()->organizationName();
|
QString organisationName = QCoreApplication::instance()->organizationName();
|
||||||
|
|
||||||
if (!qgetenv("SNAP").isEmpty()) {
|
if (!qEnvironmentVariableIsEmpty("SNAP")) {
|
||||||
path = QString(qgetenv("SNAP_DATA"));
|
path = QString(qgetenv("SNAP_DATA"));
|
||||||
} else if (organisationName == "nymea-test") {
|
} else if (organisationName == "nymea-test") {
|
||||||
path = "/tmp/" + organisationName;
|
path = "/tmp/" + organisationName;
|
||||||
@ -174,7 +181,7 @@ QString NymeaSettings::translationsPath()
|
|||||||
{
|
{
|
||||||
QString organisationName = QCoreApplication::instance()->organizationName();
|
QString organisationName = QCoreApplication::instance()->organizationName();
|
||||||
|
|
||||||
if (!qgetenv("SNAP").isEmpty()) {
|
if (!qEnvironmentVariableIsEmpty("SNAP")) {
|
||||||
return QString(qgetenv("SNAP") + "/usr/share/nymea/translations");
|
return QString(qgetenv("SNAP") + "/usr/share/nymea/translations");
|
||||||
} else if (organisationName == "nymea-test") {
|
} else if (organisationName == "nymea-test") {
|
||||||
return "/tmp/" + organisationName;
|
return "/tmp/" + organisationName;
|
||||||
@ -188,7 +195,7 @@ QString NymeaSettings::storagePath()
|
|||||||
{
|
{
|
||||||
QString path;
|
QString path;
|
||||||
QString organisationName = QCoreApplication::instance()->organizationName();
|
QString organisationName = QCoreApplication::instance()->organizationName();
|
||||||
if (!qgetenv("SNAP").isEmpty()) {
|
if (!qEnvironmentVariableIsEmpty("SNAP")) {
|
||||||
path = QString(qgetenv("SNAP_DATA"));
|
path = QString(qgetenv("SNAP_DATA"));
|
||||||
} else if (organisationName == "nymea-test") {
|
} else if (organisationName == "nymea-test") {
|
||||||
path = "/tmp/" + organisationName;
|
path = "/tmp/" + organisationName;
|
||||||
|
|||||||
@ -53,7 +53,9 @@ public:
|
|||||||
SettingsRoleMqttPolicies,
|
SettingsRoleMqttPolicies,
|
||||||
SettingsRoleIOConnections,
|
SettingsRoleIOConnections,
|
||||||
SettingsRoleZigbee,
|
SettingsRoleZigbee,
|
||||||
|
SettingsRoleModbusRtu
|
||||||
};
|
};
|
||||||
|
Q_ENUM(SettingsRole)
|
||||||
|
|
||||||
explicit NymeaSettings(const SettingsRole &role = SettingsRoleNone, QObject *parent = nullptr);
|
explicit NymeaSettings(const SettingsRole &role = SettingsRoleNone, QObject *parent = nullptr);
|
||||||
~NymeaSettings();
|
~NymeaSettings();
|
||||||
|
|||||||
@ -150,6 +150,16 @@
|
|||||||
"MediaBrowserIconSoundCloud",
|
"MediaBrowserIconSoundCloud",
|
||||||
"MediaBrowserIconRadioParadise"
|
"MediaBrowserIconRadioParadise"
|
||||||
],
|
],
|
||||||
|
"ModbusRtuError": [
|
||||||
|
"ModbusRtuErrorNoError",
|
||||||
|
"ModbusRtuErrorNotAvailable",
|
||||||
|
"ModbusRtuErrorUuidNotFound",
|
||||||
|
"ModbusRtuErrorHardwareNotFound",
|
||||||
|
"ModbusRtuErrorResourceBusy",
|
||||||
|
"ModbusRtuErrorNotSupported",
|
||||||
|
"ModbusRtuErrorInvalidTimeoutValue",
|
||||||
|
"ModbusRtuErrorConnectionFailed"
|
||||||
|
],
|
||||||
"NetworkDeviceState": [
|
"NetworkDeviceState": [
|
||||||
"NetworkDeviceStateUnknown",
|
"NetworkDeviceStateUnknown",
|
||||||
"NetworkDeviceStateUnmanaged",
|
"NetworkDeviceStateUnmanaged",
|
||||||
@ -232,6 +242,27 @@
|
|||||||
"ScriptMessageTypeLog",
|
"ScriptMessageTypeLog",
|
||||||
"ScriptMessageTypeWarning"
|
"ScriptMessageTypeWarning"
|
||||||
],
|
],
|
||||||
|
"SerialPortDataBits": [
|
||||||
|
"SerialPortDataBitsData5",
|
||||||
|
"SerialPortDataBitsData6",
|
||||||
|
"SerialPortDataBitsData7",
|
||||||
|
"SerialPortDataBitsData8",
|
||||||
|
"SerialPortDataBitsUnknownDataBits"
|
||||||
|
],
|
||||||
|
"SerialPortParity": [
|
||||||
|
"SerialPortParityNoParity",
|
||||||
|
"SerialPortParityEvenParity",
|
||||||
|
"SerialPortParityOddParity",
|
||||||
|
"SerialPortParitySpaceParity",
|
||||||
|
"SerialPortParityMarkParity",
|
||||||
|
"SerialPortParityUnknownParity"
|
||||||
|
],
|
||||||
|
"SerialPortStopBits": [
|
||||||
|
"SerialPortStopBitsOneStop",
|
||||||
|
"SerialPortStopBitsOneAndHalfStop",
|
||||||
|
"SerialPortStopBitsTwoStop",
|
||||||
|
"SerialPortStopBitsUnknownStopBits"
|
||||||
|
],
|
||||||
"SetupMethod": [
|
"SetupMethod": [
|
||||||
"SetupMethodJustAdd",
|
"SetupMethodJustAdd",
|
||||||
"SetupMethodDisplayPin",
|
"SetupMethodDisplayPin",
|
||||||
@ -1491,6 +1522,66 @@
|
|||||||
"offset": "Int"
|
"offset": "Int"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModbusRtu.AddModbusRtuMaster": {
|
||||||
|
"description": "Add a new modbus RTU master with the given configuration. The timeout value is in milli seconds and the minimum value is 10 ms.",
|
||||||
|
"params": {
|
||||||
|
"baudrate": "Uint",
|
||||||
|
"dataBits": "$ref:SerialPortDataBits",
|
||||||
|
"numberOfRetries": "Uint",
|
||||||
|
"parity": "$ref:SerialPortParity",
|
||||||
|
"serialPort": "String",
|
||||||
|
"stopBits": "$ref:SerialPortStopBits",
|
||||||
|
"timeout": "Uint"
|
||||||
|
},
|
||||||
|
"returns": {
|
||||||
|
"modbusError": "$ref:ModbusRtuError",
|
||||||
|
"o:modbusUuid": "Uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ModbusRtu.GetModbusRtuMasters": {
|
||||||
|
"description": "Get the list of configured modbus RTU masters.",
|
||||||
|
"params": {
|
||||||
|
},
|
||||||
|
"returns": {
|
||||||
|
"modbusError": "$ref:ModbusRtuError",
|
||||||
|
"o:modbusRtuMasters": [
|
||||||
|
"$ref:ModbusRtuMaster"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ModbusRtu.GetSerialPorts": {
|
||||||
|
"description": "Get the list of available serial ports from the host system.",
|
||||||
|
"params": {
|
||||||
|
},
|
||||||
|
"returns": {
|
||||||
|
"serialPorts": "$ref:SerialPorts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ModbusRtu.ReconfigureModbusRtuMaster": {
|
||||||
|
"description": "Reconfigure the modbus RTU master with the given UUID and configuration.",
|
||||||
|
"params": {
|
||||||
|
"baudrate": "Uint",
|
||||||
|
"dataBits": "$ref:SerialPortDataBits",
|
||||||
|
"modbusUuid": "Uuid",
|
||||||
|
"numberOfRetries": "Uint",
|
||||||
|
"parity": "$ref:SerialPortParity",
|
||||||
|
"serialPort": "String",
|
||||||
|
"stopBits": "$ref:SerialPortStopBits",
|
||||||
|
"timeout": "Uint"
|
||||||
|
},
|
||||||
|
"returns": {
|
||||||
|
"modbusError": "$ref:ModbusRtuError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ModbusRtu.RemoveModbusRtuMaster": {
|
||||||
|
"description": "Remove the modbus RTU master with the given modbus UUID.",
|
||||||
|
"params": {
|
||||||
|
"modbusUuid": "Uuid"
|
||||||
|
},
|
||||||
|
"returns": {
|
||||||
|
"modbusError": "$ref:ModbusRtuError"
|
||||||
|
}
|
||||||
|
},
|
||||||
"NetworkManager.ConnectWifiNetwork": {
|
"NetworkManager.ConnectWifiNetwork": {
|
||||||
"description": "Connect to the wifi network with the given ssid and password.",
|
"description": "Connect to the wifi network with the given ssid and password.",
|
||||||
"params": {
|
"params": {
|
||||||
@ -2351,6 +2442,36 @@
|
|||||||
"logEntry": "$ref:LogEntry"
|
"logEntry": "$ref:LogEntry"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModbusRtu.ModbusRtuMasterAdded": {
|
||||||
|
"description": "Emitted whenever a new modbus RTU master has been added to the system.",
|
||||||
|
"params": {
|
||||||
|
"modbusRtuMaster": "$ref:ModbusRtuMaster"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ModbusRtu.ModbusRtuMasterChanged": {
|
||||||
|
"description": "Emitted whenever a modbus RTU master has been changed in the system.",
|
||||||
|
"params": {
|
||||||
|
"modbusRtuMaster": "$ref:ModbusRtuMaster"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ModbusRtu.ModbusRtuMasterRemoved": {
|
||||||
|
"description": "Emitted whenever a modbus RTU master has been removed from the system.",
|
||||||
|
"params": {
|
||||||
|
"modbusUuid": "Uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ModbusRtu.SerialPortAdded": {
|
||||||
|
"description": "Emitted whenever a serial port has been added to the system.",
|
||||||
|
"params": {
|
||||||
|
"serialPort": "$ref:SerialPort"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ModbusRtu.SerialPortRemoved": {
|
||||||
|
"description": "Emitted whenever a serial port has been removed from the system.",
|
||||||
|
"params": {
|
||||||
|
"serialPort": "$ref:SerialPort"
|
||||||
|
}
|
||||||
|
},
|
||||||
"NetworkManager.NetworkStatusChanged": {
|
"NetworkManager.NetworkStatusChanged": {
|
||||||
"description": "Emitted whenever a status of a NetworkManager changes.",
|
"description": "Emitted whenever a status of a NetworkManager changes.",
|
||||||
"params": {
|
"params": {
|
||||||
@ -2765,6 +2886,17 @@
|
|||||||
"r:source": "$ref:LoggingSource",
|
"r:source": "$ref:LoggingSource",
|
||||||
"r:timestamp": "Uint"
|
"r:timestamp": "Uint"
|
||||||
},
|
},
|
||||||
|
"ModbusRtuMaster": {
|
||||||
|
"baudrate": "Uint",
|
||||||
|
"connected": "Bool",
|
||||||
|
"dataBits": "$ref:SerialPortDataBits",
|
||||||
|
"modbusUuid": "Uuid",
|
||||||
|
"numberOfRetries": "Uint",
|
||||||
|
"parity": "$ref:SerialPortParity",
|
||||||
|
"serialPort": "String",
|
||||||
|
"stopBits": "$ref:SerialPortStopBits",
|
||||||
|
"timeout": "Uint"
|
||||||
|
},
|
||||||
"MqttPolicy": {
|
"MqttPolicy": {
|
||||||
"allowedPublishTopicFilters": "StringList",
|
"allowedPublishTopicFilters": "StringList",
|
||||||
"allowedSubscribeTopicFilters": "StringList",
|
"allowedSubscribeTopicFilters": "StringList",
|
||||||
@ -2892,6 +3024,15 @@
|
|||||||
"Scripts": [
|
"Scripts": [
|
||||||
"$ref:Script"
|
"$ref:Script"
|
||||||
],
|
],
|
||||||
|
"SerialPort": {
|
||||||
|
"r:description": "String",
|
||||||
|
"r:manufacturer": "String",
|
||||||
|
"r:serialNumber": "String",
|
||||||
|
"r:systemLocation": "String"
|
||||||
|
},
|
||||||
|
"SerialPorts": [
|
||||||
|
"$ref:SerialPort"
|
||||||
|
],
|
||||||
"ServerConfiguration": {
|
"ServerConfiguration": {
|
||||||
"address": "String",
|
"address": "String",
|
||||||
"authenticationEnabled": "Bool",
|
"authenticationEnabled": "Bool",
|
||||||
|
|||||||
@ -2,6 +2,18 @@ QT += dbus testlib network sql websockets
|
|||||||
CONFIG += testcase
|
CONFIG += testcase
|
||||||
CONFIG += link_pkgconfig
|
CONFIG += link_pkgconfig
|
||||||
|
|
||||||
|
# Qt serial bus module is officially available since Qt 5.8
|
||||||
|
# but not all platforms host the qt serialbus package.
|
||||||
|
# Let's check if the package exists, not the qt version
|
||||||
|
packagesExist(Qt5SerialBus) {
|
||||||
|
message("Building with QtSerialBus support.")
|
||||||
|
# Qt += serialbus
|
||||||
|
PKGCONFIG += Qt5SerialBus
|
||||||
|
DEFINES += WITH_QTSERIALBUS
|
||||||
|
} else {
|
||||||
|
message("Qt5SerialBus package not found. Building without QtSerialBus support.")
|
||||||
|
}
|
||||||
|
|
||||||
INCLUDEPATH += $$top_srcdir/libnymea \
|
INCLUDEPATH += $$top_srcdir/libnymea \
|
||||||
$$top_srcdir/libnymea-core \
|
$$top_srcdir/libnymea-core \
|
||||||
$$top_srcdir/tests/testlib/ \
|
$$top_srcdir/tests/testlib/ \
|
||||||
|
|||||||
@ -674,7 +674,7 @@ void TestJSONRPC::enableDisableNotifications_legacy()
|
|||||||
|
|
||||||
QStringList expectedNamespaces;
|
QStringList expectedNamespaces;
|
||||||
if (enabled == "true") {
|
if (enabled == "true") {
|
||||||
expectedNamespaces << "Actions" << "NetworkManager" << "Devices" << "Integrations" << "System" << "Rules" << "States" << "Logging" << "Tags" << "AppData" << "JSONRPC" << "Configuration" << "Events" << "Scripts" << "Users" << "Zigbee";
|
expectedNamespaces << "Actions" << "NetworkManager" << "Devices" << "Integrations" << "System" << "Rules" << "States" << "Logging" << "Tags" << "AppData" << "JSONRPC" << "Configuration" << "Events" << "Scripts" << "Users" << "Zigbee" << "ModbusRtu";
|
||||||
}
|
}
|
||||||
std::sort(expectedNamespaces.begin(), expectedNamespaces.end());
|
std::sort(expectedNamespaces.begin(), expectedNamespaces.end());
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,14 @@ include(../../nymea.pri)
|
|||||||
|
|
||||||
QT += testlib dbus network sql websockets
|
QT += testlib dbus network sql websockets
|
||||||
|
|
||||||
|
# Qt serial bus module is officially available since Qt 5.8
|
||||||
|
# but not all platforms host the qt serialbus package.
|
||||||
|
# Let's check if the package exists, not the qt version
|
||||||
|
packagesExist(Qt5SerialBus) {
|
||||||
|
Qt += serialbus
|
||||||
|
DEFINES += WITH_QTSERIALBUS
|
||||||
|
}
|
||||||
|
|
||||||
INCLUDEPATH += $$top_srcdir/libnymea \
|
INCLUDEPATH += $$top_srcdir/libnymea \
|
||||||
$$top_srcdir/libnymea-core
|
$$top_srcdir/libnymea-core
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user