diff --git a/docs/deCONZ-BHB-en.pdf b/docs/deCONZ-BHB-en.pdf
new file mode 100644
index 0000000..64b43b9
Binary files /dev/null and b/docs/deCONZ-BHB-en.pdf differ
diff --git a/libnymea-zigbee/deconz/interface/deconz.h b/libnymea-zigbee/deconz/interface/deconz.h
new file mode 100644
index 0000000..6f799ac
--- /dev/null
+++ b/libnymea-zigbee/deconz/interface/deconz.h
@@ -0,0 +1,112 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea-zigbee.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* 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 DECONZ_H
+#define DECONZ_H
+
+#include
+
+class Deconz
+{
+ Q_GADGET
+
+public:
+ enum StatusCode {
+ StatusCodeSuccess = 0x00,
+ StatusCodeFailure = 0x01,
+ StatusCodeBusy = 0x02,
+ StatusCodeTimeout = 0x03,
+ StatusCodeUnsupported = 0x04,
+ StatusCodeError = 0x05,
+ StatusCodeNoNetwork = 0x06,
+ StatusCodeInvalidValue = 0x07
+ };
+ Q_ENUM(StatusCode)
+
+ enum NetworkState {
+ NetworkStateOffline = 0x00,
+ NetworkStateJoining = 0x01,
+ NetworkStateConnected = 0x02,
+ NetworkStateLeaving = 0x03
+ };
+ Q_ENUM(NetworkState)
+
+ enum Command {
+ CommandDeviceState = 0x07,
+ CommandChangeNetworkState = 0x08,
+ CommandReadParameter = 0x0A,
+ CommandWriteParameter = 0x0B,
+ CommandDeviceStateChanged = 0x0E,
+ CommandVersion = 0x0D,
+ CommandApsDataRequest = 0x12,
+ CommandApsDataConfirm = 0x04,
+ CommandApsDataIndication = 0x17
+ };
+ Q_ENUM(Command)
+
+ enum Parameter {
+ ParameterMacAddress = 0x01, // R
+ ParameterPanId = 0x05, // R
+ ParameterNetworkAddress = 0x07, // R
+ ParameterNetworkExtendedPanId = 0x08, // R
+ ParameterNodeType = 0x09, //RW
+ ParameterChannelMask = 0x0A, // RW
+ ParameterApsExtendedPanId = 0x0B, //RW
+ ParameterTrustCenterAddress = 0x0E, // RW
+ ParameterSecurityMode = 0x10, // RW
+ ParameterNetworkKey = 0x18, //W
+ ParameterCurrentChannel = 0x1c, // R
+ ParameterPermitJoin = 0x21, // RW
+ ParameterProtocolVersion = 0x22, // R
+ ParameterNetworkUpdateId = 0x24, // RW
+ ParameterWatchdogTtl = 0x26 // RW since protocol version 0x0108
+ };
+ Q_ENUM(Parameter)
+
+ enum NodeType {
+ NodeTypeRouter = 0x00,
+ NodeTypeCoordinator = 0x01
+ };
+ Q_ENUM(NodeType)
+
+ enum SecurityMode {
+ SecurityModeNoSecurity = 0x00,
+ SecurityModePreconfiguredNetworkKey = 0x01,
+ SecurityModeNetworkKeyFromTrustCenter = 0x02,
+ SecurityModeNoMasterButTrustCenterKey = 0x03
+ };
+ Q_ENUM(SecurityMode)
+
+ enum Platform {
+ PlatformConbeeRaspbee = 0x05,
+ PlatformConbeeII = 0x07
+ };
+ Q_ENUM(Platform)
+
+};
+
+#endif // DECONZ_H
diff --git a/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconz.cpp b/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconz.cpp
new file mode 100644
index 0000000..bb25933
--- /dev/null
+++ b/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconz.cpp
@@ -0,0 +1,272 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea-zigbee.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* 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 "zigbeeinterfacedeconz.h"
+#include "zigbee.h"
+#include "zigbeeutils.h"
+#include "loggingcategory.h"
+
+#include
+
+// SLIP: https://tools.ietf.org/html/rfc1055
+
+ZigbeeInterfaceDeconz::ZigbeeInterfaceDeconz(QObject *parent) : QObject(parent)
+{
+ m_reconnectTimer = new QTimer(this);
+ m_reconnectTimer->setSingleShot(true);
+ m_reconnectTimer->setInterval(2000);
+
+ connect(m_reconnectTimer, &QTimer::timeout, this, &ZigbeeInterfaceDeconz::onReconnectTimeout);
+}
+
+ZigbeeInterfaceDeconz::~ZigbeeInterfaceDeconz()
+{
+
+}
+
+quint16 ZigbeeInterfaceDeconz::calculateCrc(const QByteArray &data)
+{
+ quint16 crc = 0;
+ for (int i = 0; i < data.length(); i++) {
+ crc += static_cast(data.at(i));
+ }
+ quint8 crc0 = (~crc + 1) & 0xFF;
+ quint8 crc1 = ((~crc + 1) >> 8) & 0xFF;
+ return (static_cast(crc1 << 8) | static_cast(crc0));
+}
+
+QByteArray ZigbeeInterfaceDeconz::unescapeData(const QByteArray &data)
+{
+ QByteArray deserializedData;
+ // Parse serial data and built InterfaceMessage
+ bool escaped = false;
+ for (int i = 0; i < data.length(); i++) {
+ quint8 byte = static_cast(data.at(i));
+
+ if (escaped) {
+ if (byte == ProtocolByteTransposedEnd) {
+ deserializedData.append(static_cast(ProtocolByteEnd));
+ } else if (byte == ProtocolByteTransposedEsc) {
+ deserializedData.append(static_cast(ProtocolByteEsc));
+ } else {
+ qCWarning(dcZigbeeInterfaceTraffic()) << "Error while deserialing data. Escape character received but the escaped character was not recognized.";
+ return QByteArray();
+ }
+
+ escaped = false;
+ continue;
+ }
+
+ // If escape byte, the next byte has to be a modified byte
+ if (byte == ProtocolByteEsc) {
+ escaped = true;
+ } else {
+ deserializedData.append(static_cast(byte));
+ }
+ }
+
+ return deserializedData;
+}
+
+QByteArray ZigbeeInterfaceDeconz::escapeData(const QByteArray &data)
+{
+ QByteArray serializedData;
+ QDataStream stream(&serializedData, QIODevice::WriteOnly);
+
+ for (int i = 0; i < data.length(); i++) {
+ quint8 byte = static_cast(data.at(i));
+ switch (byte) {
+ case ProtocolByteEnd:
+ stream << static_cast(ProtocolByteEsc);
+ stream << static_cast(ProtocolByteTransposedEnd);
+ break;
+ case ProtocolByteEsc:
+ stream << static_cast(ProtocolByteEsc);
+ stream << static_cast(ProtocolByteTransposedEsc);
+ break;
+ default:
+ stream << byte;
+ break;
+ }
+ }
+
+ return serializedData;
+}
+
+void ZigbeeInterfaceDeconz::setAvailable(bool available)
+{
+ if (m_available == available)
+ return;
+
+ m_available = available;
+ emit availableChanged(m_available);
+
+ // Clear the data buffer in any case
+ m_dataBuffer.clear();
+}
+
+void ZigbeeInterfaceDeconz::onReconnectTimeout()
+{
+ if (m_serialPort && !m_serialPort->isOpen()) {
+ if (!m_serialPort->open(QSerialPort::ReadWrite)) {
+ setAvailable(false);
+ m_reconnectTimer->start();
+ } else {
+ qCDebug(dcZigbeeInterface()) << "Interface reconnected successfully on" << m_serialPort->portName() << m_serialPort->baudRate();
+ m_serialPort->clear();
+ setAvailable(true);
+ }
+ }
+}
+
+void ZigbeeInterfaceDeconz::onReadyRead()
+{
+ QByteArray data = m_serialPort->readAll();
+ // Read each byte until we get END byte, then unescape the package
+ for (int i = 0; i < data.length(); i++) {
+ quint8 byte = static_cast(data.at(i));
+ if (byte == ProtocolByteEnd) {
+ // If there is no data...continue since it might be a starting END byte
+ if (m_dataBuffer.isEmpty())
+ continue;
+
+ qCDebug(dcZigbeeInterfaceTraffic()) << "<--" << ZigbeeUtils::convertByteArrayToHexString(m_dataBuffer);
+ QByteArray frame = unescapeData(m_dataBuffer);
+ if (frame.isNull()) {
+ qCWarning(dcZigbeeInterface()) << "Received inconsistant message. Ignoring data" << ZigbeeUtils::convertByteArrayToHexString(m_dataBuffer);
+ } else {
+ QByteArray package = frame.left(frame.length() - 2);
+ QByteArray checksumBytes = frame.right(2);
+ QDataStream stream(&checksumBytes, QIODevice::ReadOnly);
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 receivedChecksum = 0;
+ stream >> receivedChecksum;
+ quint16 calculatedChecksum = calculateCrc(package);
+ if (receivedChecksum != calculatedChecksum) {
+ qCWarning(dcZigbeeInterfaceTraffic()) << "Checksum verification failed for frame" << ZigbeeUtils::convertByteArrayToHexString(m_dataBuffer) << receivedChecksum << "!=" << calculatedChecksum;
+ continue;
+ }
+
+ // Checksum verified, we got valid data
+ emit packageReceived(package);
+ }
+ m_dataBuffer.clear();
+ } else {
+ m_dataBuffer.append(data.at(i));
+ }
+ }
+}
+
+void ZigbeeInterfaceDeconz::onError(const QSerialPort::SerialPortError &error)
+{
+ if (error != QSerialPort::NoError && m_serialPort->isOpen()) {
+ qCWarning(dcZigbeeInterface()) << "Serial port error:" << error << m_serialPort->errorString();
+ m_reconnectTimer->start();
+ m_serialPort->close();
+ setAvailable(false);
+ }
+}
+
+void ZigbeeInterfaceDeconz::sendPackage(const QByteArray &package)
+{
+ if (!m_available) {
+ qCWarning(dcZigbeeInterface()) << "Can not send data. The interface is not available";
+ return;
+ }
+
+ // Build the frame and escape the package data and crc
+ quint16 checksum = calculateCrc(package);
+
+ QByteArray frame = package;
+ QDataStream frameStream(&frame, QIODevice::WriteOnly | QIODevice::Append);
+ frameStream.setByteOrder(QDataStream::LittleEndian);
+ frameStream << checksum;
+
+ // Escape data according to SLIP for transfere
+ QByteArray serializedData = escapeData(frame);
+
+ // Build transport data
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ stream << static_cast(ProtocolByteEnd); // Start with SLIP END character
+ for (int i = 0; i < serializedData.length(); i++)
+ stream << static_cast(serializedData.at(i));
+
+ stream << static_cast(ProtocolByteEnd); // End with SLIP END character
+
+ // Send the data
+ qCDebug(dcZigbeeInterfaceTraffic()) << "-->" << ZigbeeUtils::convertByteArrayToHexString(data);
+ if (m_serialPort->write(data) < 0) {
+ qCWarning(dcZigbeeInterface()) << "Could not stream byte" << ZigbeeUtils::convertByteArrayToHexString(data);
+ }
+
+ m_serialPort->flush();
+}
+
+bool ZigbeeInterfaceDeconz::enable(const QString &serialPort, qint32 baudrate)
+{
+ if (m_serialPort) {
+ delete m_serialPort;
+ m_serialPort = nullptr;
+ }
+
+ setAvailable(false);
+
+ m_serialPort = new QSerialPort(serialPort, this);
+ m_serialPort->setBaudRate(baudrate);
+ m_serialPort->setDataBits(QSerialPort::Data8);
+ m_serialPort->setStopBits(QSerialPort::OneStop);
+ m_serialPort->setParity(QSerialPort::NoParity);
+ m_serialPort->setFlowControl(QSerialPort::NoFlowControl);
+
+ connect(m_serialPort, &QSerialPort::readyRead, this, &ZigbeeInterfaceDeconz::onReadyRead);
+ connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onError(QSerialPort::SerialPortError)));
+
+ if (!m_serialPort->open(QSerialPort::ReadWrite)) {
+ qCWarning(dcZigbeeInterface()) << "Could not open serial port" << serialPort << baudrate;
+ m_reconnectTimer->start();
+ return false;
+ }
+
+ qCDebug(dcZigbeeInterface()) << "Interface enabled successfully on" << serialPort << baudrate;
+ setAvailable(true);
+ return true;
+}
+
+void ZigbeeInterfaceDeconz::disable()
+{
+ if (!m_serialPort)
+ return;
+
+ if (m_serialPort->isOpen())
+ m_serialPort->close();
+
+ delete m_serialPort;
+ m_serialPort = nullptr;
+ setAvailable(false);
+ qCDebug(dcZigbeeInterface()) << "Interface disabled";
+}
diff --git a/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconz.h b/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconz.h
new file mode 100644
index 0000000..58af5b7
--- /dev/null
+++ b/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconz.h
@@ -0,0 +1,82 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea-zigbee.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* 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 ZIGBEEINTERFACEDECONZ_H
+#define ZIGBEEINTERFACEDECONZ_H
+
+#include
+#include
+#include
+
+class ZigbeeInterfaceDeconz : public QObject
+{
+ Q_OBJECT
+public:
+ enum ProtocolByte {
+ ProtocolByteEnd = 0xC0,
+ ProtocolByteEsc = 0xDB,
+ ProtocolByteTransposedEnd = 0xDC,
+ ProtocolByteTransposedEsc = 0xDD
+ };
+ Q_ENUM(ProtocolByte)
+
+ explicit ZigbeeInterfaceDeconz(QObject *parent = nullptr);
+ ~ZigbeeInterfaceDeconz();
+
+ bool available() const;
+ QString serialPort() const;
+
+private:
+ QTimer *m_reconnectTimer = nullptr;
+ QSerialPort *m_serialPort = nullptr;
+ bool m_available = false;
+ QByteArray m_dataBuffer;
+
+ quint16 calculateCrc(const QByteArray &data);
+ QByteArray unescapeData(const QByteArray &data);
+ QByteArray escapeData(const QByteArray &data);
+
+ void setAvailable(bool available);
+
+signals:
+ void availableChanged(bool available);
+ void packageReceived(const QByteArray &package);
+
+private slots:
+ void onReconnectTimeout();
+ void onReadyRead();
+ void onError(const QSerialPort::SerialPortError &error);
+
+public slots:
+ void sendPackage(const QByteArray &package);
+
+ bool enable(const QString &serialPort = "/dev/ttyS0", qint32 baudrate = 115200);
+ void disable();
+
+};
+
+#endif // ZIGBEEINTERFACEDECONZ_H
diff --git a/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconzreply.cpp b/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconzreply.cpp
new file mode 100644
index 0000000..3469fd5
--- /dev/null
+++ b/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconzreply.cpp
@@ -0,0 +1,56 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea-zigbee.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* 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 "zigbeeinterfacedeconzreply.h"
+
+Deconz::Command ZigbeeInterfaceDeconzReply::command() const
+{
+ return m_command;
+}
+
+quint8 ZigbeeInterfaceDeconzReply::sequenceNumber() const
+{
+ return m_sequenceNumber;
+}
+
+QByteArray ZigbeeInterfaceDeconzReply::responseData() const
+{
+ return m_responseData;
+}
+
+Deconz::StatusCode ZigbeeInterfaceDeconzReply::statusCode() const
+{
+ return m_statusCode;
+}
+
+ZigbeeInterfaceDeconzReply::ZigbeeInterfaceDeconzReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent) :
+ QObject(parent),
+ m_command(command),
+ m_sequenceNumber(sequenceNumber)
+{
+
+}
diff --git a/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconzreply.h b/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconzreply.h
new file mode 100644
index 0000000..2a67a5f
--- /dev/null
+++ b/libnymea-zigbee/deconz/interface/zigbeeinterfacedeconzreply.h
@@ -0,0 +1,66 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea-zigbee.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* 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 ZIGBEEINTERFACEDECONZREPLY_H
+#define ZIGBEEINTERFACEDECONZREPLY_H
+
+#include
+
+#include "deconz.h"
+
+class ZigbeeInterfaceDeconzReply : public QObject
+{
+ Q_OBJECT
+
+ friend class ZigbeeBridgeControllerDeconz;
+
+public:
+ // Request content
+ Deconz::Command command() const;
+ quint8 sequenceNumber() const;
+ QByteArray responseData() const;
+
+ // Response content
+ Deconz::StatusCode statusCode() const;
+
+private:
+ explicit ZigbeeInterfaceDeconzReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent = nullptr);
+
+ // Request content
+ Deconz::Command m_command;
+ quint8 m_sequenceNumber = 0;
+
+ // Response content
+ Deconz::StatusCode m_statusCode = Deconz::StatusCodeError;
+ QByteArray m_responseData;
+
+signals:
+ void finished();
+
+};
+
+#endif // ZIGBEEINTERFACEDECONZREPLY_H
diff --git a/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.cpp b/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.cpp
new file mode 100644
index 0000000..c1fc5d6
--- /dev/null
+++ b/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.cpp
@@ -0,0 +1,589 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea-zigbee.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* 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 "zigbeebridgecontrollerdeconz.h"
+#include "loggingcategory.h"
+#include "zigbeeutils.h"
+
+#include
+
+ZigbeeBridgeControllerDeconz::ZigbeeBridgeControllerDeconz(QObject *parent) :
+ ZigbeeBridgeController(parent)
+{
+ m_interface = new ZigbeeInterfaceDeconz(this);
+ connect(m_interface, &ZigbeeInterfaceDeconz::availableChanged, this, &ZigbeeBridgeControllerDeconz::onInterfaceAvailableChanged);
+ connect(m_interface, &ZigbeeInterfaceDeconz::packageReceived, this, &ZigbeeBridgeControllerDeconz::onInterfacePackageReceived);
+
+ m_watchdogTimer = new QTimer(this);
+ m_watchdogTimer->setSingleShot(false);
+ m_watchdogTimer->setInterval(m_watchdogResetTimout * 1000); // Set the watchdog to 85 seconds, reset every 60 s
+ connect(m_watchdogTimer, &QTimer::timeout, this, &ZigbeeBridgeControllerDeconz::onWatchdogTimerTimeout);
+}
+
+ZigbeeBridgeControllerDeconz::~ZigbeeBridgeControllerDeconz()
+{
+ qCDebug(dcZigbeeController()) << "Destroy controller";
+}
+
+ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestVersion()
+{
+ quint8 sequenceNumber = generateSequenceNumber();
+ qCDebug(dcZigbeeController()) << "Request version. SQN:" << sequenceNumber;
+
+ QByteArray message;
+ QDataStream stream(&message, QIODevice::WriteOnly);
+ stream.setByteOrder(QDataStream::LittleEndian);
+ stream << static_cast(Deconz::CommandVersion);
+ stream << static_cast(sequenceNumber);
+ stream << static_cast(0); // Reserverd
+ stream << static_cast(5); // Frame length
+
+ ZigbeeInterfaceDeconzReply *reply = new ZigbeeInterfaceDeconzReply(Deconz::CommandVersion, sequenceNumber, this);
+ connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater);
+ m_pendingReplies.insert(sequenceNumber, reply);
+
+ m_interface->sendPackage(message);
+ return reply;
+}
+
+ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestDeviceState()
+{
+ quint8 sequenceNumber = generateSequenceNumber();
+ qCDebug(dcZigbeeController()) << "Request device state. SQN:" << sequenceNumber;
+
+ QByteArray message;
+ QDataStream stream(&message, QIODevice::WriteOnly);
+ stream.setByteOrder(QDataStream::LittleEndian);
+ stream << static_cast(Deconz::CommandDeviceState);
+ stream << static_cast(sequenceNumber);
+ stream << static_cast(0); // Reserverd
+ stream << static_cast(8); // Frame length
+ stream << static_cast(0); // Reserverd
+ stream << static_cast(0); // Reserverd
+ stream << static_cast(0); // Reserverd
+
+ ZigbeeInterfaceDeconzReply *reply = new ZigbeeInterfaceDeconzReply(Deconz::CommandDeviceState, sequenceNumber, this);
+ connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater);
+ m_pendingReplies.insert(sequenceNumber, reply);
+
+ m_interface->sendPackage(message);
+
+ return createReply(Deconz::CommandDeviceState, sequenceNumber, this);
+}
+
+ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestReadParameter(Deconz::Parameter parameter)
+{
+ quint8 sequenceNumber = generateSequenceNumber();
+ qCDebug(dcZigbeeController()) << "Request read parameter. SQN:" << sequenceNumber << parameter;
+
+ QByteArray message;
+ QDataStream stream(&message, QIODevice::WriteOnly);
+ stream.setByteOrder(QDataStream::LittleEndian);
+ stream << static_cast(Deconz::CommandReadParameter);
+ stream << static_cast(sequenceNumber);
+ stream << static_cast(0); // Reserverd
+ stream << static_cast(8); // Frame length 7 + 1 payload
+ stream << static_cast(1); // Payload length
+ stream << static_cast(parameter);
+
+ m_interface->sendPackage(message);
+
+ return createReply(Deconz::CommandReadParameter, sequenceNumber, this);
+}
+
+ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestWriteParameter(Deconz::Parameter parameter, const QByteArray &data)
+{
+ quint8 sequenceNumber = generateSequenceNumber();
+ qCDebug(dcZigbeeController()) << "Request write parameter. SQN:" << sequenceNumber << parameter << ZigbeeUtils::convertByteArrayToHexString(data);
+
+ QByteArray message;
+ QDataStream stream(&message, QIODevice::WriteOnly);
+ stream.setByteOrder(QDataStream::LittleEndian);
+ stream << static_cast(Deconz::CommandWriteParameter);
+ stream << static_cast(sequenceNumber);
+ stream << static_cast(0); // Reserverd
+ stream << static_cast(7 + 1 + data.length()); // Frame length 7 + 1 parameter + payload length
+ stream << static_cast(1 + data.length()); // 1 parameter + payload length
+ stream << static_cast(parameter);
+ for (int i = 0; i < data.length(); i++) {
+ stream << static_cast(data.at(i));
+ }
+
+ m_interface->sendPackage(message);
+
+ return createReply(Deconz::CommandWriteParameter, sequenceNumber, this);
+}
+
+ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestChangeNetworkState(Deconz::NetworkState networkState)
+{
+ quint8 sequenceNumber = generateSequenceNumber();
+ qCDebug(dcZigbeeController()) << "Request change network state. SQN:" << sequenceNumber << networkState;
+
+ QByteArray message;
+ QDataStream stream(&message, QIODevice::WriteOnly);
+ stream.setByteOrder(QDataStream::LittleEndian);
+ stream << static_cast(Deconz::CommandChangeNetworkState);
+ stream << static_cast(sequenceNumber);
+ stream << static_cast(0); // Reserverd
+ stream << static_cast(6); // Frame length
+ stream << static_cast(networkState);
+
+ m_interface->sendPackage(message);
+
+ return createReply(Deconz::CommandChangeNetworkState, sequenceNumber, this);
+}
+
+
+quint8 ZigbeeBridgeControllerDeconz::generateSequenceNumber()
+{
+ return m_sequenceNumber++;
+}
+
+ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::createReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent)
+{
+ // Create the reply
+ ZigbeeInterfaceDeconzReply *reply = new ZigbeeInterfaceDeconzReply(command, sequenceNumber, parent);
+
+ // Auto delete the object on finished
+ connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater);
+
+ // Add it to the pending list
+ m_pendingReplies.insert(sequenceNumber, reply);
+
+ return reply;
+}
+
+ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters()
+{
+ qCDebug(dcZigbeeController()) << "Start reading network parameters";
+
+ // This method reads all network configuration parameters sequentially. This method returns a reply which will be finished either
+ // when a read request failes or all requests finished successfully.
+ // If read request failes, this mehtod returns the status code of the failed request.
+
+ // Create an independent reply for finishing the entire read sequence
+ ZigbeeInterfaceDeconzReply *readNetworkParametersReply = new ZigbeeInterfaceDeconzReply(Deconz::CommandReadParameter, m_sequenceNumber, this);
+ connect(readNetworkParametersReply, &ZigbeeInterfaceDeconzReply::finished, readNetworkParametersReply, &ZigbeeInterfaceDeconzReply::deleteLater);
+
+ // Read MAC address of the bridge
+ ZigbeeInterfaceDeconzReply *replyMacAddress = requestReadParameter(Deconz::ParameterMacAddress);
+ connect(replyMacAddress, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyMacAddress](){
+ if (replyMacAddress->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyMacAddress->command() << Deconz::ParameterMacAddress
+ << "finished with error" << replyMacAddress->statusCode();
+
+ readNetworkParametersReply->m_statusCode = replyMacAddress->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+ QDataStream stream(replyMacAddress->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint64 macAddress = 0;
+ stream >> payloadLenght >> parameter >> macAddress;
+
+ m_networkConfiguration.ieeeAddress = ZigbeeAddress(macAddress);
+ qCDebug(dcZigbeeController()) << "Request" << replyMacAddress->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << "IEEE address:" << m_networkConfiguration.ieeeAddress.toString();
+
+ // Read PAN ID
+ ZigbeeInterfaceDeconzReply *replyPanId = requestReadParameter(Deconz::ParameterPanId);
+ connect(replyPanId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyPanId](){
+ if (replyPanId->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyPanId->command() << Deconz::ParameterPanId
+ << "finished with error" << replyPanId->statusCode();
+ readNetworkParametersReply->m_statusCode = replyPanId->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+ QDataStream stream(replyPanId->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint16 panId = 0;
+ stream >> payloadLenght >> parameter >> panId;
+
+ m_networkConfiguration.panId = panId;
+ qCDebug(dcZigbeeController()) << "Request" << replyPanId->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << "PAN ID:" << ZigbeeUtils::convertUint16ToHexString(m_networkConfiguration.panId);
+
+ // Read short address
+ ZigbeeInterfaceDeconzReply *replyShortAddress = requestReadParameter(Deconz::ParameterNetworkAddress);
+ connect(replyShortAddress, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyShortAddress](){
+ if (replyShortAddress->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyShortAddress->command() << Deconz::ParameterNetworkAddress
+ << "finished with error" << replyShortAddress->statusCode();
+ readNetworkParametersReply->m_statusCode = replyShortAddress->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyShortAddress->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint16 shortAddress = 0;
+ stream >> payloadLenght >> parameter >> shortAddress;
+ m_networkConfiguration.shortAddress = shortAddress;
+ qCDebug(dcZigbeeController()) << "Request" << replyShortAddress->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << ZigbeeUtils::convertUint16ToHexString(m_networkConfiguration.shortAddress);
+
+ // Read extended PAN ID
+ ZigbeeInterfaceDeconzReply *replyExtendedPanId = requestReadParameter(Deconz::ParameterNetworkExtendedPanId);
+ connect(replyExtendedPanId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyExtendedPanId](){
+ if (replyExtendedPanId->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyExtendedPanId->command() << Deconz::ParameterNetworkExtendedPanId
+ << "finished with error" << replyExtendedPanId->statusCode();
+ readNetworkParametersReply->m_statusCode = replyExtendedPanId->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyExtendedPanId->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint64 networkExtendedPanId = 0;
+ stream >> payloadLenght >> parameter >> networkExtendedPanId;
+ m_networkConfiguration.extendedPanId = networkExtendedPanId;
+ qCDebug(dcZigbeeController()) << "Request" << replyExtendedPanId->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << ZigbeeUtils::convertUint64ToHexString(m_networkConfiguration.extendedPanId);
+
+ // Read device type
+ ZigbeeInterfaceDeconzReply *replyNodeType = requestReadParameter(Deconz::ParameterNodeType);
+ connect(replyNodeType, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyNodeType](){
+ if (replyNodeType->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyNodeType->command() << Deconz::ParameterNodeType
+ << "finished with error" << replyNodeType->statusCode();
+ readNetworkParametersReply->m_statusCode = replyNodeType->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyNodeType->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint8 nodeType = 0;
+ stream >> payloadLenght >> parameter >> nodeType;
+
+ m_networkConfiguration.nodeType = static_cast(nodeType);
+ qCDebug(dcZigbeeController()) << "Request" << replyNodeType->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << m_networkConfiguration.nodeType;
+
+ // Read channel mask
+ ZigbeeInterfaceDeconzReply *replyChannelMask = requestReadParameter(Deconz::ParameterChannelMask);
+ connect(replyChannelMask, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyChannelMask](){
+ if (replyChannelMask->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyChannelMask->command() << Deconz::ParameterChannelMask
+ << "finished with error" << replyChannelMask->statusCode();
+ readNetworkParametersReply->m_statusCode = replyChannelMask->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyChannelMask->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint32 channelMask = 0;
+ stream >> payloadLenght >> parameter >> channelMask;
+
+ m_networkConfiguration.channelMask = channelMask;
+ qCDebug(dcZigbeeController()) << "Request" << replyChannelMask->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << ZigbeeUtils::convertUint32ToHexString(m_networkConfiguration.channelMask);
+
+ // Read APS extended PAN ID
+ ZigbeeInterfaceDeconzReply *replyApsExtendedPanId = requestReadParameter(Deconz::ParameterApsExtendedPanId);
+ connect(replyApsExtendedPanId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyApsExtendedPanId](){
+ if (replyApsExtendedPanId->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyApsExtendedPanId->command() << Deconz::ParameterApsExtendedPanId
+ << "finished with error" << replyApsExtendedPanId->statusCode();
+ readNetworkParametersReply->m_statusCode = replyApsExtendedPanId->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyApsExtendedPanId->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint64 apsExtendedPanId = 0;
+ stream >> payloadLenght >> parameter >> apsExtendedPanId;
+
+ m_networkConfiguration.apsExtendedPanId = apsExtendedPanId;
+ qCDebug(dcZigbeeController()) << "Request" << replyApsExtendedPanId->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << ZigbeeUtils::convertUint64ToHexString(m_networkConfiguration.apsExtendedPanId);
+
+ // Read trust center address
+ ZigbeeInterfaceDeconzReply *replyTrustCenterAddress = requestReadParameter(Deconz::ParameterTrustCenterAddress);
+ connect(replyTrustCenterAddress, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyTrustCenterAddress](){
+ if (replyTrustCenterAddress->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyTrustCenterAddress->command() << Deconz::ParameterTrustCenterAddress
+ << "finished with error" << replyTrustCenterAddress->statusCode();
+ readNetworkParametersReply->m_statusCode = replyTrustCenterAddress->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyTrustCenterAddress->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint64 trustCenterAddress = 0;
+ stream >> payloadLenght >> parameter >> trustCenterAddress;
+
+ m_networkConfiguration.trustCenterAddress = ZigbeeAddress(trustCenterAddress);
+ qCDebug(dcZigbeeController()) << "Request" << replyTrustCenterAddress->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << m_networkConfiguration.trustCenterAddress;
+
+ // Read security mode
+ ZigbeeInterfaceDeconzReply *replySecurityMode = requestReadParameter(Deconz::ParameterSecurityMode);
+ connect(replySecurityMode, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replySecurityMode](){
+ if (replySecurityMode->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replySecurityMode->command() << Deconz::ParameterSecurityMode
+ << "finished with error" << replySecurityMode->statusCode();
+ readNetworkParametersReply->m_statusCode = replySecurityMode->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replySecurityMode->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint8 securityMode = 0;
+ stream >> payloadLenght >> parameter >> securityMode;
+
+ m_networkConfiguration.securityMode = static_cast(securityMode);
+ qCDebug(dcZigbeeController()) << "Request" << replySecurityMode->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << m_networkConfiguration.securityMode;
+
+ // Note: reading the network key returns "InavlidParameter". Might be for security reasons which is good!
+
+ // Read channel
+ ZigbeeInterfaceDeconzReply *replyChannel = requestReadParameter(Deconz::ParameterCurrentChannel);
+ connect(replyChannel, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyChannel](){
+ if (replyChannel->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyChannel->command() << Deconz::ParameterCurrentChannel
+ << "finished with error" << replyChannel->statusCode();
+ readNetworkParametersReply->m_statusCode = replyChannel->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyChannel->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint8 channel = 0;
+ stream >> payloadLenght >> parameter >> channel;
+ m_networkConfiguration.currentChannel = channel;
+ qCDebug(dcZigbeeController()) << "Request" << replyChannel->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << "Current channel:" << m_networkConfiguration.currentChannel;
+
+
+ // Read permit join status
+ ZigbeeInterfaceDeconzReply *replyPermitJoin = requestReadParameter(Deconz::ParameterPermitJoin);
+ connect(replyPermitJoin, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyPermitJoin](){
+ if (replyPermitJoin->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyPermitJoin->command() << Deconz::ParameterPermitJoin
+ << "finished with error" << replyPermitJoin->statusCode();
+ readNetworkParametersReply->m_statusCode = replyPermitJoin->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyPermitJoin->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0;
+ stream >> payloadLenght >> parameter;
+ //m_networkConfiguration.currentChannel = channel;
+ qCDebug(dcZigbeeController()) << "Request" << replyPermitJoin->command() << static_cast(parameter)
+ << "finished successfully" << ZigbeeUtils::convertByteArrayToHexString(replyPermitJoin->responseData());
+
+
+ // Read protocol version
+ ZigbeeInterfaceDeconzReply *replyProtocolVersion = requestReadParameter(Deconz::ParameterProtocolVersion);
+ connect(replyProtocolVersion, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyProtocolVersion](){
+ if (replyProtocolVersion->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyProtocolVersion->command() << Deconz::ParameterProtocolVersion
+ << "finished with error" << replyProtocolVersion->statusCode();
+ readNetworkParametersReply->m_statusCode = replyProtocolVersion->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyProtocolVersion->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint16 protocolVersion = 0;
+ stream >> payloadLenght >> parameter >> protocolVersion;
+ m_networkConfiguration.protocolVersion = protocolVersion;
+ qCDebug(dcZigbeeController()) << "Request" << replyProtocolVersion->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << "Protocol version:" << ZigbeeUtils::convertUint16ToHexString(m_networkConfiguration.protocolVersion);
+
+ // Read network updat id
+ ZigbeeInterfaceDeconzReply *replyNetworkUpdateId = requestReadParameter(Deconz::ParameterNetworkUpdateId);
+ connect(replyNetworkUpdateId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyNetworkUpdateId](){
+ if (replyNetworkUpdateId->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyNetworkUpdateId->command() << Deconz::ParameterNetworkUpdateId
+ << "finished with error" << replyNetworkUpdateId->statusCode();
+ readNetworkParametersReply->m_statusCode = replyNetworkUpdateId->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyNetworkUpdateId->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint8 networkUpdateId = 0;
+ stream >> payloadLenght >> parameter >> networkUpdateId;
+ m_networkConfiguration.networkUpdateId = networkUpdateId;
+ qCDebug(dcZigbeeController()) << "Request" << replyNetworkUpdateId->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << "Network update ID:" << m_networkConfiguration.networkUpdateId;
+
+ // Make sure the watchdog is available for this version
+ if (m_networkConfiguration.protocolVersion < 0x0108) {
+ qCDebug(dcZigbeeController()) << "The watchdog api is available since protocol version 0x0108. The watchdog is not required for this version";
+ m_watchdogTimer->stop();
+
+ // Finished reading all parameters. Finish the independent reply in order to indicate the process has finished
+ readNetworkParametersReply->m_statusCode = Deconz::StatusCodeSuccess;
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ // Read watchdog timeout
+ ZigbeeInterfaceDeconzReply *replyWatchdogTimeout = requestReadParameter(Deconz::ParameterWatchdogTtl);
+ connect(replyWatchdogTimeout, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyWatchdogTimeout](){
+ if (replyWatchdogTimeout->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << replyWatchdogTimeout->command() << Deconz::ParameterWatchdogTtl
+ << "finished with error" << replyWatchdogTimeout->statusCode();
+ readNetworkParametersReply->m_statusCode = replyWatchdogTimeout->statusCode();
+ readNetworkParametersReply->finished();
+ return;
+ }
+
+ QDataStream stream(replyWatchdogTimeout->responseData());
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint16 payloadLenght = 0; quint8 parameter = 0; quint32 watchdogTimeout = 0;
+ stream >> payloadLenght >> parameter >> watchdogTimeout;
+ m_networkConfiguration.watchdogTimeout = watchdogTimeout;
+ qCDebug(dcZigbeeController()) << "Request" << replyWatchdogTimeout->command() << static_cast(parameter)
+ << "finished successfully";
+ qCDebug(dcZigbeeController()) << "Watchdog timeout:" << m_networkConfiguration.watchdogTimeout;
+
+ // Note: this value describes how much seconds are left until the watchdog triggers. Reset it right the way
+ if (watchdogTimeout < 15) {
+ onWatchdogTimerTimeout();
+ }
+
+ // Finished reading all parameters. Finish the independent reply in order to indicate the process has finished
+ readNetworkParametersReply->m_statusCode = Deconz::StatusCodeSuccess;
+ readNetworkParametersReply->finished();
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+
+ return readNetworkParametersReply;
+}
+
+ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::resetWatchdog()
+{
+ QByteArray parameterData;
+ QDataStream stream(¶meterData, QIODevice::WriteOnly);
+ stream.setByteOrder(QDataStream::LittleEndian);
+ stream << m_watchdogTimeout;
+ return requestWriteParameter(Deconz::ParameterWatchdogTtl, parameterData);
+}
+
+void ZigbeeBridgeControllerDeconz::onInterfaceAvailableChanged(bool available)
+{
+ if (available) {
+ m_watchdogTimer->start();
+ } else {
+ m_watchdogTimer->stop();
+ }
+
+ setAvailable(available);
+}
+
+void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray &package)
+{
+ QDataStream stream(package);
+ stream.setByteOrder(QDataStream::LittleEndian);
+ quint8 command = 0; quint8 sequenceNumber = 0; quint8 status = 0; quint16 frameLength = 0;
+ stream >> command >> sequenceNumber >> status >> frameLength;
+
+ qCDebug(dcZigbeeController()) << "Interface message received"
+ << static_cast(command)
+ << "SQN:" << sequenceNumber
+ << static_cast(status)
+ << "Frame length:" << frameLength;
+
+ // Check if this is an interface response for a pending reply
+ if (m_pendingReplies.contains(sequenceNumber) && m_pendingReplies.value(sequenceNumber)->command() == command) {
+ ZigbeeInterfaceDeconzReply *reply = m_pendingReplies.take(sequenceNumber);
+ reply->m_responseData = package.right(package.length() - 5);
+ reply->m_statusCode = static_cast(status);
+ reply->finished();
+ return;
+ }
+
+ // Note: we got a notification, lets set the current sequence number to the notification id,
+ // so the next request will be a continuouse increase
+
+ m_sequenceNumber = sequenceNumber;
+
+ // No request for this data, lets check which notification and process the data
+}
+
+void ZigbeeBridgeControllerDeconz::onWatchdogTimerTimeout()
+{
+ qCDebug(dcZigbeeController()) << "Reset application watchdog on the deCONZ controller";
+ ZigbeeInterfaceDeconzReply *reply = resetWatchdog();
+ connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [reply](){
+ if (reply->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Could not reset the application watchdog on the deCONZ controller." << reply->statusCode();
+ return;
+ }
+ qCDebug(dcZigbeeController()) << "Reset application watchdog on the deCONZ controller successfully";
+ });
+}
+
+bool ZigbeeBridgeControllerDeconz::enable(const QString &serialPort, qint32 baudrate)
+{
+ return m_interface->enable(serialPort, baudrate);
+}
+
+void ZigbeeBridgeControllerDeconz::disable()
+{
+ m_interface->disable();
+}
diff --git a/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.h b/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.h
new file mode 100644
index 0000000..456cade
--- /dev/null
+++ b/libnymea-zigbee/deconz/zigbeebridgecontrollerdeconz.h
@@ -0,0 +1,110 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea-zigbee.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* 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 ZIGBEEBRIDGECONTROLLERDECONZ_H
+#define ZIGBEEBRIDGECONTROLLERDECONZ_H
+
+#include
+#include
+#include
+
+#include "zigbee.h"
+#include "zigbeeaddress.h"
+#include "zigbeenetworkkey.h"
+#include "zigbeebridgecontroller.h"
+
+#include "interface/deconz.h"
+#include "interface/zigbeeinterfacedeconz.h"
+#include "interface/zigbeeinterfacedeconzreply.h"
+
+typedef struct DeconzNetworkConfiguration {
+ ZigbeeAddress ieeeAddress; // R
+ quint16 panId; // R
+ quint16 shortAddress; // R
+ quint64 extendedPanId; // R
+ Deconz::NodeType nodeType; // RW
+ quint32 channelMask; // RW
+ quint64 apsExtendedPanId; // RW
+ ZigbeeAddress trustCenterAddress; // RW
+ Deconz::SecurityMode securityMode; // RW
+ ZigbeeNetworkKey networkKey; // RW
+ quint8 currentChannel; // R
+ quint16 protocolVersion; // R
+ quint8 networkUpdateId; // RW
+ quint32 watchdogTimeout; // RW
+} DeconzNetworkConfiguration;
+
+
+class ZigbeeBridgeControllerDeconz : public ZigbeeBridgeController
+{
+ Q_OBJECT
+
+ friend class ZigbeeNetworkDeconz;
+
+public:
+ explicit ZigbeeBridgeControllerDeconz(QObject *parent = nullptr);
+ ~ZigbeeBridgeControllerDeconz() override;
+
+ ZigbeeInterfaceDeconzReply *requestVersion();
+ ZigbeeInterfaceDeconzReply *requestDeviceState();
+ ZigbeeInterfaceDeconzReply *requestReadParameter(Deconz::Parameter parameter);
+ ZigbeeInterfaceDeconzReply *requestWriteParameter(Deconz::Parameter parameter, const QByteArray &data);
+ ZigbeeInterfaceDeconzReply *requestStartJoinNetwork();
+
+private:
+ ZigbeeInterfaceDeconz *m_interface = nullptr;
+ quint8 m_sequenceNumber = 0;
+ quint32 m_watchdogTimeout = 85;
+ int m_watchdogResetTimout = 60;
+ QHash m_pendingReplies;
+ DeconzNetworkConfiguration m_networkConfiguration;
+ QTimer *m_watchdogTimer = nullptr;
+
+ quint8 generateSequenceNumber();
+
+ ZigbeeInterfaceDeconzReply *createReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent);
+
+ // Note: this method reads all parameters individual. The returned reply it self will not send or receive any data.
+ // The data can be fetched from m_networkConfiguration on success.
+ ZigbeeInterfaceDeconzReply *readNetworkParameters();
+
+ ZigbeeInterfaceDeconzReply *resetWatchdog();
+
+signals:
+
+private slots:
+ void onInterfaceAvailableChanged(bool available);
+ void onInterfacePackageReceived(const QByteArray &package);
+
+ void onWatchdogTimerTimeout();
+
+public slots:
+ bool enable(const QString &serialPort, qint32 baudrate);
+ void disable();
+};
+
+#endif // ZIGBEEBRIDGECONTROLLERDECONZ_H
diff --git a/libnymea-zigbee/deconz/zigbeenetworkdeconz.cpp b/libnymea-zigbee/deconz/zigbeenetworkdeconz.cpp
new file mode 100644
index 0000000..f56e32b
--- /dev/null
+++ b/libnymea-zigbee/deconz/zigbeenetworkdeconz.cpp
@@ -0,0 +1,171 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea-zigbee.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* 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 "zigbeenetworkdeconz.h"
+#include "loggingcategory.h"
+#include "zigbeeutils.h"
+
+ZigbeeNetworkDeconz::ZigbeeNetworkDeconz(QObject *parent) :
+ ZigbeeNetwork(parent)
+{
+ m_controller = new ZigbeeBridgeControllerDeconz(this);
+ //connect(m_controller, &ZigbeeBridgeControllerDeconz::messageReceived, this, &ZigbeeNetworkDeconz::onMessageReceived);
+ connect(m_controller, &ZigbeeBridgeControllerDeconz::availableChanged, this, &ZigbeeNetworkDeconz::onControllerAvailableChanged);
+}
+
+ZigbeeBridgeController *ZigbeeNetworkDeconz::bridgeController() const
+{
+ if (m_controller)
+ return qobject_cast(m_controller);
+
+ return nullptr;
+}
+
+ZigbeeNode *ZigbeeNetworkDeconz::createNode(QObject *parent)
+{
+ //FIXME
+ Q_UNUSED(parent)
+ return nullptr;
+}
+
+void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
+{
+ //FIXME
+ Q_UNUSED(permitJoining)
+}
+
+void ZigbeeNetworkDeconz::onControllerAvailableChanged(bool available)
+{
+ qCDebug(dcZigbeeNetwork()) << "Hardware controller is" << (available ? "now available" : "not available");
+
+ if (!available) {
+ // foreach (ZigbeeNode *node, nodes()) {
+ // qobject_cast(node)->setConnected(false);
+ // }
+
+ setError(ErrorHardwareUnavailable);
+ m_permitJoining = false;
+ emit permitJoiningChanged(m_permitJoining);
+ //setStartingState(StartingStateNone);
+ setState(StateOffline);
+ } else {
+ m_error = ErrorNoError;
+ m_permitJoining = false;
+ emit permitJoiningChanged(m_permitJoining);
+ // Note: if we are factory resetting, erase also the data on the controller before resetting
+ // if (m_factoryResetting) {
+ // setStartingState(StartingStateErase);
+ // } else {
+ // setStartingState(StartingStateReset);
+ // }
+
+ setState(StateStarting);
+
+ // FIXME: do this in the startig state machine
+ ZigbeeInterfaceDeconzReply *reply = m_controller->requestVersion();
+ connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
+ if (reply->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Request" << reply->command() << "finished with error" << reply->statusCode();
+ // FIXME: set an appropriate error
+ return;
+ }
+ qCDebug(dcZigbeeNetwork()) << "Version request finished" << reply->statusCode() << ZigbeeUtils::convertByteArrayToHexString(reply->responseData());
+ // Note: version is an uint32 value, little endian, but we can read the individual bytes in reversed order
+ quint8 majorVersion = static_cast(reply->responseData().at(3));
+ quint8 minorVersion = static_cast(reply->responseData().at(2));
+ Deconz::Platform platform = static_cast(reply->responseData().at(1));
+ QString firmwareVersion = QString("%1.%2").arg(majorVersion).arg(minorVersion);
+ qCDebug(dcZigbeeNetwork()) << "Firmware version" << firmwareVersion << platform;
+
+ // Read all network parameters
+ ZigbeeInterfaceDeconzReply *reply = m_controller->readNetworkParameters();
+ connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
+ if (reply->statusCode() != Deconz::StatusCodeSuccess) {
+ qCWarning(dcZigbeeController()) << "Could not read network parameters during network start up." << reply->statusCode();
+ // FIXME: set an appropriate error
+ return;
+ }
+
+ qCDebug(dcZigbeeNetwork()) << "Reading network parameters finished successfully.";
+
+
+
+
+ });
+ });
+ }
+}
+
+void ZigbeeNetworkDeconz::startNetwork()
+{
+ loadNetwork();
+
+ // Check if we have to create a pan ID and select the channel
+ if (extendedPanId() == 0) {
+ setExtendedPanId(ZigbeeUtils::generateRandomPanId());
+ qCDebug(dcZigbeeNetwork()) << "Created new PAN ID:" << extendedPanId();
+ }
+
+ if (securityConfiguration().networkKey().isNull()) {
+ qCDebug(dcZigbeeNetwork()) << "Create a new network key";
+ ZigbeeNetworkKey key = ZigbeeNetworkKey::generateKey();
+ m_securityConfiguration.setNetworkKey(key);
+ }
+
+ qCDebug(dcZigbeeNetwork()) << "Using network link key" << securityConfiguration().networkKey();
+ qCDebug(dcZigbeeNetwork()) << "Using global trust center link key" << securityConfiguration().globalTrustCenterLinkKey();
+
+ // TODO: get desired channel, by default use all
+
+ if (!m_controller->enable(serialPortName(), serialBaudrate())) {
+ m_permitJoining = false;
+ emit permitJoiningChanged(m_permitJoining);
+ setState(StateOffline);
+ //setStartingState(StartingStateNone);
+ setError(ErrorHardwareUnavailable);
+ return;
+ }
+
+ m_permitJoining = false;
+ emit permitJoiningChanged(m_permitJoining);
+ // Note: wait for the controller available signal and start the initialization there
+}
+
+void ZigbeeNetworkDeconz::stopNetwork()
+{
+
+}
+
+void ZigbeeNetworkDeconz::reset()
+{
+
+}
+
+void ZigbeeNetworkDeconz::factoryResetNetwork()
+{
+
+}
diff --git a/libnymea-zigbee/deconz/zigbeenetworkdeconz.h b/libnymea-zigbee/deconz/zigbeenetworkdeconz.h
new file mode 100644
index 0000000..606dd52
--- /dev/null
+++ b/libnymea-zigbee/deconz/zigbeenetworkdeconz.h
@@ -0,0 +1,63 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+*
+* Copyright 2013 - 2020, nymea GmbH
+* Contact: contact@nymea.io
+*
+* This file is part of nymea-zigbee.
+* This project including source code and documentation is protected by copyright law, and
+* remains the property of nymea GmbH. All rights, including reproduction, publication,
+* editing and translation, are reserved. The use of this project is subject to the terms of a
+* license agreement to be concluded with nymea GmbH in accordance with the terms
+* of use of nymea GmbH, available under https://nymea.io/license
+*
+* GNU Lesser General Public License Usage
+* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
+* Lesser General Public License as published by the Free Software Foundation; version 3.
+* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+* See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along with this project.
+* If not, see .
+*
+* 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 ZIGBEENETWORKDECONZ_H
+#define ZIGBEENETWORKDECONZ_H
+
+#include
+#include "zigbeenetwork.h"
+
+#include "zigbeebridgecontrollerdeconz.h"
+
+class ZigbeeNetworkDeconz : public ZigbeeNetwork
+{
+ Q_OBJECT
+public:
+ explicit ZigbeeNetworkDeconz(QObject *parent = nullptr);
+
+ ZigbeeBridgeController *bridgeController() const override;
+
+private:
+ ZigbeeBridgeControllerDeconz *m_controller = nullptr;
+ bool m_networkRunning = false;
+
+protected:
+ ZigbeeNode *createNode(QObject *parent) override;
+ void setPermitJoiningInternal(bool permitJoining) override;
+
+private slots:
+ void onControllerAvailableChanged(bool available);
+
+public slots:
+ void startNetwork() override;
+ void stopNetwork() override;
+ void reset() override;
+ void factoryResetNetwork() override;
+
+};
+
+#endif // ZIGBEENETWORKDECONZ_H
diff --git a/libnymea-zigbee/libnymea-zigbee.pro b/libnymea-zigbee/libnymea-zigbee.pro
index c7d8a43..5558592 100644
--- a/libnymea-zigbee/libnymea-zigbee.pro
+++ b/libnymea-zigbee/libnymea-zigbee.pro
@@ -4,6 +4,10 @@ TARGET = nymea-zigbee1
TEMPLATE = lib
SOURCES += \
+ deconz/interface/zigbeeinterfacedeconz.cpp \
+ deconz/interface/zigbeeinterfacedeconzreply.cpp \
+ deconz/zigbeebridgecontrollerdeconz.cpp \
+ deconz/zigbeenetworkdeconz.cpp \
nxp/interface/zigbeeinterface.cpp \
nxp/interface/zigbeeinterfacemessage.cpp \
nxp/interface/zigbeeinterfacerequest.cpp \
@@ -29,6 +33,11 @@ SOURCES += \
zigbeeaddress.cpp \
HEADERS += \
+ deconz/interface/deconz.h \
+ deconz/interface/zigbeeinterfacedeconz.h \
+ deconz/interface/zigbeeinterfacedeconzreply.h \
+ deconz/zigbeebridgecontrollerdeconz.h \
+ deconz/zigbeenetworkdeconz.h \
nxp/interface/zigbeeinterface.h \
nxp/interface/zigbeeinterfacemessage.h \
nxp/interface/zigbeeinterfacerequest.h \
diff --git a/libnymea-zigbee/zigbeenetworkkey.cpp b/libnymea-zigbee/zigbeenetworkkey.cpp
index e2ba46f..95f4212 100644
--- a/libnymea-zigbee/zigbeenetworkkey.cpp
+++ b/libnymea-zigbee/zigbeenetworkkey.cpp
@@ -39,9 +39,9 @@ ZigbeeNetworkKey::ZigbeeNetworkKey(const ZigbeeNetworkKey &other)
m_key = other.toByteArray();
}
-ZigbeeNetworkKey::ZigbeeNetworkKey(const QString &key)
+ZigbeeNetworkKey::ZigbeeNetworkKey(const QString &keyString)
{
- QString rawKey = QString(key).remove(':');
+ QString rawKey = QString(keyString).remove(':');
if (rawKey.isEmpty())
return;
@@ -49,8 +49,8 @@ ZigbeeNetworkKey::ZigbeeNetworkKey(const QString &key)
m_key = QByteArray::fromHex(rawKey.toLatin1());
}
-ZigbeeNetworkKey::ZigbeeNetworkKey(const QByteArray &keyString) :
- m_key(keyString)
+ZigbeeNetworkKey::ZigbeeNetworkKey(const QByteArray &key) :
+ m_key(key)
{
Q_ASSERT_X(isValid(), "ZigbeeNetworkKey", "invalid key length in ZigbeeNetworkKey(QByteArray).");
}
diff --git a/libnymea-zigbee/zigbeenetworkkey.h b/libnymea-zigbee/zigbeenetworkkey.h
index ce00781..2f9c950 100644
--- a/libnymea-zigbee/zigbeenetworkkey.h
+++ b/libnymea-zigbee/zigbeenetworkkey.h
@@ -38,8 +38,8 @@ class ZigbeeNetworkKey
public:
ZigbeeNetworkKey();
ZigbeeNetworkKey(const ZigbeeNetworkKey &other);
- ZigbeeNetworkKey(const QString &key);
- ZigbeeNetworkKey(const QByteArray &keyString);
+ ZigbeeNetworkKey(const QString &keyString);
+ ZigbeeNetworkKey(const QByteArray &key);
bool isValid() const;
bool isNull() const;
diff --git a/libnymea-zigbee/zigbeenetworkmanager.cpp b/libnymea-zigbee/zigbeenetworkmanager.cpp
index 4b7aebf..d9f9b97 100644
--- a/libnymea-zigbee/zigbeenetworkmanager.cpp
+++ b/libnymea-zigbee/zigbeenetworkmanager.cpp
@@ -29,6 +29,7 @@
#include "loggingcategory.h"
#include "nxp/zigbeenetworknxp.h"
+#include "deconz/zigbeenetworkdeconz.h"
#include
@@ -40,6 +41,8 @@ ZigbeeNetwork *ZigbeeNetworkManager::createZigbeeNetwork(ZigbeeNetworkManager::B
switch (backend) {
case BackendTypeNxp:
return qobject_cast(new ZigbeeNetworkNxp(parent));
+ case BackendTypeDeconz:
+ return qobject_cast(new ZigbeeNetworkDeconz(parent));
}
return nullptr;
diff --git a/libnymea-zigbee/zigbeenetworkmanager.h b/libnymea-zigbee/zigbeenetworkmanager.h
index 92e6c9c..f99323c 100644
--- a/libnymea-zigbee/zigbeenetworkmanager.h
+++ b/libnymea-zigbee/zigbeenetworkmanager.h
@@ -36,7 +36,8 @@ class ZigbeeNetworkManager
{
public:
enum BackendType {
- BackendTypeNxp
+ BackendTypeNxp,
+ BackendTypeDeconz
};
static ZigbeeNetwork *createZigbeeNetwork(BackendType backend, QObject *parent = nullptr);