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
|
||||
|
||||
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
|
||||
|
||||
* JN5168 (SoM)
|
||||
* 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);
|
||||
}
|
||||
|
||||
m_serialPort->flush();
|
||||
//m_serialPort->flush();
|
||||
}
|
||||
|
||||
bool ZigbeeInterfaceDeconz::enable(const QString &serialPort, qint32 baudrate)
|
||||
|
||||
@ -60,8 +60,18 @@ void ZigbeeInterfaceDeconzReply::abort()
|
||||
|
||||
ZigbeeInterfaceDeconzReply::ZigbeeInterfaceDeconzReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_timer(new QTimer(this)),
|
||||
m_command(command),
|
||||
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
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include "deconz.h"
|
||||
|
||||
@ -47,12 +48,14 @@ public:
|
||||
// Response content
|
||||
Deconz::StatusCode statusCode() const;
|
||||
|
||||
bool timeout() const;
|
||||
bool aborted() const;
|
||||
void abort();
|
||||
|
||||
private:
|
||||
explicit ZigbeeInterfaceDeconzReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent = nullptr);
|
||||
|
||||
QTimer *m_timer = nullptr;
|
||||
bool m_timeout = false;
|
||||
bool m_aborted = false;
|
||||
|
||||
// Request content
|
||||
@ -63,7 +66,11 @@ private:
|
||||
Deconz::StatusCode m_statusCode = Deconz::StatusCodeError;
|
||||
QByteArray m_responseData;
|
||||
|
||||
private slots:
|
||||
void onTimeout();
|
||||
|
||||
signals:
|
||||
void timeout();
|
||||
void finished();
|
||||
|
||||
};
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "zigbeebridgecontrollerdeconz.h"
|
||||
#include "loggingcategory.h"
|
||||
#include "zigbeeutils.h"
|
||||
#include "zigbeedeviceprofile.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
@ -219,7 +220,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestQuerySendDataCo
|
||||
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();
|
||||
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>(0); // Reserverd
|
||||
stream << static_cast<quint16>(7 + payloadLength); // Frame length
|
||||
stream << static_cast<quint16>(payloadLength);
|
||||
stream << payloadLength;
|
||||
stream << requestId;
|
||||
stream << static_cast<quint8>(0); // Flags
|
||||
stream << static_cast<quint8>(Zigbee::DestinationAddressModeGroup);
|
||||
stream << groupAddress << destinationEndpoint;
|
||||
stream << static_cast<quint16>(profileId);
|
||||
stream << static_cast<quint16>(clusterId);
|
||||
stream << profileId;
|
||||
stream << clusterId;
|
||||
stream << sourceEndpoint;
|
||||
stream << static_cast<quint16>(asdu.length());
|
||||
for (int i = 0; i < asdu.length(); i++) {
|
||||
@ -260,7 +261,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
||||
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();
|
||||
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>(0); // Reserverd
|
||||
stream << static_cast<quint16>(7 + payloadLength); // Frame length
|
||||
stream << static_cast<quint16>(payloadLength);
|
||||
stream << payloadLength;
|
||||
stream << requestId;
|
||||
stream << static_cast<quint8>(0); // Flags
|
||||
stream << static_cast<quint8>(Zigbee::DestinationAddressModeShortAddress);
|
||||
stream << shortAddress << destinationEndpoint;
|
||||
stream << static_cast<quint16>(profileId);
|
||||
stream << static_cast<quint16>(clusterId);
|
||||
stream << profileId;
|
||||
stream << clusterId;
|
||||
stream << sourceEndpoint;
|
||||
stream << static_cast<quint16>(asdu.length());
|
||||
for (int i = 0; i < asdu.length(); i++) {
|
||||
@ -301,7 +302,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
||||
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();
|
||||
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>(0); // Reserverd
|
||||
stream << static_cast<quint16>(7 + payloadLength); // Frame length
|
||||
stream << static_cast<quint16>(payloadLength);
|
||||
stream << payloadLength;
|
||||
stream << requestId;
|
||||
stream << static_cast<quint8>(0); // Flags
|
||||
stream << static_cast<quint8>(Zigbee::DestinationAddressModeIeeeAddress);
|
||||
stream << ieeeAddress.toUInt64() << destinationEndpoint;
|
||||
stream << static_cast<quint16>(profileId);
|
||||
stream << static_cast<quint16>(clusterId);
|
||||
stream << profileId;
|
||||
stream << clusterId;
|
||||
stream << sourceEndpoint;
|
||||
stream << static_cast<quint16>(asdu.length());
|
||||
for (int i = 0; i < asdu.length(); i++) {
|
||||
@ -342,6 +343,30 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
||||
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()
|
||||
{
|
||||
return m_sequenceNumber++;
|
||||
@ -358,6 +383,9 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::createReply(Deconz::Co
|
||||
// Add it to the pending list
|
||||
m_pendingReplies.insert(sequenceNumber, reply);
|
||||
|
||||
// Fixme: start the timer once actually sent to the interface
|
||||
reply->m_timer->start();
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
@ -712,6 +740,38 @@ DeconzDeviceState ZigbeeBridgeControllerDeconz::parseDeviceStateFlag(quint8 devi
|
||||
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)
|
||||
{
|
||||
qCDebug(dcZigbeeController()) << deviceState;
|
||||
@ -732,36 +792,16 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
|
||||
if (m_networkState != Deconz::NetworkStateConnected)
|
||||
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
|
||||
if (deviceState.aspDataIndication) {
|
||||
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());
|
||||
});
|
||||
readDataIndication();
|
||||
}
|
||||
|
||||
// Check if we have a response to read for a request
|
||||
if (deviceState.aspDataConfirm) {
|
||||
ZigbeeInterfaceDeconzReply *reply = requestQuerySendDataConfirm();
|
||||
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());
|
||||
});
|
||||
readDataConfirm();
|
||||
}
|
||||
|
||||
}
|
||||
@ -771,104 +811,76 @@ void ZigbeeBridgeControllerDeconz::processDataIndication(const QByteArray &data)
|
||||
// ASP data indication
|
||||
QDataStream stream(data);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 destinationAddressModeFlag = 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;
|
||||
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 reserved = 0; quint16 asduLength = 0;
|
||||
|
||||
stream >> payloadLenght >> deviceStateFlag >> destinationAddressModeFlag;
|
||||
Zigbee::DestinationAddressMode destinationAddressMode = static_cast<Zigbee::DestinationAddressMode>(destinationAddressModeFlag);
|
||||
DeconzApsDataIndication indication;
|
||||
stream >> payloadLenght >> deviceStateFlag;
|
||||
stream >> indication.destinationAddressMode;
|
||||
Zigbee::DestinationAddressMode destinationAddressMode = static_cast<Zigbee::DestinationAddressMode>(indication.destinationAddressMode);
|
||||
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup || destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
||||
stream >> destinationShortAddress;
|
||||
stream >> indication.destinationShortAddress;
|
||||
|
||||
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)
|
||||
stream >> sourceShortAddress;
|
||||
stream >> indication.sourceShortAddress;
|
||||
|
||||
if (sourceAddressMode == Zigbee::SourceAddressModeIeeeAddress || sourceAddressMode == Zigbee::SourceAddressModeShortAndIeeeAddress)
|
||||
stream >> sourceIeeeAddress;
|
||||
|
||||
stream >> sourceEndpoint >> profileId >> clusterId >> asduLength;
|
||||
stream >> indication.sourceIeeeAddress;
|
||||
|
||||
stream >> indication.sourceEndpoint >> indication.profileId >> indication.clusterId >> asduLength;
|
||||
// Fill asdu data
|
||||
for (int i = 0; i < asduLength; i++) {
|
||||
quint8 byte = 0;
|
||||
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
|
||||
qCDebug(dcZigbeeController()) << "Data indication received:";
|
||||
qCDebug(dcZigbeeController()) << " Destination address mode:" << destinationAddressMode;
|
||||
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup)
|
||||
qCDebug(dcZigbeeController()) << " Destination address (group):" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
|
||||
qCDebug(dcZigbeeController()) << indication;
|
||||
|
||||
if (destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
||||
qCDebug(dcZigbeeController()) << " Destination short address:" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
|
||||
emit aspDataIndicationReceived(indication);
|
||||
|
||||
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
||||
qCDebug(dcZigbeeController()) << " Destination IEEE address:" << ZigbeeAddress(destinationIeeeAddress).toString();
|
||||
|
||||
qCDebug(dcZigbeeController()) << " Destination endpoint" << ZigbeeUtils::convertByteToHexString(destinationEndpoint);
|
||||
|
||||
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));
|
||||
// Process the device state in order to check if we have to request another indication
|
||||
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
|
||||
if (deviceState.aspDataIndication) {
|
||||
readDataIndication();
|
||||
}
|
||||
}
|
||||
|
||||
void ZigbeeBridgeControllerDeconz::processDataConfirm(const QByteArray &data)
|
||||
{
|
||||
QDataStream stream(data);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 requestId = 0; quint8 destinationAddressMode = 0;
|
||||
quint16 destinationShortAddress = 0; quint64 destinationIeeeAddress = 0; quint8 destinationEndpoint = 0;
|
||||
quint8 sourceEndpoint = 0; quint8 zigbeeConfirmStatus = 0;
|
||||
DeconzApsDataConfirm confirm;
|
||||
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0;
|
||||
stream >> payloadLenght >> deviceStateFlag;
|
||||
stream >> confirm.requestId >> confirm.destinationAddressMode;
|
||||
|
||||
stream >> payloadLenght >> deviceStateFlag >> requestId >> destinationAddressMode;
|
||||
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup || destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
||||
stream >> destinationShortAddress;
|
||||
if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeGroup || confirm.destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
||||
stream >> confirm.destinationShortAddress;
|
||||
|
||||
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
||||
stream >> destinationIeeeAddress;
|
||||
if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
||||
stream >> confirm.destinationIeeeAddress;
|
||||
|
||||
stream >> destinationEndpoint >> sourceEndpoint >> zigbeeConfirmStatus;
|
||||
stream >> confirm.destinationEndpoint >> confirm.sourceEndpoint >> confirm.zigbeeStatusCode;
|
||||
|
||||
// Print the information for debugging
|
||||
qCDebug(dcZigbeeController()) << "Data confirm received: Request" << requestId;
|
||||
qCDebug(dcZigbeeController()) << " Destination address mode:" << destinationAddressMode;
|
||||
if (destinationAddressMode == Zigbee::DestinationAddressModeGroup)
|
||||
qCDebug(dcZigbeeController()) << " Destination address (group):" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
|
||||
qCDebug(dcZigbeeController()) << confirm;
|
||||
|
||||
if (destinationAddressMode == Zigbee::DestinationAddressModeShortAddress)
|
||||
qCDebug(dcZigbeeController()) << " Destination short address:" << ZigbeeUtils::convertUint16ToHexString(destinationShortAddress);
|
||||
emit aspDataConfirmReceived(confirm);
|
||||
|
||||
if (destinationAddressMode == Zigbee::DestinationAddressModeIeeeAddress)
|
||||
qCDebug(dcZigbeeController()) << " Destination IEEE address:" << ZigbeeAddress(destinationIeeeAddress).toString();
|
||||
|
||||
qCDebug(dcZigbeeController()) << " Destination endpoint" << ZigbeeUtils::convertByteToHexString(destinationEndpoint);
|
||||
qCDebug(dcZigbeeController()) << " Source endpoint" << ZigbeeUtils::convertByteToHexString(sourceEndpoint);
|
||||
qCDebug(dcZigbeeController()) << " Confirm status" << static_cast<Zigbee::ZigbeeStatus>(zigbeeConfirmStatus);
|
||||
// Process the device state in order to check if we have to request another indication
|
||||
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
|
||||
if (deviceState.aspDataConfirm) {
|
||||
readDataConfirm();
|
||||
}
|
||||
}
|
||||
|
||||
void ZigbeeBridgeControllerDeconz::onInterfaceAvailableChanged(bool available)
|
||||
@ -899,8 +911,8 @@ void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray &
|
||||
QByteArray data = package.right(package.length() - 5);
|
||||
Deconz::Command command = static_cast<Deconz::Command>(commandInt);
|
||||
Deconz::StatusCode status = static_cast<Deconz::StatusCode>(statusInt);
|
||||
qCDebug(dcZigbeeController()) << "Interface message received" << command << "SQN:" << sequenceNumber
|
||||
<< status << "Frame length:" << frameLength << ZigbeeUtils::convertByteArrayToHexString(data);
|
||||
//qCDebug(dcZigbeeController()) << "Interface message received" << command << "SQN:" << sequenceNumber
|
||||
// << status << "Frame length:" << frameLength << ZigbeeUtils::convertByteArrayToHexString(data);
|
||||
|
||||
// Check if this is an interface response for a pending reply
|
||||
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 << ")";
|
||||
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 "zigbeeaddress.h"
|
||||
#include "zigbeenetworkkey.h"
|
||||
#include "zigbeenetworkrequest.h"
|
||||
#include "zigbeebridgecontroller.h"
|
||||
|
||||
#include "interface/deconz.h"
|
||||
@ -70,6 +71,34 @@ typedef struct DeconzDeviceState {
|
||||
bool aspDataRequestFreeSlots = false;
|
||||
} 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
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -96,9 +125,11 @@ public:
|
||||
ZigbeeInterfaceDeconzReply *requestQuerySendDataConfirm();
|
||||
|
||||
// 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 *requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, Zigbee::ZigbeeProfile profileId, Zigbee::ClusterId 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 *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, quint16 profileId, quint16 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:
|
||||
ZigbeeInterfaceDeconz *m_interface = nullptr;
|
||||
@ -122,8 +153,11 @@ private:
|
||||
|
||||
// Device state helper
|
||||
DeconzDeviceState parseDeviceStateFlag(quint8 deviceStateFlag);
|
||||
void processDeviceState(DeconzDeviceState deviceState);
|
||||
|
||||
void readDataIndication();
|
||||
void readDataConfirm();
|
||||
|
||||
void processDeviceState(DeconzDeviceState deviceState);
|
||||
void processDataIndication(const QByteArray &data);
|
||||
void processDataConfirm(const QByteArray &data);
|
||||
|
||||
@ -131,6 +165,9 @@ signals:
|
||||
void networkStateChanged(Deconz::NetworkState networkState);
|
||||
void networkConfigurationParameterChanged(const DeconzNetworkConfiguration &networkConfiguration);
|
||||
|
||||
void aspDataConfirmReceived(const DeconzApsDataConfirm &confirm);
|
||||
void aspDataIndicationReceived(const DeconzApsDataIndication &indication);
|
||||
|
||||
private slots:
|
||||
void onInterfaceAvailableChanged(bool available);
|
||||
void onInterfacePackageReceived(const QByteArray &package);
|
||||
@ -143,6 +180,8 @@ public slots:
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const DeconzDeviceState &deviceState);
|
||||
QDebug operator<<(QDebug debug, const DeconzApsDataConfirm &confirm);
|
||||
QDebug operator<<(QDebug debug, const DeconzApsDataIndication &indication);
|
||||
|
||||
|
||||
#endif // ZIGBEEBRIDGECONTROLLERDECONZ_H
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "zigbeenetworkdeconz.h"
|
||||
#include "zigbeedeviceprofile.h"
|
||||
#include "loggingcategory.h"
|
||||
#include "zigbeeutils.h"
|
||||
|
||||
@ -37,6 +38,8 @@ ZigbeeNetworkDeconz::ZigbeeNetworkDeconz(QObject *parent) :
|
||||
m_controller = new ZigbeeBridgeControllerDeconz(this);
|
||||
//connect(m_controller, &ZigbeeBridgeControllerDeconz::messageReceived, this, &ZigbeeNetworkDeconz::onMessageReceived);
|
||||
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->setInterval(1000);
|
||||
@ -52,6 +55,30 @@ ZigbeeBridgeController *ZigbeeNetworkDeconz::bridgeController() const
|
||||
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)
|
||||
{
|
||||
if (m_createState == state)
|
||||
@ -68,11 +95,13 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestChangeNetworkState(Deconz::NetworkStateOffline);
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Stop network finished successfully. SQN:" << reply->sequenceNumber();
|
||||
|
||||
// Start polling the device state, should be Online -> Leaving -> Offline
|
||||
m_pollNetworkStateTimer->start();
|
||||
});
|
||||
@ -94,12 +123,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterNodeType, paramData);
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured successfully bridge to" << Deconz::NodeTypeCoordinator;
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured successfully bridge to" << Deconz::NodeTypeCoordinator << "SQN:" << reply->sequenceNumber();
|
||||
|
||||
QByteArray paramData;
|
||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||
@ -109,12 +138,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterChannelMask, paramData);
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured channel mask successfully";
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured channel mask successfully. SQN:" << reply->sequenceNumber();
|
||||
|
||||
QByteArray paramData;
|
||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||
@ -124,12 +153,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterApsExtendedPanId, paramData);
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured APS extended PANID successfully";
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured APS extended PANID successfully. SQN:" << reply->sequenceNumber();
|
||||
|
||||
QByteArray paramData;
|
||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||
@ -139,12 +168,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterTrustCenterAddress, paramData);
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured trust center address successfully";
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured trust center address successfully. SQN:" << reply->sequenceNumber();
|
||||
|
||||
QByteArray paramData;
|
||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||
@ -154,7 +183,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterSecurityMode, paramData);
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
@ -166,12 +195,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterNetworkKey, securityConfiguration().networkKey().toByteArray());
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
// Note: writing the network key fails all the time...
|
||||
//return;
|
||||
} else {
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured network key successfully";
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured network key successfully. SQN:" << reply->sequenceNumber();
|
||||
}
|
||||
|
||||
// Configuration finished, lets start the network
|
||||
@ -188,11 +217,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestChangeNetworkState(Deconz::NetworkStateConnected);
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Start network finished successfully. SQN:" << reply->sequenceNumber();
|
||||
// Start polling the device state, should be Online -> Leaving -> Offline
|
||||
m_pollNetworkStateTimer->start();
|
||||
});
|
||||
@ -203,12 +233,12 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->readNetworkParameters();
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
if (reply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Could not read network parameters during network start up." << reply->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Could not read network parameters during network start up. SQN:" << reply->sequenceNumber() << reply->statusCode();
|
||||
// FIXME: set an appropriate error
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Reading network parameters finished successfully.";
|
||||
qCDebug(dcZigbeeNetwork()) << "Reading network parameters finished successfully. SQN:" << reply->sequenceNumber();
|
||||
|
||||
setPanId(m_controller->networkConfiguration().panId);
|
||||
setExtendedPanId(m_controller->networkConfiguration().extendedPanId);
|
||||
@ -224,22 +254,53 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
coordinatorNode->setShortAddress(m_controller->networkConfiguration().shortAddress);
|
||||
coordinatorNode->setExtendedAddress(m_controller->networkConfiguration().ieeeAddress);
|
||||
|
||||
addUnitializedNode(coordinatorNode);
|
||||
coordinatorNode->startInitialization();
|
||||
// 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)
|
||||
{
|
||||
return new ZigbeeNodeDeconz(m_controller, parent);
|
||||
return new ZigbeeNodeDeconz(this, parent);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
|
||||
@ -271,7 +332,6 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
||||
qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().networkKey() << "network link key";
|
||||
qCDebug(dcZigbeeNetwork()) << "Using" << securityConfiguration().globalTrustCenterLinkKey() << "global trust center link key";
|
||||
|
||||
|
||||
// - Read the firmware version
|
||||
// - Read the network configuration parameters
|
||||
// - Read the network state
|
||||
@ -313,12 +373,12 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestDeviceState();
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
|
||||
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully. SQN:" << reply->sequenceNumber();
|
||||
QDataStream stream(reply->responseData());
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 deviceStateFlag = 0;
|
||||
@ -328,11 +388,19 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
||||
|
||||
if (m_createNewNetwork) {
|
||||
setCreateNetworkState(CreateNetworkStateStopNetwork);
|
||||
// Set offline
|
||||
// Write configurations
|
||||
// Set online
|
||||
// Read configurations
|
||||
// Create and initialize coordinator node
|
||||
// Done. Save network
|
||||
} else {
|
||||
// Get the network state and start the network if required
|
||||
if (m_controller->networkState() == Deconz::NetworkStateConnected) {
|
||||
qCDebug(dcZigbeeNetwork()) << "The network is already running.";
|
||||
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)
|
||||
{
|
||||
qCDebug(dcZigbeeNetwork()) << "Hardware controller is" << (available ? "now available" : "not available");
|
||||
@ -387,7 +441,7 @@ void ZigbeeNetworkDeconz::onPollNetworkStateTimeout()
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
|
||||
//qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
|
||||
QDataStream stream(reply->responseData());
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 deviceStateFlag = 0;
|
||||
@ -409,12 +463,12 @@ void ZigbeeNetworkDeconz::onPollNetworkStateTimeout()
|
||||
ZigbeeInterfaceDeconzReply *reply = m_controller->requestDeviceState();
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully";
|
||||
//qCDebug(dcZigbeeNetwork()) << "Read device state finished successfully. SQN:" << reply->sequenceNumber();
|
||||
QDataStream stream(reply->responseData());
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
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()
|
||||
{
|
||||
loadNetwork();
|
||||
@ -466,12 +556,12 @@ void ZigbeeNetworkDeconz::stopNetwork()
|
||||
setState(StateStopping);
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply](){
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Network left successfully";
|
||||
qCDebug(dcZigbeeNetwork()) << "Network left successfully. SQN:" << reply->sequenceNumber();
|
||||
setState(StateOffline);
|
||||
});
|
||||
}
|
||||
|
||||
@ -53,7 +53,9 @@ public:
|
||||
|
||||
ZigbeeBridgeController *bridgeController() const override;
|
||||
|
||||
ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override;
|
||||
|
||||
quint8 generateSequenceNumber();
|
||||
|
||||
private:
|
||||
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
|
||||
@ -61,9 +63,16 @@ private:
|
||||
CreateNetworkState m_createState = CreateNetworkStateIdle;
|
||||
bool m_createNewNetwork = false;
|
||||
|
||||
QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies;
|
||||
|
||||
quint8 m_sequenceNumber = 0;
|
||||
|
||||
QTimer *m_pollNetworkStateTimer = nullptr;
|
||||
void setCreateNetworkState(CreateNetworkState state);
|
||||
|
||||
void handleZigbeeDeviceProfileIndication(const DeconzApsDataIndication &indication);
|
||||
|
||||
|
||||
protected:
|
||||
ZigbeeNode *createNode(QObject *parent) override;
|
||||
|
||||
@ -71,12 +80,15 @@ protected:
|
||||
|
||||
void startNetworkInternally();
|
||||
|
||||
void createNetwork();
|
||||
|
||||
private slots:
|
||||
void onControllerAvailableChanged(bool available);
|
||||
void onPollNetworkStateTimeout();
|
||||
|
||||
void onAspDataConfirmReceived(const DeconzApsDataConfirm &confirm);
|
||||
void onAspDataIndicationReceived(const DeconzApsDataIndication &indication);
|
||||
|
||||
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
|
||||
|
||||
public slots:
|
||||
void startNetwork() override;
|
||||
void stopNetwork() override;
|
||||
|
||||
@ -26,10 +26,15 @@
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#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),
|
||||
m_controller(controller)
|
||||
m_network(network)
|
||||
{
|
||||
|
||||
}
|
||||
@ -47,6 +52,40 @@ void ZigbeeNodeDeconz::setClusterAttributeReport(const ZigbeeClusterAttributeRep
|
||||
|
||||
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 descriptor
|
||||
* - Power descriptor
|
||||
|
||||
@ -32,7 +32,8 @@
|
||||
|
||||
#include "zigbee.h"
|
||||
#include "zigbeenode.h"
|
||||
#include "zigbeebridgecontrollerdeconz.h"
|
||||
|
||||
class ZigbeeNetworkDeconz;
|
||||
|
||||
class ZigbeeNodeDeconz : public ZigbeeNode
|
||||
{
|
||||
@ -41,12 +42,12 @@ class ZigbeeNodeDeconz : public ZigbeeNode
|
||||
friend class ZigbeeNetworkDeconz;
|
||||
|
||||
public:
|
||||
explicit ZigbeeNodeDeconz(ZigbeeBridgeControllerDeconz *controller, QObject *parent = nullptr);
|
||||
explicit ZigbeeNodeDeconz(ZigbeeNetworkDeconz *network, QObject *parent = nullptr);
|
||||
|
||||
void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) override;
|
||||
|
||||
private:
|
||||
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
|
||||
ZigbeeNetworkDeconz *m_network = nullptr;
|
||||
|
||||
void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) override;
|
||||
|
||||
|
||||
@ -23,7 +23,6 @@ SOURCES += \
|
||||
zigbeechannelmask.cpp \
|
||||
zigbeecluster.cpp \
|
||||
zigbeeclusterattribute.cpp \
|
||||
zigbeedeviceobject.cpp \
|
||||
zigbeedeviceprofile.cpp \
|
||||
zigbeemanufacturer.cpp \
|
||||
zigbeenetwork.cpp \
|
||||
@ -60,7 +59,6 @@ HEADERS += \
|
||||
zigbeechannelmask.h \
|
||||
zigbeecluster.h \
|
||||
zigbeeclusterattribute.h \
|
||||
zigbeedeviceobject.h \
|
||||
zigbeedeviceprofile.h \
|
||||
zigbeemanufacturer.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)
|
||||
{
|
||||
return new ZigbeeNodeNxp(m_controller, parent);
|
||||
|
||||
@ -62,6 +62,9 @@ private:
|
||||
void readControllerVersion();
|
||||
void readPermitJoinStatus();
|
||||
|
||||
|
||||
ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override;
|
||||
|
||||
protected:
|
||||
ZigbeeNode *createNode(QObject *parent) 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 "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
|
||||
#define ZIGBEEDEVICEPROFILE_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
|
||||
#include "zigbee.h"
|
||||
|
||||
typedef struct ZigbeeDeviceProfileAdpu {
|
||||
quint8 sequenceNumber = 0;
|
||||
Zigbee::ZigbeeStatus status = Zigbee::ZigbeeStatusSuccess;
|
||||
quint16 addressOfInterest = 0;
|
||||
QByteArray payload;
|
||||
} ZigbeeDeviceProfileAdpu;
|
||||
|
||||
class ZigbeeDeviceProfile
|
||||
{
|
||||
Q_GADGET
|
||||
|
||||
public:
|
||||
|
||||
enum ZdoCommand {
|
||||
/* Requests */
|
||||
/*Device and service discovery */
|
||||
@ -136,9 +145,11 @@ public:
|
||||
MgmtCacheResponse = 0x8037,
|
||||
MgmtNetworkUpdateResponse = 0x8038
|
||||
};
|
||||
Q_ENUM(ZdoCommand)
|
||||
|
||||
|
||||
|
||||
static ZigbeeDeviceProfileAdpu parseAdpu(const QByteArray &adpu);
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfileAdpu &deviceAdpu);
|
||||
|
||||
#endif // ZIGBEEDEVICEPROFILE_H
|
||||
|
||||
@ -378,6 +378,9 @@ void ZigbeeNetwork::saveNode(ZigbeeNode *node)
|
||||
settings.beginGroup(node->extendedAddress().toString());
|
||||
settings.setValue("nwkAddress", node->shortAddress());
|
||||
settings.setValue("macCapabilitiesFlag", node->m_macCapabilitiesFlag);
|
||||
settings.setValue("manufacturerCode", node->m_manufacturerCode);
|
||||
|
||||
|
||||
settings.setValue("nodeDescriptorRawData", node->m_nodeDescriptorRawData);
|
||||
settings.setValue("powerDescriptorFlag", node->m_powerDescriptorFlag);
|
||||
|
||||
@ -491,6 +494,26 @@ bool ZigbeeNetwork::networkConfigurationAvailable() const
|
||||
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)
|
||||
{
|
||||
ZigbeeNode *node = qobject_cast<ZigbeeNode *>(sender());
|
||||
|
||||
@ -94,6 +94,8 @@ public:
|
||||
bool permitJoining() const;
|
||||
void setPermitJoining(bool permitJoining);
|
||||
|
||||
|
||||
// Network nodes
|
||||
QList<ZigbeeNode *> nodes() const;
|
||||
|
||||
ZigbeeNode *coordinatorNode() const;
|
||||
@ -150,6 +152,13 @@ protected:
|
||||
|
||||
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:
|
||||
void settingsFileNameChanged(const QString &settingsFileName);
|
||||
void serialPortNameChanged(const QString &serialPortName);
|
||||
|
||||
@ -42,6 +42,11 @@ Zigbee::ZigbeeStatus ZigbeeNetworkReply::zigbeeStatus() const
|
||||
return m_zigbeeStatus;
|
||||
}
|
||||
|
||||
QByteArray ZigbeeNetworkReply::responseData() const
|
||||
{
|
||||
return m_responseData;
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_request(request)
|
||||
|
||||
@ -37,20 +37,25 @@ class ZigbeeNetworkReply : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ZigbeeNetwork;
|
||||
friend class ZigbeeNodeEndpoint;
|
||||
|
||||
public:
|
||||
enum Error {
|
||||
ErrorNoError,
|
||||
ErrorZigbeeStatusError,
|
||||
ErrorInterfaceError,
|
||||
ErrorNetworkOffline,
|
||||
ErrorNetworkNotImplemented,
|
||||
ErrorUnknown
|
||||
};
|
||||
Q_ENUM(Error)
|
||||
|
||||
|
||||
Error error() const;
|
||||
ZigbeeNetworkRequest request() const;
|
||||
Zigbee::ZigbeeStatus zigbeeStatus() const;
|
||||
QByteArray responseData() const;
|
||||
|
||||
private:
|
||||
explicit ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr);
|
||||
@ -59,6 +64,7 @@ private:
|
||||
bool m_finished = false;
|
||||
Error m_error = ErrorNoError;
|
||||
Zigbee::ZigbeeStatus m_zigbeeStatus = Zigbee::ZigbeeStatusSuccess;
|
||||
QByteArray m_responseData;
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
@ -156,20 +156,6 @@ private:
|
||||
quint16 m_shortAddress = 0;
|
||||
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
|
||||
quint16 m_serverMask = 0;
|
||||
bool m_isPrimaryTrustCenter = false;
|
||||
@ -208,6 +194,20 @@ protected:
|
||||
|
||||
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 setConnected(bool connected);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user