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")) + } + } + } +}