Make basic node adding mechanism work
This commit is contained in:
parent
7cdf772b1a
commit
029ca76bae
Binary file not shown.
@ -296,7 +296,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
||||
for (int i = 0; i < asdu.length(); i++) {
|
||||
stream << static_cast<quint8>(asdu.at(i));
|
||||
}
|
||||
stream << static_cast<quint8>(txOptions); // TX Options: Use ASP ACKs
|
||||
stream << static_cast<quint8>(txOptions); // TX Options: Use APS ACKs
|
||||
stream << radius;
|
||||
|
||||
m_interface->sendPackage(message);
|
||||
@ -337,7 +337,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
||||
for (int i = 0; i < asdu.length(); i++) {
|
||||
stream << static_cast<quint8>(asdu.at(i));
|
||||
}
|
||||
stream << static_cast<quint8>(txOptions); // TX Options: Use ASP ACKs
|
||||
stream << static_cast<quint8>(txOptions); // TX Options: Use APS ACKs
|
||||
stream << radius;
|
||||
|
||||
m_interface->sendPackage(message);
|
||||
@ -347,6 +347,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
|
||||
|
||||
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestSendRequest(const ZigbeeNetworkRequest &request)
|
||||
{
|
||||
qCDebug(dcZigbeeAps()) << "APSDE-DATA.request" << request;
|
||||
ZigbeeInterfaceDeconzReply *interfaceReply = nullptr;
|
||||
switch (request.destinationAddressMode()) {
|
||||
case Zigbee::DestinationAddressModeGroup:
|
||||
@ -733,10 +734,10 @@ DeconzDeviceState ZigbeeBridgeControllerDeconz::parseDeviceStateFlag(quint8 devi
|
||||
{
|
||||
DeconzDeviceState state;
|
||||
state.networkState = static_cast<Deconz::NetworkState>(deviceStateFlag & 0x03);
|
||||
state.aspDataConfirm = (deviceStateFlag & 0x04);
|
||||
state.aspDataIndication = (deviceStateFlag & 0x08);
|
||||
state.apsDataConfirm = (deviceStateFlag & 0x04);
|
||||
state.apsDataIndication = (deviceStateFlag & 0x08);
|
||||
state.configurationChanged = (deviceStateFlag & 0x10);
|
||||
state.aspDataRequestFreeSlots = (deviceStateFlag & 0x20);
|
||||
state.apsDataRequestFreeSlots = (deviceStateFlag & 0x20);
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -750,7 +751,7 @@ void ZigbeeBridgeControllerDeconz::readDataIndication()
|
||||
return;
|
||||
}
|
||||
|
||||
// ASP data indication received, process the content
|
||||
// APS data indication received, process the content
|
||||
qCDebug(dcZigbeeController()) << "Reading data indication finished successfully";
|
||||
processDataIndication(reply->responseData());
|
||||
});
|
||||
@ -766,7 +767,7 @@ void ZigbeeBridgeControllerDeconz::readDataConfirm()
|
||||
return;
|
||||
}
|
||||
|
||||
// ASP data indication received, process the content
|
||||
// APS data confirm received, process the content
|
||||
qCDebug(dcZigbeeController()) << "Reading data confirm finished successfully";
|
||||
processDataConfirm(reply->responseData());
|
||||
});
|
||||
@ -782,10 +783,10 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
|
||||
emit networkStateChanged(m_networkState);
|
||||
}
|
||||
|
||||
if (m_aspFreeSlotsAvailable != deviceState.aspDataRequestFreeSlots) {
|
||||
m_aspFreeSlotsAvailable = deviceState.aspDataRequestFreeSlots;
|
||||
if (m_apsFreeSlotsAvailable != deviceState.apsDataRequestFreeSlots) {
|
||||
m_apsFreeSlotsAvailable = deviceState.apsDataRequestFreeSlots;
|
||||
|
||||
// FIXME: if changed to true, send next asp data request
|
||||
// FIXME: if changed to true, send next aps data request
|
||||
|
||||
}
|
||||
|
||||
@ -795,12 +796,12 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
|
||||
// Note: read a data indication before a confirmation since the confirmation arrives after a related indication normally
|
||||
|
||||
// Check if we have to read a data indication message
|
||||
if (deviceState.aspDataIndication) {
|
||||
if (deviceState.apsDataIndication) {
|
||||
readDataIndication();
|
||||
}
|
||||
|
||||
// Check if we have a response to read for a request
|
||||
if (deviceState.aspDataConfirm) {
|
||||
if (deviceState.apsDataConfirm) {
|
||||
readDataConfirm();
|
||||
}
|
||||
|
||||
@ -808,7 +809,7 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
|
||||
|
||||
void ZigbeeBridgeControllerDeconz::processDataIndication(const QByteArray &data)
|
||||
{
|
||||
// ASP data indication
|
||||
// APS data indication
|
||||
QDataStream stream(data);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 reserved = 0; quint16 asduLength = 0;
|
||||
@ -843,13 +844,14 @@ void ZigbeeBridgeControllerDeconz::processDataIndication(const QByteArray &data)
|
||||
stream >> reserved >> reserved >> indication.lqi >> reserved >> reserved >> reserved >> reserved >> indication.rssi;
|
||||
|
||||
// Print the information for debugging
|
||||
qCDebug(dcZigbeeAps()) << "APSDE-DATA.indication" << indication;
|
||||
qCDebug(dcZigbeeController()) << indication;
|
||||
|
||||
emit aspDataIndicationReceived(indication);
|
||||
emit apsDataIndicationReceived(indication);
|
||||
|
||||
// Process the device state in order to check if we have to request another indication
|
||||
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
|
||||
if (deviceState.aspDataIndication) {
|
||||
if (deviceState.apsDataIndication) {
|
||||
readDataIndication();
|
||||
}
|
||||
}
|
||||
@ -873,12 +875,13 @@ void ZigbeeBridgeControllerDeconz::processDataConfirm(const QByteArray &data)
|
||||
|
||||
// Print the information for debugging
|
||||
qCDebug(dcZigbeeController()) << confirm;
|
||||
qCDebug(dcZigbeeAps()) << "APSDE-DATA.confirm" << confirm;
|
||||
|
||||
emit aspDataConfirmReceived(confirm);
|
||||
emit apsDataConfirmReceived(confirm);
|
||||
|
||||
// Process the device state in order to check if we have to request another indication
|
||||
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
|
||||
if (deviceState.aspDataConfirm) {
|
||||
if (deviceState.apsDataConfirm) {
|
||||
readDataConfirm();
|
||||
}
|
||||
}
|
||||
@ -996,16 +999,16 @@ QDebug operator<<(QDebug debug, const DeconzDeviceState &deviceState)
|
||||
break;
|
||||
}
|
||||
|
||||
debug.nospace() << "Confirm=" << static_cast<int>(deviceState.aspDataConfirm) << ", ";
|
||||
debug.nospace() << "Indication=" << static_cast<int>(deviceState.aspDataIndication) << ", ";
|
||||
debug.nospace() << "Confirm=" << static_cast<int>(deviceState.apsDataConfirm) << ", ";
|
||||
debug.nospace() << "Indication=" << static_cast<int>(deviceState.apsDataIndication) << ", ";
|
||||
debug.nospace() << "ConfigChanged=" << static_cast<int>(deviceState.configurationChanged) << ", ";
|
||||
debug.nospace() << "CanSend=" << deviceState.aspDataRequestFreeSlots << ")";
|
||||
debug.nospace() << "CanSend=" << deviceState.apsDataRequestFreeSlots << ")";
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const DeconzApsDataConfirm &confirm)
|
||||
{
|
||||
debug.nospace() << "ASP.Confirm(";
|
||||
debug.nospace() << "APSDE-DATA.confirm(";
|
||||
debug.nospace() << "Request ID: " << confirm.requestId << ", ";
|
||||
|
||||
if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeGroup)
|
||||
@ -1027,7 +1030,7 @@ QDebug operator<<(QDebug debug, const DeconzApsDataConfirm &confirm)
|
||||
|
||||
QDebug operator<<(QDebug debug, const DeconzApsDataIndication &indication)
|
||||
{
|
||||
debug.nospace() << "ASP.Indication(";
|
||||
debug.nospace() << "APSDE-DATA.indication(";
|
||||
if (indication.destinationAddressMode == Zigbee::DestinationAddressModeGroup)
|
||||
debug.nospace() << "Group address:" << ZigbeeUtils::convertUint16ToHexString(indication.destinationShortAddress) << ", ";
|
||||
|
||||
@ -1067,7 +1070,7 @@ QDebug operator<<(QDebug debug, const DeconzNetworkConfiguration &configuration)
|
||||
debug.nospace() << " - NWK address:" << ZigbeeUtils::convertUint16ToHexString(configuration.shortAddress) << endl;
|
||||
debug.nospace() << " - PAN ID:" << ZigbeeUtils::convertUint16ToHexString(configuration.panId) << endl;
|
||||
debug.nospace() << " - Extended PAN ID:" << ZigbeeUtils::convertUint64ToHexString(configuration.extendedPanId) << endl;
|
||||
debug.nospace() << " - ASP Extended PAN ID:" << ZigbeeUtils::convertUint64ToHexString(configuration.apsExtendedPanId) << endl;
|
||||
debug.nospace() << " - APS Extended PAN ID:" << ZigbeeUtils::convertUint64ToHexString(configuration.apsExtendedPanId) << endl;
|
||||
debug.nospace() << " - Trust center IEEE address:" << configuration.trustCenterAddress.toString() << endl;
|
||||
debug.nospace() << " - Channel mask:" << ZigbeeChannelMask(configuration.channelMask) << endl;
|
||||
debug.nospace() << " - Channel:" << configuration.currentChannel << endl;
|
||||
|
||||
@ -61,14 +61,13 @@ typedef struct DeconzNetworkConfiguration {
|
||||
} DeconzNetworkConfiguration;
|
||||
|
||||
|
||||
|
||||
// This struct describes the deCONZ device state
|
||||
typedef struct DeconzDeviceState {
|
||||
Deconz::NetworkState networkState = Deconz::NetworkStateOffline;
|
||||
bool aspDataConfirm = false;
|
||||
bool aspDataIndication = false;
|
||||
bool apsDataConfirm = false;
|
||||
bool apsDataIndication = false;
|
||||
bool configurationChanged = false;
|
||||
bool aspDataRequestFreeSlots = false;
|
||||
bool apsDataRequestFreeSlots = false;
|
||||
} DeconzDeviceState;
|
||||
|
||||
|
||||
@ -141,7 +140,7 @@ private:
|
||||
Deconz::NetworkState m_networkState = Deconz::NetworkStateOffline;
|
||||
QTimer *m_watchdogTimer = nullptr;
|
||||
|
||||
bool m_aspFreeSlotsAvailable = false;
|
||||
bool m_apsFreeSlotsAvailable = false;
|
||||
|
||||
quint8 generateSequenceNumber();
|
||||
|
||||
@ -165,8 +164,8 @@ signals:
|
||||
void networkStateChanged(Deconz::NetworkState networkState);
|
||||
void networkConfigurationParameterChanged(const DeconzNetworkConfiguration &networkConfiguration);
|
||||
|
||||
void aspDataConfirmReceived(const DeconzApsDataConfirm &confirm);
|
||||
void aspDataIndicationReceived(const DeconzApsDataIndication &indication);
|
||||
void apsDataConfirmReceived(const DeconzApsDataConfirm &confirm);
|
||||
void apsDataIndicationReceived(const DeconzApsDataIndication &indication);
|
||||
|
||||
private slots:
|
||||
void onInterfaceAvailableChanged(bool available);
|
||||
|
||||
@ -38,8 +38,8 @@ ZigbeeNetworkDeconz::ZigbeeNetworkDeconz(QObject *parent) :
|
||||
m_controller = new ZigbeeBridgeControllerDeconz(this);
|
||||
//connect(m_controller, &ZigbeeBridgeControllerDeconz::messageReceived, this, &ZigbeeNetworkDeconz::onMessageReceived);
|
||||
connect(m_controller, &ZigbeeBridgeControllerDeconz::availableChanged, this, &ZigbeeNetworkDeconz::onControllerAvailableChanged);
|
||||
connect(m_controller, &ZigbeeBridgeControllerDeconz::aspDataConfirmReceived, this, &ZigbeeNetworkDeconz::onAspDataConfirmReceived);
|
||||
connect(m_controller, &ZigbeeBridgeControllerDeconz::aspDataIndicationReceived, this, &ZigbeeNetworkDeconz::onAspDataIndicationReceived);
|
||||
connect(m_controller, &ZigbeeBridgeControllerDeconz::apsDataConfirmReceived, this, &ZigbeeNetworkDeconz::onApsDataConfirmReceived);
|
||||
connect(m_controller, &ZigbeeBridgeControllerDeconz::apsDataIndicationReceived, this, &ZigbeeNetworkDeconz::onApsDataIndicationReceived);
|
||||
|
||||
m_pollNetworkStateTimer = new QTimer(this);
|
||||
m_pollNetworkStateTimer->setInterval(1000);
|
||||
@ -70,7 +70,12 @@ ZigbeeNetworkReply *ZigbeeNetworkDeconz::sendRequest(const ZigbeeNetworkRequest
|
||||
m_pendingReplies.remove(request.requestId());
|
||||
});
|
||||
|
||||
qCDebug(dcZigbeeNetwork()) << "Send request" << request;
|
||||
// Finish the reply right the way if the network is offline
|
||||
if (!m_controller->available()) {
|
||||
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorNetworkOffline);
|
||||
return reply;
|
||||
}
|
||||
|
||||
ZigbeeInterfaceDeconzReply *interfaceReply = m_controller->requestSendRequest(request);
|
||||
connect(interfaceReply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply, interfaceReply](){
|
||||
if (interfaceReply->statusCode() != Deconz::StatusCodeSuccess) {
|
||||
@ -285,13 +290,11 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
||||
return;
|
||||
}
|
||||
|
||||
ZigbeeNodeDeconz *coordinatorNode = qobject_cast<ZigbeeNodeDeconz *>(createNode(this));
|
||||
coordinatorNode->setShortAddress(m_controller->networkConfiguration().shortAddress);
|
||||
coordinatorNode->setExtendedAddress(m_controller->networkConfiguration().ieeeAddress);
|
||||
ZigbeeNode *coordinatorNode = createNode(m_controller->networkConfiguration().shortAddress, m_controller->networkConfiguration().ieeeAddress, this);
|
||||
m_coordinatorNode = coordinatorNode;
|
||||
|
||||
// Network creation done when coordinator node is initialized
|
||||
connect(coordinatorNode, &ZigbeeNodeDeconz::stateChanged, this, [this, coordinatorNode](ZigbeeNode::State state){
|
||||
connect(coordinatorNode, &ZigbeeNode::stateChanged, this, [this, coordinatorNode](ZigbeeNode::State state){
|
||||
if (state == ZigbeeNode::StateInitialized) {
|
||||
qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode;
|
||||
setState(StateRunning);
|
||||
@ -317,31 +320,39 @@ void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const DeconzApsDat
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ZigbeeNetworkReply *reply, m_pendingReplies.values()) {
|
||||
// Check if this is a response for a ZDO request
|
||||
if (reply->request().profileId() == Zigbee::ZigbeeProfileDevice) {
|
||||
// We have a reply which is waiting for a ZDO response, lets check if they match
|
||||
// Check if this is the response to the sent request command
|
||||
if (indication.clusterId == (reply->request().clusterId() | 0x8000)) {
|
||||
// Now check if the id matches, if so set the ADPU as response to the reply, otherwise this is not the message for this reply
|
||||
ZigbeeDeviceProfileAdpu deviceAdpu = ZigbeeDeviceProfile::parseAdpu(indication.asdu);
|
||||
if (deviceAdpu.sequenceNumber == reply->request().requestId()) {
|
||||
// We found the correct reply
|
||||
|
||||
// Set the response payload of the
|
||||
qCDebug(dcZigbeeNetwork()) << "Indication response for ZDO request received"
|
||||
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(reply->request().clusterId())
|
||||
<< "-->"
|
||||
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(indication.clusterId)
|
||||
<< deviceAdpu;
|
||||
setReplyResponseData(reply, indication.asdu);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
|
||||
if (!node) {
|
||||
qCWarning(dcZigbeeNetwork()) << "Received a ZDO indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
||||
return;
|
||||
}
|
||||
|
||||
qCWarning(dcZigbeeNetwork()) << "FIXME: Unhandled ZDO indication" << indication;
|
||||
node->deviceObject()->processApsDataIndication(indication.destinationEndpoint, indication.sourceEndpoint, indication.clusterId, indication.asdu, indication.lqi, indication.rssi);
|
||||
|
||||
// foreach (ZigbeeNetworkReply *reply, m_pendingReplies.values()) {
|
||||
// // Check if this is a reply if for a ZDO request
|
||||
// if (reply->request().profileId() == Zigbee::ZigbeeProfileDevice) {
|
||||
// // We have a reply which is waiting for a ZDO response, lets check if they match
|
||||
// // Check if this is the response to the sent request command
|
||||
// if (indication.clusterId == (reply->request().clusterId() | 0x8000)) {
|
||||
// // Now check if the id matches, if so set the ADPU as response to the reply, otherwise this is not the message for this reply
|
||||
// ZigbeeDeviceProfile::Adpu deviceAdpu = ZigbeeDeviceProfile::parseAdpu(indication.asdu);
|
||||
// if (deviceAdpu.transactionSequenceNumber == reply->request().requestId()) {
|
||||
// // We found the correct reply
|
||||
|
||||
// // Set the response payload of the
|
||||
// qCDebug(dcZigbeeNetwork()) << "Indication response for ZDO request received"
|
||||
// << static_cast<ZigbeeDeviceProfile::ZdoCommand>(reply->request().clusterId())
|
||||
// << "-->"
|
||||
// << static_cast<ZigbeeDeviceProfile::ZdoCommand>(indication.clusterId)
|
||||
// << deviceAdpu;
|
||||
// setReplyResponseData(reply, indication.asdu);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//qCWarning(dcZigbeeNetwork()) << "FIXME: Unhandled ZDO indication" << indication;
|
||||
}
|
||||
|
||||
void ZigbeeNetworkDeconz::handleZigbeeHomeAutomationIndication(const DeconzApsDataIndication &indication)
|
||||
@ -352,11 +363,6 @@ void ZigbeeNetworkDeconz::handleZigbeeHomeAutomationIndication(const DeconzApsDa
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
ZigbeeNode *ZigbeeNetworkDeconz::createNode(QObject *parent)
|
||||
{
|
||||
return new ZigbeeNodeDeconz(this, parent);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
|
||||
@ -371,7 +377,7 @@ void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
|
||||
|
||||
ZigbeeNetworkReply *reply = setPermitJoin(Zigbee::BroadcastAddressAllRouters, duration);
|
||||
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply, permitJoining, duration](){
|
||||
if (reply->zigbeeStatus() != Zigbee::ZigbeeStatusSuccess) {
|
||||
if (reply->zigbeeApsStatus() != Zigbee::ZigbeeApsStatusSuccess) {
|
||||
qCDebug(dcZigbeeNetwork()) << "Could not set permit join to" << duration;
|
||||
m_permitJoining = false;
|
||||
emit permitJoiningChanged(m_permitJoining);
|
||||
@ -598,23 +604,19 @@ void ZigbeeNetworkDeconz::onPermitJoinRefreshTimout()
|
||||
setPermitJoiningInternal(true);
|
||||
}
|
||||
|
||||
void ZigbeeNetworkDeconz::onAspDataConfirmReceived(const DeconzApsDataConfirm &confirm)
|
||||
void ZigbeeNetworkDeconz::onApsDataConfirmReceived(const DeconzApsDataConfirm &confirm)
|
||||
{
|
||||
qCDebug(dcZigbeeNetwork()) << confirm;
|
||||
|
||||
ZigbeeNetworkReply *reply = m_pendingReplies.value(confirm.requestId);
|
||||
if (!reply) {
|
||||
qCWarning(dcZigbeeNetwork()) << "Received confirmation but could not find any reply. Ignoring the confirmation";
|
||||
return;
|
||||
}
|
||||
|
||||
setReplyResponseError(reply, static_cast<Zigbee::ZigbeeStatus>(confirm.zigbeeStatusCode));
|
||||
setReplyResponseError(reply, static_cast<Zigbee::ZigbeeApsStatus>(confirm.zigbeeStatusCode));
|
||||
}
|
||||
|
||||
void ZigbeeNetworkDeconz::onAspDataIndicationReceived(const DeconzApsDataIndication &indication)
|
||||
void ZigbeeNetworkDeconz::onApsDataIndicationReceived(const DeconzApsDataIndication &indication)
|
||||
{
|
||||
qCDebug(dcZigbeeNetwork()) << indication;
|
||||
|
||||
// Check if this indocation is related to any pending reply
|
||||
if (indication.profileId == Zigbee::ZigbeeProfileDevice) {
|
||||
handleZigbeeDeviceProfileIndication(indication);
|
||||
@ -644,10 +646,7 @@ void ZigbeeNetworkDeconz::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress
|
||||
return;
|
||||
}
|
||||
|
||||
ZigbeeNodeDeconz *node = static_cast<ZigbeeNodeDeconz *>(createNode(this));
|
||||
node->setExtendedAddress(ieeeAddress);
|
||||
node->setShortAddress(shortAddress);
|
||||
node->setMacCapabilitiesFlag(macCapabilities);
|
||||
ZigbeeNode *node = createNode(shortAddress, ieeeAddress, macCapabilities, this);
|
||||
addUnitializedNode(node);
|
||||
node->startInitialization();
|
||||
}
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include <QObject>
|
||||
|
||||
#include "zigbeenetwork.h"
|
||||
#include "zigbeenodedeconz.h"
|
||||
#include "zigbeechannelmask.h"
|
||||
#include "zigbeeclusterlibrary.h"
|
||||
#include "zigbeebridgecontrollerdeconz.h"
|
||||
@ -54,6 +53,7 @@ public:
|
||||
|
||||
ZigbeeBridgeController *bridgeController() const override;
|
||||
|
||||
// Sending an APSDE-DATA.request, will be finished on APSDE-DATA.confirm
|
||||
ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override;
|
||||
|
||||
ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress, quint8 duration);
|
||||
@ -82,10 +82,7 @@ private:
|
||||
// GP
|
||||
|
||||
protected:
|
||||
ZigbeeNode *createNode(QObject *parent) override;
|
||||
|
||||
void setPermitJoiningInternal(bool permitJoining) override;
|
||||
|
||||
void startNetworkInternally();
|
||||
|
||||
private slots:
|
||||
@ -93,8 +90,8 @@ private slots:
|
||||
void onPollNetworkStateTimeout();
|
||||
void onPermitJoinRefreshTimout();
|
||||
|
||||
void onAspDataConfirmReceived(const DeconzApsDataConfirm &confirm);
|
||||
void onAspDataIndicationReceived(const DeconzApsDataIndication &indication);
|
||||
void onApsDataConfirmReceived(const DeconzApsDataConfirm &confirm);
|
||||
void onApsDataIndicationReceived(const DeconzApsDataIndication &indication);
|
||||
|
||||
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
|
||||
|
||||
|
||||
@ -1,429 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea-zigbee.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "zigbeeutils.h"
|
||||
#include "zigbeenodedeconz.h"
|
||||
#include "zdo/zigbeedeviceprofile.h"
|
||||
#include "zigbeenetworkdeconz.h"
|
||||
#include "zigbeenodeendpointdeconz.h"
|
||||
|
||||
#include "loggingcategory.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
ZigbeeNodeDeconz::ZigbeeNodeDeconz(ZigbeeNetworkDeconz *network, QObject *parent) :
|
||||
ZigbeeNode(network, parent),
|
||||
m_network(network)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply *ZigbeeNodeDeconz::requestNodeDescriptor()
|
||||
{
|
||||
// Get the node descriptor
|
||||
ZigbeeNetworkRequest request;
|
||||
request.setRequestId(m_network->generateSequenceNumber());
|
||||
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||
request.setDestinationShortAddress(shortAddress());
|
||||
request.setDestinationEndpoint(0); // ZDO
|
||||
request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP
|
||||
request.setClusterId(ZigbeeDeviceProfile::NodeDescriptorRequest);
|
||||
request.setSourceEndpoint(0); // ZDO
|
||||
|
||||
// Build ASDU
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << request.requestId() << request.destinationShortAddress();
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// We expect an indication with the response and the confirmation
|
||||
request.setExpectIndication(true);
|
||||
return m_network->sendRequest(request);
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply *ZigbeeNodeDeconz::requestPowerDescriptor()
|
||||
{
|
||||
// Get the power descriptor
|
||||
ZigbeeNetworkRequest request;
|
||||
request.setRequestId(m_network->generateSequenceNumber());
|
||||
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||
request.setDestinationShortAddress(shortAddress());
|
||||
request.setDestinationEndpoint(0); // ZDO
|
||||
request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP
|
||||
request.setClusterId(ZigbeeDeviceProfile::PowerDescriptorRequest);
|
||||
request.setSourceEndpoint(0); // ZDO
|
||||
|
||||
// Build ASDU
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << request.requestId() << request.destinationShortAddress();
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// We expect an indication with the response and the confirmation
|
||||
request.setExpectIndication(true);
|
||||
return m_network->sendRequest(request);
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply *ZigbeeNodeDeconz::requestActiveEndpoints()
|
||||
{
|
||||
// Get the power descriptor
|
||||
ZigbeeNetworkRequest request;
|
||||
request.setRequestId(m_network->generateSequenceNumber());
|
||||
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||
request.setDestinationShortAddress(shortAddress());
|
||||
request.setDestinationEndpoint(0); // ZDO
|
||||
request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP
|
||||
request.setClusterId(ZigbeeDeviceProfile::ActiveEndpointsRequest);
|
||||
request.setSourceEndpoint(0); // ZDO
|
||||
|
||||
// Build ASDU
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << request.requestId() << request.destinationShortAddress();
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// We expect an indication with the response and the confirmation
|
||||
request.setExpectIndication(true);
|
||||
return m_network->sendRequest(request);
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply *ZigbeeNodeDeconz::requestSimpleDescriptor(quint8 endpoint)
|
||||
{
|
||||
// Get the power descriptor
|
||||
ZigbeeNetworkRequest request;
|
||||
request.setRequestId(m_network->generateSequenceNumber());
|
||||
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||
request.setDestinationShortAddress(shortAddress());
|
||||
request.setDestinationEndpoint(0); // ZDO
|
||||
request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP
|
||||
request.setClusterId(ZigbeeDeviceProfile::SimpleDescriptorRequest);
|
||||
request.setSourceEndpoint(0); // ZDO
|
||||
|
||||
// Build ASDU
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << request.requestId() << request.destinationShortAddress() << endpoint;
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// We expect an indication with the response and the confirmation
|
||||
request.setExpectIndication(true);
|
||||
return m_network->sendRequest(request);
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply *ZigbeeNodeDeconz::requestLeaveNetwork(bool rejoin, bool removeChildren)
|
||||
{
|
||||
ZigbeeNetworkRequest request;
|
||||
request.setRequestId(m_network->generateSequenceNumber());
|
||||
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||
request.setDestinationShortAddress(shortAddress());
|
||||
request.setDestinationEndpoint(0); // ZDO
|
||||
request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP
|
||||
request.setClusterId(ZigbeeDeviceProfile::MgmtLeaveRequest);
|
||||
request.setSourceEndpoint(0); // ZDO
|
||||
|
||||
// Build ASDU
|
||||
QByteArray asdu;
|
||||
quint8 leaveFlag = 0;
|
||||
if (rejoin) {
|
||||
leaveFlag |= 0x01;
|
||||
}
|
||||
|
||||
if (removeChildren) {
|
||||
leaveFlag |= 0x02;
|
||||
}
|
||||
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << request.requestId() << extendedAddress().toUInt64() << leaveFlag;
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// We expect an indication with the response and the confirmation
|
||||
request.setExpectIndication(true);
|
||||
return m_network->sendRequest(request);
|
||||
}
|
||||
|
||||
void ZigbeeNodeDeconz::leaveNetworkRequest(bool rejoin, bool removeChildren)
|
||||
{
|
||||
ZigbeeNetworkReply *reply = requestLeaveNetwork(rejoin, removeChildren);
|
||||
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
||||
// TODO: check reply error
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNodeDeconz::initNodeDescriptor()
|
||||
{
|
||||
ZigbeeNetworkReply *reply = requestNodeDescriptor();
|
||||
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
||||
// TODO: check reply error
|
||||
|
||||
ZigbeeDeviceProfileAdpu adpu = ZigbeeDeviceProfile::parseAdpu(reply->responseData());
|
||||
qCDebug(dcZigbeeNode()) << "Node descriptor request finished" << adpu;
|
||||
QDataStream stream(adpu.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();
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNodeDeconz::initPowerDescriptor()
|
||||
{
|
||||
ZigbeeNetworkReply *reply = requestPowerDescriptor();
|
||||
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
||||
// TODO: check reply error
|
||||
|
||||
ZigbeeDeviceProfileAdpu adpu = ZigbeeDeviceProfile::parseAdpu(reply->responseData());
|
||||
qCDebug(dcZigbeeNode()) << "Power descriptor request finished" << this << adpu;
|
||||
QDataStream stream(adpu.payload);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint16 powerDescriptorFlag = 0;
|
||||
stream >> powerDescriptorFlag;
|
||||
setPowerDescriptorFlag(powerDescriptorFlag);
|
||||
|
||||
// Continue with endpoint fetching
|
||||
initEndpoints();
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNodeDeconz::initEndpoints()
|
||||
{
|
||||
ZigbeeNetworkReply *reply = requestActiveEndpoints();
|
||||
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply](){
|
||||
// TODO: check reply error
|
||||
|
||||
ZigbeeDeviceProfileAdpu adpu = ZigbeeDeviceProfile::parseAdpu(reply->responseData());
|
||||
qCDebug(dcZigbeeNode()) << "Active endpoints request finished" << this << adpu;
|
||||
QDataStream stream(adpu.payload);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 endpointCount = 0;
|
||||
m_uninitializedEndpoints.clear();
|
||||
stream >> endpointCount;
|
||||
for (int i = 0; i < endpointCount; i++) {
|
||||
quint8 endpoint = 0;
|
||||
stream >> endpoint;
|
||||
m_uninitializedEndpoints.append(endpoint);
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNode()) << "Endpoints" << endpointCount;
|
||||
for (int i = 0; i < m_uninitializedEndpoints.count(); i++) {
|
||||
qCDebug(dcZigbeeNode()) << " -" << ZigbeeUtils::convertByteToHexString(m_uninitializedEndpoints.at(i));
|
||||
}
|
||||
|
||||
// Read simple descriptor for each endpoint
|
||||
if (m_uninitializedEndpoints.isEmpty()) {
|
||||
initBasicCluster();
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_uninitializedEndpoints.count(); i++) {
|
||||
quint8 endpointId = m_uninitializedEndpoints.at(i);
|
||||
qCDebug(dcZigbeeNode()) << "Read simple descriptor of endpoint" << ZigbeeUtils::convertByteToHexString(endpointId);
|
||||
ZigbeeNetworkReply *reply = requestSimpleDescriptor(endpointId);
|
||||
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply, endpointId](){
|
||||
// TODO: check reply error
|
||||
ZigbeeDeviceProfileAdpu adpu = ZigbeeDeviceProfile::parseAdpu(reply->responseData());
|
||||
qCDebug(dcZigbeeNode()) << "Simple descriptor request finished" << this << endpointId << adpu;
|
||||
|
||||
QDataStream stream(adpu.payload);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 length = 0;
|
||||
quint8 endpointId = 0;
|
||||
quint16 profileId = 0;
|
||||
quint16 deviceId = 0;
|
||||
quint8 deviceVersion = 0;
|
||||
quint8 inputClusterCount = 0;
|
||||
quint8 outputClusterCount = 0;
|
||||
|
||||
QList<quint16> inputClusters;
|
||||
QList<quint16> outputClusters;
|
||||
|
||||
stream >> length >> endpointId >> profileId >> deviceId >> deviceVersion >> inputClusterCount;
|
||||
|
||||
qCDebug(dcZigbeeNode()) << "Node endpoint simple descriptor:";
|
||||
qCDebug(dcZigbeeNode()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
|
||||
qCDebug(dcZigbeeNode()) << " End Point:" << ZigbeeUtils::convertByteToHexString(endpointId);
|
||||
qCDebug(dcZigbeeNode()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
||||
if (profileId == Zigbee::ZigbeeProfileLightLink) {
|
||||
qCDebug(dcZigbeeNode()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::LightLinkDevice>(deviceId);
|
||||
} else if (profileId == Zigbee::ZigbeeProfileHomeAutomation) {
|
||||
qCDebug(dcZigbeeNode()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::HomeAutomationDevice>(deviceId);
|
||||
} else if (profileId == Zigbee::ZigbeeProfileGreenPower) {
|
||||
qCDebug(dcZigbeeNode()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::GreenPowerDevice>(deviceId);
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNode()) << " Device version:" << ZigbeeUtils::convertByteToHexString(deviceVersion);
|
||||
|
||||
// Create endpoint
|
||||
ZigbeeNodeEndpointDeconz *endpoint = nullptr;
|
||||
if (!hasEndpoint(endpointId)) {
|
||||
endpoint = qobject_cast<ZigbeeNodeEndpointDeconz *>(createNodeEndpoint(endpointId, this));
|
||||
m_endpoints.append(endpoint);
|
||||
} else {
|
||||
endpoint = qobject_cast<ZigbeeNodeEndpointDeconz *>(getEndpoint(endpointId));
|
||||
}
|
||||
endpoint->setProfile(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
||||
endpoint->setDeviceId(deviceId);
|
||||
endpoint->setDeviceVersion(deviceVersion);
|
||||
|
||||
qCDebug(dcZigbeeNode()) << " Input clusters: (" << inputClusterCount << ")";
|
||||
for (int i = 0; i < inputClusterCount; i++) {
|
||||
quint16 clusterId = 0;
|
||||
stream >> clusterId;
|
||||
if (!endpoint->hasInputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||
endpoint->addInputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Input, endpoint));
|
||||
}
|
||||
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||
|
||||
}
|
||||
stream >> outputClusterCount;
|
||||
|
||||
qCDebug(dcZigbeeNode()) << " Output clusters: (" << outputClusterCount << ")";
|
||||
for (int i = 0; i < outputClusterCount; i++) {
|
||||
quint16 clusterId = 0;
|
||||
stream >> clusterId;
|
||||
if (!endpoint->hasOutputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||
endpoint->addOutputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Output, endpoint));
|
||||
}
|
||||
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||
}
|
||||
|
||||
m_uninitializedEndpoints.removeAll(endpointId);
|
||||
|
||||
if (m_uninitializedEndpoints.isEmpty()) {
|
||||
// Continue with the basic cluster attributes
|
||||
initBasicCluster();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNodeDeconz::initBasicCluster()
|
||||
{
|
||||
|
||||
// TODO
|
||||
|
||||
setState(StateInitialized);
|
||||
}
|
||||
|
||||
void ZigbeeNodeDeconz::setClusterAttributeReport(const ZigbeeClusterAttributeReport &report)
|
||||
{
|
||||
Q_UNUSED(report)
|
||||
}
|
||||
|
||||
void ZigbeeNodeDeconz::startInitialization()
|
||||
{
|
||||
setState(StateInitializing);
|
||||
|
||||
/* Node initialisation steps (sequentially)
|
||||
* - Node descriptor
|
||||
* - Power descriptor
|
||||
* - Active endpoints
|
||||
* - for each endpoint do:
|
||||
* - Simple descriptor request
|
||||
* - for each endpoint
|
||||
* - read basic cluster
|
||||
*/
|
||||
|
||||
initNodeDescriptor();
|
||||
|
||||
/*
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
ZigbeeNodeEndpoint *ZigbeeNodeDeconz::createNodeEndpoint(quint8 endpointId, QObject *parent)
|
||||
{
|
||||
return qobject_cast<ZigbeeNodeEndpoint *>(new ZigbeeNodeEndpointDeconz(m_network, this, endpointId, parent));
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea-zigbee.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef ZIGBEENODEDECONZ_H
|
||||
#define ZIGBEENODEDECONZ_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "zigbee.h"
|
||||
#include "zigbeenode.h"
|
||||
|
||||
class ZigbeeNodeEndpoint;
|
||||
class ZigbeeNetworkDeconz;
|
||||
|
||||
class ZigbeeNodeDeconz : public ZigbeeNode
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ZigbeeNetworkDeconz;
|
||||
|
||||
public:
|
||||
explicit ZigbeeNodeDeconz(ZigbeeNetworkDeconz *network, QObject *parent = nullptr);
|
||||
|
||||
ZigbeeNetworkReply *requestNodeDescriptor();
|
||||
ZigbeeNetworkReply *requestPowerDescriptor();
|
||||
ZigbeeNetworkReply *requestActiveEndpoints();
|
||||
ZigbeeNetworkReply *requestSimpleDescriptor(quint8 endpoint);
|
||||
|
||||
ZigbeeNetworkReply *requestLeaveNetwork(bool rejoin = false, bool removeChildren = false);
|
||||
|
||||
void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) override;
|
||||
|
||||
private:
|
||||
ZigbeeNetworkDeconz *m_network = nullptr;
|
||||
|
||||
// Init methods
|
||||
void initNodeDescriptor();
|
||||
void initPowerDescriptor();
|
||||
void initEndpoints();
|
||||
void initBasicCluster();
|
||||
|
||||
QList<quint8> m_uninitializedEndpoints;
|
||||
QList<quint16> m_uninitalizedBasicClusterAttributes;
|
||||
|
||||
void setClusterAttributeReport(const ZigbeeClusterAttributeReport &report) override;
|
||||
|
||||
protected:
|
||||
void startInitialization() override;
|
||||
ZigbeeNodeEndpoint *createNodeEndpoint(quint8 endpointId, QObject *parent) override;
|
||||
|
||||
private slots:
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // ZIGBEENODEDECONZ_H
|
||||
@ -1,43 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea-zigbee.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "zigbeenodeendpointdeconz.h"
|
||||
#include "zigbeenodeendpoint.h"
|
||||
|
||||
ZigbeeNodeEndpointDeconz::ZigbeeNodeEndpointDeconz(ZigbeeNetworkDeconz *network, ZigbeeNode *node, quint8 endpointId, QObject *parent) :
|
||||
ZigbeeNodeEndpoint(node, endpointId, parent),
|
||||
m_network(network),
|
||||
m_node(node)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ZigbeeNodeEndpointDeconz::setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute)
|
||||
{
|
||||
Q_UNUSED(clusterId)
|
||||
Q_UNUSED(attribute)
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea-zigbee.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef ZIGBEENODEENDPOINTDECONZ_H
|
||||
#define ZIGBEENODEENDPOINTDECONZ_H
|
||||
|
||||
#include <QObject>
|
||||
#include "zigbeenodeendpoint.h"
|
||||
#include "zigbeeclusterlibrary.h"
|
||||
|
||||
class ZigbeeNodeDeconz;
|
||||
class ZigbeeNetworkDeconz;
|
||||
|
||||
class ZigbeeNodeEndpointDeconz : public ZigbeeNodeEndpoint
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ZigbeeNodeDeconz;
|
||||
|
||||
public:
|
||||
explicit ZigbeeNodeEndpointDeconz(ZigbeeNetworkDeconz *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr);
|
||||
|
||||
protected:
|
||||
// Cluster commands
|
||||
void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()) override;
|
||||
|
||||
private:
|
||||
ZigbeeNetworkDeconz *m_network = nullptr;
|
||||
ZigbeeNode *m_node = nullptr;
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
#endif // ZIGBEENODEENDPOINTDECONZ_H
|
||||
@ -8,8 +8,6 @@ SOURCES += \
|
||||
deconz/interface/zigbeeinterfacedeconzreply.cpp \
|
||||
deconz/zigbeebridgecontrollerdeconz.cpp \
|
||||
deconz/zigbeenetworkdeconz.cpp \
|
||||
deconz/zigbeenodedeconz.cpp \
|
||||
deconz/zigbeenodeendpointdeconz.cpp \
|
||||
# nxp/interface/zigbeeinterface.cpp \
|
||||
# nxp/interface/zigbeeinterfacemessage.cpp \
|
||||
# nxp/interface/zigbeeinterfacerequest.cpp \
|
||||
@ -19,9 +17,9 @@ SOURCES += \
|
||||
# nxp/zigbeenodeendpointnxp.cpp \
|
||||
# nxp/zigbeenodenxp.cpp \
|
||||
zcl/zigbeeclusterbasic.cpp \
|
||||
zcl/zigbeeclusterreply.cpp \
|
||||
zdo/zigbeedeviceobject.cpp \
|
||||
zdo/zigbeedeviceobjectreply.cpp \
|
||||
zdo/zigbeedeviceprofilehandler.cpp \
|
||||
zdo/zigbeedeviceprofile.cpp \
|
||||
zigbeeadpu.cpp \
|
||||
zigbeebridgecontroller.cpp \
|
||||
@ -52,8 +50,6 @@ HEADERS += \
|
||||
deconz/interface/zigbeeinterfacedeconzreply.h \
|
||||
deconz/zigbeebridgecontrollerdeconz.h \
|
||||
deconz/zigbeenetworkdeconz.h \
|
||||
deconz/zigbeenodedeconz.h \
|
||||
deconz/zigbeenodeendpointdeconz.h \
|
||||
# nxp/interface/zigbeeinterface.h \
|
||||
# nxp/interface/zigbeeinterfacemessage.h \
|
||||
# nxp/interface/zigbeeinterfacerequest.h \
|
||||
@ -63,9 +59,9 @@ HEADERS += \
|
||||
# nxp/zigbeenodeendpointnxp.h \
|
||||
# nxp/zigbeenodenxp.h \
|
||||
zcl/zigbeeclusterbasic.h \
|
||||
zcl/zigbeeclusterreply.h \
|
||||
zdo/zigbeedeviceobject.h \
|
||||
zdo/zigbeedeviceobjectreply.h \
|
||||
zdo/zigbeedeviceprofilehandler.h \
|
||||
zdo/zigbeedeviceprofile.h \
|
||||
zigbeeadpu.h \
|
||||
zigbeebridgecontroller.h \
|
||||
|
||||
@ -29,8 +29,10 @@
|
||||
|
||||
Q_LOGGING_CATEGORY(dcZigbeeNetwork, "ZigbeeNetwork")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeNode, "ZigbeeNode")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeAps, "ZigbeeAps")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeCluster, "ZigbeeCluster")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeDeviceObject, "ZigbeeDeviceObject")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase")
|
||||
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")
|
||||
|
||||
@ -33,9 +33,11 @@
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetwork)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNode)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeAps)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeDeviceObject)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)
|
||||
|
||||
|
||||
6
libnymea-zigbee/zcl/zigbeeclusterreply.cpp
Normal file
6
libnymea-zigbee/zcl/zigbeeclusterreply.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "zigbeeclusterreply.h"
|
||||
|
||||
ZigbeeClusterReply::ZigbeeClusterReply(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
16
libnymea-zigbee/zcl/zigbeeclusterreply.h
Normal file
16
libnymea-zigbee/zcl/zigbeeclusterreply.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef ZIGBEECLUSTERREPLY_H
|
||||
#define ZIGBEECLUSTERREPLY_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class ZigbeeClusterReply : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ZigbeeClusterReply(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
#endif // ZIGBEECLUSTERREPLY_H
|
||||
@ -1,9 +1,360 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea-zigbee.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "zigbeedeviceobject.h"
|
||||
#include "zigbeenetwork.h"
|
||||
#include "loggingcategory.h"
|
||||
|
||||
ZigbeeDeviceObject::ZigbeeDeviceObject(ZigbeeNetwork *network, QObject *parent) :
|
||||
#include <QDataStream>
|
||||
|
||||
ZigbeeDeviceObject::ZigbeeDeviceObject(ZigbeeNetwork *network, ZigbeeNode *node, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_network(network)
|
||||
m_network(network),
|
||||
m_node(node)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestNodeDescriptor()
|
||||
{
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Request node descriptor from" << m_node;
|
||||
|
||||
// Build APS request
|
||||
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::NodeDescriptorRequest);
|
||||
|
||||
// Generate a new transaction sequence number for this device object
|
||||
quint8 transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// Build ZDO frame
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << transactionSequenceNumber << m_node->shortAddress();
|
||||
|
||||
// Set the ZDO frame as APS request payload
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// Create the device object reply and wait for the response indication
|
||||
ZigbeeDeviceObjectReply *zdoReply = createZigbeeDeviceObjectReply(request, transactionSequenceNumber);
|
||||
|
||||
// Send the request, on finished read the confirm information
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){
|
||||
if (!verifyNetworkError(zdoReply, networkReply)) {
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Failed to send request"
|
||||
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId())
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zdoReply->isComplete()) {
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// We received the confirmation but not yet the indication
|
||||
});
|
||||
|
||||
return zdoReply;
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestPowerDescriptor()
|
||||
{
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Request power descriptor from" << m_node;
|
||||
|
||||
// Build APS request
|
||||
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::PowerDescriptorRequest);
|
||||
|
||||
// Generate a new transaction sequence number for this device object
|
||||
quint8 transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// Build ZDO frame
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << transactionSequenceNumber << m_node->shortAddress();
|
||||
|
||||
// Set the ZDO frame as APS request payload
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// Create the device object reply and wait for the response indication
|
||||
ZigbeeDeviceObjectReply *zdoReply = createZigbeeDeviceObjectReply(request, transactionSequenceNumber);
|
||||
|
||||
// Send the request, on finished read the confirm information
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){
|
||||
if (!verifyNetworkError(zdoReply, networkReply)) {
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Failed to send request"
|
||||
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId())
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zdoReply->isComplete()) {
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
// We received the confirmation but not yet the indication
|
||||
});
|
||||
|
||||
return zdoReply;
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestActiveEndpoints()
|
||||
{
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Request active endpoints from" << m_node;
|
||||
|
||||
// Build APS request
|
||||
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::ActiveEndpointsRequest);
|
||||
|
||||
// Generate a new transaction sequence number for this device object
|
||||
quint8 transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// Build ZDO frame
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << transactionSequenceNumber << m_node->shortAddress();
|
||||
|
||||
// Set the ZDO frame as APS request payload
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// Create the device object reply and wait for the response indication
|
||||
ZigbeeDeviceObjectReply *zdoReply = createZigbeeDeviceObjectReply(request, transactionSequenceNumber);
|
||||
|
||||
// Send the request, on finished read the confirm information
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){
|
||||
if (!verifyNetworkError(zdoReply, networkReply)) {
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Failed to send request"
|
||||
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId())
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zdoReply->isComplete()) {
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
// We received the confirmation but not yet the indication
|
||||
});
|
||||
|
||||
return zdoReply;
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestSimpleDescriptor(quint8 endpointId)
|
||||
{
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Request simple descriptor from" << m_node << "endpoint" << endpointId;
|
||||
|
||||
// Build APS request
|
||||
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::SimpleDescriptorRequest);
|
||||
|
||||
// Generate a new transaction sequence number for this device object
|
||||
quint8 transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// Build ZDO frame
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << transactionSequenceNumber << request.destinationShortAddress() << endpointId;
|
||||
|
||||
// Set the ZDO frame as APS request payload
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// Create the device object reply and wait for the response indication
|
||||
ZigbeeDeviceObjectReply *zdoReply = createZigbeeDeviceObjectReply(request, transactionSequenceNumber);
|
||||
|
||||
// Send the request, on finished read the confirm information
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){
|
||||
if (!verifyNetworkError(zdoReply, networkReply)) {
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Failed to send request"
|
||||
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId())
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zdoReply->isComplete()) {
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
// We received the confirmation but not yet the indication
|
||||
});
|
||||
|
||||
return zdoReply;
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestMgmtLeaveNetwork(bool rejoin, bool removeChildren)
|
||||
{
|
||||
qCDebug(dcZigbeeDeviceObject()) << "Request management leave network from" << m_node << "rejoin" << rejoin << "remove children" << removeChildren;
|
||||
|
||||
// Build APS request
|
||||
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::MgmtLeaveRequest);
|
||||
|
||||
// Generate a new transaction sequence number for this device object
|
||||
quint8 transactionSequenceNumber = m_transactionSequenceNumber++;
|
||||
|
||||
// Build ZDO frame
|
||||
quint8 leaveFlag = 0;
|
||||
if (rejoin) {
|
||||
leaveFlag |= 0x01;
|
||||
}
|
||||
|
||||
if (removeChildren) {
|
||||
leaveFlag |= 0x02;
|
||||
}
|
||||
|
||||
QByteArray asdu;
|
||||
QDataStream stream(&asdu, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream << transactionSequenceNumber << m_node->extendedAddress().toUInt64() << leaveFlag;
|
||||
|
||||
// Set the ZDO frame as APS request payload
|
||||
request.setAsdu(asdu);
|
||||
|
||||
// Create the device object reply and wait for the response indication
|
||||
ZigbeeDeviceObjectReply *zdoReply = createZigbeeDeviceObjectReply(request, transactionSequenceNumber);
|
||||
|
||||
// Send the request, on finished read the confirm information
|
||||
ZigbeeNetworkReply *networkReply = m_network->sendRequest(request);
|
||||
connect(networkReply, &ZigbeeNetworkReply::finished, this, [this, networkReply, zdoReply](){
|
||||
if (!verifyNetworkError(zdoReply, networkReply)) {
|
||||
qCWarning(dcZigbeeDeviceObject()) << "Failed to send request"
|
||||
<< static_cast<ZigbeeDeviceProfile::ZdoCommand>(networkReply->request().clusterId())
|
||||
<< m_node << networkReply->error()
|
||||
<< networkReply->zigbeeApsStatus();
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
|
||||
// The request was successfully sent to the device
|
||||
// Now check if the expected indication response received already
|
||||
if (zdoReply->isComplete()) {
|
||||
finishZdoReply(zdoReply);
|
||||
return;
|
||||
}
|
||||
// We received the confirmation but not yet the indication
|
||||
});
|
||||
|
||||
return zdoReply;
|
||||
}
|
||||
|
||||
ZigbeeNetworkRequest ZigbeeDeviceObject::buildZdoRequest(quint16 zdoRequest)
|
||||
{
|
||||
ZigbeeNetworkRequest request;
|
||||
request.setRequestId(m_network->generateSequenceNumber());
|
||||
request.setDestinationAddressMode(Zigbee::DestinationAddressModeShortAddress);
|
||||
request.setDestinationShortAddress(m_node->shortAddress());
|
||||
request.setDestinationEndpoint(0); // ZDO
|
||||
request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP
|
||||
request.setClusterId(zdoRequest);
|
||||
request.setSourceEndpoint(0); // ZDO
|
||||
return request;
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::createZigbeeDeviceObjectReply(const ZigbeeNetworkRequest &request, quint8 transactionSequenceNumber)
|
||||
{
|
||||
ZigbeeDeviceObjectReply *zdoReply = new ZigbeeDeviceObjectReply(request, this);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, zdoReply, &ZigbeeDeviceObjectReply::deleteLater);
|
||||
zdoReply->m_expectedResponse = static_cast<ZigbeeDeviceProfile::ZdoCommand>(request.clusterId() | 0x8000);
|
||||
zdoReply->m_transactionSequenceNumber = transactionSequenceNumber;
|
||||
m_pendingReplies.insert(transactionSequenceNumber, zdoReply);
|
||||
return zdoReply;
|
||||
}
|
||||
|
||||
bool ZigbeeDeviceObject::verifyNetworkError(ZigbeeDeviceObjectReply *zdoReply, ZigbeeNetworkReply *networkReply)
|
||||
{
|
||||
bool success = false;
|
||||
switch (networkReply->error()) {
|
||||
case ZigbeeNetworkReply::ErrorNoError:
|
||||
// The request has been transported successfully to he destination, now
|
||||
// wait for the expected indication or check if we already recieved it
|
||||
zdoReply->m_apsConfirmReceived = true;
|
||||
zdoReply->m_zigbeeApsStatus = networkReply->zigbeeApsStatus();
|
||||
success = true;
|
||||
break;
|
||||
case ZigbeeNetworkReply::ErrorInterfaceError:
|
||||
zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorInterfaceError;
|
||||
break;
|
||||
case ZigbeeNetworkReply::ErrorNetworkOffline:
|
||||
zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorNetworkOffline;
|
||||
break;
|
||||
case ZigbeeNetworkReply::ErrorZigbeeApsStatusError:
|
||||
zdoReply->m_error = ZigbeeDeviceObjectReply::ErrorZigbeeApsStatusError;
|
||||
zdoReply->m_apsConfirmReceived = true;
|
||||
zdoReply->m_zigbeeApsStatus = networkReply->zigbeeApsStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void ZigbeeDeviceObject::finishZdoReply(ZigbeeDeviceObjectReply *zdoReply)
|
||||
{
|
||||
m_pendingReplies.remove(zdoReply->transactionSequenceNumber());
|
||||
zdoReply->finished();
|
||||
}
|
||||
|
||||
void ZigbeeDeviceObject::processApsDataIndication(quint8 destinationEndpoint, quint8 sourceEndpoint, quint16 clusterId, QByteArray payload, quint8 lqi, qint8 rssi)
|
||||
{
|
||||
Q_UNUSED(destinationEndpoint)
|
||||
Q_UNUSED(sourceEndpoint)
|
||||
Q_UNUSED(clusterId)
|
||||
Q_UNUSED(lqi)
|
||||
Q_UNUSED(rssi)
|
||||
|
||||
// Check if we have a waiting ZDO reply for this data
|
||||
ZigbeeDeviceProfile::Adpu asdu = ZigbeeDeviceProfile::parseAdpu(payload);
|
||||
ZigbeeDeviceObjectReply *zdoReply = m_pendingReplies.value(asdu.transactionSequenceNumber);
|
||||
if (zdoReply && clusterId == (zdoReply->request().clusterId() | 0x8000)) {
|
||||
zdoReply->m_responseData = payload;
|
||||
zdoReply->m_responseAdpu = asdu;
|
||||
zdoReply->m_zdpIndicationReceived = true;
|
||||
if (zdoReply->isComplete()) {
|
||||
finishZdoReply(zdoReply);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
qCWarning(dcZigbeeDeviceObject()) << m_node << "unhandled ZDO indication";
|
||||
}
|
||||
|
||||
@ -1,21 +1,76 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea-zigbee.
|
||||
* This project including source code and documentation is protected by copyright law, and
|
||||
* remains the property of nymea GmbH. All rights, including reproduction, publication,
|
||||
* editing and translation, are reserved. The use of this project is subject to the terms of a
|
||||
* license agreement to be concluded with nymea GmbH in accordance with the terms
|
||||
* of use of nymea GmbH, available under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation; version 3.
|
||||
* this project is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this project.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under contact@nymea.io
|
||||
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef ZIGBEEDEVICEOBJECT_H
|
||||
#define ZIGBEEDEVICEOBJECT_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "zigbeenetworkreply.h"
|
||||
#include "zigbeedeviceobjectreply.h"
|
||||
|
||||
class ZigbeeNode;
|
||||
class ZigbeeNetwork;
|
||||
|
||||
class ZigbeeDeviceObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ZigbeeDeviceObject(ZigbeeNetwork *network, QObject *parent = nullptr);
|
||||
explicit ZigbeeDeviceObject(ZigbeeNetwork *network, ZigbeeNode *node, QObject *parent = nullptr);
|
||||
|
||||
// Device and service discovery
|
||||
ZigbeeDeviceObjectReply *requestNodeDescriptor();
|
||||
ZigbeeDeviceObjectReply *requestPowerDescriptor();
|
||||
ZigbeeDeviceObjectReply *requestActiveEndpoints();
|
||||
ZigbeeDeviceObjectReply *requestSimpleDescriptor(quint8 endpointId);
|
||||
|
||||
// Management request
|
||||
ZigbeeDeviceObjectReply *requestMgmtLeaveNetwork(bool rejoin = false, bool removeChildren = false);
|
||||
|
||||
// TODO: write all requests
|
||||
|
||||
private:
|
||||
ZigbeeNetwork *m_network = nullptr;
|
||||
ZigbeeNode *m_node = nullptr;
|
||||
|
||||
quint8 m_transactionSequenceNumber = 0;
|
||||
QHash<quint8, ZigbeeDeviceObjectReply *> m_pendingReplies;
|
||||
|
||||
// Helper methods
|
||||
ZigbeeNetworkRequest buildZdoRequest(quint16 zdoRequest);
|
||||
ZigbeeDeviceObjectReply *createZigbeeDeviceObjectReply(const ZigbeeNetworkRequest &request, quint8 transactionSequenceNumber);
|
||||
bool verifyNetworkError(ZigbeeDeviceObjectReply *zdoReply, ZigbeeNetworkReply *networkReply);
|
||||
void finishZdoReply(ZigbeeDeviceObjectReply *zdoReply);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void processApsDataIndication(quint8 destinationEndpoint, quint8 sourceEndpoint, quint16 clusterId, QByteArray payload, quint8 lqi, qint8 rssi);
|
||||
|
||||
};
|
||||
|
||||
#endif // ZIGBEEDEVICEOBJECT_H
|
||||
|
||||
@ -1,6 +1,75 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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 "zigbeedeviceobjectreply.h"
|
||||
|
||||
ZigbeeDeviceObjectReply::ZigbeeDeviceObjectReply(QObject *parent) : QObject(parent)
|
||||
ZigbeeDeviceObjectReply::ZigbeeDeviceObjectReply(const ZigbeeNetworkRequest &request, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_request(request)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ZigbeeDeviceObjectReply::Error ZigbeeDeviceObjectReply::error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
ZigbeeNetworkRequest ZigbeeDeviceObjectReply::request() const
|
||||
{
|
||||
return m_request;
|
||||
}
|
||||
|
||||
quint8 ZigbeeDeviceObjectReply::transactionSequenceNumber() const
|
||||
{
|
||||
return m_transactionSequenceNumber;
|
||||
}
|
||||
|
||||
ZigbeeDeviceProfile::ZdoCommand ZigbeeDeviceObjectReply::expectedResponse() const
|
||||
{
|
||||
return m_expectedResponse;
|
||||
}
|
||||
|
||||
QByteArray ZigbeeDeviceObjectReply::responseData() const
|
||||
{
|
||||
return m_responseData;
|
||||
}
|
||||
|
||||
ZigbeeDeviceProfile::Adpu ZigbeeDeviceObjectReply::responseAdpu() const
|
||||
{
|
||||
return m_responseAdpu;
|
||||
}
|
||||
|
||||
Zigbee::ZigbeeApsStatus ZigbeeDeviceObjectReply::zigbeeApsStatus() const
|
||||
{
|
||||
return m_zigbeeApsStatus;
|
||||
}
|
||||
|
||||
bool ZigbeeDeviceObjectReply::isComplete() const
|
||||
{
|
||||
return m_apsConfirmReceived && m_zdpIndicationReceived;
|
||||
}
|
||||
|
||||
@ -1,15 +1,89 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* 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 ZIGBEEDEVICEOBJECTREPLY_H
|
||||
#define ZIGBEEDEVICEOBJECTREPLY_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "zigbeedeviceprofile.h"
|
||||
#include "zigbeenetworkrequest.h"
|
||||
|
||||
class ZigbeeDeviceObjectReply : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ZigbeeDeviceObject;
|
||||
|
||||
public:
|
||||
explicit ZigbeeDeviceObjectReply(QObject *parent = nullptr);
|
||||
enum Error {
|
||||
ErrorNoError, // All OK, no error occured
|
||||
ErrorTimeout, // The request timeouted
|
||||
ErrorZigbeeApsStatusError, // An APS transport error occured. See zigbeeApsStatus()
|
||||
ErrorInterfaceError, // A transport interface error occured. Could not communicate with the hardware.
|
||||
ErrorNetworkOffline // The network is offline. Cannot send any requests
|
||||
};
|
||||
Q_ENUM(Error)
|
||||
|
||||
Error error() const;
|
||||
|
||||
ZigbeeNetworkRequest request() const;
|
||||
quint8 transactionSequenceNumber() const;
|
||||
ZigbeeDeviceProfile::ZdoCommand expectedResponse() const;
|
||||
|
||||
QByteArray responseData() const;
|
||||
ZigbeeDeviceProfile::Adpu responseAdpu() const;
|
||||
|
||||
Zigbee::ZigbeeApsStatus zigbeeApsStatus() const;
|
||||
|
||||
bool isComplete() const;
|
||||
|
||||
private:
|
||||
explicit ZigbeeDeviceObjectReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr);
|
||||
|
||||
Error m_error = ErrorNoError;
|
||||
|
||||
// Request information
|
||||
ZigbeeNetworkRequest m_request;
|
||||
quint8 m_transactionSequenceNumber = 0;
|
||||
|
||||
// APS transport
|
||||
bool m_apsConfirmReceived = false;
|
||||
Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess;
|
||||
|
||||
// ZDP response data
|
||||
bool m_zdpIndicationReceived = false;
|
||||
ZigbeeDeviceProfile::ZdoCommand m_expectedResponse;
|
||||
QByteArray m_responseData;
|
||||
ZigbeeDeviceProfile::Adpu m_responseAdpu;
|
||||
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -30,22 +30,22 @@
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
ZigbeeDeviceProfileAdpu ZigbeeDeviceProfile::parseAdpu(const QByteArray &adpu)
|
||||
ZigbeeDeviceProfile::Adpu ZigbeeDeviceProfile::parseAdpu(const QByteArray &adpu)
|
||||
{
|
||||
QDataStream stream(adpu);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
ZigbeeDeviceProfileAdpu deviceAdpu;
|
||||
ZigbeeDeviceProfile::Adpu deviceAdpu;
|
||||
quint8 statusFlag = 0;
|
||||
stream >> deviceAdpu.sequenceNumber >> statusFlag >> deviceAdpu.addressOfInterest;
|
||||
deviceAdpu.status = static_cast<Zigbee::ZigbeeStatus>(statusFlag);
|
||||
stream >> deviceAdpu.transactionSequenceNumber >> statusFlag >> deviceAdpu.addressOfInterest;
|
||||
deviceAdpu.status = static_cast<ZigbeeDeviceProfile::Status>(statusFlag);
|
||||
deviceAdpu.payload = adpu.right(adpu.length() - 4);
|
||||
return deviceAdpu;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfileAdpu &deviceAdpu)
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::Adpu &deviceAdpu)
|
||||
{
|
||||
debug.nospace() << "DeviceAdpu(SQN: " << deviceAdpu.sequenceNumber << ", ";
|
||||
debug.nospace() << "DeviceAdpu(SQN: " << deviceAdpu.transactionSequenceNumber << ", ";
|
||||
debug.nospace() << deviceAdpu.status << ", ";
|
||||
debug.nospace() << ZigbeeUtils::convertUint16ToHexString(deviceAdpu.addressOfInterest) << ", ";
|
||||
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(deviceAdpu.payload) << ")";
|
||||
|
||||
@ -33,13 +33,6 @@
|
||||
|
||||
#include "zigbee.h"
|
||||
|
||||
typedef struct ZigbeeDeviceProfileAdpu {
|
||||
quint8 sequenceNumber = 0;
|
||||
Zigbee::ZigbeeStatus status = Zigbee::ZigbeeStatusSuccess;
|
||||
quint16 addressOfInterest = 0;
|
||||
QByteArray payload;
|
||||
} ZigbeeDeviceProfileAdpu;
|
||||
|
||||
class ZigbeeDeviceProfile
|
||||
{
|
||||
Q_GADGET
|
||||
@ -47,8 +40,20 @@ class ZigbeeDeviceProfile
|
||||
public:
|
||||
enum Status {
|
||||
StatusSuccess = 0x00,
|
||||
StatusInvalidRequestType = 0x01,
|
||||
StatusDeviceNotFound = 0x02
|
||||
StatusInvalidRequestType = 0x80,
|
||||
StatusDeviceNotFound = 0x81,
|
||||
StatusInvalidEndpoint = 0x82,
|
||||
StatusNotActive = 0x83,
|
||||
StatusNotSupported = 0x84,
|
||||
StatusTimeout = 0x85,
|
||||
StatusNoMatch = 0x86,
|
||||
StatusNoEntry = 0x88,
|
||||
StatusNoDescriptor = 0x89,
|
||||
StatusInsufficientSpace = 0x8a,
|
||||
StatusNotPermitted = 0x8b,
|
||||
StatusTableFull = 0x8c,
|
||||
StatusNotAuthorized = 0x8d,
|
||||
StatusDeviceBindingTableFull = 0x8e
|
||||
};
|
||||
Q_ENUM(Status)
|
||||
|
||||
@ -154,9 +159,23 @@ public:
|
||||
};
|
||||
Q_ENUM(ZdoCommand)
|
||||
|
||||
static ZigbeeDeviceProfileAdpu parseAdpu(const QByteArray &adpu);
|
||||
// For sending
|
||||
typedef struct Frame {
|
||||
quint8 transactionSequenceNumber = 0;
|
||||
QByteArray payload;
|
||||
} Frame;
|
||||
|
||||
// Receiving
|
||||
typedef struct Adpu {
|
||||
quint8 transactionSequenceNumber = 0;
|
||||
ZigbeeDeviceProfile::Status status = ZigbeeDeviceProfile::StatusSuccess;
|
||||
quint16 addressOfInterest = 0;
|
||||
QByteArray payload;
|
||||
} Adpu;
|
||||
|
||||
static ZigbeeDeviceProfile::Adpu parseAdpu(const QByteArray &adpu);
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfileAdpu &deviceAdpu);
|
||||
QDebug operator<<(QDebug debug, const ZigbeeDeviceProfile::Adpu &deviceAdpu);
|
||||
|
||||
#endif // ZIGBEEDEVICEPROFILE_H
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
#include "zigbeedeviceprofilehandler.h"
|
||||
|
||||
ZigbeeDeviceProfileHandler::ZigbeeDeviceProfileHandler(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
#ifndef ZIGBEEDEVICEPROFILEHANDLER_H
|
||||
#define ZIGBEEDEVICEPROFILEHANDLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class ZigbeeDeviceProfileHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ZigbeeDeviceProfileHandler(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
#endif // ZIGBEEDEVICEPROFILEHANDLER_H
|
||||
@ -74,210 +74,210 @@ public:
|
||||
Q_ENUM(ZigbeeChannel)
|
||||
Q_DECLARE_FLAGS(ZigbeeChannels, ZigbeeChannel)
|
||||
|
||||
enum InterfaceMessageType {
|
||||
// Common Commands
|
||||
MessageTypeNone = 0x0000,
|
||||
MessageTypeStatus = 0x8000,
|
||||
MessageTypeLogging = 0x8001,
|
||||
// enum InterfaceMessageType {
|
||||
// // Common Commands
|
||||
// MessageTypeNone = 0x0000,
|
||||
// MessageTypeStatus = 0x8000,
|
||||
// MessageTypeLogging = 0x8001,
|
||||
|
||||
MessageTypeDataIndication = 0x8002,
|
||||
// MessageTypeDataIndication = 0x8002,
|
||||
|
||||
MessageTypeNodeClusterList = 0x8003,
|
||||
MessageTypeNodeAttributeList = 0x8004,
|
||||
MessageTypeNodeCommandIdList = 0x8005,
|
||||
MessageTypeRestartProvisioned = 0x8006,
|
||||
MessageTypeFactoryNewRestart = 0x8007,
|
||||
MessageTypeGetVersion = 0x0010,
|
||||
MessageTypeVersionList = 0x8010,
|
||||
// MessageTypeNodeClusterList = 0x8003,
|
||||
// MessageTypeNodeAttributeList = 0x8004,
|
||||
// MessageTypeNodeCommandIdList = 0x8005,
|
||||
// MessageTypeRestartProvisioned = 0x8006,
|
||||
// MessageTypeFactoryNewRestart = 0x8007,
|
||||
// MessageTypeGetVersion = 0x0010,
|
||||
// MessageTypeVersionList = 0x8010,
|
||||
|
||||
MessageTypeSetExtendetPanId = 0x0020,
|
||||
MessageTypeSetChannelMask = 0x0021,
|
||||
MessageTypeSetSecurity = 0x0022,
|
||||
MessageTypeSetDeviceType = 0x0023,
|
||||
MessageTypeStartNetwork = 0x0024,
|
||||
MessageTypeStartScan = 0x0025,
|
||||
MessageTypeNetworkJoinedFormed = 0x8024,
|
||||
MessageTypeNetworkRemoveDevice = 0x0026,
|
||||
MessageTypeNetworkWhitelistEnable = 0x0027,
|
||||
MessageTypeAuthenticateDeviceRequest = 0x0028,
|
||||
MessageTypeAuthenticateDeviceResponse = 0x8028,
|
||||
MessageTypeOutOfBandCommisioningDataRequest = 0x0029,
|
||||
MessageTypeOutOfBandCommisioningDataResponse = 0x8029,
|
||||
MessageTypeUserDescriptorSet = 0x002B,
|
||||
MessageTypeUserDescriptorNotify = 0x802B,
|
||||
MessageTypeUserDescriptorRequest = 0x002C,
|
||||
MessageTypeUserDescriptorResponse = 0x802C,
|
||||
// MessageTypeSetExtendetPanId = 0x0020,
|
||||
// MessageTypeSetChannelMask = 0x0021,
|
||||
// MessageTypeSetSecurity = 0x0022,
|
||||
// MessageTypeSetDeviceType = 0x0023,
|
||||
// MessageTypeStartNetwork = 0x0024,
|
||||
// MessageTypeStartScan = 0x0025,
|
||||
// MessageTypeNetworkJoinedFormed = 0x8024,
|
||||
// MessageTypeNetworkRemoveDevice = 0x0026,
|
||||
// MessageTypeNetworkWhitelistEnable = 0x0027,
|
||||
// MessageTypeAuthenticateDeviceRequest = 0x0028,
|
||||
// MessageTypeAuthenticateDeviceResponse = 0x8028,
|
||||
// MessageTypeOutOfBandCommisioningDataRequest = 0x0029,
|
||||
// MessageTypeOutOfBandCommisioningDataResponse = 0x8029,
|
||||
// MessageTypeUserDescriptorSet = 0x002B,
|
||||
// MessageTypeUserDescriptorNotify = 0x802B,
|
||||
// MessageTypeUserDescriptorRequest = 0x002C,
|
||||
// MessageTypeUserDescriptorResponse = 0x802C,
|
||||
|
||||
MessageTypeReset = 0x0011,
|
||||
MessageTypeErasePersistentData = 0x0012,
|
||||
MessageTypeZllFactoryNew = 0x0013,
|
||||
MessageTypeGetPermitJoining = 0x0014,
|
||||
MessageTypeGetPermitJoiningResponse = 0x8014,
|
||||
MessageTypeBind = 0x0030,
|
||||
MessageTypeBindResponse = 0x8030,
|
||||
MessageTypeUnbind = 0x0031,
|
||||
MessageTypeBindGroup = 0x0032,
|
||||
MessageTypeBindGroupResponse = 0x8032,
|
||||
MessageTypeUnbindGroup = 0x0033,
|
||||
MessageTypeUnbindGroupResponse = 0x8033,
|
||||
// MessageTypeReset = 0x0011,
|
||||
// MessageTypeErasePersistentData = 0x0012,
|
||||
// MessageTypeZllFactoryNew = 0x0013,
|
||||
// MessageTypeGetPermitJoining = 0x0014,
|
||||
// MessageTypeGetPermitJoiningResponse = 0x8014,
|
||||
// MessageTypeBind = 0x0030,
|
||||
// MessageTypeBindResponse = 0x8030,
|
||||
// MessageTypeUnbind = 0x0031,
|
||||
// MessageTypeBindGroup = 0x0032,
|
||||
// MessageTypeBindGroupResponse = 0x8032,
|
||||
// MessageTypeUnbindGroup = 0x0033,
|
||||
// MessageTypeUnbindGroupResponse = 0x8033,
|
||||
|
||||
MessageTypeUnbindResponse = 0x8031,
|
||||
MessageTypeComplexDescriptorRequest = 0x0034,
|
||||
MessageTypeComplexDescriptorResponse = 0x8034,
|
||||
// MessageTypeUnbindResponse = 0x8031,
|
||||
// MessageTypeComplexDescriptorRequest = 0x0034,
|
||||
// MessageTypeComplexDescriptorResponse = 0x8034,
|
||||
|
||||
MessageTypeNetworkAdressRequest = 0x0040,
|
||||
MessageTypeNetworkAdressResponse = 0x8040,
|
||||
MessageTypeIeeeAddressResponse = 0x0041,
|
||||
MessageTypeIeeeAddressRequest = 0x8041,
|
||||
MessageTypeNodeDescriptorRequest = 0x0042,
|
||||
MessageTypeNodeDescriptorRsponse = 0x8042,
|
||||
MessageTypeSimpleDescriptorRequest = 0x0043,
|
||||
MessageTypeSimpleDescriptorResponse = 0x8043,
|
||||
MessageTypePowerDescriptorRequest = 0x0044,
|
||||
MessageTypePowerDescriptorResponse = 0x8044,
|
||||
MessageTypeActiveEndpointRequest = 0x0045,
|
||||
MessageTypeActiveEndpointResponse = 0x8045,
|
||||
MessageTypeMatchDescriptorRequest = 0x0046,
|
||||
MessageTypeMatchDescriptorResponse = 0x8046,
|
||||
MessageTypeManagementLeaveRequest = 0x0047,
|
||||
MessageTypeManagementLeaveResponse = 0x8047,
|
||||
MessageTypeLeaveIndication = 0x8048,
|
||||
MessageTypePermitJoiningRequest = 0x0049,
|
||||
MessageTypeManagementNetworkUpdateRequest = 0x004A,
|
||||
MessageTypeManagementNetworkUpdateResponse = 0x804A,
|
||||
MessageTypeSystemServerDiscoveryRequest = 0x004B,
|
||||
MessageTypeSystemServerDiscoveryResponse = 0x804B,
|
||||
MessageTypeDeviceAnnounce = 0x004D,
|
||||
MessageTypeManagementLqiRequest = 0x004E,
|
||||
MessageTypeManagementLqiResponse = 0x804E,
|
||||
// MessageTypeNetworkAdressRequest = 0x0040,
|
||||
// MessageTypeNetworkAdressResponse = 0x8040,
|
||||
// MessageTypeIeeeAddressResponse = 0x0041,
|
||||
// MessageTypeIeeeAddressRequest = 0x8041,
|
||||
// MessageTypeNodeDescriptorRequest = 0x0042,
|
||||
// MessageTypeNodeDescriptorRsponse = 0x8042,
|
||||
// MessageTypeSimpleDescriptorRequest = 0x0043,
|
||||
// MessageTypeSimpleDescriptorResponse = 0x8043,
|
||||
// MessageTypePowerDescriptorRequest = 0x0044,
|
||||
// MessageTypePowerDescriptorResponse = 0x8044,
|
||||
// MessageTypeActiveEndpointRequest = 0x0045,
|
||||
// MessageTypeActiveEndpointResponse = 0x8045,
|
||||
// MessageTypeMatchDescriptorRequest = 0x0046,
|
||||
// MessageTypeMatchDescriptorResponse = 0x8046,
|
||||
// MessageTypeManagementLeaveRequest = 0x0047,
|
||||
// MessageTypeManagementLeaveResponse = 0x8047,
|
||||
// MessageTypeLeaveIndication = 0x8048,
|
||||
// MessageTypePermitJoiningRequest = 0x0049,
|
||||
// MessageTypeManagementNetworkUpdateRequest = 0x004A,
|
||||
// MessageTypeManagementNetworkUpdateResponse = 0x804A,
|
||||
// MessageTypeSystemServerDiscoveryRequest = 0x004B,
|
||||
// MessageTypeSystemServerDiscoveryResponse = 0x804B,
|
||||
// MessageTypeDeviceAnnounce = 0x004D,
|
||||
// MessageTypeManagementLqiRequest = 0x004E,
|
||||
// MessageTypeManagementLqiResponse = 0x804E,
|
||||
|
||||
// Basic cluster
|
||||
MessageBasicResetFactoryDefaults = 0x0050,
|
||||
MessageBasicResetFactoryDefaultsResponse = 0x8050,
|
||||
// // Basic cluster
|
||||
// MessageBasicResetFactoryDefaults = 0x0050,
|
||||
// MessageBasicResetFactoryDefaultsResponse = 0x8050,
|
||||
|
||||
// Group Cluster
|
||||
MessageTypeAddGroupRequest = 0x0060,
|
||||
MessageTypeAddGroupResponse = 0x8060,
|
||||
MessageTypeViewGroupRequest = 0x0061,
|
||||
MessageTypeViewGroupResponse = 0x8061,
|
||||
MessageTypeGetGroupMembershipRequest = 0x0062,
|
||||
MessageTypeGetGroupMembershipResponse = 0x8062,
|
||||
MessageTypeRemoveGroupRequest = 0x0063,
|
||||
MessageTypeRemoveGroupResponse = 0x8063,
|
||||
MessageTypeRemoveAllGroups = 0x0064,
|
||||
MessageTypeGroupIfIdentify = 0x0065,
|
||||
// // Group Cluster
|
||||
// MessageTypeAddGroupRequest = 0x0060,
|
||||
// MessageTypeAddGroupResponse = 0x8060,
|
||||
// MessageTypeViewGroupRequest = 0x0061,
|
||||
// MessageTypeViewGroupResponse = 0x8061,
|
||||
// MessageTypeGetGroupMembershipRequest = 0x0062,
|
||||
// MessageTypeGetGroupMembershipResponse = 0x8062,
|
||||
// MessageTypeRemoveGroupRequest = 0x0063,
|
||||
// MessageTypeRemoveGroupResponse = 0x8063,
|
||||
// MessageTypeRemoveAllGroups = 0x0064,
|
||||
// MessageTypeGroupIfIdentify = 0x0065,
|
||||
|
||||
// Identify Cluster
|
||||
MessageTypeIdentifySend = 0x0070,
|
||||
MessageTypeIdentifyQuery = 0x0071,
|
||||
// // Identify Cluster
|
||||
// MessageTypeIdentifySend = 0x0070,
|
||||
// MessageTypeIdentifyQuery = 0x0071,
|
||||
|
||||
// Level Cluster
|
||||
MessageTypeMoveToLevel = 0x0080,
|
||||
MessageTypeMoveToLevelOnOff = 0x0081,
|
||||
MessageTypeMoveStep = 0x0082,
|
||||
MessageTypeMoveStopMove = 0x0083,
|
||||
MessageTypeMoveStopMoveOnOff = 0x0084,
|
||||
// // Level Cluster
|
||||
// MessageTypeMoveToLevel = 0x0080,
|
||||
// MessageTypeMoveToLevelOnOff = 0x0081,
|
||||
// MessageTypeMoveStep = 0x0082,
|
||||
// MessageTypeMoveStopMove = 0x0083,
|
||||
// MessageTypeMoveStopMoveOnOff = 0x0084,
|
||||
|
||||
// Scenes Cluster
|
||||
MessageTypeViewScene = 0x00A0,
|
||||
MessageTypeViewSceneResponse = 0x80A0,
|
||||
MessageTypeAddScene = 0x00A1,
|
||||
MessageTypeAddSceneResponse = 0x80A1,
|
||||
MessageTypeRemoveScene = 0x00A2,
|
||||
MessageTypeRemoveSceneResponse = 0x80A2,
|
||||
MessageTypeRemoveAllScenes = 0x00A3,
|
||||
MessageTypeRemoveAllScenesResponse = 0x80A3,
|
||||
MessageTypeStoreScene = 0x00A4,
|
||||
MessageTypeStoreSceneResponse = 0x80A4,
|
||||
MessageTypeRecallScene = 0x00A5,
|
||||
MessageTypeSceneMembershipRequest = 0x00A6,
|
||||
MessageTypeSceneMembershipResponse = 0x80A6,
|
||||
// // Scenes Cluster
|
||||
// MessageTypeViewScene = 0x00A0,
|
||||
// MessageTypeViewSceneResponse = 0x80A0,
|
||||
// MessageTypeAddScene = 0x00A1,
|
||||
// MessageTypeAddSceneResponse = 0x80A1,
|
||||
// MessageTypeRemoveScene = 0x00A2,
|
||||
// MessageTypeRemoveSceneResponse = 0x80A2,
|
||||
// MessageTypeRemoveAllScenes = 0x00A3,
|
||||
// MessageTypeRemoveAllScenesResponse = 0x80A3,
|
||||
// MessageTypeStoreScene = 0x00A4,
|
||||
// MessageTypeStoreSceneResponse = 0x80A4,
|
||||
// MessageTypeRecallScene = 0x00A5,
|
||||
// MessageTypeSceneMembershipRequest = 0x00A6,
|
||||
// MessageTypeSceneMembershipResponse = 0x80A6,
|
||||
|
||||
//Colour Cluster
|
||||
MessageTypeMoveToHue = 0x00B0,
|
||||
MessageTypeMoveHue = 0x00B1,
|
||||
MessageTypeStepHue = 0x00B2,
|
||||
MessageTypeMoveToSaturation = 0x00B3,
|
||||
MessageTypeMoveSaturation = 0x00B4,
|
||||
MessageTypeStepStaturation = 0x00B5,
|
||||
MessageTypeMoveToHueSaturation = 0x00B6,
|
||||
MessageTypeMoveToColor = 0x00B7,
|
||||
MessageTypeMoveColor = 0x00B8,
|
||||
MessageTypeStepColor = 0x00B9,
|
||||
// //Colour Cluster
|
||||
// MessageTypeMoveToHue = 0x00B0,
|
||||
// MessageTypeMoveHue = 0x00B1,
|
||||
// MessageTypeStepHue = 0x00B2,
|
||||
// MessageTypeMoveToSaturation = 0x00B3,
|
||||
// MessageTypeMoveSaturation = 0x00B4,
|
||||
// MessageTypeStepStaturation = 0x00B5,
|
||||
// MessageTypeMoveToHueSaturation = 0x00B6,
|
||||
// MessageTypeMoveToColor = 0x00B7,
|
||||
// MessageTypeMoveColor = 0x00B8,
|
||||
// MessageTypeStepColor = 0x00B9,
|
||||
|
||||
// ZLL Commands
|
||||
// Touchlink
|
||||
MessageTypeInitiateTouchlink = 0x00D0,
|
||||
MessageTypeTouchlinkStatus = 0x00D1,
|
||||
MessageTypeTouchlinkFactoryReset = 0x00D2,
|
||||
// // ZLL Commands
|
||||
// // Touchlink
|
||||
// MessageTypeInitiateTouchlink = 0x00D0,
|
||||
// MessageTypeTouchlinkStatus = 0x00D1,
|
||||
// MessageTypeTouchlinkFactoryReset = 0x00D2,
|
||||
|
||||
// Identify Cluster
|
||||
MessageTypeIdentifyTriggerEffect = 0x00E0,
|
||||
// // Identify Cluster
|
||||
// MessageTypeIdentifyTriggerEffect = 0x00E0,
|
||||
|
||||
// On/Off Cluster
|
||||
MessageTypeCluserOnOff = 0x0092,
|
||||
MessageTypeCluserOnOffTimed = 0x0093,
|
||||
MessageTypeCluserOnOffEffects = 0x0094,
|
||||
MessageTypeCluserOnOffUpdate = 0x8095,
|
||||
// // On/Off Cluster
|
||||
// MessageTypeCluserOnOff = 0x0092,
|
||||
// MessageTypeCluserOnOffTimed = 0x0093,
|
||||
// MessageTypeCluserOnOffEffects = 0x0094,
|
||||
// MessageTypeCluserOnOffUpdate = 0x8095,
|
||||
|
||||
// Scenes Cluster
|
||||
MessageTypeAddEnhancedScene = 0x00A7,
|
||||
MessageTypeViewEnhancedScene = 0x00A8,
|
||||
MessageTypeCopyScene = 0x00A9,
|
||||
// // Scenes Cluster
|
||||
// MessageTypeAddEnhancedScene = 0x00A7,
|
||||
// MessageTypeViewEnhancedScene = 0x00A8,
|
||||
// MessageTypeCopyScene = 0x00A9,
|
||||
|
||||
// Colour Cluster
|
||||
MessageTypeEnhancedMoveToHue = 0x00BA,
|
||||
MessageTypeEnhancedMoveHue = 0x00BB,
|
||||
MessageTypeEnhancedStepHue = 0x00BC,
|
||||
MessageTypeEnhancedMoveToHueSaturation = 0x00BD,
|
||||
MessageTypeColourLoopSet = 0x00BE,
|
||||
MessageTypeStopMoveStep = 0x00BF,
|
||||
MessageTypeMoveToColorTemperature = 0x00C0,
|
||||
MessageTypeMoveColorTemperature = 0x00C1,
|
||||
MessageTypeStepColorTemperature = 0x00C2,
|
||||
// // Colour Cluster
|
||||
// MessageTypeEnhancedMoveToHue = 0x00BA,
|
||||
// MessageTypeEnhancedMoveHue = 0x00BB,
|
||||
// MessageTypeEnhancedStepHue = 0x00BC,
|
||||
// MessageTypeEnhancedMoveToHueSaturation = 0x00BD,
|
||||
// MessageTypeColourLoopSet = 0x00BE,
|
||||
// MessageTypeStopMoveStep = 0x00BF,
|
||||
// MessageTypeMoveToColorTemperature = 0x00C0,
|
||||
// MessageTypeMoveColorTemperature = 0x00C1,
|
||||
// MessageTypeStepColorTemperature = 0x00C2,
|
||||
|
||||
// ZHA Commands
|
||||
// Door Lock Cluster
|
||||
MessageTypeLockUnlockDoor = 0x00F0,
|
||||
// // ZHA Commands
|
||||
// // Door Lock Cluster
|
||||
// MessageTypeLockUnlockDoor = 0x00F0,
|
||||
|
||||
// Attributes
|
||||
MessageTypeReadAttributeRequest = 0x0100,
|
||||
MessageTypeReadAttributeResponse = 0x8100,
|
||||
MessageTypeDefaultResponse = 0x8101,
|
||||
MessageTypeAttributeReport = 0x8102,
|
||||
MessageTypeWriteAttributeRequest = 0x0110,
|
||||
MessageTypeWriteAttributeResponse = 0x8110,
|
||||
MessageTypeConfigReportingRequest = 0x0120,
|
||||
MessageTypeConfigReportingResponse = 0x8120,
|
||||
MessageTypeReportAttributes = 0x8121,
|
||||
MessageTypeAttributeDiscoveryRequest = 0x0140,
|
||||
MessageTypeAttributeDiscoveryResponse = 0x8140,
|
||||
// // Attributes
|
||||
// MessageTypeReadAttributeRequest = 0x0100,
|
||||
// MessageTypeReadAttributeResponse = 0x8100,
|
||||
// MessageTypeDefaultResponse = 0x8101,
|
||||
// MessageTypeAttributeReport = 0x8102,
|
||||
// MessageTypeWriteAttributeRequest = 0x0110,
|
||||
// MessageTypeWriteAttributeResponse = 0x8110,
|
||||
// MessageTypeConfigReportingRequest = 0x0120,
|
||||
// MessageTypeConfigReportingResponse = 0x8120,
|
||||
// MessageTypeReportAttributes = 0x8121,
|
||||
// MessageTypeAttributeDiscoveryRequest = 0x0140,
|
||||
// MessageTypeAttributeDiscoveryResponse = 0x8140,
|
||||
|
||||
// Persistant data manager messages
|
||||
MessageTypeDataManagerAvailableRequest = 0x0300,
|
||||
MessageTypeDataManagerAvailableResponse = 0x8300,
|
||||
MessageTypeDataManagerSaveRecordRequest = 0x0200,
|
||||
MessageTypeDataManagerSaveRecordResponse = 0x8200,
|
||||
MessageTypeDataManagerLoadRecordRequest = 0x0201,
|
||||
MessageTypeDataManagerLoadRecordResponse = 0x8201,
|
||||
MessageTypeDataManagerDeleteAllRecordsRequest = 0x0202,
|
||||
MessageTypeDataManagerDeleteAllRecordsResponse = 0x8202,
|
||||
// // Persistant data manager messages
|
||||
// MessageTypeDataManagerAvailableRequest = 0x0300,
|
||||
// MessageTypeDataManagerAvailableResponse = 0x8300,
|
||||
// MessageTypeDataManagerSaveRecordRequest = 0x0200,
|
||||
// MessageTypeDataManagerSaveRecordResponse = 0x8200,
|
||||
// MessageTypeDataManagerLoadRecordRequest = 0x0201,
|
||||
// MessageTypeDataManagerLoadRecordResponse = 0x8201,
|
||||
// MessageTypeDataManagerDeleteAllRecordsRequest = 0x0202,
|
||||
// MessageTypeDataManagerDeleteAllRecordsResponse = 0x8202,
|
||||
|
||||
// Appliance Statistics Cluster 0x0B03
|
||||
// http://www.nxp.com/documents/user_manual/JN-UG-3076.pdf
|
||||
MessageTypeStatisticsClusterLogMessage = 0x0301, // Was 0x0500, was 0x0301
|
||||
MessageTypeStatisticsClusterLogMessageResponse = 0x8301,
|
||||
// // Appliance Statistics Cluster 0x0B03
|
||||
// // http://www.nxp.com/documents/user_manual/JN-UG-3076.pdf
|
||||
// MessageTypeStatisticsClusterLogMessage = 0x0301, // Was 0x0500, was 0x0301
|
||||
// MessageTypeStatisticsClusterLogMessageResponse = 0x8301,
|
||||
|
||||
// IAS Cluster
|
||||
MessageTypeSendIasZoneEnroolResponse = 0x0400,
|
||||
MessageTypeIasZoneStatusChangeNotify = 0x8401,
|
||||
// // IAS Cluster
|
||||
// MessageTypeSendIasZoneEnroolResponse = 0x0400,
|
||||
// MessageTypeIasZoneStatusChangeNotify = 0x8401,
|
||||
|
||||
// Extended utils
|
||||
MessageTypeRawApsDataRequest = 0x0530,
|
||||
MessageTypeRouterDiscoveryConfirm = 0x8701,
|
||||
MessageTypeApsDataConfirmFail = 0x8702
|
||||
};
|
||||
Q_ENUM(InterfaceMessageType)
|
||||
// // Extended utils
|
||||
// MessageTypeRawApsDataRequest = 0x0530,
|
||||
// MessageTypeRouterDiscoveryConfirm = 0x8701,
|
||||
// MessageTypeApsDataConfirmFail = 0x8702
|
||||
// };
|
||||
// Q_ENUM(InterfaceMessageType)
|
||||
|
||||
|
||||
enum ClusterId {
|
||||
@ -616,6 +616,28 @@ public:
|
||||
};
|
||||
Q_ENUM(ZigbeeNwkLayerStatus)
|
||||
|
||||
enum ZigbeeApsStatus {
|
||||
ZigbeeApsStatusSuccess = 0x00,
|
||||
ZigbeeApsStatusAsduTooLong = 0xa0,
|
||||
ZigbeeApsStatusDefragDeferred = 0xa1,
|
||||
ZigbeeApsStatusDefragUnsupported = 0xa2,
|
||||
ZigbeeApsStatusIllegalRequest = 0xa3,
|
||||
ZigbeeApsStatusInvalidBinding = 0xa4,
|
||||
ZigbeeApsStatusInvalidGroup = 0xa5,
|
||||
ZigbeeApsStatusInvalidParameter = 0xa6,
|
||||
ZigbeeApsStatusNoAck = 0xa7,
|
||||
ZigbeeApsStatusNoBoundDevice = 0xa8,
|
||||
ZigbeeApsStatusNoShortAddress = 0xa9,
|
||||
ZigbeeApsStatusNotSupported = 0xaa,
|
||||
ZigbeeApsStatusSecuredLinkKey = 0xab,
|
||||
ZigbeeApsStatusSecuredNwkKey = 0xac,
|
||||
ZigbeeApsStatusSecurityFail = 0xad,
|
||||
ZigbeeApsStatusTableFull = 0xae,
|
||||
ZigbeeApsStatusUnsecured = 0xaf,
|
||||
ZigbeeApsStatusUnsupportedAttribute = 0xb0
|
||||
};
|
||||
Q_ENUM(ZigbeeApsStatus)
|
||||
|
||||
enum ZigbeeStatus {
|
||||
ZigbeeStatusSuccess = 0x00,
|
||||
ZigbeeStatusFailure = 0x01,
|
||||
|
||||
@ -81,10 +81,8 @@ private:
|
||||
FrameControl m_frameControl;
|
||||
quint8 m_destinationEndpoint;
|
||||
|
||||
|
||||
quint8 buildFrameControlByte(FrameControl frameControl);
|
||||
FrameControl readFrameControlByte(quint8 frameControlByte);
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -34,11 +34,6 @@
|
||||
ZigbeeNetwork::ZigbeeNetwork(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), "zigbee");
|
||||
m_db.setDatabaseName("");
|
||||
qCDebug(dcZigbeeNetwork()) << "Opening zigbee network database" << m_db.databaseName();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -269,6 +264,18 @@ void ZigbeeNetwork::removeNodeInternally(ZigbeeNode *node)
|
||||
node->deleteLater();
|
||||
}
|
||||
|
||||
ZigbeeNode *ZigbeeNetwork::createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent)
|
||||
{
|
||||
return new ZigbeeNode(this, shortAddress, extendedAddress, parent);
|
||||
}
|
||||
|
||||
ZigbeeNode *ZigbeeNetwork::createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, quint8 macCapabilities, QObject *parent)
|
||||
{
|
||||
ZigbeeNode *node = createNode(shortAddress, extendedAddress, parent);
|
||||
node->setMacCapabilitiesFlag(macCapabilities);
|
||||
return node;
|
||||
}
|
||||
|
||||
void ZigbeeNetwork::saveNetwork()
|
||||
{
|
||||
qCDebug(dcZigbeeNetwork()) << "Save current network configuration to" << m_settingsFileName;
|
||||
@ -308,10 +315,8 @@ void ZigbeeNetwork::loadNetwork()
|
||||
settings.beginGroup("Nodes");
|
||||
foreach (const QString ieeeAddressString, settings.childGroups()) {
|
||||
settings.beginGroup(ieeeAddressString);
|
||||
|
||||
ZigbeeNode *node = createNode(this);
|
||||
node->setExtendedAddress(ZigbeeAddress(ieeeAddressString));
|
||||
node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt()));
|
||||
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());
|
||||
@ -334,7 +339,7 @@ void ZigbeeNetwork::loadNetwork()
|
||||
for (int i = 0; i < endpointsCount; i++) {
|
||||
settings.setArrayIndex(i);
|
||||
quint8 endpointId = static_cast<quint8>(settings.value("id", 0).toUInt());
|
||||
ZigbeeNodeEndpoint *endpoint = node->createNodeEndpoint(endpointId, node);
|
||||
ZigbeeNodeEndpoint *endpoint = new ZigbeeNodeEndpoint(this, node, endpointId, node);
|
||||
endpoint->m_profile = static_cast<Zigbee::ZigbeeProfile>(settings.value("profile", 0).toUInt());
|
||||
endpoint->m_deviceId = static_cast<quint16>(settings.value("deviceId", 0).toUInt());
|
||||
endpoint->m_deviceVersion = static_cast<quint8>(settings.value("deviceId", 0).toUInt());
|
||||
@ -542,29 +547,14 @@ ZigbeeNetworkReply *ZigbeeNetwork::createNetworkReply(const ZigbeeNetworkRequest
|
||||
return reply;
|
||||
}
|
||||
|
||||
void ZigbeeNetwork::setReplyResponseData(ZigbeeNetworkReply *reply, const QByteArray &responseData)
|
||||
void ZigbeeNetwork::setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeApsStatus zigbeeApsStatus)
|
||||
{
|
||||
reply->m_responseData = responseData;
|
||||
if (reply->isComplete()) {
|
||||
if (reply->m_zigbeeStatus == Zigbee::ZigbeeStatusSuccess) {
|
||||
finishNetworkReply(reply);
|
||||
} else {
|
||||
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeStatusError);
|
||||
}
|
||||
}
|
||||
}
|
||||
reply->m_zigbeeApsStatus = zigbeeApsStatus;
|
||||
|
||||
void ZigbeeNetwork::setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeStatus zigbeeStatus)
|
||||
{
|
||||
reply->m_zigbeeStatus = zigbeeStatus;
|
||||
reply->m_zigbeeConfirmArrived = true;
|
||||
|
||||
if (reply->isComplete()) {
|
||||
if (reply->m_zigbeeStatus == Zigbee::ZigbeeStatusSuccess) {
|
||||
finishNetworkReply(reply);
|
||||
} else {
|
||||
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeStatusError);
|
||||
}
|
||||
if (reply->m_zigbeeApsStatus == Zigbee::ZigbeeApsStatusSuccess) {
|
||||
finishNetworkReply(reply);
|
||||
} else {
|
||||
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeApsStatusError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include <QSqlDatabase>
|
||||
|
||||
#include "zigbeenode.h"
|
||||
#include "zigbeenodeendpoint.h"
|
||||
#include "zigbeechannelmask.h"
|
||||
#include "zigbeebridgecontroller.h"
|
||||
#include "zigbeesecurityconfiguration.h"
|
||||
@ -134,11 +135,7 @@ private:
|
||||
QList<ZigbeeNode *> m_nodes;
|
||||
QList<ZigbeeNode *> m_uninitializedNodes;
|
||||
|
||||
QSqlDatabase m_db;
|
||||
|
||||
private:
|
||||
bool initDB();
|
||||
|
||||
void addNodeInternally(ZigbeeNode *node);
|
||||
void removeNodeInternally(ZigbeeNode *node);
|
||||
|
||||
@ -148,7 +145,8 @@ protected:
|
||||
bool m_permitJoining = false;
|
||||
ZigbeeSecurityConfiguration m_securityConfiguration;
|
||||
|
||||
virtual ZigbeeNode *createNode(QObject *parent) = 0;
|
||||
ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent);
|
||||
ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, quint8 macCapabilities, QObject *parent);
|
||||
virtual void setPermitJoiningInternal(bool permitJoining) = 0;
|
||||
|
||||
void saveNetwork();
|
||||
@ -169,8 +167,7 @@ protected:
|
||||
|
||||
// Network reply methods
|
||||
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
|
||||
void setReplyResponseData(ZigbeeNetworkReply *reply, const QByteArray &responseData);
|
||||
void setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeStatus zigbeeStatus = Zigbee::ZigbeeStatusSuccess);
|
||||
void setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeApsStatus zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess);
|
||||
void finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error = ZigbeeNetworkReply::ErrorNoError);
|
||||
|
||||
signals:
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#include "zigbeenetworkmanager.h"
|
||||
#include "loggingcategory.h"
|
||||
|
||||
#include "nxp/zigbeenetworknxp.h"
|
||||
#include "deconz/zigbeenetworkdeconz.h"
|
||||
|
||||
#include <QDateTime>
|
||||
@ -39,8 +38,8 @@ ZigbeeNetwork *ZigbeeNetworkManager::createZigbeeNetwork(ZigbeeNetworkManager::B
|
||||
srand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
|
||||
|
||||
switch (backend) {
|
||||
case BackendTypeNxp:
|
||||
return qobject_cast<ZigbeeNetwork *>(new ZigbeeNetworkNxp(parent));
|
||||
// case BackendTypeNxp:
|
||||
// return qobject_cast<ZigbeeNetwork *>(new ZigbeeNetworkNxp(parent));
|
||||
case BackendTypeDeconz:
|
||||
return qobject_cast<ZigbeeNetwork *>(new ZigbeeNetworkDeconz(parent));
|
||||
}
|
||||
|
||||
@ -36,7 +36,6 @@ class ZigbeeNetworkManager
|
||||
{
|
||||
public:
|
||||
enum BackendType {
|
||||
BackendTypeNxp,
|
||||
BackendTypeDeconz
|
||||
};
|
||||
|
||||
|
||||
@ -37,34 +37,9 @@ ZigbeeNetworkRequest ZigbeeNetworkReply::request() const
|
||||
return m_request;
|
||||
}
|
||||
|
||||
Zigbee::ZigbeeStatus ZigbeeNetworkReply::zigbeeStatus() const
|
||||
Zigbee::ZigbeeApsStatus ZigbeeNetworkReply::zigbeeApsStatus() const
|
||||
{
|
||||
return m_zigbeeStatus;
|
||||
}
|
||||
|
||||
QByteArray ZigbeeNetworkReply::responseData() const
|
||||
{
|
||||
return m_responseData;
|
||||
}
|
||||
|
||||
bool ZigbeeNetworkReply::isComplete() const
|
||||
{
|
||||
// If we expect indication and confirmation
|
||||
if (m_request.expectConfirmation() && m_request.expectIndication()) {
|
||||
if (m_zigbeeConfirmArrived && !m_responseData.isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we expect only a confirmation
|
||||
if (m_request.expectConfirmation() && !m_request.expectIndication()) {
|
||||
return m_zigbeeConfirmArrived;
|
||||
}
|
||||
|
||||
// If we don't expect any response...
|
||||
return true;
|
||||
return m_zigbeeApsStatus;
|
||||
}
|
||||
|
||||
ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent) :
|
||||
|
||||
@ -43,30 +43,23 @@ class ZigbeeNetworkReply : public QObject
|
||||
public:
|
||||
enum Error {
|
||||
ErrorNoError,
|
||||
ErrorZigbeeStatusError,
|
||||
ErrorZigbeeApsStatusError,
|
||||
ErrorInterfaceError,
|
||||
ErrorNetworkOffline,
|
||||
ErrorNetworkNotImplemented,
|
||||
ErrorUnknown
|
||||
ErrorNetworkOffline
|
||||
};
|
||||
Q_ENUM(Error)
|
||||
|
||||
Error error() const;
|
||||
ZigbeeNetworkRequest request() const;
|
||||
Zigbee::ZigbeeStatus zigbeeStatus() const;
|
||||
QByteArray responseData() const;
|
||||
|
||||
bool isComplete() const;
|
||||
ZigbeeNetworkRequest request() const;
|
||||
Zigbee::ZigbeeApsStatus zigbeeApsStatus() const;
|
||||
|
||||
private:
|
||||
explicit ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr);
|
||||
ZigbeeNetworkRequest m_request;
|
||||
|
||||
bool m_finished = false;
|
||||
Error m_error = ErrorNoError;
|
||||
bool m_zigbeeConfirmArrived = false;
|
||||
Zigbee::ZigbeeStatus m_zigbeeStatus = Zigbee::ZigbeeStatusSuccess;
|
||||
QByteArray m_responseData;
|
||||
Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess;
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
@ -144,26 +144,6 @@ void ZigbeeNetworkRequest::setRadius(quint8 radius)
|
||||
m_radius = radius;
|
||||
}
|
||||
|
||||
bool ZigbeeNetworkRequest::expectIndication() const
|
||||
{
|
||||
return m_expectIndication;
|
||||
}
|
||||
|
||||
void ZigbeeNetworkRequest::setExpectIndication(bool expectIndication)
|
||||
{
|
||||
m_expectIndication = expectIndication;
|
||||
}
|
||||
|
||||
bool ZigbeeNetworkRequest::expectConfirmation() const
|
||||
{
|
||||
return m_expectConfirmation;
|
||||
}
|
||||
|
||||
void ZigbeeNetworkRequest::setExpectConfirmation(bool expectConfirmation)
|
||||
{
|
||||
m_expectConfirmation = expectConfirmation;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeNetworkRequest &request)
|
||||
{
|
||||
debug.nospace() << "Request(ID:" << request.requestId() << ", ";
|
||||
@ -187,7 +167,7 @@ QDebug operator<<(QDebug debug, const ZigbeeNetworkRequest &request)
|
||||
debug.nospace() << "Source EP:" << ZigbeeUtils::convertByteToHexString(request.sourceEndpoint()) << ", ";
|
||||
debug.nospace() << "Radius:" << request.radius() << ", ";
|
||||
debug.nospace() << request.txOptions() << ", ";
|
||||
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(request.asdu()) << ", ";
|
||||
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(request.asdu());
|
||||
debug.nospace() << ")";
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
@ -72,13 +72,6 @@ public:
|
||||
quint8 radius() const;
|
||||
void setRadius(quint8 radius);
|
||||
|
||||
// Response expectations
|
||||
bool expectIndication() const;
|
||||
void setExpectIndication(bool expectIndication);
|
||||
|
||||
bool expectConfirmation() const;
|
||||
void setExpectConfirmation(bool expectConfirmation);
|
||||
|
||||
private:
|
||||
quint8 m_requestId = 0;
|
||||
Zigbee::DestinationAddressMode m_destinationAddressMode = Zigbee::DestinationAddressModeShortAddress;
|
||||
@ -92,8 +85,6 @@ private:
|
||||
Zigbee::ZigbeeTxOptions m_txOptions = Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission);
|
||||
quint8 m_radius = 0;
|
||||
|
||||
bool m_expectIndication = false;
|
||||
bool m_expectConfirmation = true;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug debug, const ZigbeeNetworkRequest &request);
|
||||
|
||||
@ -32,11 +32,13 @@
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
ZigbeeNode::ZigbeeNode(ZigbeeNetwork *network, QObject *parent) :
|
||||
ZigbeeNode::ZigbeeNode(ZigbeeNetwork *network, quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_network(network)
|
||||
m_network(network),
|
||||
m_shortAddress(shortAddress),
|
||||
m_extendedAddress(extendedAddress)
|
||||
{
|
||||
m_deviceObject = new ZigbeeDeviceObject(m_network, this);
|
||||
m_deviceObject = new ZigbeeDeviceObject(m_network, this, this);
|
||||
}
|
||||
|
||||
ZigbeeNode::State ZigbeeNode::state() const
|
||||
@ -230,7 +232,7 @@ void ZigbeeNode::setState(ZigbeeNode::State state)
|
||||
if (m_state == state)
|
||||
return;
|
||||
|
||||
qCDebug(dcZigbeeNode()) << "State changed" << state;
|
||||
qCDebug(dcZigbeeNode()) << "State changed" << this << state;
|
||||
m_state = state;
|
||||
emit stateChanged(m_state);
|
||||
}
|
||||
@ -240,7 +242,7 @@ void ZigbeeNode::setConnected(bool connected)
|
||||
if (m_connected == connected)
|
||||
return;
|
||||
|
||||
qCDebug(dcZigbeeNode()) << "Connected changed" << connected;
|
||||
qCDebug(dcZigbeeNode()) << "Connected changed" << this << connected;
|
||||
m_connected = connected;
|
||||
emit connectedChanged(m_connected);
|
||||
}
|
||||
@ -410,10 +412,10 @@ void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag)
|
||||
}
|
||||
|
||||
// Bit 4 - 7 Available power sources
|
||||
// Bit 0: Permanent mains supply
|
||||
// Bit 1: Rechargeable battery
|
||||
// Bit 2: Disposable battery
|
||||
// Bit 4: Reserved
|
||||
// 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)) {
|
||||
@ -450,19 +452,293 @@ void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag)
|
||||
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;
|
||||
// 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()
|
||||
{
|
||||
qCWarning(dcZigbeeNode()) << "Start initialization is not implemented for this backend.";
|
||||
setState(StateInitializing);
|
||||
|
||||
/* Node initialisation steps (sequentially)
|
||||
* - Node descriptor
|
||||
* - Power descriptor
|
||||
* - Active endpoints
|
||||
* - for each endpoint do:
|
||||
* - Simple descriptor request
|
||||
* - for each endpoint
|
||||
* - read basic cluster
|
||||
*/
|
||||
|
||||
initNodeDescriptor();
|
||||
}
|
||||
|
||||
void ZigbeeNode::initNodeDescriptor()
|
||||
{
|
||||
ZigbeeDeviceObjectReply *reply = deviceObject()->requestNodeDescriptor();
|
||||
connect(reply, &ZigbeeDeviceObjectReply::finished, this, [this, reply](){
|
||||
if (reply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeNode()) << "Error occured during initialization of" << this << "Failed to read node descriptor" << reply->error();
|
||||
// FIXME: decide what to do, retry or stop initialization
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responseAdpu().status != ZigbeeDeviceProfile::StatusSuccess) {
|
||||
qCWarning(dcZigbeeNode()) << this << "failed to read node descriptor" << reply->responseAdpu().status;
|
||||
// FIXME: decide what to do, retry or stop initialization
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNode()) << this << "reading node descriptor finished successfully.";
|
||||
|
||||
// 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();
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNode::initPowerDescriptor()
|
||||
{
|
||||
ZigbeeDeviceObjectReply *reply = deviceObject()->requestPowerDescriptor();
|
||||
connect(reply, &ZigbeeDeviceObjectReply::finished, this, [this, reply](){
|
||||
if (reply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeNode()) << "Error occured during initialization of" << this << "Failed to read power descriptor" << reply->error();
|
||||
// FIXME: decide what to do, retry or stop initialization
|
||||
return;
|
||||
}
|
||||
|
||||
ZigbeeDeviceProfile::Adpu adpu = reply->responseAdpu();
|
||||
if (adpu.status != ZigbeeDeviceProfile::StatusSuccess) {
|
||||
qCWarning(dcZigbeeNode()) << this << "failed to read node descriptor" << adpu.status;
|
||||
// FIXME: decide what to do, retry or stop initialization
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNode()) << this << "reading power descriptor finished successfully.";
|
||||
|
||||
QDataStream stream(adpu.payload);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint16 powerDescriptorFlag = 0;
|
||||
stream >> powerDescriptorFlag;
|
||||
setPowerDescriptorFlag(powerDescriptorFlag);
|
||||
|
||||
// Continue with endpoint fetching
|
||||
initEndpoints();
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNode::initEndpoints()
|
||||
{
|
||||
ZigbeeDeviceObjectReply *reply = deviceObject()->requestActiveEndpoints();
|
||||
connect(reply, &ZigbeeDeviceObjectReply::finished, this, [this, reply](){
|
||||
if (reply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeNode()) << "Error occured during initialization of" << this << "Failed to read active endpoints" << reply->error();
|
||||
// FIXME: decide what to do, retry or stop initialization
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responseAdpu().status != ZigbeeDeviceProfile::StatusSuccess) {
|
||||
qCWarning(dcZigbeeNode()) << this << "failed to read active endpoints" << reply->responseAdpu().status;
|
||||
// FIXME: decide what to do, retry or stop initialization
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNode()) << this << "reading active endpoints finished successfully.";
|
||||
|
||||
QDataStream stream(reply->responseAdpu().payload);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint8 endpointCount = 0;
|
||||
m_uninitializedEndpoints.clear();
|
||||
stream >> endpointCount;
|
||||
for (int i = 0; i < endpointCount; i++) {
|
||||
quint8 endpoint = 0;
|
||||
stream >> endpoint;
|
||||
m_uninitializedEndpoints.append(endpoint);
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNode()) << "Endpoints (" << endpointCount << ")";
|
||||
for (int i = 0; i < m_uninitializedEndpoints.count(); i++) {
|
||||
qCDebug(dcZigbeeNode()) << " -" << ZigbeeUtils::convertByteToHexString(m_uninitializedEndpoints.at(i));
|
||||
}
|
||||
|
||||
// If there a no endpoints or all endpoints have already be initialized, continue with reading the basic cluster information
|
||||
if (m_uninitializedEndpoints.isEmpty()) {
|
||||
initBasicCluster();
|
||||
}
|
||||
|
||||
// Read simple descriptor for each uninitialized endpoint
|
||||
for (int i = 0; i < m_uninitializedEndpoints.count(); i++) {
|
||||
quint8 endpointId = m_uninitializedEndpoints.at(i);
|
||||
qCDebug(dcZigbeeNode()) << "Read simple descriptor of endpoint" << ZigbeeUtils::convertByteToHexString(endpointId);
|
||||
initEndpoint(endpointId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void ZigbeeNode::initEndpoint(quint8 endpointId)
|
||||
{
|
||||
ZigbeeDeviceObjectReply *reply = deviceObject()->requestSimpleDescriptor(endpointId);
|
||||
connect(reply, &ZigbeeDeviceObjectReply::finished, this, [this, reply, endpointId](){
|
||||
if (reply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeNode()) << "Error occured during initialization of" << this << "Failed to read simple descriptor for endpoint" << endpointId << reply->error();
|
||||
// FIXME: decide what to do, retry or stop initialization
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responseAdpu().status != ZigbeeDeviceProfile::StatusSuccess) {
|
||||
qCWarning(dcZigbeeNode()) << this << "failed to read simple descriptor from endpoint" << endpointId << reply->responseAdpu().status;
|
||||
// FIXME: decide what to do, retry or stop initialization
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNode()) << this << "reading simple descriptor for endpoint" << endpointId << "finished successfully.";
|
||||
|
||||
quint8 length = 0; quint8 endpointId = 0; quint16 profileId = 0; quint16 deviceId = 0; quint8 deviceVersion = 0;
|
||||
quint8 inputClusterCount = 0; quint8 outputClusterCount = 0;
|
||||
QList<quint16> inputClusters;
|
||||
QList<quint16> outputClusters;
|
||||
|
||||
QDataStream stream(reply->responseAdpu().payload);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream >> length >> endpointId >> profileId >> deviceId >> deviceVersion >> inputClusterCount;
|
||||
|
||||
qCDebug(dcZigbeeNode()) << "Node endpoint simple descriptor:";
|
||||
qCDebug(dcZigbeeNode()) << " Lenght:" << ZigbeeUtils::convertByteToHexString(length);
|
||||
qCDebug(dcZigbeeNode()) << " End Point:" << ZigbeeUtils::convertByteToHexString(endpointId);
|
||||
qCDebug(dcZigbeeNode()) << " Profile:" << ZigbeeUtils::profileIdToString(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
||||
if (profileId == Zigbee::ZigbeeProfileLightLink) {
|
||||
qCDebug(dcZigbeeNode()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::LightLinkDevice>(deviceId);
|
||||
} else if (profileId == Zigbee::ZigbeeProfileHomeAutomation) {
|
||||
qCDebug(dcZigbeeNode()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::HomeAutomationDevice>(deviceId);
|
||||
} else if (profileId == Zigbee::ZigbeeProfileGreenPower) {
|
||||
qCDebug(dcZigbeeNode()) << " Device ID:" << ZigbeeUtils::convertUint16ToHexString(deviceId) << static_cast<Zigbee::GreenPowerDevice>(deviceId);
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeNode()) << " Device version:" << ZigbeeUtils::convertByteToHexString(deviceVersion);
|
||||
|
||||
// Create endpoint
|
||||
ZigbeeNodeEndpoint *endpoint = nullptr;
|
||||
if (!hasEndpoint(endpointId)) {
|
||||
endpoint = new ZigbeeNodeEndpoint(m_network, this, endpointId, this);
|
||||
m_endpoints.append(endpoint);
|
||||
} else {
|
||||
endpoint = getEndpoint(endpointId);
|
||||
}
|
||||
endpoint->setProfile(static_cast<Zigbee::ZigbeeProfile>(profileId));
|
||||
endpoint->setDeviceId(deviceId);
|
||||
endpoint->setDeviceVersion(deviceVersion);
|
||||
|
||||
qCDebug(dcZigbeeNode()) << " Input clusters: (" << inputClusterCount << ")";
|
||||
for (int i = 0; i < inputClusterCount; i++) {
|
||||
quint16 clusterId = 0;
|
||||
stream >> clusterId;
|
||||
if (!endpoint->hasInputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||
endpoint->addInputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Input, endpoint));
|
||||
}
|
||||
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||
|
||||
}
|
||||
stream >> outputClusterCount;
|
||||
|
||||
qCDebug(dcZigbeeNode()) << " Output clusters: (" << outputClusterCount << ")";
|
||||
for (int i = 0; i < outputClusterCount; i++) {
|
||||
quint16 clusterId = 0;
|
||||
stream >> clusterId;
|
||||
if (!endpoint->hasOutputCluster(static_cast<Zigbee::ClusterId>(clusterId))) {
|
||||
endpoint->addOutputCluster(new ZigbeeCluster(m_network, this, endpoint, static_cast<Zigbee::ClusterId>(clusterId), ZigbeeCluster::Output, endpoint));
|
||||
}
|
||||
qCDebug(dcZigbeeNode()) << " Cluster ID:" << ZigbeeUtils::convertUint16ToHexString(clusterId) << ZigbeeUtils::clusterIdToString(static_cast<Zigbee::ClusterId>(clusterId));
|
||||
}
|
||||
|
||||
m_uninitializedEndpoints.removeAll(endpointId);
|
||||
|
||||
if (m_uninitializedEndpoints.isEmpty()) {
|
||||
|
||||
//if (m_shortAddress == 0) {
|
||||
setState(StateInitialized);
|
||||
return;
|
||||
//}
|
||||
|
||||
// Continue with the basic cluster attributes
|
||||
//initBasicCluster();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ZigbeeNode::initBasicCluster()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ZigbeeNode::onClusterAttributeChanged(const ZigbeeClusterAttribute &attribute)
|
||||
@ -511,7 +787,6 @@ QDebug operator<<(QDebug debug, ZigbeeNode *node)
|
||||
{
|
||||
debug.nospace().noquote() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress());
|
||||
debug.nospace().noquote() << ", " << node->extendedAddress().toString();
|
||||
debug.nospace().noquote() << ", " << node->nodeType();
|
||||
debug.nospace().noquote() << ")";
|
||||
return debug.space();
|
||||
}
|
||||
|
||||
@ -100,6 +100,45 @@ public:
|
||||
};
|
||||
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 = NodeTypeRouter;
|
||||
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;
|
||||
|
||||
@ -152,50 +191,11 @@ public:
|
||||
QList<PowerSource> availablePowerSources() const;
|
||||
PowerLevel powerLevel() const;
|
||||
|
||||
virtual void leaveNetworkRequest(bool rejoin = false, bool removeChildren = false) = 0;
|
||||
// This method starts the node initialization phase (read descriptors and endpoints)
|
||||
void startInitialization();
|
||||
|
||||
private:
|
||||
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;
|
||||
|
||||
protected:
|
||||
ZigbeeNode(ZigbeeNetwork *network, QObject *parent = nullptr);
|
||||
ZigbeeNode(ZigbeeNetwork *network, quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent = nullptr);
|
||||
|
||||
ZigbeeNetwork *m_network;
|
||||
ZigbeeDeviceObject *m_deviceObject = nullptr;
|
||||
@ -235,9 +235,55 @@ protected:
|
||||
quint16 powerDescriptorFlag() const;
|
||||
void setPowerDescriptorFlag(quint16 powerDescriptorFlag);
|
||||
|
||||
// This method starts the node initialization phase (read descriptors and endpoints)
|
||||
virtual void startInitialization();
|
||||
virtual ZigbeeNodeEndpoint *createNodeEndpoint(quint8 endpointId, QObject *parent) = 0;
|
||||
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
|
||||
void initNodeDescriptor();
|
||||
void initPowerDescriptor();
|
||||
void initEndpoints();
|
||||
void initEndpoint(quint8 endpointId);
|
||||
void initBasicCluster();
|
||||
|
||||
QList<quint8> m_uninitializedEndpoints;
|
||||
QList<quint16> m_uninitalizedBasicClusterAttributes;
|
||||
|
||||
|
||||
signals:
|
||||
void stateChanged(State state);
|
||||
|
||||
@ -110,8 +110,9 @@ bool ZigbeeNodeEndpoint::hasOutputCluster(Zigbee::ClusterId clusterId) const
|
||||
return m_outputClusters.keys().contains(clusterId);
|
||||
}
|
||||
|
||||
ZigbeeNodeEndpoint::ZigbeeNodeEndpoint(ZigbeeNode *node, quint8 endpointId, QObject *parent) :
|
||||
ZigbeeNodeEndpoint::ZigbeeNodeEndpoint(ZigbeeNetwork *network, ZigbeeNode *node, quint8 endpointId, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_network(network),
|
||||
m_node(node),
|
||||
m_endpointId(endpointId)
|
||||
{
|
||||
@ -163,10 +164,10 @@ ZigbeeNetworkReply *ZigbeeNodeEndpoint::createNetworkReply(const ZigbeeNetworkRe
|
||||
return reply;
|
||||
}
|
||||
|
||||
void ZigbeeNodeEndpoint::finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error, Zigbee::ZigbeeStatus zigbeeStatus)
|
||||
void ZigbeeNodeEndpoint::finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error, Zigbee::ZigbeeApsStatus zigbeeApsStatus)
|
||||
{
|
||||
reply->m_error = error;
|
||||
reply->m_zigbeeStatus = zigbeeStatus;
|
||||
reply->m_zigbeeApsStatus = zigbeeApsStatus;
|
||||
reply->finished();
|
||||
}
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include "zigbeenetworkreply.h"
|
||||
|
||||
class ZigbeeNode;
|
||||
class ZigbeeNetwork;
|
||||
|
||||
class ZigbeeNodeEndpoint : public QObject
|
||||
{
|
||||
@ -74,14 +75,15 @@ public:
|
||||
bool hasOutputCluster(Zigbee::ClusterId clusterId) const;
|
||||
|
||||
private:
|
||||
explicit ZigbeeNodeEndpoint(ZigbeeNetwork *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr);
|
||||
|
||||
ZigbeeNetwork *m_network = nullptr;
|
||||
ZigbeeNode *m_node = nullptr;
|
||||
quint8 m_endpointId = 0;
|
||||
Zigbee::ZigbeeProfile m_profile = Zigbee::ZigbeeProfileLightLink;
|
||||
quint16 m_deviceId = 0;
|
||||
quint8 m_deviceVersion = 0;
|
||||
|
||||
protected:
|
||||
explicit ZigbeeNodeEndpoint(ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr);
|
||||
|
||||
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_inputClusters;
|
||||
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_outputClusters;
|
||||
@ -95,14 +97,14 @@ protected:
|
||||
void setSoftwareBuildId(const QString &softwareBuildId);
|
||||
|
||||
// Cluster commands
|
||||
virtual void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()) = 0;
|
||||
//virtual void setClusterAttribute(Zigbee::ClusterId clusterId, const ZigbeeClusterAttribute &attribute = ZigbeeClusterAttribute()) = 0;
|
||||
|
||||
void addInputCluster(ZigbeeCluster *cluster);
|
||||
void addOutputCluster(ZigbeeCluster *cluster);
|
||||
|
||||
// Network reply methods
|
||||
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
|
||||
void finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error = ZigbeeNetworkReply::ErrorNoError, Zigbee::ZigbeeStatus zigbeeStatus = Zigbee::ZigbeeStatusSuccess);
|
||||
void finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error = ZigbeeNetworkReply::ErrorNoError, Zigbee::ZigbeeApsStatus zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess);
|
||||
|
||||
signals:
|
||||
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);
|
||||
|
||||
@ -260,15 +260,15 @@ QString ZigbeeUtils::convertUint64ToHexString(const quint64 &value)
|
||||
return QString("0x%1").arg(convertByteArrayToHexString(data).remove(" ").remove("0x"));
|
||||
}
|
||||
|
||||
QString ZigbeeUtils::messageTypeToString(const Zigbee::InterfaceMessageType &type)
|
||||
{
|
||||
QMetaObject metaObject = Zigbee::staticMetaObject;
|
||||
QMetaEnum metaEnum = metaObject.enumerator(metaObject.indexOfEnumerator("InterfaceMessageType"));
|
||||
//QString ZigbeeUtils::messageTypeToString(const Zigbee::InterfaceMessageType &type)
|
||||
//{
|
||||
// QMetaObject metaObject = Zigbee::staticMetaObject;
|
||||
// QMetaEnum metaEnum = metaObject.enumerator(metaObject.indexOfEnumerator("InterfaceMessageType"));
|
||||
|
||||
QString enumString = metaEnum.valueToKey(type);
|
||||
// QString enumString = metaEnum.valueToKey(type);
|
||||
|
||||
return enumString.remove("Zigbee::InterfaceMessageType(MessageType").remove(")");
|
||||
}
|
||||
// return enumString.remove("Zigbee::InterfaceMessageType(MessageType").remove(")");
|
||||
//}
|
||||
|
||||
QString ZigbeeUtils::clusterIdToString(const Zigbee::ClusterId &clusterId)
|
||||
{
|
||||
|
||||
@ -61,7 +61,7 @@ public:
|
||||
static QString convertUint64ToHexString(const quint64 &value);
|
||||
|
||||
// Enum prittify print methods
|
||||
static QString messageTypeToString(const Zigbee::InterfaceMessageType &type);
|
||||
//static QString messageTypeToString(const Zigbee::InterfaceMessageType &type);
|
||||
static QString clusterIdToString(const Zigbee::ClusterId &clusterId);
|
||||
static QString profileIdToString(const Zigbee::ZigbeeProfile &profileId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user