Restructure the descriptor handling and implement level control cluster server side
This commit is contained in:
parent
b5b6709da3
commit
80d4b1416e
@ -73,8 +73,7 @@ private slots:
|
||||
|
||||
public slots:
|
||||
void sendPackage(const QByteArray &package);
|
||||
|
||||
bool enable(const QString &serialPort = "/dev/ttyS0", qint32 baudrate = 115200);
|
||||
bool enable(const QString &serialPort = "/dev/ttyS0", qint32 baudrate = 38400);
|
||||
void reconnectController();
|
||||
void disable();
|
||||
|
||||
|
||||
@ -27,6 +27,11 @@
|
||||
|
||||
#include "zigbeeinterfacedeconzreply.h"
|
||||
|
||||
ZigbeeNetworkRequest ZigbeeInterfaceDeconzReply::networkRequest() const
|
||||
{
|
||||
return m_networkRequest;
|
||||
}
|
||||
|
||||
Deconz::Command ZigbeeInterfaceDeconzReply::command() const
|
||||
{
|
||||
return m_command;
|
||||
@ -47,6 +52,11 @@ Deconz::StatusCode ZigbeeInterfaceDeconzReply::statusCode() const
|
||||
return m_statusCode;
|
||||
}
|
||||
|
||||
bool ZigbeeInterfaceDeconzReply::timendOut() const
|
||||
{
|
||||
return m_timeout;
|
||||
}
|
||||
|
||||
bool ZigbeeInterfaceDeconzReply::aborted() const
|
||||
{
|
||||
return m_aborted;
|
||||
@ -64,7 +74,7 @@ ZigbeeInterfaceDeconzReply::ZigbeeInterfaceDeconzReply(Deconz::Command command,
|
||||
m_command(command),
|
||||
m_sequenceNumber(sequenceNumber)
|
||||
{
|
||||
m_timer->setInterval(2000);
|
||||
m_timer->setInterval(5000);
|
||||
m_timer->setSingleShot(true);
|
||||
connect(m_timer, &QTimer::timeout, this, &ZigbeeInterfaceDeconzReply::onTimeout);
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include <QTimer>
|
||||
|
||||
#include "deconz.h"
|
||||
#include "zigbeenetworkrequest.h"
|
||||
|
||||
class ZigbeeInterfaceDeconzReply : public QObject
|
||||
{
|
||||
@ -41,6 +42,7 @@ class ZigbeeInterfaceDeconzReply : public QObject
|
||||
|
||||
public:
|
||||
// Request content
|
||||
ZigbeeNetworkRequest networkRequest() const;
|
||||
Deconz::Command command() const;
|
||||
quint8 sequenceNumber() const;
|
||||
QByteArray responseData() const;
|
||||
@ -48,12 +50,13 @@ public:
|
||||
// Response content
|
||||
Deconz::StatusCode statusCode() const;
|
||||
|
||||
bool timeout() const;
|
||||
bool timendOut() const;
|
||||
bool aborted() const;
|
||||
void abort();
|
||||
|
||||
private:
|
||||
explicit ZigbeeInterfaceDeconzReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent = nullptr);
|
||||
ZigbeeNetworkRequest m_networkRequest;
|
||||
QTimer *m_timer = nullptr;
|
||||
bool m_timeout = false;
|
||||
bool m_aborted = false;
|
||||
|
||||
@ -221,6 +221,66 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestQuerySendDataCo
|
||||
return createReply(Deconz::CommandApsDataConfirm, sequenceNumber, this);
|
||||
}
|
||||
|
||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestSendRequest(const ZigbeeNetworkRequest &request)
|
||||
{
|
||||
// Send the request only if there are free slots on the device, otherwise enque request
|
||||
// if (m_apsFreeSlotsAvailable) {
|
||||
|
||||
// }
|
||||
|
||||
qCDebug(dcZigbeeAps()) << "APSDE-DATA.request" << request;
|
||||
ZigbeeInterfaceDeconzReply *interfaceReply = nullptr;
|
||||
switch (request.destinationAddressMode()) {
|
||||
case Zigbee::DestinationAddressModeGroup:
|
||||
interfaceReply = requestEnqueueSendDataGroup(request.requestId(), request.destinationShortAddress(),
|
||||
request.profileId(), request.clusterId(),request.sourceEndpoint(),
|
||||
request.asdu(), request.txOptions(), request.radius());
|
||||
break;
|
||||
case Zigbee::DestinationAddressModeShortAddress:
|
||||
interfaceReply = requestEnqueueSendDataShortAddress(request.requestId(), request.destinationShortAddress(),
|
||||
request.destinationEndpoint(), request.profileId(), request.clusterId(),
|
||||
request.sourceEndpoint(), request.asdu(), request.txOptions(), request.radius());
|
||||
break;
|
||||
case Zigbee::DestinationAddressModeIeeeAddress:
|
||||
interfaceReply = requestEnqueueSendDataIeeeAddress(request.requestId(), request.destinationIeeeAddress(),
|
||||
request.destinationEndpoint(), request.profileId(), request.clusterId(),
|
||||
request.sourceEndpoint(), request.asdu(), request.txOptions(), request.radius());
|
||||
break;
|
||||
}
|
||||
|
||||
return interfaceReply;
|
||||
}
|
||||
|
||||
quint8 ZigbeeBridgeControllerDeconz::generateSequenceNumber()
|
||||
{
|
||||
return m_sequenceNumber++;
|
||||
}
|
||||
|
||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::createReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent)
|
||||
{
|
||||
// Create the reply
|
||||
ZigbeeInterfaceDeconzReply *reply = new ZigbeeInterfaceDeconzReply(command, sequenceNumber, parent);
|
||||
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::timeout, this, [this, reply](){
|
||||
qCWarning(dcZigbeeController()) << "Reply timeout" << reply->command() << "SQN:" << reply->sequenceNumber();
|
||||
if (m_pendingReplies.contains(reply->sequenceNumber())) {
|
||||
m_pendingReplies.remove(reply->sequenceNumber());
|
||||
// Note: will be deleted with the finished signal
|
||||
}
|
||||
});
|
||||
|
||||
// Auto delete the object on finished
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater, Qt::QueuedConnection);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendDataGroup(quint8 requestId, quint16 groupAddress, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius)
|
||||
{
|
||||
quint8 sequenceNumber = generateSequenceNumber();
|
||||
@ -313,7 +373,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
||||
<< profileId << clusterId
|
||||
<< ZigbeeUtils::convertByteToHexString(sourceEndpoint);
|
||||
|
||||
Q_ASSERT_X(asdu.length() <= 127, "ASDU", "ASDU package length has to <= 127 bytes");
|
||||
Q_ASSERT_X(asdu.length() <= 127, "ZigbeeController", "ASDU package length has to be <= 127 bytes");
|
||||
|
||||
// Note: 21 protocol bytes + asdu package length
|
||||
quint16 payloadLength = static_cast<quint16>(21 + asdu.length());
|
||||
@ -345,53 +405,6 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
||||
return createReply(Deconz::CommandApsDataRequest, sequenceNumber, this);
|
||||
}
|
||||
|
||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestSendRequest(const ZigbeeNetworkRequest &request)
|
||||
{
|
||||
qCDebug(dcZigbeeAps()) << "APSDE-DATA.request" << request;
|
||||
ZigbeeInterfaceDeconzReply *interfaceReply = nullptr;
|
||||
switch (request.destinationAddressMode()) {
|
||||
case Zigbee::DestinationAddressModeGroup:
|
||||
interfaceReply = requestEnqueueSendDataGroup(request.requestId(), request.destinationShortAddress(),
|
||||
request.profileId(), request.clusterId(),request.sourceEndpoint(),
|
||||
request.asdu(), request.txOptions(), request.radius());
|
||||
break;
|
||||
case Zigbee::DestinationAddressModeShortAddress:
|
||||
interfaceReply = requestEnqueueSendDataShortAddress(request.requestId(), request.destinationShortAddress(),
|
||||
request.destinationEndpoint(), request.profileId(), request.clusterId(),
|
||||
request.sourceEndpoint(), request.asdu(), request.txOptions(), request.radius());
|
||||
break;
|
||||
case Zigbee::DestinationAddressModeIeeeAddress:
|
||||
interfaceReply = requestEnqueueSendDataIeeeAddress(request.requestId(), request.destinationIeeeAddress(),
|
||||
request.destinationEndpoint(), request.profileId(), request.clusterId(),
|
||||
request.sourceEndpoint(), request.asdu(), request.txOptions(), request.radius());
|
||||
break;
|
||||
}
|
||||
|
||||
return interfaceReply;
|
||||
}
|
||||
|
||||
quint8 ZigbeeBridgeControllerDeconz::generateSequenceNumber()
|
||||
{
|
||||
return m_sequenceNumber++;
|
||||
}
|
||||
|
||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::createReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent)
|
||||
{
|
||||
// Create the reply
|
||||
ZigbeeInterfaceDeconzReply *reply = new ZigbeeInterfaceDeconzReply(command, sequenceNumber, parent);
|
||||
|
||||
// Auto delete the object on finished
|
||||
connect(reply, &ZigbeeInterfaceDeconzReply::finished, reply, &ZigbeeInterfaceDeconzReply::deleteLater, Qt::QueuedConnection);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters()
|
||||
{
|
||||
qCDebug(dcZigbeeController()) << "Start reading network parameters";
|
||||
@ -408,8 +421,8 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
ZigbeeInterfaceDeconzReply *replyMacAddress = requestReadParameter(Deconz::ParameterMacAddress);
|
||||
connect(replyMacAddress, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyMacAddress](){
|
||||
if (replyMacAddress->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyMacAddress->command() << Deconz::ParameterMacAddress
|
||||
<< "finished with error" << replyMacAddress->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyMacAddress->sequenceNumber() << replyMacAddress->command()
|
||||
<< Deconz::ParameterMacAddress << "finished with error" << replyMacAddress->statusCode();
|
||||
|
||||
readNetworkParametersReply->m_statusCode = replyMacAddress->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
@ -421,16 +434,16 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
stream >> payloadLenght >> parameter >> macAddress;
|
||||
|
||||
m_networkConfiguration.ieeeAddress = ZigbeeAddress(macAddress);
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyMacAddress->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyMacAddress->sequenceNumber() << replyMacAddress->command()
|
||||
<< static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "IEEE address:" << m_networkConfiguration.ieeeAddress.toString();
|
||||
|
||||
// Read PAN ID
|
||||
ZigbeeInterfaceDeconzReply *replyPanId = requestReadParameter(Deconz::ParameterPanId);
|
||||
connect(replyPanId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyPanId](){
|
||||
if (replyPanId->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyPanId->command() << Deconz::ParameterPanId
|
||||
<< "finished with error" << replyPanId->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyPanId->sequenceNumber() << replyPanId->command()
|
||||
<< Deconz::ParameterPanId << "finished with error" << replyPanId->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyPanId->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -441,15 +454,15 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
stream >> payloadLenght >> parameter >> panId;
|
||||
|
||||
m_networkConfiguration.panId = panId;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyPanId->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyPanId->sequenceNumber() << replyPanId->command()
|
||||
<< static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "PAN ID:" << ZigbeeUtils::convertUint16ToHexString(m_networkConfiguration.panId);
|
||||
|
||||
// Read short address
|
||||
ZigbeeInterfaceDeconzReply *replyShortAddress = requestReadParameter(Deconz::ParameterNetworkAddress);
|
||||
connect(replyShortAddress, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyShortAddress](){
|
||||
if (replyShortAddress->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyShortAddress->command() << Deconz::ParameterNetworkAddress
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyShortAddress->sequenceNumber() << replyShortAddress->command() << Deconz::ParameterNetworkAddress
|
||||
<< "finished with error" << replyShortAddress->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyShortAddress->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
@ -461,16 +474,16 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
quint16 payloadLenght = 0; quint8 parameter = 0; quint16 shortAddress = 0;
|
||||
stream >> payloadLenght >> parameter >> shortAddress;
|
||||
m_networkConfiguration.shortAddress = shortAddress;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyShortAddress->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyShortAddress->sequenceNumber()
|
||||
<< replyShortAddress->command() << static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << ZigbeeUtils::convertUint16ToHexString(m_networkConfiguration.shortAddress);
|
||||
|
||||
// Read extended PAN ID
|
||||
ZigbeeInterfaceDeconzReply *replyExtendedPanId = requestReadParameter(Deconz::ParameterNetworkExtendedPanId);
|
||||
connect(replyExtendedPanId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyExtendedPanId](){
|
||||
if (replyExtendedPanId->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyExtendedPanId->command() << Deconz::ParameterNetworkExtendedPanId
|
||||
<< "finished with error" << replyExtendedPanId->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyExtendedPanId->sequenceNumber() << replyExtendedPanId->command()
|
||||
<< Deconz::ParameterNetworkExtendedPanId << "finished with error" << replyExtendedPanId->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyExtendedPanId->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -481,7 +494,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
quint16 payloadLenght = 0; quint8 parameter = 0; quint64 networkExtendedPanId = 0;
|
||||
stream >> payloadLenght >> parameter >> networkExtendedPanId;
|
||||
m_networkConfiguration.extendedPanId = networkExtendedPanId;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyExtendedPanId->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyExtendedPanId->sequenceNumber() << replyExtendedPanId->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << ZigbeeUtils::convertUint64ToHexString(m_networkConfiguration.extendedPanId);
|
||||
|
||||
@ -489,8 +502,8 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
ZigbeeInterfaceDeconzReply *replyNodeType = requestReadParameter(Deconz::ParameterNodeType);
|
||||
connect(replyNodeType, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyNodeType](){
|
||||
if (replyNodeType->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyNodeType->command() << Deconz::ParameterNodeType
|
||||
<< "finished with error" << replyNodeType->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyNodeType->sequenceNumber() << replyNodeType->command()
|
||||
<< Deconz::ParameterNodeType << "finished with error" << replyNodeType->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyNodeType->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -502,7 +515,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
stream >> payloadLenght >> parameter >> nodeType;
|
||||
|
||||
m_networkConfiguration.nodeType = static_cast<Deconz::NodeType>(nodeType);
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyNodeType->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyNodeType->sequenceNumber() << replyNodeType->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << m_networkConfiguration.nodeType;
|
||||
|
||||
@ -510,7 +523,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
ZigbeeInterfaceDeconzReply *replyChannelMask = requestReadParameter(Deconz::ParameterChannelMask);
|
||||
connect(replyChannelMask, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyChannelMask](){
|
||||
if (replyChannelMask->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyChannelMask->command() << Deconz::ParameterChannelMask
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyChannelMask->sequenceNumber() << replyChannelMask->command() << Deconz::ParameterChannelMask
|
||||
<< "finished with error" << replyChannelMask->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyChannelMask->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
@ -523,16 +536,16 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
stream >> payloadLenght >> parameter >> channelMask;
|
||||
|
||||
m_networkConfiguration.channelMask = channelMask;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyChannelMask->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyChannelMask->sequenceNumber() << replyChannelMask->command()
|
||||
<< static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << ZigbeeUtils::convertUint32ToHexString(m_networkConfiguration.channelMask);
|
||||
|
||||
// Read APS extended PAN ID
|
||||
ZigbeeInterfaceDeconzReply *replyApsExtendedPanId = requestReadParameter(Deconz::ParameterApsExtendedPanId);
|
||||
connect(replyApsExtendedPanId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyApsExtendedPanId](){
|
||||
if (replyApsExtendedPanId->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyApsExtendedPanId->command() << Deconz::ParameterApsExtendedPanId
|
||||
<< "finished with error" << replyApsExtendedPanId->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyApsExtendedPanId->sequenceNumber() << replyApsExtendedPanId->command()
|
||||
<< Deconz::ParameterApsExtendedPanId << "finished with error" << replyApsExtendedPanId->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyApsExtendedPanId->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -544,16 +557,16 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
stream >> payloadLenght >> parameter >> apsExtendedPanId;
|
||||
|
||||
m_networkConfiguration.apsExtendedPanId = apsExtendedPanId;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyApsExtendedPanId->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyApsExtendedPanId->sequenceNumber() << replyApsExtendedPanId->command()
|
||||
<< static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << ZigbeeUtils::convertUint64ToHexString(m_networkConfiguration.apsExtendedPanId);
|
||||
|
||||
// Read trust center address
|
||||
ZigbeeInterfaceDeconzReply *replyTrustCenterAddress = requestReadParameter(Deconz::ParameterTrustCenterAddress);
|
||||
connect(replyTrustCenterAddress, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyTrustCenterAddress](){
|
||||
if (replyTrustCenterAddress->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyTrustCenterAddress->command() << Deconz::ParameterTrustCenterAddress
|
||||
<< "finished with error" << replyTrustCenterAddress->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyTrustCenterAddress->sequenceNumber() << replyTrustCenterAddress->command()
|
||||
<< Deconz::ParameterTrustCenterAddress << "finished with error" << replyTrustCenterAddress->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyTrustCenterAddress->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -565,16 +578,16 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
stream >> payloadLenght >> parameter >> trustCenterAddress;
|
||||
|
||||
m_networkConfiguration.trustCenterAddress = ZigbeeAddress(trustCenterAddress);
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyTrustCenterAddress->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyTrustCenterAddress->sequenceNumber() << replyTrustCenterAddress->command()
|
||||
<< static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << m_networkConfiguration.trustCenterAddress;
|
||||
|
||||
// Read security mode
|
||||
ZigbeeInterfaceDeconzReply *replySecurityMode = requestReadParameter(Deconz::ParameterSecurityMode);
|
||||
connect(replySecurityMode, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replySecurityMode](){
|
||||
if (replySecurityMode->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replySecurityMode->command() << Deconz::ParameterSecurityMode
|
||||
<< "finished with error" << replySecurityMode->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replySecurityMode->sequenceNumber() << replySecurityMode->command()
|
||||
<< Deconz::ParameterSecurityMode << "finished with error" << replySecurityMode->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replySecurityMode->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -586,8 +599,8 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
stream >> payloadLenght >> parameter >> securityMode;
|
||||
|
||||
m_networkConfiguration.securityMode = static_cast<Deconz::SecurityMode>(securityMode);
|
||||
qCDebug(dcZigbeeController()) << "Request" << replySecurityMode->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replySecurityMode->sequenceNumber() << replySecurityMode->command()
|
||||
<< static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << m_networkConfiguration.securityMode;
|
||||
|
||||
// Note: reading the network key returns "InavlidParameter". Might be for security reasons which is good!
|
||||
@ -596,7 +609,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
ZigbeeInterfaceDeconzReply *replyChannel = requestReadParameter(Deconz::ParameterCurrentChannel);
|
||||
connect(replyChannel, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyChannel](){
|
||||
if (replyChannel->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyChannel->command() << Deconz::ParameterCurrentChannel
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyChannel->sequenceNumber() << replyChannel->command() << Deconz::ParameterCurrentChannel
|
||||
<< "finished with error" << replyChannel->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyChannel->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
@ -608,7 +621,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
quint16 payloadLenght = 0; quint8 parameter = 0; quint8 channel = 0;
|
||||
stream >> payloadLenght >> parameter >> channel;
|
||||
m_networkConfiguration.currentChannel = channel;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyChannel->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyChannel->sequenceNumber() << replyChannel->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Current channel:" << m_networkConfiguration.currentChannel;
|
||||
|
||||
@ -617,8 +630,8 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
ZigbeeInterfaceDeconzReply *replyPermitJoin = requestReadParameter(Deconz::ParameterPermitJoin);
|
||||
connect(replyPermitJoin, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyPermitJoin](){
|
||||
if (replyPermitJoin->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyPermitJoin->command() << Deconz::ParameterPermitJoin
|
||||
<< "finished with error" << replyPermitJoin->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyPermitJoin->sequenceNumber() << replyPermitJoin->command()
|
||||
<< Deconz::ParameterPermitJoin << "finished with error" << replyPermitJoin->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyPermitJoin->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -629,7 +642,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
quint16 payloadLenght = 0; quint8 parameter = 0;
|
||||
stream >> payloadLenght >> parameter;
|
||||
//m_networkConfiguration.currentChannel = channel;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyPermitJoin->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyPermitJoin->sequenceNumber() << replyPermitJoin->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully" << ZigbeeUtils::convertByteArrayToHexString(replyPermitJoin->responseData());
|
||||
|
||||
|
||||
@ -637,8 +650,8 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
ZigbeeInterfaceDeconzReply *replyProtocolVersion = requestReadParameter(Deconz::ParameterProtocolVersion);
|
||||
connect(replyProtocolVersion, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyProtocolVersion](){
|
||||
if (replyProtocolVersion->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyProtocolVersion->command() << Deconz::ParameterProtocolVersion
|
||||
<< "finished with error" << replyProtocolVersion->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyProtocolVersion->sequenceNumber() << replyProtocolVersion->command()
|
||||
<< Deconz::ParameterProtocolVersion << "finished with error" << replyProtocolVersion->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyProtocolVersion->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -649,16 +662,16 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
quint16 payloadLenght = 0; quint8 parameter = 0; quint16 protocolVersion = 0;
|
||||
stream >> payloadLenght >> parameter >> protocolVersion;
|
||||
m_networkConfiguration.protocolVersion = protocolVersion;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyProtocolVersion->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyProtocolVersion->sequenceNumber() << replyProtocolVersion->command()
|
||||
<< static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Protocol version:" << ZigbeeUtils::convertUint16ToHexString(m_networkConfiguration.protocolVersion);
|
||||
|
||||
// Read network updat id
|
||||
ZigbeeInterfaceDeconzReply *replyNetworkUpdateId = requestReadParameter(Deconz::ParameterNetworkUpdateId);
|
||||
connect(replyNetworkUpdateId, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyNetworkUpdateId](){
|
||||
if (replyNetworkUpdateId->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyNetworkUpdateId->command() << Deconz::ParameterNetworkUpdateId
|
||||
<< "finished with error" << replyNetworkUpdateId->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyNetworkUpdateId->sequenceNumber() << replyNetworkUpdateId->command()
|
||||
<< Deconz::ParameterNetworkUpdateId << "finished with error" << replyNetworkUpdateId->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyNetworkUpdateId->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -669,8 +682,8 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
quint16 payloadLenght = 0; quint8 parameter = 0; quint8 networkUpdateId = 0;
|
||||
stream >> payloadLenght >> parameter >> networkUpdateId;
|
||||
m_networkConfiguration.networkUpdateId = networkUpdateId;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyNetworkUpdateId->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyNetworkUpdateId->sequenceNumber() << replyNetworkUpdateId->command()
|
||||
<< static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Network update ID:" << m_networkConfiguration.networkUpdateId;
|
||||
|
||||
// Make sure the watchdog is available for this version
|
||||
@ -692,8 +705,8 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
ZigbeeInterfaceDeconzReply *replyWatchdogTimeout = requestReadParameter(Deconz::ParameterWatchdogTtl);
|
||||
connect(replyWatchdogTimeout, &ZigbeeInterfaceDeconzReply::finished, this, [this, readNetworkParametersReply, replyWatchdogTimeout](){
|
||||
if (replyWatchdogTimeout->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
qCWarning(dcZigbeeController()) << "Request" << replyWatchdogTimeout->command() << Deconz::ParameterWatchdogTtl
|
||||
<< "finished with error" << replyWatchdogTimeout->statusCode();
|
||||
qCWarning(dcZigbeeController()) << "Request" << "SQN:" << replyWatchdogTimeout->sequenceNumber() << replyWatchdogTimeout->command()
|
||||
<< Deconz::ParameterWatchdogTtl << "finished with error" << replyWatchdogTimeout->statusCode();
|
||||
readNetworkParametersReply->m_statusCode = replyWatchdogTimeout->statusCode();
|
||||
readNetworkParametersReply->finished();
|
||||
return;
|
||||
@ -704,8 +717,8 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::readNetworkParameters(
|
||||
quint16 payloadLenght = 0; quint8 parameter = 0; quint32 watchdogTimeout = 0;
|
||||
stream >> payloadLenght >> parameter >> watchdogTimeout;
|
||||
m_networkConfiguration.watchdogTimeout = watchdogTimeout;
|
||||
qCDebug(dcZigbeeController()) << "Request" << replyWatchdogTimeout->command() << static_cast<Deconz::Parameter>(parameter)
|
||||
<< "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Request" << "SQN:" << replyWatchdogTimeout->sequenceNumber() << replyWatchdogTimeout->command()
|
||||
<< static_cast<Deconz::Parameter>(parameter) << "finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Watchdog timeout:" << m_networkConfiguration.watchdogTimeout;
|
||||
|
||||
// Finished reading all parameters. Finish the independent reply in order to indicate the process has finished
|
||||
@ -746,13 +759,13 @@ 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();
|
||||
qCWarning(dcZigbeeController()) << "Could not read data indication." << "SQN:" << reply->sequenceNumber() << reply->statusCode();
|
||||
// FIXME: set an appropriate error
|
||||
return;
|
||||
}
|
||||
|
||||
// APS data indication received, process the content
|
||||
qCDebug(dcZigbeeController()) << "Reading data indication finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Reading data indication finished successfully" << "SQN:" << reply->sequenceNumber();
|
||||
processDataIndication(reply->responseData());
|
||||
});
|
||||
}
|
||||
@ -762,20 +775,20 @@ 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();
|
||||
qCWarning(dcZigbeeController()) << "Could not read data confirm." << "SQN:" << reply->sequenceNumber() << reply->statusCode();
|
||||
// FIXME: set an appropriate error
|
||||
return;
|
||||
}
|
||||
|
||||
// APS data confirm received, process the content
|
||||
qCDebug(dcZigbeeController()) << "Reading data confirm finished successfully";
|
||||
qCDebug(dcZigbeeController()) << "Reading data confirm finished successfully" << "SQN:" << reply->sequenceNumber();
|
||||
processDataConfirm(reply->responseData());
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceState)
|
||||
{
|
||||
qCDebug(dcZigbeeController()) << deviceState;
|
||||
qCDebug(dcZigbeeController()) << "Process device state notification" << deviceState;
|
||||
|
||||
if (m_networkState != deviceState.networkState) {
|
||||
qCDebug(dcZigbeeController()) << "Network state changed" << deviceState.networkState;
|
||||
@ -785,7 +798,10 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
|
||||
|
||||
if (m_apsFreeSlotsAvailable != deviceState.apsDataRequestFreeSlots) {
|
||||
m_apsFreeSlotsAvailable = deviceState.apsDataRequestFreeSlots;
|
||||
|
||||
if (!m_apsFreeSlotsAvailable) {
|
||||
qCWarning(dcZigbeeController()) << "The APS request table is full on the device. Cannot send requests until the queue gets processed on the controller.";
|
||||
return;
|
||||
}
|
||||
// FIXME: if changed to true, send next aps data request
|
||||
|
||||
}
|
||||
@ -851,6 +867,7 @@ void ZigbeeBridgeControllerDeconz::processDataIndication(const QByteArray &data)
|
||||
|
||||
// Process the device state in order to check if we have to request another indication
|
||||
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
|
||||
qCDebug(dcZigbeeController()) << "Verify device state after data indication response" << deviceState;
|
||||
if (deviceState.apsDataIndication) {
|
||||
readDataIndication();
|
||||
}
|
||||
@ -881,6 +898,7 @@ void ZigbeeBridgeControllerDeconz::processDataConfirm(const QByteArray &data)
|
||||
|
||||
// Process the device state in order to check if we have to request another indication
|
||||
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
|
||||
qCDebug(dcZigbeeController()) << "Verify device state after data confirmation response" << deviceState;
|
||||
if (deviceState.apsDataConfirm) {
|
||||
readDataConfirm();
|
||||
}
|
||||
@ -912,12 +930,16 @@ 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) {
|
||||
ZigbeeInterfaceDeconzReply *reply = m_pendingReplies.take(sequenceNumber);
|
||||
if (!reply) {
|
||||
qCWarning(dcZigbeeController()) << "Received message but the corresponding reply does not exist any more.";
|
||||
return;
|
||||
}
|
||||
reply->m_responseData = data;
|
||||
reply->m_statusCode = status;
|
||||
reply->finished();
|
||||
@ -927,7 +949,7 @@ void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray &
|
||||
// Note: we got a notification, lets set the current sequence number to the notification id,
|
||||
// so the next request will be a continuouse increase
|
||||
|
||||
m_sequenceNumber = sequenceNumber;
|
||||
m_sequenceNumber = sequenceNumber + 1;
|
||||
|
||||
// No request for this data, lets check which notification and process the data
|
||||
switch (command) {
|
||||
@ -938,12 +960,12 @@ void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray &
|
||||
break;
|
||||
}
|
||||
case Deconz::CommandMacPoll: {
|
||||
// FIXME: parse the data and print info
|
||||
|
||||
qCDebug(dcZigbeeController()) << "MAC Poll command received" << ZigbeeUtils::convertByteArrayToHexString(data);// FIXME: parse the data and print info
|
||||
break;
|
||||
}
|
||||
case Deconz::CommandSimplifiedBeacon: {
|
||||
// FIXME: parse the data and print info
|
||||
qCDebug(dcZigbeeController()) << "Simplified beacon command received" << ZigbeeUtils::convertByteArrayToHexString(data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -951,7 +973,6 @@ void ZigbeeBridgeControllerDeconz::onInterfacePackageReceived(const QByteArray &
|
||||
<< status << "Frame length:" << frameLength << ZigbeeUtils::convertByteArrayToHexString(data);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ZigbeeBridgeControllerDeconz::resetControllerWatchdog()
|
||||
|
||||
@ -29,8 +29,9 @@
|
||||
#define ZIGBEEBRIDGECONTROLLERDECONZ_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QQueue>
|
||||
#include <QObject>
|
||||
|
||||
#include "zigbee.h"
|
||||
#include "zigbeeaddress.h"
|
||||
@ -85,6 +86,7 @@ public:
|
||||
|
||||
Deconz::NetworkState networkState() const;
|
||||
|
||||
// Controllere requests
|
||||
ZigbeeInterfaceDeconzReply *requestVersion();
|
||||
ZigbeeInterfaceDeconzReply *requestDeviceState();
|
||||
ZigbeeInterfaceDeconzReply *requestReadParameter(Deconz::Parameter parameter);
|
||||
@ -96,12 +98,8 @@ public:
|
||||
ZigbeeInterfaceDeconzReply *requestQuerySendDataConfirm();
|
||||
|
||||
// Send data
|
||||
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataGroup(quint8 requestId, quint16 groupAddress, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);
|
||||
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);
|
||||
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataIeeeAddress(quint8 requestId, ZigbeeAddress ieeeAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);
|
||||
ZigbeeInterfaceDeconzReply *requestSendRequest(const ZigbeeNetworkRequest &request);
|
||||
|
||||
|
||||
private:
|
||||
ZigbeeInterfaceDeconz *m_interface = nullptr;
|
||||
quint8 m_sequenceNumber = 0;
|
||||
@ -112,12 +110,20 @@ private:
|
||||
Deconz::NetworkState m_networkState = Deconz::NetworkStateOffline;
|
||||
QTimer *m_watchdogTimer = nullptr;
|
||||
|
||||
// APS request queue
|
||||
bool m_apsFreeSlotsAvailable = false;
|
||||
QQueue<ZigbeeNetworkRequest> m_requestQueue;
|
||||
void sendNextRequest();
|
||||
|
||||
quint8 generateSequenceNumber();
|
||||
|
||||
ZigbeeInterfaceDeconzReply *createReply(Deconz::Command command, quint8 sequenceNumber, QObject *parent);
|
||||
|
||||
// Send data depending on the request destination address mode
|
||||
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataGroup(quint8 requestId, quint16 groupAddress, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);
|
||||
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataShortAddress(quint8 requestId, quint16 shortAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);
|
||||
ZigbeeInterfaceDeconzReply *requestEnqueueSendDataIeeeAddress(quint8 requestId, ZigbeeAddress ieeeAddress, quint8 destinationEndpoint, quint16 profileId, quint16 clusterId, quint8 sourceEndpoint, const QByteArray &asdu, Zigbee::ZigbeeTxOptions txOptions, quint8 radius = 0);
|
||||
|
||||
// Note: this method reads all parameters individual. The returned reply it self will not send or receive any data.
|
||||
// The data can be fetched from m_networkConfiguration on success.
|
||||
ZigbeeInterfaceDeconzReply *readNetworkParameters();
|
||||
|
||||
@ -191,7 +191,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured APS extended PANID successfully. SQN:" << reply->sequenceNumber();
|
||||
qCDebug(dcZigbeeController()) << "Configured APS extended PANID successfully. SQN:" << reply->sequenceNumber();
|
||||
|
||||
QByteArray paramData;
|
||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||
@ -206,7 +206,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured trust center address successfully. SQN:" << reply->sequenceNumber();
|
||||
qCDebug(dcZigbeeController()) << "Configured trust center address successfully. SQN:" << reply->sequenceNumber();
|
||||
|
||||
QByteArray paramData;
|
||||
QDataStream stream(¶mData, QIODevice::WriteOnly);
|
||||
@ -221,7 +221,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured security mode successfully. SQN:" << reply->sequenceNumber();
|
||||
qCDebug(dcZigbeeController()) << "Configured security mode successfully. SQN:" << reply->sequenceNumber();
|
||||
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Configure network key" << securityConfiguration().networkKey().toString();
|
||||
@ -233,7 +233,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
// Note: writing the network key fails all the time...
|
||||
//return;
|
||||
} else {
|
||||
qCDebug(dcZigbeeNetwork()) << "Configured network key successfully. SQN:" << reply->sequenceNumber();
|
||||
qCDebug(dcZigbeeController()) << "Configured network key successfully. SQN:" << reply->sequenceNumber();
|
||||
}
|
||||
|
||||
// Configuration finished, lets start the network
|
||||
@ -284,7 +284,9 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
case CreateNetworkStateInitializeCoordinatorNode: {
|
||||
if (m_coordinatorNode) {
|
||||
qCDebug(dcZigbeeNetwork()) << "We already have the coordinator node. Network starting done.";
|
||||
m_initializing = false;
|
||||
setState(StateRunning);
|
||||
setPermitJoiningInternal(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -295,7 +297,9 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
connect(coordinatorNode, &ZigbeeNode::stateChanged, this, [this, coordinatorNode](ZigbeeNode::State state){
|
||||
if (state == ZigbeeNode::StateInitialized) {
|
||||
qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode;
|
||||
m_initializing = false;
|
||||
setState(StateRunning);
|
||||
setPermitJoiningInternal(false);
|
||||
return;
|
||||
}
|
||||
});
|
||||
@ -350,6 +354,11 @@ void ZigbeeNetworkDeconz::handleZigbeeClusterLibraryIndication(const Zigbee::Aps
|
||||
if (!node) {
|
||||
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
||||
// FIXME: maybe create and init the node, since it is in the network, but not recognized
|
||||
|
||||
// Remove this node since we might have removed it but it did not respond, or we not explicitly allowed it to join.
|
||||
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -467,6 +476,8 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Reading current network state finished successfully." << "SQN:" << reply->sequenceNumber();
|
||||
|
||||
QDataStream stream(reply->responseData());
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 deviceStateFlag = 0;
|
||||
@ -489,8 +500,11 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
|
||||
// Get the network state and start the network if required
|
||||
if (m_controller->networkState() == Deconz::NetworkStateConnected) {
|
||||
qCDebug(dcZigbeeNetwork()) << "The network is already running.";
|
||||
m_initializing = false;
|
||||
setState(StateRunning);
|
||||
setPermitJoiningInternal(false);
|
||||
} else if (m_controller->networkState() == Deconz::NetworkStateOffline) {
|
||||
m_initializing = true;
|
||||
qCDebug(dcZigbeeNetwork()) << "The network is offline. Lets start it";
|
||||
setCreateNetworkState(CreateNetworkStateStartNetwork);
|
||||
} else {
|
||||
@ -507,12 +521,14 @@ void ZigbeeNetworkDeconz::onControllerAvailableChanged(bool available)
|
||||
if (!available) {
|
||||
qCWarning(dcZigbeeNetwork()) << "Hardware controller is not available any more.";
|
||||
setError(ErrorHardwareUnavailable);
|
||||
m_initializing = false;
|
||||
m_permitJoining = false;
|
||||
emit permitJoiningChanged(m_permitJoining);
|
||||
setState(StateOffline);
|
||||
} else {
|
||||
m_error = ErrorNoError;
|
||||
m_permitJoining = false;
|
||||
m_initializing = true;
|
||||
emit permitJoiningChanged(m_permitJoining);
|
||||
setState(StateStarting);
|
||||
qCDebug(dcZigbeeNetwork()) << "Hardware controller is now available.";
|
||||
@ -647,7 +663,10 @@ void ZigbeeNetworkDeconz::startNetwork()
|
||||
|
||||
m_permitJoining = false;
|
||||
emit permitJoiningChanged(m_permitJoining);
|
||||
|
||||
// Note: wait for the controller available signal and start the initialization there
|
||||
|
||||
m_initializing = true;
|
||||
}
|
||||
|
||||
void ZigbeeNetworkDeconz::stopNetwork()
|
||||
@ -674,6 +693,7 @@ void ZigbeeNetworkDeconz::reset()
|
||||
void ZigbeeNetworkDeconz::factoryResetNetwork()
|
||||
{
|
||||
qCDebug(dcZigbeeNetwork()) << "Factory reset network and forget all information. This cannot be undone.";
|
||||
m_controller->disable();
|
||||
clearSettings();
|
||||
setState(StateUninitialized);
|
||||
qCDebug(dcZigbeeNetwork()) << "The factory reset is finished. Start restart with a fresh network.";
|
||||
|
||||
@ -56,13 +56,14 @@ public:
|
||||
// Sending an APSDE-DATA.request, will be finished on APSDE-DATA.confirm
|
||||
ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override;
|
||||
|
||||
ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress, quint8 duration);
|
||||
ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
|
||||
|
||||
private:
|
||||
ZigbeeBridgeControllerDeconz *m_controller = nullptr;
|
||||
bool m_networkRunning = false;
|
||||
CreateNetworkState m_createState = CreateNetworkStateIdle;
|
||||
bool m_createNewNetwork = false;
|
||||
bool m_initializing = false;
|
||||
|
||||
QTimer *m_permitJoinRefreshTimer = nullptr;
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ SOURCES += \
|
||||
backends/deconz/zigbeebridgecontrollerdeconz.cpp \
|
||||
backends/deconz/zigbeenetworkdeconz.cpp \
|
||||
zcl/general/zigbeeclusteridentify.cpp \
|
||||
zcl/general/zigbeeclusterlevelcontrol.cpp \
|
||||
zcl/general/zigbeeclusteronoff.cpp \
|
||||
zcl/measurement/zigbeeclusterilluminancemeasurment.cpp \
|
||||
zcl/measurement/zigbeeclusteroccupancysensing.cpp \
|
||||
@ -57,6 +58,7 @@ HEADERS += \
|
||||
backends/deconz/zigbeebridgecontrollerdeconz.h \
|
||||
backends/deconz/zigbeenetworkdeconz.h \
|
||||
zcl/general/zigbeeclusteridentify.h \
|
||||
zcl/general/zigbeeclusterlevelcontrol.h \
|
||||
zcl/general/zigbeeclusteronoff.h \
|
||||
zcl/measurement/zigbeeclusterilluminancemeasurment.h \
|
||||
zcl/measurement/zigbeeclusteroccupancysensing.h \
|
||||
|
||||
@ -40,156 +40,25 @@ ZigbeeClusterIdentify::ZigbeeClusterIdentify(ZigbeeNetwork *network, ZigbeeNode
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterIdentify::identify(quint16 seconds)
|
||||
{
|
||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||
|
||||
// Build ZCL frame
|
||||
|
||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||
frameControl.manufacturerSpecific = false;
|
||||
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||
frameControl.disableDefaultResponse = false;
|
||||
|
||||
// ZCL header
|
||||
ZigbeeClusterLibrary::Header header;
|
||||
header.frameControl = frameControl;
|
||||
header.command = ZigbeeClusterIdentify::CommandIdentify;
|
||||
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// Note: the identify time unit is 0.5 seconds
|
||||
QByteArray payload = ZigbeeDataType(seconds * 2).data();
|
||||
|
||||
// Put them together
|
||||
ZigbeeClusterLibrary::Frame frame;
|
||||
frame.header = header;
|
||||
frame.payload = payload;
|
||||
|
||||
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||
|
||||
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zclReply->isComplete()) {
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return zclReply;
|
||||
return executeClusterCommand(ZigbeeClusterIdentify::CommandIdentify, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterIdentify::identifyQuery()
|
||||
{
|
||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||
|
||||
// Build ZCL frame
|
||||
|
||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||
frameControl.manufacturerSpecific = false;
|
||||
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||
frameControl.disableDefaultResponse = false;
|
||||
|
||||
// ZCL header
|
||||
ZigbeeClusterLibrary::Header header;
|
||||
header.frameControl = frameControl;
|
||||
header.command = ZigbeeClusterIdentify::CommandIdentifyQuery;
|
||||
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// No payload
|
||||
|
||||
// Put them together
|
||||
ZigbeeClusterLibrary::Frame frame;
|
||||
frame.header = header;
|
||||
|
||||
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||
|
||||
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zclReply->isComplete()) {
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return zclReply;
|
||||
return executeClusterCommand(ZigbeeClusterIdentify::CommandIdentifyQuery);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterIdentify::triggerEffect(ZigbeeClusterIdentify::Effect effect, quint8 effectVariant)
|
||||
{
|
||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||
|
||||
// Build ZCL frame
|
||||
|
||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||
frameControl.manufacturerSpecific = false;
|
||||
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||
frameControl.disableDefaultResponse = false;
|
||||
|
||||
// ZCL header
|
||||
ZigbeeClusterLibrary::Header header;
|
||||
header.frameControl = frameControl;
|
||||
header.command = ZigbeeClusterIdentify::CommandTriggerEffect;
|
||||
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << static_cast<quint8>(effect);
|
||||
stream << static_cast<quint8>(effectVariant);
|
||||
|
||||
// Put them together
|
||||
ZigbeeClusterLibrary::Frame frame;
|
||||
frame.header = header;
|
||||
frame.payload = payload;
|
||||
|
||||
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||
|
||||
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zclReply->isComplete()) {
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return zclReply;
|
||||
return executeClusterCommand(ZigbeeClusterIdentify::CommandTriggerEffect, payload);
|
||||
}
|
||||
|
||||
void ZigbeeClusterIdentify::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||
|
||||
137
libnymea-zigbee/zcl/general/zigbeeclusterlevelcontrol.cpp
Normal file
137
libnymea-zigbee/zcl/general/zigbeeclusterlevelcontrol.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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 "zigbeeclusterlevelcontrol.h"
|
||||
#include "zigbeenetworkreply.h"
|
||||
#include "loggingcategory.h"
|
||||
#include "zigbeenetwork.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
ZigbeeClusterLevelControl::ZigbeeClusterLevelControl(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, ZigbeeCluster::Direction direction, QObject *parent) :
|
||||
ZigbeeCluster(network, node, endpoint, Zigbee::ClusterIdLevelControl, direction, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMoveToLevel(quint8 level, quint16 transistionTime)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << level << transistionTime;
|
||||
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMoveToLevel, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMove(ZigbeeClusterLevelControl::MoveMode moveMode, quint8 rate)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << static_cast<quint8>(moveMode) << rate;
|
||||
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMove, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStep(ZigbeeClusterLevelControl::FadeMode fadeMode, quint8 stepSize, quint16 transistionTime)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << static_cast<quint8>(fadeMode) << stepSize << transistionTime;
|
||||
return executeClusterCommand(ZigbeeClusterLevelControl::CommandStep, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStop()
|
||||
{
|
||||
return executeClusterCommand(ZigbeeClusterLevelControl::CommandStop);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMoveToLevelWithOnOff(quint8 level, quint16 transistionTime)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << level << transistionTime;
|
||||
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMoveToLevelWithOnOff, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandMoveWithOnOff(ZigbeeClusterLevelControl::MoveMode moveMode, quint8 rate)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << static_cast<quint8>(moveMode) << rate;
|
||||
return executeClusterCommand(ZigbeeClusterLevelControl::CommandMoveWithOnOff, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStepWithOnOff(ZigbeeClusterLevelControl::FadeMode fadeMode, quint8 stepSize, quint16 transistionTime)
|
||||
{
|
||||
QByteArray payload;
|
||||
QDataStream stream(&payload, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << static_cast<quint8>(fadeMode) << stepSize << transistionTime;
|
||||
return executeClusterCommand(ZigbeeClusterLevelControl::CommandStepWithOnOff, payload);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterLevelControl::commandStopWithOnOff()
|
||||
{
|
||||
return executeClusterCommand(ZigbeeClusterLevelControl::CommandStopWithOnOff);
|
||||
}
|
||||
|
||||
void ZigbeeClusterLevelControl::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||
{
|
||||
qCDebug(dcZigbeeCluster()) << "Update attribute" << m_node << m_endpoint << this << static_cast<Attribute>(attribute.id()) << attribute.dataType();
|
||||
if (hasAttribute(attribute.id())) {
|
||||
m_attributes[attribute.id()] = attribute;
|
||||
emit attributeChanged(attribute);
|
||||
} else {
|
||||
m_attributes.insert(attribute.id(), attribute);
|
||||
emit attributeChanged(attribute);
|
||||
}
|
||||
|
||||
// Parse the information for convinience
|
||||
if (attribute.id() == AttributeCurrentLevel) {
|
||||
bool valueOk = false;
|
||||
quint8 value = attribute.dataType().toUInt8(&valueOk);
|
||||
if (valueOk) {
|
||||
qCDebug(dcZigbeeCluster()) << "CurrentLevel state changed on" << m_node << m_endpoint << this << value;
|
||||
emit currentLevelChanged(value);
|
||||
} else {
|
||||
qCWarning(dcZigbeeCluster()) << "Failed to parse attribute data" << m_node << m_endpoint << this << attribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ZigbeeClusterLevelControl::processDataIndication(ZigbeeClusterLibrary::Frame frame)
|
||||
{
|
||||
qCDebug(dcZigbeeCluster()) << "Processing cluster frame" << m_node << m_endpoint << this << frame;
|
||||
|
||||
// Increase the tsn for continuouse id increasing on both sides
|
||||
m_transactionSequenceNumber = frame.header.transactionSequenceNumber;
|
||||
|
||||
// FIXME: parse client commands to group
|
||||
}
|
||||
108
libnymea-zigbee/zcl/general/zigbeeclusterlevelcontrol.h
Normal file
108
libnymea-zigbee/zcl/general/zigbeeclusterlevelcontrol.h
Normal file
@ -0,0 +1,108 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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 ZIGBEECLUSTERLEVELCONTROL_H
|
||||
#define ZIGBEECLUSTERLEVELCONTROL_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "zcl/zigbeecluster.h"
|
||||
#include "zcl/zigbeeclusterreply.h"
|
||||
|
||||
class ZigbeeNode;
|
||||
class ZigbeeNetwork;
|
||||
class ZigbeeNodeEndpoint;
|
||||
class ZigbeeNetworkReply;
|
||||
|
||||
class ZigbeeClusterLevelControl : public ZigbeeCluster
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ZigbeeNode;
|
||||
friend class ZigbeeNetwork;
|
||||
|
||||
public:
|
||||
enum Attribute {
|
||||
AttributeCurrentLevel = 0x0000,
|
||||
AttributeRemainingTime = 0x0001,
|
||||
AttributeOnOffTransitionTime = 0x0010,
|
||||
AttributeOnLevel = 0x0011,
|
||||
AttributeOnTransitionTime = 0x0012,
|
||||
AttributeOffTransitionTime = 0x0013,
|
||||
AttributeDefaultMoveRate = 0x0014
|
||||
};
|
||||
Q_ENUM(Attribute)
|
||||
|
||||
enum Command {
|
||||
CommandMoveToLevel = 0x00,
|
||||
CommandMove = 0x01,
|
||||
CommandStep = 0x02,
|
||||
CommandStop = 0x03,
|
||||
CommandMoveToLevelWithOnOff = 0x04,
|
||||
CommandMoveWithOnOff = 0x05,
|
||||
CommandStepWithOnOff = 0x06,
|
||||
CommandStopWithOnOff = 0x07
|
||||
};
|
||||
Q_ENUM(Command)
|
||||
|
||||
enum MoveMode {
|
||||
MoveModeUp = 0x00,
|
||||
ModeModeDown = 0x01
|
||||
};
|
||||
Q_ENUM(MoveMode)
|
||||
|
||||
enum FadeMode {
|
||||
FadeModeUp = 0x00,
|
||||
FadeModeDown = 0x01
|
||||
};
|
||||
Q_ENUM(FadeMode)
|
||||
|
||||
explicit ZigbeeClusterLevelControl(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint, Direction direction, QObject *parent = nullptr);
|
||||
|
||||
ZigbeeClusterReply *commandMoveToLevel(quint8 level, quint16 transistionTime = 0xffff);
|
||||
ZigbeeClusterReply *commandMove(MoveMode moveMode, quint8 rate = 0xff);
|
||||
ZigbeeClusterReply *commandStep(FadeMode fadeMode, quint8 stepSize = 0x01, quint16 transistionTime = 0xffff);
|
||||
ZigbeeClusterReply *commandStop();
|
||||
|
||||
// With on/off
|
||||
ZigbeeClusterReply *commandMoveToLevelWithOnOff(quint8 level, quint16 transistionTime = 0xffff);
|
||||
ZigbeeClusterReply *commandMoveWithOnOff(MoveMode moveMode, quint8 rate = 0xff);
|
||||
ZigbeeClusterReply *commandStepWithOnOff(FadeMode fadeMode, quint8 stepSize = 0x01, quint16 transistionTime = 0xffff);
|
||||
ZigbeeClusterReply *commandStopWithOnOff();
|
||||
|
||||
private:
|
||||
void setAttribute(const ZigbeeClusterAttribute &attribute) override;
|
||||
|
||||
protected:
|
||||
void processDataIndication(ZigbeeClusterLibrary::Frame frame) override;
|
||||
|
||||
signals:
|
||||
void currentLevelChanged(quint8 level);
|
||||
|
||||
};
|
||||
|
||||
#endif // ZIGBEECLUSTERLEVELCONTROL_H
|
||||
@ -40,152 +40,17 @@ ZigbeeClusterOnOff::ZigbeeClusterOnOff(ZigbeeNetwork *network, ZigbeeNode *node,
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterOnOff::commandOff()
|
||||
{
|
||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||
|
||||
// Build ZCL frame
|
||||
|
||||
// Note: for basic commands the frame control files has to be zero accoring to spec ZCL 2.4.1.1
|
||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||
frameControl.manufacturerSpecific = false;
|
||||
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||
frameControl.disableDefaultResponse = false;
|
||||
|
||||
// ZCL header
|
||||
ZigbeeClusterLibrary::Header header;
|
||||
header.frameControl = frameControl;
|
||||
header.command = ZigbeeClusterOnOff::CommandOff;
|
||||
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// there is no ZCL payload
|
||||
|
||||
// Put them together
|
||||
ZigbeeClusterLibrary::Frame frame;
|
||||
frame.header = header;
|
||||
|
||||
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||
|
||||
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zclReply->isComplete()) {
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return zclReply;
|
||||
return executeClusterCommand(ZigbeeClusterOnOff::CommandOff);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterOnOff::commandOn()
|
||||
{
|
||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||
|
||||
// Build ZCL frame
|
||||
|
||||
// Note: for basic commands the frame control files has to be zero accoring to spec ZCL 2.4.1.1
|
||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||
frameControl.manufacturerSpecific = false;
|
||||
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||
frameControl.disableDefaultResponse = false;
|
||||
|
||||
// ZCL header
|
||||
ZigbeeClusterLibrary::Header header;
|
||||
header.frameControl = frameControl;
|
||||
header.command = ZigbeeClusterOnOff::CommandOn;
|
||||
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// There is no ZCL payload
|
||||
|
||||
// Put them together
|
||||
ZigbeeClusterLibrary::Frame frame;
|
||||
frame.header = header;
|
||||
|
||||
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||
|
||||
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zclReply->isComplete()) {
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return zclReply;
|
||||
return executeClusterCommand(ZigbeeClusterOnOff::CommandOn);
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeClusterOnOff::commandToggle()
|
||||
{
|
||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||
|
||||
// Build ZCL frame
|
||||
|
||||
// Note: for basic commands the frame control files has to be zero accoring to spec ZCL 2.4.1.1
|
||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||
frameControl.manufacturerSpecific = false;
|
||||
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||
frameControl.disableDefaultResponse = false;
|
||||
|
||||
// ZCL header
|
||||
ZigbeeClusterLibrary::Header header;
|
||||
header.frameControl = frameControl;
|
||||
header.command = ZigbeeClusterOnOff::CommandToggle;
|
||||
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// There is no ZCL payload
|
||||
|
||||
// Put them together
|
||||
ZigbeeClusterLibrary::Frame frame;
|
||||
frame.header = header;
|
||||
|
||||
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||
|
||||
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zclReply->isComplete()) {
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return zclReply;
|
||||
return executeClusterCommand(ZigbeeClusterOnOff::CommandToggle);
|
||||
}
|
||||
|
||||
void ZigbeeClusterOnOff::setAttribute(const ZigbeeClusterAttribute &attribute)
|
||||
@ -240,13 +105,10 @@ void ZigbeeClusterOnOff::processDataIndication(ZigbeeClusterLibrary::Frame frame
|
||||
qCWarning(dcZigbeeCluster()) << "Unhandled command sent from" << m_node << m_endpoint << this << command;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Server:
|
||||
// keep it unhandled if not parsed yet in order to warn about the handled indication
|
||||
qCWarning(dcZigbeeCluster()) << "Unhandled ZCL indication in" << m_node << m_endpoint << this << frame;
|
||||
break;
|
||||
}
|
||||
|
||||
qCWarning(dcZigbeeCluster()) << "Unhandled ZCL indication in" << m_node << m_endpoint << this << frame;
|
||||
}
|
||||
|
||||
@ -80,7 +80,6 @@ void ZigbeeClusterIasZone::processDataIndication(ZigbeeClusterLibrary::Frame fra
|
||||
|
||||
// Update the ZoneState attribute
|
||||
setAttribute(ZigbeeClusterAttribute(AttributeZoneState, ZigbeeDataType(Zigbee::BitMap16, frame.payload.left(2))));
|
||||
|
||||
emit zoneStatusChanged(ZoneStatusFlags(zoneStatus), extendedStatus, zoneId, delay);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ ZigbeeCluster::ZigbeeCluster(ZigbeeNetwork *network, ZigbeeNode *node, ZigbeeNod
|
||||
m_clusterId(clusterId),
|
||||
m_direction(direction)
|
||||
{
|
||||
qCDebug(dcZigbeeCluster()) << "Create cluster" << ZigbeeUtils::convertUint16ToHexString(clusterId) << direction;
|
||||
//qCDebug(dcZigbeeCluster()) << "Create cluster" << ZigbeeUtils::convertUint16ToHexString(clusterId) << direction;
|
||||
}
|
||||
|
||||
ZigbeeCluster::Direction ZigbeeCluster::direction() const
|
||||
@ -162,6 +162,53 @@ ZigbeeClusterReply *ZigbeeCluster::createClusterReply(const ZigbeeNetworkRequest
|
||||
return zclReply;
|
||||
}
|
||||
|
||||
ZigbeeClusterReply *ZigbeeCluster::executeClusterCommand(quint8 command, const QByteArray &payload)
|
||||
{
|
||||
ZigbeeNetworkRequest request = createGeneralRequest();
|
||||
|
||||
// Build ZCL frame control
|
||||
ZigbeeClusterLibrary::FrameControl frameControl;
|
||||
frameControl.frameType = ZigbeeClusterLibrary::FrameTypeClusterSpecific;
|
||||
frameControl.manufacturerSpecific = false;
|
||||
frameControl.direction = ZigbeeClusterLibrary::DirectionClientToServer;
|
||||
frameControl.disableDefaultResponse = false;
|
||||
|
||||
// Build ZCL header
|
||||
ZigbeeClusterLibrary::Header header;
|
||||
header.frameControl = frameControl;
|
||||
header.command = command;
|
||||
header.transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// Build ZCL frame
|
||||
ZigbeeClusterLibrary::Frame frame;
|
||||
frame.header = header;
|
||||
frame.payload = payload;
|
||||
|
||||
request.setTxOptions(Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission));
|
||||
request.setAsdu(ZigbeeClusterLibrary::buildFrame(frame));
|
||||
|
||||
ZigbeeClusterReply *zclReply = createClusterReply(request, frame);
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zclReply](){
|
||||
if (!verifyNetworkError(zclReply, networkReply)) {
|
||||
qCWarning(dcZigbeeClusterLibrary()) << "Failed to send request"
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zclReply->isComplete()) {
|
||||
finishZclReply(zclReply);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return zclReply;
|
||||
}
|
||||
|
||||
ZigbeeNetworkRequest ZigbeeCluster::createGeneralRequest()
|
||||
{
|
||||
// Build the request
|
||||
|
||||
@ -90,31 +90,6 @@ public:
|
||||
// Q_ENUM(PowerConfigurationAttribute)
|
||||
|
||||
|
||||
// // Level cluster 0x0008
|
||||
|
||||
// enum LevelClusterAttribute {
|
||||
// LevelClusterAttributeCurrentLevel = 0x0000,
|
||||
// LevelClusterAttributeRemainingTime = 0x0001,
|
||||
// LevelClusterAttributeOnOffTransitionTime = 0x0010,
|
||||
// LevelClusterAttributeOnLevel = 0x0011,
|
||||
// LevelClusterAttributeOnTransitionTime = 0x0012,
|
||||
// LevelClusterAttributeOffTransitionTime = 0x0013,
|
||||
// LevelClusterAttributeDefaultMoveRate = 0x0014
|
||||
// };
|
||||
// Q_ENUM(LevelClusterAttribute)
|
||||
|
||||
// enum LevelClusterCommand {
|
||||
// LevelClusterCommandMoveToLevel = 0x00,
|
||||
// LevelClusterCommandMove = 0x01,
|
||||
// LevelClusterCommandStep = 0x02,
|
||||
// LevelClusterCommandStop = 0x03,
|
||||
// LevelClusterCommandMoveToLevelWithOnOff = 0x04,
|
||||
// LevelClusterCommandMoveWithOnOff = 0x05,
|
||||
// LevelClusterCommandStepWithOnOff = 0x06,
|
||||
// LevelClusterCommandStopWithOnOff = 0x07,
|
||||
// };
|
||||
// Q_ENUM(LevelClusterCommand)
|
||||
|
||||
// // Color cluster 0x0300
|
||||
|
||||
// enum ColorControlClusterAttribute {
|
||||
@ -170,11 +145,12 @@ protected:
|
||||
Direction m_direction = Server;
|
||||
QHash<quint16, ZigbeeClusterAttribute> m_attributes;
|
||||
|
||||
// Helper methods for sending cluster specific commands
|
||||
ZigbeeNetworkRequest createGeneralRequest();
|
||||
quint8 m_transactionSequenceNumber = 0;
|
||||
QHash<quint8, ZigbeeClusterReply *> m_pendingReplies;
|
||||
ZigbeeClusterReply *createClusterReply(const ZigbeeNetworkRequest &request, ZigbeeClusterLibrary::Frame frame);
|
||||
|
||||
ZigbeeClusterReply *executeClusterCommand(quint8 command, const QByteArray &payload = QByteArray());
|
||||
bool verifyNetworkError(ZigbeeClusterReply *zclReply, ZigbeeNetworkReply *networkReply);
|
||||
void finishZclReply(ZigbeeClusterReply *zclReply);
|
||||
|
||||
|
||||
@ -30,6 +30,158 @@
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
ZigbeeDeviceProfile::NodeDescriptor ZigbeeDeviceProfile::parseNodeDescriptor(const QByteArray &payload)
|
||||
{
|
||||
NodeDescriptor nodeDescriptor;
|
||||
nodeDescriptor.descriptorRawData = payload;
|
||||
|
||||
// Parse and set the node descriptor
|
||||
QDataStream stream(payload);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 typeDescriptorFlag = 0; quint8 frequencyFlag = 0; quint8 macCapabilitiesFlag = 0;
|
||||
quint16 serverMaskFlag = 0; quint8 descriptorCapabilitiesFlag = 0;
|
||||
|
||||
stream >> typeDescriptorFlag >> frequencyFlag >> macCapabilitiesFlag >> nodeDescriptor.manufacturerCode >> nodeDescriptor.maximumBufferSize;
|
||||
stream >> nodeDescriptor.maximumRxSize >> serverMaskFlag >> nodeDescriptor.maximumTxSize >> descriptorCapabilitiesFlag;
|
||||
|
||||
// 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device
|
||||
if (!ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 1)) {
|
||||
nodeDescriptor.nodeType = NodeTypeCoordinator;
|
||||
} else if (!ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 0) && ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 1)) {
|
||||
nodeDescriptor.nodeType = NodeTypeRouter;
|
||||
} else if (ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 1)) {
|
||||
nodeDescriptor.nodeType = NodeTypeEndDevice;
|
||||
}
|
||||
|
||||
nodeDescriptor.complexDescriptorAvailable = (typeDescriptorFlag >> 3) & 0x0001;
|
||||
nodeDescriptor.userDescriptorAvailable = (typeDescriptorFlag >> 4) & 0x0001;
|
||||
|
||||
// Frequency band, 5 bits
|
||||
if (ZigbeeUtils::checkBitUint8(frequencyFlag, 3)) {
|
||||
nodeDescriptor.frequencyBand = FrequencyBand868Mhz;
|
||||
} else if (ZigbeeUtils::checkBitUint8(frequencyFlag, 5)) {
|
||||
nodeDescriptor.frequencyBand = FrequencyBand902Mhz;
|
||||
} else if (ZigbeeUtils::checkBitUint8(frequencyFlag, 6)) {
|
||||
nodeDescriptor.frequencyBand = FrequencyBand2400Mhz;
|
||||
}
|
||||
|
||||
nodeDescriptor.macCapabilities = parseMacCapabilities(macCapabilitiesFlag);
|
||||
nodeDescriptor.serverMask = parseServerMask(serverMaskFlag);
|
||||
nodeDescriptor.descriptorCapabilities = parseDescriptorCapabilities(descriptorCapabilitiesFlag);
|
||||
|
||||
return nodeDescriptor;
|
||||
}
|
||||
|
||||
ZigbeeDeviceProfile::MacCapabilities ZigbeeDeviceProfile::parseMacCapabilities(quint8 macCapabilitiesFlag)
|
||||
{
|
||||
MacCapabilities capabilities;
|
||||
capabilities.flag = macCapabilitiesFlag;
|
||||
capabilities.alternatePanCoordinator = ((macCapabilitiesFlag >> 0) & 0x01);
|
||||
if (((macCapabilitiesFlag >> 1) & 0x01)) {
|
||||
capabilities.deviceType = DeviceTypeFullFunction;
|
||||
} else {
|
||||
capabilities.deviceType = DeviceTypeReducedFunction;
|
||||
}
|
||||
capabilities.powerSourceFlagMainPower = ((macCapabilitiesFlag >> 2) & 0x01);
|
||||
capabilities.receiverOnWhenIdle = ((macCapabilitiesFlag >> 3) & 0x01);
|
||||
capabilities.securityCapability = ((macCapabilitiesFlag >> 6) & 0x01);
|
||||
capabilities.allocateAddress = ((macCapabilitiesFlag >> 7) & 0x01);
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
ZigbeeDeviceProfile::ServerMask ZigbeeDeviceProfile::parseServerMask(quint16 serverMaskFlag)
|
||||
{
|
||||
ServerMask serverMask;
|
||||
serverMask.serverMaskFlag = serverMaskFlag;
|
||||
serverMask.primaryTrustCenter = ((serverMaskFlag >> 0) & 0x0001);
|
||||
serverMask.backupTrustCenter = ((serverMaskFlag >> 1) & 0x0001);
|
||||
serverMask.primaryBindingCache = ((serverMaskFlag >> 2) & 0x0001);
|
||||
serverMask.backupBindingCache = ((serverMaskFlag >> 3) & 0x0001);
|
||||
serverMask.primaryDiscoveryCache = ((serverMaskFlag >> 4) & 0x0001);
|
||||
serverMask.backupDiscoveryCache = ((serverMaskFlag >> 5) & 0x0001);
|
||||
serverMask.networkManager = ((serverMaskFlag >> 6) & 0x0001);
|
||||
return serverMask;
|
||||
}
|
||||
|
||||
ZigbeeDeviceProfile::DescriptorCapabilities ZigbeeDeviceProfile::parseDescriptorCapabilities(quint8 descriptorCapabilitiesFlag)
|
||||
{
|
||||
DescriptorCapabilities capabilities;
|
||||
capabilities.descriptorCapabilitiesFlag = descriptorCapabilitiesFlag;
|
||||
capabilities.extendedActiveEndpointListAvailable = ((descriptorCapabilitiesFlag >> 0) & 0x01);
|
||||
capabilities.extendedSimpleDescriptorListAvailable = ((descriptorCapabilitiesFlag >> 1) & 0x01);
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
ZigbeeDeviceProfile::PowerDescriptor ZigbeeDeviceProfile::parsePowerDescriptor(quint16 powerDescriptorFlag)
|
||||
{
|
||||
PowerDescriptor powerDescriptor;
|
||||
|
||||
powerDescriptor.powerDescriptoFlag = powerDescriptorFlag;
|
||||
|
||||
|
||||
// Bit 0 - 3 Power mode
|
||||
// 0000: Receiver configured according to “Receiver on when idle” MAC flag in the Node Descriptor
|
||||
// 0001: Receiver switched on periodically
|
||||
// 0010: Receiver switched on when stimulated, e.g. by pressing a button
|
||||
|
||||
powerDescriptor.powerMode = ZigbeeDeviceProfile::PowerModeAlwaysOn;
|
||||
if (!ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 1)) {
|
||||
powerDescriptor.powerMode = ZigbeeDeviceProfile::PowerModeAlwaysOn;
|
||||
} else if (ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 1)) {
|
||||
powerDescriptor.powerMode = ZigbeeDeviceProfile::PowerModeOnPeriodically;
|
||||
} else if (!ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 0) && ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 1)) {
|
||||
powerDescriptor.powerMode = ZigbeeDeviceProfile::PowerModeOnWhenStimulated;
|
||||
}
|
||||
|
||||
// Bit 4 - 7 Available power sources
|
||||
// Bit 0: Permanent mains supply
|
||||
// Bit 1: Rechargeable battery
|
||||
// Bit 2: Disposable battery
|
||||
// Bit 4: Reserved
|
||||
if (ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 4)) {
|
||||
powerDescriptor.availablePowerSources.append(ZigbeeDeviceProfile::PowerSourcePermanentMainSupply);
|
||||
} else if (ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 5)) {
|
||||
powerDescriptor.availablePowerSources.append(ZigbeeDeviceProfile::PowerSourceRecharchableBattery);
|
||||
} else if (ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 6)) {
|
||||
powerDescriptor.availablePowerSources.append(ZigbeeDeviceProfile::PowerSourceDisposableBattery);
|
||||
}
|
||||
|
||||
// Bit 8 - 11 Active source: according to the same schema as available power sources
|
||||
powerDescriptor.powerSource = ZigbeeDeviceProfile::PowerSourcePermanentMainSupply;
|
||||
if (ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 8)) {
|
||||
powerDescriptor.powerSource = ZigbeeDeviceProfile::PowerSourcePermanentMainSupply;
|
||||
} else if (ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 9)) {
|
||||
powerDescriptor.powerSource = ZigbeeDeviceProfile::PowerSourceRecharchableBattery;
|
||||
} else if (ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 10)) {
|
||||
powerDescriptor.powerSource = ZigbeeDeviceProfile::PowerSourceDisposableBattery;
|
||||
}
|
||||
|
||||
// Bit 12 - 15: Battery level if available
|
||||
// 0000: Critically low
|
||||
// 0100: Approximately 33%
|
||||
// 1000: Approximately 66%
|
||||
// 1100: Approximately 100% (near fully charged)
|
||||
if (!ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 14) && !ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 15)) {
|
||||
powerDescriptor.powerLevel = ZigbeeDeviceProfile::PowerLevelCriticalLow;
|
||||
} else if (ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 14) && !ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 15)) {
|
||||
powerDescriptor.powerLevel = ZigbeeDeviceProfile::PowerLevelLow;
|
||||
} else if (!ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 14) && ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 15)) {
|
||||
powerDescriptor.powerLevel = ZigbeeDeviceProfile::PowerLevelOk;
|
||||
} else if (ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 14) && ZigbeeUtils::checkBitUint16(powerDescriptorFlag, 15)) {
|
||||
powerDescriptor.powerLevel = ZigbeeDeviceProfile::PowerLevelFull;
|
||||
}
|
||||
|
||||
// qCDebug(dcZigbeeNode()) << "Node power descriptor (" << ZigbeeUtils::convertUint16ToHexString(m_powerDescriptorFlag) << "):";
|
||||
// qCDebug(dcZigbeeNode()) << " Power mode:" << m_powerMode;
|
||||
// qCDebug(dcZigbeeNode()) << " Available power sources:";
|
||||
// foreach (const PowerSource &source, m_availablePowerSources) {
|
||||
// qCDebug(dcZigbeeNode()) << " " << source;
|
||||
// }
|
||||
// qCDebug(dcZigbeeNode()) << " Power source:" << m_powerSource;
|
||||
// qCDebug(dcZigbeeNode()) << " Power level:" << m_powerLevel;
|
||||
return powerDescriptor;
|
||||
}
|
||||
|
||||
ZigbeeDeviceProfile::Adpu ZigbeeDeviceProfile::parseAdpu(const QByteArray &adpu)
|
||||
{
|
||||
QDataStream stream(adpu);
|
||||
@ -51,3 +203,62 @@ QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::Adpu &deviceAdpu)
|
||||
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(deviceAdpu.payload) << ")";
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::NodeDescriptor &nodeDescriptor)
|
||||
{
|
||||
debug.nospace() << "NodeDescriptor(" << nodeDescriptor.nodeType << ")" << endl;
|
||||
debug.nospace() << " Complex descriptor available: " << nodeDescriptor.complexDescriptorAvailable << endl;
|
||||
debug.nospace() << " User descriptor available: " << nodeDescriptor.userDescriptorAvailable << endl;
|
||||
debug.nospace() << " " << nodeDescriptor.frequencyBand << endl;
|
||||
debug.nospace() << " " << nodeDescriptor.macCapabilities;
|
||||
debug.nospace() << " Manufacturer code: " << ZigbeeUtils::convertUint16ToHexString(nodeDescriptor.manufacturerCode) << "(" << nodeDescriptor.manufacturerCode << ")" << endl;
|
||||
debug.nospace() << " Maximum buffer size: " << nodeDescriptor.maximumBufferSize << endl;
|
||||
debug.nospace() << " Maximum RX size: " << nodeDescriptor.maximumRxSize << endl;
|
||||
debug.nospace() << " Maximum TX size: " << nodeDescriptor.maximumTxSize << endl;
|
||||
debug.nospace() << " " << nodeDescriptor.serverMask;
|
||||
debug.nospace() << " " << nodeDescriptor.descriptorCapabilities;
|
||||
return debug;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::MacCapabilities &macCapabilities)
|
||||
{
|
||||
debug.nospace() << "MacCapabilities(" << ZigbeeUtils::convertByteToHexString(macCapabilities.flag) << ")" << endl;
|
||||
debug.nospace() << " Alternate PAN Coordinator: " << macCapabilities.alternatePanCoordinator << endl;
|
||||
debug.nospace() << " " << macCapabilities.deviceType << endl;
|
||||
debug.nospace() << " Power source main power: " << macCapabilities.powerSourceFlagMainPower << endl;
|
||||
debug.nospace() << " Receiver on when idle: " << macCapabilities.receiverOnWhenIdle << endl;
|
||||
debug.nospace() << " Security capability: " << macCapabilities.securityCapability << endl;
|
||||
debug.nospace() << " Allocate address: " << macCapabilities.allocateAddress << endl;
|
||||
return debug;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::ServerMask &serverMask)
|
||||
{
|
||||
debug.nospace() << "ServerMask(" << ZigbeeUtils::convertUint16ToHexString(serverMask.serverMaskFlag) << ")" << endl;
|
||||
debug.nospace() << " Primary trust center: " << serverMask.primaryTrustCenter << endl;
|
||||
debug.nospace() << " Backup trust center: " << serverMask.backupTrustCenter << endl;
|
||||
debug.nospace() << " Primary binding cache: " << serverMask.primaryBindingCache << endl;
|
||||
debug.nospace() << " Backup binding cache: " << serverMask.backupBindingCache << endl;
|
||||
debug.nospace() << " Primary discovery cache: " << serverMask.primaryDiscoveryCache << endl;
|
||||
debug.nospace() << " Backup discovery cache: " << serverMask.backupDiscoveryCache << endl;
|
||||
debug.nospace() << " Network manager: " << serverMask.networkManager << endl;
|
||||
return debug;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::DescriptorCapabilities &descriptorCapabilities)
|
||||
{
|
||||
debug.nospace() << "DescriptorCapabilities(" << ZigbeeUtils::convertByteToHexString(descriptorCapabilities.descriptorCapabilitiesFlag) << ")" << endl;
|
||||
debug.nospace() << " Extended active endpoint list available: " << descriptorCapabilities.extendedActiveEndpointListAvailable << endl;
|
||||
debug.nospace() << " Extended simple descriptor list available: " << descriptorCapabilities.extendedSimpleDescriptorListAvailable << endl;
|
||||
return debug;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::PowerDescriptor &powerDescriptor)
|
||||
{
|
||||
debug.nospace() << "PowerDescriptor(" << ZigbeeUtils::convertByteToHexString(powerDescriptor.powerDescriptoFlag) << ")" << endl;
|
||||
debug.nospace() << " Power mode: " << powerDescriptor.powerMode << endl;
|
||||
debug.nospace() << " Available power sources: " << powerDescriptor.availablePowerSources << endl;
|
||||
debug.nospace() << " Power source: " << powerDescriptor.powerSource << endl;
|
||||
debug.nospace() << " Power level: " << powerDescriptor.powerLevel << endl;
|
||||
return debug;
|
||||
}
|
||||
|
||||
@ -174,8 +174,121 @@ public:
|
||||
} Adpu;
|
||||
|
||||
static ZigbeeDeviceProfile::Adpu parseAdpu(const QByteArray &adpu);
|
||||
|
||||
// Node information
|
||||
enum NodeType {
|
||||
NodeTypeCoordinator = 0,
|
||||
NodeTypeRouter = 1,
|
||||
NodeTypeEndDevice = 2
|
||||
};
|
||||
Q_ENUM(NodeType)
|
||||
|
||||
enum FrequencyBand {
|
||||
FrequencyBand868Mhz,
|
||||
FrequencyBand902Mhz,
|
||||
FrequencyBand2400Mhz
|
||||
};
|
||||
Q_ENUM(FrequencyBand)
|
||||
|
||||
enum DeviceType {
|
||||
DeviceTypeFullFunction,
|
||||
DeviceTypeReducedFunction
|
||||
};
|
||||
Q_ENUM(DeviceType)
|
||||
|
||||
enum Relationship {
|
||||
Parent,
|
||||
Child,
|
||||
Sibling
|
||||
};
|
||||
Q_ENUM(Relationship)
|
||||
|
||||
enum PowerMode {
|
||||
PowerModeAlwaysOn,
|
||||
PowerModeOnPeriodically,
|
||||
PowerModeOnWhenStimulated
|
||||
};
|
||||
Q_ENUM(PowerMode)
|
||||
|
||||
enum PowerSource {
|
||||
PowerSourcePermanentMainSupply,
|
||||
PowerSourceRecharchableBattery,
|
||||
PowerSourceDisposableBattery
|
||||
};
|
||||
Q_ENUM(PowerSource)
|
||||
|
||||
enum PowerLevel {
|
||||
PowerLevelCriticalLow,
|
||||
PowerLevelLow,
|
||||
PowerLevelOk,
|
||||
PowerLevelFull
|
||||
};
|
||||
Q_ENUM(PowerLevel)
|
||||
|
||||
typedef struct MacCapabilities {
|
||||
quint8 flag = 0x00; // For saving
|
||||
bool alternatePanCoordinator = false;
|
||||
DeviceType deviceType = DeviceTypeReducedFunction;
|
||||
bool powerSourceFlagMainPower = false;
|
||||
bool receiverOnWhenIdle = false;
|
||||
bool securityCapability = false;
|
||||
bool allocateAddress = false;
|
||||
} MacCapabilities;
|
||||
|
||||
typedef struct DescriptorCapabilities {
|
||||
quint8 descriptorCapabilitiesFlag = 0x00; // For saving
|
||||
bool extendedActiveEndpointListAvailable = false;
|
||||
bool extendedSimpleDescriptorListAvailable = false;
|
||||
} DescriptorCapabilities;
|
||||
|
||||
typedef struct ServerMask {
|
||||
quint16 serverMaskFlag = 0x0000; // For saving
|
||||
bool primaryTrustCenter = false;
|
||||
bool backupTrustCenter = false;
|
||||
bool primaryBindingCache = false;
|
||||
bool backupBindingCache = false;
|
||||
bool primaryDiscoveryCache = false;
|
||||
bool backupDiscoveryCache = false;
|
||||
bool networkManager = false;
|
||||
quint8 stackComplianceVersion = 0;
|
||||
} ServerMask;
|
||||
|
||||
typedef struct NodeDescriptor {
|
||||
QByteArray descriptorRawData; // For saving
|
||||
NodeType nodeType = NodeTypeEndDevice;
|
||||
bool complexDescriptorAvailable = false;
|
||||
bool userDescriptorAvailable = false;
|
||||
FrequencyBand frequencyBand = FrequencyBand2400Mhz;
|
||||
MacCapabilities macCapabilities;
|
||||
quint16 manufacturerCode = 0;
|
||||
quint8 maximumBufferSize = 0;
|
||||
quint16 maximumRxSize = 0;
|
||||
ServerMask serverMask;
|
||||
quint16 maximumTxSize = 0;
|
||||
DescriptorCapabilities descriptorCapabilities;
|
||||
} NodeDescriptor;
|
||||
|
||||
typedef struct PowerDescriptor {
|
||||
quint16 powerDescriptoFlag = 0x0000;
|
||||
PowerMode powerMode = PowerModeAlwaysOn;
|
||||
QList<PowerSource> availablePowerSources;
|
||||
PowerSource powerSource = PowerSourcePermanentMainSupply;
|
||||
PowerLevel powerLevel = PowerLevelFull;
|
||||
} PowerDescriptor;
|
||||
|
||||
static NodeDescriptor parseNodeDescriptor(const QByteArray &payload);
|
||||
static MacCapabilities parseMacCapabilities(quint8 macCapabilitiesFlag);
|
||||
static ServerMask parseServerMask(quint16 serverMaskFlag);
|
||||
static DescriptorCapabilities parseDescriptorCapabilities(quint8 descriptorCapabilitiesFlag);
|
||||
|
||||
static PowerDescriptor parsePowerDescriptor(quint16 powerDescriptorFlag);
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::Adpu &deviceAdpu);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::NodeDescriptor &nodeDescriptor);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::MacCapabilities &macCapabilities);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::ServerMask &serverMask);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::DescriptorCapabilities &descriptorCapabilities);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::PowerDescriptor &powerDescriptor);
|
||||
|
||||
#endif // ZIGBEEDEVICEPROFILE_H
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "zigbeeutils.h"
|
||||
#include "zigbeenetwork.h"
|
||||
#include "loggingcategory.h"
|
||||
#include "zdo/zigbeedeviceprofile.h"
|
||||
|
||||
#include <QSqlQuery>
|
||||
|
||||
@ -174,11 +175,6 @@ quint8 ZigbeeNetwork::generateSequenceNumber()
|
||||
return m_sequenceNumber++;
|
||||
}
|
||||
|
||||
quint8 ZigbeeNetwork::generateTranactionSequenceNumber()
|
||||
{
|
||||
return m_transactionSequenceNumber++;
|
||||
}
|
||||
|
||||
QList<ZigbeeNode *> ZigbeeNetwork::nodes() const
|
||||
{
|
||||
return m_nodes;
|
||||
@ -233,6 +229,28 @@ bool ZigbeeNetwork::hasNode(const ZigbeeAddress &address) const
|
||||
return getZigbeeNode(address) != nullptr;
|
||||
}
|
||||
|
||||
void ZigbeeNetwork::removeZigbeeNode(const ZigbeeAddress &address)
|
||||
{
|
||||
|
||||
ZigbeeNode *node = getZigbeeNode(address);
|
||||
if (!node) {
|
||||
qCWarning(dcZigbeeNetwork()) << "Failed remove zigbee node since there is no node with" << address;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Removing" << node << "from the newtork";
|
||||
ZigbeeDeviceObjectReply *zdoReply = node->deviceObject()->requestMgmtLeaveNetwork();
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, this, [this, zdoReply, node](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeNode()) << "Failed to send management leave request to" << node << zdoReply->error();
|
||||
qCWarning(dcZigbeeNode()) << "This node is gonna be removed internally and tried to remove once it shows up the next time.";
|
||||
}
|
||||
|
||||
removeNode(node);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void ZigbeeNetwork::addNodeInternally(ZigbeeNode *node)
|
||||
{
|
||||
if (m_nodes.contains(node)) {
|
||||
@ -272,7 +290,7 @@ ZigbeeNode *ZigbeeNetwork::createNode(quint16 shortAddress, const ZigbeeAddress
|
||||
ZigbeeNode *ZigbeeNetwork::createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, quint8 macCapabilities, QObject *parent)
|
||||
{
|
||||
ZigbeeNode *node = createNode(shortAddress, extendedAddress, parent);
|
||||
node->setMacCapabilitiesFlag(macCapabilities);
|
||||
node->m_macCapabilities = ZigbeeDeviceProfile::parseMacCapabilities(macCapabilities);
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -317,22 +335,9 @@ void ZigbeeNetwork::loadNetwork()
|
||||
settings.beginGroup(ieeeAddressString);
|
||||
quint16 shortAddress = static_cast<quint16>(settings.value("nwkAddress", 0).toUInt());
|
||||
ZigbeeNode *node = createNode(shortAddress, ZigbeeAddress(ieeeAddressString), this);
|
||||
|
||||
// Node descriptor
|
||||
node->m_nodeType = static_cast<ZigbeeNode::NodeType>(settings.value("nodeType", 0).toUInt());
|
||||
node->m_complexDescriptorAvailable = settings.value("complexDescriptor", false).toBool();
|
||||
node->m_userDescriptorAvailable = settings.value("userDescriptor", false).toBool();
|
||||
node->m_frequencyBand = static_cast<ZigbeeNode::FrequencyBand>(settings.value("frequencyBand", 0).toUInt());
|
||||
node->setMacCapabilitiesFlag(static_cast<quint8>(settings.value("macCapabilitiesFlag", 0).toUInt()));
|
||||
node->m_manufacturerCode = static_cast<quint16>(settings.value("manufacturerCode", 0).toUInt());
|
||||
node->m_maximumBufferSize = static_cast<quint8>(settings.value("maximumBufferSize", 0).toUInt());
|
||||
node->m_maximumRxSize = static_cast<quint16>(settings.value("maximumRxSize", 0).toUInt());
|
||||
node->m_maximumTxSize = static_cast<quint16>(settings.value("maximumTxSize", 0).toUInt());
|
||||
node->setServerMask(static_cast<quint16>(settings.value("serverMask", 0).toUInt()));
|
||||
node->setDescriptorFlag(static_cast<quint8>(settings.value("descriptorCapabilities", 0).toUInt()));
|
||||
|
||||
// Power descriptor
|
||||
node->setPowerDescriptorFlag(static_cast<quint16>(settings.value("powerDescriptorFlag", 0).toUInt()));
|
||||
node->m_nodeDescriptor = ZigbeeDeviceProfile::parseNodeDescriptor(settings.value("nodeDescriptorRaw").toByteArray());
|
||||
node->m_macCapabilities = node->nodeDescriptor().macCapabilities;
|
||||
node->m_powerDescriptor = ZigbeeDeviceProfile::parsePowerDescriptor(static_cast<quint16>(settings.value("powerDescriptorFlag", 0).toUInt()));
|
||||
|
||||
int endpointsCount = settings.beginReadArray("endpoints");
|
||||
//qCDebug(dcZigbeeNetwork()) << "loading endpoints" << endpointsCount << settings.childKeys() << settings.childGroups();
|
||||
@ -399,7 +404,7 @@ void ZigbeeNetwork::clearSettings()
|
||||
m_extendedPanId = 0;
|
||||
m_channel = 0;
|
||||
m_securityConfiguration.clear();
|
||||
m_nodeType = ZigbeeNode::NodeTypeCoordinator;
|
||||
m_nodeType = ZigbeeDeviceProfile::NodeTypeCoordinator;
|
||||
}
|
||||
|
||||
void ZigbeeNetwork::saveNode(ZigbeeNode *node)
|
||||
@ -412,20 +417,10 @@ void ZigbeeNetwork::saveNode(ZigbeeNode *node)
|
||||
settings.setValue("nwkAddress", node->shortAddress());
|
||||
|
||||
// Node descriptor
|
||||
settings.setValue("nodeType", node->m_nodeType);
|
||||
settings.setValue("complexDescriptor", node->complexDescriptorAvailable());
|
||||
settings.setValue("userDescriptor", node->userDescriptorAvailable());
|
||||
settings.setValue("frequencyBand", node->frequencyBand());
|
||||
settings.setValue("macCapabilitiesFlag", node->m_macCapabilitiesFlag);
|
||||
settings.setValue("manufacturerCode", node->m_manufacturerCode);
|
||||
settings.setValue("maximumBufferSize", node->m_maximumBufferSize);
|
||||
settings.setValue("maximumRxSize", node->m_maximumRxSize);
|
||||
settings.setValue("maximumTxSize", node->m_maximumTxSize);
|
||||
settings.setValue("serverMask", node->m_serverMask);
|
||||
settings.setValue("descriptorCapabilities", node->m_descriptorFlag);
|
||||
settings.setValue("nodeDescriptorRaw", node->nodeDescriptor().descriptorRawData);
|
||||
|
||||
// Power descriptor
|
||||
settings.setValue("powerDescriptorFlag", node->m_powerDescriptorFlag);
|
||||
settings.setValue("powerDescriptorFlag", node->powerDescriptor().powerDescriptoFlag);
|
||||
|
||||
settings.beginWriteArray("endpoints");
|
||||
for (int i = 0; i < node->endpoints().count(); i++) {
|
||||
@ -603,53 +598,25 @@ void ZigbeeNetwork::onNodeClusterAttributeChanged(ZigbeeCluster *cluster, const
|
||||
saveNode(node);
|
||||
}
|
||||
|
||||
|
||||
QDebug operator<<(QDebug debug, ZigbeeNetwork *network)
|
||||
{
|
||||
debug.nospace().noquote() << "ZigbeeNetwork (" << ZigbeeUtils::convertUint64ToHexString(network->extendedPanId())
|
||||
<< ", Channel " << network->channel()
|
||||
<< ")" << endl;
|
||||
foreach (ZigbeeNode *node, network->nodes()) {
|
||||
debug.nospace().noquote() << " - " << node << endl;
|
||||
debug.nospace().noquote() << " Node type:" << node->nodeType() << endl;
|
||||
debug.nospace().noquote() << " Manufacturer code: " << ZigbeeUtils::convertUint16ToHexString(node->manufacturerCode()) << endl;
|
||||
debug.nospace().noquote() << " Maximum Rx size: " << ZigbeeUtils::convertUint16ToHexString(node->maximumRxSize()) << endl;
|
||||
debug.nospace().noquote() << " Maximum Tx size: " << ZigbeeUtils::convertUint16ToHexString(node->maximumTxSize()) << endl;
|
||||
debug.nospace().noquote() << " Maximum buffer size: " << ZigbeeUtils::convertByteToHexString(node->maximumBufferSize()) << endl;
|
||||
debug.nospace().noquote() << " Primary Trust center: " << node->isPrimaryTrustCenter() << endl;
|
||||
debug.nospace().noquote() << " Backup Trust center: " << node->isBackupTrustCenter() << endl;
|
||||
debug.nospace().noquote() << " Primary Binding cache: " << node->isPrimaryBindingCache() << endl;
|
||||
debug.nospace().noquote() << " Backup Binding cache: " << node->isBackupBindingCache() << endl;
|
||||
debug.nospace().noquote() << " Primary Discovery cache: " << node->isPrimaryDiscoveryCache() << endl;
|
||||
debug.nospace().noquote() << " Backup Discovery cache: " << node->isBackupDiscoveryCache() << endl;
|
||||
debug.nospace().noquote() << " Network Manager: " << node->isNetworkManager() << endl;
|
||||
debug.nospace().noquote() << " Extended active endpoint list available: " << node->extendedActiveEndpointListAvailable() << endl;
|
||||
debug.nospace().noquote() << " Extended simple descriptor list available: " << node->extendedSimpleDescriptorListAvailable() << endl;
|
||||
debug.nospace().noquote() << " Alternate PAN coordinator: " << node->alternatePanCoordinator() << endl;
|
||||
debug.nospace().noquote() << " Device type: " << node->deviceType() << endl;
|
||||
debug.nospace().noquote() << " Power source flag main power: " << node->powerSourceFlagMainPower() << endl;
|
||||
debug.nospace().noquote() << " Receiver on when idle: " << node->receiverOnWhenIdle() << endl;
|
||||
debug.nospace().noquote() << " Security capability: " << node->securityCapability() << endl;
|
||||
debug.nospace().noquote() << " Allocate address: " << node->allocateAddress() << endl;
|
||||
debug.nospace().noquote() << " Complex desciptor available: " << node->complexDescriptorAvailable() << endl;
|
||||
debug.nospace().noquote() << " User desciptor available: " << node->userDescriptorAvailable() << endl;
|
||||
debug.nospace().noquote() << " Power mode: " << node->powerMode() << endl;
|
||||
debug.nospace().noquote() << " Available power sources:" << endl;
|
||||
foreach (const ZigbeeNode::PowerSource &source, node->availablePowerSources()) {
|
||||
debug.nospace().noquote() << " - " << source << endl;
|
||||
}
|
||||
debug.nospace().noquote() << " Power source: " << node->powerSource() << endl;
|
||||
debug.nospace().noquote() << " Power level: " << node->powerLevel() << endl;
|
||||
debug.nospace().noquote() << " Endpoints: " << node->endpoints().count() << endl;
|
||||
debug.nospace().noquote() << " ---> " << node << endl;
|
||||
debug.nospace().noquote() << " " << node->nodeDescriptor();
|
||||
debug.nospace().noquote() << " " << node->powerDescriptor();
|
||||
debug.nospace().noquote() << " Endpoints: " << node->endpoints().count() << endl;
|
||||
foreach (ZigbeeNodeEndpoint *endpoint, node->endpoints()) {
|
||||
debug.nospace().noquote() << " - " << endpoint << endl;
|
||||
debug.nospace().noquote() << " Input clusters:" << endl;
|
||||
debug.nospace().noquote() << " - " << endpoint << endl;
|
||||
debug.nospace().noquote() << " Input clusters:" << endl;
|
||||
foreach (ZigbeeCluster *cluster, endpoint->inputClusters()) {
|
||||
debug.nospace().noquote() << " - " << cluster << endl;
|
||||
debug.nospace().noquote() << " - " << cluster << endl;
|
||||
}
|
||||
debug.nospace().noquote() << " Output clusters:" << endl;
|
||||
debug.nospace().noquote() << " Output clusters:" << endl;
|
||||
foreach (ZigbeeCluster *cluster, endpoint->outputClusters()) {
|
||||
debug.nospace().noquote() << " - " << cluster << endl;
|
||||
debug.nospace().noquote() << " - " << cluster << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +98,6 @@ public:
|
||||
void setPermitJoining(bool permitJoining);
|
||||
|
||||
quint8 generateSequenceNumber();
|
||||
quint8 generateTranactionSequenceNumber();
|
||||
|
||||
// Network nodes
|
||||
QList<ZigbeeNode *> nodes() const;
|
||||
@ -113,6 +112,8 @@ public:
|
||||
|
||||
virtual ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) = 0;
|
||||
|
||||
void removeZigbeeNode(const ZigbeeAddress &address);
|
||||
|
||||
private:
|
||||
State m_state = StateUninitialized;
|
||||
|
||||
@ -120,15 +121,15 @@ private:
|
||||
QString m_serialPortName = "/dev/ttyUSB0";
|
||||
qint32 m_serialBaudrate = 115200;
|
||||
|
||||
// Continuouse ASP sequence number for network requests
|
||||
quint8 m_sequenceNumber = 0;
|
||||
quint8 m_transactionSequenceNumber = 0;
|
||||
|
||||
// Network configurations
|
||||
quint16 m_panId = 0;
|
||||
quint64 m_extendedPanId = 0;
|
||||
quint32 m_channel = 0;
|
||||
ZigbeeChannelMask m_channelMask = ZigbeeChannelMask(ZigbeeChannelMask::ChannelConfigurationAllChannels);
|
||||
ZigbeeNode::NodeType m_nodeType = ZigbeeNode::NodeTypeCoordinator;
|
||||
ZigbeeDeviceProfile::NodeType m_nodeType = ZigbeeDeviceProfile::NodeTypeCoordinator;
|
||||
|
||||
// Network storage
|
||||
QString m_settingsFileName = "/etc/nymea/nymea-zigbee.conf";
|
||||
|
||||
@ -87,144 +87,19 @@ ZigbeeNodeEndpoint *ZigbeeNode::getEndpoint(quint8 endpointId) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZigbeeNode::NodeType ZigbeeNode::nodeType() const
|
||||
ZigbeeDeviceProfile::NodeDescriptor ZigbeeNode::nodeDescriptor() const
|
||||
{
|
||||
return m_nodeType;
|
||||
return m_nodeDescriptor;
|
||||
}
|
||||
|
||||
ZigbeeNode::FrequencyBand ZigbeeNode::frequencyBand() const
|
||||
ZigbeeDeviceProfile::MacCapabilities ZigbeeNode::macCapabilities() const
|
||||
{
|
||||
return m_frequencyBand;
|
||||
return m_macCapabilities;
|
||||
}
|
||||
|
||||
ZigbeeNode::Relationship ZigbeeNode::relationship() const
|
||||
ZigbeeDeviceProfile::PowerDescriptor ZigbeeNode::powerDescriptor() const
|
||||
{
|
||||
return m_relationship;
|
||||
}
|
||||
|
||||
quint16 ZigbeeNode::manufacturerCode() const
|
||||
{
|
||||
return m_manufacturerCode;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::complexDescriptorAvailable() const
|
||||
{
|
||||
return m_complexDescriptorAvailable;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::userDescriptorAvailable() const
|
||||
{
|
||||
return m_userDescriptorAvailable;
|
||||
}
|
||||
|
||||
quint16 ZigbeeNode::maximumRxSize() const
|
||||
{
|
||||
return m_maximumRxSize;
|
||||
}
|
||||
|
||||
quint16 ZigbeeNode::maximumTxSize() const
|
||||
{
|
||||
return m_maximumTxSize;
|
||||
}
|
||||
|
||||
quint8 ZigbeeNode::maximumBufferSize() const
|
||||
{
|
||||
return m_maximumBufferSize;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::isPrimaryTrustCenter() const
|
||||
{
|
||||
return m_isPrimaryTrustCenter;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::isBackupTrustCenter() const
|
||||
{
|
||||
return m_isBackupTrustCenter;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::isPrimaryBindingCache() const
|
||||
{
|
||||
return m_isPrimaryBindingCache;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::isBackupBindingCache() const
|
||||
{
|
||||
return m_isBackupBindingCache;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::isPrimaryDiscoveryCache() const
|
||||
{
|
||||
return m_isPrimaryDiscoveryCache;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::isBackupDiscoveryCache() const
|
||||
{
|
||||
return m_isBackupDiscoveryCache;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::isNetworkManager() const
|
||||
{
|
||||
return m_isNetworkManager;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::extendedActiveEndpointListAvailable() const
|
||||
{
|
||||
return m_extendedActiveEndpointListAvailable;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::extendedSimpleDescriptorListAvailable() const
|
||||
{
|
||||
return m_extendedSimpleDescriptorListAvailable;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::alternatePanCoordinator() const
|
||||
{
|
||||
return m_alternatePanCoordinator;
|
||||
}
|
||||
|
||||
ZigbeeNode::DeviceType ZigbeeNode::deviceType() const
|
||||
{
|
||||
return m_deviceType;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::powerSourceFlagMainPower() const
|
||||
{
|
||||
return m_powerSourceFlagMainPower;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::receiverOnWhenIdle() const
|
||||
{
|
||||
return m_receiverOnWhenIdle;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::securityCapability() const
|
||||
{
|
||||
return m_securityCapability;
|
||||
}
|
||||
|
||||
bool ZigbeeNode::allocateAddress() const
|
||||
{
|
||||
return m_allocateAddress;
|
||||
}
|
||||
|
||||
ZigbeeNode::PowerMode ZigbeeNode::powerMode() const
|
||||
{
|
||||
return m_powerMode;
|
||||
}
|
||||
|
||||
ZigbeeNode::PowerSource ZigbeeNode::powerSource() const
|
||||
{
|
||||
return m_powerSource;
|
||||
}
|
||||
|
||||
QList<ZigbeeNode::PowerSource> ZigbeeNode::availablePowerSources() const
|
||||
{
|
||||
return m_availablePowerSources;
|
||||
}
|
||||
|
||||
ZigbeeNode::PowerLevel ZigbeeNode::powerLevel() const
|
||||
{
|
||||
return m_powerLevel;
|
||||
return m_powerDescriptor;
|
||||
}
|
||||
|
||||
void ZigbeeNode::setState(ZigbeeNode::State state)
|
||||
@ -247,136 +122,6 @@ void ZigbeeNode::setConnected(bool connected)
|
||||
emit connectedChanged(m_connected);
|
||||
}
|
||||
|
||||
void ZigbeeNode::setShortAddress(const quint16 &shortAddress)
|
||||
{
|
||||
m_shortAddress = shortAddress;
|
||||
}
|
||||
|
||||
void ZigbeeNode::setExtendedAddress(const ZigbeeAddress &extendedAddress)
|
||||
{
|
||||
m_extendedAddress = extendedAddress;
|
||||
}
|
||||
|
||||
quint16 ZigbeeNode::serverMask() const
|
||||
{
|
||||
return m_serverMask;
|
||||
}
|
||||
|
||||
void ZigbeeNode::setServerMask(quint16 serverMask)
|
||||
{
|
||||
m_serverMask = serverMask;
|
||||
m_isPrimaryTrustCenter = ((m_serverMask >> 0) & 0x0001);
|
||||
m_isBackupTrustCenter = ((m_serverMask >> 1) & 0x0001);
|
||||
m_isPrimaryBindingCache = ((m_serverMask >> 2) & 0x0001);
|
||||
m_isBackupBindingCache = ((m_serverMask >> 3) & 0x0001);
|
||||
m_isPrimaryDiscoveryCache = ((m_serverMask >> 4) & 0x0001);
|
||||
m_isBackupDiscoveryCache = ((m_serverMask >> 5) & 0x0001);
|
||||
m_isNetworkManager = ((m_serverMask >> 6) & 0x0001);
|
||||
}
|
||||
|
||||
quint8 ZigbeeNode::macCapabilitiesFlag() const
|
||||
{
|
||||
return m_macCapabilitiesFlag;
|
||||
}
|
||||
|
||||
void ZigbeeNode::setMacCapabilitiesFlag(quint8 macFlag)
|
||||
{
|
||||
m_macCapabilitiesFlag = macFlag;
|
||||
m_alternatePanCoordinator = ((m_macCapabilitiesFlag >> 0) & 0x01);
|
||||
if (((m_macCapabilitiesFlag >> 1) & 0x01)) {
|
||||
m_deviceType = DeviceTypeFullFunction;
|
||||
} else {
|
||||
m_deviceType = DeviceTypeReducedFunction;
|
||||
}
|
||||
m_powerSourceFlagMainPower = ((m_macCapabilitiesFlag >> 2) & 0x01);
|
||||
m_receiverOnWhenIdle = ((m_macCapabilitiesFlag >> 3) & 0x01);
|
||||
m_securityCapability = ((m_macCapabilitiesFlag >> 6) & 0x01);
|
||||
m_allocateAddress = ((m_macCapabilitiesFlag >> 7) & 0x01);
|
||||
}
|
||||
|
||||
void ZigbeeNode::setDescriptorFlag(quint8 descriptorFlag)
|
||||
{
|
||||
m_descriptorFlag = descriptorFlag;
|
||||
m_extendedActiveEndpointListAvailable = ((m_descriptorFlag >> 0) & 0x01);
|
||||
m_extendedSimpleDescriptorListAvailable = ((m_descriptorFlag >> 1) & 0x01);
|
||||
}
|
||||
|
||||
quint16 ZigbeeNode::powerDescriptorFlag() const
|
||||
{
|
||||
return m_powerDescriptorFlag;
|
||||
}
|
||||
|
||||
void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag)
|
||||
{
|
||||
m_powerDescriptorFlag = powerDescriptorFlag;
|
||||
|
||||
qCDebug(dcZigbeeNode()) << "Parse power descriptor flag" << ZigbeeUtils::convertUint16ToHexString(m_powerDescriptorFlag);
|
||||
|
||||
// Bit 0 - 3 Power mode
|
||||
// 0000: Receiver configured according to “Receiver on when idle” MAC flag in the Node Descriptor
|
||||
// 0001: Receiver switched on periodically
|
||||
// 0010: Receiver switched on when stimulated, e.g. by pressing a button
|
||||
|
||||
m_powerMode = PowerModeAlwaysOn;
|
||||
if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 1)) {
|
||||
m_powerMode = PowerModeAlwaysOn;
|
||||
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 1)) {
|
||||
m_powerMode = PowerModeOnPeriodically;
|
||||
} else if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 0) && ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 1)) {
|
||||
m_powerMode = PowerModeOnWhenStimulated;
|
||||
}
|
||||
|
||||
// Bit 4 - 7 Available power sources
|
||||
// Bit 0: Permanent mains supply
|
||||
// Bit 1: Rechargeable battery
|
||||
// Bit 2: Disposable battery
|
||||
// Bit 4: Reserved
|
||||
|
||||
m_availablePowerSources.clear();
|
||||
if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 4)) {
|
||||
m_availablePowerSources.append(PowerSourcePermanentMainSupply);
|
||||
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 5)) {
|
||||
m_availablePowerSources.append(PowerSourceRecharchableBattery);
|
||||
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 6)) {
|
||||
m_availablePowerSources.append(PowerSourceDisposableBattery);
|
||||
}
|
||||
|
||||
// Bit 8 - 11 Active source: according to the same schema as available power sources
|
||||
m_powerSource = PowerSourcePermanentMainSupply;
|
||||
if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 8)) {
|
||||
m_powerSource = PowerSourcePermanentMainSupply;
|
||||
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 9)) {
|
||||
m_powerSource = PowerSourceRecharchableBattery;
|
||||
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 10)) {
|
||||
m_powerSource = PowerSourceDisposableBattery;
|
||||
}
|
||||
|
||||
// Bit 12 - 15: Battery level if available
|
||||
// 0000: Critically low
|
||||
// 0100: Approximately 33%
|
||||
// 1000: Approximately 66%
|
||||
// 1100: Approximately 100% (near fully charged)
|
||||
m_powerLevel = PowerLevelCriticalLow;
|
||||
if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) {
|
||||
m_powerLevel = PowerLevelCriticalLow;
|
||||
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && !ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) {
|
||||
m_powerLevel = PowerLevelLow;
|
||||
} else if (!ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) {
|
||||
m_powerLevel = PowerLevelOk;
|
||||
} else if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 14) && ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 15)) {
|
||||
m_powerLevel = PowerLevelFull;
|
||||
}
|
||||
|
||||
// qCDebug(dcZigbeeNode()) << "Node power descriptor (" << ZigbeeUtils::convertUint16ToHexString(m_powerDescriptorFlag) << "):";
|
||||
// qCDebug(dcZigbeeNode()) << " Power mode:" << m_powerMode;
|
||||
// qCDebug(dcZigbeeNode()) << " Available power sources:";
|
||||
// foreach (const PowerSource &source, m_availablePowerSources) {
|
||||
// qCDebug(dcZigbeeNode()) << " " << source;
|
||||
// }
|
||||
// qCDebug(dcZigbeeNode()) << " Power source:" << m_powerSource;
|
||||
// qCDebug(dcZigbeeNode()) << " Power level:" << m_powerLevel;
|
||||
}
|
||||
|
||||
void ZigbeeNode::startInitialization()
|
||||
{
|
||||
setState(StateInitializing);
|
||||
@ -421,72 +166,10 @@ void ZigbeeNode::initNodeDescriptor()
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNode()) << this << "reading node descriptor finished successfully.";
|
||||
m_nodeDescriptor = ZigbeeDeviceProfile::parseNodeDescriptor(reply->responseAdpu().payload);
|
||||
qCDebug(dcZigbeeNode()) << m_nodeDescriptor;
|
||||
m_requestRetry = 0;
|
||||
|
||||
// Parse and set the node descriptor FIXME: make it nicer using the data types
|
||||
QDataStream stream(reply->responseAdpu().payload);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 typeDescriptorFlag = 0; quint8 frequencyFlag = 0; quint8 macCapabilities = 0;
|
||||
quint16 serverMask = 0;
|
||||
quint8 descriptorCapabilities = 0;
|
||||
|
||||
stream >> typeDescriptorFlag >> frequencyFlag >> macCapabilities >> m_manufacturerCode >> m_maximumBufferSize;
|
||||
stream >> m_maximumRxSize >> serverMask >> m_maximumTxSize >> descriptorCapabilities;
|
||||
|
||||
// 0-2 Bit = logical type, 0 = coordinator, 1 = router, 2 = end device
|
||||
if (!ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 1)) {
|
||||
m_nodeType = NodeTypeCoordinator;
|
||||
} else if (!ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 0) && ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 1)) {
|
||||
m_nodeType = NodeTypeRouter;
|
||||
} else if (ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 0) && !ZigbeeUtils::checkBitUint8(typeDescriptorFlag, 1)) {
|
||||
m_nodeType = NodeTypeEndDevice;
|
||||
}
|
||||
|
||||
m_complexDescriptorAvailable = (typeDescriptorFlag >> 3) & 0x0001;
|
||||
m_userDescriptorAvailable = (typeDescriptorFlag >> 4) & 0x0001;
|
||||
|
||||
// Frequency band, 5 bits
|
||||
if (ZigbeeUtils::checkBitUint8(frequencyFlag, 3)) {
|
||||
m_frequencyBand = FrequencyBand868Mhz;
|
||||
} else if (ZigbeeUtils::checkBitUint8(frequencyFlag, 5)) {
|
||||
m_frequencyBand = FrequencyBand902Mhz;
|
||||
} else if (ZigbeeUtils::checkBitUint8(frequencyFlag, 6)) {
|
||||
m_frequencyBand = FrequencyBand2400Mhz;
|
||||
}
|
||||
|
||||
setMacCapabilitiesFlag(macCapabilities);
|
||||
setServerMask(serverMask);
|
||||
setDescriptorFlag(descriptorCapabilities);
|
||||
|
||||
qCDebug(dcZigbeeNode()) << "Node descriptor:" << ZigbeeUtils::convertUint16ToHexString(shortAddress()) << extendedAddress().toString();
|
||||
qCDebug(dcZigbeeNode()) << " Node type:" << nodeType();
|
||||
qCDebug(dcZigbeeNode()) << " Complex desciptor available:" << complexDescriptorAvailable();
|
||||
qCDebug(dcZigbeeNode()) << " User desciptor available:" << userDescriptorAvailable();
|
||||
qCDebug(dcZigbeeNode()) << " Frequency band:" << frequencyBand();
|
||||
qCDebug(dcZigbeeNode()) << " Manufacturer code:" << ZigbeeUtils::convertUint16ToHexString(m_manufacturerCode);
|
||||
qCDebug(dcZigbeeNode()) << " Maximum Rx size:" << ZigbeeUtils::convertUint16ToHexString(m_maximumRxSize) << "(" << m_maximumRxSize << ")";
|
||||
qCDebug(dcZigbeeNode()) << " Maximum Tx size:" << ZigbeeUtils::convertUint16ToHexString(m_maximumTxSize) << "(" << m_maximumTxSize << ")";
|
||||
qCDebug(dcZigbeeNode()) << " Maximum buffer size:" << ZigbeeUtils::convertByteToHexString(m_maximumBufferSize) << "(" << m_maximumBufferSize << ")";
|
||||
qCDebug(dcZigbeeNode()) << " Server mask:" << ZigbeeUtils::convertUint16ToHexString(serverMask);
|
||||
qCDebug(dcZigbeeNode()) << " Primary Trust center:" << isPrimaryTrustCenter();
|
||||
qCDebug(dcZigbeeNode()) << " Backup Trust center:" << isBackupTrustCenter();
|
||||
qCDebug(dcZigbeeNode()) << " Primary Binding cache:" << isPrimaryBindingCache();
|
||||
qCDebug(dcZigbeeNode()) << " Backup Binding cache:" << isBackupBindingCache();
|
||||
qCDebug(dcZigbeeNode()) << " Primary Discovery cache:" << isPrimaryDiscoveryCache();
|
||||
qCDebug(dcZigbeeNode()) << " Backup Discovery cache:" << isBackupDiscoveryCache();
|
||||
qCDebug(dcZigbeeNode()) << " Network Manager:" << isNetworkManager();
|
||||
qCDebug(dcZigbeeNode()) << " Descriptor flag:" << ZigbeeUtils::convertByteToHexString(descriptorCapabilities);
|
||||
qCDebug(dcZigbeeNode()) << " Extended active endpoint list available:" << extendedActiveEndpointListAvailable();
|
||||
qCDebug(dcZigbeeNode()) << " Extended simple descriptor list available:" << extendedSimpleDescriptorListAvailable();
|
||||
qCDebug(dcZigbeeNode()) << " MAC flags:" << ZigbeeUtils::convertByteToHexString(macCapabilities);
|
||||
qCDebug(dcZigbeeNode()) << " Alternate PAN coordinator:" << alternatePanCoordinator();
|
||||
qCDebug(dcZigbeeNode()) << " Device type:" << deviceType();
|
||||
qCDebug(dcZigbeeNode()) << " Power source flag main power:" << powerSourceFlagMainPower();
|
||||
qCDebug(dcZigbeeNode()) << " Receiver on when idle:" << receiverOnWhenIdle();
|
||||
qCDebug(dcZigbeeNode()) << " Security capability:" << securityCapability();
|
||||
qCDebug(dcZigbeeNode()) << " Allocate address:" << allocateAddress();
|
||||
|
||||
|
||||
// Continue with the power descriptor
|
||||
initPowerDescriptor();
|
||||
});
|
||||
@ -524,7 +207,8 @@ void ZigbeeNode::initPowerDescriptor()
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint16 powerDescriptorFlag = 0;
|
||||
stream >> powerDescriptorFlag;
|
||||
setPowerDescriptorFlag(powerDescriptorFlag);
|
||||
m_powerDescriptor = ZigbeeDeviceProfile::parsePowerDescriptor(powerDescriptorFlag);
|
||||
qCDebug(dcZigbeeNode()) << m_powerDescriptor;
|
||||
|
||||
// Continue with endpoint fetching
|
||||
initEndpoints();
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "zigbeeaddress.h"
|
||||
#include "zigbeenodeendpoint.h"
|
||||
#include "zdo/zigbeedeviceobject.h"
|
||||
#include "zdo/zigbeedeviceprofile.h"
|
||||
|
||||
class ZigbeeNetwork;
|
||||
|
||||
@ -51,94 +52,6 @@ public:
|
||||
};
|
||||
Q_ENUM(State)
|
||||
|
||||
enum NodeType {
|
||||
NodeTypeCoordinator = 0,
|
||||
NodeTypeRouter = 1,
|
||||
NodeTypeEndDevice = 2
|
||||
};
|
||||
Q_ENUM(NodeType)
|
||||
|
||||
enum FrequencyBand {
|
||||
FrequencyBand868Mhz,
|
||||
FrequencyBand902Mhz,
|
||||
FrequencyBand2400Mhz
|
||||
};
|
||||
Q_ENUM(FrequencyBand)
|
||||
|
||||
enum DeviceType {
|
||||
DeviceTypeFullFunction,
|
||||
DeviceTypeReducedFunction
|
||||
};
|
||||
Q_ENUM(DeviceType)
|
||||
|
||||
enum Relationship {
|
||||
Parent,
|
||||
Child,
|
||||
Sibling
|
||||
};
|
||||
Q_ENUM(Relationship)
|
||||
|
||||
enum PowerMode {
|
||||
PowerModeAlwaysOn,
|
||||
PowerModeOnPeriodically,
|
||||
PowerModeOnWhenStimulated
|
||||
};
|
||||
Q_ENUM(PowerMode)
|
||||
|
||||
enum PowerSource {
|
||||
PowerSourcePermanentMainSupply,
|
||||
PowerSourceRecharchableBattery,
|
||||
PowerSourceDisposableBattery
|
||||
};
|
||||
Q_ENUM(PowerSource)
|
||||
|
||||
enum PowerLevel {
|
||||
PowerLevelCriticalLow,
|
||||
PowerLevelLow,
|
||||
PowerLevelOk,
|
||||
PowerLevelFull
|
||||
};
|
||||
Q_ENUM(PowerLevel)
|
||||
|
||||
typedef struct MacCapabilities {
|
||||
bool alternatePanCoordinator = false;
|
||||
DeviceType deviceType = DeviceTypeReducedFunction;
|
||||
bool powerSourceFlagMainPower = false;
|
||||
bool receiverOnWhenIdle = false;
|
||||
bool securityCapability = false;
|
||||
bool allocateAddress = false;
|
||||
} MacCapabilities;
|
||||
|
||||
typedef struct DescriptorCapabilities {
|
||||
bool extendedActiveEndpointListAvailable = false;
|
||||
bool extendedSimpleDescriptorListAvailable = false;
|
||||
} DescriptorCapabilities;
|
||||
|
||||
typedef struct ServerMask {
|
||||
bool primaryTrustCenter = false;
|
||||
bool backupTrustCenter = false;
|
||||
bool primaryBindingCache = false;
|
||||
bool backupBindingCache = false;
|
||||
bool primaryDiscoveryCache = false;
|
||||
bool backupDiscoveryCache = false;
|
||||
bool networkManager = false;
|
||||
quint8 stackComplianceVersion = 0;
|
||||
} ServerMask;
|
||||
|
||||
typedef struct NodeDescriptor {
|
||||
NodeType nodeType = NodeTypeEndDevice;
|
||||
bool complexDescriptorAvailable = false;
|
||||
bool userDescriptorAvailable = false;
|
||||
FrequencyBand frequencyBand = FrequencyBand2400Mhz;
|
||||
MacCapabilities macCapabilities;
|
||||
quint16 manufacturerCode = 0;
|
||||
quint8 maximumBufferSize = 0;
|
||||
quint16 maximumRxSize = 0;
|
||||
ServerMask serverMask;
|
||||
quint16 maximumTxSize = 0;
|
||||
DescriptorCapabilities descriptorCapabilities;
|
||||
} NodeDescriptor;
|
||||
|
||||
State state() const;
|
||||
bool connected() const;
|
||||
|
||||
@ -151,45 +64,16 @@ public:
|
||||
bool hasEndpoint(quint8 endpointId) const;
|
||||
ZigbeeNodeEndpoint *getEndpoint(quint8 endpointId) const;
|
||||
|
||||
// Information from node descriptor
|
||||
NodeType nodeType() const;
|
||||
FrequencyBand frequencyBand() const;
|
||||
Relationship relationship() const;
|
||||
quint16 manufacturerCode() const;
|
||||
|
||||
bool complexDescriptorAvailable() const;
|
||||
bool userDescriptorAvailable() const;
|
||||
|
||||
quint16 maximumRxSize() const;
|
||||
quint16 maximumTxSize() const;
|
||||
quint8 maximumBufferSize() const;
|
||||
|
||||
// Server Mask
|
||||
bool isPrimaryTrustCenter() const;
|
||||
bool isBackupTrustCenter() const;
|
||||
bool isPrimaryBindingCache() const;
|
||||
bool isBackupBindingCache() const;
|
||||
bool isPrimaryDiscoveryCache() const;
|
||||
bool isBackupDiscoveryCache() const;
|
||||
bool isNetworkManager() const;
|
||||
|
||||
// Descriptor capability
|
||||
bool extendedActiveEndpointListAvailable() const;
|
||||
bool extendedSimpleDescriptorListAvailable() const;
|
||||
|
||||
// Mac capabilities flag
|
||||
bool alternatePanCoordinator() const;
|
||||
DeviceType deviceType() const;
|
||||
bool powerSourceFlagMainPower() const;
|
||||
bool receiverOnWhenIdle() const;
|
||||
bool securityCapability() const;
|
||||
bool allocateAddress() const;
|
||||
// Information from descriptors
|
||||
ZigbeeDeviceProfile::NodeDescriptor nodeDescriptor() const;
|
||||
ZigbeeDeviceProfile::MacCapabilities macCapabilities() const;
|
||||
ZigbeeDeviceProfile::PowerDescriptor powerDescriptor() const;
|
||||
|
||||
// Information from node power descriptor
|
||||
PowerMode powerMode() const;
|
||||
PowerSource powerSource() const;
|
||||
QList<PowerSource> availablePowerSources() const;
|
||||
PowerLevel powerLevel() const;
|
||||
ZigbeeDeviceProfile::PowerMode powerMode() const;
|
||||
ZigbeeDeviceProfile::PowerSource powerSource() const;
|
||||
QList<ZigbeeDeviceProfile::PowerSource> availablePowerSources() const;
|
||||
ZigbeeDeviceProfile::PowerLevel powerLevel() const;
|
||||
|
||||
// This method starts the node initialization phase (read descriptors and endpoints)
|
||||
void startInitialization();
|
||||
@ -198,86 +82,26 @@ private:
|
||||
ZigbeeNode(ZigbeeNetwork *network, quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent = nullptr);
|
||||
|
||||
ZigbeeNetwork *m_network;
|
||||
quint16 m_shortAddress = 0;
|
||||
ZigbeeAddress m_extendedAddress;
|
||||
|
||||
ZigbeeDeviceObject *m_deviceObject = nullptr;
|
||||
QList<ZigbeeNodeEndpoint *> m_endpoints;
|
||||
bool m_connected = false;
|
||||
State m_state = StateUninitialized;
|
||||
quint8 m_lqi = 0;
|
||||
|
||||
// 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;
|
||||
// Node information
|
||||
ZigbeeDeviceProfile::NodeDescriptor m_nodeDescriptor;
|
||||
ZigbeeDeviceProfile::MacCapabilities m_macCapabilities;
|
||||
ZigbeeDeviceProfile::PowerDescriptor m_powerDescriptor;
|
||||
|
||||
void setState(State state);
|
||||
void setConnected(bool connected);
|
||||
|
||||
void setShortAddress(const quint16 &shortAddress);
|
||||
void setExtendedAddress(const ZigbeeAddress &extendedAddress);
|
||||
|
||||
quint16 serverMask() const;
|
||||
void setServerMask(quint16 serverMask);
|
||||
|
||||
// MAC capability raw data flag for settings
|
||||
quint8 macCapabilitiesFlag() const;
|
||||
void setMacCapabilitiesFlag(quint8 macFlag);
|
||||
|
||||
quint8 descriptorFlag() const;
|
||||
void setDescriptorFlag(quint8 descriptorFlag);
|
||||
|
||||
// Power decriptor data
|
||||
quint16 powerDescriptorFlag() const;
|
||||
void setPowerDescriptorFlag(quint16 powerDescriptorFlag);
|
||||
|
||||
bool m_connected = false;
|
||||
State m_state = StateUninitialized;
|
||||
|
||||
quint16 m_shortAddress = 0;
|
||||
ZigbeeAddress m_extendedAddress;
|
||||
|
||||
// Server Mask
|
||||
quint16 m_serverMask = 0;
|
||||
bool m_isPrimaryTrustCenter = false;
|
||||
bool m_isBackupTrustCenter = false;
|
||||
bool m_isPrimaryBindingCache = false;
|
||||
bool m_isBackupBindingCache = false;
|
||||
bool m_isPrimaryDiscoveryCache = false;
|
||||
bool m_isBackupDiscoveryCache = false;
|
||||
bool m_isNetworkManager = false;
|
||||
|
||||
// Power information
|
||||
quint16 m_powerDescriptorFlag = 0;
|
||||
PowerMode m_powerMode;
|
||||
PowerSource m_powerSource;
|
||||
QList<PowerSource> m_availablePowerSources;
|
||||
PowerLevel m_powerLevel;
|
||||
|
||||
// Mac capabilities flag
|
||||
quint8 m_macCapabilitiesFlag = 0;
|
||||
bool m_alternatePanCoordinator = false;
|
||||
DeviceType m_deviceType = DeviceTypeFullFunction;
|
||||
bool m_powerSourceFlagMainPower = false;
|
||||
bool m_receiverOnWhenIdle = false;
|
||||
bool m_securityCapability = false;
|
||||
bool m_allocateAddress = false;
|
||||
|
||||
// Descriptor capability
|
||||
quint8 m_descriptorFlag = 0;
|
||||
bool m_extendedActiveEndpointListAvailable = false;
|
||||
bool m_extendedSimpleDescriptorListAvailable = false;
|
||||
|
||||
//virtual void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) = 0;
|
||||
|
||||
// Init methods
|
||||
int m_requestRetry = 0;
|
||||
QList<quint8> m_uninitializedEndpoints;
|
||||
|
||||
void initNodeDescriptor();
|
||||
void initPowerDescriptor();
|
||||
void initEndpoints();
|
||||
@ -291,6 +115,7 @@ private:
|
||||
|
||||
signals:
|
||||
void stateChanged(State state);
|
||||
void lqiChanged(quint8 lqi);
|
||||
void connectedChanged(bool connected);
|
||||
void clusterAdded(ZigbeeCluster *cluster);
|
||||
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);
|
||||
|
||||
@ -176,7 +176,11 @@ ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(Zigbee::ClusterId clusterId, Zi
|
||||
case Zigbee::ClusterIdIdentify:
|
||||
return new ZigbeeClusterIdentify(m_network, m_node, this, direction, this);
|
||||
break;
|
||||
// Measurement
|
||||
case Zigbee::ClusterIdLevelControl:
|
||||
return new ZigbeeClusterLevelControl(m_network, m_node, this, direction, this);
|
||||
break;
|
||||
|
||||
// Measurement
|
||||
case Zigbee::ClusterIdTemperatureMeasurement:
|
||||
return new ZigbeeClusterTemperatureMeasurement(m_network, m_node, this, direction, this);
|
||||
break;
|
||||
@ -189,7 +193,8 @@ ZigbeeCluster *ZigbeeNodeEndpoint::createCluster(Zigbee::ClusterId clusterId, Zi
|
||||
case Zigbee::ClusterIdIlluminanceMeasurement:
|
||||
return new ZigbeeClusterIlluminanceMeasurment(m_network, m_node, this, direction, this);
|
||||
break;
|
||||
// Security
|
||||
|
||||
// Security
|
||||
case Zigbee::ClusterIdIasZone:
|
||||
return new ZigbeeClusterIasZone(m_network, m_node, this, direction, this);
|
||||
break;
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "zcl/general/zigbeeclusterbasic.h"
|
||||
#include "zcl/general/zigbeeclusteronoff.h"
|
||||
#include "zcl/general/zigbeeclusteridentify.h"
|
||||
#include "zcl/general/zigbeeclusterlevelcontrol.h"
|
||||
|
||||
#include "zcl/measurement/zigbeeclusteroccupancysensing.h"
|
||||
#include "zcl/measurement/zigbeeclusterilluminancemeasurment.h"
|
||||
|
||||
Reference in New Issue
Block a user