Implement first ZDO call
This commit is contained in:
parent
4472700160
commit
118cdedc6a
@ -5,9 +5,16 @@ This repository contains the nymea-zigbee library and tools.
|
|||||||
|
|
||||||
# Supported hardware
|
# Supported hardware
|
||||||
|
|
||||||
Currently the only supported hardware is from NXP, but the tool will be designed to support also other hardware modules.
|
Depending on your available hardware following gateway modules are supported
|
||||||
|
|
||||||
## NXP
|
## NXP
|
||||||
|
|
||||||
* JN5168 (SoM)
|
* JN5168 (SoM)
|
||||||
* JN5169 (USB Stick)
|
* JN5169 (USB Stick)
|
||||||
|
|
||||||
|
## deCONZ
|
||||||
|
|
||||||
|
* ConBee
|
||||||
|
* RaspBee
|
||||||
|
* ConBee II
|
||||||
|
* RaspBee II
|
||||||
|
|||||||
@ -224,7 +224,7 @@ void ZigbeeInterfaceDeconz::sendPackage(const QByteArray &package)
|
|||||||
qCWarning(dcZigbeeInterface()) << "Could not stream byte" << ZigbeeUtils::convertByteArrayToHexString(data);
|
qCWarning(dcZigbeeInterface()) << "Could not stream byte" << ZigbeeUtils::convertByteArrayToHexString(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_serialPort->flush();
|
//m_serialPort->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZigbeeInterfaceDeconz::enable(const QString &serialPort, qint32 baudrate)
|
bool ZigbeeInterfaceDeconz::enable(const QString &serialPort, qint32 baudrate)
|
||||||
|
|||||||
@ -60,8 +60,18 @@ void ZigbeeInterfaceDeconzReply::abort()
|
|||||||
|
|
||||||
ZigbeeInterfaceDeconzReply::ZigbeeInterfaceDeconzReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent) :
|
ZigbeeInterfaceDeconzReply::ZigbeeInterfaceDeconzReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
|
m_timer(new QTimer(this)),
|
||||||
m_command(command),
|
m_command(command),
|
||||||
m_sequenceNumber(sequenceNumber)
|
m_sequenceNumber(sequenceNumber)
|
||||||
{
|
{
|
||||||
|
m_timer->setInterval(2000);
|
||||||
|
m_timer->setSingleShot(true);
|
||||||
|
connect(m_timer, &QTimer::timeout, this, &ZigbeeInterfaceDeconzReply::onTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeInterfaceDeconzReply::onTimeout()
|
||||||
|
{
|
||||||
|
m_timeout = true;
|
||||||
|
emit timeout();
|
||||||
|
emit finished();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
#define ZIGBEEINTERFACEDECONZREPLY_H
|
#define ZIGBEEINTERFACEDECONZREPLY_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include "deconz.h"
|
#include "deconz.h"
|
||||||
|
|
||||||
@ -47,12 +48,14 @@ public:
|
|||||||
// Response content
|
// Response content
|
||||||
Deconz::StatusCode statusCode() const;
|
Deconz::StatusCode statusCode() const;
|
||||||
|
|
||||||
|
bool timeout() const;
|
||||||
bool aborted() const;
|
bool aborted() const;
|
||||||
void abort();
|
void abort();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ZigbeeInterfaceDeconzReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent = nullptr);
|
explicit ZigbeeInterfaceDeconzReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent = nullptr);
|
||||||
|
QTimer *m_timer = nullptr;
|
||||||
|
bool m_timeout = false;
|
||||||
bool m_aborted = false;
|
bool m_aborted = false;
|
||||||
|
|
||||||
// Request content
|
// Request content
|
||||||
@ -63,7 +66,11 @@ private:
|
|||||||
Deconz::StatusCode m_statusCode = Deconz::StatusCodeError;
|
Deconz::StatusCode m_statusCode = Deconz::StatusCodeError;
|
||||||
QByteArray m_responseData;
|
QByteArray m_responseData;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onTimeout();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void timeout();
|
||||||
void finished();
|
void finished();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
#include "zigbeebridgecontrollerdeconz.h"
|
#include "zigbeebridgecontrollerdeconz.h"
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
|
#include "zigbeedeviceprofile.h"
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
|
||||||
@ -219,7 +220,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestQuerySendDataCo
|
|||||||
return createReply(Deconz::CommandApsDataConfirm, sequenceNumber, this);
|
return createReply(Deconz::CommandApsDataConfirm, sequenceNumber, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataGroup(quint8 requestId, quint16 groupAddress, quint8 destinationEndpoint, Zigbee::ZigbeeProfile profileId, Zigbee::ClusterId clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius)
|
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataGroup(quint8 requestId, quint16 groupAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius)
|
||||||
{
|
{
|
||||||
quint8 sequenceNumber = generateSequenceNumber();
|
quint8 sequenceNumber = generateSequenceNumber();
|
||||||
qCDebug(dcZigbeeController()) << "Request enqueue send data to group" << ZigbeeUtils::convertUint16ToHexString(groupAddress)
|
qCDebug(dcZigbeeController()) << "Request enqueue send data to group" << ZigbeeUtils::convertUint16ToHexString(groupAddress)
|
||||||
@ -240,13 +241,13 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
|||||||
stream << static_cast<quint8>(sequenceNumber);
|
stream << static_cast<quint8>(sequenceNumber);
|
||||||
stream << static_cast<quint8>(0); // Reserverd
|
stream << static_cast<quint8>(0); // Reserverd
|
||||||
stream << static_cast<quint16>(7 + payloadLength); // Frame length
|
stream << static_cast<quint16>(7 + payloadLength); // Frame length
|
||||||
stream << static_cast<quint16>(payloadLength);
|
stream << payloadLength;
|
||||||
stream << requestId;
|
stream << requestId;
|
||||||
stream << static_cast<quint8>(0); // Flags
|
stream << static_cast<quint8>(0); // Flags
|
||||||
stream << static_cast<quint8>(Zigbee::DestinationAddressModeGroup);
|
stream << static_cast<quint8>(Zigbee::DestinationAddressModeGroup);
|
||||||
stream << groupAddress << destinationEndpoint;
|
stream << groupAddress << destinationEndpoint;
|
||||||
stream << static_cast<quint16>(profileId);
|
stream << profileId;
|
||||||
stream << static_cast<quint16>(clusterId);
|
stream << clusterId;
|
||||||
stream << sourceEndpoint;
|
stream << sourceEndpoint;
|
||||||
stream << static_cast<quint16>(asdu.length());
|
stream << static_cast<quint16>(asdu.length());
|
||||||
for (int i = 0; i < asdu.length(); i++) {
|
for (int i = 0; i < asdu.length(); i++) {
|
||||||
@ -260,7 +261,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
|||||||
return createReply(Deconz::CommandApsDataRequest, sequenceNumber, this);
|
return createReply(Deconz::CommandApsDataRequest, sequenceNumber, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, Zigbee::ZigbeeProfile profileId, Zigbee::ClusterId clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius)
|
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius)
|
||||||
{
|
{
|
||||||
quint8 sequenceNumber = generateSequenceNumber();
|
quint8 sequenceNumber = generateSequenceNumber();
|
||||||
qCDebug(dcZigbeeController()) << "Request enqueue send data to short address" << ZigbeeUtils::convertUint16ToHexString(shortAddress)
|
qCDebug(dcZigbeeController()) << "Request enqueue send data to short address" << ZigbeeUtils::convertUint16ToHexString(shortAddress)
|
||||||
@ -281,13 +282,13 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
|||||||
stream << static_cast<quint8>(sequenceNumber);
|
stream << static_cast<quint8>(sequenceNumber);
|
||||||
stream << static_cast<quint8>(0); // Reserverd
|
stream << static_cast<quint8>(0); // Reserverd
|
||||||
stream << static_cast<quint16>(7 + payloadLength); // Frame length
|
stream << static_cast<quint16>(7 + payloadLength); // Frame length
|
||||||
stream << static_cast<quint16>(payloadLength);
|
stream << payloadLength;
|
||||||
stream << requestId;
|
stream << requestId;
|
||||||
stream << static_cast<quint8>(0); // Flags
|
stream << static_cast<quint8>(0); // Flags
|
||||||
stream << static_cast<quint8>(Zigbee::DestinationAddressModeShortAddress);
|
stream << static_cast<quint8>(Zigbee::DestinationAddressModeShortAddress);
|
||||||
stream << shortAddress << destinationEndpoint;
|
stream << shortAddress << destinationEndpoint;
|
||||||
stream << static_cast<quint16>(profileId);
|
stream << profileId;
|
||||||
stream << static_cast<quint16>(clusterId);
|
stream << clusterId;
|
||||||
stream << sourceEndpoint;
|
stream << sourceEndpoint;
|
||||||
stream << static_cast<quint16>(asdu.length());
|
stream << static_cast<quint16>(asdu.length());
|
||||||
for (int i = 0; i < asdu.length(); i++) {
|
for (int i = 0; i < asdu.length(); i++) {
|
||||||
@ -301,7 +302,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
|||||||
return createReply(Deconz::CommandApsDataRequest, sequenceNumber, this);
|
return createReply(Deconz::CommandApsDataRequest, sequenceNumber, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataIeeeAddress(quint8 requestId, ZigbeeAddress ieeeAddress, quint8 destinationEndpoint, Zigbee::ZigbeeProfile profileId, Zigbee::ClusterId clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius)
|
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataIeeeAddress(quint8 requestId, ZigbeeAddress ieeeAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius)
|
||||||
{
|
{
|
||||||
quint8 sequenceNumber = generateSequenceNumber();
|
quint8 sequenceNumber = generateSequenceNumber();
|
||||||
qCDebug(dcZigbeeController()) << "Request enqueue send data to IEEE address" << ieeeAddress.toString()
|
qCDebug(dcZigbeeController()) << "Request enqueue send data to IEEE address" << ieeeAddress.toString()
|
||||||
@ -322,13 +323,13 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
|||||||
stream << static_cast<quint8>(sequenceNumber);
|
stream << static_cast<quint8>(sequenceNumber);
|
||||||
stream << static_cast<quint8>(0); // Reserverd
|
stream << static_cast<quint8>(0); // Reserverd
|
||||||
stream << static_cast<quint16>(7 + payloadLength); // Frame length
|
stream << static_cast<quint16>(7 + payloadLength); // Frame length
|
||||||
stream << static_cast<quint16>(payloadLength);
|
stream << payloadLength;
|
||||||
stream << requestId;
|
stream << requestId;
|
||||||
stream << static_cast<quint8>(0); // Flags
|
stream << static_cast<quint8>(0); // Flags
|
||||||
stream << static_cast<quint8>(Zigbee::DestinationAddressModeIeeeAddress);
|
stream << static_cast<quint8>(Zigbee::DestinationAddressModeIeeeAddress);
|
||||||
stream << ieeeAddress.toUInt64() << destinationEndpoint;
|
stream << ieeeAddress.toUInt64() << destinationEndpoint;
|
||||||
stream << static_cast<quint16>(profileId);
|
stream << profileId;
|
||||||
stream << static_cast<quint16>(clusterId);
|
stream << clusterId;
|
||||||
stream << sourceEndpoint;
|
stream << sourceEndpoint;
|
||||||
stream << static_cast<quint16>(asdu.length());
|
stream << static_cast<quint16>(asdu.length());
|
||||||
for (int i = 0; i < asdu.length(); i++) {
|
for (int i = 0; i < asdu.length(); i++) {
|
||||||
@ -342,6 +343,30 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
|||||||
return createReply(Deconz::CommandApsDataRequest, sequenceNumber, this);
|
return createReply(Deconz::CommandApsDataRequest, sequenceNumber, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestSendRequest(const ZigbeeNetworkRequest &request)
|
||||||
|
{
|
||||||
|
ZigbeeInterfaceDeconzReply *interfaceReply = nullptr;
|
||||||
|
switch (request.destinationAddressMode()) {
|
||||||
|
case Zigbee::DestinationAddressModeGroup:
|
||||||
|
interfaceReply = requestEnqueueSendDataGroup(request.requestId(), request.destinationShortAddress(),
|
||||||
|
request.destinationEndpoint(), request.profileId(), request.clusterId(),
|
||||||
|
request.sourceEndpoint(), request.asdu(), request.radius());
|
||||||
|
break;
|
||||||
|
case Zigbee::DestinationAddressModeShortAddress:
|
||||||
|
interfaceReply = requestEnqueueSendDataShortAddress(request.requestId(), request.destinationShortAddress(),
|
||||||
|
request.destinationEndpoint(), request.profileId(), request.clusterId(),
|
||||||
|
request.sourceEndpoint(), request.asdu(), request.radius());
|
||||||
|
break;
|
||||||
|
case Zigbee::DestinationAddressModeIeeeAddress:
|
||||||
|
interfaceReply = requestEnqueueSendDataIeeeAddress(request.requestId(), request.destinationIeeeAddress(),
|
||||||
|
request.destinationEndpoint(), request.profileId(), request.clusterId(),
|
||||||
|
request.sourceEndpoint(), request.asdu(), request.radius());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return interfaceReply;
|
||||||
|
}
|
||||||
|
|
||||||
quint8 ZigbeeBridgeControllerDeconz::generateSequenceNumber()
|
quint8 ZigbeeBridgeControllerDeconz::generateSequenceNumber()
|
||||||
{
|
{
|
||||||
return m_sequenceNumber++;
|
return m_sequenceNumber++;
|
||||||
@ -358,6 +383,9 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::createReply(Deconz::Co
|
|||||||
// Add it to the pending list
|
// Add it to the pending list
|
||||||
m_pendingReplies.insert(sequenceNumber, reply);
|
m_pendingReplies.insert(sequenceNumber, reply);
|
||||||
|
|
||||||
|
// Fixme: start the timer once actually sent to the interface
|
||||||
|
reply->m_timer->start();
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,6 +740,38 @@ DeconzDeviceState ZigbeeBridgeControllerDeconz::parseDeviceStateFlag(quint8 devi
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeBridgeControllerDeconz::readDataIndication()
|
||||||
|
{
|
||||||
|
ZigbeeInterfaceDeconzReply *reply = requestReadReceivedDataIndication();
|
||||||
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
|
qCWarning(dcZigbeeController()) << "Could not read data indication." << reply->statusCode();
|
||||||
|
// FIXME: set an appropriate error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASP data indication received, process the content
|
||||||
|
qCDebug(dcZigbeeController()) << "Reading data indication finished successfully";
|
||||||
|
processDataIndication(reply->responseData());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeBridgeControllerDeconz::readDataConfirm()
|
||||||
|
{
|
||||||
|
ZigbeeInterfaceDeconzReply *reply = requestQuerySendDataConfirm();
|
||||||
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
|
qCWarning(dcZigbeeController()) << "Could not read data confirm." << reply->statusCode();
|
||||||
|
// FIXME: set an appropriate error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASP data indication received, process the content
|
||||||
|
qCDebug(dcZigbeeController()) << "Reading data confirm finished successfully";
|
||||||
|
processDataConfirm(reply->responseData());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceState)
|
void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceState)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeController()) << deviceState;
|
qCDebug(dcZigbeeController()) << deviceState;
|
||||||
@ -732,36 +792,16 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
|
|||||||
if (m_networkState != Deconz::NetworkStateConnected)
|
if (m_networkState != Deconz::NetworkStateConnected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Note: read a data indication before a confirmation since the confirmation arrives after a related indication normally
|
||||||
|
|
||||||
// Check if we have to read a data indication message
|
// Check if we have to read a data indication message
|
||||||
if (deviceState.aspDataIndication) {
|
if (deviceState.aspDataIndication) {
|
||||||
ZigbeeInterfaceDeconzReply *reply = requestReadReceivedDataIndication();
|
readDataIndication();
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
|
||||||
qCWarning(dcZigbeeController()) << "Could not read data indication." << reply->statusCode();
|
|
||||||
// FIXME: set an appropriate error
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASP data indication received, process the content
|
|
||||||
qCDebug(dcZigbeeController()) << "Reading data indication finished successfully";
|
|
||||||
processDataIndication(reply->responseData());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have a response to read for a request
|
// Check if we have a response to read for a request
|
||||||
if (deviceState.aspDataConfirm) {
|
if (deviceState.aspDataConfirm) {
|
||||||
ZigbeeInterfaceDeconzReply *reply = requestQuerySendDataConfirm();
|
readDataConfirm();
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
|
||||||
qCWarning(dcZigbeeController()) << "Could not read data indication." << reply->statusCode();
|
|
||||||
// FIXME: set an appropriate error
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASP data indication received, process the content
|
|
||||||
qCDebug(dcZigbeeController()) << "Reading data confirm finished successfully";
|
|
||||||
processDataConfirm(reply->responseData());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -771,104 +811,76 @@ void ZigbeeBridgeControllerDeconz::processDataIndication(const QByteArray &data)
|
|||||||
// ASP data indication
|
// ASP data indication
|
||||||
QDataStream stream(data);
|
QDataStream stream(data);
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 destinationAddressModeFlag = 0;
|
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 reserved = 0; quint16 asduLength = 0;
|
||||||
quint16 destinationShortAddress = 0; quint64 destinationIeeeAddress = 0; quint8 destinationEndpoint = 0;
|
|
||||||
quint8 sourceAddressModeFlag = 0; quint16 sourceShortAddress = 0; quint64 sourceIeeeAddress = 0; quint8 sourceEndpoint = 0;
|
|
||||||
quint16 profileId = 0; quint16 clusterId = 0; quint16 asduLength = 0; QByteArray asdu; quint8 reserved = 0;
|
|
||||||
quint8 lqi = 0; qint8 rssi = 0;
|
|
||||||
|
|
||||||
stream >> payloadLenght >> deviceStateFlag >> destinationAddressModeFlag;
|
DeconzApsDataIndication indication;
|
||||||
Zigbee::DestinationAddressMode destinationAddressMode = static_cast<Zigbee::DestinationAddressMode>(destinationAddressModeFlag);
|
stream >> payloadLenght >> deviceStateFlag;
|
||||||
|
stream >> indication.destinationAddressMode;
|
||||||
|
Zigbee::DestinationAddressMode destinationAddressMode = static_cast<Zigbee::DestinationAddressMode>(indication.destinationAddressMode);
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup || destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup || destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
||||||
stream >> destinationShortAddress;
|
stream >> indication.destinationShortAddress;
|
||||||
|
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
||||||
stream >> destinationIeeeAddress;
|
stream >> indication.destinationIeeeAddress;
|
||||||
|
|
||||||
stream >> destinationEndpoint >> sourceAddressModeFlag;
|
stream >> indication.destinationEndpoint >> indication.sourceAddressMode;
|
||||||
|
|
||||||
Zigbee::SourceAddressMode sourceAddressMode = static_cast<Zigbee::SourceAddressMode>(sourceAddressModeFlag);
|
Zigbee::SourceAddressMode sourceAddressMode = static_cast<Zigbee::SourceAddressMode>(indication.sourceAddressMode);
|
||||||
if (sourceAddressMode == Zigbee::SourceAddressModeShortAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
|
if (sourceAddressMode == Zigbee::SourceAddressModeShortAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
|
||||||
stream >> sourceShortAddress;
|
stream >> indication.sourceShortAddress;
|
||||||
|
|
||||||
if (sourceAddressMode == Zigbee::SourceAddressModeIeeeAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
|
if (sourceAddressMode == Zigbee::SourceAddressModeIeeeAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
|
||||||
stream >> sourceIeeeAddress;
|
stream >> indication.sourceIeeeAddress;
|
||||||
|
|
||||||
stream >> sourceEndpoint >> profileId >> clusterId >> asduLength;
|
|
||||||
|
|
||||||
|
stream >> indication.sourceEndpoint >> indication.profileId >> indication.clusterId >> asduLength;
|
||||||
// Fill asdu data
|
// Fill asdu data
|
||||||
for (int i = 0; i < asduLength; i++) {
|
for (int i = 0; i < asduLength; i++) {
|
||||||
quint8 byte = 0;
|
quint8 byte = 0;
|
||||||
stream >> byte;
|
stream >> byte;
|
||||||
asdu.append(static_cast<char>(byte));
|
indication.asdu.append(static_cast<char>(byte));
|
||||||
}
|
}
|
||||||
|
|
||||||
stream >> reserved >> reserved >> lqi >> reserved >> reserved >> reserved >> reserved >> rssi;
|
stream >> reserved >> reserved >> indication.lqi >> reserved >> reserved >> reserved >> reserved >> indication.rssi;
|
||||||
|
|
||||||
// Print the information for debugging
|
// Print the information for debugging
|
||||||
qCDebug(dcZigbeeController()) << "Data indication received:";
|
qCDebug(dcZigbeeController()) << indication;
|
||||||
qCDebug(dcZigbeeController()) << " Destination address mode:" << destinationAddressMode;
|
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup)
|
|
||||||
qCDebug(dcZigbeeController()) << " Destination address (group):" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
|
|
||||||
|
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
emit aspDataIndicationReceived(indication);
|
||||||
qCDebug(dcZigbeeController()) << " Destination short address:" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
|
|
||||||
|
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
// Process the device state in order to check if we have to request another indication
|
||||||
qCDebug(dcZigbeeController()) << " Destination IEEE address:" << ZigbeeAddress(destinationIeeeAddress).toString();
|
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
|
||||||
|
if (deviceState.aspDataIndication) {
|
||||||
qCDebug(dcZigbeeController()) << " Destination endpoint" << ZigbeeUtils::convertByteToHexString(destinationEndpoint);
|
readDataIndication();
|
||||||
|
}
|
||||||
qCDebug(dcZigbeeController()) << " Source address mode:" << sourceAddressMode;
|
|
||||||
if (sourceAddressMode == Zigbee::SourceAddressModeShortAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
|
|
||||||
qCDebug(dcZigbeeController()) << " Source address:" << ZigbeeUtils::convertUint16ToHexString(sourceShortAddress);
|
|
||||||
|
|
||||||
if (sourceAddressMode == Zigbee::SourceAddressModeIeeeAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
|
|
||||||
qCDebug(dcZigbeeController()) << " Source IEEE address:" << ZigbeeAddress(sourceIeeeAddress).toString();
|
|
||||||
|
|
||||||
|
|
||||||
qCDebug(dcZigbeeController()) << " Source endpoint:" << ZigbeeUtils::convertByteToHexString(sourceEndpoint);
|
|
||||||
qCDebug(dcZigbeeController()) << " Profile:" << static_cast<Zigbee::ZigbeeProfile>(profileId);
|
|
||||||
qCDebug(dcZigbeeController()) << " Cluster:" << static_cast<Zigbee::ClusterId>(clusterId);
|
|
||||||
qCDebug(dcZigbeeController()) << " ASDU:" << ZigbeeUtils::convertByteArrayToHexString(asdu);
|
|
||||||
qCDebug(dcZigbeeController()) << " LQI:" << lqi;
|
|
||||||
qCDebug(dcZigbeeController()) << " RSSI:" << rssi << "dBm";
|
|
||||||
|
|
||||||
processDeviceState(parseDeviceStateFlag(deviceStateFlag));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeBridgeControllerDeconz::processDataConfirm(const QByteArray &data)
|
void ZigbeeBridgeControllerDeconz::processDataConfirm(const QByteArray &data)
|
||||||
{
|
{
|
||||||
QDataStream stream(data);
|
QDataStream stream(data);
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 requestId = 0; quint8 destinationAddressMode = 0;
|
DeconzApsDataConfirm confirm;
|
||||||
quint16 destinationShortAddress = 0; quint64 destinationIeeeAddress = 0; quint8 destinationEndpoint = 0;
|
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0;
|
||||||
quint8 sourceEndpoint = 0; quint8 zigbeeConfirmStatus = 0;
|
stream >> payloadLenght >> deviceStateFlag;
|
||||||
|
stream >> confirm.requestId >> confirm.destinationAddressMode;
|
||||||
|
|
||||||
stream >> payloadLenght >> deviceStateFlag >> requestId >> destinationAddressMode;
|
if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeGroup || confirm.destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup || destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
stream >> confirm.destinationShortAddress;
|
||||||
stream >> destinationShortAddress;
|
|
||||||
|
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
||||||
stream >> destinationIeeeAddress;
|
stream >> confirm.destinationIeeeAddress;
|
||||||
|
|
||||||
stream >> destinationEndpoint >> sourceEndpoint >> zigbeeConfirmStatus;
|
stream >> confirm.destinationEndpoint >> confirm.sourceEndpoint >> confirm.zigbeeStatusCode;
|
||||||
|
|
||||||
// Print the information for debugging
|
// Print the information for debugging
|
||||||
qCDebug(dcZigbeeController()) << "Data confirm received: Request" << requestId;
|
qCDebug(dcZigbeeController()) << confirm;
|
||||||
qCDebug(dcZigbeeController()) << " Destination address mode:" << destinationAddressMode;
|
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup)
|
|
||||||
qCDebug(dcZigbeeController()) << " Destination address (group):" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
|
|
||||||
|
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
emit aspDataConfirmReceived(confirm);
|
||||||
qCDebug(dcZigbeeController()) << " Destination short address:" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
|
|
||||||
|
|
||||||
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
// Process the device state in order to check if we have to request another indication
|
||||||
qCDebug(dcZigbeeController()) << " Destination IEEE address:" << ZigbeeAddress(destinationIeeeAddress).toString();
|
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
|
||||||
|
if (deviceState.aspDataConfirm) {
|
||||||
qCDebug(dcZigbeeController()) << " Destination endpoint" << ZigbeeUtils::convertByteToHexString(destinationEndpoint);
|
readDataConfirm();
|
||||||
qCDebug(dcZigbeeController()) << " Source endpoint" << ZigbeeUtils::convertByteToHexString(sourceEndpoint);
|
}
|
||||||
qCDebug(dcZigbeeController()) << " Confirm status" << static_cast<Zigbee::ZigbeeStatus>(zigbeeConfirmStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeBridgeControllerDeconz::onInterfaceAvailableChanged(bool available)
|
void ZigbeeBridgeControllerDeconz::onInterfaceAvailableChanged(bool available)
|
||||||
@ -899,8 +911,8 @@ void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray &
|
|||||||
QByteArray data = package.right(package.length() - 5);
|
QByteArray data = package.right(package.length() - 5);
|
||||||
Deconz::Command command = static_cast<Deconz::Command>(commandInt);
|
Deconz::Command command = static_cast<Deconz::Command>(commandInt);
|
||||||
Deconz::StatusCode status = static_cast<Deconz::StatusCode>(statusInt);
|
Deconz::StatusCode status = static_cast<Deconz::StatusCode>(statusInt);
|
||||||
qCDebug(dcZigbeeController()) << "Interface message received" << command << "SQN:" << sequenceNumber
|
//qCDebug(dcZigbeeController()) << "Interface message received" << command << "SQN:" << sequenceNumber
|
||||||
<< status << "Frame length:" << frameLength << ZigbeeUtils::convertByteArrayToHexString(data);
|
// << status << "Frame length:" << frameLength << ZigbeeUtils::convertByteArrayToHexString(data);
|
||||||
|
|
||||||
// Check if this is an interface response for a pending reply
|
// Check if this is an interface response for a pending reply
|
||||||
if (m_pendingReplies.contains(sequenceNumber) && m_pendingReplies.value(sequenceNumber)->command() == command) {
|
if (m_pendingReplies.contains(sequenceNumber) && m_pendingReplies.value(sequenceNumber)->command() == command) {
|
||||||
@ -982,3 +994,59 @@ QDebug operator<<(QDebug debug, const DeconzDeviceState &deviceState)
|
|||||||
debug.nospace() << "CanSend=" << deviceState.aspDataRequestFreeSlots << ")";
|
debug.nospace() << "CanSend=" << deviceState.aspDataRequestFreeSlots << ")";
|
||||||
return debug.space();
|
return debug.space();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const DeconzApsDataConfirm &confirm)
|
||||||
|
{
|
||||||
|
debug.nospace() << "ASP.Confirm(";
|
||||||
|
debug.nospace() << "Request ID: " << confirm.requestId << ", ";
|
||||||
|
|
||||||
|
if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeGroup)
|
||||||
|
debug.nospace() << "Group address:" << ZigbeeUtils::convertUint16ToHexString(confirm.destinationShortAddress) << ", ";
|
||||||
|
|
||||||
|
if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
||||||
|
debug.nospace() << "NWK address:" << ZigbeeUtils::convertUint16ToHexString(confirm.destinationShortAddress) << ", ";
|
||||||
|
|
||||||
|
if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
||||||
|
debug.nospace() << "IEEE address:" << ZigbeeAddress(confirm.destinationIeeeAddress).toString() << ", ";
|
||||||
|
|
||||||
|
debug.nospace() << "Destination EP:" << ZigbeeUtils::convertByteToHexString(confirm.destinationEndpoint) << ", ";
|
||||||
|
debug.nospace() << "Source EP:" << ZigbeeUtils::convertByteToHexString(confirm.sourceEndpoint) << ", ";
|
||||||
|
debug.nospace() << static_cast<Zigbee::ZigbeeStatus>(confirm.zigbeeStatusCode);
|
||||||
|
debug.nospace() << ")";
|
||||||
|
|
||||||
|
return debug.space();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const DeconzApsDataIndication &indication)
|
||||||
|
{
|
||||||
|
debug.nospace() << "ASP.Indication(";
|
||||||
|
if (indication.destinationAddressMode == Zigbee::DestinationAddressModeGroup)
|
||||||
|
debug.nospace() << "Group address:" << ZigbeeUtils::convertUint16ToHexString(indication.destinationShortAddress) << ", ";
|
||||||
|
|
||||||
|
if (indication.destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
||||||
|
debug.nospace() << "NWK address:" << ZigbeeUtils::convertUint16ToHexString(indication.destinationShortAddress) << ", ";
|
||||||
|
|
||||||
|
if (indication.destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
||||||
|
debug.nospace() << "IEEE address:" << ZigbeeAddress(indication.destinationIeeeAddress).toString() << ", ";
|
||||||
|
|
||||||
|
debug.nospace() << "Destination EP:" << ZigbeeUtils::convertByteToHexString(indication.destinationEndpoint) << ", ";
|
||||||
|
debug.nospace() << "Source EP:" << ZigbeeUtils::convertByteToHexString(indication.sourceEndpoint) << ", ";
|
||||||
|
|
||||||
|
if (indication.sourceAddressMode == Zigbee::SourceAddressModeShortAddress || indication.sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
|
||||||
|
debug.nospace() << "Source NWK address:" << ZigbeeUtils::convertUint16ToHexString(indication.sourceShortAddress) << ", ";
|
||||||
|
|
||||||
|
if (indication.sourceAddressMode == Zigbee::SourceAddressModeIeeeAddress || indication.sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
|
||||||
|
debug.nospace() << "Source IEEE address:" << ZigbeeAddress(indication.sourceIeeeAddress).toString() << ", ";
|
||||||
|
|
||||||
|
debug.nospace() << static_cast<Zigbee::ZigbeeProfile>(indication.profileId) << ", ";
|
||||||
|
if (indication.profileId == static_cast<quint16>(Zigbee::ZigbeeProfileDevice)) {
|
||||||
|
debug.nospace() << static_cast<ZigbeeDeviceProfile::ZdoCommand>(indication.clusterId) << ", ";
|
||||||
|
} else {
|
||||||
|
debug.nospace() << static_cast<Zigbee::ClusterId>(indication.clusterId) << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
debug.nospace() << "ASDU: " << ZigbeeUtils::convertByteArrayToHexString(indication.asdu) << ", ";
|
||||||
|
debug.nospace() << "LQI: " << indication.lqi << ", ";
|
||||||
|
debug.nospace() << "RSSI: " << indication.rssi << "dBm)";
|
||||||
|
return debug.space();
|
||||||
|
}
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
#include "zigbeeaddress.h"
|
#include "zigbeeaddress.h"
|
||||||
#include "zigbeenetworkkey.h"
|
#include "zigbeenetworkkey.h"
|
||||||
|
#include "zigbeenetworkrequest.h"
|
||||||
#include "zigbeebridgecontroller.h"
|
#include "zigbeebridgecontroller.h"
|
||||||
|
|
||||||
#include "interface/deconz.h"
|
#include "interface/deconz.h"
|
||||||
@ -70,6 +71,34 @@ typedef struct DeconzDeviceState {
|
|||||||
bool aspDataRequestFreeSlots = false;
|
bool aspDataRequestFreeSlots = false;
|
||||||
} DeconzDeviceState;
|
} DeconzDeviceState;
|
||||||
|
|
||||||
|
|
||||||
|
// Basic struct for interface data. Default Response
|
||||||
|
typedef struct DeconzApsDataConfirm {
|
||||||
|
quint8 requestId = 0;
|
||||||
|
quint8 destinationAddressMode = Zigbee::DestinationAddressModeShortAddress;
|
||||||
|
quint16 destinationShortAddress = 0;
|
||||||
|
quint64 destinationIeeeAddress;
|
||||||
|
quint8 destinationEndpoint = 0;
|
||||||
|
quint8 sourceEndpoint = 0;
|
||||||
|
quint8 zigbeeStatusCode = 0;
|
||||||
|
} DeconzApsDataConfirm;
|
||||||
|
|
||||||
|
typedef struct DeconzApsDataIndication {
|
||||||
|
quint8 destinationAddressMode = 0;
|
||||||
|
quint16 destinationShortAddress = 0;
|
||||||
|
quint64 destinationIeeeAddress = 0;
|
||||||
|
quint8 destinationEndpoint = 0;
|
||||||
|
quint8 sourceAddressMode = 0;
|
||||||
|
quint16 sourceShortAddress = 0;
|
||||||
|
quint64 sourceIeeeAddress = 0;
|
||||||
|
quint8 sourceEndpoint = 0;
|
||||||
|
quint16 profileId = 0;
|
||||||
|
quint16 clusterId = 0;
|
||||||
|
QByteArray asdu;
|
||||||
|
quint8 lqi = 0;
|
||||||
|
qint8 rssi = 0;
|
||||||
|
} DeconzApsDataIndication;
|
||||||
|
|
||||||
class ZigbeeBridgeControllerDeconz : public ZigbeeBridgeController
|
class ZigbeeBridgeControllerDeconz : public ZigbeeBridgeController
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -96,9 +125,11 @@ public:
|
|||||||
ZigbeeInterfaceDeconzReply *requestQuerySendDataConfirm();
|
ZigbeeInterfaceDeconzReply *requestQuerySendDataConfirm();
|
||||||
|
|
||||||
// Send data
|
// Send data
|
||||||
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataGroup(quint8 requestId, quint16 groupAddress, quint8 destinationEndpoint, Zigbee::ZigbeeProfile profileId, Zigbee::ClusterId clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius = 0);
|
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataGroup(quint8 requestId, quint16 groupAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius = 0);
|
||||||
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, Zigbee::ZigbeeProfile profileId, Zigbee::ClusterId clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius = 0);
|
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius = 0);
|
||||||
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataIeeeAddress(quint8 requestId, ZigbeeAddress ieeeAddress, quint8 destinationEndpoint, Zigbee::ZigbeeProfile profileId, Zigbee::ClusterId clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius = 0);
|
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataIeeeAddress(quint8 requestId, ZigbeeAddress ieeeAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, quint8 radius = 0);
|
||||||
|
ZigbeeInterfaceDeconzReply *requestSendRequest(const ZigbeeNetworkRequest &request);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ZigbeeInterfaceDeconz *m_interface = nullptr;
|
ZigbeeInterfaceDeconz *m_interface = nullptr;
|
||||||
@ -122,8 +153,11 @@ private:
|
|||||||
|
|
||||||
// Device state helper
|
// Device state helper
|
||||||
DeconzDeviceState parseDeviceStateFlag(quint8 deviceStateFlag);
|
DeconzDeviceState parseDeviceStateFlag(quint8 deviceStateFlag);
|
||||||
void processDeviceState(DeconzDeviceState deviceState);
|
|
||||||
|
|
||||||
|
void readDataIndication();
|
||||||
|
void readDataConfirm();
|
||||||
|
|
||||||
|
void processDeviceState(DeconzDeviceState deviceState);
|
||||||
void processDataIndication(const QByteArray &data);
|
void processDataIndication(const QByteArray &data);
|
||||||
void processDataConfirm(const QByteArray &data);
|
void processDataConfirm(const QByteArray &data);
|
||||||
|
|
||||||
@ -131,6 +165,9 @@ signals:
|
|||||||
void networkStateChanged(Deconz::NetworkState networkState);
|
void networkStateChanged(Deconz::NetworkState networkState);
|
||||||
void networkConfigurationParameterChanged(const DeconzNetworkConfiguration &networkConfiguration);
|
void networkConfigurationParameterChanged(const DeconzNetworkConfiguration &networkConfiguration);
|
||||||
|
|
||||||
|
void aspDataConfirmReceived(const DeconzApsDataConfirm &confirm);
|
||||||
|
void aspDataIndicationReceived(const DeconzApsDataIndication &indication);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onInterfaceAvailableChanged(bool available);
|
void onInterfaceAvailableChanged(bool available);
|
||||||
void onInterfacePackageReceived(const QByteArray &package);
|
void onInterfacePackageReceived(const QByteArray &package);
|
||||||
@ -143,6 +180,8 @@ public slots:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const DeconzDeviceState &deviceState);
|
QDebug operator<<(QDebug debug, const DeconzDeviceState &deviceState);
|
||||||
|
QDebug operator<<(QDebug debug, const DeconzApsDataConfirm &confirm);
|
||||||
|
QDebug operator<<(QDebug debug, const DeconzApsDataIndication &indication);
|
||||||
|
|
||||||
|
|
||||||
#endif // ZIGBEEBRIDGECONTROLLERDECONZ_H
|
#endif // ZIGBEEBRIDGECONTROLLERDECONZ_H
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "zigbeenetworkdeconz.h"
|
#include "zigbeenetworkdeconz.h"
|
||||||
|
#include "zigbeedeviceprofile.h"
|
||||||
#include "loggingcategory.h"
|
#include "loggingcategory.h"
|
||||||
#include "zigbeeutils.h"
|
#include "zigbeeutils.h"
|
||||||
|
|
||||||
@ -37,6 +38,8 @@ ZigbeeNetworkDeconz::ZigbeeNetworkDeconz(QObject *parent) :
|
|||||||
m_controller = new ZigbeeBridgeControllerDeconz(this);
|
m_controller = new ZigbeeBridgeControllerDeconz(this);
|
||||||
//connect(m_controller, &ZigbeeBridgeControllerDeconz::messageReceived, this, &ZigbeeNetworkDeconz::onMessageReceived);
|
//connect(m_controller, &ZigbeeBridgeControllerDeconz::messageReceived, this, &ZigbeeNetworkDeconz::onMessageReceived);
|
||||||
connect(m_controller, &ZigbeeBridgeControllerDeconz::availableChanged, this, &ZigbeeNetworkDeconz::onControllerAvailableChanged);
|
connect(m_controller, &ZigbeeBridgeControllerDeconz::availableChanged, this, &ZigbeeNetworkDeconz::onControllerAvailableChanged);
|
||||||
|
connect(m_controller, &ZigbeeBridgeControllerDeconz::aspDataConfirmReceived, this, &ZigbeeNetworkDeconz::onAspDataConfirmReceived);
|
||||||
|
connect(m_controller, &ZigbeeBridgeControllerDeconz::aspDataIndicationReceived, this, &ZigbeeNetworkDeconz::onAspDataIndicationReceived);
|
||||||
|
|
||||||
m_pollNetworkStateTimer = new QTimer(this);
|
m_pollNetworkStateTimer = new QTimer(this);
|
||||||
m_pollNetworkStateTimer->setInterval(1000);
|
m_pollNetworkStateTimer->setInterval(1000);
|
||||||
@ -52,6 +55,30 @@ ZigbeeBridgeController *ZigbeeNetworkDeconz::bridgeController() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *ZigbeeNetworkDeconz::sendRequest(const ZigbeeNetworkRequest &request)
|
||||||
|
{
|
||||||
|
ZigbeeNetworkReply *reply = createNetworkReply(request);
|
||||||
|
|
||||||
|
// Send the request, and keep the reply until transposrt, zigbee trasmission and response arrived
|
||||||
|
m_pendingReplies.insert(request.requestId(), reply);
|
||||||
|
|
||||||
|
ZigbeeInterfaceDeconzReply *interfaceReply = m_controller->requestSendRequest(request);
|
||||||
|
connect(interfaceReply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply, interfaceReply](){
|
||||||
|
if (interfaceReply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
|
qCWarning(dcZigbeeController()) << "Could send request to controller. SQN:" << interfaceReply->sequenceNumber() << interfaceReply->statusCode();
|
||||||
|
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorInterfaceError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint8 ZigbeeNetworkDeconz::generateSequenceNumber()
|
||||||
|
{
|
||||||
|
return m_sequenceNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetworkState state)
|
void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetworkState state)
|
||||||
{
|
{
|
||||||
if (m_createState == state)
|
if (m_createState == state)
|
||||||
@ -68,11 +95,13 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestChangeNetworkState(Deconz::NetworkStateOffline);
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestChangeNetworkState(Deconz::NetworkStateOffline);
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not stop network for creating a new one." << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not stop network for creating a new one. SQN:" << reply->sequenceNumber() << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "Stop network finished successfully. SQN:" << reply->sequenceNumber();
|
||||||
|
|
||||||
// Start polling the device state, should be Online -> Leaving -> Offline
|
// Start polling the device state, should be Online -> Leaving -> Offline
|
||||||
m_pollNetworkStateTimer->start();
|
m_pollNetworkStateTimer->start();
|
||||||
});
|
});
|
||||||
@ -94,12 +123,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterNodeType, paramData);
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterNodeType, paramData);
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterNodeType << Deconz::NodeTypeCoordinator << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterNodeType << Deconz::NodeTypeCoordinator << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Configured successfully bridge to" << Deconz::NodeTypeCoordinator;
|
qCDebug(dcZigbeeNetwork()) << "Configured successfully bridge to" << Deconz::NodeTypeCoordinator << "SQN:" << reply->sequenceNumber();
|
||||||
|
|
||||||
QByteArray paramData;
|
QByteArray paramData;
|
||||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||||
@ -109,12 +138,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterChannelMask, paramData);
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterChannelMask, paramData);
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterChannelMask << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterChannelMask << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Configured channel mask successfully";
|
qCDebug(dcZigbeeNetwork()) << "Configured channel mask successfully. SQN:" << reply->sequenceNumber();
|
||||||
|
|
||||||
QByteArray paramData;
|
QByteArray paramData;
|
||||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||||
@ -124,12 +153,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterApsExtendedPanId, paramData);
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterApsExtendedPanId, paramData);
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterApsExtendedPanId << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterApsExtendedPanId << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Configured APS extended PANID successfully";
|
qCDebug(dcZigbeeNetwork()) << "Configured APS extended PANID successfully. SQN:" << reply->sequenceNumber();
|
||||||
|
|
||||||
QByteArray paramData;
|
QByteArray paramData;
|
||||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||||
@ -139,12 +168,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterTrustCenterAddress, paramData);
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterTrustCenterAddress, paramData);
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterTrustCenterAddress << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterTrustCenterAddress << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Configured trust center address successfully";
|
qCDebug(dcZigbeeNetwork()) << "Configured trust center address successfully. SQN:" << reply->sequenceNumber();
|
||||||
|
|
||||||
QByteArray paramData;
|
QByteArray paramData;
|
||||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||||
@ -154,7 +183,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterSecurityMode, paramData);
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterSecurityMode, paramData);
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterSecurityMode << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterSecurityMode << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -166,12 +195,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterNetworkKey, securityConfiguration().networkKey().toByteArray());
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterNetworkKey, securityConfiguration().networkKey().toByteArray());
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not write parameter" << Deconz::ParameterNetworkKey << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not write parameter. SQN:" << reply->sequenceNumber() << Deconz::ParameterNetworkKey << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
// Note: writing the network key fails all the time...
|
// Note: writing the network key fails all the time...
|
||||||
//return;
|
//return;
|
||||||
} else {
|
} else {
|
||||||
qCDebug(dcZigbeeNetwork()) << "Configured network key successfully";
|
qCDebug(dcZigbeeNetwork()) << "Configured network key successfully. SQN:" << reply->sequenceNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuration finished, lets start the network
|
// Configuration finished, lets start the network
|
||||||
@ -188,11 +217,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestChangeNetworkState(Deconz::NetworkStateConnected);
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestChangeNetworkState(Deconz::NetworkStateConnected);
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not start network for creating a new one." << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not start network for creating a new one. SQN:" << reply->sequenceNumber() << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "Start network finished successfully. SQN:" << reply->sequenceNumber();
|
||||||
// Start polling the device state, should be Online -> Leaving -> Offline
|
// Start polling the device state, should be Online -> Leaving -> Offline
|
||||||
m_pollNetworkStateTimer->start();
|
m_pollNetworkStateTimer->start();
|
||||||
});
|
});
|
||||||
@ -203,12 +233,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->readNetworkParameters();
|
ZigbeeInterfaceDeconzReply *reply = m_controller->readNetworkParameters();
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not read network parameters during network start up." << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not read network parameters during network start up. SQN:" << reply->sequenceNumber() << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Reading network parameters finished successfully.";
|
qCDebug(dcZigbeeNetwork()) << "Reading network parameters finished successfully. SQN:" << reply->sequenceNumber();
|
||||||
|
|
||||||
setPanId(m_controller->networkConfiguration().panId);
|
setPanId(m_controller->networkConfiguration().panId);
|
||||||
setExtendedPanId(m_controller->networkConfiguration().extendedPanId);
|
setExtendedPanId(m_controller->networkConfiguration().extendedPanId);
|
||||||
@ -224,22 +254,53 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
coordinatorNode->setShortAddress(m_controller->networkConfiguration().shortAddress);
|
coordinatorNode->setShortAddress(m_controller->networkConfiguration().shortAddress);
|
||||||
coordinatorNode->setExtendedAddress(m_controller->networkConfiguration().ieeeAddress);
|
coordinatorNode->setExtendedAddress(m_controller->networkConfiguration().ieeeAddress);
|
||||||
|
|
||||||
|
addUnitializedNode(coordinatorNode);
|
||||||
|
coordinatorNode->startInitialization();
|
||||||
// TODO: done when when node initialized
|
// TODO: done when when node initialized
|
||||||
m_coordinatorNode = coordinatorNode;
|
|
||||||
addNode(coordinatorNode);
|
|
||||||
|
|
||||||
setCreateNetworkState(CreateNetworkStateIdle);
|
|
||||||
setState(StateRunning);
|
|
||||||
|
|
||||||
//addUnitializedNode(coordinatorNode);
|
|
||||||
//coordinatorNode->startInitialization();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const DeconzApsDataIndication &indication)
|
||||||
|
{
|
||||||
|
if (indication.clusterId == ZigbeeDeviceProfile::DeviceAnnounce) {
|
||||||
|
QDataStream stream(indication.asdu);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
quint8 sequenceNumber = 0; quint16 shortAddress = 0; quint64 ieeeAddress = 0; quint8 macFlag = 0;
|
||||||
|
stream >> sequenceNumber >> shortAddress >> ieeeAddress >> macFlag;
|
||||||
|
onDeviceAnnounced(shortAddress, ZigbeeAddress(ieeeAddress), macFlag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is a response for a ZDO request
|
||||||
|
foreach (ZigbeeNetworkReply *reply, m_pendingReplies) {
|
||||||
|
if (reply->request().profileId() == Zigbee::ZigbeeProfileDevice) {
|
||||||
|
// We have a reply which is waiting for a ZDO response, lets check if they match
|
||||||
|
|
||||||
|
// Check if this is the response to the sent request command
|
||||||
|
if (indication.clusterId == (reply->request().clusterId() | 0x8000)) {
|
||||||
|
// Now check if the id matches, if so set the ADPU as response to the reply, otherwise this is not the message for this reply
|
||||||
|
ZigbeeDeviceProfileAdpu deviceAdpu = ZigbeeDeviceProfile::parseAdpu(indication.asdu);
|
||||||
|
if (deviceAdpu.sequenceNumber == reply->request().requestId() && deviceAdpu.addressOfInterest == reply->request().destinationShortAddress()) {
|
||||||
|
// We found the correct reply
|
||||||
|
|
||||||
|
// Set the response payload of the
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "Indication response for ZDO request received"
|
||||||
|
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(reply->request().clusterId())
|
||||||
|
<< "-->"
|
||||||
|
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(indication.clusterId)
|
||||||
|
<< deviceAdpu;
|
||||||
|
setReplyResponseData(reply, indication.asdu);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeNode *ZigbeeNetworkDeconz::createNode(QObject *parent)
|
ZigbeeNode *ZigbeeNetworkDeconz::createNode(QObject *parent)
|
||||||
{
|
{
|
||||||
return new ZigbeeNodeDeconz(m_controller, parent);
|
return new ZigbeeNodeDeconz(this, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
|
void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
|
||||||
@ -271,7 +332,6 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
|||||||
qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().networkKey() << "network link key";
|
qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().networkKey() << "network link key";
|
||||||
qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().globalTrustCenterLinkKey() << "global trust center link key";
|
qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().globalTrustCenterLinkKey() << "global trust center link key";
|
||||||
|
|
||||||
|
|
||||||
// - Read the firmware version
|
// - Read the firmware version
|
||||||
// - Read the network configuration parameters
|
// - Read the network configuration parameters
|
||||||
// - Read the network state
|
// - Read the network state
|
||||||
@ -313,12 +373,12 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestDeviceState();
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestDeviceState();
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not read device state during network start up." << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not read device state during network start up. SQN:" << reply->sequenceNumber() << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
|
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully. SQN:" << reply->sequenceNumber();
|
||||||
QDataStream stream(reply->responseData());
|
QDataStream stream(reply->responseData());
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
quint8 deviceStateFlag = 0;
|
quint8 deviceStateFlag = 0;
|
||||||
@ -328,11 +388,19 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
|||||||
|
|
||||||
if (m_createNewNetwork) {
|
if (m_createNewNetwork) {
|
||||||
setCreateNetworkState(CreateNetworkStateStopNetwork);
|
setCreateNetworkState(CreateNetworkStateStopNetwork);
|
||||||
|
// Set offline
|
||||||
|
// Write configurations
|
||||||
|
// Set online
|
||||||
|
// Read configurations
|
||||||
|
// Create and initialize coordinator node
|
||||||
|
// Done. Save network
|
||||||
} else {
|
} else {
|
||||||
// Get the network state and start the network if required
|
// Get the network state and start the network if required
|
||||||
if (m_controller->networkState() == Deconz::NetworkStateConnected) {
|
if (m_controller->networkState() == Deconz::NetworkStateConnected) {
|
||||||
qCDebug(dcZigbeeNetwork()) << "The network is already running.";
|
qCDebug(dcZigbeeNetwork()) << "The network is already running.";
|
||||||
setState(StateRunning);
|
setState(StateRunning);
|
||||||
|
} else {
|
||||||
|
startNetwork();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -340,20 +408,6 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::createNetwork()
|
|
||||||
{
|
|
||||||
// Set offline
|
|
||||||
setCreateNetworkState(CreateNetworkStateStopNetwork);
|
|
||||||
|
|
||||||
// Write configurations
|
|
||||||
|
|
||||||
// Set online
|
|
||||||
|
|
||||||
// Read configurations
|
|
||||||
|
|
||||||
// Create and initialize coordinator node
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::onControllerAvailableChanged(bool available)
|
void ZigbeeNetworkDeconz::onControllerAvailableChanged(bool available)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeNetwork()) << "Hardware controller is" << (available ? "now available" : "not available");
|
qCDebug(dcZigbeeNetwork()) << "Hardware controller is" << (available ? "now available" : "not available");
|
||||||
@ -387,7 +441,7 @@ void ZigbeeNetworkDeconz::onPollNetworkStateTimeout()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
|
//qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
|
||||||
QDataStream stream(reply->responseData());
|
QDataStream stream(reply->responseData());
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
quint8 deviceStateFlag = 0;
|
quint8 deviceStateFlag = 0;
|
||||||
@ -409,12 +463,12 @@ void ZigbeeNetworkDeconz::onPollNetworkStateTimeout()
|
|||||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestDeviceState();
|
ZigbeeInterfaceDeconzReply *reply = m_controller->requestDeviceState();
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not read device state during network start up." << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not read device state during network start up. SQN:" << reply->sequenceNumber() << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
|
//qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully. SQN:" << reply->sequenceNumber();
|
||||||
QDataStream stream(reply->responseData());
|
QDataStream stream(reply->responseData());
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
quint8 deviceStateFlag = 0;
|
quint8 deviceStateFlag = 0;
|
||||||
@ -442,6 +496,42 @@ void ZigbeeNetworkDeconz::onPollNetworkStateTimeout()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetworkDeconz::onAspDataConfirmReceived(const DeconzApsDataConfirm &confirm)
|
||||||
|
{
|
||||||
|
qCDebug(dcZigbeeNetwork()) << confirm;
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *reply = m_pendingReplies.take(confirm.requestId);
|
||||||
|
if (!reply) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Received confirmation but could not find any reply. Ignoring the confirmation";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorNoError, static_cast<Zigbee::ZigbeeStatus>(confirm.zigbeeStatusCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetworkDeconz::onAspDataIndicationReceived(const DeconzApsDataIndication &indication)
|
||||||
|
{
|
||||||
|
qCDebug(dcZigbeeNetwork()) << indication;
|
||||||
|
|
||||||
|
// Check if this indocation is related to any pending reply
|
||||||
|
if (indication.profileId == Zigbee::ZigbeeProfileDevice) {
|
||||||
|
handleZigbeeDeviceProfileIndication(indication);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find reply finish it
|
||||||
|
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "Unhandled indication" << indication;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetworkDeconz::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities)
|
||||||
|
{
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "Device announced" << ZigbeeUtils::convertUint16ToHexString(shortAddress) << ieeeAddress.toString() << ZigbeeUtils::convertByteToHexString(macCapabilities);
|
||||||
|
// Create node and initialize it
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::startNetwork()
|
void ZigbeeNetworkDeconz::startNetwork()
|
||||||
{
|
{
|
||||||
loadNetwork();
|
loadNetwork();
|
||||||
@ -466,12 +556,12 @@ void ZigbeeNetworkDeconz::stopNetwork()
|
|||||||
setState(StateStopping);
|
setState(StateStopping);
|
||||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||||
qCWarning(dcZigbeeController()) << "Could not leave network." << reply->statusCode();
|
qCWarning(dcZigbeeController()) << "Could not leave network. SQN:" << reply->sequenceNumber() << reply->statusCode();
|
||||||
// FIXME: set an appropriate error
|
// FIXME: set an appropriate error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Network left successfully";
|
qCDebug(dcZigbeeNetwork()) << "Network left successfully. SQN:" << reply->sequenceNumber();
|
||||||
setState(StateOffline);
|
setState(StateOffline);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,9 @@ public:
|
|||||||
|
|
||||||
ZigbeeBridgeController *bridgeController() const override;
|
ZigbeeBridgeController *bridgeController() const override;
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override;
|
||||||
|
|
||||||
|
quint8 generateSequenceNumber();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
|
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
|
||||||
@ -61,9 +63,16 @@ private:
|
|||||||
CreateNetworkState m_createState = CreateNetworkStateIdle;
|
CreateNetworkState m_createState = CreateNetworkStateIdle;
|
||||||
bool m_createNewNetwork = false;
|
bool m_createNewNetwork = false;
|
||||||
|
|
||||||
|
QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies;
|
||||||
|
|
||||||
|
quint8 m_sequenceNumber = 0;
|
||||||
|
|
||||||
QTimer *m_pollNetworkStateTimer = nullptr;
|
QTimer *m_pollNetworkStateTimer = nullptr;
|
||||||
void setCreateNetworkState(CreateNetworkState state);
|
void setCreateNetworkState(CreateNetworkState state);
|
||||||
|
|
||||||
|
void handleZigbeeDeviceProfileIndication(const DeconzApsDataIndication &indication);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ZigbeeNode *createNode(QObject *parent) override;
|
ZigbeeNode *createNode(QObject *parent) override;
|
||||||
|
|
||||||
@ -71,12 +80,15 @@ protected:
|
|||||||
|
|
||||||
void startNetworkInternally();
|
void startNetworkInternally();
|
||||||
|
|
||||||
void createNetwork();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onControllerAvailableChanged(bool available);
|
void onControllerAvailableChanged(bool available);
|
||||||
void onPollNetworkStateTimeout();
|
void onPollNetworkStateTimeout();
|
||||||
|
|
||||||
|
void onAspDataConfirmReceived(const DeconzApsDataConfirm &confirm);
|
||||||
|
void onAspDataIndicationReceived(const DeconzApsDataIndication &indication);
|
||||||
|
|
||||||
|
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void startNetwork() override;
|
void startNetwork() override;
|
||||||
void stopNetwork() override;
|
void stopNetwork() override;
|
||||||
|
|||||||
@ -26,10 +26,15 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "zigbeenodedeconz.h"
|
#include "zigbeenodedeconz.h"
|
||||||
|
#include "zigbeedeviceprofile.h"
|
||||||
|
#include "zigbeenetworkdeconz.h"
|
||||||
|
#include "loggingcategory.h"
|
||||||
|
|
||||||
ZigbeeNodeDeconz::ZigbeeNodeDeconz(ZigbeeBridgeControllerDeconz *controller, QObject *parent) :
|
#include <QDataStream>
|
||||||
|
|
||||||
|
ZigbeeNodeDeconz::ZigbeeNodeDeconz(ZigbeeNetworkDeconz *network, QObject *parent) :
|
||||||
ZigbeeNode(parent),
|
ZigbeeNode(parent),
|
||||||
m_controller(controller)
|
m_network(network)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -47,6 +52,40 @@ void ZigbeeNodeDeconz::setClusterAttributeReport(const ZigbeeClusterAttributeRep
|
|||||||
|
|
||||||
void ZigbeeNodeDeconz::startInitialization()
|
void ZigbeeNodeDeconz::startInitialization()
|
||||||
{
|
{
|
||||||
|
setState(StateInitializing);
|
||||||
|
|
||||||
|
// Get the node descriptor
|
||||||
|
ZigbeeNetworkRequest request;
|
||||||
|
request.setRequestId(m_network->generateSequenceNumber());
|
||||||
|
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||||
|
request.setDestinationShortAddress(shortAddress());
|
||||||
|
request.setDestinationEndpoint(0); // ZDO
|
||||||
|
request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP
|
||||||
|
request.setClusterId(ZigbeeDeviceProfile::NodeDescriptorRequest);
|
||||||
|
request.setSourceEndpoint(0); // ZDO
|
||||||
|
|
||||||
|
// Build ASDU
|
||||||
|
QByteArray asdu;
|
||||||
|
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
stream << request.requestId() << request.destinationShortAddress();
|
||||||
|
request.setAsdu(asdu);
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *reply = m_network->sendRequest(request);
|
||||||
|
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
||||||
|
// TODO: check reply error
|
||||||
|
|
||||||
|
ZigbeeDeviceProfileAdpu adpu = ZigbeeDeviceProfile::parseAdpu(reply->responseData());
|
||||||
|
qCDebug(dcZigbeeNode()) << "Node descriptor request finished" << adpu;
|
||||||
|
setNodeDescriptorRawData(reply->responseData());
|
||||||
|
|
||||||
|
QDataStream stream(adpu.payload);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
/* Node initialisation steps (sequentially)
|
/* Node initialisation steps (sequentially)
|
||||||
* - Node descriptor
|
* - Node descriptor
|
||||||
* - Power descriptor
|
* - Power descriptor
|
||||||
|
|||||||
@ -32,7 +32,8 @@
|
|||||||
|
|
||||||
#include "zigbee.h"
|
#include "zigbee.h"
|
||||||
#include "zigbeenode.h"
|
#include "zigbeenode.h"
|
||||||
#include "zigbeebridgecontrollerdeconz.h"
|
|
||||||
|
class ZigbeeNetworkDeconz;
|
||||||
|
|
||||||
class ZigbeeNodeDeconz : public ZigbeeNode
|
class ZigbeeNodeDeconz : public ZigbeeNode
|
||||||
{
|
{
|
||||||
@ -41,12 +42,12 @@ class ZigbeeNodeDeconz : public ZigbeeNode
|
|||||||
friend class ZigbeeNetworkDeconz;
|
friend class ZigbeeNetworkDeconz;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ZigbeeNodeDeconz(ZigbeeBridgeControllerDeconz *controller, QObject *parent = nullptr);
|
explicit ZigbeeNodeDeconz(ZigbeeNetworkDeconz *network, QObject *parent = nullptr);
|
||||||
|
|
||||||
void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) override;
|
void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
|
ZigbeeNetworkDeconz *m_network = nullptr;
|
||||||
|
|
||||||
void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) override;
|
void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) override;
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,6 @@ SOURCES += \
|
|||||||
zigbeechannelmask.cpp \
|
zigbeechannelmask.cpp \
|
||||||
zigbeecluster.cpp \
|
zigbeecluster.cpp \
|
||||||
zigbeeclusterattribute.cpp \
|
zigbeeclusterattribute.cpp \
|
||||||
zigbeedeviceobject.cpp \
|
|
||||||
zigbeedeviceprofile.cpp \
|
zigbeedeviceprofile.cpp \
|
||||||
zigbeemanufacturer.cpp \
|
zigbeemanufacturer.cpp \
|
||||||
zigbeenetwork.cpp \
|
zigbeenetwork.cpp \
|
||||||
@ -60,7 +59,6 @@ HEADERS += \
|
|||||||
zigbeechannelmask.h \
|
zigbeechannelmask.h \
|
||||||
zigbeecluster.h \
|
zigbeecluster.h \
|
||||||
zigbeeclusterattribute.h \
|
zigbeeclusterattribute.h \
|
||||||
zigbeedeviceobject.h \
|
|
||||||
zigbeedeviceprofile.h \
|
zigbeedeviceprofile.h \
|
||||||
zigbeemanufacturer.h \
|
zigbeemanufacturer.h \
|
||||||
zigbeenetwork.h \
|
zigbeenetwork.h \
|
||||||
|
|||||||
@ -265,6 +265,13 @@ void ZigbeeNetworkNxp::readPermitJoinStatus()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &request)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
qCCritical(dcZigbeeNetwork()) << "Cannot send request. Not implemented for this backend";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeNode *ZigbeeNetworkNxp::createNode(QObject *parent)
|
ZigbeeNode *ZigbeeNetworkNxp::createNode(QObject *parent)
|
||||||
{
|
{
|
||||||
return new ZigbeeNodeNxp(m_controller, parent);
|
return new ZigbeeNodeNxp(m_controller, parent);
|
||||||
|
|||||||
@ -62,6 +62,9 @@ private:
|
|||||||
void readControllerVersion();
|
void readControllerVersion();
|
||||||
void readPermitJoinStatus();
|
void readPermitJoinStatus();
|
||||||
|
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ZigbeeNode *createNode(QObject *parent) override;
|
ZigbeeNode *createNode(QObject *parent) override;
|
||||||
void setPermitJoiningInternal(bool permitJoining) override;
|
void setPermitJoiningInternal(bool permitJoining) override;
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
||||||
*
|
|
||||||
* Copyright 2013 - 2020, nymea GmbH
|
|
||||||
* Contact: contact@nymea.io
|
|
||||||
*
|
|
||||||
* This file is part of nymea-zigbee.
|
|
||||||
* This project including source code and documentation is protected by copyright law, and
|
|
||||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
|
||||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
|
||||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
|
||||||
* of use of nymea GmbH, available under https://nymea.io/license
|
|
||||||
*
|
|
||||||
* GNU Lesser General Public License Usage
|
|
||||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
|
||||||
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
|
||||||
* If not, see <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 "zigbeedeviceobject.h"
|
|
||||||
|
|
||||||
ZigbeeDeviceObject::ZigbeeDeviceObject(QObject *parent) : QObject(parent)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
||||||
*
|
|
||||||
* Copyright 2013 - 2020, nymea GmbH
|
|
||||||
* Contact: contact@nymea.io
|
|
||||||
*
|
|
||||||
* This file is part of nymea-zigbee.
|
|
||||||
* This project including source code and documentation is protected by copyright law, and
|
|
||||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
|
||||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
|
||||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
|
||||||
* of use of nymea GmbH, available under https://nymea.io/license
|
|
||||||
*
|
|
||||||
* GNU Lesser General Public License Usage
|
|
||||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
|
||||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
|
||||||
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
|
||||||
* If not, see <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 ZIGBEEDEVICEOBJECT_H
|
|
||||||
#define ZIGBEEDEVICEOBJECT_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
class ZigbeeDeviceObject : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit ZigbeeDeviceObject(QObject *parent = nullptr);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ZIGBEEDEVICEOBJECT_H
|
|
||||||
@ -26,3 +26,28 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "zigbeedeviceprofile.h"
|
#include "zigbeedeviceprofile.h"
|
||||||
|
#include "zigbeeutils.h"
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
ZigbeeDeviceProfileAdpu ZigbeeDeviceProfile::parseAdpu(const QByteArray &adpu)
|
||||||
|
{
|
||||||
|
QDataStream stream(adpu);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
|
||||||
|
ZigbeeDeviceProfileAdpu deviceAdpu;
|
||||||
|
quint8 statusFlag = 0;
|
||||||
|
stream >> deviceAdpu.sequenceNumber >> statusFlag >> deviceAdpu.addressOfInterest;
|
||||||
|
deviceAdpu.status = static_cast<Zigbee::ZigbeeStatus>(statusFlag);
|
||||||
|
deviceAdpu.payload = adpu.right(adpu.length() - 4);
|
||||||
|
return deviceAdpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfileAdpu &deviceAdpu)
|
||||||
|
{
|
||||||
|
debug.nospace() << "DeviceAdpu(SQN: " << deviceAdpu.sequenceNumber << ", ";
|
||||||
|
debug.nospace() << deviceAdpu.status << ", ";
|
||||||
|
debug.nospace() << ZigbeeUtils::convertUint16ToHexString(deviceAdpu.addressOfInterest) << ", ";
|
||||||
|
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(deviceAdpu.payload) << ")";
|
||||||
|
return debug.space();
|
||||||
|
}
|
||||||
|
|||||||
@ -28,14 +28,23 @@
|
|||||||
#ifndef ZIGBEEDEVICEPROFILE_H
|
#ifndef ZIGBEEDEVICEPROFILE_H
|
||||||
#define ZIGBEEDEVICEPROFILE_H
|
#define ZIGBEEDEVICEPROFILE_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "zigbee.h"
|
||||||
|
|
||||||
|
typedef struct ZigbeeDeviceProfileAdpu {
|
||||||
|
quint8 sequenceNumber = 0;
|
||||||
|
Zigbee::ZigbeeStatus status = Zigbee::ZigbeeStatusSuccess;
|
||||||
|
quint16 addressOfInterest = 0;
|
||||||
|
QByteArray payload;
|
||||||
|
} ZigbeeDeviceProfileAdpu;
|
||||||
|
|
||||||
class ZigbeeDeviceProfile
|
class ZigbeeDeviceProfile
|
||||||
{
|
{
|
||||||
Q_GADGET
|
Q_GADGET
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum ZdoCommand {
|
enum ZdoCommand {
|
||||||
/* Requests */
|
/* Requests */
|
||||||
/*Device and service discovery */
|
/*Device and service discovery */
|
||||||
@ -136,9 +145,11 @@ public:
|
|||||||
MgmtCacheResponse = 0x8037,
|
MgmtCacheResponse = 0x8037,
|
||||||
MgmtNetworkUpdateResponse = 0x8038
|
MgmtNetworkUpdateResponse = 0x8038
|
||||||
};
|
};
|
||||||
|
Q_ENUM(ZdoCommand)
|
||||||
|
|
||||||
|
static ZigbeeDeviceProfileAdpu parseAdpu(const QByteArray &adpu);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfileAdpu &deviceAdpu);
|
||||||
|
|
||||||
#endif // ZIGBEEDEVICEPROFILE_H
|
#endif // ZIGBEEDEVICEPROFILE_H
|
||||||
|
|||||||
@ -378,6 +378,9 @@ void ZigbeeNetwork::saveNode(ZigbeeNode *node)
|
|||||||
settings.beginGroup(node->extendedAddress().toString());
|
settings.beginGroup(node->extendedAddress().toString());
|
||||||
settings.setValue("nwkAddress", node->shortAddress());
|
settings.setValue("nwkAddress", node->shortAddress());
|
||||||
settings.setValue("macCapabilitiesFlag", node->m_macCapabilitiesFlag);
|
settings.setValue("macCapabilitiesFlag", node->m_macCapabilitiesFlag);
|
||||||
|
settings.setValue("manufacturerCode", node->m_manufacturerCode);
|
||||||
|
|
||||||
|
|
||||||
settings.setValue("nodeDescriptorRawData", node->m_nodeDescriptorRawData);
|
settings.setValue("nodeDescriptorRawData", node->m_nodeDescriptorRawData);
|
||||||
settings.setValue("powerDescriptorFlag", node->m_powerDescriptorFlag);
|
settings.setValue("powerDescriptorFlag", node->m_powerDescriptorFlag);
|
||||||
|
|
||||||
@ -491,6 +494,26 @@ bool ZigbeeNetwork::networkConfigurationAvailable() const
|
|||||||
return m_extendedPanId != 0 && m_channel != 0;
|
return m_extendedPanId != 0 && m_channel != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeNetworkReply *ZigbeeNetwork::createNetworkReply(const ZigbeeNetworkRequest &request)
|
||||||
|
{
|
||||||
|
ZigbeeNetworkReply *reply = new ZigbeeNetworkReply(request, this);
|
||||||
|
// Make sure the reply will be deleted
|
||||||
|
connect(reply, &ZigbeeNetworkReply::finished, reply, &ZigbeeNetworkReply::deleteLater);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetwork::setReplyResponseData(ZigbeeNetworkReply *reply, const QByteArray &responseData)
|
||||||
|
{
|
||||||
|
reply->m_responseData = responseData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetwork::finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error, Zigbee::ZigbeeStatus zigbeeStatus)
|
||||||
|
{
|
||||||
|
reply->m_error = error;
|
||||||
|
reply->m_zigbeeStatus = zigbeeStatus;
|
||||||
|
reply->finished();
|
||||||
|
}
|
||||||
|
|
||||||
void ZigbeeNetwork::onNodeStateChanged(ZigbeeNode::State state)
|
void ZigbeeNetwork::onNodeStateChanged(ZigbeeNode::State state)
|
||||||
{
|
{
|
||||||
ZigbeeNode *node = qobject_cast<ZigbeeNode *>(sender());
|
ZigbeeNode *node = qobject_cast<ZigbeeNode *>(sender());
|
||||||
|
|||||||
@ -94,6 +94,8 @@ public:
|
|||||||
bool permitJoining() const;
|
bool permitJoining() const;
|
||||||
void setPermitJoining(bool permitJoining);
|
void setPermitJoining(bool permitJoining);
|
||||||
|
|
||||||
|
|
||||||
|
// Network nodes
|
||||||
QList<ZigbeeNode *> nodes() const;
|
QList<ZigbeeNode *> nodes() const;
|
||||||
|
|
||||||
ZigbeeNode *coordinatorNode() const;
|
ZigbeeNode *coordinatorNode() const;
|
||||||
@ -150,6 +152,13 @@ protected:
|
|||||||
|
|
||||||
bool networkConfigurationAvailable() const;
|
bool networkConfigurationAvailable() const;
|
||||||
|
|
||||||
|
virtual ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) = 0;
|
||||||
|
|
||||||
|
// Network reply methods
|
||||||
|
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
|
||||||
|
void setReplyResponseData(ZigbeeNetworkReply *reply, const QByteArray &responseData);
|
||||||
|
void finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error = ZigbeeNetworkReply::ErrorNoError, Zigbee::ZigbeeStatus zigbeeStatus = Zigbee::ZigbeeStatusSuccess);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void settingsFileNameChanged(const QString &settingsFileName);
|
void settingsFileNameChanged(const QString &settingsFileName);
|
||||||
void serialPortNameChanged(const QString &serialPortName);
|
void serialPortNameChanged(const QString &serialPortName);
|
||||||
|
|||||||
@ -42,6 +42,11 @@ Zigbee::ZigbeeStatus ZigbeeNetworkReply::zigbeeStatus() const
|
|||||||
return m_zigbeeStatus;
|
return m_zigbeeStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray ZigbeeNetworkReply::responseData() const
|
||||||
|
{
|
||||||
|
return m_responseData;
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent) :
|
ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
m_request(request)
|
m_request(request)
|
||||||
|
|||||||
@ -37,20 +37,25 @@ class ZigbeeNetworkReply : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class ZigbeeNetwork;
|
||||||
friend class ZigbeeNodeEndpoint;
|
friend class ZigbeeNodeEndpoint;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Error {
|
enum Error {
|
||||||
ErrorNoError,
|
ErrorNoError,
|
||||||
ErrorZigbeeStatusError,
|
ErrorZigbeeStatusError,
|
||||||
|
ErrorInterfaceError,
|
||||||
ErrorNetworkOffline,
|
ErrorNetworkOffline,
|
||||||
|
ErrorNetworkNotImplemented,
|
||||||
ErrorUnknown
|
ErrorUnknown
|
||||||
};
|
};
|
||||||
Q_ENUM(Error)
|
Q_ENUM(Error)
|
||||||
|
|
||||||
|
|
||||||
Error error() const;
|
Error error() const;
|
||||||
ZigbeeNetworkRequest request() const;
|
ZigbeeNetworkRequest request() const;
|
||||||
Zigbee::ZigbeeStatus zigbeeStatus() const;
|
Zigbee::ZigbeeStatus zigbeeStatus() const;
|
||||||
|
QByteArray responseData() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr);
|
explicit ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr);
|
||||||
@ -59,6 +64,7 @@ private:
|
|||||||
bool m_finished = false;
|
bool m_finished = false;
|
||||||
Error m_error = ErrorNoError;
|
Error m_error = ErrorNoError;
|
||||||
Zigbee::ZigbeeStatus m_zigbeeStatus = Zigbee::ZigbeeStatusSuccess;
|
Zigbee::ZigbeeStatus m_zigbeeStatus = Zigbee::ZigbeeStatusSuccess;
|
||||||
|
QByteArray m_responseData;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished();
|
void finished();
|
||||||
|
|||||||
@ -156,20 +156,6 @@ private:
|
|||||||
quint16 m_shortAddress = 0;
|
quint16 m_shortAddress = 0;
|
||||||
ZigbeeAddress m_extendedAddress;
|
ZigbeeAddress m_extendedAddress;
|
||||||
|
|
||||||
// Node descriptor information
|
|
||||||
QByteArray m_nodeDescriptorRawData;
|
|
||||||
NodeType m_nodeType = NodeTypeRouter;
|
|
||||||
FrequencyBand m_frequencyBand = FrequencyBand2400Mhz;
|
|
||||||
Relationship m_relationship = Parent;
|
|
||||||
quint16 m_manufacturerCode = 0;
|
|
||||||
|
|
||||||
bool m_complexDescriptorAvailable = false;
|
|
||||||
bool m_userDescriptorAvailable = false;
|
|
||||||
|
|
||||||
quint16 m_maximumRxSize = 0;
|
|
||||||
quint16 m_maximumTxSize = 0;
|
|
||||||
quint8 m_maximumBufferSize = 0;
|
|
||||||
|
|
||||||
// Server Mask
|
// Server Mask
|
||||||
quint16 m_serverMask = 0;
|
quint16 m_serverMask = 0;
|
||||||
bool m_isPrimaryTrustCenter = false;
|
bool m_isPrimaryTrustCenter = false;
|
||||||
@ -208,6 +194,20 @@ protected:
|
|||||||
|
|
||||||
QList<ZigbeeNodeEndpoint *> m_endpoints;
|
QList<ZigbeeNodeEndpoint *> m_endpoints;
|
||||||
|
|
||||||
|
// Node descriptor information
|
||||||
|
QByteArray m_nodeDescriptorRawData;
|
||||||
|
NodeType m_nodeType = NodeTypeRouter;
|
||||||
|
FrequencyBand m_frequencyBand = FrequencyBand2400Mhz;
|
||||||
|
Relationship m_relationship = Parent;
|
||||||
|
quint16 m_manufacturerCode = 0;
|
||||||
|
|
||||||
|
bool m_complexDescriptorAvailable = false;
|
||||||
|
bool m_userDescriptorAvailable = false;
|
||||||
|
|
||||||
|
quint16 m_maximumRxSize = 0;
|
||||||
|
quint16 m_maximumTxSize = 0;
|
||||||
|
quint8 m_maximumBufferSize = 0;
|
||||||
|
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
void setConnected(bool connected);
|
void setConnected(bool connected);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user