Begin restructuring for abstraction

This commit is contained in:
Simon Stürz 2020-02-27 19:08:58 +01:00
parent 9ddc4770a3
commit f870c705af
20 changed files with 863 additions and 599 deletions

View File

@ -32,7 +32,7 @@
#include <QTimer>
#include <QSerialPort>
#include "zigbee.h"
#include "../zigbee.h"
#include "zigbeeinterfacemessage.h"
class ZigbeeInterface : public QObject

View File

@ -31,7 +31,7 @@
#include <QObject>
#include <QDebug>
#include "zigbee.h"
#include "../zigbee.h"
class ZigbeeInterfaceMessage
{

View File

@ -8,14 +8,15 @@ SOURCES += \
interface/zigbeeinterfacemessage.cpp \
interface/zigbeeinterfacerequest.cpp \
interface/zigbeeinterfacereply.cpp \
nxp/nxpzigbeenetworkmanager.cpp \
nxp/zigbeenetworknxp.cpp \
nxp/zigbeebridgecontrollernxp.cpp \
zigbeecluster.cpp \
zigbeeclusterattribute.cpp \
zigbeenetwork.cpp \
zigbeenetworkmanager.cpp \
zigbee.cpp \
loggingcategory.cpp \
zigbeebridgecontroller.cpp \
zigbeenodeendpoint.cpp \
zigbeesecurityconfiguration.cpp \
zigbeeutils.cpp \
zigbeenode.cpp \
@ -26,14 +27,15 @@ HEADERS += \
interface/zigbeeinterfacemessage.h \
interface/zigbeeinterfacerequest.h \
interface/zigbeeinterfacereply.h \
nxp/nxpzigbeenetworkmanager.h \
nxp/zigbeenetworknxp.h \
nxp/zigbeebridgecontrollernxp.h \
zigbeecluster.h \
zigbeeclusterattribute.h \
zigbeenetwork.h \
zigbeenetworkmanager.h \
zigbee.h \
loggingcategory.h \
zigbeebridgecontroller.h \
zigbeenodeendpoint.h \
zigbeesecurityconfiguration.h \
zigbeeutils.h \
zigbeenode.h \

View File

@ -1,33 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU 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 <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 "nxpzigbeenetworkmanager.h"
NxpZigbeeNetworkManager::NxpZigbeeNetworkManager(QObject *parent) : QObject(parent)
{
}

View File

@ -1,44 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU 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 <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 NXPZIGBEENETWORKMANAGER_H
#define NXPZIGBEENETWORKMANAGER_H
#include <QObject>
class NxpZigbeeNetworkManager : public QObject
{
Q_OBJECT
public:
explicit NxpZigbeeNetworkManager(QObject *parent = nullptr);
signals:
public slots:
};
#endif // NXPZIGBEENETWORKMANAGER_H

View File

@ -102,12 +102,16 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetChannelMask(quint32 chan
// 0x07fff800 select from all channels 11 - 26
// 0x2108800 primary zigbee light link channels 11, 15, 20, 25
//Zigbee::ZigbeeChannels channels = (Zigbee::ZigbeeChannel11 | Zigbee::ZigbeeChannel15 | Zigbee::ZigbeeChannel20 | Zigbee::ZigbeeChannel25);
qCDebug(dcZigbeeController()) << "Set channel mask" << ZigbeeUtils::convertUint32ToHexString(channelMask);
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::BigEndian);
stream << channelMask;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSetChannelMask, data));
request.setDescription("Set channel mask " + ZigbeeUtils::convertByteArrayToHexString(data));
request.setDescription("Set channel mask" + ZigbeeUtils::convertByteArrayToHexString(data));
return sendRequest(request);
}
@ -186,6 +190,20 @@ ZigbeeInterfaceReply *ZigbeeBridgeController::commandGetPermitJoinStatus()
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandRequestActiveEndpoints(quint16 shortAddress)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << shortAddress;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeActiveEndpointRequest, data));
request.setDescription("Get active endpoints");
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeActiveEndpointResponse);
request.setTimoutIntervall(3000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandRequestLinkQuality(quint16 shortAddress)
{
QByteArray data;

View File

@ -59,6 +59,7 @@ public:
ZigbeeInterfaceReply *commandStartScan();
ZigbeeInterfaceReply *commandPermitJoin(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 180, bool tcSignificance = false);
ZigbeeInterfaceReply *commandGetPermitJoinStatus();
ZigbeeInterfaceReply *commandRequestActiveEndpoints(quint16 shortAddress);
ZigbeeInterfaceReply *commandRequestLinkQuality(quint16 shortAddress);
ZigbeeInterfaceReply *commandEnableWhiteList();
ZigbeeInterfaceReply *commandInitiateTouchLink();
@ -71,6 +72,7 @@ public:
ZigbeeInterfaceReply *commandPowerDescriptorRequest(quint16 shortAddress);
ZigbeeInterfaceReply *commandUserDescriptorRequest(quint16 shortAddress, quint16 address);
private:
ZigbeeInterface *m_interface = nullptr;
ZigbeeInterfaceReply *m_currentReply = nullptr;

View File

@ -0,0 +1,7 @@
#include "zigbeenetworknxp.h"
ZigbeeNetworkNxp::ZigbeeNetworkNxp(QObject *parent) :
ZigbeeNetwork(parent)
{
}

View File

@ -0,0 +1,23 @@
#ifndef ZIGBEENETWORKNXP_H
#define ZIGBEENETWORKNXP_H
#include <QObject>
#include "../zigbeenetwork.h"
class ZigbeeNetworkNxp : public ZigbeeNetwork
{
Q_OBJECT
public:
explicit ZigbeeNetworkNxp(QObject *parent = nullptr);
signals:
public slots:
void startNetwork() override;
void stopNetwork() override;
void factoryResetNetwork() override;
};
#endif // ZIGBEENETWORKNXP_H

View File

@ -44,6 +44,26 @@ public:
};
Q_ENUM(ZigbeeProfile)
enum ZigbeeChannel {
ZigbeeChannel11,
ZigbeeChannel12,
ZigbeeChannel13,
ZigbeeChannel14,
ZigbeeChannel15,
ZigbeeChannel16,
ZigbeeChannel17,
ZigbeeChannel18,
ZigbeeChannel19,
ZigbeeChannel20,
ZigbeeChannel21,
ZigbeeChannel22,
ZigbeeChannel23,
ZigbeeChannel24,
ZigbeeChannel25
};
Q_ENUM(ZigbeeChannel)
Q_DECLARE_FLAGS(ZigbeeChannels, ZigbeeChannel)
enum InterfaceMessageType {
// Common Commands
MessageTypeNone = 0x0000,
@ -470,6 +490,25 @@ public:
};
Q_ENUM(Manufacturer)
enum ZigbeeNwkLayerStatus {
ZigbeeNwkLayerStatusJointNetwork = 0x00,
ZigbeeNwkLayerStatusFormedNetwork = 0x01,
ZigbeeNwkLayerStatusInvalidParameter = 0xc1,
ZigbeeNwkLayerStatusInvalidRequest = 0xc2,
ZigbeeNwkLayerStatusNotPermitted = 0xc3,
ZigbeeNwkLayerStatusStartupFailure = 0xc4,
ZigbeeNwkLayerStatusAlreadyPresent = 0xc5,
ZigbeeNwkLayerStatusSynchFailure = 0xc6,
ZigbeeNwkLayerStatusTableFull = 0xc7,
ZigbeeNwkLayerStatusUnknownDevice = 0xc8,
ZigbeeNwkLayerStatusUnsupportedAttribute = 0xc9,
ZigbeeNwkLayerStatusNoNetworks = 0xca,
ZigbeeNwkLayerStatusLeaveUnconfirmed = 0xcb,
ZigbeeNwkLayerStatusMaxFrmCntr = 0xcc,
ZigbeeNwkLayerStatusNoKey = 0xcd,
ZigbeeNwkLayerStatusBadCcmOutput = 0xce
};
Q_ENUM(ZigbeeNwkLayerStatus)
///* Manufacturer Codes */
///* Codes less than 0x1000 were issued for RF4CE */
@ -1165,4 +1204,6 @@ public:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Zigbee::ZigbeeChannels)
#endif // ZIGBEE_H

View File

@ -29,9 +29,8 @@
#include "zigbeenetwork.h"
#include "loggingcategory.h"
ZigbeeNetwork::ZigbeeNetwork(ControllerType controllerType, QObject *parent) :
ZigbeeNode(parent),
m_controllerType(controllerType)
ZigbeeNetwork::ZigbeeNetwork(QObject *parent) :
QObject(parent)
{
}
@ -41,11 +40,6 @@ ZigbeeNetwork::State ZigbeeNetwork::state() const
return m_state;
}
ZigbeeNetwork::ControllerType ZigbeeNetwork::controlerType() const
{
return m_controllerType;
}
ZigbeeNetwork::Error ZigbeeNetwork::error() const
{
return m_error;
@ -232,6 +226,7 @@ void ZigbeeNetwork::loadNetwork()
{
qCDebug(dcZigbeeNetwork()) << "Load current network configuration from" << m_settingsFileName;
QSettings settings(m_settingsFileName, QSettings::IniFormat, this);
settings.beginGroup("Network");
quint64 extendedPanId = static_cast<quint64>(settings.value("panId", 0).toULongLong());
if (extendedPanId == 0) {
@ -240,7 +235,7 @@ void ZigbeeNetwork::loadNetwork()
}
setExtendedPanId(extendedPanId);
setChannel(settings.value("channel", 0).toUInt());
settings.endGroup();
settings.endGroup(); // Network
// Load nodes
settings.beginGroup("Nodes");
@ -250,42 +245,46 @@ void ZigbeeNetwork::loadNetwork()
ZigbeeNode *node = createNode();
node->setExtendedAddress(ZigbeeAddress(ieeeAddressString));
node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt()));
// TODO: load the rest of the node
node->setMacCapabilitiesFlag(static_cast<quint8>(settings.value("macCapabilitiesFlag", 0).toUInt()));
node->setNodeDescriptorRawData(settings.value("nodeDescriptorRawData", QByteArray()).toByteArray());
node->setPowerDescriptorFlag(static_cast<quint16>(settings.value("powerDescriptorFlag", 0).toUInt()));
settings.beginGroup("inputCluster");
foreach (const QString &clusterIdString, settings.childGroups()) {
settings.beginGroup(clusterIdString);
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(clusterIdString.toInt());
// TODO: load endpoints
foreach (const QString &attributeIdString, settings.childGroups()) {
settings.beginGroup(attributeIdString);
quint16 id = static_cast<quint16>(attributeIdString.toInt());
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt());
QByteArray data = settings.value("data").toByteArray();
node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data));
settings.endGroup(); // attributeId
}
settings.endGroup(); // clusterId
}
settings.endGroup(); // inputCluster
// settings.beginGroup("inputCluster");
// foreach (const QString &clusterIdString, settings.childGroups()) {
// settings.beginGroup(clusterIdString);
// Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(clusterIdString.toInt());
// Output cluster
settings.beginGroup("outputCluster");
foreach (const QString &clusterIdString, settings.childGroups()) {
settings.beginGroup(clusterIdString);
Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(clusterIdString.toInt());
// foreach (const QString &attributeIdString, settings.childGroups()) {
// settings.beginGroup(attributeIdString);
// quint16 id = static_cast<quint16>(attributeIdString.toInt());
// Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt());
// QByteArray data = settings.value("data").toByteArray();
// node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data));
// settings.endGroup(); // attributeId
// }
// settings.endGroup(); // clusterId
// }
// settings.endGroup(); // inputCluster
foreach (const QString &attributeIdString, settings.childGroups()) {
settings.beginGroup(attributeIdString);
quint16 id = static_cast<quint16>(attributeIdString.toInt());
Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt());
QByteArray data = settings.value("data").toByteArray();
node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data));
settings.endGroup(); // attributeId
}
settings.endGroup(); // clusterId
}
settings.endGroup(); // inputCluster
// // Output cluster
// settings.beginGroup("outputCluster");
// foreach (const QString &clusterIdString, settings.childGroups()) {
// settings.beginGroup(clusterIdString);
// Zigbee::ClusterId clusterId = static_cast<Zigbee::ClusterId>(clusterIdString.toInt());
// foreach (const QString &attributeIdString, settings.childGroups()) {
// settings.beginGroup(attributeIdString);
// quint16 id = static_cast<quint16>(attributeIdString.toInt());
// Zigbee::DataType dataType = static_cast<Zigbee::DataType>(settings.value("dataType", 0).toInt());
// QByteArray data = settings.value("data").toByteArray();
// node->setClusterAttribute(clusterId, ZigbeeClusterAttribute(id, dataType, data));
// settings.endGroup(); // attributeId
// }
// settings.endGroup(); // clusterId
// }
// settings.endGroup(); // outputCluster
node->setState(StateInitialized);
addNodeInternally(node);
@ -299,21 +298,21 @@ void ZigbeeNetwork::loadNetwork()
qCDebug(dcZigbeeNetwork()) << QStringLiteral("Nodes: (%1)").arg(m_nodes.count());
foreach (ZigbeeNode *node, nodes()) {
qCDebug(dcZigbeeNetwork()) << " - " << node;
qCDebug(dcZigbeeNetwork()) << "Output cluster:";
foreach (ZigbeeCluster *cluster, node->outputClusters()) {
qCDebug(dcZigbeeNetwork()) << " " << cluster;
foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
qCDebug(dcZigbeeNetwork()) << " " << attribute;
}
}
// qCDebug(dcZigbeeNetwork()) << "Output cluster:";
// foreach (ZigbeeCluster *cluster, node->outputClusters()) {
// qCDebug(dcZigbeeNetwork()) << " " << cluster;
// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
// qCDebug(dcZigbeeNetwork()) << " " << attribute;
// }
// }
qCDebug(dcZigbeeNetwork()) << "Input cluster:";
foreach (ZigbeeCluster *cluster, node->inputClusters()) {
qCDebug(dcZigbeeNetwork()) << " " << cluster;
foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
qCDebug(dcZigbeeNetwork()) << " " << attribute;
}
}
// qCDebug(dcZigbeeNetwork()) << "Input cluster:";
// foreach (ZigbeeCluster *cluster, node->inputClusters()) {
// qCDebug(dcZigbeeNetwork()) << " " << cluster;
// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
// qCDebug(dcZigbeeNetwork()) << " " << attribute;
// }
// }
}
}
@ -350,36 +349,43 @@ void ZigbeeNetwork::saveNode(ZigbeeNode *node)
// Save this node
settings.beginGroup(node->extendedAddress().toString());
settings.setValue("nwkAddress", node->shortAddress());
settings.setValue("macCapabilitiesFlag", node->m_macCapabilitiesFlag);
settings.setValue("nodeDescriptorRawData", node->m_nodeDescriptorRawData);
settings.setValue("powerDescriptorFlag", node->m_powerDescriptorFlag);
// TODO: store endpoints
// TODO: save the rest of the node
// Input clusters
settings.beginGroup("inputCluster");
foreach (ZigbeeCluster *cluster, node->inputClusters()) {
settings.beginGroup(QString::number(static_cast<int>(cluster->clusterId())));
foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
settings.beginGroup(QString::number(static_cast<int>(attribute.id())));
settings.setValue("dataType", static_cast<int>(attribute.dataType()));
settings.setValue("data", attribute.data());
settings.endGroup(); // attributeId
}
settings.endGroup(); // clusterId
}
settings.endGroup(); // inputCluster
// // Input clusters
// settings.beginGroup("inputCluster");
// foreach (ZigbeeCluster *cluster, node->inputClusters()) {
// settings.beginGroup(QString::number(static_cast<int>(cluster->clusterId())));
// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
// settings.beginGroup(QString::number(static_cast<int>(attribute.id())));
// settings.setValue("dataType", static_cast<int>(attribute.dataType()));
// settings.setValue("data", attribute.data());
// settings.endGroup(); // attributeId
// }
// settings.endGroup(); // clusterId
// }
// settings.endGroup(); // inputCluster
// Output clusters
settings.beginGroup("outputCluster");
foreach (ZigbeeCluster *cluster, node->outputClusters()) {
settings.beginGroup(QString::number(static_cast<int>(cluster->clusterId())));
foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
settings.beginGroup(QString::number(static_cast<int>(attribute.id())));
settings.setValue("dataType", static_cast<int>(attribute.dataType()));
settings.setValue("data", attribute.data());
settings.endGroup(); // attributeId
}
settings.endGroup(); // clusterId
}
settings.endGroup(); // inputCluster
// // Output clusters
// settings.beginGroup("outputCluster");
// foreach (ZigbeeCluster *cluster, node->outputClusters()) {
// settings.beginGroup(QString::number(static_cast<int>(cluster->clusterId())));
// foreach (const ZigbeeClusterAttribute &attribute, cluster->attributes()) {
// settings.beginGroup(QString::number(static_cast<int>(attribute.id())));
// settings.setValue("dataType", static_cast<int>(attribute.dataType()));
// settings.setValue("data", attribute.data());
// settings.endGroup(); // attributeId
// }
// settings.endGroup(); // clusterId
// }
// settings.endGroup(); // inputCluster
settings.endGroup(); // Node ieee address
@ -400,7 +406,6 @@ void ZigbeeNetwork::removeNodeFromSettings(ZigbeeNode *node)
settings.endGroup(); // Nodes
}
void ZigbeeNetwork::addNode(ZigbeeNode *node)
{
qCDebug(dcZigbeeNetwork()) << "Add node" << node;
@ -425,12 +430,6 @@ void ZigbeeNetwork::removeNode(ZigbeeNode *node)
removeNodeFromSettings(node);
}
ZigbeeNode *ZigbeeNetwork::createNode()
{
ZigbeeNode *node = new ZigbeeNode(this);
return node;
}
void ZigbeeNetwork::setState(ZigbeeNetwork::State state)
{
if (m_state == state)

View File

@ -34,16 +34,11 @@
#include "zigbeenode.h"
#include "zigbeesecurityconfiguration.h"
class ZigbeeNetwork : public ZigbeeNode
class ZigbeeNetwork : public QObject
{
Q_OBJECT
public:
enum ControllerType {
ControlerTypeNxp
};
Q_ENUM(ControllerType)
enum State {
StateUninitialized,
StateDisconnected,
@ -60,10 +55,9 @@ public:
};
Q_ENUM(Error)
explicit ZigbeeNetwork(ControllerType controllerType, QObject *parent = nullptr);
explicit ZigbeeNetwork(QObject *parent = nullptr);
State state() const;
ControllerType controlerType() const;
Error error() const;
@ -99,7 +93,6 @@ public:
private:
ControllerType m_controllerType = ControlerTypeNxp;
State m_state = StateUninitialized;
Error m_error = ErrorNoError;

View File

@ -34,7 +34,7 @@
#include <QSettings>
ZigbeeNetworkManager::ZigbeeNetworkManager(QObject *parent) :
ZigbeeNetwork(ZigbeeNetwork::ControlerTypeNxp, parent)
QObject(parent)
{
}
@ -80,6 +80,21 @@ void ZigbeeNetworkManager::setPermitJoining(bool permitJoining)
});
}
void ZigbeeNetworkManager::resetController()
{
ZigbeeInterfaceReply *reply = m_controller->commandResetController();
connect(reply, &ZigbeeInterfaceReply::finished, this, [reply](){
reply->deleteLater();
if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
return;
}
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
});
}
void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState state)
{
if (m_startingState == state)
@ -99,6 +114,13 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState
}
case StartingStateReset: {
m_networkRunning = false;
// qCDebug(dcZigbeeNetwork()) << "";
// ZigbeeInterfaceReply *reply = m_controller->commandSoftResetController();
// connect(reply, &ZigbeeInterfaceReply::finished, this, [this, reply](){
// reply->deleteLater();
// });
qCDebug(dcZigbeeNetwork()) << "Starting state changed: Reset controller";
ZigbeeInterfaceReply *reply = m_controller->commandResetController();
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandResetControllerFinished);
@ -121,15 +143,22 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState
case StartingStateSetChannel: {
// Create channel mask
// Note: normal number passed, that specific channel will be used || Bitfield: all channels would be 0x07FFF800
// 0x07fff800 select from all channels 11 - 26
// 0x02108800 primary zigbee light link channels 11, 15, 20, 25
qCDebug(dcZigbeeNetwork()) << "Starting state changed: Set channel mask";
quint32 channelMask = 0;
ZigbeeInterfaceReply *reply = nullptr;
if (channel() == 0) {
qCDebug(dcZigbeeNetwork()) << "Autoselect quitest channel for the zigbee network.";
qCDebug(dcZigbeeNetwork()) << "Autoselect quitest channel for the zigbee network. FIXME: currently hardcoded to 13 due to firmware error.";
quint32 channelMask = 0;
channelMask |= 1 << (13);
reply = m_controller->commandSetChannelMask(channelMask);
} else {
quint32 channelMask = 0;
channelMask |= 1 << (channel());
qCDebug(dcZigbeeNetwork()) << "Using channel" << channel() << "for the zigbee network.";
reply = m_controller->commandSetChannelMask(channelMask);
}
ZigbeeInterfaceReply *reply = m_controller->commandSetChannelMask(channelMask);
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSetChannelMaskFinished);
break;
}
@ -162,12 +191,6 @@ void ZigbeeNetworkManager::setStartingState(ZigbeeNetworkManager::StartingState
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished);
break;
}
case StartingStateReadSimpleDescriptor: {
qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator simple descriptor";
ZigbeeInterfaceReply *reply = m_controller->commandSimpleDescriptorRequest(shortAddress(), endPoint());
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished);
break;
}
case StartingStateReadPowerDescriptor: {
qCDebug(dcZigbeeNetwork()) << "Starting state changed: Read coordinator power descriptor";
ZigbeeInterfaceReply *reply = m_controller->commandPowerDescriptorRequest(shortAddress());
@ -203,7 +226,6 @@ void ZigbeeNetworkManager::readControllerVersion()
qCDebug(dcZigbeeNetwork()) << "Controller version:" << m_controllerFirmwareVersion;
if (m_startingState == StartingStateGetVersion) setStartingState(StartingStateSetPanId);
});
}
@ -476,14 +498,10 @@ void ZigbeeNetworkManager::processNetworkFormed(const ZigbeeInterfaceMessage &me
} else if (networkStatus == 1) {
networkStatusString = "created";
success = true;
} else if (networkStatus >= 128 && networkStatus <= 244) {
networkStatusString = "failed: Zigbee event code: " + QString::number(networkStatus);
} else {
networkStatusString = "unknown";
}
if (!success) {
qCWarning(dcZigbeeNetwork()) << "Forming network failed" << networkStatusString;
qCWarning(dcZigbeeNetwork()) << "Forming network failed" << networkStatus << static_cast<Zigbee::ZigbeeNwkLayerStatus>(networkStatus);
setError(ErrorZigbeeError);
setStartingState(StartingStateNone);
setState(StateDisconnected);
@ -531,106 +549,106 @@ void ZigbeeNetworkManager::onCommandEnableWhitelistFinished()
void ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished()
{
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
reply->deleteLater();
// ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
// reply->deleteLater();
if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
return;
}
// if (reply->status() != ZigbeeInterfaceReply::Success) {
// qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
// return;
// }
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
qCDebug(dcZigbeeController()) << reply->additionalMessage();
// qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
// qCDebug(dcZigbeeController()) << reply->additionalMessage();
QByteArray data = reply->additionalMessage().data();
// QByteArray data = reply->additionalMessage().data();
quint8 sequenceNumber = 0;
quint8 status = 0;
quint16 shortAddress = 0;
quint16 manufacturerCode = 0;
quint16 maximalRxSize = 0;
quint16 maximalTxSize = 0;
quint16 serverMask = 0;
quint8 descriptorFlag = 0;
quint8 macFlags = 0;
quint8 maxBufferSize = 0;
quint16 bitField = 0;
// quint8 sequenceNumber = 0;
// quint8 status = 0;
// quint16 shortAddress = 0;
// quint16 manufacturerCode = 0;
// quint16 maximalRxSize = 0;
// quint16 maximalTxSize = 0;
// quint16 serverMask = 0;
// quint8 descriptorFlag = 0;
// quint8 macFlags = 0;
// quint8 maxBufferSize = 0;
// quint16 bitField = 0;
QDataStream stream(&data, QIODevice::ReadOnly);
stream >> sequenceNumber;
stream >> status;
stream >> shortAddress;
stream >> manufacturerCode;
stream >> maximalRxSize;
stream >> maximalTxSize;
stream >> serverMask;
stream >> descriptorFlag;
stream >> macFlags;
stream >> maxBufferSize;
stream >> bitField;
// QDataStream stream(&data, QIODevice::ReadOnly);
// stream >> sequenceNumber;
// stream >> status;
// stream >> shortAddress;
// stream >> manufacturerCode;
// stream >> maximalRxSize;
// stream >> maximalTxSize;
// stream >> serverMask;
// stream >> descriptorFlag;
// stream >> macFlags;
// stream >> maxBufferSize;
// stream >> bitField;
// Get node object
ZigbeeNode *node = getZigbeeNode(shortAddress);
if (!node) {
qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
return;
}
// // Get node object
// ZigbeeNode *node = getZigbeeNode(shortAddress);
// if (!node) {
// qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
// return;
// }
// Set node data
node->setManufacturerCode(manufacturerCode);
node->setMaximumRxSize(maximalRxSize);
node->setMaximumTxSize(maximalTxSize);
node->setMaximumBufferSize(maxBufferSize);
node->setServerMask(serverMask);
node->setMacCapabilitiesFlag(macFlags);
node->setDescriptorFlag(descriptorFlag);
// // Set node data
// node->setManufacturerCode(manufacturerCode);
// node->setMaximumRxSize(maximalRxSize);
// node->setMaximumTxSize(maximalTxSize);
// node->setMaximumBufferSize(maxBufferSize);
// node->setServerMask(serverMask);
// node->setMacCapabilitiesFlag(macFlags);
// node->setDescriptorFlag(descriptorFlag);
// Parse bit field
// 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
node->setNodeType(NodeTypeCoordinator);
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
node->setNodeType(NodeTypeRouter);
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
node->setNodeType(NodeTypeEndDevice);
}
// // Parse bit field
// // 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device
// if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
// node->setNodeType(NodeTypeCoordinator);
// } else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
// node->setNodeType(NodeTypeRouter);
// } else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
// node->setNodeType(NodeTypeEndDevice);
// }
node->setComplexDescriptorAvailable((bitField >> 3) & 0x0001);
node->setUserDescriptorAvailable((bitField >> 4) & 0x0001);
// node->setComplexDescriptorAvailable((bitField >> 3) & 0x0001);
// node->setUserDescriptorAvailable((bitField >> 4) & 0x0001);
qCDebug(dcZigbeeNetwork()) << "Node descriptor:";
qCDebug(dcZigbeeNetwork()) << " Node type:" << node->nodeType();
qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
qCDebug(dcZigbeeNetwork()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbeeNetwork()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
qCDebug(dcZigbeeNetwork()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumRxSize());
qCDebug(dcZigbeeNetwork()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumTxSize());
qCDebug(dcZigbeeNetwork()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(node->maximumBufferSize());
qCDebug(dcZigbeeNetwork()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
qCDebug(dcZigbeeNetwork()) << " Primary Trust center:" << node->isPrimaryTrustCenter();
qCDebug(dcZigbeeNetwork()) << " Backup Trust center:" << node->isBackupTrustCenter();
qCDebug(dcZigbeeNetwork()) << " Primary Binding cache:" << node->isPrimaryBindingCache();
qCDebug(dcZigbeeNetwork()) << " Backup Binding cache:" << node->isBackupBindingCache();
qCDebug(dcZigbeeNetwork()) << " Primary Discovery cache:" << node->isPrimaryDiscoveryCache();
qCDebug(dcZigbeeNetwork()) << " Backup Discovery cache:" << node->isBackupDiscoveryCache();
qCDebug(dcZigbeeNetwork()) << " Network Manager:" << node->isNetworkManager();
qCDebug(dcZigbeeNetwork()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag);
qCDebug(dcZigbeeNetwork()) << " Extended active endpoint list available:" << node->extendedActiveEndpointListAvailable();
qCDebug(dcZigbeeNetwork()) << " Extended simple descriptor list available:" << node->extendedSimpleDescriptorListAvailable();
qCDebug(dcZigbeeNetwork()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags);
qCDebug(dcZigbeeNetwork()) << " Alternate PAN coordinator:" << node->alternatePanCoordinator();
qCDebug(dcZigbeeNetwork()) << " Device type:" << node->deviceType();
qCDebug(dcZigbeeNetwork()) << " Power source flag main power:" << node->powerSourceFlagMainPower();
qCDebug(dcZigbeeNetwork()) << " Receiver on when idle:" << node->receiverOnWhenIdle();
qCDebug(dcZigbeeNetwork()) << " Security capability:" << node->securityCapability();
qCDebug(dcZigbeeNetwork()) << " Allocate address:" << node->allocateAddress();
qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField);
qCDebug(dcZigbeeNetwork()) << " Complex desciptor available:" << node->complexDescriptorAvailable();
qCDebug(dcZigbeeNetwork()) << " User desciptor available:" << node->userDescriptorAvailable();
// qCDebug(dcZigbeeNetwork()) << "Node descriptor:";
// qCDebug(dcZigbeeNetwork()) << " Node type:" << node->nodeType();
// qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
// qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
// qCDebug(dcZigbeeNetwork()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
// qCDebug(dcZigbeeNetwork()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
// qCDebug(dcZigbeeNetwork()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumRxSize());
// qCDebug(dcZigbeeNetwork()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(node->maximumTxSize());
// qCDebug(dcZigbeeNetwork()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(node->maximumBufferSize());
// qCDebug(dcZigbeeNetwork()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
// qCDebug(dcZigbeeNetwork()) << " Primary Trust center:" << node->isPrimaryTrustCenter();
// qCDebug(dcZigbeeNetwork()) << " Backup Trust center:" << node->isBackupTrustCenter();
// qCDebug(dcZigbeeNetwork()) << " Primary Binding cache:" << node->isPrimaryBindingCache();
// qCDebug(dcZigbeeNetwork()) << " Backup Binding cache:" << node->isBackupBindingCache();
// qCDebug(dcZigbeeNetwork()) << " Primary Discovery cache:" << node->isPrimaryDiscoveryCache();
// qCDebug(dcZigbeeNetwork()) << " Backup Discovery cache:" << node->isBackupDiscoveryCache();
// qCDebug(dcZigbeeNetwork()) << " Network Manager:" << node->isNetworkManager();
// qCDebug(dcZigbeeNetwork()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag);
// qCDebug(dcZigbeeNetwork()) << " Extended active endpoint list available:" << node->extendedActiveEndpointListAvailable();
// qCDebug(dcZigbeeNetwork()) << " Extended simple descriptor list available:" << node->extendedSimpleDescriptorListAvailable();
// qCDebug(dcZigbeeNetwork()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags);
// qCDebug(dcZigbeeNetwork()) << " Alternate PAN coordinator:" << node->alternatePanCoordinator();
// qCDebug(dcZigbeeNetwork()) << " Device type:" << node->deviceType();
// qCDebug(dcZigbeeNetwork()) << " Power source flag main power:" << node->powerSourceFlagMainPower();
// qCDebug(dcZigbeeNetwork()) << " Receiver on when idle:" << node->receiverOnWhenIdle();
// qCDebug(dcZigbeeNetwork()) << " Security capability:" << node->securityCapability();
// qCDebug(dcZigbeeNetwork()) << " Allocate address:" << node->allocateAddress();
// qCDebug(dcZigbeeNetwork()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField);
// qCDebug(dcZigbeeNetwork()) << " Complex desciptor available:" << node->complexDescriptorAvailable();
// qCDebug(dcZigbeeNetwork()) << " User desciptor available:" << node->userDescriptorAvailable();
if (m_startingState == StartingStateReadeNodeDescriptor) setStartingState(StartingStateReadSimpleDescriptor);
// if (m_startingState == StartingStateReadeNodeDescriptor) setStartingState(StartingStateReadPowerDescriptor);
}
void ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished()
@ -716,149 +734,144 @@ void ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished()
ZigbeeNode *node = getZigbeeNode(shortAddress);
if (!node) {
qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor);
return;
}
// Set node data
node->setEndPoint(endPoint);
node->setZigbeeProfile(static_cast<Zigbee::ZigbeeProfile>(profileId));
node->setDeviceId(deviceId);
if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor);
// // Set node data
// node->setEndPoint(endPoint);
// node->setZigbeeProfile(static_cast<Zigbee::ZigbeeProfile>(profileId));
// node->setDeviceId(deviceId);
}
void ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished()
{
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
reply->deleteLater();
// ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
// reply->deleteLater();
// Note: get the short address from the request data
QByteArray requestData = reply->request().message().data();
quint16 shortAddress;
QDataStream stream(&requestData, QIODevice::ReadOnly);
stream >> shortAddress;
// // Note: get the short address from the request data
// QByteArray requestData = reply->request().message().data();
// quint16 shortAddress;
// QDataStream stream(&requestData, QIODevice::ReadOnly);
// stream >> shortAddress;
if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
// Note: the power descriptor is the last request from the initialization
ZigbeeNode *node = getZigbeeNode(shortAddress);
if (!node) {
qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor);
return;
}
if (node->state() != ZigbeeNode::StateInitialized) {
node->setState(ZigbeeNode::StateInitialized);
}
return;
}
// if (reply->status() != ZigbeeInterfaceReply::Success) {
// qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
// // Note: the power descriptor is the last request from the initialization
// ZigbeeNode *node = getZigbeeNode(shortAddress);
// if (!node) {
// qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
// return;
// }
// if (node->state() != ZigbeeNode::StateInitialized) {
// node->setState(ZigbeeNode::StateInitialized);
// }
// return;
// }
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
qCDebug(dcZigbeeController()) << reply->additionalMessage();
// qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
// qCDebug(dcZigbeeController()) << reply->additionalMessage();
quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1));
// quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
// quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1));
quint16 bitField = static_cast<quint16>(reply->additionalMessage().data().at(2));
bitField <<= 8;
bitField |= static_cast<quint8>(reply->additionalMessage().data().at(3));
// quint16 bitField = static_cast<quint16>(reply->additionalMessage().data().at(2));
// bitField <<= 8;
// bitField |= static_cast<quint8>(reply->additionalMessage().data().at(3));
// Bit 0 - 3 Power mode
// 0000: Receiver configured according to “Receiver on when idle” MAC flag in the Node Descriptor
// 0001: Receiver switched on periodically
// 0010: Receiver switched on when stimulated, e.g. by pressing a button
// // Bit 0 - 3 Power mode
// // 0000: Receiver configured according to “Receiver on when idle” MAC flag in the Node Descriptor
// // 0001: Receiver switched on periodically
// // 0010: Receiver switched on when stimulated, e.g. by pressing a button
ZigbeeNode::PowerMode powerMode = PowerModeAlwaysOn;
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
powerMode = PowerModeAlwaysOn;
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
powerMode = PowerModeOnPeriodically;
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
powerMode = PowerModeOnWhenStimulated;
}
// ZigbeeNode::PowerMode powerMode = PowerModeAlwaysOn;
// if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
// powerMode = PowerModeAlwaysOn;
// } else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
// powerMode = PowerModeOnPeriodically;
// } else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
// powerMode = PowerModeOnWhenStimulated;
// }
// Bit 4 - 7 Available power sources
// Bit 0: Permanent mains supply
// Bit 1: Rechargeable battery
// Bit 2: Disposable battery
// Bit 4: Reserved
// // Bit 4 - 7 Available power sources
// // Bit 0: Permanent mains supply
// // Bit 1: Rechargeable battery
// // Bit 2: Disposable battery
// // Bit 4: Reserved
QList<ZigbeeNode::PowerSource> availablePowerSources;
if (ZigbeeUtils::checkBitUint16(bitField, 4)) {
availablePowerSources.append(PowerSourcePermanentMainSupply);
} else if (ZigbeeUtils::checkBitUint16(bitField, 5)) {
availablePowerSources.append(PowerSourceRecharchableBattery);
} else if (ZigbeeUtils::checkBitUint16(bitField, 6)) {
availablePowerSources.append(PowerSourceDisposableBattery);
}
// QList<ZigbeeNode::PowerSource> availablePowerSources;
// if (ZigbeeUtils::checkBitUint16(bitField, 4)) {
// availablePowerSources.append(PowerSourcePermanentMainSupply);
// } else if (ZigbeeUtils::checkBitUint16(bitField, 5)) {
// availablePowerSources.append(PowerSourceRecharchableBattery);
// } else if (ZigbeeUtils::checkBitUint16(bitField, 6)) {
// availablePowerSources.append(PowerSourceDisposableBattery);
// }
// Bit 8 - 11 Active source: according to the same schema as available power sources
ZigbeeNode::PowerSource powerSource = PowerSourcePermanentMainSupply;
if (ZigbeeUtils::checkBitUint16(bitField, 8)) {
powerSource = PowerSourcePermanentMainSupply;
} else if (ZigbeeUtils::checkBitUint16(bitField, 9)) {
powerSource = PowerSourceRecharchableBattery;
} else if (ZigbeeUtils::checkBitUint16(bitField, 10)) {
powerSource = PowerSourceDisposableBattery;
}
// // Bit 8 - 11 Active source: according to the same schema as available power sources
// ZigbeeNode::PowerSource powerSource = PowerSourcePermanentMainSupply;
// if (ZigbeeUtils::checkBitUint16(bitField, 8)) {
// powerSource = PowerSourcePermanentMainSupply;
// } else if (ZigbeeUtils::checkBitUint16(bitField, 9)) {
// powerSource = PowerSourceRecharchableBattery;
// } else if (ZigbeeUtils::checkBitUint16(bitField, 10)) {
// powerSource = PowerSourceDisposableBattery;
// }
// Bit 12 - 15: Battery level if available
// 0000: Critically low
// 0100: Approximately 33%
// 1000: Approximately 66%
// 1100: Approximately 100% (near fully charged)
ZigbeeNode::PowerLevel powerLevel = PowerLevelCriticalLow;
if (!ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
powerLevel = PowerLevelCriticalLow;
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
powerLevel = PowerLevelLow;
} else if (!ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
powerLevel = PowerLevelOk;
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
powerLevel = PowerLevelFull;
}
// // Bit 12 - 15: Battery level if available
// // 0000: Critically low
// // 0100: Approximately 33%
// // 1000: Approximately 66%
// // 1100: Approximately 100% (near fully charged)
// ZigbeeNode::PowerLevel powerLevel = PowerLevelCriticalLow;
// if (!ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
// powerLevel = PowerLevelCriticalLow;
// } else if (ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
// powerLevel = PowerLevelLow;
// } else if (!ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
// powerLevel = PowerLevelOk;
// } else if (ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
// powerLevel = PowerLevelFull;
// }
qCDebug(dcZigbeeNetwork()) << "Node power descriptor:";
qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
qCDebug(dcZigbeeNetwork()) << " Bitfiled:" << ZigbeeUtils::convertUint16ToHexString(bitField);
qCDebug(dcZigbeeNetwork()) << " Power mode:" << m_powerMode;
qCDebug(dcZigbeeNetwork()) << " Available power sources:";
foreach (const PowerSource &source, availablePowerSources) {
qCDebug(dcZigbeeNetwork()) << " " << source;
}
qCDebug(dcZigbeeNetwork()) << " Power source:" << powerSource;
qCDebug(dcZigbeeNetwork()) << " Power level:" << powerLevel;
// qCDebug(dcZigbeeNetwork()) << "Node power descriptor:";
// qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
// qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
// qCDebug(dcZigbeeNetwork()) << " Bitfiled:" << ZigbeeUtils::convertUint16ToHexString(bitField);
// qCDebug(dcZigbeeNetwork()) << " Power mode:" << m_powerMode;
// qCDebug(dcZigbeeNetwork()) << " Available power sources:";
// foreach (const PowerSource &source, availablePowerSources) {
// qCDebug(dcZigbeeNetwork()) << " " << source;
// }
// qCDebug(dcZigbeeNetwork()) << " Power source:" << powerSource;
// qCDebug(dcZigbeeNetwork()) << " Power level:" << powerLevel;
// Get node object
ZigbeeNode *node = getZigbeeNode(shortAddress);
if (!node) {
qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
if (m_startingState == StartingStateReadSimpleDescriptor) setStartingState(StartingStateReadPowerDescriptor);
return;
}
// // Get node object
// ZigbeeNode *node = getZigbeeNode(shortAddress);
// if (!node) {
// qCWarning(dcZigbeeNetwork()) << "Could not find node for address" << shortAddress << ZigbeeUtils::convertUint16ToHexString(shortAddress);
// return;
// }
// Set node data
node->setPowerMode(powerMode);
node->setPowerSource(powerSource);
node->setAvailablePowerSources(availablePowerSources);
node->setPowerLevel(powerLevel);
// // Set node data
//// node->setPowerMode(powerMode);
//// node->setPowerSource(powerSource);
//// node->setAvailablePowerSources(availablePowerSources);
//// node->setPowerLevel(powerLevel);
// Note: the power descriptor is the last request from the initialization
if (node->state() != ZigbeeNode::StateInitialized) {
node->setState(ZigbeeNode::StateInitialized);
}
// // Note: the power descriptor is the last request from the initialization
// if (node->state() != ZigbeeNode::StateInitialized) {
// node->setState(ZigbeeNode::StateInitialized);
// }
// Note: the power descriptor request for the coordinator is the last step from the network init process
if (m_startingState == StartingStateReadPowerDescriptor) {
setStartingState(StartingStateNone);
setState(StateRunning);
readControllerVersion();
foreach (ZigbeeNode *node, nodes()) {
node->setConnected(true);
}
}
// // Note: the power descriptor request for the coordinator is the last step from the network init process
// if (m_startingState == StartingStateReadPowerDescriptor) {
// setStartingState(StartingStateNone);
// setState(StateRunning);
// readControllerVersion();
// foreach (ZigbeeNode *node, nodes()) {
// node->setConnected(true);
// }
// }
}
void ZigbeeNetworkManager::onCommandInitiateTouchLinkFinished()
@ -1000,13 +1013,26 @@ void ZigbeeNetworkManager::processFactoryNewRestart(const ZigbeeInterfaceMessage
case 0:
controllerStatusString = "startup";
break;
case 1:
controllerStatusString = "wait start";
break;
case 2:
controllerStatusString = "NRF start";
break;
case 3:
controllerStatusString = "discovery";
break;
case 4:
controllerStatusString = "network init";
break;
case 5:
controllerStatusString = "rescan";
break;
case 6:
controllerStatusString = "running";
break;
default:
qCWarning(dcZigbeeNetwork()) << "Unhandled controller status" << controllerStatus;
break;
}
@ -1051,7 +1077,12 @@ void ZigbeeNetworkManager::processNodeAttributeList(const ZigbeeInterfaceMessage
qCDebug(dcZigbeeController()) << " Cluster ID:" << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
QByteArray attributeListData = message.data().right(message.data().count() - 5);
if (attributeListData.count() % 2 != 0) {
qCWarning(dcZigbeeController()) << "Attribute list is incomplete. Truncate last byte";
attributeListData = attributeListData.left(attributeListData.count() - 1);
}
qCWarning(dcZigbeeController()) << "Attributes" << ZigbeeUtils::convertByteArrayToHexString(attributeListData);
for (int i = 0; i < attributeListData.count(); i += 2) {
quint16 attribute = ZigbeeUtils::convertByteArrayToUint16(attributeListData.mid(i, 2));
qCDebug(dcZigbeeController()) << " Attribute:" << ZigbeeUtils::convertUint16ToHexString(attribute);
@ -1061,7 +1092,6 @@ void ZigbeeNetworkManager::processNodeAttributeList(const ZigbeeInterfaceMessage
void ZigbeeNetworkManager::processNodeCommandIdList(const ZigbeeInterfaceMessage &message)
{
quint8 sourceEndpoint = static_cast<quint8>(message.data().at(0));
quint16 profileId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(1, 2));
quint16 clusterId = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(3, 2));
@ -1080,39 +1110,48 @@ void ZigbeeNetworkManager::processNodeCommandIdList(const ZigbeeInterfaceMessage
void ZigbeeNetworkManager::processDeviceAnnounce(const ZigbeeInterfaceMessage &message)
{
quint16 shortAddress = ZigbeeUtils::convertByteArrayToUint16(message.data().mid(0, 2));
quint64 ieeeAddress = ZigbeeUtils::convertByteArrayToUint64(message.data().mid(2, 8));
QByteArray data = message.data();
quint8 macCapabilitiesFlag = static_cast<quint8>(message.data().at(10));
quint16 shortAddress = 0;
quint64 ieeeAddress = 0;
quint8 macCapabilitiesFlag = 0;
QDataStream stream(&data, QIODevice::ReadOnly);
stream >> shortAddress >> ieeeAddress >> macCapabilitiesFlag;
qCDebug(dcZigbeeNetwork()) << "Device announced:";
qCDebug(dcZigbeeNetwork()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbeeNetwork()) << " Extended address:" << ZigbeeAddress(ieeeAddress);
qCDebug(dcZigbeeNetwork()) << " Mac capabilities:" << ZigbeeUtils::convertByteToHexString(macCapabilitiesFlag);
ZigbeeNode *node = createNode();
node->setShortAddress(shortAddress);
node->setExtendedAddress(ZigbeeAddress(ieeeAddress));
node->setMacCapabilitiesFlag(macCapabilitiesFlag);
// Check if we already have a node with this
qCDebug(dcZigbeeNetwork()) << " Node:" << node;
// FIXME: check if node already added, and if we have to update it
addUnitializedNode(node);
node->setState(StateInitializing);
// ZigbeeNode *node = createNode();
// node->setShortAddress(shortAddress);
// node->setExtendedAddress(ZigbeeAddress(ieeeAddress));
// node->setMacCapabilitiesFlag(macCapabilitiesFlag);
ZigbeeInterfaceReply *reply = nullptr;
reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey());
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandAuthenticateDeviceFinished);
// qCDebug(dcZigbeeNetwork()) << " Node:" << node;
reply = m_controller->commandNodeDescriptorRequest(node->shortAddress());
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished);
reply = m_controller->commandSimpleDescriptorRequest(node->shortAddress(), endPoint());
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished);
reply = m_controller->commandPowerDescriptorRequest(node->shortAddress());
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished);
// // FIXME: check if node already added, and if we have to update it
// addUnitializedNode(node);
// node->setState(StateInitializing);
// ZigbeeInterfaceReply *reply = nullptr;
// reply = m_controller->commandAuthenticateDevice(node->extendedAddress(), securityConfiguration().globalTrustCenterLinkKey());
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandAuthenticateDeviceFinished);
// reply = m_controller->commandNodeDescriptorRequest(node->shortAddress());
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandNodeDescriptorRequestFinished);
// reply = m_controller->commandSimpleDescriptorRequest(node->shortAddress(), endPoint());
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandSimpleDescriptorRequestFinished);
// reply = m_controller->commandPowerDescriptorRequest(node->shortAddress());
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onCommandPowerDescriptorRequestFinished);
}
void ZigbeeNetworkManager::processAttributeReport(const ZigbeeInterfaceMessage &message)
@ -1210,9 +1249,21 @@ void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessag
case 0:
qCDebug(dcZigbeeNetwork()) << "Restart provisioned: start up";
break;
case 1:
qCDebug(dcZigbeeNetwork()) << "Restart provisioned: wait start";
break;
case 2:
qCDebug(dcZigbeeNetwork()) << "Restart provisioned: NFN start";
break;
case 3:
qCDebug(dcZigbeeNetwork()) << "Restart provisioned: discovery";
break;
case 4:
qCDebug(dcZigbeeNetwork()) << "Restart provisioned: network init";
break;
case 5:
qCDebug(dcZigbeeNetwork()) << "Restart provisioned: rescan";
break;
case 6:
qCDebug(dcZigbeeNetwork()) << "Restart provisioned: running";
break;
@ -1232,6 +1283,16 @@ void ZigbeeNetworkManager::processRestartProvisioned(const ZigbeeInterfaceMessag
}
}
void ZigbeeNetworkManager::processRouterDiscoveryConfirm(const ZigbeeInterfaceMessage &message)
{
if (message.data().isEmpty())
return;
quint8 status = static_cast<quint8>(message.data().at(0));
Zigbee::ZigbeeNwkLayerStatus networkStatus = static_cast<Zigbee::ZigbeeNwkLayerStatus>(message.data().at(0));
qCDebug(dcZigbeeNetwork()) << "Router discovery confirm received" << status << networkStatus;
}
void ZigbeeNetworkManager::startNetwork()
{
qCDebug(dcZigbeeNetwork()) << "Start network...";
@ -1307,6 +1368,9 @@ void ZigbeeNetworkManager::onMessageReceived(const ZigbeeInterfaceMessage &messa
case Zigbee::MessageTypeRestartProvisioned:
processRestartProvisioned(message);
break;
case Zigbee::MessageTypeRouterDiscoveryConfirm:
processRouterDiscoveryConfirm(message);
break;
default:
qCWarning(dcZigbeeController()) << "Unhandled message received:" << message;
break;
@ -1338,7 +1402,6 @@ void ZigbeeNetworkManager::onControllerAvailableChanged(bool available)
}
void ZigbeeNetworkManager::factoryResetNetwork()
{
qCDebug(dcZigbeeNetwork()) << "Factory reset network and forget all information. This cannot be undone.";

View File

@ -35,7 +35,7 @@
#include "zigbeebridgecontroller.h"
#include "zigbeesecurityconfiguration.h"
class ZigbeeNetworkManager : public ZigbeeNetwork
class ZigbeeNetworkManager : public QObject
{
Q_OBJECT
public:
@ -51,6 +51,7 @@ public:
// Note: Follwoing methods should be abstract
bool permitJoining() const;
void setPermitJoining(bool permitJoining);
void resetController();
private:
enum StartingState {
@ -65,7 +66,6 @@ private:
StartingStateStartNetwork,
StartingStateGetPermitJoinStatus,
StartingStateReadeNodeDescriptor,
StartingStateReadSimpleDescriptor,
StartingStateReadPowerDescriptor
};
@ -126,6 +126,7 @@ private slots:
void processAttributeReport(const ZigbeeInterfaceMessage &message);
void processLeaveIndication(const ZigbeeInterfaceMessage &message);
void processRestartProvisioned(const ZigbeeInterfaceMessage &message);
void processRouterDiscoveryConfirm(const ZigbeeInterfaceMessage &message);
public slots:
void startNetwork() override;

View File

@ -31,6 +31,16 @@
#include <QDataStream>
/* Node initialisation steps (sequentially)
* - Authenticate
* - Node descriptor
* - Power descriptor
* - Active endpoints
* - for each endpoint do:
* * Simple descriptor request
*/
ZigbeeNode::ZigbeeNode(QObject *parent) :
QObject(parent)
{
@ -57,9 +67,9 @@ ZigbeeAddress ZigbeeNode::extendedAddress() const
return m_extendedAddress;
}
quint8 ZigbeeNode::endPoint() const
QList<quint8> ZigbeeNode::endPoints() const
{
return m_endPoint;
return m_endPoints;
}
ZigbeeNode::NodeType ZigbeeNode::nodeType() const
@ -77,21 +87,11 @@ ZigbeeNode::Relationship ZigbeeNode::relationship() const
return m_relationship;
}
Zigbee::ZigbeeProfile ZigbeeNode::profile() const
{
return m_profile;
}
quint16 ZigbeeNode::manufacturerCode() const
{
return m_manufacturerCode;
}
quint16 ZigbeeNode::deviceId() const
{
return m_deviceId;
}
bool ZigbeeNode::complexDescriptorAvailable() const
{
return m_complexDescriptorAvailable;
@ -117,35 +117,6 @@ quint8 ZigbeeNode::maximumBufferSize() const
return m_maximumBufferSize;
}
QList<ZigbeeCluster *> ZigbeeNode::inputClusters() const
{
return m_inputClusters.values();
}
ZigbeeCluster *ZigbeeNode::getInputCluster(Zigbee::ClusterId clusterId) const
{
return m_inputClusters.value(clusterId);
}
bool ZigbeeNode::hasInputCluster(Zigbee::ClusterId clusterId) const
{
return m_inputClusters.keys().contains(clusterId);
}
QList<ZigbeeCluster *> ZigbeeNode::outputClusters() const
{
return m_outputClusters.values();
}
bool ZigbeeNode::hasOutputCluster(Zigbee::ClusterId clusterId) const
{
return m_outputClusters.keys().contains(clusterId);
}
ZigbeeCluster *ZigbeeNode::getOutputCluster(Zigbee::ClusterId clusterId) const
{
return m_outputClusters.value(clusterId);
}
bool ZigbeeNode::isPrimaryTrustCenter() const
{
@ -308,139 +279,241 @@ void ZigbeeNode::setExtendedAddress(const ZigbeeAddress &extendedAddress)
m_extendedAddress = extendedAddress;
}
void ZigbeeNode::setEndPoint(quint8 endPoint)
void ZigbeeNode::setEndPoints(QList<quint8> endPoints)
{
m_endPoint = endPoint;
m_endPoints = endPoints;
}
void ZigbeeNode::setNodeType(ZigbeeNode::NodeType nodeType)
QByteArray ZigbeeNode::nodeDescriptorRawData() const
{
m_nodeType = nodeType;
return m_nodeDescriptorRawData;
}
void ZigbeeNode::setFrequencyBand(ZigbeeNode::FrequencyBand frequencyBand)
void ZigbeeNode::setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData)
{
m_frequencyBand = frequencyBand;
}
m_nodeDescriptorRawData = nodeDescriptorRawData;
void ZigbeeNode::setRelationship(ZigbeeNode::Relationship relationship)
{
m_relationship = relationship;
}
// Parse the raw data
quint8 sequenceNumber = 0;
quint8 status = 0;
quint16 shortAddress = 0;
quint16 manufacturerCode = 0;
quint16 maximalRxSize = 0;
quint16 maximalTxSize = 0;
quint16 serverMask = 0;
quint8 descriptorFlag = 0;
quint8 macFlags = 0;
quint8 maxBufferSize = 0;
quint16 bitField = 0;
void ZigbeeNode::setZigbeeProfile(Zigbee::ZigbeeProfile profile)
{
m_profile = profile;
}
QDataStream stream(&m_nodeDescriptorRawData, QIODevice::ReadOnly);
stream >> sequenceNumber;
stream >> status;
stream >> shortAddress;
stream >> manufacturerCode;
stream >> maximalRxSize;
stream >> maximalTxSize;
stream >> serverMask;
stream >> descriptorFlag;
stream >> macFlags;
stream >> maxBufferSize;
stream >> bitField;
void ZigbeeNode::setManufacturerCode(quint16 manufacturerCode)
{
// Set node data
m_manufacturerCode = manufacturerCode;
m_maximumRxSize = maximalRxSize;
m_maximumTxSize = maximalTxSize;
m_maximumBufferSize = maxBufferSize;
setServerMask(serverMask);
setMacCapabilitiesFlag(macFlags);
setDescriptorFlag(descriptorFlag);
// Parse bit field
// 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
m_nodeType = NodeTypeCoordinator;
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
m_nodeType = NodeTypeRouter;
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) {
m_nodeType = NodeTypeEndDevice;
}
m_complexDescriptorAvailable = (bitField >> 3) & 0x0001;
m_userDescriptorAvailable = (bitField >> 4) & 0x0001;
qCDebug(dcZigbeeNode()) << "Node descriptor:";
qCDebug(dcZigbeeNode()) << " Node type:" << nodeType();
qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
qCDebug(dcZigbeeNode()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbeeNode()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
qCDebug(dcZigbeeNode()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(maximumRxSize());
qCDebug(dcZigbeeNode()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(maximumTxSize());
qCDebug(dcZigbeeNode()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maximumBufferSize());
qCDebug(dcZigbeeNode()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
qCDebug(dcZigbeeNode()) << " Primary Trust center:" << isPrimaryTrustCenter();
qCDebug(dcZigbeeNode()) << " Backup Trust center:" << isBackupTrustCenter();
qCDebug(dcZigbeeNode()) << " Primary Binding cache:" << isPrimaryBindingCache();
qCDebug(dcZigbeeNode()) << " Backup Binding cache:" << isBackupBindingCache();
qCDebug(dcZigbeeNode()) << " Primary Discovery cache:" << isPrimaryDiscoveryCache();
qCDebug(dcZigbeeNode()) << " Backup Discovery cache:" << isBackupDiscoveryCache();
qCDebug(dcZigbeeNode()) << " Network Manager:" << isNetworkManager();
qCDebug(dcZigbeeNode()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag);
qCDebug(dcZigbeeNode()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable();
qCDebug(dcZigbeeNode()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable();
qCDebug(dcZigbeeNode()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags);
qCDebug(dcZigbeeNode()) << " Alternate PAN coordinator:" << alternatePanCoordinator();
qCDebug(dcZigbeeNode()) << " Device type:" << deviceType();
qCDebug(dcZigbeeNode()) << " Power source flag main power:" << powerSourceFlagMainPower();
qCDebug(dcZigbeeNode()) << " Receiver on when idle:" << receiverOnWhenIdle();
qCDebug(dcZigbeeNode()) << " Security capability:" << securityCapability();
qCDebug(dcZigbeeNode()) << " Allocate address:" << allocateAddress();
qCDebug(dcZigbeeNode()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField);
qCDebug(dcZigbeeNode()) << " Complex desciptor available:" << complexDescriptorAvailable();
qCDebug(dcZigbeeNode()) << " User desciptor available:" << userDescriptorAvailable();
}
void ZigbeeNode::setDeviceId(quint16 deviceId)
quint16 ZigbeeNode::serverMask() const
{
m_deviceId = deviceId;
}
void ZigbeeNode::setMaximumRxSize(quint16 size)
{
m_maximumRxSize = size;
}
void ZigbeeNode::setMaximumTxSize(quint16 size)
{
m_maximumTxSize = size;
}
void ZigbeeNode::setMaximumBufferSize(quint8 size)
{
m_maximumBufferSize = size;
return m_serverMask;
}
void ZigbeeNode::setServerMask(quint16 serverMask)
{
m_isPrimaryTrustCenter = ((serverMask >> 0) & 0x0001);
m_isBackupTrustCenter = ((serverMask >> 1) & 0x0001);
m_isPrimaryBindingCache = ((serverMask >> 2) & 0x0001);
m_isBackupBindingCache = ((serverMask >> 3) & 0x0001);
m_isPrimaryDiscoveryCache = ((serverMask >> 4) & 0x0001);
m_isBackupDiscoveryCache = ((serverMask >> 5) & 0x0001);
m_isNetworkManager = ((serverMask >> 6) & 0x0001);
m_serverMask = serverMask;
m_isPrimaryTrustCenter = ((m_serverMask >> 0) & 0x0001);
m_isBackupTrustCenter = ((m_serverMask >> 1) & 0x0001);
m_isPrimaryBindingCache = ((m_serverMask >> 2) & 0x0001);
m_isBackupBindingCache = ((m_serverMask >> 3) & 0x0001);
m_isPrimaryDiscoveryCache = ((m_serverMask >> 4) & 0x0001);
m_isBackupDiscoveryCache = ((m_serverMask >> 5) & 0x0001);
m_isNetworkManager = ((m_serverMask >> 6) & 0x0001);
}
void ZigbeeNode::setComplexDescriptorAvailable(bool complexDescriptorAvailable)
quint8 ZigbeeNode::macCapabilitiesFlag() const
{
m_complexDescriptorAvailable = complexDescriptorAvailable;
return m_macCapabilitiesFlag;
}
void ZigbeeNode::setUserDescriptorAvailable(bool userDescriptorAvailable)
void ZigbeeNode::setMacCapabilitiesFlag(quint8 macFlag)
{
m_userDescriptorAvailable = userDescriptorAvailable;
}
void ZigbeeNode::setMacCapabilitiesFlag(quint16 macFlag)
{
// Parse MAC capabilities
m_alternatePanCoordinator = ((macFlag >> 0) & 0x01);
if (((macFlag >> 1) & 0x01)) {
m_macCapabilitiesFlag = macFlag;
m_alternatePanCoordinator = ((m_macCapabilitiesFlag >> 0) & 0x01);
if (((m_macCapabilitiesFlag >> 1) & 0x01)) {
m_deviceType = DeviceTypeFullFunction;
} else {
m_deviceType = DeviceTypeReducedFunction;
}
m_powerSourceFlagMainPower = ((macFlag >> 2) & 0x01);
m_receiverOnWhenIdle = ((macFlag >> 3) & 0x01);
m_securityCapability = ((macFlag >> 6) & 0x01);
m_allocateAddress = ((macFlag >> 7) & 0x01);
m_powerSourceFlagMainPower = ((m_macCapabilitiesFlag >> 2) & 0x01);
m_receiverOnWhenIdle = ((m_macCapabilitiesFlag >> 3) & 0x01);
m_securityCapability = ((m_macCapabilitiesFlag >> 6) & 0x01);
m_allocateAddress = ((m_macCapabilitiesFlag >> 7) & 0x01);
}
void ZigbeeNode::setDescriptorFlag(quint8 descriptorFlag)
{
m_extendedActiveEndpointListAvailable = ((descriptorFlag >> 0) & 0x01);
m_extendedSimpleDescriptorListAvailable = ((descriptorFlag >> 1) & 0x01);
m_descriptorFlag = descriptorFlag;
m_extendedActiveEndpointListAvailable = ((m_descriptorFlag >> 0) & 0x01);
m_extendedSimpleDescriptorListAvailable = ((m_descriptorFlag >> 1) & 0x01);
}
void ZigbeeNode::setPowerMode(ZigbeeNode::PowerMode powerMode)
quint16 ZigbeeNode::powerDescriptorFlag() const
{
m_powerMode = powerMode;
return m_powerDescriptorFlag;
}
void ZigbeeNode::setPowerSource(ZigbeeNode::PowerSource powerSource)
void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag)
{
m_powerSource = powerSource;
}
m_powerDescriptorFlag = powerDescriptorFlag;
void ZigbeeNode::setAvailablePowerSources(QList<ZigbeeNode::PowerSource> availablePowerSources)
{
m_availablePowerSources = availablePowerSources;
}
// Bit 0 - 3 Power mode
// 0000: Receiver configured according to “Receiver on when idle” MAC flag in the Node Descriptor
// 0001: Receiver switched on periodically
// 0010: Receiver switched on when stimulated, e.g. by pressing a button
m_powerMode = PowerModeAlwaysOn;
if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 1)) {
m_powerMode = PowerModeAlwaysOn;
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 1)) {
m_powerMode = PowerModeOnPeriodically;
} else if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 0) && ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 1)) {
m_powerMode = PowerModeOnWhenStimulated;
}
// Bit 4 - 7 Available power sources
// Bit 0: Permanent mains supply
// Bit 1: Rechargeable battery
// Bit 2: Disposable battery
// Bit 4: Reserved
m_availablePowerSources.clear();
if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 4)) {
m_availablePowerSources.append(PowerSourcePermanentMainSupply);
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 5)) {
m_availablePowerSources.append(PowerSourceRecharchableBattery);
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 6)) {
m_availablePowerSources.append(PowerSourceDisposableBattery);
}
// Bit 8 - 11 Active source: according to the same schema as available power sources
m_powerSource = PowerSourcePermanentMainSupply;
if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 8)) {
m_powerSource = PowerSourcePermanentMainSupply;
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 9)) {
m_powerSource = PowerSourceRecharchableBattery;
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 10)) {
m_powerSource = PowerSourceDisposableBattery;
}
// Bit 12 - 15: Battery level if available
// 0000: Critically low
// 0100: Approximately 33%
// 1000: Approximately 66%
// 1100: Approximately 100% (near fully charged)
m_powerLevel = PowerLevelCriticalLow;
if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) {
m_powerLevel = PowerLevelCriticalLow;
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) {
m_powerLevel = PowerLevelLow;
} else if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) {
m_powerLevel = PowerLevelOk;
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) {
m_powerLevel = PowerLevelFull;
}
qCDebug(dcZigbeeNode()) << "Node power descriptor (" << ZigbeeUtils::convertUint16ToHexString(m_powerDescriptorFlag) << "):";
qCDebug(dcZigbeeNode()) << " Power mode:" << m_powerMode;
qCDebug(dcZigbeeNode()) << " Available power sources:";
foreach (const PowerSource &source, m_availablePowerSources) {
qCDebug(dcZigbeeNode()) << " " << source;
}
qCDebug(dcZigbeeNode()) << " Power source:" << m_powerSource;
qCDebug(dcZigbeeNode()) << " Power level:" << m_powerLevel;
void ZigbeeNode::setPowerLevel(ZigbeeNode::PowerLevel powerLevel)
{
m_powerLevel = powerLevel;
}
void ZigbeeNode::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute)
{
qCDebug(dcZigbeeNode()) << this << "cluster attribute changed" << clusterId << attribute;
ZigbeeCluster *cluster = m_outputClusters.value(clusterId);
// ZigbeeCluster *cluster = m_outputClusters.value(clusterId);
// Note: create the cluster if not there yet
bool clusterCreated = false;
if (!cluster) {
cluster = new ZigbeeCluster(clusterId, this);
qCDebug(dcZigbeeNode()) << "Created cluster" << cluster;
connect(cluster, &ZigbeeCluster::attributeChanged, this, &ZigbeeNode::onClusterAttributeChanged);
m_outputClusters.insert(clusterId, cluster);
clusterCreated = true;
}
// // Note: create the cluster if not there yet
// bool clusterCreated = false;
// if (!cluster) {
// cluster = new ZigbeeCluster(clusterId, this);
// qCDebug(dcZigbeeNode()) << "Created cluster" << cluster;
// connect(cluster, &ZigbeeCluster::attributeChanged, this, &ZigbeeNode::onClusterAttributeChanged);
// m_outputClusters.insert(clusterId, cluster);
// clusterCreated = true;
// }
// Set the attribute if valid
if (attribute.isValid())
cluster->setAttribute(attribute);
// // Set the attribute if valid
// if (attribute.isValid())
// cluster->setAttribute(attribute);
if (clusterCreated)
emit clusterAdded(cluster);
// if (clusterCreated)
// emit clusterAdded(cluster);
}
@ -478,12 +551,12 @@ void ZigbeeNode::onClusterAttributeChanged(const ZigbeeClusterAttribute &attribu
// data = reply->additionalMessage().data().mid(5, length);
// }
// qCDebug(dcZigbeeNetwork()) << "User descriptor:";
// qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
// qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
// qCDebug(dcZigbeeNetwork()) << " Attribute address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress);
// qCDebug(dcZigbeeNetwork()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
// qCDebug(dcZigbeeNetwork()) << " Data:" << data;
// qCDebug(dcZigbeeNode()) << "User descriptor:";
// qCDebug(dcZigbeeNode()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
// qCDebug(dcZigbeeNode()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
// qCDebug(dcZigbeeNode()) << " Attribute address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress);
// qCDebug(dcZigbeeNode()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
// qCDebug(dcZigbeeNode()) << " Data:" << data;
//}
//void ZigbeeNode::onToggleFinished()
@ -506,6 +579,17 @@ void ZigbeeNode::onClusterAttributeChanged(const ZigbeeClusterAttribute &attribu
QDebug operator<<(QDebug debug, ZigbeeNode *node)
{
debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress()) << ", " << node->extendedAddress().toString() << ") ";
debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress());
debug.nospace().noquote() << ", " << node->extendedAddress().toString();
// debug.nospace().noquote() << ", End points: ";
// for (int i = 0; i < node->endPoints().count(); i++) {
// debug.nospace().noquote() << ZigbeeUtils::convertByteToHexString(node->endPoints().at(i));
// if (i != node->endPoints().count() - 1 && node->endPoints().count() > 1) {
// debug.nospace().noquote() << ", ";
// }
// }
debug.nospace().noquote() << ") ";
return debug;
}

View File

@ -103,15 +103,13 @@ public:
quint16 shortAddress() const;
ZigbeeAddress extendedAddress() const;
quint8 endPoint() const;
QList<quint8> endPoints() const;
// Information from node descriptor
NodeType nodeType() const;
FrequencyBand frequencyBand() const;
Relationship relationship() const;
Zigbee::ZigbeeProfile profile() const;
quint16 manufacturerCode() const;
quint16 deviceId() const;
bool complexDescriptorAvailable() const;
bool userDescriptorAvailable() const;
@ -120,14 +118,6 @@ public:
quint16 maximumTxSize() const;
quint8 maximumBufferSize() const;
QList<ZigbeeCluster *> inputClusters() const;
ZigbeeCluster *getInputCluster(Zigbee::ClusterId clusterId) const;
bool hasInputCluster(Zigbee::ClusterId clusterId) const;
QList<ZigbeeCluster *> outputClusters() const;
ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const;
bool hasOutputCluster(Zigbee::ClusterId clusterId) const;
// Server Mask
bool isPrimaryTrustCenter() const;
bool isBackupTrustCenter() const;
@ -160,19 +150,16 @@ private:
bool m_connected = false;
State m_state = StateUninitialized;
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_inputClusters;
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_outputClusters;
quint16 m_shortAddress = 0;
ZigbeeAddress m_extendedAddress;
quint8 m_endPoint = 1;
QList<quint8> m_endPoints;
// Node descriptor information
QByteArray m_nodeDescriptorRawData;
NodeType m_nodeType = NodeTypeRouter;
FrequencyBand m_frequencyBand = FrequencyBand2400Mhz;
Relationship m_relationship = Parent;
Zigbee::ZigbeeProfile m_profile;
quint16 m_manufacturerCode = 0;
quint16 m_deviceId = 0;
bool m_complexDescriptorAvailable = false;
bool m_userDescriptorAvailable = false;
@ -182,6 +169,7 @@ private:
quint8 m_maximumBufferSize = 0;
// Server Mask
quint16 m_serverMask = 0;
bool m_isPrimaryTrustCenter = false;
bool m_isBackupTrustCenter = false;
bool m_isPrimaryBindingCache = false;
@ -191,12 +179,14 @@ private:
bool m_isNetworkManager = false;
// Power information
quint16 m_powerDescriptorFlag = 0;
PowerMode m_powerMode;
PowerSource m_powerSource;
QList<PowerSource> m_availablePowerSources;
PowerLevel m_powerLevel;
// Mac capabilities flag
quint8 m_macCapabilitiesFlag = 0;
bool m_alternatePanCoordinator = false;
DeviceType m_deviceType = DeviceTypeFullFunction;
bool m_powerSourceFlagMainPower = false;
@ -205,38 +195,35 @@ private:
bool m_allocateAddress = false;
// Descriptor capability
quint8 m_descriptorFlag = 0;
bool m_extendedActiveEndpointListAvailable = false;
bool m_extendedSimpleDescriptorListAvailable = false;
protected:
private:
void setState(State state);
void setConnected(bool connected);
void setShortAddress(const quint16 &shortAddress);
void setExtendedAddress(const ZigbeeAddress &extendedAddress);
void setEndPoint(quint8 endPoint);
void setEndPoints(QList<quint8> endPoints);
void setNodeType(NodeType nodeType);
void setFrequencyBand(FrequencyBand frequencyBand);
void setRelationship(Relationship relationship);
void setZigbeeProfile(Zigbee::ZigbeeProfile profile);
void setManufacturerCode(quint16 manufacturerCode);
void setDeviceId(quint16 deviceType);
void setMaximumRxSize(quint16 size);
void setMaximumTxSize(quint16 size);
void setMaximumBufferSize(quint8 size);
// Note: node descriptor properties (raw data for settings)
QByteArray nodeDescriptorRawData() const;
void setNodeDescriptorRawData(const QByteArray nodeDescriptorRawData);
quint16 serverMask() const;
void setServerMask(quint16 serverMask);
void setComplexDescriptorAvailable(bool complexDescriptorAvailable);
void setUserDescriptorAvailable(bool userDescriptorAvailable);
void setMacCapabilitiesFlag(quint16 macFlag);
// MAC capability raw data flag for settings
quint8 macCapabilitiesFlag() const;
void setMacCapabilitiesFlag(quint8 macFlag);
quint8 descriptorFlag() const;
void setDescriptorFlag(quint8 descriptorFlag);
void setPowerMode(PowerMode powerMode);
void setPowerSource(PowerSource powerSource);
void setAvailablePowerSources(QList<PowerSource> availablePowerSources);
void setPowerLevel(PowerLevel powerLevel);
// Power decriptor data
quint16 powerDescriptorFlag() const;
void setPowerDescriptorFlag(quint16 powerDescriptorFlag);
// Cluster commands
void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute());

View File

@ -0,0 +1,64 @@
#include "zigbeenodeendpoint.h"
ZigbeeNodeEndpoint::ZigbeeNodeEndpoint(quint8 endpoint, QObject *parent) :
QObject(parent),
m_endpoint(endpoint)
{
}
quint8 ZigbeeNodeEndpoint::endpoint() const
{
return m_endpoint;
}
Zigbee::ZigbeeProfile ZigbeeNodeEndpoint::profile() const
{
return m_profile;
}
void ZigbeeNodeEndpoint::setProfile(Zigbee::ZigbeeProfile profile)
{
m_profile = profile;
}
quint16 ZigbeeNodeEndpoint::deviceId() const
{
return m_deviceId;
}
void ZigbeeNodeEndpoint::setDeviceId(quint16 deviceId)
{
m_deviceId = deviceId;
}
QList<ZigbeeCluster *> ZigbeeNodeEndpoint::inputClusters() const
{
return m_inputClusters.values();
}
ZigbeeCluster *ZigbeeNodeEndpoint::getInputCluster(Zigbee::ClusterId clusterId) const
{
return m_inputClusters.value(clusterId);
}
bool ZigbeeNodeEndpoint::hasInputCluster(Zigbee::ClusterId clusterId) const
{
return m_inputClusters.keys().contains(clusterId);
}
QList<ZigbeeCluster *> ZigbeeNodeEndpoint::outputClusters() const
{
return m_outputClusters.values();
}
bool ZigbeeNodeEndpoint::hasOutputCluster(Zigbee::ClusterId clusterId) const
{
return m_outputClusters.keys().contains(clusterId);
}
ZigbeeCluster *ZigbeeNodeEndpoint::getOutputCluster(Zigbee::ClusterId clusterId) const
{
return m_outputClusters.value(clusterId);
}

View File

@ -0,0 +1,46 @@
#ifndef ZIGBEENODEENDPOINT_H
#define ZIGBEENODEENDPOINT_H
#include <QObject>
#include "zigbee.h"
#include "zigbeecluster.h"
class ZigbeeNodeEndpoint : public QObject
{
Q_OBJECT
public:
explicit ZigbeeNodeEndpoint(quint8 endpoint, QObject *parent = nullptr);
quint8 endpoint() const;
Zigbee::ZigbeeProfile profile() const;
void setProfile(Zigbee::ZigbeeProfile profile);
quint16 deviceId() const;
void setDeviceId(quint16 deviceId);
quint8 deviceVersion() const;
void setDeviceVersion(quint8 deviceVersion);
QList<ZigbeeCluster *> inputClusters() const;
ZigbeeCluster *getInputCluster(Zigbee::ClusterId clusterId) const;
bool hasInputCluster(Zigbee::ClusterId clusterId) const;
QList<ZigbeeCluster *> outputClusters() const;
ZigbeeCluster *getOutputCluster(Zigbee::ClusterId clusterId) const;
bool hasOutputCluster(Zigbee::ClusterId clusterId) const;
private:
quint8 m_endpoint = 0;
Zigbee::ZigbeeProfile m_profile = Zigbee::ZigbeeProfileLightLink;
quint16 m_deviceId = 0;
quint8 m_deviceVersion = 0;
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_inputClusters;
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_outputClusters;
signals:
};
#endif // ZIGBEENODEENDPOINT_H

View File

@ -120,6 +120,15 @@ QString ZigbeeUtils::convertUint16ToHexString(const quint16 &value)
return QString("0x%1").arg(convertByteArrayToHexString(data).remove(" ").remove("0x"));
}
QString ZigbeeUtils::convertUint32ToHexString(const quint32 &value)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << value;
return QString("0x%1").arg(convertByteArrayToHexString(data).remove(" ").remove("0x"));
}
QString ZigbeeUtils::convertUint64ToHexString(const quint64 &value)
{
QByteArray data;
@ -160,6 +169,7 @@ QString ZigbeeUtils::profileIdToString(const Zigbee::ZigbeeProfile &profileId)
quint64 ZigbeeUtils::generateRandomPanId()
{
// Note: the PAN ID has to be between 0x0000 and 0x3fff
qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
return static_cast<quint64>((ULLONG_MAX - 0) * (qrand()/static_cast<double>(RAND_MAX)));
return static_cast<quint64>(rand() % (0x3fff - 1) + 1);
}

View File

@ -52,6 +52,7 @@ public:
static QString convertByteToHexString(const quint8 &byte);
static QString convertByteArrayToHexString(const QByteArray &byteArray);
static QString convertUint16ToHexString(const quint16 &value);
static QString convertUint32ToHexString(const quint32 &value);
static QString convertUint64ToHexString(const quint64 &value);
// Enum prittify print methods