Merge PR #459: Add support for zigbee network management

This commit is contained in:
Jenkins nymea 2020-11-28 21:09:17 +01:00
commit babad6f409
25 changed files with 2799 additions and 0 deletions

View File

@ -154,6 +154,7 @@ void Engine::onDeviceManagerFetchingChanged()
m_scriptManager->init();
m_nymeaConfiguration->init();
m_systemController->init();
if (m_jsonRpcClient->ensureServerVersion("1.7")) {
m_tagsManager->init();
}

View File

@ -120,6 +120,12 @@
#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 "zigbee/zigbeenetwork.h"
#include "zigbee/zigbeenetworks.h"
#include <QtQml/qqml.h>
@ -297,6 +303,13 @@ void registerQmlTypes() {
qmlRegisterUncreatableType<Repository>(uri, 1, 0, "Repository", "Get it from Repositories");
qmlRegisterType<PackagesFilterModel>(uri, 1, 0, "PackagesFilterModel");
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");
qmlRegisterUncreatableType<ZigbeeNetwork>(uri, 1, 0, "ZigbeeNetwork", "Get it from the ZigbeeManager");
qmlRegisterUncreatableType<ZigbeeNetworks>(uri, 1, 0, "ZigbeeNetworks", "Get it from the ZigbeeManager");
qmlRegisterType<NetworkManager>(uri, 1, 0, "NetworkManager");
qmlRegisterUncreatableType<NetworkDevices>(uri, 1, 0, "NetworkDevices", "Get it from NetworkManager");
qmlRegisterUncreatableType<WiredNetworkDevices>(uri, 1, 0, "WiredNetworkDevices", "Get it from NetworkManager");

View File

@ -160,6 +160,13 @@ SOURCES += \
models/devicemodel.cpp \
system/systemcontroller.cpp \
thinggroup.cpp \
zigbee/zigbeeadapters.cpp \
zigbee/zigbeeadaptersproxy.cpp \
zigbee/zigbeemanager.cpp \
zigbee/zigbeeadapter.cpp \
zigbee/zigbeenetwork.cpp \
zigbee/zigbeenetworks.cpp
HEADERS += \
@ -299,6 +306,12 @@ HEADERS += \
models/devicemodel.h \
system/systemcontroller.h \
thinggroup.h \
zigbee/zigbeeadapters.h \
zigbee/zigbeeadaptersproxy.h \
zigbee/zigbeemanager.h \
zigbee/zigbeeadapter.h \
zigbee/zigbeenetwork.h \
zigbee/zigbeenetworks.h
ubports: {
DEFINES += UBPORTS

View File

@ -0,0 +1,136 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#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::serialPort() const
{
return m_serialPort;
}
void ZigbeeAdapter::setSerialPort(const QString &serialPort)
{
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
{
return m_hardwareRecognized;
}
void ZigbeeAdapter::setHardwareRecognized(bool hardwareRecognized)
{
m_hardwareRecognized = hardwareRecognized;
emit hardwareRecognizedChanged();
}
QString ZigbeeAdapter::backend() const
{
return m_backend;
}
void ZigbeeAdapter::setBackend(const QString &backend)
{
m_backend = backend;
emit backendChanged();
}
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_serialPort == other.serialPort()
&& m_name == other.name()
&& m_description == other.description()
&& m_hardwareRecognized == other.hardwareRecognized()
&& m_backend == other.backend()
&& m_baudRate == other.baudRate();
}
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.backend();
debug.nospace() << ", " << adapter.baudRate();
}
debug.nospace() << ")";
return debug.space();
}

View File

@ -0,0 +1,95 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEEADAPTER_H
#define ZIGBEEADAPTER_H
#include <QDebug>
#include <QObject>
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 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(QString backend READ backend WRITE setBackend NOTIFY backendChanged)
Q_PROPERTY(qint32 baudRate READ baudRate WRITE setBaudRate NOTIFY baudRateChanged)
public:
explicit ZigbeeAdapter(QObject *parent = nullptr);
QString name() const;
void setName(const QString &name);
QString description() const;
void setDescription(const QString &description);
QString serialPort() const;
void setSerialPort(const QString &serialPort);
QString serialNumber() const;
void setSerialNumber(const QString &serialNumber);
bool hardwareRecognized() const;
void setHardwareRecognized(bool hardwareRecognized);
QString backend() const;
void setBackend(const QString &backend);
qint32 baudRate() const;
void setBaudRate(qint32 baudRate);
bool operator==(const ZigbeeAdapter &other) const;
private:
QString m_name;
QString m_description;
QString m_serialPort;
QString m_serialNumber;
bool m_hardwareRecognized = false;
QString m_backend;
qint32 m_baudRate = 38400;
signals:
void nameChanged();
void descriptionChanged();
void serialPortChanged();
void serialNumberChanged();
void hardwareRecognizedChanged();
void backendChanged();
void baudRateChanged();
};
QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter);
#endif // ZIGBEEADAPTER_H

View File

@ -0,0 +1,145 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#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 RoleSerialPort:
return m_adapters.at(index.row())->serialPort();
case RoleHardwareRecognized:
return m_adapters.at(index.row())->hardwareRecognized();
case RoleBackend:
return m_adapters.at(index.row())->backend();
case RoleBaudRate:
return m_adapters.at(index.row())->baudRate();
}
return QVariant();
}
QHash<int, QByteArray> ZigbeeAdapters::roleNames() const
{
QHash<int, QByteArray> roles;
roles.insert(RoleName, "name");
roles.insert(RoleDescription, "description");
roles.insert(RoleSerialPort, "serialPort");
roles.insert(RoleHardwareRecognized, "hardwareRecognized");
roles.insert(RoleBackend, "backend");
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::serialPortChanged, this, [this, adapter]() {
QModelIndex idx = index(m_adapters.indexOf(adapter), 0);
emit dataChanged(idx, idx, {RoleSerialPort});
});
connect(adapter, &ZigbeeAdapter::hardwareRecognizedChanged, this, [this, adapter]() {
QModelIndex idx = index(m_adapters.indexOf(adapter), 0);
emit dataChanged(idx, idx, {RoleHardwareRecognized});
});
connect(adapter, &ZigbeeAdapter::backendChanged, this, [this, adapter]() {
QModelIndex idx = index(m_adapters.indexOf(adapter), 0);
emit dataChanged(idx, idx, {RoleBackend});
});
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 &serialPort)
{
for (int i = 0; i < m_adapters.count(); i++) {
if (m_adapters.at(i)->serialPort() == serialPort) {
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()) {
return nullptr;
}
return m_adapters.at(index);
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEEADAPTERS_H
#define ZIGBEEADAPTERS_H
#include <QObject>
#include <QAbstractListModel>
#include "zigbeeadapter.h"
class ZigbeeAdapters : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
public:
enum Roles {
RoleName,
RoleDescription,
RoleSerialPort,
RoleHardwareRecognized,
RoleBackend,
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<int, QByteArray> roleNames() const override;
void addAdapter(ZigbeeAdapter *adapter);
void removeAdapter(const QString &serialPort);
void clear();
Q_INVOKABLE virtual ZigbeeAdapter *get(int index) const;
signals:
void countChanged();
protected:
QList<ZigbeeAdapter *> m_adapters;
};
#endif // ZIGBEEADAPTERS_H

View File

@ -0,0 +1,126 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "zigbeeadaptersproxy.h"
#include "zigbeemanager.h"
#include "zigbeeadapters.h"
#include "zigbeenetworks.h"
ZigbeeAdaptersProxy::ZigbeeAdaptersProxy(QObject *parent) : QSortFilterProxyModel(parent)
{
}
ZigbeeManager *ZigbeeAdaptersProxy::manager() const
{
return m_manager;
}
void ZigbeeAdaptersProxy::setManager(ZigbeeManager *manager)
{
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();
}
}
ZigbeeAdaptersProxy::HardwareFilter ZigbeeAdaptersProxy::hardwareFilter() const
{
return m_hardwareFilter;
}
void ZigbeeAdaptersProxy::setHardwareFilter(ZigbeeAdaptersProxy::HardwareFilter hardwareFilter)
{
if (m_hardwareFilter != hardwareFilter) {
m_hardwareFilter = hardwareFilter;
emit hardwareFilterChanged(m_hardwareFilter);
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
{
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_manager->adapters()->get(source_row);
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

@ -0,0 +1,88 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEEADAPTERSPROXY_H
#define ZIGBEEADAPTERSPROXY_H
#include <QObject>
#include <QSortFilterProxyModel>
class ZigbeeAdapter;
class ZigbeeManager;
class ZigbeeAdaptersProxy : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
// 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,
HardwareFilterRecognized,
HardwareFilterUnrecognized
};
Q_ENUM(HardwareFilter)
explicit ZigbeeAdaptersProxy(QObject *parent = nullptr);
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:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
signals:
void countChanged();
void managerChanged();
void hardwareFilterChanged(HardwareFilter hardwareFilter);
void onlyUnusedChanged();
private:
ZigbeeManager *m_manager = nullptr;
HardwareFilter m_hardwareFilter = HardwareFilterNone;
bool m_onlyUnused = false;
};
#endif // ZIGBEEADAPTERSPROXY_H

View File

@ -0,0 +1,285 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#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 <QMetaEnum>
ZigbeeManager::ZigbeeManager(QObject *parent) :
JsonHandler(parent),
m_adapters(new ZigbeeAdapters(this)),
m_networks(new ZigbeeNetworks(this))
{
}
ZigbeeManager::~ZigbeeManager()
{
if (m_engine) {
m_engine->jsonRpcClient()->unregisterNotificationHandler(this);
}
}
QString ZigbeeManager::nameSpace() const
{
return "Zigbee";
}
void ZigbeeManager::setEngine(Engine *engine)
{
if (m_engine != engine) {
if (m_engine) {
m_engine->jsonRpcClient()->unregisterNotificationHandler(this);
}
m_engine = engine;
emit engineChanged();
init();
}
}
Engine *ZigbeeManager::engine() const
{
return m_engine;
}
QStringList ZigbeeManager::availableBackends() const
{
return m_availableBackends;
}
ZigbeeAdapters *ZigbeeManager::adapters() const
{
return m_adapters;
}
ZigbeeNetworks *ZigbeeManager::networks() const
{
return m_networks;
}
int ZigbeeManager::addNetwork(const QString &serialPort, uint baudRate, const QString &backend)
{
QVariantMap params;
params.insert("serialPort", serialPort);
params.insert("baudRate", baudRate);
params.insert("backend", backend);
qDebug() << "Add zigbee network" << params;
return m_engine->jsonRpcClient()->sendCommand("Zigbee.AddNetwork", params, this, "addNetworkResponse");
}
void ZigbeeManager::removeNetwork(const QUuid &networkUuid)
{
QVariantMap params;
params.insert("networkUuid", networkUuid);
qDebug() << "Remove zigbee network" << params;
m_engine->jsonRpcClient()->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_engine->jsonRpcClient()->sendCommand("Zigbee.SetPermitJoin", params, this, "setPermitJoinResponse");
}
void ZigbeeManager::factoryResetNetwork(const QUuid &networkUuid)
{
QVariantMap params;
params.insert("networkUuid", networkUuid);
m_engine->jsonRpcClient()->sendCommand("Zigbee.FactoryResetNetwork", params, this, "factoryResetNetworkResponse");
}
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 &params)
{
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 &params)
{
qDebug() << "Zigbee get adapters response" << commandId << params;
m_adapters->clear();
foreach (const QVariant &adapterVariant, params.value("adapters").toList()) {
QVariantMap adapterMap = adapterVariant.toMap();
ZigbeeAdapter *adapter = unpackAdapter(adapterMap);
qDebug() << "Zigbee adapter added" << adapter->description() << adapter->serialPort() << adapter->hardwareRecognized();
m_adapters->addAdapter(adapter);
}
// ZigbeeAdapter *fakeAdapter = new ZigbeeAdapter();
// fakeAdapter->setSerialPort("/dev/fake");
// fakeAdapter->setBackend("Fake");
// 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)
{
qDebug() << "Zigbee get networks response" << commandId << params;
m_networks->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::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)
{
qDebug() << "Zigbee remove network response" << commandId << params;
}
void ZigbeeManager::setPermitJoinResponse(int commandId, const QVariantMap &params)
{
qDebug() << "Zigbee set permit join network response" << commandId << params;
}
void ZigbeeManager::factoryResetNetworkResponse(int commandId, const QVariantMap &params)
{
qDebug() << "Zigbee factory reset network response" << commandId << params;
}
void ZigbeeManager::notificationReceived(const QVariantMap &notification)
{
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("serialPort").toString());
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("networkUuid").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;
}
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->setSerialPort(adapterMap.value("serialPort").toString());
adapter->setSerialNumber(adapterMap.value("serialNumber").toString());
adapter->setHardwareRecognized(adapterMap.value("hardwareRecognized").toBool());
adapter->setBackend(adapterMap.value("backend").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->setBackend(networkMap.value("backend").toString());
network->setNetworkState(ZigbeeNetwork::stringToZigbeeNetworkState(networkMap.value("networkState").toString()));
}

View File

@ -0,0 +1,102 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEEMANAGER_H
#define ZIGBEEMANAGER_H
#include <QObject>
#include "zigbeeadapter.h"
#include "jsonrpc/jsonhandler.h"
class JsonRpcClient;
class ZigbeeAdapters;
class ZigbeeNetwork;
class ZigbeeNetworks;
class Engine;
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)
public:
explicit ZigbeeManager(QObject *parent = nullptr);
~ZigbeeManager();
QString nameSpace() const override;
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, 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 &params);
Q_INVOKABLE void getAdaptersResponse(int commandId, const QVariantMap &params);
Q_INVOKABLE void getNetworksResponse(int commandId, const QVariantMap &params);
Q_INVOKABLE void addNetworkResponse(int commandId, const QVariantMap &params);
Q_INVOKABLE void removeNetworkResponse(int commandId, const QVariantMap &params);
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:
Engine* m_engine = nullptr;
QStringList m_availableBackends;
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);
};
#endif // ZIGBEEMANAGER_H

View File

@ -0,0 +1,267 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "zigbeenetwork.h"
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
{
return m_networkUuid;
}
void ZigbeeNetwork::setNetworkUuid(const QUuid &networkUuid)
{
if (m_networkUuid == networkUuid)
return;
m_networkUuid = 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;
}
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();
if (m_permitJoinTimer->isActive())
m_permitJoinTimer->stop();
if (m_permitJoiningRemaining != 0) {
m_permitJoinTimer->start();
}
}
QString ZigbeeNetwork::backend() const
{
return m_backend;
}
void ZigbeeNetwork::setBackend(const QString &backend)
{
if (m_backend == backend)
return;
m_backend = backend;
emit backendChanged();
}
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;
}
}

View File

@ -0,0 +1,151 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEENETWORK_H
#define ZIGBEENETWORK_H
#include <QUuid>
#include <QObject>
#include <QTimer>
#include "zigbeeadapter.h"
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)
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(QString backend READ backend NOTIFY backendChanged)
Q_PROPERTY(ZigbeeNetworkState networkState READ networkState NOTIFY networkStateChanged)
// Internal properties
public:
enum ZigbeeNetworkState {
ZigbeeNetworkStateOffline,
ZigbeeNetworkStateStarting,
ZigbeeNetworkStateUpdating,
ZigbeeNetworkStateOnline,
ZigbeeNetworkStateError
};
Q_ENUM(ZigbeeNetworkState)
explicit ZigbeeNetwork(QObject *parent = nullptr);
QUuid networkUuid() const;
void setNetworkUuid(const QUuid &networkUuid);
bool enabled() const;
void setEnabled(bool enabled);
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);
QString backend() const;
void setBackend(const QString &backend);
ZigbeeNetworkState networkState() const;
void setNetworkState(ZigbeeNetworkState networkState);
static ZigbeeNetworkState stringToZigbeeNetworkState(const QString &networkStateString);
signals:
void networkUuidChanged();
void enabledChanged();
void serialPortChanged();
void baudRateChanged();
void macAddressChanged();
void firmwareVersionChanged();
void panIdChanged();
void channelChanged();
void channelMaskChanged();
void permitJoiningEnabledChanged();
void permitJoiningDurationChanged();
void permitJoiningRemainingChanged();
void backendChanged();
void networkStateChanged();
private:
QUuid m_networkUuid;
bool m_enabled;
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;
QString m_backend;
ZigbeeNetworkState m_networkState;
QTimer *m_permitJoinTimer = nullptr;
};
#endif // ZIGBEENETWORK_H

View File

@ -0,0 +1,222 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#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 RoleBackend:
return m_networks.at(index.row())->backend();
case RoleNetworkState:
return m_networks.at(index.row())->networkState();
}
return QVariant();
}
QHash<int, QByteArray> ZigbeeNetworks::roleNames() const
{
QHash<int, QByteArray> 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(RoleBackend, "backend");
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::backendChanged, this, [this, network]() {
QModelIndex idx = index(m_networks.indexOf(network), 0);
emit dataChanged(idx, idx, {RoleBackend});
});
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();
emit countChanged();
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()) {
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;
}
ZigbeeNetwork *ZigbeeNetworks::findBySerialPort(const QString &serialPort) const
{
foreach (ZigbeeNetwork* network, m_networks) {
if (network->serialPort() == serialPort) {
return network;
}
}
return nullptr;
}

View File

@ -0,0 +1,86 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef ZIGBEENETWORKS_H
#define ZIGBEENETWORKS_H
#include <QObject>
#include <QAbstractListModel>
#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,
RoleBackend,
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<int, QByteArray> 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;
ZigbeeNetwork *findBySerialPort(const QString &serialPort) const;
signals:
void countChanged();
protected:
QList<ZigbeeNetwork *> m_networks;
};
#endif // ZIGBEENETWORKS_H

View File

@ -241,5 +241,7 @@
<file>ui/images/state-in.svg</file>
<file>ui/images/state-out.svg</file>
<file>ui/images/like.svg</file>
<file>ui/images/zigbee.svg</file>
<file>ui/images/stock_usb.svg</file>
</qresource>
</RCC>

View File

@ -225,5 +225,9 @@
<file>ui/components/ThingStatusIcons.qml</file>
<file>ui/components/InfoPaneBase.qml</file>
<file>ui/components/ThingInfoPane.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>
</RCC>

View File

@ -153,6 +153,23 @@ Page {
}
}
Pane {
Layout.fillWidth: true
Material.elevation: layout.isGrid ? 1 : 0
visible: engine.jsonRpcClient.ensureServerVersion("5.3")
padding: 0
NymeaListItemDelegate {
width: parent.width
iconName: "../images/zigbee.svg"
text: qsTr("ZigBee")
subText: qsTr("Configure ZigBee networks")
prominentSubText: false
wrapTexts: false
onClicked: pageStack.push(Qt.resolvedUrl("system/ZigbeeSettingsPage.qml"))
}
}
Pane {
Layout.fillWidth: true
Material.elevation: layout.isGrid ? 1 : 0

View File

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="96"
height="96"
id="svg4874"
version="1.1"
inkscape:version="0.91+devel r"
viewBox="0 0 96 96.000001"
sodipodi:docname="stock_usb.svg">
<defs
id="defs4876" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.0249991"
inkscape:cx="35.629893"
inkscape:cy="53.907462"
inkscape:document-units="px"
inkscape:current-layer="g4780"
showgrid="true"
showborder="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="true"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-midpoints="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-center="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid5451"
empspacing="8" />
<sodipodi:guide
orientation="1,0"
position="8,-8.0000001"
id="guide4063" />
<sodipodi:guide
orientation="1,0"
position="4,-8.0000001"
id="guide4065" />
<sodipodi:guide
orientation="0,1"
position="-8,88.000001"
id="guide4067" />
<sodipodi:guide
orientation="0,1"
position="-8,92.000001"
id="guide4069" />
<sodipodi:guide
orientation="0,1"
position="104,4"
id="guide4071" />
<sodipodi:guide
orientation="0,1"
position="-5,8.0000001"
id="guide4073" />
<sodipodi:guide
orientation="1,0"
position="88,-8.0000001"
id="guide4077" />
<sodipodi:guide
orientation="0,1"
position="-8,84.000001"
id="guide4074" />
<sodipodi:guide
orientation="1,0"
position="12,-8.0000001"
id="guide4076" />
<sodipodi:guide
orientation="1,0"
position="84,-8.0000001"
id="guide4080" />
<sodipodi:guide
position="48,-8.0000001"
orientation="1,0"
id="guide4170" />
<sodipodi:guide
position="-8,48"
orientation="0,1"
id="guide4172" />
<sodipodi:guide
position="92,-8.0000001"
orientation="1,0"
id="guide4760" />
</sodipodi:namedview>
<metadata
id="metadata4879">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(67.857146,-78.50504)">
<g
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
id="g4845"
style="display:inline">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="next01.png"
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
id="g4778"
inkscape:label="Layer 1">
<g
transform="matrix(-1,0,0,1,575.99999,611)"
id="g4780"
style="display:inline">
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
id="rect4782"
width="96.037987"
height="96"
x="-438.00244"
y="345.36221"
transform="scale(-1,1)" />
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.00059342;marker:none;enable-background:accumulate"
d="m 421.99612,401.93458 0,-17.14379 c 0,0 9.50358,4.04713 16.00635,8.57143 -6.50277,4.5243 -16.00635,8.57236 -16.00635,8.57236 z"
id="path4198"
inkscape:connector-curvature="0"
inkscape:transform-center-x="0.00046899999"
inkscape:transform-center-y="8.0000098" />
<rect
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
id="rect4192"
width="10.000016"
height="10.003973"
x="-383.36221"
y="-411.99216"
transform="matrix(0,-1,-1,0,0,0)" />
<ellipse
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
id="path4194"
cx="-408.36221"
cy="-393.98505"
transform="matrix(0,-1,-1,0,0,0)"
rx="5.9999971"
ry="6.0023713" />
<ellipse
ry="7.0027828"
rx="7.0000129"
transform="matrix(0,-1,-1,0,0,0)"
cy="-348.96722"
cx="-393.36221"
id="ellipse4196"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#808080;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 422.99651,393.36222 -70.02769,0"
id="path4199"
inkscape:connector-curvature="0" />
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#808080;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 363.97317,393.36222 c 11.00436,0 12.00475,15 22.0087,15 l 4.00159,0"
id="path4201"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path4203"
d="m 376.97833,393.36222 c 11.00436,0 12.00475,-15 22.0087,-15 l 4.00159,0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#808080;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="96"
height="96"
id="svg4874"
version="1.1"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
viewBox="0 0 96 96.000001"
sodipodi:docname="zigbee_.svg">
<defs
id="defs4876" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8.7812489"
inkscape:cx="10.528112"
inkscape:cy="41.064759"
inkscape:document-units="px"
inkscape:current-layer="g4780"
showgrid="true"
showborder="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="true"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-midpoints="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-center="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="2880"
inkscape:window-height="1663"
inkscape:window-x="0"
inkscape:window-y="76"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid5451"
empspacing="8" />
<sodipodi:guide
orientation="1,0"
position="8,-8.0000001"
id="guide4063"
inkscape:locked="false" />
<sodipodi:guide
orientation="1,0"
position="4,-8.0000001"
id="guide4065"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="-8,88.000001"
id="guide4067"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="-8,92.000001"
id="guide4069"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="104,4"
id="guide4071"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="-5,8.0000001"
id="guide4073"
inkscape:locked="false" />
<sodipodi:guide
orientation="1,0"
position="92,-8.0000001"
id="guide4075"
inkscape:locked="false" />
<sodipodi:guide
orientation="1,0"
position="88,-8.0000001"
id="guide4077"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="-8,84.000001"
id="guide4074"
inkscape:locked="false" />
<sodipodi:guide
orientation="1,0"
position="12,-8.0000001"
id="guide4076"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="-5,12"
id="guide4078"
inkscape:locked="false" />
<sodipodi:guide
orientation="1,0"
position="84,-9.0000001"
id="guide4080"
inkscape:locked="false" />
<sodipodi:guide
position="48,-8.0000001"
orientation="1,0"
id="guide4170"
inkscape:locked="false" />
<sodipodi:guide
position="-8,48"
orientation="0,1"
id="guide4172"
inkscape:locked="false" />
</sodipodi:namedview>
<metadata
id="metadata4879">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(67.857146,-78.50504)">
<g
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
id="g4845"
style="display:inline">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="next01.png"
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
id="g4778"
inkscape:label="Layer 1">
<g
transform="matrix(-1,0,0,1,575.99999,611)"
id="g4780"
style="display:inline">
<path
inkscape:connector-curvature="0"
d="m 418.41067,377.27822 c -2.47698,-9.19 -6.3325,-9.76 -10.1,-11.048 -5.65022,5.45 -41.7365,40.432 -41.7365,40.432 0,0 -2.35494,-21.802 2.0068,-46.974 -0.058,0.002 -0.096,0.004 -0.152,0.006 6.22646,-3.99 13.61138,-6.332 21.55452,-6.332 22.10074,0 40.01582,17.908 40.01582,40 0,11.268 -4.67784,21.43 -12.17882,28.7 1.92676,-11.678 3.36934,-34.48 0.59024,-44.784 z"
id="path2"
style="fill:#808080;fill-opacity:1;stroke-width:2.00039554" />
<path
inkscape:connector-curvature="0"
d="m 363.40291,411.91422 c 0.69428,3.964 4.2637,8.424 10.6082,9.414 2.47898,-2.874 41.03022,-39.988 41.03022,-39.988 0.84834,14.016 0.93038,29.138 -1.72868,44.474 -6.5726,4.732 -14.61378,7.548 -23.32922,7.548 -22.10074,0 -40.01582,-17.908 -40.01582,-40 0,-12.346 5.6022,-23.378 14.39568,-30.716 -1.05042,7.744 -3.92954,32.202 -0.96038,49.268 z"
id="path4"
style="fill:#808080;fill-opacity:1;stroke-width:2.00039554" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

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,217 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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, backend) {
d.pendingCommandId = root.zigbeeManager.addNetwork(serialPort, baudRate, backend)
}
}
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.backend + " - " + model.description + " - " + model.serialPort
onClicked: d.addNetwork(model.serialPort, model.baudRate, model.backend)
}
}
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, backend: model.backend})
dialog.open()
}
}
}
Component {
id: serialPortOptionsDialogComponent
MeaDialog {
id: serialPortOptionsDialog
property string serialPort
property int baudRate
property string backend
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: root.zigbeeManager.availableBackends
Component.onCompleted: {
currentIndex = backendComboBox.find(serialPortOptionsDialog.backend)
}
}
}
RowLayout {
Label {
text: qsTr("Baud rate")
Layout.fillWidth: true
}
ComboBox {
id: baudRateComboBox
model: ["9600", "14400", "19200", "38400", "57600", "115200", "128000", "230400", "256000"]
Component.onCompleted: {
currentIndex = baudRateComboBox.find(serialPortOptionsDialog.baudRate)
}
}
}
onAccepted: {
d.addNetwork(serialPortOptionsDialog.serialPort, baudRateComboBox.currentText, backendComboBox.currentText)
}
}
}
}

View File

@ -0,0 +1,126 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, GNU version 3. This project is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.8
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.1
import QtQuick.Layouts 1.3
import "../components"
import Nymea 1.0
SettingsPageBase {
id: root
property ZigbeeManager zigbeeManager: null
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: root.network.backend
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 {
Button {
Layout.fillWidth: true
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
text: qsTr("Remove network")
onClicked: {
root.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: {
root.zigbeeManager.factoryResetNetwork(root.network.networkUuid)
pageStack.pop()
}
}
}
}

View File

@ -0,0 +1,138 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, GNU version 3. This project is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this project. If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
import QtQuick 2.8
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.1
import QtQuick.Layouts 1.3
import "../components"
import Nymea 1.0
SettingsPageBase {
id: root
property ZigbeeManager zigbeeManager: null
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, zigbeeManager: root.zigbeeManager })
}
}
SettingsPageSectionHeader {
text: qsTr("Network information")
}
NymeaListItemDelegate {
Layout.fillWidth: true
text: qsTr("Network state")
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
}
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("Network control")
}
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 {
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: root.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: root.zigbeeManager.setPermitJoin(root.network.networkUuid, 0)
}
}
}

View File

@ -0,0 +1,104 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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
}
// 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
// }
// }
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.backend + " - " + 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})
}
}