Make basic network start working

This commit is contained in:
Simon Stürz 2019-05-09 18:39:10 +02:00
parent a8c1fe9b9f
commit 128763b5cc
24 changed files with 1598 additions and 1038 deletions

BIN
docs/JN-UG-3113.pdf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -3,11 +3,13 @@
#include "zigbeeutils.h" #include "zigbeeutils.h"
ZigbeeInterface::ZigbeeInterface(QObject *parent) : ZigbeeInterface::ZigbeeInterface(QObject *parent) :
QObject(parent), QObject(parent)
m_serialPort(nullptr),
m_readingState(WaitForStart)
{ {
m_reconnectTimer = new QTimer(this);
m_reconnectTimer->setSingleShot(true);
m_reconnectTimer->setInterval(5000);
connect(m_reconnectTimer, &QTimer::timeout, this, &ZigbeeInterface::onReconnectTimeout);
} }
ZigbeeInterface::~ZigbeeInterface() ZigbeeInterface::~ZigbeeInterface()
@ -56,13 +58,24 @@ void ZigbeeInterface::streamByte(quint8 byte, bool specialCharacter)
byte ^= 0x10; byte ^= 0x10;
} }
qCDebug(dcZigbeeInterfaceTraffic()) << "[out]" << ZigbeeUtils::convertByteToHexString(byte); qCDebug(dcZigbeeInterfaceTraffic()) << "[out]" << ZigbeeUtils::convertByteToHexString(byte);
if (m_serialPort->write(QByteArray(1, (char)byte)) < 0) { if (m_serialPort->write(QByteArray(1, static_cast<char>(byte))) < 0) {
qCWarning(dcZigbeeInterface()) << "Could not stream byte" << ZigbeeUtils::convertByteToHexString(byte); qCWarning(dcZigbeeInterface()) << "Could not stream byte" << ZigbeeUtils::convertByteToHexString(byte);
} }
m_serialPort->flush(); m_serialPort->flush();
} }
void ZigbeeInterface::setAvailable(bool available)
{
if (m_available == available)
return;
m_available = available;
emit availableChanged(m_available);
}
void ZigbeeInterface::setReadingState(const ZigbeeInterface::ReadingState &state) void ZigbeeInterface::setReadingState(const ZigbeeInterface::ReadingState &state)
{ {
if (m_readingState == state) if (m_readingState == state)
@ -72,6 +85,19 @@ void ZigbeeInterface::setReadingState(const ZigbeeInterface::ReadingState &state
qCDebug(dcZigbeeInterfaceTraffic()) << m_readingState; qCDebug(dcZigbeeInterfaceTraffic()) << m_readingState;
} }
void ZigbeeInterface::onReconnectTimeout()
{
if (m_serialPort && !m_serialPort->isOpen()) {
if (!m_serialPort->open(QSerialPort::ReadWrite)) {
setAvailable(false);
m_reconnectTimer->start();
} else {
qCDebug(dcZigbeeInterface()) << "The controller showed up again.";
setAvailable(true);
}
}
}
void ZigbeeInterface::onReadyRead() void ZigbeeInterface::onReadyRead()
{ {
QByteArray data = m_serialPort->readAll(); QByteArray data = m_serialPort->readAll();
@ -159,8 +185,11 @@ void ZigbeeInterface::onReadyRead()
void ZigbeeInterface::onError(const QSerialPort::SerialPortError &error) void ZigbeeInterface::onError(const QSerialPort::SerialPortError &error)
{ {
if (error != QSerialPort::NoError) { if (error != QSerialPort::NoError && m_serialPort->isOpen()) {
qCWarning(dcZigbeeInterface()) << "Serial port error:" << error << m_serialPort->errorString(); qCCritical(dcZigbeeInterface()) << "Serial port error:" << error << m_serialPort->errorString();
m_reconnectTimer->start();
m_serialPort->close();
setAvailable(false);
} }
} }
@ -171,6 +200,8 @@ bool ZigbeeInterface::enable(const QString &serialPort, qint32 baudrate)
m_serialPort = nullptr; m_serialPort = nullptr;
} }
setAvailable(false);
m_serialPort = new QSerialPort(serialPort, this); m_serialPort = new QSerialPort(serialPort, this);
m_serialPort->setBaudRate(baudrate); m_serialPort->setBaudRate(baudrate);
m_serialPort->setDataBits(QSerialPort::Data8); m_serialPort->setDataBits(QSerialPort::Data8);
@ -182,12 +213,12 @@ bool ZigbeeInterface::enable(const QString &serialPort, qint32 baudrate)
if (!m_serialPort->open(QSerialPort::ReadWrite)) { if (!m_serialPort->open(QSerialPort::ReadWrite)) {
qCWarning(dcZigbeeInterface()) << "Could not open serial port" << serialPort << baudrate; qCWarning(dcZigbeeInterface()) << "Could not open serial port" << serialPort << baudrate;
delete m_serialPort; m_reconnectTimer->start();
m_serialPort = nullptr;
return false; return false;
} }
qCDebug(dcZigbeeInterface()) << "Interface enabled successfully on" << serialPort; qCDebug(dcZigbeeInterface()) << "Interface enabled successfully on" << serialPort;
setAvailable(true);
return true; return true;
} }
@ -208,7 +239,6 @@ void ZigbeeInterface::sendMessage(const ZigbeeInterfaceMessage &message)
{ {
quint16 messageTypeValue = static_cast<quint16>(message.messageType()); quint16 messageTypeValue = static_cast<quint16>(message.messageType());
quint16 lengthValue = static_cast<quint16>(message.data().count()); quint16 lengthValue = static_cast<quint16>(message.data().count());
quint8 crcValue = calculateCrc(messageTypeValue, lengthValue, message.data()); quint8 crcValue = calculateCrc(messageTypeValue, lengthValue, message.data());
qCDebug(dcZigbeeInterface()) << "-->" << message << "|" << "crc:" << ZigbeeUtils::convertByteToHexString(crcValue) << ", length:" << ZigbeeUtils::convertUint16ToHexString(lengthValue); qCDebug(dcZigbeeInterface()) << "-->" << message << "|" << "crc:" << ZigbeeUtils::convertByteToHexString(crcValue) << ", length:" << ZigbeeUtils::convertUint16ToHexString(lengthValue);
@ -221,7 +251,7 @@ void ZigbeeInterface::sendMessage(const ZigbeeInterfaceMessage &message)
streamByte(crcValue); streamByte(crcValue);
for (int i = 0; i < message.data().count(); i++) { for (int i = 0; i < message.data().count(); i++) {
streamByte(message.data().at(i)); streamByte(static_cast<quint8>(message.data().at(i)));
} }
streamByte(0x03, true); streamByte(0x03, true);
} }

View File

@ -2,6 +2,7 @@
#define ZIGBEEINTERFACE_H #define ZIGBEEINTERFACE_H
#include <QObject> #include <QObject>
#include <QTimer>
#include <QSerialPort> #include <QSerialPort>
#include "zigbee.h" #include "zigbee.h"
@ -29,11 +30,13 @@ public:
QString serialPort() const; QString serialPort() const;
private: private:
QSerialPort *m_serialPort; QTimer *m_reconnectTimer = nullptr;
QSerialPort *m_serialPort = nullptr;
QByteArray m_messageBuffer; QByteArray m_messageBuffer;
bool m_available = false;
// Message parsing // Message parsing
ReadingState m_readingState; ReadingState m_readingState = WaitForStart;
quint8 m_crcValue; quint8 m_crcValue;
quint8 m_currentValue; quint8 m_currentValue;
quint16 m_messageTypeValue; quint16 m_messageTypeValue;
@ -44,14 +47,15 @@ private:
quint8 calculateCrc(const quint16 &messageTypeValue, const quint16 &lenghtValue, const QByteArray &data); quint8 calculateCrc(const quint16 &messageTypeValue, const quint16 &lenghtValue, const QByteArray &data);
void streamByte(quint8 byte, bool specialCharacter = false); void streamByte(quint8 byte, bool specialCharacter = false);
void setAvailable(bool available);
void setReadingState(const ReadingState & state); void setReadingState(const ReadingState & state);
signals: signals:
void availableChanged(const bool &available); void availableChanged(bool available);
void messageReceived(const ZigbeeInterfaceMessage &message); void messageReceived(const ZigbeeInterfaceMessage &message);
private slots: private slots:
void onReconnectTimeout();
void onReadyRead(); void onReadyRead();
void onError(const QSerialPort::SerialPortError &error); void onError(const QSerialPort::SerialPortError &error);

View File

@ -10,10 +10,13 @@ SOURCES += \
interface/zigbeeinterfacemessage.cpp \ interface/zigbeeinterfacemessage.cpp \
interface/zigbeeinterfacerequest.cpp \ interface/zigbeeinterfacerequest.cpp \
interface/zigbeeinterfacereply.cpp \ interface/zigbeeinterfacereply.cpp \
nxp/nxpzigbeenetworkmanager.cpp \
zigbeenetwork.cpp \
zigbeenetworkmanager.cpp \ zigbeenetworkmanager.cpp \
zigbee.cpp \ zigbee.cpp \
loggingcategory.cpp \ loggingcategory.cpp \
zigbeebridgecontroller.cpp \ zigbeebridgecontroller.cpp \
zigbeesecurityconfiguration.cpp \
zigbeeutils.cpp \ zigbeeutils.cpp \
zigbeenode.cpp \ zigbeenode.cpp \
zigbeeaddress.cpp \ zigbeeaddress.cpp \
@ -23,10 +26,13 @@ HEADERS += \
interface/zigbeeinterfacemessage.h \ interface/zigbeeinterfacemessage.h \
interface/zigbeeinterfacerequest.h \ interface/zigbeeinterfacerequest.h \
interface/zigbeeinterfacereply.h \ interface/zigbeeinterfacereply.h \
nxp/nxpzigbeenetworkmanager.h \
zigbeenetwork.h \
zigbeenetworkmanager.h \ zigbeenetworkmanager.h \
zigbee.h \ zigbee.h \
loggingcategory.h \ loggingcategory.h \
zigbeebridgecontroller.h \ zigbeebridgecontroller.h \
zigbeesecurityconfiguration.h \
zigbeeutils.h \ zigbeeutils.h \
zigbeenode.h \ zigbeenode.h \
zigbeeaddress.h \ zigbeeaddress.h \

View File

@ -1,6 +1,6 @@
#include "loggingcategory.h" #include "loggingcategory.h"
Q_LOGGING_CATEGORY(dcZigbee, "Zigbee") Q_LOGGING_CATEGORY(dcZigbeeNetwork, "ZigbeeNetwork")
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface") Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController") Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic") Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")

View File

@ -4,7 +4,7 @@
#include <QDebug> #include <QDebug>
#include <QLoggingCategory> #include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(dcZigbee) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetwork)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)

View File

@ -0,0 +1,6 @@
#include "nxpzigbeenetworkmanager.h"
NxpZigbeeNetworkManager::NxpZigbeeNetworkManager(QObject *parent) : QObject(parent)
{
}

View File

@ -0,0 +1,17 @@
#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

@ -1,17 +1,15 @@
#include "zigbeebridgecontroller.h" #include "zigbeebridgecontroller.h"
#include "loggingcategory.h" #include "loggingcategory.h"
#include "zigbeeutils.h"
ZigbeeBridgeController::ZigbeeBridgeController(const QString &serialPort, qint32 baudrate, QObject *parent) : #include <QDataStream>
ZigbeeBridgeController::ZigbeeBridgeController(QObject *parent) :
QObject(parent) QObject(parent)
{ {
m_interface = new ZigbeeInterface(this); m_interface = new ZigbeeInterface(this);
connect(m_interface, &ZigbeeInterface::availableChanged, this, &ZigbeeBridgeController::availableChanged);
connect(m_interface, &ZigbeeInterface::messageReceived, this, &ZigbeeBridgeController::onMessageReceived); connect(m_interface, &ZigbeeInterface::messageReceived, this, &ZigbeeBridgeController::onMessageReceived);
if (!m_interface->enable(serialPort, baudrate)) {
qCCritical(dcZigbeeController()) << "Could not enable ZigbeeInterface on" << serialPort;
return;
}
} }
bool ZigbeeBridgeController::available() const bool ZigbeeBridgeController::available() const
@ -19,6 +17,290 @@ bool ZigbeeBridgeController::available() const
return m_interface->available(); return m_interface->available();
} }
ZigbeeInterfaceReply *ZigbeeBridgeController::commandResetController()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeReset, QByteArray()));
request.setDescription("Reset controller");
request.setTimoutIntervall(5000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandErasePersistantData()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeErasePersistentData, QByteArray()));
request.setDescription("Erase persistent data");
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandGetVersion()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeGetVersion, QByteArray()));
request.setDescription("Get version");
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeVersionList);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetExtendedPanId(quint64 extendedPanId)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << extendedPanId;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSetExtendetPanId, data));
request.setDescription("Set extended PAN id " + QString::number(extendedPanId) + " " + ZigbeeUtils::convertUint64ToHexString(extendedPanId));
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetChannelMask(quint32 channelMask)
{
// Note: 10 < value < 27 -> using sinle channel value
// 0x07fff800 select from all channels 11 - 26
// 0x2108800 primary zigbee light link channels 11, 15, 20, 25
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << channelMask;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSetChannelMask, data));
request.setDescription("Set channel mask " + ZigbeeUtils::convertByteArrayToHexString(data));
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetNodeType(ZigbeeNode::NodeType nodeType)
{
quint8 deviceTypeValue = 0;
if (nodeType == ZigbeeNode::NodeTypeEndDevice) {
qCWarning(dcZigbeeController()) << "Set the controller as EndDevice is not allowed. Default to coordinator node type.";
deviceTypeValue = static_cast<quint8>(ZigbeeNode::NodeTypeCoordinator);
} else {
deviceTypeValue = static_cast<quint8>(nodeType);
}
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << deviceTypeValue;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSetDeviceType, data));
switch (nodeType) {
case ZigbeeNode::NodeTypeCoordinator:
request.setDescription("Set device type coordinator");
break;
case ZigbeeNode::NodeTypeRouter:
request.setDescription("Set device type router");
break;
default:
break;
}
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandStartNetwork()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeStartNetwork, QByteArray()));
request.setDescription("Start network");
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNetworkJoinedFormed);
request.setTimoutIntervall(12000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandStartScan()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeStartScan, QByteArray()));
request.setDescription("Start scan");
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNetworkJoinedFormed);
request.setTimoutIntervall(12000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandPermitJoin(quint16 targetAddress, const quint8 advertisingIntervall, bool tcSignificance)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << targetAddress;
stream << advertisingIntervall;
stream << static_cast<quint8>(tcSignificance);
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypePermitJoiningRequest, data));
request.setDescription("Permit joining request on " + ZigbeeUtils::convertUint16ToHexString(targetAddress) + " for " + QString::number(advertisingIntervall) + "[s]");
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandGetPermitJoinStatus()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeGetPermitJoining, QByteArray()));
request.setDescription("Get permit joining status");
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeGetPermitJoiningResponse);
request.setTimoutIntervall(1000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandRequestLinkQuality(quint16 shortAddress)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << shortAddress;
stream << static_cast<quint8>(0);
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeManagementLqiRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeManagementLqiResponse);
request.setDescription("Request link quality request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
request.setTimoutIntervall(5000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandEnableWhiteList()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNetworkWhitelistEnable, QByteArray()));
request.setDescription("Enable whitelist");
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandInitiateTouchLink()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeInitiateTouchlink, QByteArray()));
request.setDescription("Initiate touch link");
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandTouchLinkFactoryReset()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeTouchlinkFactoryReset, QByteArray()));
request.setDescription("Touch link factory reset");
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandNetworkAddressRequest(quint16 targetAddress, quint64 extendedAddress)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << targetAddress;
stream << extendedAddress;
stream << static_cast<quint8>(1);
stream << static_cast<quint8>(0);
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNetworkAdressRequest, data));
request.setDescription("Network address request on " + ZigbeeUtils::convertUint16ToHexString(targetAddress));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNetworkAdressResponse);
request.setTimoutIntervall(1000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandSetSecurityStateAndKey(quint8 keyState, quint8 keySequence, quint8 keyType, const QString &key)
{
// Note: calls ZPS_vAplSecSetInitialSecurityState
// Key state:
// ZPS_ZDO_PRECONFIGURED_LINK_KEY = 3
// This key will be used to encrypt the network key. This is the master or manufacturer key
// ZPS_ZDO_ZLL_LINK_KEY = 4
// This key will be generated by the trust center.
// Key Type:
// ZPS_APS_UNIQUE_LINK_KEY =
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << keyState;
stream << keySequence;
stream << keyType;
stream << QByteArray::fromHex(key.toUtf8());
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSetSecurity, data));
request.setDescription("Set security configuration");
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandAuthenticateDevice(const ZigbeeAddress &ieeeAddress, const QString &key)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << ieeeAddress.toUInt64();
stream << QByteArray::fromHex(key.toUtf8());
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeAuthenticateDeviceRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeAuthenticateDeviceResponse);
request.setDescription(QString("Authenticate device %1").arg(ieeeAddress.toString()));
request.setTimoutIntervall(5000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandNodeDescriptorRequest(quint16 shortAddress)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << shortAddress;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNodeDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNodeDescriptorRsponse);
request.setDescription("Node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
request.setTimoutIntervall(5000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandSimpleDescriptorRequest(quint16 shortAddress, quint8 endpoint)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << shortAddress;
stream << endpoint;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSimpleDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeSimpleDescriptorResponse);
request.setDescription("Simple node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress) + "endpoint " + QString::number(endpoint));
request.setTimoutIntervall(5000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandPowerDescriptorRequest(quint16 shortAddress)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << shortAddress;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypePowerDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypePowerDescriptorResponse);
request.setDescription("Node power descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress));
request.setTimoutIntervall(5000);
return sendRequest(request);
}
ZigbeeInterfaceReply *ZigbeeBridgeController::commandUserDescriptorRequest(quint16 shortAddress, quint16 address)
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << shortAddress;
stream << address;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeUserDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeUserDescriptorResponse);
request.setDescription("Node user descriptor request for " + ZigbeeUtils::convertUint16ToHexString(shortAddress) + " " + ZigbeeUtils::convertUint16ToHexString(address));
request.setTimoutIntervall(5000);
return sendRequest(request);
}
void ZigbeeBridgeController::sendMessage(ZigbeeInterfaceReply *reply) void ZigbeeBridgeController::sendMessage(ZigbeeInterfaceReply *reply)
{ {
if (!reply) if (!reply)
@ -72,6 +354,16 @@ void ZigbeeBridgeController::onReplyTimeout()
} }
bool ZigbeeBridgeController::enable(const QString &serialPort, qint32 baudrate)
{
return m_interface->enable(serialPort, baudrate);
}
void ZigbeeBridgeController::disable()
{
m_interface->disable();
}
ZigbeeInterfaceReply *ZigbeeBridgeController::sendRequest(const ZigbeeInterfaceRequest &request) ZigbeeInterfaceReply *ZigbeeBridgeController::sendRequest(const ZigbeeInterfaceRequest &request)
{ {
// Create Reply // Create Reply

View File

@ -5,6 +5,7 @@
#include <QQueue> #include <QQueue>
#include "zigbee.h" #include "zigbee.h"
#include "zigbeenode.h"
#include "interface/zigbeeinterface.h" #include "interface/zigbeeinterface.h"
#include "interface/zigbeeinterfacereply.h" #include "interface/zigbeeinterfacereply.h"
#include "interface/zigbeeinterfacerequest.h" #include "interface/zigbeeinterfacerequest.h"
@ -14,10 +15,33 @@ class ZigbeeBridgeController : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ZigbeeBridgeController(const QString &serialPort, qint32 baudrate, QObject *parent = nullptr); explicit ZigbeeBridgeController(QObject *parent = nullptr);
bool available() const; bool available() const;
// Direct commands
ZigbeeInterfaceReply *commandResetController();
ZigbeeInterfaceReply *commandErasePersistantData();
ZigbeeInterfaceReply *commandGetVersion();
ZigbeeInterfaceReply *commandSetExtendedPanId(quint64 extendedPanId);
ZigbeeInterfaceReply *commandSetChannelMask(quint32 channelMask = 0x07fff800);
ZigbeeInterfaceReply *commandSetNodeType(ZigbeeNode::NodeType nodeType);
ZigbeeInterfaceReply *commandStartNetwork();
ZigbeeInterfaceReply *commandStartScan();
ZigbeeInterfaceReply *commandPermitJoin(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 180, bool tcSignificance = false);
ZigbeeInterfaceReply *commandGetPermitJoinStatus();
ZigbeeInterfaceReply *commandRequestLinkQuality(quint16 shortAddress);
ZigbeeInterfaceReply *commandEnableWhiteList();
ZigbeeInterfaceReply *commandInitiateTouchLink();
ZigbeeInterfaceReply *commandTouchLinkFactoryReset();
ZigbeeInterfaceReply *commandNetworkAddressRequest(quint16 targetAddress, quint64 extendedAddress);
ZigbeeInterfaceReply *commandSetSecurityStateAndKey(quint8 keyState, quint8 keySequence, quint8 keyType, const QString &key);
ZigbeeInterfaceReply *commandAuthenticateDevice(const ZigbeeAddress &ieeeAddress, const QString &key);
ZigbeeInterfaceReply *commandNodeDescriptorRequest(quint16 shortAddress);
ZigbeeInterfaceReply *commandSimpleDescriptorRequest(quint16 shortAddress, quint8 endpoint);
ZigbeeInterfaceReply *commandPowerDescriptorRequest(quint16 shortAddress);
ZigbeeInterfaceReply *commandUserDescriptorRequest(quint16 shortAddress, quint16 address);
private: private:
ZigbeeInterface *m_interface = nullptr; ZigbeeInterface *m_interface = nullptr;
ZigbeeInterfaceReply *m_currentReply = nullptr; ZigbeeInterfaceReply *m_currentReply = nullptr;
@ -27,6 +51,7 @@ private:
void sendMessage(ZigbeeInterfaceReply *reply); void sendMessage(ZigbeeInterfaceReply *reply);
signals: signals:
void availableChanged(bool available);
void messageReceived(const ZigbeeInterfaceMessage &message); void messageReceived(const ZigbeeInterfaceMessage &message);
private slots: private slots:
@ -34,8 +59,10 @@ private slots:
void onReplyTimeout(); void onReplyTimeout();
public slots: public slots:
ZigbeeInterfaceReply *sendRequest(const ZigbeeInterfaceRequest &request); bool enable(const QString &serialPort, qint32 baudrate);
void disable();
ZigbeeInterfaceReply *sendRequest(const ZigbeeInterfaceRequest &request);
}; };

View File

@ -0,0 +1,143 @@
#include "zigbeenetwork.h"
#include "loggingcategory.h"
ZigbeeNetwork::ZigbeeNetwork(ControllerType controllerType, QObject *parent) :
ZigbeeNode(parent),
m_controllerType(controllerType)
{
}
ZigbeeNetwork::State ZigbeeNetwork::state() const
{
return m_state;
}
ZigbeeNetwork::ControllerType ZigbeeNetwork::controlerType() const
{
return m_controllerType;
}
ZigbeeNetwork::Error ZigbeeNetwork::error() const
{
return m_error;
}
QString ZigbeeNetwork::serialPortName() const
{
return m_serialPortName;
}
void ZigbeeNetwork::setSerialPortName(const QString &serialPortName)
{
m_serialPortName = serialPortName;
}
qint32 ZigbeeNetwork::serialBaudrate() const
{
return m_serialBaudrate;
}
void ZigbeeNetwork::setSerialBaudrate(qint32 baudrate)
{
m_serialBaudrate = baudrate;
}
quint64 ZigbeeNetwork::extendedPanId() const
{
return m_extendedPanId;
}
void ZigbeeNetwork::setExtendedPanId(quint64 extendedPanId)
{
m_extendedPanId = extendedPanId;
}
uint ZigbeeNetwork::channel() const
{
return m_channel;
}
void ZigbeeNetwork::setChannel(uint channel)
{
m_channel = channel;
}
ZigbeeSecurityConfiguration ZigbeeNetwork::securityConfiguration() const
{
return m_securityConfiguration;
}
void ZigbeeNetwork::setSecurityConfiguration(const ZigbeeSecurityConfiguration &securityConfiguration)
{
m_securityConfiguration = securityConfiguration;
}
QList<ZigbeeNode *> ZigbeeNetwork::nodes() const
{
return m_nodes;
}
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(quint16 shortAddress)
{
foreach (ZigbeeNode *node, m_nodes) {
if (node->shortAddress() == shortAddress) {
return node;
}
}
return nullptr;
}
ZigbeeNode *ZigbeeNetwork::getZigbeeNode(ZigbeeAddress address)
{
foreach (ZigbeeNode *node, m_nodes) {
if (node->extendedAddress() == address) {
return node;
}
}
return nullptr;
}
void ZigbeeNetwork::addNode(ZigbeeNode *node)
{
if (m_nodes.contains(node)) {
qCWarning(dcZigbeeNetwork()) << "The node" << node << "has already been added.";
return;
}
m_nodes.append(node);
emit nodeAdded(node);
}
void ZigbeeNetwork::removeNode(ZigbeeNode *node)
{
if (!m_nodes.contains(node)) {
qCWarning(dcZigbeeNetwork()) << "Try to remove node" << node << "but not in the node list.";
return;
}
m_nodes.removeAll(node);
emit nodeRemoved(node);
}
void ZigbeeNetwork::setState(ZigbeeNetwork::State state)
{
if (m_state == state)
return;
qCDebug(dcZigbeeNetwork()) << "State changed" << state;
m_state = state;
emit stateChanged(m_state);
}
void ZigbeeNetwork::setError(ZigbeeNetwork::Error error)
{
if (m_error == error)
return;
if (m_error != ErrorNoError) qCDebug(dcZigbeeNetwork()) << "Error occured" << error;
m_error = error;
emit errorOccured(m_error);
}

View File

@ -0,0 +1,99 @@
#ifndef ZIGBEENETWORK_H
#define ZIGBEENETWORK_H
#include <QObject>
#include "zigbeenode.h"
#include "zigbeesecurityconfiguration.h"
class ZigbeeNetwork : public ZigbeeNode
{
Q_OBJECT
public:
enum ControllerType {
ControlerTypeNxp
};
Q_ENUM(ControllerType)
enum State {
StateDisconnected,
StateStarting,
StateRunning,
StateStopping
};
Q_ENUM(State)
enum Error {
ErrorNoError,
ErrorHardwareUnavailable
};
Q_ENUM(Error)
explicit ZigbeeNetwork(ControllerType controllerType, QObject *parent = nullptr);
State state() const;
ControllerType controlerType() const;
Error error() const;
// Serial port configuration
QString serialPortName() const;
void setSerialPortName(const QString &serialPortName);
qint32 serialBaudrate() const;
void setSerialBaudrate(qint32 baudrate);
// Network configurations
quint64 extendedPanId() const;
void setExtendedPanId(quint64 extendedPanId);
uint channel() const;
void setChannel(uint channel);
ZigbeeSecurityConfiguration securityConfiguration() const;
void setSecurityConfiguration(const ZigbeeSecurityConfiguration &securityConfiguration);
QList<ZigbeeNode *> nodes() const;
ZigbeeNode *getZigbeeNode(quint16 shortAddress);
ZigbeeNode *getZigbeeNode(ZigbeeAddress address);
private:
ControllerType m_controllerType = ControlerTypeNxp;
State m_state = StateDisconnected;
Error m_error = ErrorNoError;
// Serial port configuration
QString m_serialPortName = "/dev/ttyUSB0";
qint32 m_serialBaudrate = 115200;
// Network configurations
quint64 m_extendedPanId = 0;
uint m_channel = 0;
ZigbeeSecurityConfiguration m_securityConfiguration;
ZigbeeNode::NodeType m_nodeType = ZigbeeNode::NodeTypeCoordinator;
QList<ZigbeeNode *> m_nodes;
protected:
void addNode(ZigbeeNode *node);
void removeNode(ZigbeeNode *node);
void setState(State state);
void setError(Error error);
signals:
void nodeAdded(ZigbeeNode *node);
void nodeRemoved(ZigbeeNode *node);
void stateChanged(State state);
void errorOccured(Error error);
public slots:
virtual void startNetwork() = 0;
virtual void stopNetwork() = 0;
};
#endif // ZIGBEENETWORK_H

File diff suppressed because it is too large Load Diff

View File

@ -3,100 +3,77 @@
#include <QObject> #include <QObject>
#include "zigbeenode.h" #include "zigbeenetwork.h"
#include "zigbeeaddress.h" #include "zigbeeaddress.h"
#include "zigbeebridgecontroller.h" #include "zigbeebridgecontroller.h"
#include "zigbeesecurityconfiguration.h"
class ZigbeeNetworkManager : public ZigbeeNode class ZigbeeNetworkManager : public ZigbeeNetwork
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ZigbeeNetworkManager(const int &channel = 0, const QString &serialPort = "/dev/ttyS0", qint32 baudrate = 115200, QObject *parent = nullptr); explicit ZigbeeNetworkManager(QObject *parent = nullptr);
bool isAvailable() const;
QString controllerVersion() const; QString controllerVersion() const;
QString serialPort() const;
QList<ZigbeeNode *> nodeList() const;
quint64 extendedPanId() const;
bool networkRunning() const; bool networkRunning() const;
// Controller methods
void resetController();
void erasePersistentData();
void sendDataManagerAvailableResponse();
void getVersion();
void setExtendedPanId(const quint64 &panId);
void setChannelMask(const quint32 &channelMask = 0x07fff800);
void setDeviceType(const NodeType &deviceType);
void startNetwork();
void startScan();
void permitJoining(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 180, bool tcSignificance = false);
void requestLinkQuality();
void getPermitJoiningStatus();
void enableWhitelist();
void initiateTouchLink();
void touchLinkFactoryReset();
void networkAddressRequest(quint16 targetAddress, quint64 extendedAddress);
void requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile);
void setInitialSecurity(quint8 keyState, quint8 keySequence, quint8 keyType, const QString &key);
void authenticateDevice(const ZigbeeAddress &ieeeAddress);
private: private:
enum StartingState {
StartingStateNone,
StartingStateErase,
StartingStateReset,
StartingStateGetVersion,
StartingStateSetPanId,
StartingStateSetChannel,
StartingStateSetSecurity,
StartingStateStartNetwork,
StartingStateReadeNodeDescriptor,
StartingStateReadSimpleDescriptor,
StartingStateReadPowerDescriptor
};
ZigbeeBridgeController *m_controller = nullptr; ZigbeeBridgeController *m_controller = nullptr;
QString m_serialPort;
QString m_controllerVersion; QString m_controllerVersion;
quint64 m_extendedPanId = 0;
QList<ZigbeeNode *> m_nodeList; StartingState m_startingState = StartingStateNone;
void setStartingState(StartingState state);
bool m_networkRunning = false;
quint64 generateRandomPanId();
void parseNetworkFormed(const QByteArray &data);
signals: signals:
void runningChanged(const bool &running); void runningChanged(const bool &running);
private slots: private slots:
void onMessageReceived(const ZigbeeInterfaceMessage &message); void onMessageReceived(const ZigbeeInterfaceMessage &message);
void onControllerAvailableChanged(bool available);
void loadNetwork(); // Controller command finished slots
void saveNetwork(); void onCommandResetControllerFinished();
void onCommandErasePersistentDataFinished();
void onCommandGetVersionFinished();
void onCommandSetExtendedPanIdFinished();
void onCommandSetChannelMaskFinished();
void onCommandSetDeviceTypeFinished();
void onCommandStartNetworkFinished();
void onCommandStartScanFinished();
void onCommandGetPermitJoiningStatusFinished();
void onCommandPermitJoiningFinished();
void onCommandEnableWhitelistFinished();
// Controller methods finished slots void onCommandNodeDescriptorRequestFinished();
void onResetControllerFinished(); void onCommandSimpleDescriptorRequestFinished();
void onErasePersistentDataFinished(); void onCommandPowerDescriptorRequestFinished();
void onGetVersionFinished();
void onSetExtendedPanIdFinished();
void onSetChannelMaskFinished();
void onSetDeviceTypeFinished();
void onStartNetworkFinished();
void onStartScanFinished();
void onGetPermitJoiningStatusFinished();
void onPermitJoiningFinished();
void onEnableWhitelistFinished();
void onInitiateTouchLinkFinished(); void onCommandInitiateTouchLinkFinished();
void onTouchLinkFactoryResetFinished(); void onCommandTouchLinkFactoryResetFinished();
void onRequestLinkQualityFinished(); void onCommandRequestLinkQualityFinished();
void onRequestMatchDescriptorFinished(); void onCommandRequestMatchDescriptorFinished();
void onSetSecurityFinished(); void onCommandSetSecurityFinished();
void onNetworkAddressRequestFinished(); void onCommandNetworkAddressRequestFinished();
void onAuthenticateDeviceFinished(); void onCommandAuthenticateDeviceFinished();
// Process controller notifications/messages // Process controller notifications/messages
void processNetworkFormed(const ZigbeeInterfaceMessage &message);
void processLoggingMessage(const ZigbeeInterfaceMessage &message); void processLoggingMessage(const ZigbeeInterfaceMessage &message);
void processFactoryNewRestart(const ZigbeeInterfaceMessage &message); void processFactoryNewRestart(const ZigbeeInterfaceMessage &message);
void processNodeClusterList(const ZigbeeInterfaceMessage &message); void processNodeClusterList(const ZigbeeInterfaceMessage &message);
@ -106,6 +83,11 @@ private slots:
void processAttributeReport(const ZigbeeInterfaceMessage &message); void processAttributeReport(const ZigbeeInterfaceMessage &message);
void processLeaveIndication(const ZigbeeInterfaceMessage &message); void processLeaveIndication(const ZigbeeInterfaceMessage &message);
void processRestartProvisioned(const ZigbeeInterfaceMessage &message); void processRestartProvisioned(const ZigbeeInterfaceMessage &message);
public slots:
void startNetwork() override;
void stopNetwork() override;
}; };
#endif // ZIGBEEMANAGER_H #endif // ZIGBEEMANAGER_H

View File

@ -4,6 +4,12 @@
#include <QDataStream> #include <QDataStream>
ZigbeeNode::ZigbeeNode(QObject *parent) :
QObject(parent)
{
}
quint16 ZigbeeNode::shortAddress() const quint16 ZigbeeNode::shortAddress() const
{ {
return m_shortAddress; return m_shortAddress;
@ -14,7 +20,7 @@ ZigbeeAddress ZigbeeNode::extendedAddress() const
return m_extendedAddress; return m_extendedAddress;
} }
int ZigbeeNode::endPoint() const quint8 ZigbeeNode::endPoint() const
{ {
return m_endPoint; return m_endPoint;
} }
@ -29,9 +35,9 @@ ZigbeeNode::FrequencyBand ZigbeeNode::frequencyBand() const
return m_frequencyBand; return m_frequencyBand;
} }
ZigbeeNode::Relationship ZigbeeNode::relationShip() const ZigbeeNode::Relationship ZigbeeNode::relationship() const
{ {
return m_relationShip; return m_relationship;
} }
Zigbee::ZigbeeProfile ZigbeeNode::profile() const Zigbee::ZigbeeProfile ZigbeeNode::profile() const
@ -44,6 +50,31 @@ quint16 ZigbeeNode::manufacturerCode() const
return m_manufacturerCode; return m_manufacturerCode;
} }
bool ZigbeeNode::complexDescriptorAvailable() const
{
return m_complexDescriptorAvailable;
}
bool ZigbeeNode::userDescriptorAvailable() const
{
return m_userDescriptorAvailable;
}
quint16 ZigbeeNode::maximumRxSize() const
{
return m_maximumRxSize;
}
quint16 ZigbeeNode::maximumTxSize() const
{
return m_maximumTxSize;
}
quint8 ZigbeeNode::maximumBufferSize() const
{
return m_maximumBufferSize;
}
ZigbeeNode::PowerMode ZigbeeNode::powerMode() const ZigbeeNode::PowerMode ZigbeeNode::powerMode() const
{ {
return m_powerMode; return m_powerMode;
@ -64,16 +95,9 @@ ZigbeeNode::PowerLevel ZigbeeNode::powerLevel() const
return m_powerLevel; return m_powerLevel;
} }
void ZigbeeNode::init()
{
requestNodeDescription();
requestSimpleNodeDescription();
requestPowerDescriptor();
}
//void ZigbeeNode::identify()
void ZigbeeNode::identify() //{
{
// QByteArray data; // QByteArray data;
// QDataStream stream(&data, QIODevice::WriteOnly); // QDataStream stream(&data, QIODevice::WriteOnly);
// stream << m_shortAddress; // stream << m_shortAddress;
@ -86,98 +110,26 @@ void ZigbeeNode::identify()
// ZigbeeInterfaceReply *reply = controller()->sendRequest(request); // ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
// connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestLinkQuality); // connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestLinkQuality);
} //}
void ZigbeeNode::toggle(int addressMode) //void ZigbeeNode::toggle(int addressMode)
{ //{
QByteArray data; // QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly); // QDataStream stream(&data, QIODevice::WriteOnly);
stream << static_cast<quint8>(addressMode); // adress mode // stream << static_cast<quint8>(addressMode); // adress mode
stream << m_shortAddress; // stream << m_shortAddress;
stream << static_cast<quint8>(1); // source endpoint // stream << static_cast<quint8>(1); // source endpoint
stream << static_cast<quint8>(1); // destination endpoint // stream << static_cast<quint8>(1); // destination endpoint
stream << static_cast<quint8>(2); // command toggle // stream << static_cast<quint8>(2); // command toggle
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeCluserOnOff, data)); // ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeCluserOnOff, data));
request.setDescription("Toggle request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress)); // request.setDescription("Toggle request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
ZigbeeInterfaceReply *reply = controller()->sendRequest(request); // ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onToggleFinished); // connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onToggleFinished);
} //}
void ZigbeeNode::requestNodeDescription()
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << m_shortAddress;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeNodeDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeNodeDescriptorRsponse);
request.setDescription("Node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
request.setTimoutIntervall(5000);
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestNodeDescriptionFinished);
}
void ZigbeeNode::requestSimpleNodeDescription()
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << m_shortAddress;
stream << quint8(1);
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSimpleDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeSimpleDescriptorResponse);
request.setDescription("Simple node descriptor request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
request.setTimoutIntervall(5000);
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestSimpleNodeDescriptionFinished);
}
void ZigbeeNode::requestPowerDescriptor()
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << m_shortAddress;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypePowerDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypePowerDescriptorResponse);
request.setDescription("Node power descriptor request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
request.setTimoutIntervall(5000);
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestPowerDescriptorFinished);
}
void ZigbeeNode::requestUserDescriptor()
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << m_shortAddress;
stream << static_cast<quint16>(0);
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeUserDescriptorRequest, data));
request.setExpectedAdditionalMessageType(Zigbee::MessageTypeUserDescriptorResponse);
request.setDescription("Node user descriptor request for " + ZigbeeUtils::convertUint16ToHexString(m_shortAddress));
request.setTimoutIntervall(5000);
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNode::onRequestUserDescriptorFinished);
}
ZigbeeNode::ZigbeeNode(ZigbeeBridgeController *controller, QObject *parent) :
QObject(parent),
m_controller(controller)
{
}
ZigbeeBridgeController *ZigbeeNode::controller()
{
return m_controller;
}
void ZigbeeNode::setShortAddress(const quint16 &shortAddress) void ZigbeeNode::setShortAddress(const quint16 &shortAddress)
{ {
@ -189,55 +141,53 @@ void ZigbeeNode::setExtendedAddress(const ZigbeeAddress &extendedAddress)
m_extendedAddress = extendedAddress; m_extendedAddress = extendedAddress;
} }
void ZigbeeNode::onRequestNodeDescriptionFinished() void ZigbeeNode::setEndPoint(quint8 endPoint)
{ {
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender()); m_endPoint = endPoint;
reply->deleteLater(); }
if (reply->status() != ZigbeeInterfaceReply::Success) { void ZigbeeNode::setNodeType(ZigbeeNode::NodeType nodeType)
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); {
return; m_nodeType = nodeType;
} }
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; void ZigbeeNode::setFrequencyBand(ZigbeeNode::FrequencyBand frequencyBand)
{
m_frequencyBand = frequencyBand;
}
quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0)); void ZigbeeNode::setRelationship(ZigbeeNode::Relationship relationship)
quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1)); {
m_relationship = relationship;
}
quint16 shortAddress = reply->additionalMessage().data().at(2); void ZigbeeNode::setZigbeeProfile(Zigbee::ZigbeeProfile profile)
shortAddress <<= 8; {
shortAddress |= reply->additionalMessage().data().at(3); m_profile = profile;
}
quint16 manufacturerCode = reply->additionalMessage().data().at(4); void ZigbeeNode::setManufacturerCode(quint16 manufacturerCode)
manufacturerCode <<= 8; {
manufacturerCode |= reply->additionalMessage().data().at(5);
quint16 maximalRxSize = reply->additionalMessage().data().at(6);
maximalRxSize <<= 8;
maximalRxSize |= reply->additionalMessage().data().at(7);
quint16 maximalTxSize = reply->additionalMessage().data().at(8);
maximalTxSize <<= 8;
maximalTxSize |= reply->additionalMessage().data().at(9);
quint16 serverMask = reply->additionalMessage().data().at(10);
serverMask <<= 8;
serverMask |= reply->additionalMessage().data().at(11);
quint8 descriptorFlag = static_cast<quint8>(reply->additionalMessage().data().at(12));
quint8 macFlags = static_cast<quint8>(reply->additionalMessage().data().at(13));
quint8 maxBufferSize = static_cast<quint8>(reply->additionalMessage().data().at(14));
quint16 bitField = reply->additionalMessage().data().at(15);
bitField <<= 8;
bitField |= reply->additionalMessage().data().at(16);
// Set node data
m_manufacturerCode = manufacturerCode; m_manufacturerCode = manufacturerCode;
m_maximalRxSize = maximalRxSize; }
m_maximalTxSize = maximalTxSize;
// Parse server mask void ZigbeeNode::setMaximumRxSize(quint16 size)
{
m_maximumRxSize = size;
}
void ZigbeeNode::setMaximumTxSize(quint16 size)
{
m_maximumTxSize = size;
}
void ZigbeeNode::setMaximumBufferSize(quint8 size)
{
m_maximumBufferSize = size;
}
void ZigbeeNode::setServerMask(quint16 serverMask)
{
m_isPrimaryTrustCenter = ((serverMask >> 0) & 0x0001); m_isPrimaryTrustCenter = ((serverMask >> 0) & 0x0001);
m_isBackupTrustCenter = ((serverMask >> 1) & 0x0001); m_isBackupTrustCenter = ((serverMask >> 1) & 0x0001);
m_isPrimaryBindingCache = ((serverMask >> 2) & 0x0001); m_isPrimaryBindingCache = ((serverMask >> 2) & 0x0001);
@ -245,298 +195,94 @@ void ZigbeeNode::onRequestNodeDescriptionFinished()
m_isPrimaryDiscoveryCache = ((serverMask >> 4) & 0x0001); m_isPrimaryDiscoveryCache = ((serverMask >> 4) & 0x0001);
m_isBackupDiscoveryCache = ((serverMask >> 5) & 0x0001); m_isBackupDiscoveryCache = ((serverMask >> 5) & 0x0001);
m_isNetworkManager = ((serverMask >> 6) & 0x0001); m_isNetworkManager = ((serverMask >> 6) & 0x0001);
}
// Parse desciptor flag void ZigbeeNode::setComplexDescriptorAvailable(bool complexDescriptorAvailable)
bool extendedActiveEndpointListAvailable = ((descriptorFlag >> 0) & 0x01); {
bool extendedSimpleDescriptorListAvailable = ((descriptorFlag >> 1) & 0x01); m_complexDescriptorAvailable = complexDescriptorAvailable;
}
void ZigbeeNode::setUserDescriptorAvailable(bool userDescriptorAvailable)
{
m_userDescriptorAvailable = userDescriptorAvailable;
}
void ZigbeeNode::setMacCapabilitiesFlag(quint16 macFlag)
{
// Parse MAC capabilities // Parse MAC capabilities
m_receiverOnWhenIdle = ((macFlags >> 3) & 0x01); m_alternatePanCoordinator = ((macFlag >> 0) & 0x01);
m_securityCapability = ((macFlags >> 6) & 0x01); if (((macFlag >> 1) & 0x01)) {
m_deviceType = DeviceTypeFullFunction;
// Parse bit field
bool isCoordinator = ((bitField >> 0) & 0x0001);
bool isRouter = ((bitField >> 1) & 0x0001);
bool isEndDevice = ((bitField >> 2) & 0x0001);
bool complexDescriptorAvailable = ((bitField >> 3) & 0x0001);
bool userDescriptorAvailable = ((bitField >> 4) & 0x0001);
if (isCoordinator && !isRouter && !isEndDevice) {
m_nodeType = NodeTypeCoordinator;
} else if (!isCoordinator && isRouter && !isEndDevice) {
m_nodeType = NodeTypeRouter;
} else if (!isCoordinator && !isRouter && isEndDevice) {
m_nodeType = NodeTypeEndDevice;
} else { } else {
if (m_isNetworkManager) { m_deviceType = DeviceTypeReducedFunction;
m_nodeType = NodeTypeCoordinator;
} else {
m_nodeType = NodeTypeEndDevice;
}
} }
m_powerSourceFlagMainPower = ((macFlag >> 2) & 0x01);
// Note: Frequency always 2,4 GHz m_receiverOnWhenIdle = ((macFlag >> 3) & 0x01);
m_securityCapability = ((macFlag >> 6) & 0x01);
qCDebug(dcZigbee()) << "Node descriptor:"; m_allocateAddress = ((macFlag >> 7) & 0x01);
qCDebug(dcZigbee()) << " Node type:" << m_nodeType;
qCDebug(dcZigbee()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
qCDebug(dcZigbee()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
qCDebug(dcZigbee()) << " Short address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbee()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(manufacturerCode);
qCDebug(dcZigbee()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(m_maximalRxSize);
qCDebug(dcZigbee()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(m_maximalTxSize);
qCDebug(dcZigbee()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
qCDebug(dcZigbee()) << " Primary Trust center:" << m_isPrimaryTrustCenter;
qCDebug(dcZigbee()) << " Backup Trust center:" << m_isBackupTrustCenter;
qCDebug(dcZigbee()) << " Primary Binding cache:" << m_isPrimaryBindingCache;
qCDebug(dcZigbee()) << " Backup Binding cache:" << m_isBackupBindingCache;
qCDebug(dcZigbee()) << " Primary Discovery cache:" << m_isPrimaryDiscoveryCache;
qCDebug(dcZigbee()) << " Backup Discovery cache:" << m_isBackupDiscoveryCache;
qCDebug(dcZigbee()) << " Network Manager:" << m_isNetworkManager;
qCDebug(dcZigbee()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorFlag);
qCDebug(dcZigbee()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable;
qCDebug(dcZigbee()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable;
qCDebug(dcZigbee()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macFlags);
qCDebug(dcZigbee()) << " Receiver on when idle:" << m_receiverOnWhenIdle;
qCDebug(dcZigbee()) << " Security capability:" << m_securityCapability;
qCDebug(dcZigbee()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(maxBufferSize);
qCDebug(dcZigbee()) << " Bit field:" << ZigbeeUtils::convertUint16ToHexString(bitField);
qCDebug(dcZigbee()) << " Is coordinator:" << isCoordinator;
qCDebug(dcZigbee()) << " Is router:" << isRouter;
qCDebug(dcZigbee()) << " Is end device:" << isEndDevice;
qCDebug(dcZigbee()) << " Complex desciptor available:" << complexDescriptorAvailable;
qCDebug(dcZigbee()) << " User desciptor available:" << userDescriptorAvailable;
if (userDescriptorAvailable) {
requestUserDescriptor();
}
} }
void ZigbeeNode::onRequestSimpleNodeDescriptionFinished() void ZigbeeNode::setDescriptorFlag(quint8 descriptorFlag)
{ {
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender()); m_extendedActiveEndpointListAvailable = ((descriptorFlag >> 0) & 0x01);
reply->deleteLater(); m_extendedSimpleDescriptorListAvailable = ((descriptorFlag >> 1) & 0x01);
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();
quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1));
quint16 nwkAddress = reply->additionalMessage().data().at(2);
nwkAddress <<= 8;
nwkAddress |= reply->additionalMessage().data().at(3);
quint8 length = static_cast<quint8>(reply->additionalMessage().data().at(4));
if (length == 0) {
qCWarning(dcZigbee()) << "Length 0";
return;
}
quint8 endPoint = static_cast<quint8>(reply->additionalMessage().data().at(5));
quint16 profileId = reply->additionalMessage().data().at(6);
profileId <<= 8;
profileId |= reply->additionalMessage().data().at(7);
quint16 deviceId = reply->additionalMessage().data().at(8);
deviceId <<= 8;
deviceId |= reply->additionalMessage().data().at(9);
quint8 bitField = static_cast<quint8>(reply->additionalMessage().data().at(10));
qCDebug(dcZigbee()) << "Node simple descriptor:";
qCDebug(dcZigbee()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
qCDebug(dcZigbee()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
qCDebug(dcZigbee()) << " Nwk address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress);
qCDebug(dcZigbee()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
qCDebug(dcZigbee()) << " End Point:" << ZigbeeUtils::convertByteToHexString(endPoint);
qCDebug(dcZigbee()) << " Profile:" << ZigbeeUtils::profileIdToString((Zigbee::ZigbeeProfile)profileId);
if (profileId == Zigbee::ZigbeeProfileLightLink) {
qCDebug(dcZigbee()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::LightLinkDevice>(deviceId);
} else {
qCDebug(dcZigbee()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::HomeAutomationDevice>(deviceId);
}
qCDebug(dcZigbee()) << " Bit field:" << ZigbeeUtils::convertByteToHexString(bitField);
quint8 inputClusterCount = static_cast<quint8>(reply->additionalMessage().data().at(10));
qCDebug(dcZigbee()) << " Input clusters:";
QByteArray inputClusterListData = reply->additionalMessage().data().mid(11, inputClusterCount * 2);
for (int i = 0; i < inputClusterListData.count(); i+=2) {
quint16 clusterId = inputClusterListData.at(i);
clusterId <<= 8;
clusterId |= inputClusterListData .at(i+1);
qCDebug(dcZigbee()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
}
quint8 outputClusterCount = static_cast<quint8>(reply->additionalMessage().data().at(12 + inputClusterCount * 2));
qCDebug(dcZigbee()) << " Output clusters:";
QByteArray outputClusterListData = reply->additionalMessage().data().mid(12 + inputClusterCount * 2, outputClusterCount * 2);
for (int i = 0; i < outputClusterListData.count(); i+=2) {
quint16 clusterId = outputClusterListData.at(i);
clusterId <<= 8;
clusterId |= outputClusterListData .at(i+1);
qCDebug(dcZigbee()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
}
} }
void ZigbeeNode::onRequestPowerDescriptorFinished() //void ZigbeeNode::onRequestUserDescriptorFinished()
{ //{
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender()); // ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
reply->deleteLater(); // reply->deleteLater();
if (reply->status() != ZigbeeInterfaceReply::Success) { // if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage(); // qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
return; // return;
} // }
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully"; // qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
qCDebug(dcZigbeeController()) << reply->additionalMessage(); // qCDebug(dcZigbeeController()) << reply->additionalMessage();
quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0)); // quint8 sequenceNumber = static_cast<quint8>(reply->additionalMessage().data().at(0));
quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1)); // quint8 status = static_cast<quint8>(reply->additionalMessage().data().at(1));
quint16 bitField = reply->additionalMessage().data().at(2); // quint16 nwkAddress = static_cast<quint16>(reply->additionalMessage().data().at(2));
bitField <<= 8; // nwkAddress <<= 8;
bitField |= reply->additionalMessage().data().at(3); // nwkAddress |= reply->additionalMessage().data().at(3);
// Bit 0 - 3 Power mode // quint8 length = static_cast<quint8>(reply->additionalMessage().data().at(4));
// 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
if (!ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) { // QByteArray data;
m_powerMode = PowerModeAlwaysOn; // if (length > 0) {
} else if (ZigbeeUtils::checkBitUint16(bitField, 0) && !ZigbeeUtils::checkBitUint16(bitField, 1)) { // data = reply->additionalMessage().data().mid(5, length);
m_powerMode = PowerModeOnPeriodically; // }
} else if (!ZigbeeUtils::checkBitUint16(bitField, 0) && ZigbeeUtils::checkBitUint16(bitField, 1)) {
m_powerMode = PowerModeOnWhenStimulated;
}
// Bit 4 - 7 Available power sources // qCDebug(dcZigbeeNetwork()) << "User descriptor:";
// Bit 0: Permanent mains supply // qCDebug(dcZigbeeNetwork()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
// Bit 1: Rechargeable battery // qCDebug(dcZigbeeNetwork()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
// Bit 2: Disposable battery // qCDebug(dcZigbeeNetwork()) << " Attribute address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress);
// Bit 4: Reserved // qCDebug(dcZigbeeNetwork()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
// qCDebug(dcZigbeeNetwork()) << " Data:" << data;
//}
if (ZigbeeUtils::checkBitUint16(bitField, 4)) { //void ZigbeeNode::onToggleFinished()
m_availablePowerSources.append(PowerSourcePermanentMainSupply); //{
} else if (ZigbeeUtils::checkBitUint16(bitField, 5)) { // ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
m_availablePowerSources.append(PowerSourceRecharchableBattery); // reply->deleteLater();
} else if (ZigbeeUtils::checkBitUint16(bitField, 6)) {
m_availablePowerSources.append(PowerSourceDisposableBattery);
}
// Bit 8 - 11 Active source: according to the same schema as available power sources // if (reply->status() != ZigbeeInterfaceReply::Success) {
if (ZigbeeUtils::checkBitUint16(bitField, 8)) { // qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
m_powerSource = PowerSourcePermanentMainSupply; // return;
} else if (ZigbeeUtils::checkBitUint16(bitField, 9)) { // }
m_powerSource = PowerSourceRecharchableBattery;
} else if (ZigbeeUtils::checkBitUint16(bitField, 10)) {
m_powerSource = PowerSourceDisposableBattery;
}
// Bit 12 - 15: Battery level if available // qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
// 0000: Critically low //}
// 0100: Approximately 33%
// 1000: Approximately 66%
// 1100: Approximately 100% (near fully charged)
if (!ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) { //void ZigbeeNode::onIdentifyFinished()
m_powerLevel = PowerLevelCriticalLow; //{
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && !ZigbeeUtils::checkBitUint16(bitField, 15)) {
m_powerLevel = PowerLevelLow;
} else if (!ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
m_powerLevel = PowerLevelOk;
} else if (ZigbeeUtils::checkBitUint16(bitField, 14) && ZigbeeUtils::checkBitUint16(bitField, 15)) {
m_powerLevel = PowerLevelFull;
}
qCDebug(dcZigbee()) << "Node power descriptor:"; //}
qCDebug(dcZigbee()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
qCDebug(dcZigbee()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
qCDebug(dcZigbee()) << " Bitfiled:" << ZigbeeUtils::convertUint16ToHexString(bitField);
qCDebug(dcZigbee()) << " Power mode:" << m_powerMode;
qCDebug(dcZigbee()) << " Available power sources:";
foreach (const PowerSource &source, m_availablePowerSources) {
qCDebug(dcZigbee()) << " " << source;
}
qCDebug(dcZigbee()) << " Power source:" << m_powerSource;
qCDebug(dcZigbee()) << " Power level:" << m_powerLevel;
}
void ZigbeeNode::onRequestUserDescriptorFinished()
{
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;
}
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));
quint16 nwkAddress = reply->additionalMessage().data().at(2);
nwkAddress <<= 8;
nwkAddress |= reply->additionalMessage().data().at(3);
quint8 length = static_cast<quint8>(reply->additionalMessage().data().at(4));
QByteArray data;
if (length > 0) {
data = reply->additionalMessage().data().mid(5, length);
}
qCDebug(dcZigbee()) << "User descriptor:";
qCDebug(dcZigbee()) << " Sequence number:" << ZigbeeUtils::convertByteToHexString(sequenceNumber);
qCDebug(dcZigbee()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
qCDebug(dcZigbee()) << " Attribute address:" << ZigbeeUtils::convertUint16ToHexString(nwkAddress);
qCDebug(dcZigbee()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
qCDebug(dcZigbee()) << " Data:" << data;
}
void ZigbeeNode::onToggleFinished()
{
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;
}
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
}
void ZigbeeNode::onIdentifyFinished()
{
}
QDebug operator<<(QDebug debug, ZigbeeNode *node) QDebug operator<<(QDebug debug, ZigbeeNode *node)
{ {
debug.nospace().noquote() << "Node(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress()) << " | " << node->extendedAddress().toString() << ") "; debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress()) << ", " << node->extendedAddress().toString() << ") ";
debug.nospace().noquote() << " " << ZigbeeUtils::convertUint16ToHexString(node->shortAddress()) << " | " << node->extendedAddress().toString() << ") ";
return debug; return debug;
} }

View File

@ -5,9 +5,6 @@
#include "zigbee.h" #include "zigbee.h"
#include "zigbeeaddress.h" #include "zigbeeaddress.h"
#include "zigbeebridgecontroller.h"
class ZigbeeNetworkManager;
class ZigbeeNode : public QObject class ZigbeeNode : public QObject
{ {
@ -30,6 +27,12 @@ public:
}; };
Q_ENUM(FrequencyBand) Q_ENUM(FrequencyBand)
enum DeviceType {
DeviceTypeFullFunction,
DeviceTypeReducedFunction
};
Q_ENUM(DeviceType)
enum Relationship { enum Relationship {
Parent, Parent,
Child, Child,
@ -59,44 +62,56 @@ public:
}; };
Q_ENUM(PowerLevel) Q_ENUM(PowerLevel)
ZigbeeNode(QObject *parent = nullptr);
quint16 shortAddress() const; quint16 shortAddress() const;
ZigbeeAddress extendedAddress() const; ZigbeeAddress extendedAddress() const;
int endPoint() const; quint8 endPoint() const;
// Information from node descriptor // Information from node descriptor
NodeType nodeType() const; NodeType nodeType() const;
FrequencyBand frequencyBand() const; FrequencyBand frequencyBand() const;
Relationship relationShip() const; Relationship relationship() const;
Zigbee::ZigbeeProfile profile() const; Zigbee::ZigbeeProfile profile() const;
quint16 manufacturerCode() const; quint16 manufacturerCode() const;
bool complexDescriptorAvailable() const;
bool userDescriptorAvailable() const;
quint16 maximumRxSize() const;
quint16 maximumTxSize() const;
quint8 maximumBufferSize() const;
// Information from node power descriptor
PowerMode powerMode() const; PowerMode powerMode() const;
PowerSource powerSource() const; PowerSource powerSource() const;
QList<PowerSource> availablePowerSources() const; QList<PowerSource> availablePowerSources() const;
PowerLevel powerLevel() const; PowerLevel powerLevel() const;
// Node specific zigbee commands // Node specific zigbee commands
void init(); // void init();
void identify(); // void identify();
void toggle(int addressMode); // void toggle(int addressMode);
private: private:
ZigbeeBridgeController *m_controller;
quint16 m_shortAddress = 0; quint16 m_shortAddress = 0;
ZigbeeAddress m_extendedAddress; ZigbeeAddress m_extendedAddress;
int m_endPoint = 0; quint8 m_endPoint = 1;
NodeType m_nodeType = NodeTypeRouter; NodeType m_nodeType = NodeTypeRouter;
FrequencyBand m_frequencyBand = FrequencyBand2400Mhz; FrequencyBand m_frequencyBand = FrequencyBand2400Mhz;
Relationship m_relationShip = Parent; Relationship m_relationship = Parent;
Zigbee::ZigbeeProfile m_profile; Zigbee::ZigbeeProfile m_profile;
quint16 m_manufacturerCode = 0; quint16 m_manufacturerCode = 0;
quint16 m_maximalRxSize = 0; bool m_complexDescriptorAvailable = false;
quint16 m_maximalTxSize = 0; bool m_userDescriptorAvailable = false;
quint16 m_maximumRxSize = 0;
quint16 m_maximumTxSize = 0;
quint8 m_maximumBufferSize = 0;
// Server Mask
bool m_isPrimaryTrustCenter = false; bool m_isPrimaryTrustCenter = false;
bool m_isBackupTrustCenter = false; bool m_isBackupTrustCenter = false;
bool m_isPrimaryBindingCache = false; bool m_isPrimaryBindingCache = false;
@ -111,36 +126,38 @@ private:
QList<PowerSource> m_availablePowerSources; QList<PowerSource> m_availablePowerSources;
PowerLevel m_powerLevel; PowerLevel m_powerLevel;
// Mac capabilities // Mac capabilities flag
bool m_alternatePanCoordinator = false;
DeviceType m_deviceType = DeviceTypeFullFunction;
bool m_powerSourceFlagMainPower = false;
bool m_receiverOnWhenIdle = false; bool m_receiverOnWhenIdle = false;
bool m_securityCapability = false; bool m_securityCapability = false;
bool m_allocateAddress = false;
void requestNodeDescription(); // Descriptor capability
void requestSimpleNodeDescription(); bool m_extendedActiveEndpointListAvailable = false;
void requestPowerDescriptor(); bool m_extendedSimpleDescriptorListAvailable = false;
void requestUserDescriptor();
void saveToSettings();
protected: protected:
ZigbeeNode(ZigbeeBridgeController *controller, QObject *parent = nullptr);
ZigbeeBridgeController *controller();
void setShortAddress(const quint16 &shortAddress); void setShortAddress(const quint16 &shortAddress);
void setExtendedAddress(const ZigbeeAddress &extendedAddress); void setExtendedAddress(const ZigbeeAddress &extendedAddress);
void setEndPoint(quint8 endPoint);
signals: void setNodeType(NodeType nodeType);
void setFrequencyBand(FrequencyBand frequencyBand);
void setRelationship(Relationship relationship);
void setZigbeeProfile(Zigbee::ZigbeeProfile profile);
void setManufacturerCode(quint16 manufacturerCode);
private slots: void setMaximumRxSize(quint16 size);
void onRequestNodeDescriptionFinished(); void setMaximumTxSize(quint16 size);
void onRequestSimpleNodeDescriptionFinished(); void setMaximumBufferSize(quint8 size);
void onRequestPowerDescriptorFinished();
void onRequestUserDescriptorFinished();
void onToggleFinished();
void onIdentifyFinished();
public slots: void setServerMask(quint16 serverMask);
void setComplexDescriptorAvailable(bool complexDescriptorAvailable);
void setUserDescriptorAvailable(bool userDescriptorAvailable);
void setMacCapabilitiesFlag(quint16 macFlag);
void setDescriptorFlag(quint8 descriptorFlag);
}; };

View File

@ -0,0 +1,26 @@
#include "zigbeesecurityconfiguration.h"
ZigbeeSecurityConfiguration::ZigbeeSecurityConfiguration()
{
}
QString ZigbeeSecurityConfiguration::networkKey() const
{
return m_networkKey;
}
void ZigbeeSecurityConfiguration::setNetworkKey(const QString &networkKey)
{
m_networkKey = networkKey;
}
QString ZigbeeSecurityConfiguration::globalTrustCenterLinkKey() const
{
return m_globalTrustCenterLinkKey;
}
void ZigbeeSecurityConfiguration::setGlobalTrustCenterlinkKey(const QString &globalTrustCenterLinkKey)
{
m_globalTrustCenterLinkKey = globalTrustCenterLinkKey;
}

View File

@ -0,0 +1,26 @@
#ifndef ZIGBEESECURITYCONFIGURATION_H
#define ZIGBEESECURITYCONFIGURATION_H
#include <QString>
class ZigbeeSecurityConfiguration
{
public:
ZigbeeSecurityConfiguration();
QString networkKey() const;
void setNetworkKey(const QString &networkKey);
QString globalTrustCenterLinkKey() const;
void setGlobalTrustCenterlinkKey(const QString & globalTrustCenterLinkKey);
private:
// This is the local network key
QString m_networkKey;
// Note: this is the zigbee master key from (ZigBeeAlliance09)
QString m_globalTrustCenterLinkKey = "5A6967426565416C6C69616E63653039";
};
#endif // ZIGBEESECURITYCONFIGURATION_H

View File

@ -1,5 +1,6 @@
#include "zigbeeutils.h" #include "zigbeeutils.h"
#include <QDateTime>
#include <QMetaEnum> #include <QMetaEnum>
#include <QDataStream> #include <QDataStream>
@ -22,7 +23,7 @@ QByteArray ZigbeeUtils::convertBitArrayToByteArray(const QBitArray &bitArray)
QByteArray byteArray; QByteArray byteArray;
for(int b = 0; b < bitArray.count(); ++b) { for(int b = 0; b < bitArray.count(); ++b) {
byteArray[b / 8] = (byteArray.at( b / 8) | ((bitArray[b] ? 1 : 0) << (7 - ( b % 8)))); byteArray[b / 8] = static_cast<char>((byteArray.at( b / 8) | ((bitArray[b] ? 1 : 0) << (7 - ( b % 8)))));
} }
return byteArray; return byteArray;
} }
@ -75,7 +76,7 @@ QString ZigbeeUtils::convertByteArrayToHexString(const QByteArray &byteArray)
{ {
QString hexString; QString hexString;
for (int i = 0; i < byteArray.count(); i++) { for (int i = 0; i < byteArray.count(); i++) {
hexString.append(convertByteToHexString((quint8)byteArray.at(i))); hexString.append(convertByteToHexString(static_cast<quint8>(byteArray.at(i))));
if (i != byteArray.count() - 1) { if (i != byteArray.count() - 1) {
hexString.append(" "); hexString.append(" ");
} }
@ -129,3 +130,10 @@ QString ZigbeeUtils::profileIdToString(const Zigbee::ZigbeeProfile &profileId)
return enumString.remove("Zigbee::ZigbeeProfile(ZigbeeProfile").remove(")"); return enumString.remove("Zigbee::ZigbeeProfile(ZigbeeProfile").remove(")");
} }
quint64 ZigbeeUtils::generateRandomPanId()
{
srand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
srand(static_cast<uint>(qrand()));
return static_cast<quint64>((ULLONG_MAX - 0) * (qrand()/static_cast<double>(RAND_MAX)));
}

View File

@ -32,6 +32,8 @@ public:
static QString clusterIdToString(const Zigbee::ClusterId &clusterId); static QString clusterIdToString(const Zigbee::ClusterId &clusterId);
static QString profileIdToString(const Zigbee::ZigbeeProfile &profileId); static QString profileIdToString(const Zigbee::ZigbeeProfile &profileId);
static quint64 generateRandomPanId();
}; };
#endif // ZIGBEEUTILS_H #endif // ZIGBEEUTILS_H

View File

@ -1,5 +1,5 @@
TEMPLATE = subdirs TEMPLATE = subdirs
CONFIG += ordered CONFIG += ordered
SUBDIRS += libnymea-zigbee zigbee-cli SUBDIRS += libnymea-zigbee #zigbee-cli

View File

@ -12,7 +12,10 @@ Core::Core(const QString &serialPort, qint32 baudrate, const int &channel, QObje
m_channelMask = 0; m_channelMask = 0;
m_channelMask |= 1 << (channel); m_channelMask |= 1 << (channel);
m_manager = new ZigbeeNetworkManager(channel, m_serialPort, m_baudRate, this); ZigbeeBridgeController *controller = new ZigbeeBridgeController(this);
controller->enable(serialPort, baudrate);
//m_manager = new ZigbeeNetworkManager(channel, controller, this);
// Set commands // Set commands
TerminalCommand runCommand("run", "Run the zigbee controller in a normal non interactive mode."); TerminalCommand runCommand("run", "Run the zigbee controller in a normal non interactive mode.");
@ -95,8 +98,8 @@ void Core::onCommandReceived(const QStringList &tokens)
m_manager->setChannelMask(0x2108800); m_manager->setChannelMask(0x2108800);
m_manager->setDeviceType(nodeType); m_manager->setDeviceType(nodeType);
// Note: this is the leaked philips ZLL master key // Note: this is the leaked philips ZLL master key
m_manager->setInitialSecurity(3, 0, 1, "9F5595F10257C8A469CBF42BC93FEE31"); //m_manager->setInitialSecurity(3, 0, 1, "9F5595F10257C8A469CBF42BC93FEE31");
//m_manager->setInitialSecurity(4, 0, 1, "5A6967426565416C6C69616E63653039"); m_manager->setInitialSecurity(4, 0, 1, "5A6967426565416C6C69616E63653039");
} else if (command.command() == "start") { } else if (command.command() == "start") {
m_manager->startNetwork(); m_manager->startNetwork();