some more work on zigbee

This commit is contained in:
Michael Zanetti 2020-11-11 13:56:51 +01:00
parent e2735428b8
commit 6702a6b649
23 changed files with 595 additions and 256 deletions

@ -1 +1 @@
Subproject commit 39efbe2879d93bd483ee1f14fc94281a03b49935
Subproject commit cbf4f2bf7b926b9a874af013efbf0f6dde3155e9

View File

@ -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();
}
}
}

View File

@ -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();

View File

@ -302,7 +302,7 @@ void registerQmlTypes() {
qmlRegisterUncreatableType<Repository>(uri, 1, 0, "Repository", "Get it from Repositories");
qmlRegisterType<PackagesFilterModel>(uri, 1, 0, "PackagesFilterModel");
qmlRegisterUncreatableType<ZigbeeManager>(uri, 1, 0, "ZigbeeManager", "Get it from Engine");
qmlRegisterType<ZigbeeManager>(uri, 1, 0, "ZigbeeManager");
qmlRegisterUncreatableType<ZigbeeAdapter>(uri, 1, 0, "ZigbeeAdapter", "Get it from the ZigbeeAdapters");
qmlRegisterUncreatableType<ZigbeeAdapters>(uri, 1, 0, "ZigbeeAdapters", "Get it from ZigbeeManager");
qmlRegisterType<ZigbeeAdaptersProxy>(uri, 1, 0, "ZigbeeAdaptersProxy");

View File

@ -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

View File

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

View File

@ -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;

View File

@ -35,14 +35,20 @@
#include <QSortFilterProxyModel>
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

View File

@ -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 <QMetaEnum>
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<ZigbeeAdapter::ZigbeeBackendType>();
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 &params)
@ -123,6 +145,15 @@ void ZigbeeManager::getAdaptersResponse(int commandId, const QVariantMap &params
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 &params)
@ -140,6 +171,7 @@ void ZigbeeManager::getNetworksResponse(int commandId, const QVariantMap &params
void ZigbeeManager::addNetworkResponse(int commandId, const QVariantMap &params)
{
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 &params)

View File

@ -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 &params);
Q_INVOKABLE void getNetworksResponse(int commandId, const QVariantMap &params);
@ -73,13 +85,13 @@ private:
Q_INVOKABLE void setPermitJoinResponse(int commandId, const QVariantMap &params);
Q_INVOKABLE void factoryResetNetworkResponse(int commandId, const QVariantMap &params);
Q_INVOKABLE void notificationReceived(const QVariantMap &notification);
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);

View File

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

View File

@ -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();

View File

@ -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();
}

View File

@ -0,0 +1,26 @@
#ifndef ZIGBEENETWORKSANDADAPTERS_H
#define ZIGBEENETWORKSANDADAPTERS_H
#include <QAbstractListModel>
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

View File

@ -227,6 +227,8 @@
<file>ui/components/ThingInfoPane.qml</file>
<file>ui/system/ZigbeeNetworkSettingsPage.qml</file>
<file>ui/system/ZigbeeNetworkAddPage.qml</file>
<file>ui/system/ZigbeeSettingsPage.qml</file>
<file>ui/system/ZigbeeAddNetworkPage.qml</file>
<file>ui/system/ZigbeeNetworkPage.qml</file>
<file>ui/system/ZigbeeNetworkInfoPage.qml</file>
</qresource>

View File

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

View File

@ -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 {

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.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)
}
}
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.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)
}
}
}

View File

@ -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()
}

View File

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

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.8
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.1
import QtQuick.Layouts 1.3
import "../components"
import Nymea 1.0
SettingsPageBase {
id: root
header: NymeaHeader {
text: qsTr("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"))
}
}
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.8
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.1
import QtQuick.Layouts 1.3
import "../components"
import Nymea 1.0
SettingsPageBase {
id: root
header: NymeaHeader {
text: qsTr("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})
// }
// }
}