From ff8f2d0aad4372ebadd0fb11cd2509274cd63066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Sun, 1 Nov 2020 12:29:04 +0100 Subject: [PATCH 01/18] Add basic structure for the zigbee manager and implement adapter handling --- libnymea-app/engine.cpp | 14 +- libnymea-app/engine.h | 4 + libnymea-app/libnymea-app-core.h | 9 + libnymea-app/libnymea-app.pro | 9 + libnymea-app/zigbee/zigbeeadapter.cpp | 125 ++++++++++++ libnymea-app/zigbee/zigbeeadapter.h | 94 +++++++++ libnymea-app/zigbee/zigbeeadapters.cpp | 143 ++++++++++++++ libnymea-app/zigbee/zigbeeadapters.h | 77 ++++++++ libnymea-app/zigbee/zigbeeadaptersproxy.cpp | 93 +++++++++ libnymea-app/zigbee/zigbeeadaptersproxy.h | 78 ++++++++ libnymea-app/zigbee/zigbeemanager.cpp | 111 +++++++++++ libnymea-app/zigbee/zigbeemanager.h | 72 +++++++ nymea-app/images.qrc | 1 + nymea-app/resources.qrc | 2 + nymea-app/ui/SettingsPage.qml | 17 ++ nymea-app/ui/images/zigbee.svg | 179 ++++++++++++++++++ nymea-app/ui/system/ZigbeeNetworkAddPage.qml | 81 ++++++++ .../ui/system/ZigbeeNetworkSettingsPage.qml | 75 ++++++++ 18 files changed, 1183 insertions(+), 1 deletion(-) create mode 100644 libnymea-app/zigbee/zigbeeadapter.cpp create mode 100644 libnymea-app/zigbee/zigbeeadapter.h create mode 100644 libnymea-app/zigbee/zigbeeadapters.cpp create mode 100644 libnymea-app/zigbee/zigbeeadapters.h create mode 100644 libnymea-app/zigbee/zigbeeadaptersproxy.cpp create mode 100644 libnymea-app/zigbee/zigbeeadaptersproxy.h create mode 100644 libnymea-app/zigbee/zigbeemanager.cpp create mode 100644 libnymea-app/zigbee/zigbeemanager.h create mode 100644 nymea-app/ui/images/zigbee.svg create mode 100644 nymea-app/ui/system/ZigbeeNetworkAddPage.qml create mode 100644 nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml diff --git a/libnymea-app/engine.cpp b/libnymea-app/engine.cpp index fbfa0a11..e79b06eb 100644 --- a/libnymea-app/engine.cpp +++ b/libnymea-app/engine.cpp @@ -38,6 +38,7 @@ #include "connection/awsclient.h" #include "system/systemcontroller.h" #include "configuration/networkmanager.h" +#include "zigbee/zigbeemanager.h" Engine::Engine(QObject *parent) : QObject(parent), @@ -48,7 +49,8 @@ Engine::Engine(QObject *parent) : m_logManager(new LogManager(m_jsonRpcClient, this)), m_tagsManager(new TagsManager(m_jsonRpcClient, this)), m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this)), - m_systemController(new SystemController(m_jsonRpcClient, this)) + m_systemController(new SystemController(m_jsonRpcClient, this)), + m_zigbeeManager(new ZigbeeManager(m_jsonRpcClient, this)) { connect(m_jsonRpcClient, &JsonRpcClient::connectedChanged, this, &Engine::onConnectedChanged); @@ -117,6 +119,11 @@ SystemController *Engine::systemController() const return m_systemController; } +ZigbeeManager *Engine::zigbeeManager() const +{ + return m_zigbeeManager; +} + void Engine::deployCertificate() { if (!m_jsonRpcClient->connected()) { @@ -154,8 +161,13 @@ void Engine::onDeviceManagerFetchingChanged() m_scriptManager->init(); m_nymeaConfiguration->init(); m_systemController->init(); + if (m_jsonRpcClient->ensureServerVersion("1.7")) { m_tagsManager->init(); } + + if (m_jsonRpcClient->ensureServerVersion("5.1")) { + m_zigbeeManager->init(); + } } } diff --git a/libnymea-app/engine.h b/libnymea-app/engine.h index 07b38c6a..c81b2ef4 100644 --- a/libnymea-app/engine.h +++ b/libnymea-app/engine.h @@ -45,6 +45,7 @@ class TagsManager; class NymeaConfiguration; class SystemController; class NetworkManager; +class ZigbeeManager; class Engine : public QObject { @@ -57,6 +58,7 @@ class Engine : public QObject Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT) Q_PROPERTY(NymeaConfiguration* nymeaConfiguration READ nymeaConfiguration CONSTANT) Q_PROPERTY(SystemController* systemController READ systemController CONSTANT) + Q_PROPERTY(ZigbeeManager *zigbeeManager READ zigbeeManager CONSTANT) public: explicit Engine(QObject *parent = nullptr); @@ -70,6 +72,7 @@ public: LogManager *logManager() const; NymeaConfiguration *nymeaConfiguration() const; SystemController *systemController() const; + ZigbeeManager *zigbeeManager() const; Q_INVOKABLE void deployCertificate(); @@ -82,6 +85,7 @@ private: TagsManager *m_tagsManager; NymeaConfiguration *m_nymeaConfiguration; SystemController *m_systemController; + ZigbeeManager *m_zigbeeManager; private slots: void onConnectedChanged(); diff --git a/libnymea-app/libnymea-app-core.h b/libnymea-app/libnymea-app-core.h index 987b6331..a6d6987f 100644 --- a/libnymea-app/libnymea-app-core.h +++ b/libnymea-app/libnymea-app-core.h @@ -120,6 +120,10 @@ #include "types/ioconnection.h" #include "types/ioconnections.h" #include "types/ioconnectionwatcher.h" +#include "zigbee/zigbeemanager.h" +#include "zigbee/zigbeeadapter.h" +#include "zigbee/zigbeeadapters.h" +#include "zigbee/zigbeeadaptersproxy.h" #include @@ -296,6 +300,11 @@ void registerQmlTypes() { qmlRegisterUncreatableType(uri, 1, 0, "Repository", "Get it from Repositories"); qmlRegisterType(uri, 1, 0, "PackagesFilterModel"); + qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeManager", "Get it from Engine"); + qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeAdapter", "Get it from the ZigbeeAdapters"); + qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeAdapters", "Get it from ZigbeeManager"); + qmlRegisterType(uri, 1, 0, "ZigbeeAdaptersProxy"); + qmlRegisterType(uri, 1, 0, "NetworkManager"); qmlRegisterUncreatableType(uri, 1, 0, "NetworkDevices", "Get it from NetworkManager"); qmlRegisterUncreatableType(uri, 1, 0, "WiredNetworkDevices", "Get it from NetworkManager"); diff --git a/libnymea-app/libnymea-app.pro b/libnymea-app/libnymea-app.pro index 273e7d6b..e47a1e6d 100644 --- a/libnymea-app/libnymea-app.pro +++ b/libnymea-app/libnymea-app.pro @@ -160,6 +160,11 @@ SOURCES += \ models/devicemodel.cpp \ system/systemcontroller.cpp \ thinggroup.cpp \ + zigbee/zigbeeadapters.cpp \ + zigbee/zigbeeadaptersproxy.cpp \ + zigbee/zigbeemanager.cpp \ + zigbee/zigbeeadapter.cpp \ + HEADERS += \ @@ -299,6 +304,10 @@ HEADERS += \ models/devicemodel.h \ system/systemcontroller.h \ thinggroup.h \ + zigbee/zigbeeadapters.h \ + zigbee/zigbeeadaptersproxy.h \ + zigbee/zigbeemanager.h \ + zigbee/zigbeeadapter.h \ ubports: { DEFINES += UBPORTS diff --git a/libnymea-app/zigbee/zigbeeadapter.cpp b/libnymea-app/zigbee/zigbeeadapter.cpp new file mode 100644 index 00000000..3f13415e --- /dev/null +++ b/libnymea-app/zigbee/zigbeeadapter.cpp @@ -0,0 +1,125 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 "zigbeeadapter.h" + +ZigbeeAdapter::ZigbeeAdapter(QObject *parent) : QObject(parent) +{ + +} + +QString ZigbeeAdapter::name() const +{ + return m_name; +} + +void ZigbeeAdapter::setName(const QString &name) +{ + m_name = name; + emit nameChanged(); +} + +QString ZigbeeAdapter::description() const +{ + return m_description; +} + +void ZigbeeAdapter::setDescription(const QString &description) +{ + m_description = description; + emit descriptionChanged(); +} + +QString ZigbeeAdapter::systemLocation() const +{ + return m_systemLocation; +} + +void ZigbeeAdapter::setSystemLocation(const QString &systemLocation) +{ + m_systemLocation = systemLocation; + emit systemLocationChanged(); +} + +bool ZigbeeAdapter::hardwareRecognized() const +{ + return m_hardwareRecognized; +} + +void ZigbeeAdapter::setHardwareRecognized(bool hardwareRecognized) +{ + m_hardwareRecognized = hardwareRecognized; + emit hardwareRecognizedChanged(); +} + +ZigbeeAdapter::ZigbeeBackendType ZigbeeAdapter::backendType() const +{ + return m_backendType; +} + +void ZigbeeAdapter::setBackendType(ZigbeeAdapter::ZigbeeBackendType backendType) +{ + m_backendType = backendType; + emit backendTypeChanged(); +} + +qint32 ZigbeeAdapter::baudRate() const +{ + return m_baudRate; +} + +void ZigbeeAdapter::setBaudRate(qint32 baudRate) +{ + m_baudRate = baudRate; + emit baudRateChanged(); +} + +bool ZigbeeAdapter::operator==(const ZigbeeAdapter &other) const +{ + return m_systemLocation == other.systemLocation() + && m_name == other.name() + && m_description == other.description() + && m_hardwareRecognized == other.hardwareRecognized() + && m_backendType == other.backendType() + && m_baudRate == other.baudRate(); +} + +ZigbeeAdapter::ZigbeeBackendType ZigbeeAdapter::stringToZigbeeBackendType(const QString &backendTypeString) +{ + if (backendTypeString == "ZigbeeBackendTypeNxp") { + return ZigbeeBackendTypeNxp; + } else if (backendTypeString == "ZigbeeBackendTypeDeconz") { + return ZigbeeBackendTypeDeconz; + } else { + // default if not recognized + return ZigbeeBackendTypeDeconz; + } +} + diff --git a/libnymea-app/zigbee/zigbeeadapter.h b/libnymea-app/zigbee/zigbeeadapter.h new file mode 100644 index 00000000..22375061 --- /dev/null +++ b/libnymea-app/zigbee/zigbeeadapter.h @@ -0,0 +1,94 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 ZIGBEEADAPTER_H +#define ZIGBEEADAPTER_H + +#include + +class ZigbeeAdapter : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged) + Q_PROPERTY(QString systemLocation READ systemLocation WRITE setSystemLocation NOTIFY systemLocationChanged) + Q_PROPERTY(bool hardwareRecognized READ hardwareRecognized WRITE setHardwareRecognized NOTIFY hardwareRecognizedChanged) + Q_PROPERTY(ZigbeeAdapter::ZigbeeBackendType backendType READ backendType WRITE setBackendType NOTIFY backendTypeChanged) + Q_PROPERTY(qint32 baudRate READ baudRate WRITE setBaudRate NOTIFY baudRateChanged) + +public: + enum ZigbeeBackendType { + ZigbeeBackendTypeDeconz, + ZigbeeBackendTypeNxp + }; + Q_ENUM(ZigbeeBackendType) + + explicit ZigbeeAdapter(QObject *parent = nullptr); + + QString name() const; + void setName(const QString &name); + + QString description() const; + void setDescription(const QString &description); + + QString systemLocation() const; + void setSystemLocation(const QString &systemLocation); + + bool hardwareRecognized() const; + void setHardwareRecognized(bool hardwareRecognized); + + ZigbeeAdapter::ZigbeeBackendType backendType() const; + void setBackendType(ZigbeeAdapter::ZigbeeBackendType backendType); + + qint32 baudRate() const; + void setBaudRate(qint32 baudRate); + + bool operator==(const ZigbeeAdapter &other) const; + + static ZigbeeAdapter::ZigbeeBackendType stringToZigbeeBackendType(const QString &backendTypeString); + +private: + QString m_name; + QString m_description; + QString m_systemLocation; + bool m_hardwareRecognized = false; + ZigbeeAdapter::ZigbeeBackendType m_backendType = ZigbeeAdapter::ZigbeeBackendTypeDeconz; + qint32 m_baudRate = 38400; + +signals: + void nameChanged(); + void descriptionChanged(); + void systemLocationChanged(); + void hardwareRecognizedChanged(); + void backendTypeChanged(); + void baudRateChanged(); +}; + +#endif // ZIGBEEADAPTER_H diff --git a/libnymea-app/zigbee/zigbeeadapters.cpp b/libnymea-app/zigbee/zigbeeadapters.cpp new file mode 100644 index 00000000..ae422bad --- /dev/null +++ b/libnymea-app/zigbee/zigbeeadapters.cpp @@ -0,0 +1,143 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 "zigbeeadapters.h" + +ZigbeeAdapters::ZigbeeAdapters(QObject *parent) : QAbstractListModel(parent) +{ + +} + +int ZigbeeAdapters::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return m_adapters.count(); +} + +QVariant ZigbeeAdapters::data(const QModelIndex &index, int role) const +{ + switch (role) { + case RoleName: + return m_adapters.at(index.row())->name(); + case RoleDescription: + return m_adapters.at(index.row())->description(); + case RoleSystemLocation: + return m_adapters.at(index.row())->systemLocation(); + case RoleHardwareRecognized: + return m_adapters.at(index.row())->hardwareRecognized(); + case RoleBackendType: + return m_adapters.at(index.row())->backendType(); + case RoleBaudRate: + return m_adapters.at(index.row())->baudRate(); + } + return QVariant(); +} + +QHash ZigbeeAdapters::roleNames() const +{ + QHash roles; + roles.insert(RoleName, "name"); + roles.insert(RoleDescription, "description"); + roles.insert(RoleSystemLocation, "systemLocation"); + roles.insert(RoleHardwareRecognized, "hardwareRecognized"); + roles.insert(RoleBackendType, "backendType"); + roles.insert(RoleBaudRate, "baudRate"); + return roles; +} + +void ZigbeeAdapters::addAdapter(ZigbeeAdapter *adapter) +{ + adapter->setParent(this); + beginInsertRows(QModelIndex(), m_adapters.count(), m_adapters.count()); + m_adapters.append(adapter); + + connect(adapter, &ZigbeeAdapter::nameChanged, this, [this, adapter]() { + QModelIndex idx = index(m_adapters.indexOf(adapter), 0); + emit dataChanged(idx, idx, {RoleName}); + }); + + connect(adapter, &ZigbeeAdapter::descriptionChanged, this, [this, adapter]() { + QModelIndex idx = index(m_adapters.indexOf(adapter), 0); + emit dataChanged(idx, idx, {RoleDescription}); + }); + + connect(adapter, &ZigbeeAdapter::systemLocationChanged, this, [this, adapter]() { + QModelIndex idx = index(m_adapters.indexOf(adapter), 0); + emit dataChanged(idx, idx, {RoleSystemLocation}); + }); + + connect(adapter, &ZigbeeAdapter::hardwareRecognizedChanged, this, [this, adapter]() { + QModelIndex idx = index(m_adapters.indexOf(adapter), 0); + emit dataChanged(idx, idx, {RoleHardwareRecognized}); + }); + + connect(adapter, &ZigbeeAdapter::backendTypeChanged, this, [this, adapter]() { + QModelIndex idx = index(m_adapters.indexOf(adapter), 0); + emit dataChanged(idx, idx, {RoleBackendType}); + }); + + connect(adapter, &ZigbeeAdapter::baudRateChanged, this, [this, adapter]() { + QModelIndex idx = index(m_adapters.indexOf(adapter), 0); + emit dataChanged(idx, idx, {RoleBaudRate}); + }); + + + endInsertRows(); + emit countChanged(); +} + +void ZigbeeAdapters::removeAdapter(const QString &systemLocation) +{ + for (int i = 0; i < m_adapters.count(); i++) { + if (m_adapters.at(i)->systemLocation() == systemLocation) { + beginRemoveRows(QModelIndex(), i, i); + m_adapters.takeAt(i)->deleteLater(); + endRemoveRows(); + return; + } + } +} + +void ZigbeeAdapters::clear() +{ + beginResetModel(); + qDeleteAll(m_adapters); + m_adapters.clear(); + endResetModel(); + emit countChanged(); +} + +ZigbeeAdapter *ZigbeeAdapters::get(int index) const +{ + if (index < 0 || index > m_adapters.count() - 1) { + return nullptr; + } + return m_adapters.at(index); +} diff --git a/libnymea-app/zigbee/zigbeeadapters.h b/libnymea-app/zigbee/zigbeeadapters.h new file mode 100644 index 00000000..7a0f4b5c --- /dev/null +++ b/libnymea-app/zigbee/zigbeeadapters.h @@ -0,0 +1,77 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 ZIGBEEADAPTERS_H +#define ZIGBEEADAPTERS_H + +#include +#include + +#include "zigbeeadapter.h" + +class ZigbeeAdapters : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + +public: + enum Roles { + RoleName, + RoleDescription, + RoleSystemLocation, + RoleHardwareRecognized, + RoleBackendType, + RoleBaudRate + }; + Q_ENUM(Roles) + + explicit ZigbeeAdapters(QObject *parent = nullptr); + virtual ~ZigbeeAdapters() override = default; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; + + void addAdapter(ZigbeeAdapter *adapter); + void removeAdapter(const QString &systemLocation); + + void clear(); + + Q_INVOKABLE virtual ZigbeeAdapter *get(int index) const; + +signals: + void countChanged(); + +protected: + QList m_adapters; + +}; + +#endif // ZIGBEEADAPTERS_H diff --git a/libnymea-app/zigbee/zigbeeadaptersproxy.cpp b/libnymea-app/zigbee/zigbeeadaptersproxy.cpp new file mode 100644 index 00000000..6a45c755 --- /dev/null +++ b/libnymea-app/zigbee/zigbeeadaptersproxy.cpp @@ -0,0 +1,93 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 "zigbeeadaptersproxy.h" + +#include "zigbeeadapters.h" + +ZigbeeAdaptersProxy::ZigbeeAdaptersProxy(QObject *parent) : QSortFilterProxyModel(parent) +{ + +} + +ZigbeeAdapters *ZigbeeAdaptersProxy::adapters() const +{ + return m_adapters; +} + +void ZigbeeAdaptersProxy::setAdapters(ZigbeeAdapters *adapters) +{ + m_adapters = adapters; + emit adaptersChanged(); + + setSourceModel(m_adapters); + connect(m_adapters, &ZigbeeAdapters::countChanged, this, &ZigbeeAdaptersProxy::countChanged); + setSortRole(ZigbeeAdapters::RoleSystemLocation); + sort(0, Qt::DescendingOrder); + invalidateFilter(); +} + +ZigbeeAdaptersProxy::HardwareFilter ZigbeeAdaptersProxy::hardwareFilter() const +{ + return m_hardwareFilter; +} + +void ZigbeeAdaptersProxy::setHardwareFilter(ZigbeeAdaptersProxy::HardwareFilter hardwareFilter) +{ + m_hardwareFilter = hardwareFilter; + emit hardwareFilterChanged(m_hardwareFilter); + invalidateFilter(); +} + +ZigbeeAdapter *ZigbeeAdaptersProxy::get(int index) const +{ + return m_adapters->get(mapToSource(this->index(index, 0)).row()); +} + +bool ZigbeeAdaptersProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + Q_UNUSED(source_parent) + + ZigbeeAdapter *adapter = m_adapters->get(source_row); + + if (m_hardwareFilter == HardwareFilterRecognized) { + if (adapter->hardwareRecognized() == false) { + return true; + } + } + + if (m_hardwareFilter == HardwareFilterUnrecognized) { + if (adapter->hardwareRecognized() == true) { + return true; + } + } + + return false; +} diff --git a/libnymea-app/zigbee/zigbeeadaptersproxy.h b/libnymea-app/zigbee/zigbeeadaptersproxy.h new file mode 100644 index 00000000..44fa53d4 --- /dev/null +++ b/libnymea-app/zigbee/zigbeeadaptersproxy.h @@ -0,0 +1,78 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 ZIGBEEADAPTERSPROXY_H +#define ZIGBEEADAPTERSPROXY_H + +#include +#include + +class ZigbeeAdapter; +class ZigbeeAdapters; + +class ZigbeeAdaptersProxy : public QSortFilterProxyModel +{ + Q_OBJECT + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + Q_PROPERTY(ZigbeeAdapters * adapters READ adapters WRITE setAdapters NOTIFY adaptersChanged) + Q_PROPERTY(ZigbeeAdaptersProxy::HardwareFilter hardwareFilter READ hardwareFilter WRITE setHardwareFilter NOTIFY hardwareFilterChanged) +public: + enum HardwareFilter { + HardwareFilterNone, + HardwareFilterRecognized, + HardwareFilterUnrecognized + }; + Q_ENUM(HardwareFilter) + + explicit ZigbeeAdaptersProxy(QObject *parent = nullptr); + + ZigbeeAdapters *adapters() const; + void setAdapters(ZigbeeAdapters *adapters); + + HardwareFilter hardwareFilter() const; + void setHardwareFilter(HardwareFilter hardwareFilter); + + Q_INVOKABLE ZigbeeAdapter* get(int index) const; + +protected: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; + +signals: + void countChanged(); + void adaptersChanged(); + void hardwareFilterChanged(HardwareFilter hardwareFilter); + +private: + ZigbeeAdapters *m_adapters = nullptr; + HardwareFilter m_hardwareFilter = HardwareFilterNone; + +}; + +#endif // ZIGBEEADAPTERSPROXY_H diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp new file mode 100644 index 00000000..152376b5 --- /dev/null +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -0,0 +1,111 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 "zigbeemanager.h" + +#include "jsonrpc/jsonrpcclient.h" +#include "zigbee/zigbeeadapters.h" + +ZigbeeManager::ZigbeeManager(JsonRpcClient *client, QObject *parent) : + JsonHandler(parent), + m_client(client), + m_adapters(new ZigbeeAdapters(this)) +{ + client->registerNotificationHandler(this, "notificationReceived"); +} + +ZigbeeManager::~ZigbeeManager() +{ + +} + +QString ZigbeeManager::nameSpace() const +{ + return "Zigbee"; +} + +ZigbeeAdapters *ZigbeeManager::adapters() const +{ + return m_adapters; +} + +void ZigbeeManager::init() +{ + qDebug() << "Zigbee init..."; + m_adapters->clear(); + m_client->sendCommand("Zigbee.GetAdapters", this, "getAdaptersResponse"); +} + +void ZigbeeManager::getAdaptersResponse(const QVariantMap ¶ms) +{ + qDebug() << "Get adapters response" << params; + m_adapters->clear(); + foreach (const QVariant &adapterVariant, params.value("params").toMap().value("adapters").toList()) { + QVariantMap adapterMap = adapterVariant.toMap(); + ZigbeeAdapter *adapter = new ZigbeeAdapter(m_adapters); + adapter->setName(adapterMap.value("name").toString()); + adapter->setDescription(adapterMap.value("description").toString()); + adapter->setSystemLocation(adapterMap.value("systemLocation").toString()); + adapter->setBackendType(ZigbeeAdapter::stringToZigbeeBackendType(adapterMap.value("backendType").toString())); + adapter->setBaudRate(adapterMap.value("baudRate").toUInt()); + qDebug() << "Zigbee adapter added" << adapter->description() << adapter->systemLocation(); + m_adapters->addAdapter(adapter); + } +} + +void ZigbeeManager::notificationReceived(const QVariantMap ¬ification) +{ + QString notificationString = notification.value("notification").toString(); + if (notificationString == "Zigbee.AdapterAdded") { + QVariantMap adapterMap = notification.value("params").toMap().value("adapter").toMap(); + m_adapters->addAdapter(unpackAdapter(adapterMap)); + return; + } + + if (notificationString == "Zigbee.AdapterRemoved") { + QVariantMap adapterMap = notification.value("params").toMap().value("adapter").toMap(); + m_adapters->removeAdapter(adapterMap.value("systemLocation").toString()); + return; + } + + qDebug() << "Unhandled Zigbee notification" << notificationString << notification; +} + +ZigbeeAdapter *ZigbeeManager::unpackAdapter(const QVariantMap &adapterMap) +{ + ZigbeeAdapter *adapter = new ZigbeeAdapter(m_adapters); + adapter->setName(adapterMap.value("name").toString()); + adapter->setDescription(adapterMap.value("description").toString()); + adapter->setSystemLocation(adapterMap.value("systemLocation").toString()); + adapter->setBackendType(ZigbeeAdapter::stringToZigbeeBackendType(adapterMap.value("backendType").toString())); + adapter->setBaudRate(adapterMap.value("baudRate").toUInt()); + return adapter; +} + diff --git a/libnymea-app/zigbee/zigbeemanager.h b/libnymea-app/zigbee/zigbeemanager.h new file mode 100644 index 00000000..56f99a8d --- /dev/null +++ b/libnymea-app/zigbee/zigbeemanager.h @@ -0,0 +1,72 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 ZIGBEEMANAGER_H +#define ZIGBEEMANAGER_H + +#include +#include "jsonrpc/jsonhandler.h" + +class JsonRpcClient; +class ZigbeeAdapter; +class ZigbeeAdapters; + +class ZigbeeManager : public JsonHandler +{ + Q_OBJECT + Q_PROPERTY(ZigbeeAdapters *adapters READ adapters CONSTANT) + +public: + explicit ZigbeeManager(JsonRpcClient* client, QObject *parent = nullptr); + ~ZigbeeManager(); + + QString nameSpace() const override; + + ZigbeeAdapters *adapters() const; + + void init(); + +signals: + +private: + Q_INVOKABLE void getAdaptersResponse(const QVariantMap ¶ms); + + Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification); + +private: + JsonRpcClient* m_client = nullptr; + ZigbeeAdapters *m_adapters = nullptr; + + ZigbeeAdapter *unpackAdapter(const QVariantMap &adapterMap); + + +}; + +#endif // ZIGBEEMANAGER_H diff --git a/nymea-app/images.qrc b/nymea-app/images.qrc index 4e3c404a..c9e73fe0 100644 --- a/nymea-app/images.qrc +++ b/nymea-app/images.qrc @@ -241,5 +241,6 @@ ui/images/state-in.svg ui/images/state-out.svg ui/images/like.svg + ui/images/zigbee.svg diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc index bea8e76d..87ea25d0 100644 --- a/nymea-app/resources.qrc +++ b/nymea-app/resources.qrc @@ -225,5 +225,7 @@ ui/components/ThingStatusIcons.qml ui/components/InfoPaneBase.qml ui/components/ThingInfoPane.qml + ui/system/ZigbeeNetworkSettingsPage.qml + ui/system/ZigbeeNetworkAddPage.qml diff --git a/nymea-app/ui/SettingsPage.qml b/nymea-app/ui/SettingsPage.qml index 726eb19f..77cef0d9 100644 --- a/nymea-app/ui/SettingsPage.qml +++ b/nymea-app/ui/SettingsPage.qml @@ -153,6 +153,23 @@ Page { } } + Pane { + Layout.fillWidth: true + Material.elevation: layout.isGrid ? 1 : 0 + visible: engine.jsonRpcClient.ensureServerVersion("1.11") + + padding: 0 + NymeaListItemDelegate { + width: parent.width + iconName: "../images/zigbee.svg" + text: qsTr("ZigBee networking") + subText: qsTr("Manage and configure ZigBee networks") + prominentSubText: false + wrapTexts: false + onClicked: pageStack.push(Qt.resolvedUrl("system/ZigbeeNetworkSettingsPage.qml")) + } + } + Pane { Layout.fillWidth: true Material.elevation: layout.isGrid ? 1 : 0 diff --git a/nymea-app/ui/images/zigbee.svg b/nymea-app/ui/images/zigbee.svg new file mode 100644 index 00000000..5366feb6 --- /dev/null +++ b/nymea-app/ui/images/zigbee.svg @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml new file mode 100644 index 00000000..ced5a2b7 --- /dev/null +++ b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml @@ -0,0 +1,81 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 +import Nymea 1.0 + +import "../components" + +SettingsPageBase { + id: root + title: qsTr("Add a new ZigBee network") + + SettingsPageSectionHeader { + text: qsTr("ZigBee adapters") + } + + Repeater { + model: ZigbeeAdaptersProxy { + adapters: engine.zigbeeManager.adapters + hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterRecognized + } + + delegate: NymeaListItemDelegate { + Layout.fillWidth: true + property var adapter: engine.zigbeeManager.adapters.get(index) + iconName: "../images/stock_link.svg" + text: model.description + " - " + model.systemLocation + //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) + } + } + + SettingsPageSectionHeader { + text: qsTr("Unrecognized ZigBee adapters") + } + + Repeater { + model: ZigbeeAdaptersProxy { + adapters: engine.zigbeeManager.adapters + hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterUnrecognized + } + + delegate: NymeaListItemDelegate { + Layout.fillWidth: true + property var adapter: engine.zigbeeManager.adapters.get(index) + iconName: "../images/stock_link.svg" + text: model.description + " - " + model.systemLocation + //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) + } + } + + +} diff --git a/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml b/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml new file mode 100644 index 00000000..60183519 --- /dev/null +++ b/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml @@ -0,0 +1,75 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.8 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.3 +import "../components" +import Nymea 1.0 + +Page { + id: root + header: NymeaHeader { + text: qsTr("ZigBee networking") + backButtonVisible: true + onBackPressed: pageStack.pop() + + HeaderButton { + text: qsTr("Settings") + imageSource: "../images/settings.svg" + onClicked: { + //pageStack.push() + } + } + } + + ColumnLayout { + id: contentColumn + anchors.fill: parent + + // List networks + SettingsPageSectionHeader { + text: qsTr("ZigBee networks") + } + + + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Add ZigBee network") + subText: qsTr("Set up a new ZigBee network") + prominentSubText: false + onClicked: { + pageStack.push(Qt.resolvedUrl("../system/ZigbeeNetworkAddPage.qml")) + } + } + } +} From 7013e726aa7413a4e119de3944b7b1b13f755a7e Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 2 Nov 2020 17:16:36 +0100 Subject: [PATCH 02/18] ZigBee -> Zigbee, as per spec --- nymea-app/ui/SettingsPage.qml | 4 ++-- nymea-app/ui/system/ZigbeeNetworkAddPage.qml | 6 +++--- nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/nymea-app/ui/SettingsPage.qml b/nymea-app/ui/SettingsPage.qml index 77cef0d9..3ab74e44 100644 --- a/nymea-app/ui/SettingsPage.qml +++ b/nymea-app/ui/SettingsPage.qml @@ -162,8 +162,8 @@ Page { NymeaListItemDelegate { width: parent.width iconName: "../images/zigbee.svg" - text: qsTr("ZigBee networking") - subText: qsTr("Manage and configure ZigBee networks") + text: qsTr("Zigbee") + subText: qsTr("Manage and configure Zigbee networks") prominentSubText: false wrapTexts: false onClicked: pageStack.push(Qt.resolvedUrl("system/ZigbeeNetworkSettingsPage.qml")) diff --git a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml index ced5a2b7..a3fe13ca 100644 --- a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml @@ -37,10 +37,10 @@ import "../components" SettingsPageBase { id: root - title: qsTr("Add a new ZigBee network") + title: qsTr("Add a new Zigbee network") SettingsPageSectionHeader { - text: qsTr("ZigBee adapters") + text: qsTr("Zigbee adapters") } Repeater { @@ -59,7 +59,7 @@ SettingsPageBase { } SettingsPageSectionHeader { - text: qsTr("Unrecognized ZigBee adapters") + text: qsTr("Unrecognized Zigbee adapters") } Repeater { diff --git a/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml b/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml index 60183519..2b83ad9c 100644 --- a/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml @@ -35,10 +35,10 @@ import QtQuick.Layouts 1.3 import "../components" import Nymea 1.0 -Page { +SettingsPageBase { id: root header: NymeaHeader { - text: qsTr("ZigBee networking") + text: qsTr("Zigbee") backButtonVisible: true onBackPressed: pageStack.pop() @@ -57,15 +57,15 @@ Page { // List networks SettingsPageSectionHeader { - text: qsTr("ZigBee networks") + text: qsTr("Zigbee networks") } NymeaListItemDelegate { Layout.fillWidth: true - text: qsTr("Add ZigBee network") - subText: qsTr("Set up a new ZigBee network") + text: qsTr("Add Zigbee network") + subText: qsTr("Set up a new Zigbee network") prominentSubText: false onClicked: { pageStack.push(Qt.resolvedUrl("../system/ZigbeeNetworkAddPage.qml")) From 28ff3e29f1ba42b506d75a4d90babf1a58bd1f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Tue, 3 Nov 2020 23:18:56 +0100 Subject: [PATCH 03/18] Add zigbee networks model and notifications --- QtZeroConf | 2 +- libnymea-app/libnymea-app-core.h | 4 + libnymea-app/libnymea-app.pro | 4 + libnymea-app/zigbee/zigbeeadapter.cpp | 12 + libnymea-app/zigbee/zigbeeadapter.h | 3 + libnymea-app/zigbee/zigbeeadapters.cpp | 3 - libnymea-app/zigbee/zigbeeadaptersproxy.cpp | 23 +- libnymea-app/zigbee/zigbeemanager.cpp | 86 ++++++- libnymea-app/zigbee/zigbeemanager.h | 11 +- libnymea-app/zigbee/zigbeenetwork.cpp | 237 ++++++++++++++++++ libnymea-app/zigbee/zigbeenetwork.h | 141 +++++++++++ libnymea-app/zigbee/zigbeenetworks.cpp | 211 ++++++++++++++++ libnymea-app/zigbee/zigbeenetworks.h | 85 +++++++ nymea-app/ui/system/ZigbeeNetworkAddPage.qml | 4 +- .../ui/system/ZigbeeNetworkSettingsPage.qml | 16 ++ 15 files changed, 811 insertions(+), 31 deletions(-) create mode 100644 libnymea-app/zigbee/zigbeenetwork.cpp create mode 100644 libnymea-app/zigbee/zigbeenetwork.h create mode 100644 libnymea-app/zigbee/zigbeenetworks.cpp create mode 100644 libnymea-app/zigbee/zigbeenetworks.h diff --git a/QtZeroConf b/QtZeroConf index cbf4f2bf..39efbe28 160000 --- a/QtZeroConf +++ b/QtZeroConf @@ -1 +1 @@ -Subproject commit cbf4f2bf7b926b9a874af013efbf0f6dde3155e9 +Subproject commit 39efbe2879d93bd483ee1f14fc94281a03b49935 diff --git a/libnymea-app/libnymea-app-core.h b/libnymea-app/libnymea-app-core.h index a6d6987f..89539b1c 100644 --- a/libnymea-app/libnymea-app-core.h +++ b/libnymea-app/libnymea-app-core.h @@ -124,6 +124,8 @@ #include "zigbee/zigbeeadapter.h" #include "zigbee/zigbeeadapters.h" #include "zigbee/zigbeeadaptersproxy.h" +#include "zigbee/zigbeenetwork.h" +#include "zigbee/zigbeenetworks.h" #include @@ -304,6 +306,8 @@ void registerQmlTypes() { qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeAdapter", "Get it from the ZigbeeAdapters"); qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeAdapters", "Get it from ZigbeeManager"); qmlRegisterType(uri, 1, 0, "ZigbeeAdaptersProxy"); + qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeNetwork", "Get it from the ZigbeeManager"); + qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeNetworks", "Get it from the ZigbeeManager"); qmlRegisterType(uri, 1, 0, "NetworkManager"); qmlRegisterUncreatableType(uri, 1, 0, "NetworkDevices", "Get it from NetworkManager"); diff --git a/libnymea-app/libnymea-app.pro b/libnymea-app/libnymea-app.pro index e47a1e6d..b0cdc5b9 100644 --- a/libnymea-app/libnymea-app.pro +++ b/libnymea-app/libnymea-app.pro @@ -164,6 +164,8 @@ SOURCES += \ zigbee/zigbeeadaptersproxy.cpp \ zigbee/zigbeemanager.cpp \ zigbee/zigbeeadapter.cpp \ + zigbee/zigbeenetwork.cpp \ + zigbee/zigbeenetworks.cpp @@ -308,6 +310,8 @@ HEADERS += \ zigbee/zigbeeadaptersproxy.h \ zigbee/zigbeemanager.h \ zigbee/zigbeeadapter.h \ + zigbee/zigbeenetwork.h \ + zigbee/zigbeenetworks.h ubports: { DEFINES += UBPORTS diff --git a/libnymea-app/zigbee/zigbeeadapter.cpp b/libnymea-app/zigbee/zigbeeadapter.cpp index 3f13415e..e4e65730 100644 --- a/libnymea-app/zigbee/zigbeeadapter.cpp +++ b/libnymea-app/zigbee/zigbeeadapter.cpp @@ -123,3 +123,15 @@ ZigbeeAdapter::ZigbeeBackendType ZigbeeAdapter::stringToZigbeeBackendType(const } } +QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter) +{ + debug.nospace() << "ZigbeeAdapter(" << adapter.name() << " - " << adapter.description(); + debug.nospace() << ", " << adapter.systemLocation(); + if (adapter.hardwareRecognized()) { + debug.nospace() << " Hardware recognized: " << adapter.backendType(); + debug.nospace() << ", " << adapter.baudRate(); + } + + debug.nospace() << ")"; + return debug.space(); +} diff --git a/libnymea-app/zigbee/zigbeeadapter.h b/libnymea-app/zigbee/zigbeeadapter.h index 22375061..d3faeda0 100644 --- a/libnymea-app/zigbee/zigbeeadapter.h +++ b/libnymea-app/zigbee/zigbeeadapter.h @@ -31,6 +31,7 @@ #ifndef ZIGBEEADAPTER_H #define ZIGBEEADAPTER_H +#include #include class ZigbeeAdapter : public QObject @@ -91,4 +92,6 @@ signals: void baudRateChanged(); }; +QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter); + #endif // ZIGBEEADAPTER_H diff --git a/libnymea-app/zigbee/zigbeeadapters.cpp b/libnymea-app/zigbee/zigbeeadapters.cpp index ae422bad..9584f266 100644 --- a/libnymea-app/zigbee/zigbeeadapters.cpp +++ b/libnymea-app/zigbee/zigbeeadapters.cpp @@ -77,7 +77,6 @@ void ZigbeeAdapters::addAdapter(ZigbeeAdapter *adapter) adapter->setParent(this); beginInsertRows(QModelIndex(), m_adapters.count(), m_adapters.count()); m_adapters.append(adapter); - connect(adapter, &ZigbeeAdapter::nameChanged, this, [this, adapter]() { QModelIndex idx = index(m_adapters.indexOf(adapter), 0); emit dataChanged(idx, idx, {RoleName}); @@ -107,8 +106,6 @@ void ZigbeeAdapters::addAdapter(ZigbeeAdapter *adapter) QModelIndex idx = index(m_adapters.indexOf(adapter), 0); emit dataChanged(idx, idx, {RoleBaudRate}); }); - - endInsertRows(); emit countChanged(); } diff --git a/libnymea-app/zigbee/zigbeeadaptersproxy.cpp b/libnymea-app/zigbee/zigbeeadaptersproxy.cpp index 6a45c755..63e04cab 100644 --- a/libnymea-app/zigbee/zigbeeadaptersproxy.cpp +++ b/libnymea-app/zigbee/zigbeeadaptersproxy.cpp @@ -45,13 +45,16 @@ ZigbeeAdapters *ZigbeeAdaptersProxy::adapters() const void ZigbeeAdaptersProxy::setAdapters(ZigbeeAdapters *adapters) { m_adapters = adapters; - emit adaptersChanged(); + connect(m_adapters, &ZigbeeAdapters::countChanged, this, [this](){ + invalidateFilter(); + emit countChanged(); + }); setSourceModel(m_adapters); - connect(m_adapters, &ZigbeeAdapters::countChanged, this, &ZigbeeAdaptersProxy::countChanged); setSortRole(ZigbeeAdapters::RoleSystemLocation); sort(0, Qt::DescendingOrder); invalidateFilter(); + emit countChanged(); } ZigbeeAdaptersProxy::HardwareFilter ZigbeeAdaptersProxy::hardwareFilter() const @@ -64,6 +67,7 @@ void ZigbeeAdaptersProxy::setHardwareFilter(ZigbeeAdaptersProxy::HardwareFilter m_hardwareFilter = hardwareFilter; emit hardwareFilterChanged(m_hardwareFilter); invalidateFilter(); + emit countChanged(); } ZigbeeAdapter *ZigbeeAdaptersProxy::get(int index) const @@ -76,18 +80,11 @@ bool ZigbeeAdaptersProxy::filterAcceptsRow(int source_row, const QModelIndex &so Q_UNUSED(source_parent) ZigbeeAdapter *adapter = m_adapters->get(source_row); - if (m_hardwareFilter == HardwareFilterRecognized) { - if (adapter->hardwareRecognized() == false) { - return true; - } + return adapter->hardwareRecognized(); + } else if (m_hardwareFilter == HardwareFilterUnrecognized) { + return !adapter->hardwareRecognized(); } - if (m_hardwareFilter == HardwareFilterUnrecognized) { - if (adapter->hardwareRecognized() == true) { - return true; - } - } - - return false; + return true; } diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp index 152376b5..04764b73 100644 --- a/libnymea-app/zigbee/zigbeemanager.cpp +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -31,12 +31,16 @@ #include "zigbeemanager.h" #include "jsonrpc/jsonrpcclient.h" +#include "zigbee/zigbeeadapter.h" #include "zigbee/zigbeeadapters.h" +#include "zigbee/zigbeenetwork.h" +#include "zigbee/zigbeenetworks.h" ZigbeeManager::ZigbeeManager(JsonRpcClient *client, QObject *parent) : JsonHandler(parent), m_client(client), - m_adapters(new ZigbeeAdapters(this)) + m_adapters(new ZigbeeAdapters(this)), + m_networks(new ZigbeeNetworks(this)) { client->registerNotificationHandler(this, "notificationReceived"); } @@ -56,30 +60,43 @@ ZigbeeAdapters *ZigbeeManager::adapters() const return m_adapters; } +ZigbeeNetworks *ZigbeeManager::networks() const +{ + return m_networks; +} + void ZigbeeManager::init() { qDebug() << "Zigbee init..."; m_adapters->clear(); m_client->sendCommand("Zigbee.GetAdapters", this, "getAdaptersResponse"); + m_client->sendCommand("Zigbee.GetNetworks", this, "getNetworksResponse"); } -void ZigbeeManager::getAdaptersResponse(const QVariantMap ¶ms) +void ZigbeeManager::getAdaptersResponse(int commandId, const QVariantMap ¶ms) { - qDebug() << "Get adapters response" << params; + qDebug() << "Zigbee get adapters response" << commandId << params; m_adapters->clear(); - foreach (const QVariant &adapterVariant, params.value("params").toMap().value("adapters").toList()) { + foreach (const QVariant &adapterVariant, params.value("adapters").toList()) { QVariantMap adapterMap = adapterVariant.toMap(); - ZigbeeAdapter *adapter = new ZigbeeAdapter(m_adapters); - adapter->setName(adapterMap.value("name").toString()); - adapter->setDescription(adapterMap.value("description").toString()); - adapter->setSystemLocation(adapterMap.value("systemLocation").toString()); - adapter->setBackendType(ZigbeeAdapter::stringToZigbeeBackendType(adapterMap.value("backendType").toString())); - adapter->setBaudRate(adapterMap.value("baudRate").toUInt()); + ZigbeeAdapter *adapter = unpackAdapter(adapterMap); qDebug() << "Zigbee adapter added" << adapter->description() << adapter->systemLocation(); m_adapters->addAdapter(adapter); } } +void ZigbeeManager::getNetworksResponse(int commandId, const QVariantMap ¶ms) +{ + qDebug() << "Zigbee get networks response" << commandId << params; + m_adapters->clear(); + foreach (const QVariant &networkVariant, params.value("zigbeeNetworks").toList()) { + QVariantMap networkMap = networkVariant.toMap(); + ZigbeeNetwork *network = unpackNetwork(networkMap); + qDebug() << "Zigbee network added" << network->networkUuid().toString() << network->serialPort() << network->macAddress(); + m_networks->addNetwork(network); + } +} + void ZigbeeManager::notificationReceived(const QVariantMap ¬ification) { QString notificationString = notification.value("notification").toString(); @@ -95,6 +112,30 @@ void ZigbeeManager::notificationReceived(const QVariantMap ¬ification) return; } + if (notificationString == "Zigbee.NetworkAdded") { + QVariantMap networkMap = notification.value("params").toMap().value("zigbeeNetwork").toMap(); + m_networks->addNetwork(unpackNetwork(networkMap)); + return; + } + + if (notificationString == "Zigbee.NetworkRemoved") { + QUuid networkUuid = notification.value("params").toMap().value("zigbeeNetwork").toUuid(); + m_networks->removeNetwork(networkUuid); + return; + } + + if (notificationString == "Zigbee.NetworkChanged") { + QVariantMap networkMap = notification.value("params").toMap().value("zigbeeNetwork").toMap(); + QUuid networkUuid = networkMap.value("networkUuid").toUuid(); + ZigbeeNetwork *network = m_networks->getNetwork(networkUuid); + if (!network) { + qWarning() << "Could not find network for changed notification"; + return; + } + fillNetworkData(network, networkMap); + return; + } + qDebug() << "Unhandled Zigbee notification" << notificationString << notification; } @@ -104,8 +145,33 @@ ZigbeeAdapter *ZigbeeManager::unpackAdapter(const QVariantMap &adapterMap) adapter->setName(adapterMap.value("name").toString()); adapter->setDescription(adapterMap.value("description").toString()); adapter->setSystemLocation(adapterMap.value("systemLocation").toString()); + adapter->setHardwareRecognized(adapterMap.value("hardwareRecognized").toBool()); adapter->setBackendType(ZigbeeAdapter::stringToZigbeeBackendType(adapterMap.value("backendType").toString())); adapter->setBaudRate(adapterMap.value("baudRate").toUInt()); return adapter; } +ZigbeeNetwork *ZigbeeManager::unpackNetwork(const QVariantMap &networkMap) +{ + ZigbeeNetwork *network = new ZigbeeNetwork(m_networks); + fillNetworkData(network, networkMap); + return network; +} + +void ZigbeeManager::fillNetworkData(ZigbeeNetwork *network, const QVariantMap &networkMap) +{ + network->setNetworkUuid(networkMap.value("networkUuid").toUuid()); + network->setSerialPort(networkMap.value("serialPort").toString()); + network->setBaudRate(networkMap.value("baudRate").toUInt()); + network->setMacAddress(networkMap.value("macAddress").toString()); + network->setFirmwareVersion(networkMap.value("firmwareVersion").toString()); + network->setPanId(networkMap.value("panId").toUInt()); + network->setChannel(networkMap.value("channel").toUInt()); + network->setChannelMask(networkMap.value("channelMask").toUInt()); + network->setPermitJoiningEnabled(networkMap.value("permitJoiningEnabled").toBool()); + network->setPermitJoiningDuration(networkMap.value("permitJoiningDuration").toUInt()); + network->setPermitJoiningRemaining(networkMap.value("permitJoiningRemaining").toUInt()); + network->setBackendType(ZigbeeAdapter::stringToZigbeeBackendType(networkMap.value("backendType").toString())); + network->setNetworkState(ZigbeeNetwork::stringToZigbeeNetworkState(networkMap.value("networkState").toString())); +} + diff --git a/libnymea-app/zigbee/zigbeemanager.h b/libnymea-app/zigbee/zigbeemanager.h index 56f99a8d..057c388f 100644 --- a/libnymea-app/zigbee/zigbeemanager.h +++ b/libnymea-app/zigbee/zigbeemanager.h @@ -37,11 +37,14 @@ class JsonRpcClient; class ZigbeeAdapter; class ZigbeeAdapters; +class ZigbeeNetwork; +class ZigbeeNetworks; class ZigbeeManager : public JsonHandler { Q_OBJECT Q_PROPERTY(ZigbeeAdapters *adapters READ adapters CONSTANT) + Q_PROPERTY(ZigbeeNetworks *networks READ networks CONSTANT) public: explicit ZigbeeManager(JsonRpcClient* client, QObject *parent = nullptr); @@ -50,22 +53,26 @@ public: QString nameSpace() const override; ZigbeeAdapters *adapters() const; + ZigbeeNetworks *networks() const; void init(); signals: private: - Q_INVOKABLE void getAdaptersResponse(const QVariantMap ¶ms); + Q_INVOKABLE void getAdaptersResponse(int commandId, const QVariantMap ¶ms); + Q_INVOKABLE void getNetworksResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification); private: JsonRpcClient* m_client = nullptr; ZigbeeAdapters *m_adapters = nullptr; + ZigbeeNetworks *m_networks = nullptr; ZigbeeAdapter *unpackAdapter(const QVariantMap &adapterMap); - + ZigbeeNetwork *unpackNetwork(const QVariantMap &networkMap); + void fillNetworkData(ZigbeeNetwork *network, const QVariantMap &networkMap); }; diff --git a/libnymea-app/zigbee/zigbeenetwork.cpp b/libnymea-app/zigbee/zigbeenetwork.cpp new file mode 100644 index 00000000..7eaa61a4 --- /dev/null +++ b/libnymea-app/zigbee/zigbeenetwork.cpp @@ -0,0 +1,237 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 "zigbeenetwork.h" + +ZigbeeNetwork::ZigbeeNetwork(QObject *parent) : QObject(parent) +{ + +} + +QUuid ZigbeeNetwork::networkUuid() const +{ + return m_networkUuid; +} + +void ZigbeeNetwork::setNetworkUuid(const QUuid &networkUuid) +{ + if (m_networkUuid == networkUuid) + return; + + m_networkUuid = networkUuid; + emit networkUuidChanged(); +} + +QString ZigbeeNetwork::serialPort() const +{ + return m_serialPort; +} + +void ZigbeeNetwork::setSerialPort(const QString &serialPort) +{ + if (m_serialPort == serialPort) + return; + + m_serialPort = serialPort; + emit serialPortChanged(); +} + +uint ZigbeeNetwork::baudRate() const +{ + return m_baudRate; +} + +void ZigbeeNetwork::setBaudRate(uint baudRate) +{ + if (m_baudRate == baudRate) + return; + + m_baudRate = baudRate; + emit baudRateChanged(); +} + +QString ZigbeeNetwork::macAddress() const +{ + return m_macAddress; +} + +void ZigbeeNetwork::setMacAddress(const QString &macAddress) +{ + if (m_macAddress == macAddress) + return; + + m_macAddress = macAddress; + emit macAddressChanged(); +} + +QString ZigbeeNetwork::firmwareVersion() const +{ + return m_firmwareVersion; +} + +void ZigbeeNetwork::setFirmwareVersion(const QString &firmwareVersion) +{ + if (m_firmwareVersion == firmwareVersion) + return; + + m_firmwareVersion = firmwareVersion; + emit firmwareVersionChanged(); +} + +uint ZigbeeNetwork::panId() const +{ + return m_panId; +} + +void ZigbeeNetwork::setPanId(uint panId) +{ + if (m_panId == panId) + return; + + m_panId = panId; + emit panIdChanged(); +} + +uint ZigbeeNetwork::channel() const +{ + return m_channel; +} + +void ZigbeeNetwork::setChannel(uint channel) +{ + if (m_channel == channel) + return; + + m_channel = channel; + emit channelChanged(); +} + +uint ZigbeeNetwork::channelMask() const +{ + return m_channelMask; +} + +void ZigbeeNetwork::setChannelMask(uint channelMask) +{ + if (m_channelMask == channelMask) + return; + + m_channelMask = channelMask; + emit channelMaskChanged(); +} + +bool ZigbeeNetwork::permitJoiningEnabled() const +{ + return m_permitJoiningEnabled; +} + +void ZigbeeNetwork::setPermitJoiningEnabled(bool permitJoiningEnabled) +{ + if (m_permitJoiningEnabled == permitJoiningEnabled) + return; + + m_permitJoiningEnabled = permitJoiningEnabled; + emit permitJoiningEnabledChanged(); +} + +uint ZigbeeNetwork::permitJoiningDuration() const +{ + return m_permitJoiningDuration; +} + +void ZigbeeNetwork::setPermitJoiningDuration(uint permitJoiningDuration) +{ + if (m_permitJoiningDuration == permitJoiningDuration) + return; + + m_permitJoiningDuration = permitJoiningDuration; + emit permitJoiningDurationChanged(); +} + +uint ZigbeeNetwork::permitJoiningRemaining() const +{ + return m_permitJoiningRemaining; +} + +void ZigbeeNetwork::setPermitJoiningRemaining(uint permitJoiningRemaining) +{ + if (m_permitJoiningRemaining == permitJoiningRemaining) + return; + + m_permitJoiningRemaining = permitJoiningRemaining; + emit permitJoiningRemainingChanged(); +} + +ZigbeeAdapter::ZigbeeBackendType ZigbeeNetwork::backendType() const +{ + return m_backendType; +} + +void ZigbeeNetwork::setBackendType(ZigbeeAdapter::ZigbeeBackendType backendType) +{ + if (m_backendType == backendType) + return; + + m_backendType = backendType; + emit backendTypeChanged(); +} + +ZigbeeNetwork::ZigbeeNetworkState ZigbeeNetwork::networkState() const +{ + return m_networkState; +} + +void ZigbeeNetwork::setNetworkState(ZigbeeNetwork::ZigbeeNetworkState networkState) +{ + if (m_networkState == networkState) + return; + + m_networkState = networkState; + emit networkStateChanged(); +} + +ZigbeeNetwork::ZigbeeNetworkState ZigbeeNetwork::stringToZigbeeNetworkState(const QString &networkStateString) +{ + if (networkStateString == "ZigbeeNetworkStateOffline") { + return ZigbeeNetworkStateOffline; + } else if (networkStateString == "ZigbeeNetworkStateStarting") { + return ZigbeeNetworkStateStarting; + } else if (networkStateString == "ZigbeeNetworkStateUpdating") { + return ZigbeeNetworkStateUpdating; + } else if (networkStateString == "ZigbeeNetworkStateOnline") { + return ZigbeeNetworkStateOnline; + } else if (networkStateString == "ZigbeeNetworkStateError") { + return ZigbeeNetworkStateError; + } else { + return ZigbeeNetworkStateError; + } +} + + diff --git a/libnymea-app/zigbee/zigbeenetwork.h b/libnymea-app/zigbee/zigbeenetwork.h new file mode 100644 index 00000000..805e1bbd --- /dev/null +++ b/libnymea-app/zigbee/zigbeenetwork.h @@ -0,0 +1,141 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 ZIGBEENETWORK_H +#define ZIGBEENETWORK_H + +#include +#include + +#include "zigbeeadapter.h" + +class ZigbeeNetwork : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUuid networkUuid READ networkUuid NOTIFY networkUuidChanged) + Q_PROPERTY(QString serialPort READ serialPort NOTIFY serialPortChanged) + Q_PROPERTY(uint baudRate READ baudRate NOTIFY baudRateChanged) + Q_PROPERTY(QString macAddress READ macAddress NOTIFY macAddressChanged) + Q_PROPERTY(QString firmwareVersion READ firmwareVersion NOTIFY firmwareVersionChanged) + Q_PROPERTY(uint panId READ panId NOTIFY panIdChanged) + Q_PROPERTY(uint channel READ channel NOTIFY channelChanged) + Q_PROPERTY(uint channelMask READ channelMask NOTIFY channelMaskChanged) + Q_PROPERTY(bool permitJoiningEnabled READ permitJoiningEnabled NOTIFY permitJoiningEnabledChanged) + Q_PROPERTY(uint permitJoiningDuration READ permitJoiningDuration NOTIFY permitJoiningDurationChanged) + Q_PROPERTY(uint permitJoiningRemaining READ permitJoiningRemaining NOTIFY permitJoiningRemainingChanged) + Q_PROPERTY(ZigbeeAdapter::ZigbeeBackendType backendType READ backendType NOTIFY backendTypeChanged) + Q_PROPERTY(ZigbeeNetworkState networkState READ networkState NOTIFY networkStateChanged) + +public: + + enum ZigbeeNetworkState { + ZigbeeNetworkStateOffline, + ZigbeeNetworkStateStarting, + ZigbeeNetworkStateUpdating, + ZigbeeNetworkStateOnline, + ZigbeeNetworkStateError + }; + Q_ENUM(ZigbeeNetworkState) + + explicit ZigbeeNetwork(QObject *parent = nullptr); + + QUuid networkUuid() const; + void setNetworkUuid(const QUuid &networkUuid); + + QString serialPort() const; + void setSerialPort(const QString &serialPort); + + uint baudRate() const; + void setBaudRate(uint baudRate); + + QString macAddress() const; + void setMacAddress(const QString &macAddress); + + QString firmwareVersion() const; + void setFirmwareVersion(const QString &firmwareVersion); + + uint panId() const; + void setPanId(uint panId); + + uint channel() const; + void setChannel(uint channel); + + uint channelMask() const; + void setChannelMask(uint channelMask); + + bool permitJoiningEnabled() const; + void setPermitJoiningEnabled(bool permitJoiningEnabled); + + uint permitJoiningDuration() const; + void setPermitJoiningDuration(uint permitJoiningDuration); + + uint permitJoiningRemaining() const; + void setPermitJoiningRemaining(uint permitJoiningRemaining); + + ZigbeeAdapter::ZigbeeBackendType backendType() const; + void setBackendType(ZigbeeAdapter::ZigbeeBackendType backendType); + + ZigbeeNetworkState networkState() const; + void setNetworkState(ZigbeeNetworkState networkState); + + static ZigbeeNetworkState stringToZigbeeNetworkState(const QString &networkStateString); + +signals: + void networkUuidChanged(); + void serialPortChanged(); + void baudRateChanged(); + void macAddressChanged(); + void firmwareVersionChanged(); + void panIdChanged(); + void channelChanged(); + void channelMaskChanged(); + void permitJoiningEnabledChanged(); + void permitJoiningDurationChanged(); + void permitJoiningRemainingChanged(); + void backendTypeChanged(); + void networkStateChanged(); + +private: + QUuid m_networkUuid; + QString m_serialPort; + uint m_baudRate; + QString m_macAddress; + QString m_firmwareVersion; + uint m_panId; + uint m_channel; + uint m_channelMask; + bool m_permitJoiningEnabled; + uint m_permitJoiningDuration; + uint m_permitJoiningRemaining; + ZigbeeAdapter::ZigbeeBackendType m_backendType; + ZigbeeNetworkState m_networkState; +}; + +#endif // ZIGBEENETWORK_H diff --git a/libnymea-app/zigbee/zigbeenetworks.cpp b/libnymea-app/zigbee/zigbeenetworks.cpp new file mode 100644 index 00000000..41a3ec62 --- /dev/null +++ b/libnymea-app/zigbee/zigbeenetworks.cpp @@ -0,0 +1,211 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 "zigbeenetworks.h" + +ZigbeeNetworks::ZigbeeNetworks(QObject *parent) : QAbstractListModel(parent) +{ + +} + +int ZigbeeNetworks::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return m_networks.count(); +} + +QVariant ZigbeeNetworks::data(const QModelIndex &index, int role) const +{ + switch (role) { + case RoleUuid: + return m_networks.at(index.row())->networkUuid(); + case RoleSerialPort: + return m_networks.at(index.row())->serialPort(); + case RoleBaudRate: + return m_networks.at(index.row())->baudRate(); + case RoleMacAddress: + return m_networks.at(index.row())->macAddress(); + case RoleFirmwareVersion: + return m_networks.at(index.row())->firmwareVersion(); + case RolePanId: + return m_networks.at(index.row())->panId(); + case RoleChannel: + return m_networks.at(index.row())->channel(); + case RoleChannelMask: + return m_networks.at(index.row())->channelMask(); + case RolePermitJoiningEnabled: + return m_networks.at(index.row())->permitJoiningEnabled(); + case RolePermitJoiningDuration: + return m_networks.at(index.row())->permitJoiningDuration(); + case RolePermitJoiningRemaining: + return m_networks.at(index.row())->permitJoiningRemaining(); + case RoleBackendType: + return m_networks.at(index.row())->backendType(); + case RoleNetworkState: + return m_networks.at(index.row())->networkState(); + } + + return QVariant(); +} + +QHash ZigbeeNetworks::roleNames() const +{ + QHash roles; + roles.insert(RoleUuid, "networkUuid"); + roles.insert(RoleSerialPort, "serialPort"); + roles.insert(RoleBaudRate, "baudRate"); + roles.insert(RoleMacAddress, "macAddress"); + roles.insert(RoleFirmwareVersion, "firmwareVersion"); + roles.insert(RolePanId, "panId"); + roles.insert(RoleChannel, "channel"); + roles.insert(RoleChannelMask, "channelMask"); + roles.insert(RolePermitJoiningEnabled, "permitJoiningEnabled"); + roles.insert(RolePermitJoiningDuration, "permitJoiningDuration"); + roles.insert(RolePermitJoiningRemaining, "permitJoiningRemaining"); + roles.insert(RoleBackendType, "backendType"); + roles.insert(RoleNetworkState, "networkState"); + return roles; + +} + +void ZigbeeNetworks::addNetwork(ZigbeeNetwork *network) +{ + network->setParent(this); + beginInsertRows(QModelIndex(), m_networks.count(), m_networks.count()); + m_networks.append(network); + connect(network, &ZigbeeNetwork::networkUuidChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RoleUuid}); + }); + + connect(network, &ZigbeeNetwork::serialPortChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RoleSerialPort}); + }); + + connect(network, &ZigbeeNetwork::baudRateChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RoleBaudRate}); + }); + + connect(network, &ZigbeeNetwork::macAddressChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RoleMacAddress}); + }); + + connect(network, &ZigbeeNetwork::firmwareVersionChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RoleFirmwareVersion}); + }); + + connect(network, &ZigbeeNetwork::panIdChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RolePanId}); + }); + + connect(network, &ZigbeeNetwork::channelChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RoleChannel}); + }); + + connect(network, &ZigbeeNetwork::channelMaskChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RoleChannelMask}); + }); + + connect(network, &ZigbeeNetwork::permitJoiningEnabledChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RolePermitJoiningEnabled}); + }); + + connect(network, &ZigbeeNetwork::permitJoiningDurationChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RolePermitJoiningDuration}); + }); + + connect(network, &ZigbeeNetwork::permitJoiningRemainingChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RolePermitJoiningRemaining}); + }); + + connect(network, &ZigbeeNetwork::backendTypeChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RoleBackendType}); + }); + + connect(network, &ZigbeeNetwork::networkStateChanged, this, [this, network]() { + QModelIndex idx = index(m_networks.indexOf(network), 0); + emit dataChanged(idx, idx, {RoleNetworkState}); + }); + + endInsertRows(); + emit countChanged(); + +} + +void ZigbeeNetworks::removeNetwork(const QUuid &networkUuid) +{ + for (int i = 0; i < m_networks.count(); i++) { + if (m_networks.at(i)->networkUuid() == networkUuid) { + beginRemoveRows(QModelIndex(), i, i); + m_networks.takeAt(i)->deleteLater(); + endRemoveRows(); + return; + } + } +} + +void ZigbeeNetworks::clear() +{ + beginResetModel(); + qDeleteAll(m_networks); + m_networks.clear(); + endResetModel(); + emit countChanged(); +} + +ZigbeeNetwork *ZigbeeNetworks::get(int index) const +{ + if (index < 0 || index > m_networks.count() - 1) { + return nullptr; + } + return m_networks.at(index); +} + +ZigbeeNetwork *ZigbeeNetworks::getNetwork(const QUuid &networkUuid) const +{ + foreach (ZigbeeNetwork *network, m_networks) { + if (network->networkUuid() == networkUuid) { + return network; + } + } + + return nullptr; +} diff --git a/libnymea-app/zigbee/zigbeenetworks.h b/libnymea-app/zigbee/zigbeenetworks.h new file mode 100644 index 00000000..3a6376ff --- /dev/null +++ b/libnymea-app/zigbee/zigbeenetworks.h @@ -0,0 +1,85 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* 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 ZIGBEENETWORKS_H +#define ZIGBEENETWORKS_H + +#include +#include + +#include "zigbeenetwork.h" + +class ZigbeeNetworks : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + +public: + enum Roles { + RoleUuid, + RoleSerialPort, + RoleBaudRate, + RoleMacAddress, + RoleFirmwareVersion, + RolePanId, + RoleChannel, + RoleChannelMask, + RolePermitJoiningEnabled, + RolePermitJoiningDuration, + RolePermitJoiningRemaining, + RoleBackendType, + RoleNetworkState + }; + Q_ENUM(Roles) + + explicit ZigbeeNetworks(QObject *parent = nullptr); + virtual ~ZigbeeNetworks() override = default; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; + + void addNetwork(ZigbeeNetwork *network); + void removeNetwork(const QUuid &networkUuid); + + void clear(); + + Q_INVOKABLE virtual ZigbeeNetwork *get(int index) const; + Q_INVOKABLE ZigbeeNetwork *getNetwork(const QUuid &networkUuid) const; + +signals: + void countChanged(); + +protected: + QList m_networks; + +}; + +#endif // ZIGBEENETWORKS_H diff --git a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml index a3fe13ca..2085e846 100644 --- a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml @@ -51,7 +51,7 @@ SettingsPageBase { delegate: NymeaListItemDelegate { Layout.fillWidth: true - property var adapter: engine.zigbeeManager.adapters.get(index) +// property var adapter: engine.zigbeeManager.adapters.get(index) iconName: "../images/stock_link.svg" text: model.description + " - " + model.systemLocation //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) @@ -70,7 +70,7 @@ SettingsPageBase { delegate: NymeaListItemDelegate { Layout.fillWidth: true - property var adapter: engine.zigbeeManager.adapters.get(index) +// property var adapter: engine.zigbeeManager.adapters.get(index) iconName: "../images/stock_link.svg" text: model.description + " - " + model.systemLocation //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) diff --git a/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml b/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml index 2b83ad9c..35821600 100644 --- a/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml @@ -61,6 +61,22 @@ SettingsPageBase { } + Repeater { + model: engine.zigbeeManager.networks + + + delegate: NymeaListItemDelegate { + Layout.fillWidth: true + // property var adapter: engine.zigbeeManager.adapters.get(index) + iconName: "../images/zigbee.svg" + text: model.macAddress + " - " + model.serialPort + subText: model.firmwareVersion + + //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) + } + } + + NymeaListItemDelegate { Layout.fillWidth: true From e3caf0b74206e88fb1a318b3857e429106a8d26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 5 Nov 2020 15:35:06 +0100 Subject: [PATCH 04/18] Add and remove network --- libnymea-app/zigbee/zigbeeadapter.cpp | 37 +++++- libnymea-app/zigbee/zigbeeadapter.h | 20 ++- libnymea-app/zigbee/zigbeeadapters.cpp | 19 ++- libnymea-app/zigbee/zigbeeadapters.h | 4 +- libnymea-app/zigbee/zigbeeadaptersproxy.cpp | 6 +- libnymea-app/zigbee/zigbeemanager.cpp | 48 ++++++- libnymea-app/zigbee/zigbeemanager.h | 9 +- libnymea-app/zigbee/zigbeenetwork.cpp | 18 ++- libnymea-app/zigbee/zigbeenetwork.h | 6 +- nymea-app/resources.qrc | 2 + nymea-app/ui/system/ZigbeeNetworkAddPage.qml | 18 ++- nymea-app/ui/system/ZigbeeNetworkInfoPage.qml | 122 ++++++++++++++++++ nymea-app/ui/system/ZigbeeNetworkPage.qml | 115 +++++++++++++++++ .../ui/system/ZigbeeNetworkSettingsPage.qml | 29 ++--- 14 files changed, 399 insertions(+), 54 deletions(-) create mode 100644 nymea-app/ui/system/ZigbeeNetworkInfoPage.qml create mode 100644 nymea-app/ui/system/ZigbeeNetworkPage.qml diff --git a/libnymea-app/zigbee/zigbeeadapter.cpp b/libnymea-app/zigbee/zigbeeadapter.cpp index e4e65730..8e3a591f 100644 --- a/libnymea-app/zigbee/zigbeeadapter.cpp +++ b/libnymea-app/zigbee/zigbeeadapter.cpp @@ -57,15 +57,26 @@ void ZigbeeAdapter::setDescription(const QString &description) emit descriptionChanged(); } -QString ZigbeeAdapter::systemLocation() const +QString ZigbeeAdapter::serialPort() const { - return m_systemLocation; + return m_serialPort; } -void ZigbeeAdapter::setSystemLocation(const QString &systemLocation) +void ZigbeeAdapter::setSerialPort(const QString &serialPort) { - m_systemLocation = systemLocation; - emit systemLocationChanged(); + m_serialPort = serialPort; + emit serialPortChanged(); +} + +QString ZigbeeAdapter::serialNumber() const +{ + return m_serialNumber; +} + +void ZigbeeAdapter::setSerialNumber(const QString &serialNumber) +{ + m_serialNumber = serialNumber; + emit serialNumberChanged(); } bool ZigbeeAdapter::hardwareRecognized() const @@ -103,7 +114,7 @@ void ZigbeeAdapter::setBaudRate(qint32 baudRate) bool ZigbeeAdapter::operator==(const ZigbeeAdapter &other) const { - return m_systemLocation == other.systemLocation() + return m_serialPort == other.serialPort() && m_name == other.name() && m_description == other.description() && m_hardwareRecognized == other.hardwareRecognized() @@ -123,10 +134,22 @@ ZigbeeAdapter::ZigbeeBackendType ZigbeeAdapter::stringToZigbeeBackendType(const } } +QString ZigbeeAdapter::getBackendName(ZigbeeAdapter::ZigbeeBackendType backendType) +{ + switch (backendType) { + case ZigbeeAdapter::ZigbeeBackendTypeDeconz: + return "deCONZ"; + case ZigbeeAdapter::ZigbeeBackendTypeNxp: + return "Nxp"; + default: + return tr("Unknown"); + } +} + QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter) { debug.nospace() << "ZigbeeAdapter(" << adapter.name() << " - " << adapter.description(); - debug.nospace() << ", " << adapter.systemLocation(); + debug.nospace() << ", " << adapter.serialPort(); if (adapter.hardwareRecognized()) { debug.nospace() << " Hardware recognized: " << adapter.backendType(); debug.nospace() << ", " << adapter.baudRate(); diff --git a/libnymea-app/zigbee/zigbeeadapter.h b/libnymea-app/zigbee/zigbeeadapter.h index d3faeda0..434fdfa3 100644 --- a/libnymea-app/zigbee/zigbeeadapter.h +++ b/libnymea-app/zigbee/zigbeeadapter.h @@ -39,7 +39,8 @@ class ZigbeeAdapter : public QObject Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged) - Q_PROPERTY(QString systemLocation READ systemLocation WRITE setSystemLocation NOTIFY systemLocationChanged) + Q_PROPERTY(QString serialPort READ serialPort WRITE setSerialPort NOTIFY serialPortChanged) + Q_PROPERTY(QString serialNumber READ serialNumber WRITE setSerialNumber NOTIFY serialNumberChanged) Q_PROPERTY(bool hardwareRecognized READ hardwareRecognized WRITE setHardwareRecognized NOTIFY hardwareRecognizedChanged) Q_PROPERTY(ZigbeeAdapter::ZigbeeBackendType backendType READ backendType WRITE setBackendType NOTIFY backendTypeChanged) Q_PROPERTY(qint32 baudRate READ baudRate WRITE setBaudRate NOTIFY baudRateChanged) @@ -59,8 +60,11 @@ public: QString description() const; void setDescription(const QString &description); - QString systemLocation() const; - void setSystemLocation(const QString &systemLocation); + QString serialPort() const; + void setSerialPort(const QString &serialPort); + + QString serialNumber() const; + void setSerialNumber(const QString &serialNumber); bool hardwareRecognized() const; void setHardwareRecognized(bool hardwareRecognized); @@ -75,10 +79,13 @@ public: static ZigbeeAdapter::ZigbeeBackendType stringToZigbeeBackendType(const QString &backendTypeString); + Q_INVOKABLE static QString getBackendName(ZigbeeAdapter::ZigbeeBackendType backendType); + private: QString m_name; QString m_description; - QString m_systemLocation; + QString m_serialPort; + QString m_serialNumber; bool m_hardwareRecognized = false; ZigbeeAdapter::ZigbeeBackendType m_backendType = ZigbeeAdapter::ZigbeeBackendTypeDeconz; qint32 m_baudRate = 38400; @@ -86,12 +93,15 @@ private: signals: void nameChanged(); void descriptionChanged(); - void systemLocationChanged(); + void serialPortChanged(); + void serialNumberChanged(); void hardwareRecognizedChanged(); void backendTypeChanged(); void baudRateChanged(); }; +Q_DECLARE_METATYPE(ZigbeeAdapter::ZigbeeBackendType) + QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter); #endif // ZIGBEEADAPTER_H diff --git a/libnymea-app/zigbee/zigbeeadapters.cpp b/libnymea-app/zigbee/zigbeeadapters.cpp index 9584f266..190628dc 100644 --- a/libnymea-app/zigbee/zigbeeadapters.cpp +++ b/libnymea-app/zigbee/zigbeeadapters.cpp @@ -48,8 +48,8 @@ QVariant ZigbeeAdapters::data(const QModelIndex &index, int role) const return m_adapters.at(index.row())->name(); case RoleDescription: return m_adapters.at(index.row())->description(); - case RoleSystemLocation: - return m_adapters.at(index.row())->systemLocation(); + case RoleSerialPort: + return m_adapters.at(index.row())->serialPort(); case RoleHardwareRecognized: return m_adapters.at(index.row())->hardwareRecognized(); case RoleBackendType: @@ -65,7 +65,7 @@ QHash ZigbeeAdapters::roleNames() const QHash roles; roles.insert(RoleName, "name"); roles.insert(RoleDescription, "description"); - roles.insert(RoleSystemLocation, "systemLocation"); + roles.insert(RoleSerialPort, "serialPort"); roles.insert(RoleHardwareRecognized, "hardwareRecognized"); roles.insert(RoleBackendType, "backendType"); roles.insert(RoleBaudRate, "baudRate"); @@ -75,8 +75,10 @@ QHash ZigbeeAdapters::roleNames() const void ZigbeeAdapters::addAdapter(ZigbeeAdapter *adapter) { adapter->setParent(this); + beginInsertRows(QModelIndex(), m_adapters.count(), m_adapters.count()); m_adapters.append(adapter); + connect(adapter, &ZigbeeAdapter::nameChanged, this, [this, adapter]() { QModelIndex idx = index(m_adapters.indexOf(adapter), 0); emit dataChanged(idx, idx, {RoleName}); @@ -87,9 +89,9 @@ void ZigbeeAdapters::addAdapter(ZigbeeAdapter *adapter) emit dataChanged(idx, idx, {RoleDescription}); }); - connect(adapter, &ZigbeeAdapter::systemLocationChanged, this, [this, adapter]() { + connect(adapter, &ZigbeeAdapter::serialPortChanged, this, [this, adapter]() { QModelIndex idx = index(m_adapters.indexOf(adapter), 0); - emit dataChanged(idx, idx, {RoleSystemLocation}); + emit dataChanged(idx, idx, {RoleSerialPort}); }); connect(adapter, &ZigbeeAdapter::hardwareRecognizedChanged, this, [this, adapter]() { @@ -106,14 +108,16 @@ void ZigbeeAdapters::addAdapter(ZigbeeAdapter *adapter) QModelIndex idx = index(m_adapters.indexOf(adapter), 0); emit dataChanged(idx, idx, {RoleBaudRate}); }); + endInsertRows(); + emit countChanged(); } -void ZigbeeAdapters::removeAdapter(const QString &systemLocation) +void ZigbeeAdapters::removeAdapter(const QString &serialPort) { for (int i = 0; i < m_adapters.count(); i++) { - if (m_adapters.at(i)->systemLocation() == systemLocation) { + if (m_adapters.at(i)->serialPort() == serialPort) { beginRemoveRows(QModelIndex(), i, i); m_adapters.takeAt(i)->deleteLater(); endRemoveRows(); @@ -136,5 +140,6 @@ ZigbeeAdapter *ZigbeeAdapters::get(int index) const if (index < 0 || index > m_adapters.count() - 1) { return nullptr; } + return m_adapters.at(index); } diff --git a/libnymea-app/zigbee/zigbeeadapters.h b/libnymea-app/zigbee/zigbeeadapters.h index 7a0f4b5c..e4cf2433 100644 --- a/libnymea-app/zigbee/zigbeeadapters.h +++ b/libnymea-app/zigbee/zigbeeadapters.h @@ -45,7 +45,7 @@ public: enum Roles { RoleName, RoleDescription, - RoleSystemLocation, + RoleSerialPort, RoleHardwareRecognized, RoleBackendType, RoleBaudRate @@ -60,7 +60,7 @@ public: QHash roleNames() const override; void addAdapter(ZigbeeAdapter *adapter); - void removeAdapter(const QString &systemLocation); + void removeAdapter(const QString &serialPort); void clear(); diff --git a/libnymea-app/zigbee/zigbeeadaptersproxy.cpp b/libnymea-app/zigbee/zigbeeadaptersproxy.cpp index 63e04cab..9b365c30 100644 --- a/libnymea-app/zigbee/zigbeeadaptersproxy.cpp +++ b/libnymea-app/zigbee/zigbeeadaptersproxy.cpp @@ -51,7 +51,7 @@ void ZigbeeAdaptersProxy::setAdapters(ZigbeeAdapters *adapters) }); setSourceModel(m_adapters); - setSortRole(ZigbeeAdapters::RoleSystemLocation); + setSortRole(ZigbeeAdapters::RoleSerialPort); sort(0, Qt::DescendingOrder); invalidateFilter(); emit countChanged(); @@ -66,6 +66,7 @@ void ZigbeeAdaptersProxy::setHardwareFilter(ZigbeeAdaptersProxy::HardwareFilter { m_hardwareFilter = hardwareFilter; emit hardwareFilterChanged(m_hardwareFilter); + invalidateFilter(); emit countChanged(); } @@ -80,6 +81,9 @@ bool ZigbeeAdaptersProxy::filterAcceptsRow(int source_row, const QModelIndex &so Q_UNUSED(source_parent) ZigbeeAdapter *adapter = m_adapters->get(source_row); + if (!adapter) + return false; + if (m_hardwareFilter == HardwareFilterRecognized) { return adapter->hardwareRecognized(); } else if (m_hardwareFilter == HardwareFilterUnrecognized) { diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp index 04764b73..fb54aa80 100644 --- a/libnymea-app/zigbee/zigbeemanager.cpp +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -36,12 +36,16 @@ #include "zigbee/zigbeenetwork.h" #include "zigbee/zigbeenetworks.h" +#include + ZigbeeManager::ZigbeeManager(JsonRpcClient *client, QObject *parent) : JsonHandler(parent), m_client(client), m_adapters(new ZigbeeAdapters(this)), m_networks(new ZigbeeNetworks(this)) { + qRegisterMetaType(); + client->registerNotificationHandler(this, "notificationReceived"); } @@ -65,10 +69,31 @@ ZigbeeNetworks *ZigbeeManager::networks() const return m_networks; } +void ZigbeeManager::addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType) +{ + QVariantMap params; + params.insert("serialPort", serialPort); + params.insert("baudRate", baudRate); + QMetaEnum metaEnum = QMetaEnum::fromType(); + params.insert("backendType", metaEnum.valueToKey(backendType)); + + qDebug() << "Add zigbee network" << params; + m_client->sendCommand("Zigbee.AddNetwork", params, this, "addNetworkResponse"); +} + +void ZigbeeManager::removeNetwork(const QUuid &networkUuid) +{ + QVariantMap params; + params.insert("networkUuid", networkUuid); + qDebug() << "Remove zigbee network" << params; + m_client->sendCommand("Zigbee.RemoveNetwork", params, this, "removeNetworkResponse"); +} + void ZigbeeManager::init() { - qDebug() << "Zigbee init..."; + // FIXME: load only when used m_adapters->clear(); + m_networks->clear(); m_client->sendCommand("Zigbee.GetAdapters", this, "getAdaptersResponse"); m_client->sendCommand("Zigbee.GetNetworks", this, "getNetworksResponse"); } @@ -80,7 +105,7 @@ void ZigbeeManager::getAdaptersResponse(int commandId, const QVariantMap ¶ms foreach (const QVariant &adapterVariant, params.value("adapters").toList()) { QVariantMap adapterMap = adapterVariant.toMap(); ZigbeeAdapter *adapter = unpackAdapter(adapterMap); - qDebug() << "Zigbee adapter added" << adapter->description() << adapter->systemLocation(); + qDebug() << "Zigbee adapter added" << adapter->description() << adapter->serialPort() << adapter->hardwareRecognized(); m_adapters->addAdapter(adapter); } } @@ -88,7 +113,7 @@ void ZigbeeManager::getAdaptersResponse(int commandId, const QVariantMap ¶ms void ZigbeeManager::getNetworksResponse(int commandId, const QVariantMap ¶ms) { qDebug() << "Zigbee get networks response" << commandId << params; - m_adapters->clear(); + m_networks->clear(); foreach (const QVariant &networkVariant, params.value("zigbeeNetworks").toList()) { QVariantMap networkMap = networkVariant.toMap(); ZigbeeNetwork *network = unpackNetwork(networkMap); @@ -97,6 +122,16 @@ void ZigbeeManager::getNetworksResponse(int commandId, const QVariantMap ¶ms } } +void ZigbeeManager::addNetworkResponse(int commandId, const QVariantMap ¶ms) +{ + qDebug() << "Zigbee add network response" << commandId << params; +} + +void ZigbeeManager::removeNetworkResponse(int commandId, const QVariantMap ¶ms) +{ + qDebug() << "Zigbee remove network response" << commandId << params; +} + void ZigbeeManager::notificationReceived(const QVariantMap ¬ification) { QString notificationString = notification.value("notification").toString(); @@ -108,7 +143,7 @@ void ZigbeeManager::notificationReceived(const QVariantMap ¬ification) if (notificationString == "Zigbee.AdapterRemoved") { QVariantMap adapterMap = notification.value("params").toMap().value("adapter").toMap(); - m_adapters->removeAdapter(adapterMap.value("systemLocation").toString()); + m_adapters->removeAdapter(adapterMap.value("serialPort").toString()); return; } @@ -119,7 +154,7 @@ void ZigbeeManager::notificationReceived(const QVariantMap ¬ification) } if (notificationString == "Zigbee.NetworkRemoved") { - QUuid networkUuid = notification.value("params").toMap().value("zigbeeNetwork").toUuid(); + QUuid networkUuid = notification.value("params").toMap().value("networkUuid").toUuid(); m_networks->removeNetwork(networkUuid); return; } @@ -144,7 +179,8 @@ ZigbeeAdapter *ZigbeeManager::unpackAdapter(const QVariantMap &adapterMap) ZigbeeAdapter *adapter = new ZigbeeAdapter(m_adapters); adapter->setName(adapterMap.value("name").toString()); adapter->setDescription(adapterMap.value("description").toString()); - adapter->setSystemLocation(adapterMap.value("systemLocation").toString()); + adapter->setSerialPort(adapterMap.value("serialPort").toString()); + adapter->setSerialNumber(adapterMap.value("serialNumber").toString()); adapter->setHardwareRecognized(adapterMap.value("hardwareRecognized").toBool()); adapter->setBackendType(ZigbeeAdapter::stringToZigbeeBackendType(adapterMap.value("backendType").toString())); adapter->setBaudRate(adapterMap.value("baudRate").toUInt()); diff --git a/libnymea-app/zigbee/zigbeemanager.h b/libnymea-app/zigbee/zigbeemanager.h index 057c388f..091fb047 100644 --- a/libnymea-app/zigbee/zigbeemanager.h +++ b/libnymea-app/zigbee/zigbeemanager.h @@ -32,10 +32,10 @@ #define ZIGBEEMANAGER_H #include +#include "zigbeeadapter.h" #include "jsonrpc/jsonhandler.h" class JsonRpcClient; -class ZigbeeAdapter; class ZigbeeAdapters; class ZigbeeNetwork; class ZigbeeNetworks; @@ -55,6 +55,9 @@ public: ZigbeeAdapters *adapters() const; ZigbeeNetworks *networks() const; + Q_INVOKABLE void addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType); + Q_INVOKABLE void removeNetwork(const QUuid &networkUuid); + void init(); signals: @@ -63,6 +66,10 @@ private: Q_INVOKABLE void getAdaptersResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void getNetworksResponse(int commandId, const QVariantMap ¶ms); + Q_INVOKABLE void addNetworkResponse(int commandId, const QVariantMap ¶ms); + Q_INVOKABLE void removeNetworkResponse(int commandId, const QVariantMap ¶ms); + + Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification); private: diff --git a/libnymea-app/zigbee/zigbeenetwork.cpp b/libnymea-app/zigbee/zigbeenetwork.cpp index 7eaa61a4..4458c0e1 100644 --- a/libnymea-app/zigbee/zigbeenetwork.cpp +++ b/libnymea-app/zigbee/zigbeenetwork.cpp @@ -32,7 +32,16 @@ ZigbeeNetwork::ZigbeeNetwork(QObject *parent) : QObject(parent) { + m_permitJoinTimer = new QTimer(this); + m_permitJoinTimer->setInterval(1000); + m_permitJoinTimer->setSingleShot(true); + connect(m_permitJoinTimer, &QTimer::timeout, this, [this](){ + setPermitJoiningRemaining(m_permitJoiningRemaining - 1); + if (m_permitJoiningRemaining <= 0) { + m_permitJoinTimer->stop(); + } + }); } QUuid ZigbeeNetwork::networkUuid() const @@ -186,7 +195,14 @@ void ZigbeeNetwork::setPermitJoiningRemaining(uint permitJoiningRemaining) return; m_permitJoiningRemaining = permitJoiningRemaining; - emit permitJoiningRemainingChanged(); + emit permitJoiningRemainingChanged(); + + if (m_permitJoinTimer->isActive()) + m_permitJoinTimer->stop(); + + if (m_permitJoiningRemaining != 0) { + m_permitJoinTimer->start(); + } } ZigbeeAdapter::ZigbeeBackendType ZigbeeNetwork::backendType() const diff --git a/libnymea-app/zigbee/zigbeenetwork.h b/libnymea-app/zigbee/zigbeenetwork.h index 805e1bbd..7df52102 100644 --- a/libnymea-app/zigbee/zigbeenetwork.h +++ b/libnymea-app/zigbee/zigbeenetwork.h @@ -33,6 +33,7 @@ #include #include +#include #include "zigbeeadapter.h" @@ -53,8 +54,9 @@ class ZigbeeNetwork : public QObject Q_PROPERTY(ZigbeeAdapter::ZigbeeBackendType backendType READ backendType NOTIFY backendTypeChanged) Q_PROPERTY(ZigbeeNetworkState networkState READ networkState NOTIFY networkStateChanged) -public: + // Internal properties +public: enum ZigbeeNetworkState { ZigbeeNetworkStateOffline, ZigbeeNetworkStateStarting, @@ -136,6 +138,8 @@ private: uint m_permitJoiningRemaining; ZigbeeAdapter::ZigbeeBackendType m_backendType; ZigbeeNetworkState m_networkState; + + QTimer *m_permitJoinTimer = nullptr; }; #endif // ZIGBEENETWORK_H diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc index 87ea25d0..c81ba76a 100644 --- a/nymea-app/resources.qrc +++ b/nymea-app/resources.qrc @@ -227,5 +227,7 @@ ui/components/ThingInfoPane.qml ui/system/ZigbeeNetworkSettingsPage.qml ui/system/ZigbeeNetworkAddPage.qml + ui/system/ZigbeeNetworkPage.qml + ui/system/ZigbeeNetworkInfoPage.qml diff --git a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml index 2085e846..58dd883b 100644 --- a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml @@ -39,11 +39,14 @@ SettingsPageBase { id: root title: qsTr("Add a new Zigbee network") + + SettingsPageSectionHeader { text: qsTr("Zigbee adapters") } Repeater { + id: recognizedRepeater model: ZigbeeAdaptersProxy { adapters: engine.zigbeeManager.adapters hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterRecognized @@ -51,18 +54,20 @@ SettingsPageBase { delegate: NymeaListItemDelegate { Layout.fillWidth: true -// property var adapter: engine.zigbeeManager.adapters.get(index) - iconName: "../images/stock_link.svg" - text: model.description + " - " + model.systemLocation - //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) + property ZigbeeAdapter adapter: engine.zigbeeManager.adapters.get(index) + iconName: "../images/add.svg" + text: model.description + " - " + model.serialPort + onClicked: engine.zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) } } SettingsPageSectionHeader { text: qsTr("Unrecognized Zigbee adapters") + visible: unrecognizedRepeater.count !== 0 } Repeater { + id: unrecognizedRepeater model: ZigbeeAdaptersProxy { adapters: engine.zigbeeManager.adapters hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterUnrecognized @@ -71,8 +76,9 @@ SettingsPageBase { delegate: NymeaListItemDelegate { Layout.fillWidth: true // property var adapter: engine.zigbeeManager.adapters.get(index) - iconName: "../images/stock_link.svg" - text: model.description + " - " + model.systemLocation + iconName: "../images/add.svg" + text: model.description + " - " + model.serialPort + // TODO: show backend and baudrate popup before adding //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) } } diff --git a/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml new file mode 100644 index 00000000..e3a002f9 --- /dev/null +++ b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml @@ -0,0 +1,122 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.8 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.3 +import "../components" +import Nymea 1.0 + +SettingsPageBase { + id: root + + property ZigbeeNetwork network: null + + header: NymeaHeader { + text: qsTr("Network settings") + backButtonVisible: true + onBackPressed: pageStack.pop() + } + + SettingsPageSectionHeader { + text: qsTr("Hardware information") + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("MAC address:") + subText: root.network.macAddress + progressive: false + prominentSubText: false + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Serial port") + subText: root.network.serialPort + progressive: false + prominentSubText: false + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Baud rate") + subText: root.network.baudRate + progressive: false + prominentSubText: false + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Controller backend") + subText: ZigbeeAdapter.getBackendName(root.network.backendType) + progressive: false + prominentSubText: false + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Controller firmware version") + subText: root.network.firmwareVersion + progressive: false + prominentSubText: false + } + + SettingsPageSectionHeader { + text: qsTr("Manage network") + } + + ColumnLayout { + anchors { left: parent.left; right: parent.right } + + Button { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + text: qsTr("Remove network") + onClicked: { + engine.zigbeeManager.removeNetwork(root.network.networkUuid) + pageStack.pop() + pageStack.pop() + } + } + + Button { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + text: qsTr("Factory reset controller") + onClicked: print("Reset clicked") + } + } + + +} diff --git a/nymea-app/ui/system/ZigbeeNetworkPage.qml b/nymea-app/ui/system/ZigbeeNetworkPage.qml new file mode 100644 index 00000000..6fd630cc --- /dev/null +++ b/nymea-app/ui/system/ZigbeeNetworkPage.qml @@ -0,0 +1,115 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.8 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.3 +import "../components" +import Nymea 1.0 + +SettingsPageBase { + id: root + + property ZigbeeNetwork network: null + + header: NymeaHeader { + text: qsTr("Network") + " " + root.network.macAddress + backButtonVisible: true + onBackPressed: pageStack.pop() + + HeaderButton { + text: qsTr("Settings") + imageSource: "../images/settings.svg" + onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeNetworkInfoPage.qml"), { network: root.network }) + } + } + + SettingsPageSectionHeader { + text: qsTr("Network information") + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Network state") + subText: root.network.networkState + progressive: false + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Channel") + subText: root.network.channel + progressive: false + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Network PAN ID") + subText: root.network.panId + progressive: false + } + + SettingsPageSectionHeader { + text: qsTr("Adding zigbee devices") + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: root.network.permitJoiningEnabled ? qsTr("The network is open") : qsTr("The network is closed") + subText: root.network.permitJoiningEnabled ? qsTr("Devices can join this network") : qsTr("Devices are not allowed to join this network") + progressive: false + prominentSubText: false + } + + ColumnLayout { + anchors { left: parent.left; right: parent.right } + + ProgressBar { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + visible: root.network.permitJoiningEnabled + from: root.network.permitJoiningDuration + to: 0 + value: root.network.permitJoiningRemaining + } + + Button { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + enabled: network.networkState === ZigbeeNetwork.ZigbeeNetworkStateOnline + text: root.network.permitJoiningEnabled ? qsTr("Extend network open duration") : qsTr("Open network for new Zigbee devices") + onClicked: print("Permit join clicked") + } + } + +} diff --git a/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml b/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml index 35821600..c1f64411 100644 --- a/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml @@ -42,13 +42,14 @@ SettingsPageBase { backButtonVisible: true onBackPressed: pageStack.pop() - HeaderButton { - text: qsTr("Settings") - imageSource: "../images/settings.svg" - onClicked: { - //pageStack.push() - } - } + // TODO: create a settings page where zigbee networking can be enabled/disabled in general + // HeaderButton { + // text: qsTr("Settings") + // imageSource: "../images/settings.svg" + // onClicked: { + // //pageStack.push() + // } + // } } ColumnLayout { @@ -60,24 +61,18 @@ SettingsPageBase { text: qsTr("Zigbee networks") } - Repeater { model: engine.zigbeeManager.networks - - delegate: NymeaListItemDelegate { Layout.fillWidth: true - // property var adapter: engine.zigbeeManager.adapters.get(index) + property var network: engine.zigbeeManager.networks.get(index) iconName: "../images/zigbee.svg" - text: model.macAddress + " - " + model.serialPort - subText: model.firmwareVersion - - //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) + text: model.macAddress + subText: model.serialPort + " - " + model.firmwareVersion + onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeNetworkPage.qml"), { network: network }) } } - - NymeaListItemDelegate { Layout.fillWidth: true text: qsTr("Add Zigbee network") From 9acef17318929b408fcbd386e505a5be3315f59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 5 Nov 2020 15:43:36 +0100 Subject: [PATCH 05/18] Use usb icon for adapters --- nymea-app/images.qrc | 1 + nymea-app/ui/images/stock_usb.svg | 203 +++++++++++++++++++ nymea-app/ui/system/ZigbeeNetworkAddPage.qml | 8 +- 3 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 nymea-app/ui/images/stock_usb.svg diff --git a/nymea-app/images.qrc b/nymea-app/images.qrc index c9e73fe0..c9423e13 100644 --- a/nymea-app/images.qrc +++ b/nymea-app/images.qrc @@ -242,5 +242,6 @@ ui/images/state-out.svg ui/images/like.svg ui/images/zigbee.svg + ui/images/stock_usb.svg diff --git a/nymea-app/ui/images/stock_usb.svg b/nymea-app/ui/images/stock_usb.svg new file mode 100644 index 00000000..9d988a71 --- /dev/null +++ b/nymea-app/ui/images/stock_usb.svg @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml index 58dd883b..2904f2c0 100644 --- a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml @@ -55,7 +55,8 @@ SettingsPageBase { delegate: NymeaListItemDelegate { Layout.fillWidth: true property ZigbeeAdapter adapter: engine.zigbeeManager.adapters.get(index) - iconName: "../images/add.svg" + iconName: "../images/stock_usb.svg" + progressive: false text: model.description + " - " + model.serialPort onClicked: engine.zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) } @@ -75,11 +76,12 @@ SettingsPageBase { delegate: NymeaListItemDelegate { Layout.fillWidth: true -// property var adapter: engine.zigbeeManager.adapters.get(index) - iconName: "../images/add.svg" + property ZigbeeAdapter adapter: engine.zigbeeManager.adapters.get(index) + iconName: "../images/stock_usb.svg" text: model.description + " - " + model.serialPort // TODO: show backend and baudrate popup before adding //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) + onClicked: engine.zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) } } From a171879db764e62c8530a306335f7398a07f2192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 5 Nov 2020 16:43:42 +0100 Subject: [PATCH 06/18] Add enabled property to network and implement permit join --- libnymea-app/zigbee/zigbeemanager.cpp | 13 ++++++++++ libnymea-app/zigbee/zigbeemanager.h | 2 ++ libnymea-app/zigbee/zigbeenetwork.cpp | 14 ++++++++++ libnymea-app/zigbee/zigbeenetwork.h | 6 +++++ nymea-app/ui/system/ZigbeeNetworkAddPage.qml | 6 +++-- nymea-app/ui/system/ZigbeeNetworkPage.qml | 27 ++++++++++++++++++-- 6 files changed, 64 insertions(+), 4 deletions(-) diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp index fb54aa80..c420d309 100644 --- a/libnymea-app/zigbee/zigbeemanager.cpp +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -89,6 +89,14 @@ void ZigbeeManager::removeNetwork(const QUuid &networkUuid) m_client->sendCommand("Zigbee.RemoveNetwork", params, this, "removeNetworkResponse"); } +void ZigbeeManager::setPermitJoin(const QUuid &networkUuid, uint duration) +{ + QVariantMap params; + params.insert("networkUuid", networkUuid); + params.insert("duration", duration); + m_client->sendCommand("Zigbee.SetPermitJoin", params, this, "setPermitJoinResponse"); +} + void ZigbeeManager::init() { // FIXME: load only when used @@ -132,6 +140,11 @@ void ZigbeeManager::removeNetworkResponse(int commandId, const QVariantMap ¶ qDebug() << "Zigbee remove network response" << commandId << params; } +void ZigbeeManager::setPermitJoinResponse(int commandId, const QVariantMap ¶ms) +{ + qDebug() << "Zigbee set permit join network response" << commandId << params; +} + void ZigbeeManager::notificationReceived(const QVariantMap ¬ification) { QString notificationString = notification.value("notification").toString(); diff --git a/libnymea-app/zigbee/zigbeemanager.h b/libnymea-app/zigbee/zigbeemanager.h index 091fb047..443872c0 100644 --- a/libnymea-app/zigbee/zigbeemanager.h +++ b/libnymea-app/zigbee/zigbeemanager.h @@ -57,6 +57,7 @@ public: Q_INVOKABLE void addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType); Q_INVOKABLE void removeNetwork(const QUuid &networkUuid); + Q_INVOKABLE void setPermitJoin(const QUuid &networkUuid, uint duration = 120); void init(); @@ -68,6 +69,7 @@ private: Q_INVOKABLE void addNetworkResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void removeNetworkResponse(int commandId, const QVariantMap ¶ms); + Q_INVOKABLE void setPermitJoinResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification); diff --git a/libnymea-app/zigbee/zigbeenetwork.cpp b/libnymea-app/zigbee/zigbeenetwork.cpp index 4458c0e1..982a6121 100644 --- a/libnymea-app/zigbee/zigbeenetwork.cpp +++ b/libnymea-app/zigbee/zigbeenetwork.cpp @@ -58,6 +58,20 @@ void ZigbeeNetwork::setNetworkUuid(const QUuid &networkUuid) emit networkUuidChanged(); } +bool ZigbeeNetwork::enabled() const +{ + return m_enabled; +} + +void ZigbeeNetwork::setEnabled(bool enabled) +{ + if (m_enabled == enabled) + return; + + m_enabled = enabled; + emit enabledChanged(); +} + QString ZigbeeNetwork::serialPort() const { return m_serialPort; diff --git a/libnymea-app/zigbee/zigbeenetwork.h b/libnymea-app/zigbee/zigbeenetwork.h index 7df52102..d5044bcf 100644 --- a/libnymea-app/zigbee/zigbeenetwork.h +++ b/libnymea-app/zigbee/zigbeenetwork.h @@ -41,6 +41,7 @@ class ZigbeeNetwork : public QObject { Q_OBJECT Q_PROPERTY(QUuid networkUuid READ networkUuid NOTIFY networkUuidChanged) + Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged) Q_PROPERTY(QString serialPort READ serialPort NOTIFY serialPortChanged) Q_PROPERTY(uint baudRate READ baudRate NOTIFY baudRateChanged) Q_PROPERTY(QString macAddress READ macAddress NOTIFY macAddressChanged) @@ -71,6 +72,9 @@ public: QUuid networkUuid() const; void setNetworkUuid(const QUuid &networkUuid); + bool enabled() const; + void setEnabled(bool enabled); + QString serialPort() const; void setSerialPort(const QString &serialPort); @@ -111,6 +115,7 @@ public: signals: void networkUuidChanged(); + void enabledChanged(); void serialPortChanged(); void baudRateChanged(); void macAddressChanged(); @@ -126,6 +131,7 @@ signals: private: QUuid m_networkUuid; + bool m_enabled; QString m_serialPort; uint m_baudRate; QString m_macAddress; diff --git a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml index 2904f2c0..2c97a356 100644 --- a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml @@ -58,7 +58,10 @@ SettingsPageBase { iconName: "../images/stock_usb.svg" progressive: false text: model.description + " - " + model.serialPort - onClicked: engine.zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) + onClicked: { + engine.zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) + pageStack.pop() + } } } @@ -80,7 +83,6 @@ SettingsPageBase { iconName: "../images/stock_usb.svg" text: model.description + " - " + model.serialPort // TODO: show backend and baudrate popup before adding - //onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: plugin}) onClicked: engine.zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) } } diff --git a/nymea-app/ui/system/ZigbeeNetworkPage.qml b/nymea-app/ui/system/ZigbeeNetworkPage.qml index 6fd630cc..3848a6e5 100644 --- a/nymea-app/ui/system/ZigbeeNetworkPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkPage.qml @@ -59,7 +59,21 @@ SettingsPageBase { NymeaListItemDelegate { Layout.fillWidth: true text: qsTr("Network state") - subText: root.network.networkState + subText: { + switch (root.network.networkState) { + case ZigbeeNetwork.ZigbeeNetworkStateOnline: + return qsTr("The network is online") + case ZigbeeNetwork.ZigbeeNetworkStateOffline: + return qsTr("The network is offline") + case ZigbeeNetwork.ZigbeeNetworkStateStarting: + return qsTr("The network is starting...") + case ZigbeeNetwork.ZigbeeNetworkStateUpdating: + return qsTr("The controller is currently installing an update") + case ZigbeeNetwork.ZigbeeNetworkStateError: + return qsTr("The network is in an error state.") + } + } + progressive: false } @@ -108,7 +122,16 @@ SettingsPageBase { Layout.rightMargin: app.margins enabled: network.networkState === ZigbeeNetwork.ZigbeeNetworkStateOnline text: root.network.permitJoiningEnabled ? qsTr("Extend network open duration") : qsTr("Open network for new Zigbee devices") - onClicked: print("Permit join clicked") + onClicked: engine.zigbeeManager.setPermitJoin(root.network.networkUuid) + } + + Button { + Layout.fillWidth: true + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + visible: network.networkState === ZigbeeNetwork.ZigbeeNetworkStateOnline && root.network.permitJoiningEnabled + text: qsTr("Close network") + onClicked: engine.zigbeeManager.setPermitJoin(root.network.networkUuid, 0) } } From e2735428b83717d6a6360d34d5dcd8af0b9938c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Mon, 9 Nov 2020 15:30:16 +0100 Subject: [PATCH 07/18] Add factory reset network method --- libnymea-app/zigbee/zigbeemanager.cpp | 12 ++++++++++++ libnymea-app/zigbee/zigbeemanager.h | 2 ++ nymea-app/ui/system/ZigbeeNetworkInfoPage.qml | 5 ++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp index c420d309..5c114dff 100644 --- a/libnymea-app/zigbee/zigbeemanager.cpp +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -97,6 +97,13 @@ void ZigbeeManager::setPermitJoin(const QUuid &networkUuid, uint duration) m_client->sendCommand("Zigbee.SetPermitJoin", params, this, "setPermitJoinResponse"); } +void ZigbeeManager::factoryResetNetwork(const QUuid &networkUuid) +{ + QVariantMap params; + params.insert("networkUuid", networkUuid); + m_client->sendCommand("Zigbee.FactoryResetNetwork", params, this, "factoryResetNetworkResponse"); +} + void ZigbeeManager::init() { // FIXME: load only when used @@ -145,6 +152,11 @@ void ZigbeeManager::setPermitJoinResponse(int commandId, const QVariantMap ¶ qDebug() << "Zigbee set permit join network response" << commandId << params; } +void ZigbeeManager::factoryResetNetworkResponse(int commandId, const QVariantMap ¶ms) +{ + qDebug() << "Zigbee factory reset network response" << commandId << params; +} + void ZigbeeManager::notificationReceived(const QVariantMap ¬ification) { QString notificationString = notification.value("notification").toString(); diff --git a/libnymea-app/zigbee/zigbeemanager.h b/libnymea-app/zigbee/zigbeemanager.h index 443872c0..e09c61ed 100644 --- a/libnymea-app/zigbee/zigbeemanager.h +++ b/libnymea-app/zigbee/zigbeemanager.h @@ -58,6 +58,7 @@ public: Q_INVOKABLE void addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType); Q_INVOKABLE void removeNetwork(const QUuid &networkUuid); Q_INVOKABLE void setPermitJoin(const QUuid &networkUuid, uint duration = 120); + Q_INVOKABLE void factoryResetNetwork(const QUuid &networkUuid); void init(); @@ -70,6 +71,7 @@ private: Q_INVOKABLE void addNetworkResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void removeNetworkResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void setPermitJoinResponse(int commandId, const QVariantMap ¶ms); + Q_INVOKABLE void factoryResetNetworkResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification); diff --git a/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml index e3a002f9..226f40f1 100644 --- a/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml @@ -114,7 +114,10 @@ SettingsPageBase { Layout.leftMargin: app.margins Layout.rightMargin: app.margins text: qsTr("Factory reset controller") - onClicked: print("Reset clicked") + onClicked: { + engine.zigbeeManager.factoryResetNetwork(root.network.networkUuid) + pageStack.pop() + } } } From 6702a6b64920a81b9a37060787c261299a80c564 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 11 Nov 2020 13:56:51 +0100 Subject: [PATCH 08/18] some more work on zigbee --- QtZeroConf | 2 +- libnymea-app/engine.cpp | 13 +- libnymea-app/engine.h | 4 - libnymea-app/libnymea-app-core.h | 2 +- libnymea-app/libnymea-app.pro | 6 +- libnymea-app/zigbee/zigbeeadapters.cpp | 2 +- libnymea-app/zigbee/zigbeeadaptersproxy.cpp | 80 +++++-- libnymea-app/zigbee/zigbeeadaptersproxy.h | 24 +- libnymea-app/zigbee/zigbeemanager.cpp | 56 ++++- libnymea-app/zigbee/zigbeemanager.h | 24 +- libnymea-app/zigbee/zigbeenetworks.cpp | 13 +- libnymea-app/zigbee/zigbeenetworks.h | 1 + .../zigbee/zigbeenetworksandadapters.cpp | 21 ++ .../zigbee/zigbeenetworksandadapters.h | 26 +++ nymea-app/resources.qrc | 2 + nymea-app/ui/SettingsPage.qml | 6 +- nymea-app/ui/system/NetworkSettingsPage.qml | 2 + nymea-app/ui/system/ZigbeeAddNetworkPage.qml | 218 ++++++++++++++++++ nymea-app/ui/system/ZigbeeNetworkAddPage.qml | 91 -------- nymea-app/ui/system/ZigbeeNetworkInfoPage.qml | 4 +- nymea-app/ui/system/ZigbeeNetworkPage.qml | 8 +- .../ui/system/ZigbeeNetworkSettingsPage.qml | 86 ------- nymea-app/ui/system/ZigbeeSettingsPage.qml | 160 +++++++++++++ 23 files changed, 595 insertions(+), 256 deletions(-) create mode 100644 libnymea-app/zigbee/zigbeenetworksandadapters.cpp create mode 100644 libnymea-app/zigbee/zigbeenetworksandadapters.h create mode 100644 nymea-app/ui/system/ZigbeeAddNetworkPage.qml delete mode 100644 nymea-app/ui/system/ZigbeeNetworkAddPage.qml delete mode 100644 nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml create mode 100644 nymea-app/ui/system/ZigbeeSettingsPage.qml diff --git a/QtZeroConf b/QtZeroConf index 39efbe28..cbf4f2bf 160000 --- a/QtZeroConf +++ b/QtZeroConf @@ -1 +1 @@ -Subproject commit 39efbe2879d93bd483ee1f14fc94281a03b49935 +Subproject commit cbf4f2bf7b926b9a874af013efbf0f6dde3155e9 diff --git a/libnymea-app/engine.cpp b/libnymea-app/engine.cpp index e79b06eb..b26215cc 100644 --- a/libnymea-app/engine.cpp +++ b/libnymea-app/engine.cpp @@ -38,7 +38,6 @@ #include "connection/awsclient.h" #include "system/systemcontroller.h" #include "configuration/networkmanager.h" -#include "zigbee/zigbeemanager.h" Engine::Engine(QObject *parent) : QObject(parent), @@ -49,8 +48,7 @@ Engine::Engine(QObject *parent) : m_logManager(new LogManager(m_jsonRpcClient, this)), m_tagsManager(new TagsManager(m_jsonRpcClient, this)), m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this)), - m_systemController(new SystemController(m_jsonRpcClient, this)), - m_zigbeeManager(new ZigbeeManager(m_jsonRpcClient, this)) + m_systemController(new SystemController(m_jsonRpcClient, this)) { connect(m_jsonRpcClient, &JsonRpcClient::connectedChanged, this, &Engine::onConnectedChanged); @@ -119,11 +117,6 @@ SystemController *Engine::systemController() const return m_systemController; } -ZigbeeManager *Engine::zigbeeManager() const -{ - return m_zigbeeManager; -} - void Engine::deployCertificate() { if (!m_jsonRpcClient->connected()) { @@ -165,9 +158,5 @@ void Engine::onDeviceManagerFetchingChanged() if (m_jsonRpcClient->ensureServerVersion("1.7")) { m_tagsManager->init(); } - - if (m_jsonRpcClient->ensureServerVersion("5.1")) { - m_zigbeeManager->init(); - } } } diff --git a/libnymea-app/engine.h b/libnymea-app/engine.h index c81b2ef4..07b38c6a 100644 --- a/libnymea-app/engine.h +++ b/libnymea-app/engine.h @@ -45,7 +45,6 @@ class TagsManager; class NymeaConfiguration; class SystemController; class NetworkManager; -class ZigbeeManager; class Engine : public QObject { @@ -58,7 +57,6 @@ class Engine : public QObject Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT) Q_PROPERTY(NymeaConfiguration* nymeaConfiguration READ nymeaConfiguration CONSTANT) Q_PROPERTY(SystemController* systemController READ systemController CONSTANT) - Q_PROPERTY(ZigbeeManager *zigbeeManager READ zigbeeManager CONSTANT) public: explicit Engine(QObject *parent = nullptr); @@ -72,7 +70,6 @@ public: LogManager *logManager() const; NymeaConfiguration *nymeaConfiguration() const; SystemController *systemController() const; - ZigbeeManager *zigbeeManager() const; Q_INVOKABLE void deployCertificate(); @@ -85,7 +82,6 @@ private: TagsManager *m_tagsManager; NymeaConfiguration *m_nymeaConfiguration; SystemController *m_systemController; - ZigbeeManager *m_zigbeeManager; private slots: void onConnectedChanged(); diff --git a/libnymea-app/libnymea-app-core.h b/libnymea-app/libnymea-app-core.h index 89539b1c..279becaf 100644 --- a/libnymea-app/libnymea-app-core.h +++ b/libnymea-app/libnymea-app-core.h @@ -302,7 +302,7 @@ void registerQmlTypes() { qmlRegisterUncreatableType(uri, 1, 0, "Repository", "Get it from Repositories"); qmlRegisterType(uri, 1, 0, "PackagesFilterModel"); - qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeManager", "Get it from Engine"); + qmlRegisterType(uri, 1, 0, "ZigbeeManager"); qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeAdapter", "Get it from the ZigbeeAdapters"); qmlRegisterUncreatableType(uri, 1, 0, "ZigbeeAdapters", "Get it from ZigbeeManager"); qmlRegisterType(uri, 1, 0, "ZigbeeAdaptersProxy"); diff --git a/libnymea-app/libnymea-app.pro b/libnymea-app/libnymea-app.pro index b0cdc5b9..0ca71ae5 100644 --- a/libnymea-app/libnymea-app.pro +++ b/libnymea-app/libnymea-app.pro @@ -165,7 +165,8 @@ SOURCES += \ zigbee/zigbeemanager.cpp \ zigbee/zigbeeadapter.cpp \ zigbee/zigbeenetwork.cpp \ - zigbee/zigbeenetworks.cpp + zigbee/zigbeenetworks.cpp \ + zigbee/zigbeenetworksandadapters.cpp @@ -311,7 +312,8 @@ HEADERS += \ zigbee/zigbeemanager.h \ zigbee/zigbeeadapter.h \ zigbee/zigbeenetwork.h \ - zigbee/zigbeenetworks.h + zigbee/zigbeenetworks.h \ + zigbee/zigbeenetworksandadapters.h ubports: { DEFINES += UBPORTS diff --git a/libnymea-app/zigbee/zigbeeadapters.cpp b/libnymea-app/zigbee/zigbeeadapters.cpp index 190628dc..6f701f46 100644 --- a/libnymea-app/zigbee/zigbeeadapters.cpp +++ b/libnymea-app/zigbee/zigbeeadapters.cpp @@ -137,7 +137,7 @@ void ZigbeeAdapters::clear() ZigbeeAdapter *ZigbeeAdapters::get(int index) const { - if (index < 0 || index > m_adapters.count() - 1) { + if (index < 0 || index >= m_adapters.count()) { return nullptr; } diff --git a/libnymea-app/zigbee/zigbeeadaptersproxy.cpp b/libnymea-app/zigbee/zigbeeadaptersproxy.cpp index 9b365c30..8786a873 100644 --- a/libnymea-app/zigbee/zigbeeadaptersproxy.cpp +++ b/libnymea-app/zigbee/zigbeeadaptersproxy.cpp @@ -30,31 +30,36 @@ #include "zigbeeadaptersproxy.h" +#include "zigbeemanager.h" #include "zigbeeadapters.h" +#include "zigbeenetworks.h" ZigbeeAdaptersProxy::ZigbeeAdaptersProxy(QObject *parent) : QSortFilterProxyModel(parent) { } -ZigbeeAdapters *ZigbeeAdaptersProxy::adapters() const +ZigbeeManager *ZigbeeAdaptersProxy::manager() const { - return m_adapters; + return m_manager; } -void ZigbeeAdaptersProxy::setAdapters(ZigbeeAdapters *adapters) +void ZigbeeAdaptersProxy::setManager(ZigbeeManager *manager) { - m_adapters = adapters; - connect(m_adapters, &ZigbeeAdapters::countChanged, this, [this](){ + if (m_manager != manager) { + m_manager = manager; + connect(m_manager->adapters(), &ZigbeeAdapters::countChanged, this, [this](){ + emit countChanged(); + }); + connect(m_manager->networks(), &ZigbeeNetworks::countChanged, this, [this]() { + invalidateFilter(); + }); + setSourceModel(m_manager->adapters()); + setSortRole(ZigbeeAdapters::RoleSerialPort); + sort(0, Qt::DescendingOrder); invalidateFilter(); emit countChanged(); - }); - - setSourceModel(m_adapters); - setSortRole(ZigbeeAdapters::RoleSerialPort); - sort(0, Qt::DescendingOrder); - invalidateFilter(); - emit countChanged(); + } } ZigbeeAdaptersProxy::HardwareFilter ZigbeeAdaptersProxy::hardwareFilter() const @@ -64,30 +69,57 @@ ZigbeeAdaptersProxy::HardwareFilter ZigbeeAdaptersProxy::hardwareFilter() const void ZigbeeAdaptersProxy::setHardwareFilter(ZigbeeAdaptersProxy::HardwareFilter hardwareFilter) { - m_hardwareFilter = hardwareFilter; - emit hardwareFilterChanged(m_hardwareFilter); + if (m_hardwareFilter != hardwareFilter) { + m_hardwareFilter = hardwareFilter; + emit hardwareFilterChanged(m_hardwareFilter); - invalidateFilter(); - emit countChanged(); + invalidateFilter(); + emit countChanged(); + } +} + +bool ZigbeeAdaptersProxy::onlyUnused() const +{ + return m_onlyUnused; +} + +void ZigbeeAdaptersProxy::setOnlyUnused(bool onlyUnused) +{ + if (m_onlyUnused != onlyUnused) { + m_onlyUnused = onlyUnused; + emit onlyUnusedChanged(); + + invalidateFilter(); + emit countChanged(); + } } ZigbeeAdapter *ZigbeeAdaptersProxy::get(int index) const { - return m_adapters->get(mapToSource(this->index(index, 0)).row()); + if (index >= 0 && index < m_manager->adapters()->rowCount()) { + return m_manager->adapters()->get(mapToSource(this->index(index, 0)).row()); + } + return nullptr; } bool ZigbeeAdaptersProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { Q_UNUSED(source_parent) - ZigbeeAdapter *adapter = m_adapters->get(source_row); - if (!adapter) - return false; + ZigbeeAdapter *adapter = m_manager->adapters()->get(source_row); - if (m_hardwareFilter == HardwareFilterRecognized) { - return adapter->hardwareRecognized(); - } else if (m_hardwareFilter == HardwareFilterUnrecognized) { - return !adapter->hardwareRecognized(); + if (m_hardwareFilter == HardwareFilterRecognized && !adapter->hardwareRecognized()) { + return false; + } + + if (m_hardwareFilter == HardwareFilterUnrecognized && adapter->hardwareRecognized()) { + return false; + } + + if (m_onlyUnused) { + if (m_manager->networks()->findBySerialPort(adapter->serialPort()) != nullptr) { + return false; + } } return true; diff --git a/libnymea-app/zigbee/zigbeeadaptersproxy.h b/libnymea-app/zigbee/zigbeeadaptersproxy.h index 44fa53d4..7005d7eb 100644 --- a/libnymea-app/zigbee/zigbeeadaptersproxy.h +++ b/libnymea-app/zigbee/zigbeeadaptersproxy.h @@ -35,14 +35,20 @@ #include class ZigbeeAdapter; -class ZigbeeAdapters; +class ZigbeeManager; class ZigbeeAdaptersProxy : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY(int count READ rowCount NOTIFY countChanged) - Q_PROPERTY(ZigbeeAdapters * adapters READ adapters WRITE setAdapters NOTIFY adaptersChanged) + + // Required + Q_PROPERTY(ZigbeeManager* manager READ manager WRITE setManager NOTIFY managerChanged) + + // Optional filtering Q_PROPERTY(ZigbeeAdaptersProxy::HardwareFilter hardwareFilter READ hardwareFilter WRITE setHardwareFilter NOTIFY hardwareFilterChanged) + Q_PROPERTY(bool onlyUnused READ onlyUnused WRITE setOnlyUnused NOTIFY onlyUnusedChanged) + public: enum HardwareFilter { HardwareFilterNone, @@ -53,12 +59,15 @@ public: explicit ZigbeeAdaptersProxy(QObject *parent = nullptr); - ZigbeeAdapters *adapters() const; - void setAdapters(ZigbeeAdapters *adapters); + ZigbeeManager *manager() const; + void setManager(ZigbeeManager *manager); HardwareFilter hardwareFilter() const; void setHardwareFilter(HardwareFilter hardwareFilter); + bool onlyUnused() const; + void setOnlyUnused(bool onlyUnused); + Q_INVOKABLE ZigbeeAdapter* get(int index) const; protected: @@ -66,13 +75,14 @@ protected: signals: void countChanged(); - void adaptersChanged(); + void managerChanged(); void hardwareFilterChanged(HardwareFilter hardwareFilter); + void onlyUnusedChanged(); private: - ZigbeeAdapters *m_adapters = nullptr; + ZigbeeManager *m_manager = nullptr; HardwareFilter m_hardwareFilter = HardwareFilterNone; - + bool m_onlyUnused = false; }; #endif // ZIGBEEADAPTERSPROXY_H diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp index 5c114dff..b967d339 100644 --- a/libnymea-app/zigbee/zigbeemanager.cpp +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -30,23 +30,24 @@ #include "zigbeemanager.h" +#include "engine.h" #include "jsonrpc/jsonrpcclient.h" #include "zigbee/zigbeeadapter.h" #include "zigbee/zigbeeadapters.h" #include "zigbee/zigbeenetwork.h" #include "zigbee/zigbeenetworks.h" +#include "zigbeenetworksandadapters.h" #include -ZigbeeManager::ZigbeeManager(JsonRpcClient *client, QObject *parent) : +ZigbeeManager::ZigbeeManager(QObject *parent) : JsonHandler(parent), - m_client(client), m_adapters(new ZigbeeAdapters(this)), - m_networks(new ZigbeeNetworks(this)) + m_networks(new ZigbeeNetworks(this)), + m_networksAndAdapters(new ZigbeeNetworksAndAdapters(this)) { qRegisterMetaType(); - client->registerNotificationHandler(this, "notificationReceived"); } ZigbeeManager::~ZigbeeManager() @@ -59,6 +60,20 @@ QString ZigbeeManager::nameSpace() const return "Zigbee"; } +void ZigbeeManager::setEngine(Engine *engine) +{ + if (m_engine != engine) { + m_engine = engine; + emit engineChanged(); + init(); + } +} + +Engine *ZigbeeManager::engine() const +{ + return m_engine; +} + ZigbeeAdapters *ZigbeeManager::adapters() const { return m_adapters; @@ -69,7 +84,12 @@ ZigbeeNetworks *ZigbeeManager::networks() const return m_networks; } -void ZigbeeManager::addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType) +ZigbeeNetworksAndAdapters *ZigbeeManager::networksAndAdapters() const +{ + return m_networksAndAdapters; +} + +int ZigbeeManager::addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType) { QVariantMap params; params.insert("serialPort", serialPort); @@ -78,7 +98,7 @@ void ZigbeeManager::addNetwork(const QString &serialPort, uint baudRate, ZigbeeA params.insert("backendType", metaEnum.valueToKey(backendType)); qDebug() << "Add zigbee network" << params; - m_client->sendCommand("Zigbee.AddNetwork", params, this, "addNetworkResponse"); + return m_engine->jsonRpcClient()->sendCommand("Zigbee.AddNetwork", params, this, "addNetworkResponse"); } void ZigbeeManager::removeNetwork(const QUuid &networkUuid) @@ -86,7 +106,7 @@ void ZigbeeManager::removeNetwork(const QUuid &networkUuid) QVariantMap params; params.insert("networkUuid", networkUuid); qDebug() << "Remove zigbee network" << params; - m_client->sendCommand("Zigbee.RemoveNetwork", params, this, "removeNetworkResponse"); + m_engine->jsonRpcClient()->sendCommand("Zigbee.RemoveNetwork", params, this, "removeNetworkResponse"); } void ZigbeeManager::setPermitJoin(const QUuid &networkUuid, uint duration) @@ -94,23 +114,25 @@ void ZigbeeManager::setPermitJoin(const QUuid &networkUuid, uint duration) QVariantMap params; params.insert("networkUuid", networkUuid); params.insert("duration", duration); - m_client->sendCommand("Zigbee.SetPermitJoin", params, this, "setPermitJoinResponse"); + m_engine->jsonRpcClient()->sendCommand("Zigbee.SetPermitJoin", params, this, "setPermitJoinResponse"); } void ZigbeeManager::factoryResetNetwork(const QUuid &networkUuid) { QVariantMap params; params.insert("networkUuid", networkUuid); - m_client->sendCommand("Zigbee.FactoryResetNetwork", params, this, "factoryResetNetworkResponse"); + m_engine->jsonRpcClient()->sendCommand("Zigbee.FactoryResetNetwork", params, this, "factoryResetNetworkResponse"); } void ZigbeeManager::init() { - // FIXME: load only when used m_adapters->clear(); m_networks->clear(); - m_client->sendCommand("Zigbee.GetAdapters", this, "getAdaptersResponse"); - m_client->sendCommand("Zigbee.GetNetworks", this, "getNetworksResponse"); + + m_engine->jsonRpcClient()->registerNotificationHandler(this, "notificationReceived"); + + m_engine->jsonRpcClient()->sendCommand("Zigbee.GetAdapters", this, "getAdaptersResponse"); + m_engine->jsonRpcClient()->sendCommand("Zigbee.GetNetworks", this, "getNetworksResponse"); } void ZigbeeManager::getAdaptersResponse(int commandId, const QVariantMap ¶ms) @@ -123,6 +145,15 @@ void ZigbeeManager::getAdaptersResponse(int commandId, const QVariantMap ¶ms qDebug() << "Zigbee adapter added" << adapter->description() << adapter->serialPort() << adapter->hardwareRecognized(); m_adapters->addAdapter(adapter); } + + ZigbeeAdapter *fakeAdapter = new ZigbeeAdapter(); + fakeAdapter->setSerialPort("/dev/fake"); + fakeAdapter->setBackendType(ZigbeeAdapter::ZigbeeBackendTypeDeconz); + fakeAdapter->setBaudRate(9600); + fakeAdapter->setDescription("Fake adapter"); + fakeAdapter->setHardwareRecognized(true); + fakeAdapter->setName("Fake"); + m_adapters->addAdapter(fakeAdapter); } void ZigbeeManager::getNetworksResponse(int commandId, const QVariantMap ¶ms) @@ -140,6 +171,7 @@ void ZigbeeManager::getNetworksResponse(int commandId, const QVariantMap ¶ms void ZigbeeManager::addNetworkResponse(int commandId, const QVariantMap ¶ms) { qDebug() << "Zigbee add network response" << commandId << params; + emit addNetworkReply(commandId, params.value("zigbeeError").toString(), params.value("networkUuid").toUuid()); } void ZigbeeManager::removeNetworkResponse(int commandId, const QVariantMap ¶ms) diff --git a/libnymea-app/zigbee/zigbeemanager.h b/libnymea-app/zigbee/zigbeemanager.h index e09c61ed..73cbff98 100644 --- a/libnymea-app/zigbee/zigbeemanager.h +++ b/libnymea-app/zigbee/zigbeemanager.h @@ -39,32 +39,44 @@ class JsonRpcClient; class ZigbeeAdapters; class ZigbeeNetwork; class ZigbeeNetworks; +class ZigbeeNetworksAndAdapters; +class Engine; class ZigbeeManager : public JsonHandler { Q_OBJECT + Q_PROPERTY(Engine* engine READ engine WRITE setEngine NOTIFY engineChanged) + Q_PROPERTY(ZigbeeAdapters *adapters READ adapters CONSTANT) Q_PROPERTY(ZigbeeNetworks *networks READ networks CONSTANT) + Q_PROPERTY(ZigbeeNetworksAndAdapters *networksAndAdapters READ networksAndAdapters CONSTANT) public: - explicit ZigbeeManager(JsonRpcClient* client, QObject *parent = nullptr); + explicit ZigbeeManager(QObject *parent = nullptr); ~ZigbeeManager(); QString nameSpace() const override; + void setEngine(Engine *engine); + Engine *engine() const; + ZigbeeAdapters *adapters() const; ZigbeeNetworks *networks() const; + ZigbeeNetworksAndAdapters *networksAndAdapters() const; - Q_INVOKABLE void addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType); + Q_INVOKABLE int addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType); Q_INVOKABLE void removeNetwork(const QUuid &networkUuid); Q_INVOKABLE void setPermitJoin(const QUuid &networkUuid, uint duration = 120); Q_INVOKABLE void factoryResetNetwork(const QUuid &networkUuid); - void init(); - signals: + void engineChanged(); + + void addNetworkReply(int commandId, const QString &error, const QUuid &networkUuid); private: + void init(); + Q_INVOKABLE void getAdaptersResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void getNetworksResponse(int commandId, const QVariantMap ¶ms); @@ -73,13 +85,13 @@ private: Q_INVOKABLE void setPermitJoinResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void factoryResetNetworkResponse(int commandId, const QVariantMap ¶ms); - Q_INVOKABLE void notificationReceived(const QVariantMap ¬ification); private: - JsonRpcClient* m_client = nullptr; + Engine* m_engine = nullptr; ZigbeeAdapters *m_adapters = nullptr; ZigbeeNetworks *m_networks = nullptr; + ZigbeeNetworksAndAdapters *m_networksAndAdapters = nullptr; ZigbeeAdapter *unpackAdapter(const QVariantMap &adapterMap); ZigbeeNetwork *unpackNetwork(const QVariantMap &networkMap); diff --git a/libnymea-app/zigbee/zigbeenetworks.cpp b/libnymea-app/zigbee/zigbeenetworks.cpp index 41a3ec62..66cfb5ed 100644 --- a/libnymea-app/zigbee/zigbeenetworks.cpp +++ b/libnymea-app/zigbee/zigbeenetworks.cpp @@ -177,6 +177,7 @@ void ZigbeeNetworks::removeNetwork(const QUuid &networkUuid) beginRemoveRows(QModelIndex(), i, i); m_networks.takeAt(i)->deleteLater(); endRemoveRows(); + emit countChanged(); return; } } @@ -193,7 +194,7 @@ void ZigbeeNetworks::clear() ZigbeeNetwork *ZigbeeNetworks::get(int index) const { - if (index < 0 || index > m_networks.count() - 1) { + if (index < 0 || index >= m_networks.count()) { return nullptr; } return m_networks.at(index); @@ -209,3 +210,13 @@ ZigbeeNetwork *ZigbeeNetworks::getNetwork(const QUuid &networkUuid) const return nullptr; } + +ZigbeeNetwork *ZigbeeNetworks::findBySerialPort(const QString &serialPort) const +{ + foreach (ZigbeeNetwork* network, m_networks) { + if (network->serialPort() == serialPort) { + return network; + } + } + return nullptr; +} diff --git a/libnymea-app/zigbee/zigbeenetworks.h b/libnymea-app/zigbee/zigbeenetworks.h index 3a6376ff..1c71a68f 100644 --- a/libnymea-app/zigbee/zigbeenetworks.h +++ b/libnymea-app/zigbee/zigbeenetworks.h @@ -73,6 +73,7 @@ public: Q_INVOKABLE virtual ZigbeeNetwork *get(int index) const; Q_INVOKABLE ZigbeeNetwork *getNetwork(const QUuid &networkUuid) const; + ZigbeeNetwork *findBySerialPort(const QString &serialPort) const; signals: void countChanged(); diff --git a/libnymea-app/zigbee/zigbeenetworksandadapters.cpp b/libnymea-app/zigbee/zigbeenetworksandadapters.cpp new file mode 100644 index 00000000..311fe652 --- /dev/null +++ b/libnymea-app/zigbee/zigbeenetworksandadapters.cpp @@ -0,0 +1,21 @@ +#include "zigbeenetworksandadapters.h" + +#include "zigbeemanager.h" + +ZigbeeNetworksAndAdapters::ZigbeeNetworksAndAdapters(ZigbeeManager *manager): + QAbstractListModel(manager), + m_manager(manager) +{ + +} + +int ZigbeeNetworksAndAdapters::rowCount(const QModelIndex &/*parent*/) const +{ +// return m_list.count(); + return 0; +} + +QVariant ZigbeeNetworksAndAdapters::data(const QModelIndex &index, int role) const +{ + return QVariant(); +} diff --git a/libnymea-app/zigbee/zigbeenetworksandadapters.h b/libnymea-app/zigbee/zigbeenetworksandadapters.h new file mode 100644 index 00000000..9977555d --- /dev/null +++ b/libnymea-app/zigbee/zigbeenetworksandadapters.h @@ -0,0 +1,26 @@ +#ifndef ZIGBEENETWORKSANDADAPTERS_H +#define ZIGBEENETWORKSANDADAPTERS_H + +#include + +class ZigbeeManager; + +class ZigbeeNetworksAndAdapters : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit ZigbeeNetworksAndAdapters(ZigbeeManager *manager); + + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + +signals: + +private: + ZigbeeManager *m_manager = nullptr; + +// QList< +}; + +#endif // ZIGBEENETWORKSANDADAPTERS_H diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc index c81ba76a..8e01e89b 100644 --- a/nymea-app/resources.qrc +++ b/nymea-app/resources.qrc @@ -227,6 +227,8 @@ ui/components/ThingInfoPane.qml ui/system/ZigbeeNetworkSettingsPage.qml ui/system/ZigbeeNetworkAddPage.qml + ui/system/ZigbeeSettingsPage.qml + ui/system/ZigbeeAddNetworkPage.qml ui/system/ZigbeeNetworkPage.qml ui/system/ZigbeeNetworkInfoPage.qml diff --git a/nymea-app/ui/SettingsPage.qml b/nymea-app/ui/SettingsPage.qml index 3ab74e44..023a40d1 100644 --- a/nymea-app/ui/SettingsPage.qml +++ b/nymea-app/ui/SettingsPage.qml @@ -156,17 +156,17 @@ Page { Pane { Layout.fillWidth: true Material.elevation: layout.isGrid ? 1 : 0 - visible: engine.jsonRpcClient.ensureServerVersion("1.11") + visible: engine.jsonRpcClient.ensureServerVersion("5.2") padding: 0 NymeaListItemDelegate { width: parent.width iconName: "../images/zigbee.svg" text: qsTr("Zigbee") - subText: qsTr("Manage and configure Zigbee networks") + subText: qsTr("Configure Zigbee networks") prominentSubText: false wrapTexts: false - onClicked: pageStack.push(Qt.resolvedUrl("system/ZigbeeNetworkSettingsPage.qml")) + onClicked: pageStack.push(Qt.resolvedUrl("system/ZigbeeSettingsPage.qml")) } } diff --git a/nymea-app/ui/system/NetworkSettingsPage.qml b/nymea-app/ui/system/NetworkSettingsPage.qml index 42da6468..f7865de5 100644 --- a/nymea-app/ui/system/NetworkSettingsPage.qml +++ b/nymea-app/ui/system/NetworkSettingsPage.qml @@ -132,6 +132,8 @@ SettingsPageBase { RowLayout { Layout.topMargin: app.margins * 6 + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins visible: !networkManager.available && !networkManager.loading spacing: app.margins ColorIcon { diff --git a/nymea-app/ui/system/ZigbeeAddNetworkPage.qml b/nymea-app/ui/system/ZigbeeAddNetworkPage.qml new file mode 100644 index 00000000..ad1b9379 --- /dev/null +++ b/nymea-app/ui/system/ZigbeeAddNetworkPage.qml @@ -0,0 +1,218 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.9 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.3 +import Nymea 1.0 + +import "../components" + +SettingsPageBase { + id: root + title: qsTr("Add a new Zigbee network") + busy: d.pendingCommandId != -1 + + property ZigbeeManager zigbeeManager: null + + + QtObject { + id: d + property int pendingCommandId: -1 + + function addNetwork(serialPort, baudRate, backendType) { + d.pendingCommandId = root.zigbeeManager.addNetwork(serialPort, baudRate, backendType) + } + } + + + Connections { + target: root.zigbeeManager + onAddNetworkReply: { + if (commandId == d.pendingCommandId) { + d.pendingCommandId = -1 + var props = {}; + switch (error) { + case "ZigbeeErrorNoError": + pageStack.pop(); + return; + case "ZigbeeErrorAdapterNotAvailable": + props.text = qsTr("The selected adapter is not available or the selected serial port configration is incorrect."); + break; + case "ZigbeeErrorAdapterAlreadyInUse": + props.text = qsTr("The selected adapter is already in use."); + break; + default: + props.errorCode = error; + } + var comp = Qt.createComponent("../components/ErrorDialog.qml") + var popup = comp.createObject(app, props) + popup.open(); + } + } + } + + SettingsPageSectionHeader { + text: qsTr("Hardware not available") + visible: root.zigbeeManager.adapters.count == 0 + } + + RowLayout { + Layout.leftMargin: app.margins + Layout.rightMargin: app.margins + visible: root.zigbeeManager.adapters.count == 0 + spacing: app.margins + ColorIcon { + Layout.preferredHeight: app.iconSize + Layout.preferredWidth: app.iconSize + name: "../images/connections/network-wifi-offline.svg" + } + Label { + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: qsTr("No Zigbee adapters or serial ports are available on this system. Connect a Zigbee adapter via USB or UART serial port.") + } + } + + SettingsPageSectionHeader { + text: qsTr("Available Zigbee adapters") + visible: recognizedAdapters.count > 0 + } + + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins; Layout.rightMargin: app.margins + text: qsTr("Please select the Zigbee adapter on which the new network will be created.") + font.pixelSize: app.smallFont + wrapMode: Text.WordWrap + visible: recognizedAdapters.count > 0 + } + + + Repeater { + id: recognizedRepeater + model: ZigbeeAdaptersProxy { + id: recognizedAdapters + manager: root.zigbeeManager + hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterRecognized + onlyUnused: true + } + + delegate: NymeaListItemDelegate { + Layout.fillWidth: true + iconName: "../images/zigbee.svg" + text: model.name + " - " + model.description + " - " + model.serialPort + onClicked: d.addNetwork(model.serialPort, model.baudRate, model.backendType) + } + } + + SettingsPageSectionHeader { + text: qsTr("Available serial ports") + visible: serialPorts.count > 0 + } + + Label { + Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins + wrapMode: Text.WordWrap + font.pixelSize: app.smallFont + text: qsTr("Please verify that the Zigbee adapter is properly connected to a serial port and select the appropriate port.") + visible: serialPorts.count > 0 + } + + Repeater { + id: unrecognizedRepeater + model: ZigbeeAdaptersProxy { + id: serialPorts + manager: root.zigbeeManager + hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterUnrecognized + onlyUnused: true + } + + delegate: NymeaListItemDelegate { + Layout.fillWidth: true + property ZigbeeAdapter adapter: root.zigbeeManager.adapters.get(index) + iconName: "../images/stock_usb.svg" + text: model.description + " - " + model.serialPort + onClicked: { + var dialog = serialPortOptionsDialogComponent.createObject(app, {serialPort: model.serialPort, baudRate: model.baudRate}) + dialog.open() + } + } + } + + + Component { + id: serialPortOptionsDialogComponent + MeaDialog { + id: serialPortOptionsDialog + property string serialPort + property int baudRate + + headerIcon: "../images/stock_usb.svg" + title: qsTr("Serial port options") + text: qsTr("Please select the serial port options for using the Zigbee adapter") + standardButtons: Dialog.Ok | Dialog.Cancel + + RowLayout { + Label { + text: qsTr("Adapter") + Layout.fillWidth: true + } + ComboBox { + id: backendComboBox + model: ListModel { + id: backendModel + ListElement { displayName: "deConz"; backendValue: ZigbeeAdapter.ZigbeeBackendTypeDeconz } + ListElement { displayName: "NXP"; backendValue: ZigbeeAdapter.ZigbeeBackendTypeNxp } + } + textRole: "displayName" + } + } + + RowLayout { + Label { + text: qsTr("Baud rate") + Layout.fillWidth: true + } + ComboBox { + id: baudRateComboBox + model: [300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600] + Component.onCompleted: { + currentIndex = indexOfValue(serialPortOptionsDialog.baudRate) + } + } + } + + onAccepted: { + d.addNetwork(serialPortOptionsDialog.serialPort, baudRateComboBox.currentValue, backendModel.get(backendComboBox.currentIndex).backendValue) + } + } + } +} diff --git a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml b/nymea-app/ui/system/ZigbeeNetworkAddPage.qml deleted file mode 100644 index 2c97a356..00000000 --- a/nymea-app/ui/system/ZigbeeNetworkAddPage.qml +++ /dev/null @@ -1,91 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* Copyright 2013 - 2020, nymea GmbH -* Contact: contact@nymea.io -* -* This file is part of nymea. -* This project including source code and documentation is protected by -* copyright law, and remains the property of nymea GmbH. All rights, including -* reproduction, publication, editing and translation, are reserved. The use of -* this project is subject to the terms of a license agreement to be concluded -* with nymea GmbH in accordance with the terms of use of nymea GmbH, available -* under https://nymea.io/license -* -* GNU General Public License Usage -* Alternatively, this project may be redistributed and/or modified under the -* terms of the GNU General Public License as published by the Free Software -* Foundation, GNU version 3. This project is distributed in the hope that it -* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -* Public License for more details. -* -* You should have received a copy of the GNU General Public License along with -* this project. If not, see . -* -* For any further details and any questions please contact us under -* contact@nymea.io or see our FAQ/Licensing Information on -* https://nymea.io/license/faq -* -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -import QtQuick 2.9 -import QtQuick.Controls 2.2 -import QtQuick.Layouts 1.3 -import Nymea 1.0 - -import "../components" - -SettingsPageBase { - id: root - title: qsTr("Add a new Zigbee network") - - - - SettingsPageSectionHeader { - text: qsTr("Zigbee adapters") - } - - Repeater { - id: recognizedRepeater - model: ZigbeeAdaptersProxy { - adapters: engine.zigbeeManager.adapters - hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterRecognized - } - - delegate: NymeaListItemDelegate { - Layout.fillWidth: true - property ZigbeeAdapter adapter: engine.zigbeeManager.adapters.get(index) - iconName: "../images/stock_usb.svg" - progressive: false - text: model.description + " - " + model.serialPort - onClicked: { - engine.zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) - pageStack.pop() - } - } - } - - SettingsPageSectionHeader { - text: qsTr("Unrecognized Zigbee adapters") - visible: unrecognizedRepeater.count !== 0 - } - - Repeater { - id: unrecognizedRepeater - model: ZigbeeAdaptersProxy { - adapters: engine.zigbeeManager.adapters - hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterUnrecognized - } - - delegate: NymeaListItemDelegate { - Layout.fillWidth: true - property ZigbeeAdapter adapter: engine.zigbeeManager.adapters.get(index) - iconName: "../images/stock_usb.svg" - text: model.description + " - " + model.serialPort - // TODO: show backend and baudrate popup before adding - onClicked: engine.zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) - } - } - - -} diff --git a/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml index 226f40f1..512d1517 100644 --- a/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml @@ -38,6 +38,8 @@ import Nymea 1.0 SettingsPageBase { id: root + property ZigbeeManager zigbeeManager: null + property ZigbeeNetwork network: null header: NymeaHeader { @@ -103,7 +105,7 @@ SettingsPageBase { Layout.rightMargin: app.margins text: qsTr("Remove network") onClicked: { - engine.zigbeeManager.removeNetwork(root.network.networkUuid) + root.zigbeeManager.removeNetwork(root.network.networkUuid) pageStack.pop() pageStack.pop() } diff --git a/nymea-app/ui/system/ZigbeeNetworkPage.qml b/nymea-app/ui/system/ZigbeeNetworkPage.qml index 3848a6e5..10aad8c0 100644 --- a/nymea-app/ui/system/ZigbeeNetworkPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkPage.qml @@ -38,6 +38,7 @@ import Nymea 1.0 SettingsPageBase { id: root + property ZigbeeManager zigbeeManager: null property ZigbeeNetwork network: null header: NymeaHeader { @@ -48,7 +49,7 @@ SettingsPageBase { HeaderButton { text: qsTr("Settings") imageSource: "../images/settings.svg" - onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeNetworkInfoPage.qml"), { network: root.network }) + onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeNetworkInfoPage.qml"), { network: root.network, zigbeeManager: root.zigbeeManager }) } } @@ -104,7 +105,6 @@ SettingsPageBase { } ColumnLayout { - anchors { left: parent.left; right: parent.right } ProgressBar { Layout.fillWidth: true @@ -122,7 +122,7 @@ SettingsPageBase { Layout.rightMargin: app.margins enabled: network.networkState === ZigbeeNetwork.ZigbeeNetworkStateOnline text: root.network.permitJoiningEnabled ? qsTr("Extend network open duration") : qsTr("Open network for new Zigbee devices") - onClicked: engine.zigbeeManager.setPermitJoin(root.network.networkUuid) + onClicked: root.zigbeeManager.setPermitJoin(root.network.networkUuid) } Button { @@ -131,7 +131,7 @@ SettingsPageBase { Layout.rightMargin: app.margins visible: network.networkState === ZigbeeNetwork.ZigbeeNetworkStateOnline && root.network.permitJoiningEnabled text: qsTr("Close network") - onClicked: engine.zigbeeManager.setPermitJoin(root.network.networkUuid, 0) + onClicked: root.zigbeeManager.setPermitJoin(root.network.networkUuid, 0) } } diff --git a/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml b/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml deleted file mode 100644 index c1f64411..00000000 --- a/nymea-app/ui/system/ZigbeeNetworkSettingsPage.qml +++ /dev/null @@ -1,86 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* Copyright 2013 - 2020, nymea GmbH -* Contact: contact@nymea.io -* -* This file is part of nymea. -* This project including source code and documentation is protected by -* copyright law, and remains the property of nymea GmbH. All rights, including -* reproduction, publication, editing and translation, are reserved. The use of -* this project is subject to the terms of a license agreement to be concluded -* with nymea GmbH in accordance with the terms of use of nymea GmbH, available -* under https://nymea.io/license -* -* GNU General Public License Usage -* Alternatively, this project may be redistributed and/or modified under the -* terms of the GNU General Public License as published by the Free Software -* Foundation, GNU version 3. This project is distributed in the hope that it -* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -* Public License for more details. -* -* You should have received a copy of the GNU General Public License along with -* this project. If not, see . -* -* For any further details and any questions please contact us under -* contact@nymea.io or see our FAQ/Licensing Information on -* https://nymea.io/license/faq -* -* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -import QtQuick 2.8 -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.1 -import QtQuick.Layouts 1.3 -import "../components" -import Nymea 1.0 - -SettingsPageBase { - id: root - header: NymeaHeader { - text: qsTr("Zigbee") - backButtonVisible: true - onBackPressed: pageStack.pop() - - // TODO: create a settings page where zigbee networking can be enabled/disabled in general - // HeaderButton { - // text: qsTr("Settings") - // imageSource: "../images/settings.svg" - // onClicked: { - // //pageStack.push() - // } - // } - } - - ColumnLayout { - id: contentColumn - anchors.fill: parent - - // List networks - SettingsPageSectionHeader { - text: qsTr("Zigbee networks") - } - - Repeater { - model: engine.zigbeeManager.networks - delegate: NymeaListItemDelegate { - Layout.fillWidth: true - property var network: engine.zigbeeManager.networks.get(index) - iconName: "../images/zigbee.svg" - text: model.macAddress - subText: model.serialPort + " - " + model.firmwareVersion - onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeNetworkPage.qml"), { network: network }) - } - } - - NymeaListItemDelegate { - Layout.fillWidth: true - text: qsTr("Add Zigbee network") - subText: qsTr("Set up a new Zigbee network") - prominentSubText: false - onClicked: { - pageStack.push(Qt.resolvedUrl("../system/ZigbeeNetworkAddPage.qml")) - } - } - } -} diff --git a/nymea-app/ui/system/ZigbeeSettingsPage.qml b/nymea-app/ui/system/ZigbeeSettingsPage.qml new file mode 100644 index 00000000..8c659685 --- /dev/null +++ b/nymea-app/ui/system/ZigbeeSettingsPage.qml @@ -0,0 +1,160 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU General Public License as published by the Free Software +* Foundation, GNU version 3. This project is distributed in the hope that it +* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +* Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.8 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.1 +import QtQuick.Layouts 1.3 +import "../components" +import Nymea 1.0 + +SettingsPageBase { + id: root + header: NymeaHeader { + text: qsTr("Zigbee") + backButtonVisible: true + onBackPressed: pageStack.pop() + + HeaderButton { + imageSource: "../images/add.svg" + text: qsTr("Add Zigbee network") + onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeAddNetworkPage.qml"), {zigbeeManager: zigbeeManager}) + } + } + + ZigbeeManager { + id: zigbeeManager + engine: _engine + } + + SettingsPageSectionHeader { + text: qsTr("General") + } + + NymeaListItemDelegate { + Layout.fillWidth: true + text: qsTr("Zigbee enabled") + subText: qsTr("Enable or disable Zigbee altogether") + prominentSubText: false + progressive: false + additionalItem: Switch { + anchors.centerIn: parent + } + } + + SettingsPageSectionHeader { + text: qsTr("Zigbee networks") + } + + Label { + Layout.fillWidth: true + Layout.leftMargin: app.margins; Layout.rightMargin: app.margins + wrapMode: Text.WordWrap + text: qsTr("There are no Zigbee networks set up yet. In order to use Zigbee, create a Zigbee network.") + visible: zigbeeManager.networks.count == 0 + } + + Repeater { + model: zigbeeManager.networks + delegate: NymeaListItemDelegate { + Layout.fillWidth: true + property var network: zigbeeManager.networks.get(index) + iconName: "../images/zigbee.svg" + text: model.macAddress + subText: model.serialPort + " - " + model.firmwareVersion + onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeNetworkPage.qml"), { zigbeeManager: zigbeeManager, network: network }) + } + } + + Button { + Layout.fillWidth: true + Layout.margins: app.margins + text: qsTr("Add a Zigbee network") + onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeAddNetworkPage.qml"), {zigbeeManager: zigbeeManager}) + } + + +// SettingsPageSectionHeader { +// text: qsTr("Available Zigbee adapters") +// } + +// Repeater { +// id: recognizedAdaptersRepeater +// model: ZigbeeAdaptersProxy { +// id: recognizedAdaptersProxy +// manager: zigbeeManager +// onlyUnused: true +//// hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterRecognized +// } + +// delegate: NymeaListItemDelegate { +// Layout.fillWidth: true +// property ZigbeeAdapter adapter: recognizedAdaptersProxy.get(index) +// iconName: "../images/stock_usb.svg" +// progressive: false +// text: model.description + " - " + model.serialPort +// subText: adapter.serialPort + " - " + adapter.baudRate + " - " + adapter.backendType + " - " + adapter.serialNumber +// onClicked: { +// zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) +//// pageStack.pop() +// } +// } +// } + + +// // List networks +// SettingsPageSectionHeader { +// text: qsTr("Zigbee networks") +// } + +// Repeater { +// model: zigbeeManager.networks +// delegate: NymeaListItemDelegate { +// Layout.fillWidth: true +// property var network: zigbeeManager.networks.get(index) +// iconName: "../images/zigbee.svg" +// text: model.macAddress +// subText: model.serialPort + " - " + model.firmwareVersion +// onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeNetworkPage.qml"), { network: network }) +// } +// } + +// NymeaListItemDelegate { +// Layout.fillWidth: true +// text: qsTr("Add Zigbee network") +// subText: qsTr("Set up a new Zigbee network") +// prominentSubText: false +// onClicked: { +// pageStack.push(Qt.resolvedUrl("../system/ZigbeeNetworkAddPage.qml"), {zigbeeManager: zigbeeManager}) +// } +// } + +} + From 4a5859f453aa7efb89ae4f07f9caffcf8d3ae212 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 16 Nov 2020 17:01:54 +0100 Subject: [PATCH 09/18] bump minimum required jsonrpc version for zigbee support --- nymea-app/ui/SettingsPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nymea-app/ui/SettingsPage.qml b/nymea-app/ui/SettingsPage.qml index 023a40d1..7e5c8dbf 100644 --- a/nymea-app/ui/SettingsPage.qml +++ b/nymea-app/ui/SettingsPage.qml @@ -156,7 +156,7 @@ Page { Pane { Layout.fillWidth: true Material.elevation: layout.isGrid ? 1 : 0 - visible: engine.jsonRpcClient.ensureServerVersion("5.2") + visible: engine.jsonRpcClient.ensureServerVersion("5.3") padding: 0 NymeaListItemDelegate { From 9144e0d2b6c06a17069d10b655dddab024818b11 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 16 Nov 2020 17:09:41 +0100 Subject: [PATCH 10/18] drop unused files --- libnymea-app/libnymea-app.pro | 6 ++--- .../zigbee/zigbeenetworksandadapters.cpp | 21 --------------- .../zigbee/zigbeenetworksandadapters.h | 26 ------------------ nymea-app/ui/system/ZigbeeSettingsPage.qml | 27 ++++++++++--------- 4 files changed, 16 insertions(+), 64 deletions(-) delete mode 100644 libnymea-app/zigbee/zigbeenetworksandadapters.cpp delete mode 100644 libnymea-app/zigbee/zigbeenetworksandadapters.h diff --git a/libnymea-app/libnymea-app.pro b/libnymea-app/libnymea-app.pro index 0ca71ae5..b0cdc5b9 100644 --- a/libnymea-app/libnymea-app.pro +++ b/libnymea-app/libnymea-app.pro @@ -165,8 +165,7 @@ SOURCES += \ zigbee/zigbeemanager.cpp \ zigbee/zigbeeadapter.cpp \ zigbee/zigbeenetwork.cpp \ - zigbee/zigbeenetworks.cpp \ - zigbee/zigbeenetworksandadapters.cpp + zigbee/zigbeenetworks.cpp @@ -312,8 +311,7 @@ HEADERS += \ zigbee/zigbeemanager.h \ zigbee/zigbeeadapter.h \ zigbee/zigbeenetwork.h \ - zigbee/zigbeenetworks.h \ - zigbee/zigbeenetworksandadapters.h + zigbee/zigbeenetworks.h ubports: { DEFINES += UBPORTS diff --git a/libnymea-app/zigbee/zigbeenetworksandadapters.cpp b/libnymea-app/zigbee/zigbeenetworksandadapters.cpp deleted file mode 100644 index 311fe652..00000000 --- a/libnymea-app/zigbee/zigbeenetworksandadapters.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "zigbeenetworksandadapters.h" - -#include "zigbeemanager.h" - -ZigbeeNetworksAndAdapters::ZigbeeNetworksAndAdapters(ZigbeeManager *manager): - QAbstractListModel(manager), - m_manager(manager) -{ - -} - -int ZigbeeNetworksAndAdapters::rowCount(const QModelIndex &/*parent*/) const -{ -// return m_list.count(); - return 0; -} - -QVariant ZigbeeNetworksAndAdapters::data(const QModelIndex &index, int role) const -{ - return QVariant(); -} diff --git a/libnymea-app/zigbee/zigbeenetworksandadapters.h b/libnymea-app/zigbee/zigbeenetworksandadapters.h deleted file mode 100644 index 9977555d..00000000 --- a/libnymea-app/zigbee/zigbeenetworksandadapters.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef ZIGBEENETWORKSANDADAPTERS_H -#define ZIGBEENETWORKSANDADAPTERS_H - -#include - -class ZigbeeManager; - -class ZigbeeNetworksAndAdapters : public QAbstractListModel -{ - Q_OBJECT - -public: - explicit ZigbeeNetworksAndAdapters(ZigbeeManager *manager); - - int rowCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - -signals: - -private: - ZigbeeManager *m_manager = nullptr; - -// QList< -}; - -#endif // ZIGBEENETWORKSANDADAPTERS_H diff --git a/nymea-app/ui/system/ZigbeeSettingsPage.qml b/nymea-app/ui/system/ZigbeeSettingsPage.qml index 8c659685..26661f6a 100644 --- a/nymea-app/ui/system/ZigbeeSettingsPage.qml +++ b/nymea-app/ui/system/ZigbeeSettingsPage.qml @@ -54,20 +54,21 @@ SettingsPageBase { engine: _engine } - SettingsPageSectionHeader { - text: qsTr("General") - } + // Disabled for now, the Resources API won't make it in time +// SettingsPageSectionHeader { +// text: qsTr("General") +// } - NymeaListItemDelegate { - Layout.fillWidth: true - text: qsTr("Zigbee enabled") - subText: qsTr("Enable or disable Zigbee altogether") - prominentSubText: false - progressive: false - additionalItem: Switch { - anchors.centerIn: parent - } - } +// NymeaListItemDelegate { +// Layout.fillWidth: true +// text: qsTr("Zigbee enabled") +// subText: qsTr("Enable or disable Zigbee altogether") +// prominentSubText: false +// progressive: false +// additionalItem: Switch { +// anchors.centerIn: parent +// } +// } SettingsPageSectionHeader { text: qsTr("Zigbee networks") From 747c5a53435efbc53c4dc75d0ee0852c5f3ddfac Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 16 Nov 2020 17:19:58 +0100 Subject: [PATCH 11/18] drop fake adapter --- libnymea-app/zigbee/zigbeemanager.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp index b967d339..193fa88f 100644 --- a/libnymea-app/zigbee/zigbeemanager.cpp +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -146,14 +146,14 @@ void ZigbeeManager::getAdaptersResponse(int commandId, const QVariantMap ¶ms m_adapters->addAdapter(adapter); } - ZigbeeAdapter *fakeAdapter = new ZigbeeAdapter(); - fakeAdapter->setSerialPort("/dev/fake"); - fakeAdapter->setBackendType(ZigbeeAdapter::ZigbeeBackendTypeDeconz); - fakeAdapter->setBaudRate(9600); - fakeAdapter->setDescription("Fake adapter"); - fakeAdapter->setHardwareRecognized(true); - fakeAdapter->setName("Fake"); - m_adapters->addAdapter(fakeAdapter); +// ZigbeeAdapter *fakeAdapter = new ZigbeeAdapter(); +// fakeAdapter->setSerialPort("/dev/fake"); +// fakeAdapter->setBackendType(ZigbeeAdapter::ZigbeeBackendTypeDeconz); +// fakeAdapter->setBaudRate(9600); +// fakeAdapter->setDescription("Fake adapter"); +// fakeAdapter->setHardwareRecognized(true); +// fakeAdapter->setName("Fake"); +// m_adapters->addAdapter(fakeAdapter); } void ZigbeeManager::getNetworksResponse(int commandId, const QVariantMap ¶ms) From f6af8d5cec744474563f473d1e7499a18e96f8cf Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 16 Nov 2020 17:21:48 +0100 Subject: [PATCH 12/18] cleanup old code --- libnymea-app/zigbee/zigbeemanager.cpp | 9 +-------- libnymea-app/zigbee/zigbeemanager.h | 4 ---- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp index 193fa88f..868a918a 100644 --- a/libnymea-app/zigbee/zigbeemanager.cpp +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -36,15 +36,13 @@ #include "zigbee/zigbeeadapters.h" #include "zigbee/zigbeenetwork.h" #include "zigbee/zigbeenetworks.h" -#include "zigbeenetworksandadapters.h" #include ZigbeeManager::ZigbeeManager(QObject *parent) : JsonHandler(parent), m_adapters(new ZigbeeAdapters(this)), - m_networks(new ZigbeeNetworks(this)), - m_networksAndAdapters(new ZigbeeNetworksAndAdapters(this)) + m_networks(new ZigbeeNetworks(this)) { qRegisterMetaType(); @@ -84,11 +82,6 @@ ZigbeeNetworks *ZigbeeManager::networks() const return m_networks; } -ZigbeeNetworksAndAdapters *ZigbeeManager::networksAndAdapters() const -{ - return m_networksAndAdapters; -} - int ZigbeeManager::addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType) { QVariantMap params; diff --git a/libnymea-app/zigbee/zigbeemanager.h b/libnymea-app/zigbee/zigbeemanager.h index 73cbff98..0e51c35c 100644 --- a/libnymea-app/zigbee/zigbeemanager.h +++ b/libnymea-app/zigbee/zigbeemanager.h @@ -39,7 +39,6 @@ class JsonRpcClient; class ZigbeeAdapters; class ZigbeeNetwork; class ZigbeeNetworks; -class ZigbeeNetworksAndAdapters; class Engine; class ZigbeeManager : public JsonHandler @@ -49,7 +48,6 @@ class ZigbeeManager : public JsonHandler Q_PROPERTY(ZigbeeAdapters *adapters READ adapters CONSTANT) Q_PROPERTY(ZigbeeNetworks *networks READ networks CONSTANT) - Q_PROPERTY(ZigbeeNetworksAndAdapters *networksAndAdapters READ networksAndAdapters CONSTANT) public: explicit ZigbeeManager(QObject *parent = nullptr); @@ -62,7 +60,6 @@ public: ZigbeeAdapters *adapters() const; ZigbeeNetworks *networks() const; - ZigbeeNetworksAndAdapters *networksAndAdapters() const; Q_INVOKABLE int addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType); Q_INVOKABLE void removeNetwork(const QUuid &networkUuid); @@ -91,7 +88,6 @@ private: Engine* m_engine = nullptr; ZigbeeAdapters *m_adapters = nullptr; ZigbeeNetworks *m_networks = nullptr; - ZigbeeNetworksAndAdapters *m_networksAndAdapters = nullptr; ZigbeeAdapter *unpackAdapter(const QVariantMap &adapterMap); ZigbeeNetwork *unpackNetwork(const QVariantMap &networkMap); From c268cfebec93d6ef675354acc8fb7c1f1471ba9f Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 16 Nov 2020 23:41:55 +0100 Subject: [PATCH 13/18] fixes --- nymea-app/ui/system/ZigbeeAddNetworkPage.qml | 2 +- nymea-app/ui/system/ZigbeeNetworkInfoPage.qml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/nymea-app/ui/system/ZigbeeAddNetworkPage.qml b/nymea-app/ui/system/ZigbeeAddNetworkPage.qml index ad1b9379..7ae1b1b7 100644 --- a/nymea-app/ui/system/ZigbeeAddNetworkPage.qml +++ b/nymea-app/ui/system/ZigbeeAddNetworkPage.qml @@ -211,7 +211,7 @@ SettingsPageBase { } onAccepted: { - d.addNetwork(serialPortOptionsDialog.serialPort, baudRateComboBox.currentValue, backendModel.get(backendComboBox.currentIndex).backendValue) + d.addNetwork(serialPortOptionsDialog.serialPort, baudRateComboBox.currentText, backendModel.get(backendComboBox.currentIndex).backendValue) } } } diff --git a/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml index 512d1517..6c10ac62 100644 --- a/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml @@ -97,7 +97,6 @@ SettingsPageBase { } ColumnLayout { - anchors { left: parent.left; right: parent.right } Button { Layout.fillWidth: true @@ -117,7 +116,7 @@ SettingsPageBase { Layout.rightMargin: app.margins text: qsTr("Factory reset controller") onClicked: { - engine.zigbeeManager.factoryResetNetwork(root.network.networkUuid) + root.zigbeeManager.factoryResetNetwork(root.network.networkUuid) pageStack.pop() } } From 000b7d7b6f69fca36b6f977c4966d22f691861ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 18 Nov 2020 12:20:52 +0100 Subject: [PATCH 14/18] Update zigbee to API changes and fix custom serial port dialog --- QtZeroConf | 2 +- libnymea-app/zigbee/zigbeeadapter.cpp | 38 ++++--------------- libnymea-app/zigbee/zigbeeadapter.h | 22 +++-------- libnymea-app/zigbee/zigbeeadapters.cpp | 10 ++--- libnymea-app/zigbee/zigbeeadapters.h | 2 +- libnymea-app/zigbee/zigbeemanager.cpp | 29 ++++++++++---- libnymea-app/zigbee/zigbeemanager.h | 8 +++- libnymea-app/zigbee/zigbeenetwork.cpp | 12 +++--- libnymea-app/zigbee/zigbeenetwork.h | 10 ++--- libnymea-app/zigbee/zigbeenetworks.cpp | 10 ++--- libnymea-app/zigbee/zigbeenetworks.h | 2 +- nymea-app/ui/system/ZigbeeAddNetworkPage.qml | 25 ++++++------ nymea-app/ui/system/ZigbeeNetworkInfoPage.qml | 2 +- nymea-app/ui/system/ZigbeeSettingsPage.qml | 2 +- 14 files changed, 78 insertions(+), 96 deletions(-) diff --git a/QtZeroConf b/QtZeroConf index cbf4f2bf..39efbe28 160000 --- a/QtZeroConf +++ b/QtZeroConf @@ -1 +1 @@ -Subproject commit cbf4f2bf7b926b9a874af013efbf0f6dde3155e9 +Subproject commit 39efbe2879d93bd483ee1f14fc94281a03b49935 diff --git a/libnymea-app/zigbee/zigbeeadapter.cpp b/libnymea-app/zigbee/zigbeeadapter.cpp index 8e3a591f..7a4f3741 100644 --- a/libnymea-app/zigbee/zigbeeadapter.cpp +++ b/libnymea-app/zigbee/zigbeeadapter.cpp @@ -90,15 +90,15 @@ void ZigbeeAdapter::setHardwareRecognized(bool hardwareRecognized) emit hardwareRecognizedChanged(); } -ZigbeeAdapter::ZigbeeBackendType ZigbeeAdapter::backendType() const +QString ZigbeeAdapter::backend() const { - return m_backendType; + return m_backend; } -void ZigbeeAdapter::setBackendType(ZigbeeAdapter::ZigbeeBackendType backendType) +void ZigbeeAdapter::setBackend(const QString &backend) { - m_backendType = backendType; - emit backendTypeChanged(); + m_backend = backend; + emit backendChanged(); } qint32 ZigbeeAdapter::baudRate() const @@ -118,40 +118,16 @@ bool ZigbeeAdapter::operator==(const ZigbeeAdapter &other) const && m_name == other.name() && m_description == other.description() && m_hardwareRecognized == other.hardwareRecognized() - && m_backendType == other.backendType() + && m_backend == other.backend() && m_baudRate == other.baudRate(); } -ZigbeeAdapter::ZigbeeBackendType ZigbeeAdapter::stringToZigbeeBackendType(const QString &backendTypeString) -{ - if (backendTypeString == "ZigbeeBackendTypeNxp") { - return ZigbeeBackendTypeNxp; - } else if (backendTypeString == "ZigbeeBackendTypeDeconz") { - return ZigbeeBackendTypeDeconz; - } else { - // default if not recognized - return ZigbeeBackendTypeDeconz; - } -} - -QString ZigbeeAdapter::getBackendName(ZigbeeAdapter::ZigbeeBackendType backendType) -{ - switch (backendType) { - case ZigbeeAdapter::ZigbeeBackendTypeDeconz: - return "deCONZ"; - case ZigbeeAdapter::ZigbeeBackendTypeNxp: - return "Nxp"; - default: - return tr("Unknown"); - } -} - QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter) { debug.nospace() << "ZigbeeAdapter(" << adapter.name() << " - " << adapter.description(); debug.nospace() << ", " << adapter.serialPort(); if (adapter.hardwareRecognized()) { - debug.nospace() << " Hardware recognized: " << adapter.backendType(); + debug.nospace() << " Hardware recognized: " << adapter.backend(); debug.nospace() << ", " << adapter.baudRate(); } diff --git a/libnymea-app/zigbee/zigbeeadapter.h b/libnymea-app/zigbee/zigbeeadapter.h index 434fdfa3..7bf1ab28 100644 --- a/libnymea-app/zigbee/zigbeeadapter.h +++ b/libnymea-app/zigbee/zigbeeadapter.h @@ -42,16 +42,10 @@ class ZigbeeAdapter : public QObject Q_PROPERTY(QString serialPort READ serialPort WRITE setSerialPort NOTIFY serialPortChanged) Q_PROPERTY(QString serialNumber READ serialNumber WRITE setSerialNumber NOTIFY serialNumberChanged) Q_PROPERTY(bool hardwareRecognized READ hardwareRecognized WRITE setHardwareRecognized NOTIFY hardwareRecognizedChanged) - Q_PROPERTY(ZigbeeAdapter::ZigbeeBackendType backendType READ backendType WRITE setBackendType NOTIFY backendTypeChanged) + Q_PROPERTY(QString backend READ backend WRITE setBackend NOTIFY backendChanged) Q_PROPERTY(qint32 baudRate READ baudRate WRITE setBaudRate NOTIFY baudRateChanged) public: - enum ZigbeeBackendType { - ZigbeeBackendTypeDeconz, - ZigbeeBackendTypeNxp - }; - Q_ENUM(ZigbeeBackendType) - explicit ZigbeeAdapter(QObject *parent = nullptr); QString name() const; @@ -69,25 +63,21 @@ public: bool hardwareRecognized() const; void setHardwareRecognized(bool hardwareRecognized); - ZigbeeAdapter::ZigbeeBackendType backendType() const; - void setBackendType(ZigbeeAdapter::ZigbeeBackendType backendType); + QString backend() const; + void setBackend(const QString &backend); qint32 baudRate() const; void setBaudRate(qint32 baudRate); bool operator==(const ZigbeeAdapter &other) const; - static ZigbeeAdapter::ZigbeeBackendType stringToZigbeeBackendType(const QString &backendTypeString); - - Q_INVOKABLE static QString getBackendName(ZigbeeAdapter::ZigbeeBackendType backendType); - private: QString m_name; QString m_description; QString m_serialPort; QString m_serialNumber; bool m_hardwareRecognized = false; - ZigbeeAdapter::ZigbeeBackendType m_backendType = ZigbeeAdapter::ZigbeeBackendTypeDeconz; + QString m_backend; qint32 m_baudRate = 38400; signals: @@ -96,12 +86,10 @@ signals: void serialPortChanged(); void serialNumberChanged(); void hardwareRecognizedChanged(); - void backendTypeChanged(); + void backendChanged(); void baudRateChanged(); }; -Q_DECLARE_METATYPE(ZigbeeAdapter::ZigbeeBackendType) - QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter); #endif // ZIGBEEADAPTER_H diff --git a/libnymea-app/zigbee/zigbeeadapters.cpp b/libnymea-app/zigbee/zigbeeadapters.cpp index 6f701f46..6e3a9d53 100644 --- a/libnymea-app/zigbee/zigbeeadapters.cpp +++ b/libnymea-app/zigbee/zigbeeadapters.cpp @@ -52,8 +52,8 @@ QVariant ZigbeeAdapters::data(const QModelIndex &index, int role) const return m_adapters.at(index.row())->serialPort(); case RoleHardwareRecognized: return m_adapters.at(index.row())->hardwareRecognized(); - case RoleBackendType: - return m_adapters.at(index.row())->backendType(); + case RoleBackend: + return m_adapters.at(index.row())->backend(); case RoleBaudRate: return m_adapters.at(index.row())->baudRate(); } @@ -67,7 +67,7 @@ QHash ZigbeeAdapters::roleNames() const roles.insert(RoleDescription, "description"); roles.insert(RoleSerialPort, "serialPort"); roles.insert(RoleHardwareRecognized, "hardwareRecognized"); - roles.insert(RoleBackendType, "backendType"); + roles.insert(RoleBackend, "backend"); roles.insert(RoleBaudRate, "baudRate"); return roles; } @@ -99,9 +99,9 @@ void ZigbeeAdapters::addAdapter(ZigbeeAdapter *adapter) emit dataChanged(idx, idx, {RoleHardwareRecognized}); }); - connect(adapter, &ZigbeeAdapter::backendTypeChanged, this, [this, adapter]() { + connect(adapter, &ZigbeeAdapter::backendChanged, this, [this, adapter]() { QModelIndex idx = index(m_adapters.indexOf(adapter), 0); - emit dataChanged(idx, idx, {RoleBackendType}); + emit dataChanged(idx, idx, {RoleBackend}); }); connect(adapter, &ZigbeeAdapter::baudRateChanged, this, [this, adapter]() { diff --git a/libnymea-app/zigbee/zigbeeadapters.h b/libnymea-app/zigbee/zigbeeadapters.h index e4cf2433..a022f754 100644 --- a/libnymea-app/zigbee/zigbeeadapters.h +++ b/libnymea-app/zigbee/zigbeeadapters.h @@ -47,7 +47,7 @@ public: RoleDescription, RoleSerialPort, RoleHardwareRecognized, - RoleBackendType, + RoleBackend, RoleBaudRate }; Q_ENUM(Roles) diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp index 868a918a..622bc1c0 100644 --- a/libnymea-app/zigbee/zigbeemanager.cpp +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -44,7 +44,6 @@ ZigbeeManager::ZigbeeManager(QObject *parent) : m_adapters(new ZigbeeAdapters(this)), m_networks(new ZigbeeNetworks(this)) { - qRegisterMetaType(); } @@ -72,6 +71,11 @@ Engine *ZigbeeManager::engine() const return m_engine; } +QStringList ZigbeeManager::availableBackends() const +{ + return m_availableBackends; +} + ZigbeeAdapters *ZigbeeManager::adapters() const { return m_adapters; @@ -82,13 +86,12 @@ ZigbeeNetworks *ZigbeeManager::networks() const return m_networks; } -int ZigbeeManager::addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType) +int ZigbeeManager::addNetwork(const QString &serialPort, uint baudRate, const QString &backend) { QVariantMap params; params.insert("serialPort", serialPort); params.insert("baudRate", baudRate); - QMetaEnum metaEnum = QMetaEnum::fromType(); - params.insert("backendType", metaEnum.valueToKey(backendType)); + params.insert("backend", backend); qDebug() << "Add zigbee network" << params; return m_engine->jsonRpcClient()->sendCommand("Zigbee.AddNetwork", params, this, "addNetworkResponse"); @@ -121,13 +124,25 @@ void ZigbeeManager::init() { m_adapters->clear(); m_networks->clear(); + m_availableBackends.clear(); m_engine->jsonRpcClient()->registerNotificationHandler(this, "notificationReceived"); + m_engine->jsonRpcClient()->sendCommand("Zigbee.GetAvailableBackends", this, "getAvailableBackendsResponse"); m_engine->jsonRpcClient()->sendCommand("Zigbee.GetAdapters", this, "getAdaptersResponse"); m_engine->jsonRpcClient()->sendCommand("Zigbee.GetNetworks", this, "getNetworksResponse"); } +void ZigbeeManager::getAvailableBackendsResponse(int commandId, const QVariantMap ¶ms) +{ + qDebug() << "Zigbee get available backends response" << commandId << params; + m_availableBackends.clear(); + foreach (const QVariant &backendVariant, params.value("backends").toList()) { + m_availableBackends << backendVariant.toString(); + } + emit availableBackendsChanged(); +} + void ZigbeeManager::getAdaptersResponse(int commandId, const QVariantMap ¶ms) { qDebug() << "Zigbee get adapters response" << commandId << params; @@ -141,7 +156,7 @@ void ZigbeeManager::getAdaptersResponse(int commandId, const QVariantMap ¶ms // ZigbeeAdapter *fakeAdapter = new ZigbeeAdapter(); // fakeAdapter->setSerialPort("/dev/fake"); -// fakeAdapter->setBackendType(ZigbeeAdapter::ZigbeeBackendTypeDeconz); +// fakeAdapter->setBackend("Fake"); // fakeAdapter->setBaudRate(9600); // fakeAdapter->setDescription("Fake adapter"); // fakeAdapter->setHardwareRecognized(true); @@ -232,7 +247,7 @@ ZigbeeAdapter *ZigbeeManager::unpackAdapter(const QVariantMap &adapterMap) adapter->setSerialPort(adapterMap.value("serialPort").toString()); adapter->setSerialNumber(adapterMap.value("serialNumber").toString()); adapter->setHardwareRecognized(adapterMap.value("hardwareRecognized").toBool()); - adapter->setBackendType(ZigbeeAdapter::stringToZigbeeBackendType(adapterMap.value("backendType").toString())); + adapter->setBackend(adapterMap.value("backend").toString()); adapter->setBaudRate(adapterMap.value("baudRate").toUInt()); return adapter; } @@ -257,7 +272,7 @@ void ZigbeeManager::fillNetworkData(ZigbeeNetwork *network, const QVariantMap &n network->setPermitJoiningEnabled(networkMap.value("permitJoiningEnabled").toBool()); network->setPermitJoiningDuration(networkMap.value("permitJoiningDuration").toUInt()); network->setPermitJoiningRemaining(networkMap.value("permitJoiningRemaining").toUInt()); - network->setBackendType(ZigbeeAdapter::stringToZigbeeBackendType(networkMap.value("backendType").toString())); + network->setBackend(networkMap.value("backend").toString()); network->setNetworkState(ZigbeeNetwork::stringToZigbeeNetworkState(networkMap.value("networkState").toString())); } diff --git a/libnymea-app/zigbee/zigbeemanager.h b/libnymea-app/zigbee/zigbeemanager.h index 0e51c35c..abe55811 100644 --- a/libnymea-app/zigbee/zigbeemanager.h +++ b/libnymea-app/zigbee/zigbeemanager.h @@ -46,6 +46,7 @@ class ZigbeeManager : public JsonHandler Q_OBJECT Q_PROPERTY(Engine* engine READ engine WRITE setEngine NOTIFY engineChanged) + Q_PROPERTY(QStringList availableBackends READ availableBackends NOTIFY availableBackendsChanged) Q_PROPERTY(ZigbeeAdapters *adapters READ adapters CONSTANT) Q_PROPERTY(ZigbeeNetworks *networks READ networks CONSTANT) @@ -58,22 +59,24 @@ public: void setEngine(Engine *engine); Engine *engine() const; + QStringList availableBackends() const; ZigbeeAdapters *adapters() const; ZigbeeNetworks *networks() const; - Q_INVOKABLE int addNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType); + Q_INVOKABLE int addNetwork(const QString &serialPort, uint baudRate, const QString &backend); Q_INVOKABLE void removeNetwork(const QUuid &networkUuid); Q_INVOKABLE void setPermitJoin(const QUuid &networkUuid, uint duration = 120); Q_INVOKABLE void factoryResetNetwork(const QUuid &networkUuid); signals: void engineChanged(); - + void availableBackendsChanged(); void addNetworkReply(int commandId, const QString &error, const QUuid &networkUuid); private: void init(); + Q_INVOKABLE void getAvailableBackendsResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void getAdaptersResponse(int commandId, const QVariantMap ¶ms); Q_INVOKABLE void getNetworksResponse(int commandId, const QVariantMap ¶ms); @@ -86,6 +89,7 @@ private: private: Engine* m_engine = nullptr; + QStringList m_availableBackends; ZigbeeAdapters *m_adapters = nullptr; ZigbeeNetworks *m_networks = nullptr; diff --git a/libnymea-app/zigbee/zigbeenetwork.cpp b/libnymea-app/zigbee/zigbeenetwork.cpp index 982a6121..22e0b6c4 100644 --- a/libnymea-app/zigbee/zigbeenetwork.cpp +++ b/libnymea-app/zigbee/zigbeenetwork.cpp @@ -219,18 +219,18 @@ void ZigbeeNetwork::setPermitJoiningRemaining(uint permitJoiningRemaining) } } -ZigbeeAdapter::ZigbeeBackendType ZigbeeNetwork::backendType() const +QString ZigbeeNetwork::backend() const { - return m_backendType; + return m_backend; } -void ZigbeeNetwork::setBackendType(ZigbeeAdapter::ZigbeeBackendType backendType) +void ZigbeeNetwork::setBackend(const QString &backend) { - if (m_backendType == backendType) + if (m_backend == backend) return; - m_backendType = backendType; - emit backendTypeChanged(); + m_backend = backend; + emit backendChanged(); } ZigbeeNetwork::ZigbeeNetworkState ZigbeeNetwork::networkState() const diff --git a/libnymea-app/zigbee/zigbeenetwork.h b/libnymea-app/zigbee/zigbeenetwork.h index d5044bcf..6cfd86dc 100644 --- a/libnymea-app/zigbee/zigbeenetwork.h +++ b/libnymea-app/zigbee/zigbeenetwork.h @@ -52,7 +52,7 @@ class ZigbeeNetwork : public QObject Q_PROPERTY(bool permitJoiningEnabled READ permitJoiningEnabled NOTIFY permitJoiningEnabledChanged) Q_PROPERTY(uint permitJoiningDuration READ permitJoiningDuration NOTIFY permitJoiningDurationChanged) Q_PROPERTY(uint permitJoiningRemaining READ permitJoiningRemaining NOTIFY permitJoiningRemainingChanged) - Q_PROPERTY(ZigbeeAdapter::ZigbeeBackendType backendType READ backendType NOTIFY backendTypeChanged) + Q_PROPERTY(QString backend READ backend NOTIFY backendChanged) Q_PROPERTY(ZigbeeNetworkState networkState READ networkState NOTIFY networkStateChanged) // Internal properties @@ -105,8 +105,8 @@ public: uint permitJoiningRemaining() const; void setPermitJoiningRemaining(uint permitJoiningRemaining); - ZigbeeAdapter::ZigbeeBackendType backendType() const; - void setBackendType(ZigbeeAdapter::ZigbeeBackendType backendType); + QString backend() const; + void setBackend(const QString &backend); ZigbeeNetworkState networkState() const; void setNetworkState(ZigbeeNetworkState networkState); @@ -126,7 +126,7 @@ signals: void permitJoiningEnabledChanged(); void permitJoiningDurationChanged(); void permitJoiningRemainingChanged(); - void backendTypeChanged(); + void backendChanged(); void networkStateChanged(); private: @@ -142,7 +142,7 @@ private: bool m_permitJoiningEnabled; uint m_permitJoiningDuration; uint m_permitJoiningRemaining; - ZigbeeAdapter::ZigbeeBackendType m_backendType; + QString m_backend; ZigbeeNetworkState m_networkState; QTimer *m_permitJoinTimer = nullptr; diff --git a/libnymea-app/zigbee/zigbeenetworks.cpp b/libnymea-app/zigbee/zigbeenetworks.cpp index 66cfb5ed..dd2e08eb 100644 --- a/libnymea-app/zigbee/zigbeenetworks.cpp +++ b/libnymea-app/zigbee/zigbeenetworks.cpp @@ -66,8 +66,8 @@ QVariant ZigbeeNetworks::data(const QModelIndex &index, int role) const return m_networks.at(index.row())->permitJoiningDuration(); case RolePermitJoiningRemaining: return m_networks.at(index.row())->permitJoiningRemaining(); - case RoleBackendType: - return m_networks.at(index.row())->backendType(); + case RoleBackend: + return m_networks.at(index.row())->backend(); case RoleNetworkState: return m_networks.at(index.row())->networkState(); } @@ -89,7 +89,7 @@ QHash ZigbeeNetworks::roleNames() const roles.insert(RolePermitJoiningEnabled, "permitJoiningEnabled"); roles.insert(RolePermitJoiningDuration, "permitJoiningDuration"); roles.insert(RolePermitJoiningRemaining, "permitJoiningRemaining"); - roles.insert(RoleBackendType, "backendType"); + roles.insert(RoleBackend, "backend"); roles.insert(RoleNetworkState, "networkState"); return roles; @@ -155,9 +155,9 @@ void ZigbeeNetworks::addNetwork(ZigbeeNetwork *network) emit dataChanged(idx, idx, {RolePermitJoiningRemaining}); }); - connect(network, &ZigbeeNetwork::backendTypeChanged, this, [this, network]() { + connect(network, &ZigbeeNetwork::backendChanged, this, [this, network]() { QModelIndex idx = index(m_networks.indexOf(network), 0); - emit dataChanged(idx, idx, {RoleBackendType}); + emit dataChanged(idx, idx, {RoleBackend}); }); connect(network, &ZigbeeNetwork::networkStateChanged, this, [this, network]() { diff --git a/libnymea-app/zigbee/zigbeenetworks.h b/libnymea-app/zigbee/zigbeenetworks.h index 1c71a68f..bc6f1ba4 100644 --- a/libnymea-app/zigbee/zigbeenetworks.h +++ b/libnymea-app/zigbee/zigbeenetworks.h @@ -54,7 +54,7 @@ public: RolePermitJoiningEnabled, RolePermitJoiningDuration, RolePermitJoiningRemaining, - RoleBackendType, + RoleBackend, RoleNetworkState }; Q_ENUM(Roles) diff --git a/nymea-app/ui/system/ZigbeeAddNetworkPage.qml b/nymea-app/ui/system/ZigbeeAddNetworkPage.qml index 7ae1b1b7..686ca887 100644 --- a/nymea-app/ui/system/ZigbeeAddNetworkPage.qml +++ b/nymea-app/ui/system/ZigbeeAddNetworkPage.qml @@ -47,8 +47,8 @@ SettingsPageBase { id: d property int pendingCommandId: -1 - function addNetwork(serialPort, baudRate, backendType) { - d.pendingCommandId = root.zigbeeManager.addNetwork(serialPort, baudRate, backendType) + function addNetwork(serialPort, baudRate, backend) { + d.pendingCommandId = root.zigbeeManager.addNetwork(serialPort, baudRate, backend) } } @@ -128,8 +128,8 @@ SettingsPageBase { delegate: NymeaListItemDelegate { Layout.fillWidth: true iconName: "../images/zigbee.svg" - text: model.name + " - " + model.description + " - " + model.serialPort - onClicked: d.addNetwork(model.serialPort, model.baudRate, model.backendType) + text: model.backend + " - " + model.description + " - " + model.serialPort + onClicked: d.addNetwork(model.serialPort, model.baudRate, model.backend) } } @@ -161,7 +161,7 @@ SettingsPageBase { iconName: "../images/stock_usb.svg" text: model.description + " - " + model.serialPort onClicked: { - var dialog = serialPortOptionsDialogComponent.createObject(app, {serialPort: model.serialPort, baudRate: model.baudRate}) + var dialog = serialPortOptionsDialogComponent.createObject(app, {serialPort: model.serialPort, baudRate: model.baudRate, backend: model.backend}) dialog.open() } } @@ -174,6 +174,7 @@ SettingsPageBase { id: serialPortOptionsDialog property string serialPort property int baudRate + property string backend headerIcon: "../images/stock_usb.svg" title: qsTr("Serial port options") @@ -187,12 +188,10 @@ SettingsPageBase { } ComboBox { id: backendComboBox - model: ListModel { - id: backendModel - ListElement { displayName: "deConz"; backendValue: ZigbeeAdapter.ZigbeeBackendTypeDeconz } - ListElement { displayName: "NXP"; backendValue: ZigbeeAdapter.ZigbeeBackendTypeNxp } + model: root.zigbeeManager.availableBackends + Component.onCompleted: { + currentIndex = backendComboBox.find(serialPortOptionsDialog.backend) } - textRole: "displayName" } } @@ -203,15 +202,15 @@ SettingsPageBase { } ComboBox { id: baudRateComboBox - model: [300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600] + model: ["9600", "14400", "19200", "38400", "57600", "115200", "128000", "230400", "256000"] Component.onCompleted: { - currentIndex = indexOfValue(serialPortOptionsDialog.baudRate) + currentIndex = baudRateComboBox.find(serialPortOptionsDialog.baudRate) } } } onAccepted: { - d.addNetwork(serialPortOptionsDialog.serialPort, baudRateComboBox.currentText, backendModel.get(backendComboBox.currentIndex).backendValue) + d.addNetwork(serialPortOptionsDialog.serialPort, baudRateComboBox.currentText, backendComboBox.currentText) } } } diff --git a/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml index 6c10ac62..0b1ecd68 100644 --- a/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkInfoPage.qml @@ -79,7 +79,7 @@ SettingsPageBase { NymeaListItemDelegate { Layout.fillWidth: true text: qsTr("Controller backend") - subText: ZigbeeAdapter.getBackendName(root.network.backendType) + subText: root.network.backend progressive: false prominentSubText: false } diff --git a/nymea-app/ui/system/ZigbeeSettingsPage.qml b/nymea-app/ui/system/ZigbeeSettingsPage.qml index 26661f6a..2875678c 100644 --- a/nymea-app/ui/system/ZigbeeSettingsPage.qml +++ b/nymea-app/ui/system/ZigbeeSettingsPage.qml @@ -88,7 +88,7 @@ SettingsPageBase { Layout.fillWidth: true property var network: zigbeeManager.networks.get(index) iconName: "../images/zigbee.svg" - text: model.macAddress + text: model.backend + " - " + model.macAddress subText: model.serialPort + " - " + model.firmwareVersion onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeNetworkPage.qml"), { zigbeeManager: zigbeeManager, network: network }) } From 4531c76d5fb60967ed7ccdfec88ad94c92152956 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 19 Nov 2020 10:23:09 +0100 Subject: [PATCH 15/18] fix crash --- libnymea-app/zigbee/zigbeemanager.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libnymea-app/zigbee/zigbeemanager.cpp b/libnymea-app/zigbee/zigbeemanager.cpp index 622bc1c0..a07d5ebb 100644 --- a/libnymea-app/zigbee/zigbeemanager.cpp +++ b/libnymea-app/zigbee/zigbeemanager.cpp @@ -49,7 +49,9 @@ ZigbeeManager::ZigbeeManager(QObject *parent) : ZigbeeManager::~ZigbeeManager() { - + if (m_engine) { + m_engine->jsonRpcClient()->unregisterNotificationHandler(this); + } } QString ZigbeeManager::nameSpace() const @@ -60,6 +62,11 @@ QString ZigbeeManager::nameSpace() const void ZigbeeManager::setEngine(Engine *engine) { if (m_engine != engine) { + + if (m_engine) { + m_engine->jsonRpcClient()->unregisterNotificationHandler(this); + } + m_engine = engine; emit engineChanged(); init(); From 45fd91c80e157b607339cd047c5172156b40a731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 19 Nov 2020 13:34:49 +0100 Subject: [PATCH 16/18] Update QtZeroConf to latest revision --- QtZeroConf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QtZeroConf b/QtZeroConf index 39efbe28..cbf4f2bf 160000 --- a/QtZeroConf +++ b/QtZeroConf @@ -1 +1 @@ -Subproject commit 39efbe2879d93bd483ee1f14fc94281a03b49935 +Subproject commit cbf4f2bf7b926b9a874af013efbf0f6dde3155e9 From 1e14cbc71ff50385d8d79a36f2aa1d312bb6d5f6 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sat, 28 Nov 2020 14:02:09 +0100 Subject: [PATCH 17/18] Make it ZigBee again While there is a document that says it is Zigbee, that document is not consistent on its own and ZigBee seems to be more commonly used, even by the ZigBee Alliance themselves. --- nymea-app/ui/SettingsPage.qml | 4 +- nymea-app/ui/system/ZigbeeAddNetworkPage.qml | 10 +-- nymea-app/ui/system/ZigbeeNetworkPage.qml | 4 +- nymea-app/ui/system/ZigbeeSettingsPage.qml | 67 ++------------------ 4 files changed, 14 insertions(+), 71 deletions(-) diff --git a/nymea-app/ui/SettingsPage.qml b/nymea-app/ui/SettingsPage.qml index 7e5c8dbf..36fffc8e 100644 --- a/nymea-app/ui/SettingsPage.qml +++ b/nymea-app/ui/SettingsPage.qml @@ -162,8 +162,8 @@ Page { NymeaListItemDelegate { width: parent.width iconName: "../images/zigbee.svg" - text: qsTr("Zigbee") - subText: qsTr("Configure Zigbee networks") + text: qsTr("ZigBee") + subText: qsTr("Configure ZigBee networks") prominentSubText: false wrapTexts: false onClicked: pageStack.push(Qt.resolvedUrl("system/ZigbeeSettingsPage.qml")) diff --git a/nymea-app/ui/system/ZigbeeAddNetworkPage.qml b/nymea-app/ui/system/ZigbeeAddNetworkPage.qml index 686ca887..0ead853f 100644 --- a/nymea-app/ui/system/ZigbeeAddNetworkPage.qml +++ b/nymea-app/ui/system/ZigbeeAddNetworkPage.qml @@ -97,19 +97,19 @@ SettingsPageBase { Label { Layout.fillWidth: true wrapMode: Text.WordWrap - text: qsTr("No Zigbee adapters or serial ports are available on this system. Connect a Zigbee adapter via USB or UART serial port.") + text: qsTr("No ZigBee adapters or serial ports are available on this system. Connect a ZigBee adapter via USB or UART serial port.") } } SettingsPageSectionHeader { - text: qsTr("Available Zigbee adapters") + text: qsTr("Available ZigBee adapters") visible: recognizedAdapters.count > 0 } Label { Layout.fillWidth: true Layout.leftMargin: app.margins; Layout.rightMargin: app.margins - text: qsTr("Please select the Zigbee adapter on which the new network will be created.") + text: qsTr("Please select the ZigBee adapter on which the new network will be created.") font.pixelSize: app.smallFont wrapMode: Text.WordWrap visible: recognizedAdapters.count > 0 @@ -142,7 +142,7 @@ SettingsPageBase { Layout.fillWidth: true; Layout.leftMargin: app.margins; Layout.rightMargin: app.margins wrapMode: Text.WordWrap font.pixelSize: app.smallFont - text: qsTr("Please verify that the Zigbee adapter is properly connected to a serial port and select the appropriate port.") + text: qsTr("Please verify that the ZigBee adapter is properly connected to a serial port and select the appropriate port.") visible: serialPorts.count > 0 } @@ -178,7 +178,7 @@ SettingsPageBase { headerIcon: "../images/stock_usb.svg" title: qsTr("Serial port options") - text: qsTr("Please select the serial port options for using the Zigbee adapter") + text: qsTr("Please select the serial port options for using the ZigBee adapter") standardButtons: Dialog.Ok | Dialog.Cancel RowLayout { diff --git a/nymea-app/ui/system/ZigbeeNetworkPage.qml b/nymea-app/ui/system/ZigbeeNetworkPage.qml index 10aad8c0..d3ee2247 100644 --- a/nymea-app/ui/system/ZigbeeNetworkPage.qml +++ b/nymea-app/ui/system/ZigbeeNetworkPage.qml @@ -93,7 +93,7 @@ SettingsPageBase { } SettingsPageSectionHeader { - text: qsTr("Adding zigbee devices") + text: qsTr("Network control") } NymeaListItemDelegate { @@ -121,7 +121,7 @@ SettingsPageBase { Layout.leftMargin: app.margins Layout.rightMargin: app.margins enabled: network.networkState === ZigbeeNetwork.ZigbeeNetworkStateOnline - text: root.network.permitJoiningEnabled ? qsTr("Extend network open duration") : qsTr("Open network for new Zigbee devices") + text: root.network.permitJoiningEnabled ? qsTr("Extend network open duration") : qsTr("Open network for new ZigBee devices") onClicked: root.zigbeeManager.setPermitJoin(root.network.networkUuid) } diff --git a/nymea-app/ui/system/ZigbeeSettingsPage.qml b/nymea-app/ui/system/ZigbeeSettingsPage.qml index 2875678c..a100936c 100644 --- a/nymea-app/ui/system/ZigbeeSettingsPage.qml +++ b/nymea-app/ui/system/ZigbeeSettingsPage.qml @@ -38,13 +38,13 @@ import Nymea 1.0 SettingsPageBase { id: root header: NymeaHeader { - text: qsTr("Zigbee") + text: qsTr("ZigBee") backButtonVisible: true onBackPressed: pageStack.pop() HeaderButton { imageSource: "../images/add.svg" - text: qsTr("Add Zigbee network") + text: qsTr("Add ZigBee network") onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeAddNetworkPage.qml"), {zigbeeManager: zigbeeManager}) } } @@ -71,14 +71,14 @@ SettingsPageBase { // } SettingsPageSectionHeader { - text: qsTr("Zigbee networks") + text: qsTr("ZigBee networks") } Label { Layout.fillWidth: true Layout.leftMargin: app.margins; Layout.rightMargin: app.margins wrapMode: Text.WordWrap - text: qsTr("There are no Zigbee networks set up yet. In order to use Zigbee, create a Zigbee network.") + text: qsTr("There are no ZigBee networks set up yet. In order to use ZigBee, create a ZigBee network.") visible: zigbeeManager.networks.count == 0 } @@ -97,65 +97,8 @@ SettingsPageBase { Button { Layout.fillWidth: true Layout.margins: app.margins - text: qsTr("Add a Zigbee network") + text: qsTr("Add a ZigBee network") onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeAddNetworkPage.qml"), {zigbeeManager: zigbeeManager}) } - - -// SettingsPageSectionHeader { -// text: qsTr("Available Zigbee adapters") -// } - -// Repeater { -// id: recognizedAdaptersRepeater -// model: ZigbeeAdaptersProxy { -// id: recognizedAdaptersProxy -// manager: zigbeeManager -// onlyUnused: true -//// hardwareFilter: ZigbeeAdaptersProxy.HardwareFilterRecognized -// } - -// delegate: NymeaListItemDelegate { -// Layout.fillWidth: true -// property ZigbeeAdapter adapter: recognizedAdaptersProxy.get(index) -// iconName: "../images/stock_usb.svg" -// progressive: false -// text: model.description + " - " + model.serialPort -// subText: adapter.serialPort + " - " + adapter.baudRate + " - " + adapter.backendType + " - " + adapter.serialNumber -// onClicked: { -// zigbeeManager.addNetwork(adapter.serialPort, adapter.baudRate, adapter.backendType) -//// pageStack.pop() -// } -// } -// } - - -// // List networks -// SettingsPageSectionHeader { -// text: qsTr("Zigbee networks") -// } - -// Repeater { -// model: zigbeeManager.networks -// delegate: NymeaListItemDelegate { -// Layout.fillWidth: true -// property var network: zigbeeManager.networks.get(index) -// iconName: "../images/zigbee.svg" -// text: model.macAddress -// subText: model.serialPort + " - " + model.firmwareVersion -// onClicked: pageStack.push(Qt.resolvedUrl("ZigbeeNetworkPage.qml"), { network: network }) -// } -// } - -// NymeaListItemDelegate { -// Layout.fillWidth: true -// text: qsTr("Add Zigbee network") -// subText: qsTr("Set up a new Zigbee network") -// prominentSubText: false -// onClicked: { -// pageStack.push(Qt.resolvedUrl("../system/ZigbeeNetworkAddPage.qml"), {zigbeeManager: zigbeeManager}) -// } -// } - } From ce918430eda4d4c8c01b5593d42cb23bef9aed33 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sat, 28 Nov 2020 15:37:42 +0100 Subject: [PATCH 18/18] fix rebase --- nymea-app/resources.qrc | 2 -- 1 file changed, 2 deletions(-) diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc index 8e01e89b..ccd269f7 100644 --- a/nymea-app/resources.qrc +++ b/nymea-app/resources.qrc @@ -225,8 +225,6 @@ ui/components/ThingStatusIcons.qml ui/components/InfoPaneBase.qml ui/components/ThingInfoPane.qml - ui/system/ZigbeeNetworkSettingsPage.qml - ui/system/ZigbeeNetworkAddPage.qml ui/system/ZigbeeSettingsPage.qml ui/system/ZigbeeAddNetworkPage.qml ui/system/ZigbeeNetworkPage.qml