Make basic node adding mechanism work

This commit is contained in:
Simon Stürz 2020-05-20 19:54:58 +02:00
parent 7cdf772b1a
commit 029ca76bae
38 changed files with 1340 additions and 1117 deletions

View File

@ -296,7 +296,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
for (int i = 0; i < asdu.length(); i++) { for (int i = 0; i < asdu.length(); i++) {
stream << static_cast<quint8>(asdu.at(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; stream << radius;
m_interface->sendPackage(message); m_interface->sendPackage(message);
@ -337,7 +337,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
for (int i = 0; i < asdu.length(); i++) { for (int i = 0; i < asdu.length(); i++) {
stream << static_cast<quint8>(asdu.at(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; stream << radius;
m_interface->sendPackage(message); m_interface->sendPackage(message);
@ -347,6 +347,7 @@ ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestEnqueueSendData
ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestSendRequest(const ZigbeeNetworkRequest &request) ZigbeeInterfaceDeconzReply *ZigbeeBridgeControllerDeconz::requestSendRequest(const ZigbeeNetworkRequest &request)
{ {
qCDebug(dcZigbeeAps()) << "APSDE-DATA.request" << request;
ZigbeeInterfaceDeconzReply *interfaceReply = nullptr; ZigbeeInterfaceDeconzReply *interfaceReply = nullptr;
switch (request.destinationAddressMode()) { switch (request.destinationAddressMode()) {
case Zigbee::DestinationAddressModeGroup: case Zigbee::DestinationAddressModeGroup:
@ -733,10 +734,10 @@ DeconzDeviceState ZigbeeBridgeControllerDeconz::parseDeviceStateFlag(quint8 devi
{ {
DeconzDeviceState state; DeconzDeviceState state;
state.networkState = static_cast<Deconz::NetworkState>(deviceStateFlag & 0x03); state.networkState = static_cast<Deconz::NetworkState>(deviceStateFlag & 0x03);
state.aspDataConfirm = (deviceStateFlag & 0x04); state.apsDataConfirm = (deviceStateFlag & 0x04);
state.aspDataIndication = (deviceStateFlag & 0x08); state.apsDataIndication = (deviceStateFlag & 0x08);
state.configurationChanged = (deviceStateFlag & 0x10); state.configurationChanged = (deviceStateFlag & 0x10);
state.aspDataRequestFreeSlots = (deviceStateFlag & 0x20); state.apsDataRequestFreeSlots = (deviceStateFlag & 0x20);
return state; return state;
} }
@ -750,7 +751,7 @@ void ZigbeeBridgeControllerDeconz::readDataIndication()
return; return;
} }
// ASP data indication received, process the content // APS data indication received, process the content
qCDebug(dcZigbeeController()) << "Reading data indication finished successfully"; qCDebug(dcZigbeeController()) << "Reading data indication finished successfully";
processDataIndication(reply->responseData()); processDataIndication(reply->responseData());
}); });
@ -766,7 +767,7 @@ void ZigbeeBridgeControllerDeconz::readDataConfirm()
return; return;
} }
// ASP data indication received, process the content // APS data confirm received, process the content
qCDebug(dcZigbeeController()) << "Reading data confirm finished successfully"; qCDebug(dcZigbeeController()) << "Reading data confirm finished successfully";
processDataConfirm(reply->responseData()); processDataConfirm(reply->responseData());
}); });
@ -782,10 +783,10 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
emit networkStateChanged(m_networkState); emit networkStateChanged(m_networkState);
} }
if (m_aspFreeSlotsAvailable != deviceState.aspDataRequestFreeSlots) { if (m_apsFreeSlotsAvailable != deviceState.apsDataRequestFreeSlots) {
m_aspFreeSlotsAvailable = deviceState.aspDataRequestFreeSlots; 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 // Note: read a data indication before a confirmation since the confirmation arrives after a related indication normally
// Check if we have to read a data indication message // Check if we have to read a data indication message
if (deviceState.aspDataIndication) { if (deviceState.apsDataIndication) {
readDataIndication(); readDataIndication();
} }
// Check if we have a response to read for a request // Check if we have a response to read for a request
if (deviceState.aspDataConfirm) { if (deviceState.apsDataConfirm) {
readDataConfirm(); readDataConfirm();
} }
@ -808,7 +809,7 @@ void ZigbeeBridgeControllerDeconz::processDeviceState(DeconzDeviceState deviceSt
void ZigbeeBridgeControllerDeconz::processDataIndication(const QByteArray &data) void ZigbeeBridgeControllerDeconz::processDataIndication(const QByteArray &data)
{ {
// ASP data indication // APS data indication
QDataStream stream(data); QDataStream stream(data);
stream.setByteOrder(QDataStream::LittleEndian); stream.setByteOrder(QDataStream::LittleEndian);
quint16 payloadLenght = 0; quint8 deviceStateFlag = 0; quint8 reserved = 0; quint16 asduLength = 0; 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; stream >> reserved >> reserved >> indication.lqi >> reserved >> reserved >> reserved >> reserved >> indication.rssi;
// Print the information for debugging // Print the information for debugging
qCDebug(dcZigbeeAps()) << "APSDE-DATA.indication" << indication;
qCDebug(dcZigbeeController()) << 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 // Process the device state in order to check if we have to request another indication
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag); DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
if (deviceState.aspDataIndication) { if (deviceState.apsDataIndication) {
readDataIndication(); readDataIndication();
} }
} }
@ -873,12 +875,13 @@ void ZigbeeBridgeControllerDeconz::processDataConfirm(const QByteArray &data)
// Print the information for debugging // Print the information for debugging
qCDebug(dcZigbeeController()) << confirm; 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 // Process the device state in order to check if we have to request another indication
DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag); DeconzDeviceState deviceState = parseDeviceStateFlag(deviceStateFlag);
if (deviceState.aspDataConfirm) { if (deviceState.apsDataConfirm) {
readDataConfirm(); readDataConfirm();
} }
} }
@ -996,16 +999,16 @@ QDebug operator<<(QDebug debug, const DeconzDeviceState &deviceState)
break; break;
} }
debug.nospace() << "Confirm=" << static_cast<int>(deviceState.aspDataConfirm) << ", "; debug.nospace() << "Confirm=" << static_cast<int>(deviceState.apsDataConfirm) << ", ";
debug.nospace() << "Indication=" << static_cast<int>(deviceState.aspDataIndication) << ", "; debug.nospace() << "Indication=" << static_cast<int>(deviceState.apsDataIndication) << ", ";
debug.nospace() << "ConfigChanged=" << static_cast<int>(deviceState.configurationChanged) << ", "; debug.nospace() << "ConfigChanged=" << static_cast<int>(deviceState.configurationChanged) << ", ";
debug.nospace() << "CanSend=" << deviceState.aspDataRequestFreeSlots << ")"; debug.nospace() << "CanSend=" << deviceState.apsDataRequestFreeSlots << ")";
return debug.space(); return debug.space();
} }
QDebug operator<<(QDebug debug, const DeconzApsDataConfirm &confirm) QDebug operator<<(QDebug debug, const DeconzApsDataConfirm &confirm)
{ {
debug.nospace() << "ASP.Confirm("; debug.nospace() << "APSDE-DATA.confirm(";
debug.nospace() << "Request ID: " << confirm.requestId << ", "; debug.nospace() << "Request ID: " << confirm.requestId << ", ";
if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeGroup) if (confirm.destinationAddressMode == Zigbee::DestinationAddressModeGroup)
@ -1027,7 +1030,7 @@ QDebug operator<<(QDebug debug, const DeconzApsDataConfirm &confirm)
QDebug operator<<(QDebug debug, const DeconzApsDataIndication &indication) QDebug operator<<(QDebug debug, const DeconzApsDataIndication &indication)
{ {
debug.nospace() << "ASP.Indication("; debug.nospace() << "APSDE-DATA.indication(";
if (indication.destinationAddressMode == Zigbee::DestinationAddressModeGroup) if (indication.destinationAddressMode == Zigbee::DestinationAddressModeGroup)
debug.nospace() << "Group address:" << ZigbeeUtils::convertUint16ToHexString(indication.destinationShortAddress) << ", "; 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() << " - NWK address:" << ZigbeeUtils::convertUint16ToHexString(configuration.shortAddress) << endl;
debug.nospace() << " - PAN ID:" << ZigbeeUtils::convertUint16ToHexString(configuration.panId) << endl; debug.nospace() << " - PAN ID:" << ZigbeeUtils::convertUint16ToHexString(configuration.panId) << endl;
debug.nospace() << " - Extended PAN ID:" << ZigbeeUtils::convertUint64ToHexString(configuration.extendedPanId) << 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() << " - Trust center IEEE address:" << configuration.trustCenterAddress.toString() << endl;
debug.nospace() << " - Channel mask:" << ZigbeeChannelMask(configuration.channelMask) << endl; debug.nospace() << " - Channel mask:" << ZigbeeChannelMask(configuration.channelMask) << endl;
debug.nospace() << " - Channel:" << configuration.currentChannel << endl; debug.nospace() << " - Channel:" << configuration.currentChannel << endl;

View File

@ -61,14 +61,13 @@ typedef struct DeconzNetworkConfiguration {
} DeconzNetworkConfiguration; } DeconzNetworkConfiguration;
// This struct describes the deCONZ device state // This struct describes the deCONZ device state
typedef struct DeconzDeviceState { typedef struct DeconzDeviceState {
Deconz::NetworkState networkState = Deconz::NetworkStateOffline; Deconz::NetworkState networkState = Deconz::NetworkStateOffline;
bool aspDataConfirm = false; bool apsDataConfirm = false;
bool aspDataIndication = false; bool apsDataIndication = false;
bool configurationChanged = false; bool configurationChanged = false;
bool aspDataRequestFreeSlots = false; bool apsDataRequestFreeSlots = false;
} DeconzDeviceState; } DeconzDeviceState;
@ -141,7 +140,7 @@ private:
Deconz::NetworkState m_networkState = Deconz::NetworkStateOffline; Deconz::NetworkState m_networkState = Deconz::NetworkStateOffline;
QTimer *m_watchdogTimer = nullptr; QTimer *m_watchdogTimer = nullptr;
bool m_aspFreeSlotsAvailable = false; bool m_apsFreeSlotsAvailable = false;
quint8 generateSequenceNumber(); quint8 generateSequenceNumber();
@ -165,8 +164,8 @@ signals:
void networkStateChanged(Deconz::NetworkState networkState); void networkStateChanged(Deconz::NetworkState networkState);
void networkConfigurationParameterChanged(const DeconzNetworkConfiguration &networkConfiguration); void networkConfigurationParameterChanged(const DeconzNetworkConfiguration &networkConfiguration);
void aspDataConfirmReceived(const DeconzApsDataConfirm &confirm); void apsDataConfirmReceived(const DeconzApsDataConfirm &confirm);
void aspDataIndicationReceived(const DeconzApsDataIndication &indication); void apsDataIndicationReceived(const DeconzApsDataIndication &indication);
private slots: private slots:
void onInterfaceAvailableChanged(bool available); void onInterfaceAvailableChanged(bool available);

View File

@ -38,8 +38,8 @@ ZigbeeNetworkDeconz::ZigbeeNetworkDeconz(QObject *parent) :
m_controller = new ZigbeeBridgeControllerDeconz(this); m_controller = new ZigbeeBridgeControllerDeconz(this);
//connect(m_controller, &ZigbeeBridgeControllerDeconz::messageReceived, this, &ZigbeeNetworkDeconz::onMessageReceived); //connect(m_controller, &ZigbeeBridgeControllerDeconz::messageReceived, this, &ZigbeeNetworkDeconz::onMessageReceived);
connect(m_controller, &ZigbeeBridgeControllerDeconz::availableChanged, this, &ZigbeeNetworkDeconz::onControllerAvailableChanged); connect(m_controller, &ZigbeeBridgeControllerDeconz::availableChanged, this, &ZigbeeNetworkDeconz::onControllerAvailableChanged);
connect(m_controller, &ZigbeeBridgeControllerDeconz::aspDataConfirmReceived, this, &ZigbeeNetworkDeconz::onAspDataConfirmReceived); connect(m_controller, &ZigbeeBridgeControllerDeconz::apsDataConfirmReceived, this, &ZigbeeNetworkDeconz::onApsDataConfirmReceived);
connect(m_controller, &ZigbeeBridgeControllerDeconz::aspDataIndicationReceived, this, &ZigbeeNetworkDeconz::onAspDataIndicationReceived); connect(m_controller, &ZigbeeBridgeControllerDeconz::apsDataIndicationReceived, this, &ZigbeeNetworkDeconz::onApsDataIndicationReceived);
m_pollNetworkStateTimer = new QTimer(this); m_pollNetworkStateTimer = new QTimer(this);
m_pollNetworkStateTimer->setInterval(1000); m_pollNetworkStateTimer->setInterval(1000);
@ -70,7 +70,12 @@ ZigbeeNetworkReply *ZigbeeNetworkDeconz::sendRequest(const ZigbeeNetworkRequest
m_pendingReplies.remove(request.requestId()); 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); ZigbeeInterfaceDeconzReply *interfaceReply = m_controller->requestSendRequest(request);
connect(interfaceReply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply, interfaceReply](){ connect(interfaceReply, &ZigbeeInterfaceDeconzReply::finished, this, [this, reply, interfaceReply](){
if (interfaceReply->statusCode() != Deconz::StatusCodeSuccess) { if (interfaceReply->statusCode() != Deconz::StatusCodeSuccess) {
@ -285,13 +290,11 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
return; return;
} }
ZigbeeNodeDeconz *coordinatorNode = qobject_cast<ZigbeeNodeDeconz *>(createNode(this)); ZigbeeNode *coordinatorNode = createNode(m_controller->networkConfiguration().shortAddress, m_controller->networkConfiguration().ieeeAddress, this);
coordinatorNode->setShortAddress(m_controller->networkConfiguration().shortAddress);
coordinatorNode->setExtendedAddress(m_controller->networkConfiguration().ieeeAddress);
m_coordinatorNode = coordinatorNode; m_coordinatorNode = coordinatorNode;
// Network creation done when coordinator node is initialized // 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) { if (state == ZigbeeNode::StateInitialized) {
qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode; qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode;
setState(StateRunning); setState(StateRunning);
@ -317,31 +320,39 @@ void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const DeconzApsDat
return; return;
} }
foreach (ZigbeeNetworkReply *reply, m_pendingReplies.values()) { ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
// Check if this is a response for a ZDO request if (!node) {
if (reply->request().profileId() == Zigbee::ZigbeeProfileDevice) { qCWarning(dcZigbeeNetwork()) << "Received a ZDO indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
// We have a reply which is waiting for a ZDO response, lets check if they match return;
// 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;
}
}
}
} }
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) 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) void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
@ -371,7 +377,7 @@ void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining)
ZigbeeNetworkReply *reply = setPermitJoin(Zigbee::BroadcastAddressAllRouters, duration); ZigbeeNetworkReply *reply = setPermitJoin(Zigbee::BroadcastAddressAllRouters, duration);
connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply, permitJoining, 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; qCDebug(dcZigbeeNetwork()) << "Could not set permit join to" << duration;
m_permitJoining = false; m_permitJoining = false;
emit permitJoiningChanged(m_permitJoining); emit permitJoiningChanged(m_permitJoining);
@ -598,23 +604,19 @@ void ZigbeeNetworkDeconz::onPermitJoinRefreshTimout()
setPermitJoiningInternal(true); setPermitJoiningInternal(true);
} }
void ZigbeeNetworkDeconz::onAspDataConfirmReceived(const DeconzApsDataConfirm &confirm) void ZigbeeNetworkDeconz::onApsDataConfirmReceived(const DeconzApsDataConfirm &confirm)
{ {
qCDebug(dcZigbeeNetwork()) << confirm;
ZigbeeNetworkReply *reply = m_pendingReplies.value(confirm.requestId); ZigbeeNetworkReply *reply = m_pendingReplies.value(confirm.requestId);
if (!reply) { if (!reply) {
qCWarning(dcZigbeeNetwork()) << "Received confirmation but could not find any reply. Ignoring the confirmation"; qCWarning(dcZigbeeNetwork()) << "Received confirmation but could not find any reply. Ignoring the confirmation";
return; 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 // Check if this indocation is related to any pending reply
if (indication.profileId == Zigbee::ZigbeeProfileDevice) { if (indication.profileId == Zigbee::ZigbeeProfileDevice) {
handleZigbeeDeviceProfileIndication(indication); handleZigbeeDeviceProfileIndication(indication);
@ -644,10 +646,7 @@ void ZigbeeNetworkDeconz::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress
return; return;
} }
ZigbeeNodeDeconz *node = static_cast<ZigbeeNodeDeconz *>(createNode(this)); ZigbeeNode *node = createNode(shortAddress, ieeeAddress, macCapabilities, this);
node->setExtendedAddress(ieeeAddress);
node->setShortAddress(shortAddress);
node->setMacCapabilitiesFlag(macCapabilities);
addUnitializedNode(node); addUnitializedNode(node);
node->startInitialization(); node->startInitialization();
} }

View File

@ -31,7 +31,6 @@
#include <QObject> #include <QObject>
#include "zigbeenetwork.h" #include "zigbeenetwork.h"
#include "zigbeenodedeconz.h"
#include "zigbeechannelmask.h" #include "zigbeechannelmask.h"
#include "zigbeeclusterlibrary.h" #include "zigbeeclusterlibrary.h"
#include "zigbeebridgecontrollerdeconz.h" #include "zigbeebridgecontrollerdeconz.h"
@ -54,6 +53,7 @@ public:
ZigbeeBridgeController *bridgeController() const override; ZigbeeBridgeController *bridgeController() const override;
// Sending an APSDE-DATA.request, will be finished on APSDE-DATA.confirm
ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override; ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override;
ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress, quint8 duration); ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress, quint8 duration);
@ -82,10 +82,7 @@ private:
// GP // GP
protected: protected:
ZigbeeNode *createNode(QObject *parent) override;
void setPermitJoiningInternal(bool permitJoining) override; void setPermitJoiningInternal(bool permitJoining) override;
void startNetworkInternally(); void startNetworkInternally();
private slots: private slots:
@ -93,8 +90,8 @@ private slots:
void onPollNetworkStateTimeout(); void onPollNetworkStateTimeout();
void onPermitJoinRefreshTimout(); void onPermitJoinRefreshTimout();
void onAspDataConfirmReceived(const DeconzApsDataConfirm &confirm); void onApsDataConfirmReceived(const DeconzApsDataConfirm &confirm);
void onAspDataIndicationReceived(const DeconzApsDataIndication &indication); void onApsDataIndicationReceived(const DeconzApsDataIndication &indication);
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities); void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);

View File

@ -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));
}

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -8,8 +8,6 @@ SOURCES += \
deconz/interface/zigbeeinterfacedeconzreply.cpp \ deconz/interface/zigbeeinterfacedeconzreply.cpp \
deconz/zigbeebridgecontrollerdeconz.cpp \ deconz/zigbeebridgecontrollerdeconz.cpp \
deconz/zigbeenetworkdeconz.cpp \ deconz/zigbeenetworkdeconz.cpp \
deconz/zigbeenodedeconz.cpp \
deconz/zigbeenodeendpointdeconz.cpp \
# nxp/interface/zigbeeinterface.cpp \ # nxp/interface/zigbeeinterface.cpp \
# nxp/interface/zigbeeinterfacemessage.cpp \ # nxp/interface/zigbeeinterfacemessage.cpp \
# nxp/interface/zigbeeinterfacerequest.cpp \ # nxp/interface/zigbeeinterfacerequest.cpp \
@ -19,9 +17,9 @@ SOURCES += \
# nxp/zigbeenodeendpointnxp.cpp \ # nxp/zigbeenodeendpointnxp.cpp \
# nxp/zigbeenodenxp.cpp \ # nxp/zigbeenodenxp.cpp \
zcl/zigbeeclusterbasic.cpp \ zcl/zigbeeclusterbasic.cpp \
zcl/zigbeeclusterreply.cpp \
zdo/zigbeedeviceobject.cpp \ zdo/zigbeedeviceobject.cpp \
zdo/zigbeedeviceobjectreply.cpp \ zdo/zigbeedeviceobjectreply.cpp \
zdo/zigbeedeviceprofilehandler.cpp \
zdo/zigbeedeviceprofile.cpp \ zdo/zigbeedeviceprofile.cpp \
zigbeeadpu.cpp \ zigbeeadpu.cpp \
zigbeebridgecontroller.cpp \ zigbeebridgecontroller.cpp \
@ -52,8 +50,6 @@ HEADERS += \
deconz/interface/zigbeeinterfacedeconzreply.h \ deconz/interface/zigbeeinterfacedeconzreply.h \
deconz/zigbeebridgecontrollerdeconz.h \ deconz/zigbeebridgecontrollerdeconz.h \
deconz/zigbeenetworkdeconz.h \ deconz/zigbeenetworkdeconz.h \
deconz/zigbeenodedeconz.h \
deconz/zigbeenodeendpointdeconz.h \
# nxp/interface/zigbeeinterface.h \ # nxp/interface/zigbeeinterface.h \
# nxp/interface/zigbeeinterfacemessage.h \ # nxp/interface/zigbeeinterfacemessage.h \
# nxp/interface/zigbeeinterfacerequest.h \ # nxp/interface/zigbeeinterfacerequest.h \
@ -63,9 +59,9 @@ HEADERS += \
# nxp/zigbeenodeendpointnxp.h \ # nxp/zigbeenodeendpointnxp.h \
# nxp/zigbeenodenxp.h \ # nxp/zigbeenodenxp.h \
zcl/zigbeeclusterbasic.h \ zcl/zigbeeclusterbasic.h \
zcl/zigbeeclusterreply.h \
zdo/zigbeedeviceobject.h \ zdo/zigbeedeviceobject.h \
zdo/zigbeedeviceobjectreply.h \ zdo/zigbeedeviceobjectreply.h \
zdo/zigbeedeviceprofilehandler.h \
zdo/zigbeedeviceprofile.h \ zdo/zigbeedeviceprofile.h \
zigbeeadpu.h \ zigbeeadpu.h \
zigbeebridgecontroller.h \ zigbeebridgecontroller.h \

View File

@ -29,8 +29,10 @@
Q_LOGGING_CATEGORY(dcZigbeeNetwork, "ZigbeeNetwork") Q_LOGGING_CATEGORY(dcZigbeeNetwork, "ZigbeeNetwork")
Q_LOGGING_CATEGORY(dcZigbeeNode, "ZigbeeNode") Q_LOGGING_CATEGORY(dcZigbeeNode, "ZigbeeNode")
Q_LOGGING_CATEGORY(dcZigbeeAps, "ZigbeeAps")
Q_LOGGING_CATEGORY(dcZigbeeCluster, "ZigbeeCluster") Q_LOGGING_CATEGORY(dcZigbeeCluster, "ZigbeeCluster")
Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface") Q_LOGGING_CATEGORY(dcZigbeeInterface, "ZigbeeInterface")
Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController") Q_LOGGING_CATEGORY(dcZigbeeController, "ZigbeeController")
Q_LOGGING_CATEGORY(dcZigbeeDeviceObject, "ZigbeeDeviceObject")
Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase") Q_LOGGING_CATEGORY(dcZigbeeNetworkDatabase, "ZigbeeNetworkDatabase")
Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic") Q_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic, "ZigbeeInterfaceTraffic")

View File

@ -33,9 +33,11 @@
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetwork) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetwork)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNode) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNode)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeAps)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeCluster)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterface)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeController)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeDeviceObject)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeNetworkDatabase)
Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic) Q_DECLARE_LOGGING_CATEGORY(dcZigbeeInterfaceTraffic)

View File

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

View 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

View File

@ -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 "zigbeedeviceobject.h"
#include "zigbeenetwork.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), 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";
}

View File

@ -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 #ifndef ZIGBEEDEVICEOBJECT_H
#define ZIGBEEDEVICEOBJECT_H #define ZIGBEEDEVICEOBJECT_H
#include <QObject> #include <QObject>
#include "zigbeenetworkreply.h"
#include "zigbeedeviceobjectreply.h"
class ZigbeeNode;
class ZigbeeNetwork; class ZigbeeNetwork;
class ZigbeeDeviceObject : public QObject class ZigbeeDeviceObject : public QObject
{ {
Q_OBJECT Q_OBJECT
public: 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: private:
ZigbeeNetwork *m_network = nullptr; 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: signals:
public slots:
void processApsDataIndication(quint8 destinationEndpoint, quint8 sourceEndpoint, quint16 clusterId, QByteArray payload, quint8 lqi, qint8 rssi);
}; };
#endif // ZIGBEEDEVICEOBJECT_H #endif // ZIGBEEDEVICEOBJECT_H

View File

@ -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" #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;
}

View File

@ -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 #ifndef ZIGBEEDEVICEOBJECTREPLY_H
#define ZIGBEEDEVICEOBJECTREPLY_H #define ZIGBEEDEVICEOBJECTREPLY_H
#include <QObject> #include <QObject>
#include "zigbeedeviceprofile.h"
#include "zigbeenetworkrequest.h"
class ZigbeeDeviceObjectReply : public QObject class ZigbeeDeviceObjectReply : public QObject
{ {
Q_OBJECT Q_OBJECT
friend class ZigbeeDeviceObject;
public: 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: signals:
void finished();
}; };

View File

@ -30,22 +30,22 @@
#include <QDataStream> #include <QDataStream>
ZigbeeDeviceProfileAdpu ZigbeeDeviceProfile::parseAdpu(const QByteArray &adpu) ZigbeeDeviceProfile::Adpu ZigbeeDeviceProfile::parseAdpu(const QByteArray &adpu)
{ {
QDataStream stream(adpu); QDataStream stream(adpu);
stream.setByteOrder(QDataStream::LittleEndian); stream.setByteOrder(QDataStream::LittleEndian);
ZigbeeDeviceProfileAdpu deviceAdpu; ZigbeeDeviceProfile::Adpu deviceAdpu;
quint8 statusFlag = 0; quint8 statusFlag = 0;
stream >> deviceAdpu.sequenceNumber >> statusFlag >> deviceAdpu.addressOfInterest; stream >> deviceAdpu.transactionSequenceNumber >> statusFlag >> deviceAdpu.addressOfInterest;
deviceAdpu.status = static_cast<Zigbee::ZigbeeStatus>(statusFlag); deviceAdpu.status = static_cast<ZigbeeDeviceProfile::Status>(statusFlag);
deviceAdpu.payload = adpu.right(adpu.length() - 4); deviceAdpu.payload = adpu.right(adpu.length() - 4);
return deviceAdpu; 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() << deviceAdpu.status << ", ";
debug.nospace() << ZigbeeUtils::convertUint16ToHexString(deviceAdpu.addressOfInterest) << ", "; debug.nospace() << ZigbeeUtils::convertUint16ToHexString(deviceAdpu.addressOfInterest) << ", ";
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(deviceAdpu.payload) << ")"; debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(deviceAdpu.payload) << ")";

View File

@ -33,13 +33,6 @@
#include "zigbee.h" #include "zigbee.h"
typedef struct ZigbeeDeviceProfileAdpu {
quint8 sequenceNumber = 0;
Zigbee::ZigbeeStatus status = Zigbee::ZigbeeStatusSuccess;
quint16 addressOfInterest = 0;
QByteArray payload;
} ZigbeeDeviceProfileAdpu;
class ZigbeeDeviceProfile class ZigbeeDeviceProfile
{ {
Q_GADGET Q_GADGET
@ -47,8 +40,20 @@ class ZigbeeDeviceProfile
public: public:
enum Status { enum Status {
StatusSuccess = 0x00, StatusSuccess = 0x00,
StatusInvalidRequestType = 0x01, StatusInvalidRequestType = 0x80,
StatusDeviceNotFound = 0x02 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) Q_ENUM(Status)
@ -154,9 +159,23 @@ public:
}; };
Q_ENUM(ZdoCommand) 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 #endif // ZIGBEEDEVICEPROFILE_H

View File

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

View File

@ -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

View File

@ -74,210 +74,210 @@ public:
Q_ENUM(ZigbeeChannel) Q_ENUM(ZigbeeChannel)
Q_DECLARE_FLAGS(ZigbeeChannels, ZigbeeChannel) Q_DECLARE_FLAGS(ZigbeeChannels, ZigbeeChannel)
enum InterfaceMessageType { // enum InterfaceMessageType {
// Common Commands // // Common Commands
MessageTypeNone = 0x0000, // MessageTypeNone = 0x0000,
MessageTypeStatus = 0x8000, // MessageTypeStatus = 0x8000,
MessageTypeLogging = 0x8001, // MessageTypeLogging = 0x8001,
MessageTypeDataIndication = 0x8002, // MessageTypeDataIndication = 0x8002,
MessageTypeNodeClusterList = 0x8003, // MessageTypeNodeClusterList = 0x8003,
MessageTypeNodeAttributeList = 0x8004, // MessageTypeNodeAttributeList = 0x8004,
MessageTypeNodeCommandIdList = 0x8005, // MessageTypeNodeCommandIdList = 0x8005,
MessageTypeRestartProvisioned = 0x8006, // MessageTypeRestartProvisioned = 0x8006,
MessageTypeFactoryNewRestart = 0x8007, // MessageTypeFactoryNewRestart = 0x8007,
MessageTypeGetVersion = 0x0010, // MessageTypeGetVersion = 0x0010,
MessageTypeVersionList = 0x8010, // MessageTypeVersionList = 0x8010,
MessageTypeSetExtendetPanId = 0x0020, // MessageTypeSetExtendetPanId = 0x0020,
MessageTypeSetChannelMask = 0x0021, // MessageTypeSetChannelMask = 0x0021,
MessageTypeSetSecurity = 0x0022, // MessageTypeSetSecurity = 0x0022,
MessageTypeSetDeviceType = 0x0023, // MessageTypeSetDeviceType = 0x0023,
MessageTypeStartNetwork = 0x0024, // MessageTypeStartNetwork = 0x0024,
MessageTypeStartScan = 0x0025, // MessageTypeStartScan = 0x0025,
MessageTypeNetworkJoinedFormed = 0x8024, // MessageTypeNetworkJoinedFormed = 0x8024,
MessageTypeNetworkRemoveDevice = 0x0026, // MessageTypeNetworkRemoveDevice = 0x0026,
MessageTypeNetworkWhitelistEnable = 0x0027, // MessageTypeNetworkWhitelistEnable = 0x0027,
MessageTypeAuthenticateDeviceRequest = 0x0028, // MessageTypeAuthenticateDeviceRequest = 0x0028,
MessageTypeAuthenticateDeviceResponse = 0x8028, // MessageTypeAuthenticateDeviceResponse = 0x8028,
MessageTypeOutOfBandCommisioningDataRequest = 0x0029, // MessageTypeOutOfBandCommisioningDataRequest = 0x0029,
MessageTypeOutOfBandCommisioningDataResponse = 0x8029, // MessageTypeOutOfBandCommisioningDataResponse = 0x8029,
MessageTypeUserDescriptorSet = 0x002B, // MessageTypeUserDescriptorSet = 0x002B,
MessageTypeUserDescriptorNotify = 0x802B, // MessageTypeUserDescriptorNotify = 0x802B,
MessageTypeUserDescriptorRequest = 0x002C, // MessageTypeUserDescriptorRequest = 0x002C,
MessageTypeUserDescriptorResponse = 0x802C, // MessageTypeUserDescriptorResponse = 0x802C,
MessageTypeReset = 0x0011, // MessageTypeReset = 0x0011,
MessageTypeErasePersistentData = 0x0012, // MessageTypeErasePersistentData = 0x0012,
MessageTypeZllFactoryNew = 0x0013, // MessageTypeZllFactoryNew = 0x0013,
MessageTypeGetPermitJoining = 0x0014, // MessageTypeGetPermitJoining = 0x0014,
MessageTypeGetPermitJoiningResponse = 0x8014, // MessageTypeGetPermitJoiningResponse = 0x8014,
MessageTypeBind = 0x0030, // MessageTypeBind = 0x0030,
MessageTypeBindResponse = 0x8030, // MessageTypeBindResponse = 0x8030,
MessageTypeUnbind = 0x0031, // MessageTypeUnbind = 0x0031,
MessageTypeBindGroup = 0x0032, // MessageTypeBindGroup = 0x0032,
MessageTypeBindGroupResponse = 0x8032, // MessageTypeBindGroupResponse = 0x8032,
MessageTypeUnbindGroup = 0x0033, // MessageTypeUnbindGroup = 0x0033,
MessageTypeUnbindGroupResponse = 0x8033, // MessageTypeUnbindGroupResponse = 0x8033,
MessageTypeUnbindResponse = 0x8031, // MessageTypeUnbindResponse = 0x8031,
MessageTypeComplexDescriptorRequest = 0x0034, // MessageTypeComplexDescriptorRequest = 0x0034,
MessageTypeComplexDescriptorResponse = 0x8034, // MessageTypeComplexDescriptorResponse = 0x8034,
MessageTypeNetworkAdressRequest = 0x0040, // MessageTypeNetworkAdressRequest = 0x0040,
MessageTypeNetworkAdressResponse = 0x8040, // MessageTypeNetworkAdressResponse = 0x8040,
MessageTypeIeeeAddressResponse = 0x0041, // MessageTypeIeeeAddressResponse = 0x0041,
MessageTypeIeeeAddressRequest = 0x8041, // MessageTypeIeeeAddressRequest = 0x8041,
MessageTypeNodeDescriptorRequest = 0x0042, // MessageTypeNodeDescriptorRequest = 0x0042,
MessageTypeNodeDescriptorRsponse = 0x8042, // MessageTypeNodeDescriptorRsponse = 0x8042,
MessageTypeSimpleDescriptorRequest = 0x0043, // MessageTypeSimpleDescriptorRequest = 0x0043,
MessageTypeSimpleDescriptorResponse = 0x8043, // MessageTypeSimpleDescriptorResponse = 0x8043,
MessageTypePowerDescriptorRequest = 0x0044, // MessageTypePowerDescriptorRequest = 0x0044,
MessageTypePowerDescriptorResponse = 0x8044, // MessageTypePowerDescriptorResponse = 0x8044,
MessageTypeActiveEndpointRequest = 0x0045, // MessageTypeActiveEndpointRequest = 0x0045,
MessageTypeActiveEndpointResponse = 0x8045, // MessageTypeActiveEndpointResponse = 0x8045,
MessageTypeMatchDescriptorRequest = 0x0046, // MessageTypeMatchDescriptorRequest = 0x0046,
MessageTypeMatchDescriptorResponse = 0x8046, // MessageTypeMatchDescriptorResponse = 0x8046,
MessageTypeManagementLeaveRequest = 0x0047, // MessageTypeManagementLeaveRequest = 0x0047,
MessageTypeManagementLeaveResponse = 0x8047, // MessageTypeManagementLeaveResponse = 0x8047,
MessageTypeLeaveIndication = 0x8048, // MessageTypeLeaveIndication = 0x8048,
MessageTypePermitJoiningRequest = 0x0049, // MessageTypePermitJoiningRequest = 0x0049,
MessageTypeManagementNetworkUpdateRequest = 0x004A, // MessageTypeManagementNetworkUpdateRequest = 0x004A,
MessageTypeManagementNetworkUpdateResponse = 0x804A, // MessageTypeManagementNetworkUpdateResponse = 0x804A,
MessageTypeSystemServerDiscoveryRequest = 0x004B, // MessageTypeSystemServerDiscoveryRequest = 0x004B,
MessageTypeSystemServerDiscoveryResponse = 0x804B, // MessageTypeSystemServerDiscoveryResponse = 0x804B,
MessageTypeDeviceAnnounce = 0x004D, // MessageTypeDeviceAnnounce = 0x004D,
MessageTypeManagementLqiRequest = 0x004E, // MessageTypeManagementLqiRequest = 0x004E,
MessageTypeManagementLqiResponse = 0x804E, // MessageTypeManagementLqiResponse = 0x804E,
// Basic cluster // // Basic cluster
MessageBasicResetFactoryDefaults = 0x0050, // MessageBasicResetFactoryDefaults = 0x0050,
MessageBasicResetFactoryDefaultsResponse = 0x8050, // MessageBasicResetFactoryDefaultsResponse = 0x8050,
// Group Cluster // // Group Cluster
MessageTypeAddGroupRequest = 0x0060, // MessageTypeAddGroupRequest = 0x0060,
MessageTypeAddGroupResponse = 0x8060, // MessageTypeAddGroupResponse = 0x8060,
MessageTypeViewGroupRequest = 0x0061, // MessageTypeViewGroupRequest = 0x0061,
MessageTypeViewGroupResponse = 0x8061, // MessageTypeViewGroupResponse = 0x8061,
MessageTypeGetGroupMembershipRequest = 0x0062, // MessageTypeGetGroupMembershipRequest = 0x0062,
MessageTypeGetGroupMembershipResponse = 0x8062, // MessageTypeGetGroupMembershipResponse = 0x8062,
MessageTypeRemoveGroupRequest = 0x0063, // MessageTypeRemoveGroupRequest = 0x0063,
MessageTypeRemoveGroupResponse = 0x8063, // MessageTypeRemoveGroupResponse = 0x8063,
MessageTypeRemoveAllGroups = 0x0064, // MessageTypeRemoveAllGroups = 0x0064,
MessageTypeGroupIfIdentify = 0x0065, // MessageTypeGroupIfIdentify = 0x0065,
// Identify Cluster // // Identify Cluster
MessageTypeIdentifySend = 0x0070, // MessageTypeIdentifySend = 0x0070,
MessageTypeIdentifyQuery = 0x0071, // MessageTypeIdentifyQuery = 0x0071,
// Level Cluster // // Level Cluster
MessageTypeMoveToLevel = 0x0080, // MessageTypeMoveToLevel = 0x0080,
MessageTypeMoveToLevelOnOff = 0x0081, // MessageTypeMoveToLevelOnOff = 0x0081,
MessageTypeMoveStep = 0x0082, // MessageTypeMoveStep = 0x0082,
MessageTypeMoveStopMove = 0x0083, // MessageTypeMoveStopMove = 0x0083,
MessageTypeMoveStopMoveOnOff = 0x0084, // MessageTypeMoveStopMoveOnOff = 0x0084,
// Scenes Cluster // // Scenes Cluster
MessageTypeViewScene = 0x00A0, // MessageTypeViewScene = 0x00A0,
MessageTypeViewSceneResponse = 0x80A0, // MessageTypeViewSceneResponse = 0x80A0,
MessageTypeAddScene = 0x00A1, // MessageTypeAddScene = 0x00A1,
MessageTypeAddSceneResponse = 0x80A1, // MessageTypeAddSceneResponse = 0x80A1,
MessageTypeRemoveScene = 0x00A2, // MessageTypeRemoveScene = 0x00A2,
MessageTypeRemoveSceneResponse = 0x80A2, // MessageTypeRemoveSceneResponse = 0x80A2,
MessageTypeRemoveAllScenes = 0x00A3, // MessageTypeRemoveAllScenes = 0x00A3,
MessageTypeRemoveAllScenesResponse = 0x80A3, // MessageTypeRemoveAllScenesResponse = 0x80A3,
MessageTypeStoreScene = 0x00A4, // MessageTypeStoreScene = 0x00A4,
MessageTypeStoreSceneResponse = 0x80A4, // MessageTypeStoreSceneResponse = 0x80A4,
MessageTypeRecallScene = 0x00A5, // MessageTypeRecallScene = 0x00A5,
MessageTypeSceneMembershipRequest = 0x00A6, // MessageTypeSceneMembershipRequest = 0x00A6,
MessageTypeSceneMembershipResponse = 0x80A6, // MessageTypeSceneMembershipResponse = 0x80A6,
//Colour Cluster // //Colour Cluster
MessageTypeMoveToHue = 0x00B0, // MessageTypeMoveToHue = 0x00B0,
MessageTypeMoveHue = 0x00B1, // MessageTypeMoveHue = 0x00B1,
MessageTypeStepHue = 0x00B2, // MessageTypeStepHue = 0x00B2,
MessageTypeMoveToSaturation = 0x00B3, // MessageTypeMoveToSaturation = 0x00B3,
MessageTypeMoveSaturation = 0x00B4, // MessageTypeMoveSaturation = 0x00B4,
MessageTypeStepStaturation = 0x00B5, // MessageTypeStepStaturation = 0x00B5,
MessageTypeMoveToHueSaturation = 0x00B6, // MessageTypeMoveToHueSaturation = 0x00B6,
MessageTypeMoveToColor = 0x00B7, // MessageTypeMoveToColor = 0x00B7,
MessageTypeMoveColor = 0x00B8, // MessageTypeMoveColor = 0x00B8,
MessageTypeStepColor = 0x00B9, // MessageTypeStepColor = 0x00B9,
// ZLL Commands // // ZLL Commands
// Touchlink // // Touchlink
MessageTypeInitiateTouchlink = 0x00D0, // MessageTypeInitiateTouchlink = 0x00D0,
MessageTypeTouchlinkStatus = 0x00D1, // MessageTypeTouchlinkStatus = 0x00D1,
MessageTypeTouchlinkFactoryReset = 0x00D2, // MessageTypeTouchlinkFactoryReset = 0x00D2,
// Identify Cluster // // Identify Cluster
MessageTypeIdentifyTriggerEffect = 0x00E0, // MessageTypeIdentifyTriggerEffect = 0x00E0,
// On/Off Cluster // // On/Off Cluster
MessageTypeCluserOnOff = 0x0092, // MessageTypeCluserOnOff = 0x0092,
MessageTypeCluserOnOffTimed = 0x0093, // MessageTypeCluserOnOffTimed = 0x0093,
MessageTypeCluserOnOffEffects = 0x0094, // MessageTypeCluserOnOffEffects = 0x0094,
MessageTypeCluserOnOffUpdate = 0x8095, // MessageTypeCluserOnOffUpdate = 0x8095,
// Scenes Cluster // // Scenes Cluster
MessageTypeAddEnhancedScene = 0x00A7, // MessageTypeAddEnhancedScene = 0x00A7,
MessageTypeViewEnhancedScene = 0x00A8, // MessageTypeViewEnhancedScene = 0x00A8,
MessageTypeCopyScene = 0x00A9, // MessageTypeCopyScene = 0x00A9,
// Colour Cluster // // Colour Cluster
MessageTypeEnhancedMoveToHue = 0x00BA, // MessageTypeEnhancedMoveToHue = 0x00BA,
MessageTypeEnhancedMoveHue = 0x00BB, // MessageTypeEnhancedMoveHue = 0x00BB,
MessageTypeEnhancedStepHue = 0x00BC, // MessageTypeEnhancedStepHue = 0x00BC,
MessageTypeEnhancedMoveToHueSaturation = 0x00BD, // MessageTypeEnhancedMoveToHueSaturation = 0x00BD,
MessageTypeColourLoopSet = 0x00BE, // MessageTypeColourLoopSet = 0x00BE,
MessageTypeStopMoveStep = 0x00BF, // MessageTypeStopMoveStep = 0x00BF,
MessageTypeMoveToColorTemperature = 0x00C0, // MessageTypeMoveToColorTemperature = 0x00C0,
MessageTypeMoveColorTemperature = 0x00C1, // MessageTypeMoveColorTemperature = 0x00C1,
MessageTypeStepColorTemperature = 0x00C2, // MessageTypeStepColorTemperature = 0x00C2,
// ZHA Commands // // ZHA Commands
// Door Lock Cluster // // Door Lock Cluster
MessageTypeLockUnlockDoor = 0x00F0, // MessageTypeLockUnlockDoor = 0x00F0,
// Attributes // // Attributes
MessageTypeReadAttributeRequest = 0x0100, // MessageTypeReadAttributeRequest = 0x0100,
MessageTypeReadAttributeResponse = 0x8100, // MessageTypeReadAttributeResponse = 0x8100,
MessageTypeDefaultResponse = 0x8101, // MessageTypeDefaultResponse = 0x8101,
MessageTypeAttributeReport = 0x8102, // MessageTypeAttributeReport = 0x8102,
MessageTypeWriteAttributeRequest = 0x0110, // MessageTypeWriteAttributeRequest = 0x0110,
MessageTypeWriteAttributeResponse = 0x8110, // MessageTypeWriteAttributeResponse = 0x8110,
MessageTypeConfigReportingRequest = 0x0120, // MessageTypeConfigReportingRequest = 0x0120,
MessageTypeConfigReportingResponse = 0x8120, // MessageTypeConfigReportingResponse = 0x8120,
MessageTypeReportAttributes = 0x8121, // MessageTypeReportAttributes = 0x8121,
MessageTypeAttributeDiscoveryRequest = 0x0140, // MessageTypeAttributeDiscoveryRequest = 0x0140,
MessageTypeAttributeDiscoveryResponse = 0x8140, // MessageTypeAttributeDiscoveryResponse = 0x8140,
// Persistant data manager messages // // Persistant data manager messages
MessageTypeDataManagerAvailableRequest = 0x0300, // MessageTypeDataManagerAvailableRequest = 0x0300,
MessageTypeDataManagerAvailableResponse = 0x8300, // MessageTypeDataManagerAvailableResponse = 0x8300,
MessageTypeDataManagerSaveRecordRequest = 0x0200, // MessageTypeDataManagerSaveRecordRequest = 0x0200,
MessageTypeDataManagerSaveRecordResponse = 0x8200, // MessageTypeDataManagerSaveRecordResponse = 0x8200,
MessageTypeDataManagerLoadRecordRequest = 0x0201, // MessageTypeDataManagerLoadRecordRequest = 0x0201,
MessageTypeDataManagerLoadRecordResponse = 0x8201, // MessageTypeDataManagerLoadRecordResponse = 0x8201,
MessageTypeDataManagerDeleteAllRecordsRequest = 0x0202, // MessageTypeDataManagerDeleteAllRecordsRequest = 0x0202,
MessageTypeDataManagerDeleteAllRecordsResponse = 0x8202, // MessageTypeDataManagerDeleteAllRecordsResponse = 0x8202,
// Appliance Statistics Cluster 0x0B03 // // Appliance Statistics Cluster 0x0B03
// http://www.nxp.com/documents/user_manual/JN-UG-3076.pdf // // http://www.nxp.com/documents/user_manual/JN-UG-3076.pdf
MessageTypeStatisticsClusterLogMessage = 0x0301, // Was 0x0500, was 0x0301 // MessageTypeStatisticsClusterLogMessage = 0x0301, // Was 0x0500, was 0x0301
MessageTypeStatisticsClusterLogMessageResponse = 0x8301, // MessageTypeStatisticsClusterLogMessageResponse = 0x8301,
// IAS Cluster // // IAS Cluster
MessageTypeSendIasZoneEnroolResponse = 0x0400, // MessageTypeSendIasZoneEnroolResponse = 0x0400,
MessageTypeIasZoneStatusChangeNotify = 0x8401, // MessageTypeIasZoneStatusChangeNotify = 0x8401,
// Extended utils // // Extended utils
MessageTypeRawApsDataRequest = 0x0530, // MessageTypeRawApsDataRequest = 0x0530,
MessageTypeRouterDiscoveryConfirm = 0x8701, // MessageTypeRouterDiscoveryConfirm = 0x8701,
MessageTypeApsDataConfirmFail = 0x8702 // MessageTypeApsDataConfirmFail = 0x8702
}; // };
Q_ENUM(InterfaceMessageType) // Q_ENUM(InterfaceMessageType)
enum ClusterId { enum ClusterId {
@ -616,6 +616,28 @@ public:
}; };
Q_ENUM(ZigbeeNwkLayerStatus) 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 { enum ZigbeeStatus {
ZigbeeStatusSuccess = 0x00, ZigbeeStatusSuccess = 0x00,
ZigbeeStatusFailure = 0x01, ZigbeeStatusFailure = 0x01,

View File

@ -81,10 +81,8 @@ private:
FrameControl m_frameControl; FrameControl m_frameControl;
quint8 m_destinationEndpoint; quint8 m_destinationEndpoint;
quint8 buildFrameControlByte(FrameControl frameControl); quint8 buildFrameControlByte(FrameControl frameControl);
FrameControl readFrameControlByte(quint8 frameControlByte); FrameControl readFrameControlByte(quint8 frameControlByte);
signals:
}; };

View File

@ -34,11 +34,6 @@
ZigbeeNetwork::ZigbeeNetwork(QObject *parent) : ZigbeeNetwork::ZigbeeNetwork(QObject *parent) :
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(); 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() void ZigbeeNetwork::saveNetwork()
{ {
qCDebug(dcZigbeeNetwork()) << "Save current network configuration to" << m_settingsFileName; qCDebug(dcZigbeeNetwork()) << "Save current network configuration to" << m_settingsFileName;
@ -308,10 +315,8 @@ void ZigbeeNetwork::loadNetwork()
settings.beginGroup("Nodes"); settings.beginGroup("Nodes");
foreach (const QString ieeeAddressString, settings.childGroups()) { foreach (const QString ieeeAddressString, settings.childGroups()) {
settings.beginGroup(ieeeAddressString); settings.beginGroup(ieeeAddressString);
quint16 shortAddress = static_cast<quint16>(settings.value("nwkAddress", 0).toUInt());
ZigbeeNode *node = createNode(this); ZigbeeNode *node = createNode(shortAddress, ZigbeeAddress(ieeeAddressString), this);
node->setExtendedAddress(ZigbeeAddress(ieeeAddressString));
node->setShortAddress(static_cast<quint16>(settings.value("nwkAddress", 0).toUInt()));
// Node descriptor // Node descriptor
node->m_nodeType = static_cast<ZigbeeNode::NodeType>(settings.value("nodeType", 0).toUInt()); 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++) { for (int i = 0; i < endpointsCount; i++) {
settings.setArrayIndex(i); settings.setArrayIndex(i);
quint8 endpointId = static_cast<quint8>(settings.value("id", 0).toUInt()); 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_profile = static_cast<Zigbee::ZigbeeProfile>(settings.value("profile", 0).toUInt());
endpoint->m_deviceId = static_cast<quint16>(settings.value("deviceId", 0).toUInt()); endpoint->m_deviceId = static_cast<quint16>(settings.value("deviceId", 0).toUInt());
endpoint->m_deviceVersion = static_cast<quint8>(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; return reply;
} }
void ZigbeeNetwork::setReplyResponseData(ZigbeeNetworkReply *reply, const QByteArray &responseData) void ZigbeeNetwork::setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeApsStatus zigbeeApsStatus)
{ {
reply->m_responseData = responseData; reply->m_zigbeeApsStatus = zigbeeApsStatus;
if (reply->isComplete()) {
if (reply->m_zigbeeStatus == Zigbee::ZigbeeStatusSuccess) {
finishNetworkReply(reply);
} else {
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeStatusError);
}
}
}
void ZigbeeNetwork::setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeStatus zigbeeStatus) if (reply->m_zigbeeApsStatus == Zigbee::ZigbeeApsStatusSuccess) {
{ finishNetworkReply(reply);
reply->m_zigbeeStatus = zigbeeStatus; } else {
reply->m_zigbeeConfirmArrived = true; finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeApsStatusError);
if (reply->isComplete()) {
if (reply->m_zigbeeStatus == Zigbee::ZigbeeStatusSuccess) {
finishNetworkReply(reply);
} else {
finishNetworkReply(reply, ZigbeeNetworkReply::ErrorZigbeeStatusError);
}
} }
} }

View File

@ -34,6 +34,7 @@
#include <QSqlDatabase> #include <QSqlDatabase>
#include "zigbeenode.h" #include "zigbeenode.h"
#include "zigbeenodeendpoint.h"
#include "zigbeechannelmask.h" #include "zigbeechannelmask.h"
#include "zigbeebridgecontroller.h" #include "zigbeebridgecontroller.h"
#include "zigbeesecurityconfiguration.h" #include "zigbeesecurityconfiguration.h"
@ -134,11 +135,7 @@ private:
QList<ZigbeeNode *> m_nodes; QList<ZigbeeNode *> m_nodes;
QList<ZigbeeNode *> m_uninitializedNodes; QList<ZigbeeNode *> m_uninitializedNodes;
QSqlDatabase m_db;
private: private:
bool initDB();
void addNodeInternally(ZigbeeNode *node); void addNodeInternally(ZigbeeNode *node);
void removeNodeInternally(ZigbeeNode *node); void removeNodeInternally(ZigbeeNode *node);
@ -148,7 +145,8 @@ protected:
bool m_permitJoining = false; bool m_permitJoining = false;
ZigbeeSecurityConfiguration m_securityConfiguration; 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; virtual void setPermitJoiningInternal(bool permitJoining) = 0;
void saveNetwork(); void saveNetwork();
@ -169,8 +167,7 @@ protected:
// Network reply methods // Network reply methods
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest()); ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
void setReplyResponseData(ZigbeeNetworkReply *reply, const QByteArray &responseData); void setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeApsStatus zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess);
void setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeStatus zigbeeStatus = Zigbee::ZigbeeStatusSuccess);
void finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error = ZigbeeNetworkReply::ErrorNoError); void finishNetworkReply(ZigbeeNetworkReply *reply, ZigbeeNetworkReply::Error error = ZigbeeNetworkReply::ErrorNoError);
signals: signals:

View File

@ -28,7 +28,6 @@
#include "zigbeenetworkmanager.h" #include "zigbeenetworkmanager.h"
#include "loggingcategory.h" #include "loggingcategory.h"
#include "nxp/zigbeenetworknxp.h"
#include "deconz/zigbeenetworkdeconz.h" #include "deconz/zigbeenetworkdeconz.h"
#include <QDateTime> #include <QDateTime>
@ -39,8 +38,8 @@ ZigbeeNetwork *ZigbeeNetworkManager::createZigbeeNetwork(ZigbeeNetworkManager::B
srand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000)); srand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
switch (backend) { switch (backend) {
case BackendTypeNxp: // case BackendTypeNxp:
return qobject_cast<ZigbeeNetwork *>(new ZigbeeNetworkNxp(parent)); // return qobject_cast<ZigbeeNetwork *>(new ZigbeeNetworkNxp(parent));
case BackendTypeDeconz: case BackendTypeDeconz:
return qobject_cast<ZigbeeNetwork *>(new ZigbeeNetworkDeconz(parent)); return qobject_cast<ZigbeeNetwork *>(new ZigbeeNetworkDeconz(parent));
} }

View File

@ -36,7 +36,6 @@ class ZigbeeNetworkManager
{ {
public: public:
enum BackendType { enum BackendType {
BackendTypeNxp,
BackendTypeDeconz BackendTypeDeconz
}; };

View File

@ -37,34 +37,9 @@ ZigbeeNetworkRequest ZigbeeNetworkReply::request() const
return m_request; return m_request;
} }
Zigbee::ZigbeeStatus ZigbeeNetworkReply::zigbeeStatus() const Zigbee::ZigbeeApsStatus ZigbeeNetworkReply::zigbeeApsStatus() const
{ {
return m_zigbeeStatus; return m_zigbeeApsStatus;
}
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;
} }
ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent) : ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent) :

View File

@ -43,30 +43,23 @@ class ZigbeeNetworkReply : public QObject
public: public:
enum Error { enum Error {
ErrorNoError, ErrorNoError,
ErrorZigbeeStatusError, ErrorZigbeeApsStatusError,
ErrorInterfaceError, ErrorInterfaceError,
ErrorNetworkOffline, ErrorNetworkOffline
ErrorNetworkNotImplemented,
ErrorUnknown
}; };
Q_ENUM(Error) Q_ENUM(Error)
Error error() const; Error error() const;
ZigbeeNetworkRequest request() const;
Zigbee::ZigbeeStatus zigbeeStatus() const;
QByteArray responseData() const;
bool isComplete() const; ZigbeeNetworkRequest request() const;
Zigbee::ZigbeeApsStatus zigbeeApsStatus() const;
private: private:
explicit ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr); explicit ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObject *parent = nullptr);
ZigbeeNetworkRequest m_request; ZigbeeNetworkRequest m_request;
bool m_finished = false;
Error m_error = ErrorNoError; Error m_error = ErrorNoError;
bool m_zigbeeConfirmArrived = false; Zigbee::ZigbeeApsStatus m_zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess;
Zigbee::ZigbeeStatus m_zigbeeStatus = Zigbee::ZigbeeStatusSuccess;
QByteArray m_responseData;
signals: signals:
void finished(); void finished();

View File

@ -144,26 +144,6 @@ void ZigbeeNetworkRequest::setRadius(quint8 radius)
m_radius = 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) QDebug operator<<(QDebug debug, const ZigbeeNetworkRequest &request)
{ {
debug.nospace() << "Request(ID:" << request.requestId() << ", "; 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() << "Source EP:" << ZigbeeUtils::convertByteToHexString(request.sourceEndpoint()) << ", ";
debug.nospace() << "Radius:" << request.radius() << ", "; debug.nospace() << "Radius:" << request.radius() << ", ";
debug.nospace() << request.txOptions() << ", "; debug.nospace() << request.txOptions() << ", ";
debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(request.asdu()) << ", "; debug.nospace() << ZigbeeUtils::convertByteArrayToHexString(request.asdu());
debug.nospace() << ")"; debug.nospace() << ")";
return debug.space(); return debug.space();
} }

View File

@ -72,13 +72,6 @@ public:
quint8 radius() const; quint8 radius() const;
void setRadius(quint8 radius); void setRadius(quint8 radius);
// Response expectations
bool expectIndication() const;
void setExpectIndication(bool expectIndication);
bool expectConfirmation() const;
void setExpectConfirmation(bool expectConfirmation);
private: private:
quint8 m_requestId = 0; quint8 m_requestId = 0;
Zigbee::DestinationAddressMode m_destinationAddressMode = Zigbee::DestinationAddressModeShortAddress; Zigbee::DestinationAddressMode m_destinationAddressMode = Zigbee::DestinationAddressModeShortAddress;
@ -92,8 +85,6 @@ private:
Zigbee::ZigbeeTxOptions m_txOptions = Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission); Zigbee::ZigbeeTxOptions m_txOptions = Zigbee::ZigbeeTxOptions(Zigbee::ZigbeeTxOptionAckTransmission);
quint8 m_radius = 0; quint8 m_radius = 0;
bool m_expectIndication = false;
bool m_expectConfirmation = true;
}; };
QDebug operator<<(QDebug debug, const ZigbeeNetworkRequest &request); QDebug operator<<(QDebug debug, const ZigbeeNetworkRequest &request);

View File

@ -32,11 +32,13 @@
#include <QDataStream> #include <QDataStream>
ZigbeeNode::ZigbeeNode(ZigbeeNetwork *network, QObject *parent) : ZigbeeNode::ZigbeeNode(ZigbeeNetwork *network, quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent) :
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 ZigbeeNode::State ZigbeeNode::state() const
@ -230,7 +232,7 @@ void ZigbeeNode::setState(ZigbeeNode::State state)
if (m_state == state) if (m_state == state)
return; return;
qCDebug(dcZigbeeNode()) << "State changed" << state; qCDebug(dcZigbeeNode()) << "State changed" << this << state;
m_state = state; m_state = state;
emit stateChanged(m_state); emit stateChanged(m_state);
} }
@ -240,7 +242,7 @@ void ZigbeeNode::setConnected(bool connected)
if (m_connected == connected) if (m_connected == connected)
return; return;
qCDebug(dcZigbeeNode()) << "Connected changed" << connected; qCDebug(dcZigbeeNode()) << "Connected changed" << this << connected;
m_connected = connected; m_connected = connected;
emit connectedChanged(m_connected); emit connectedChanged(m_connected);
} }
@ -410,10 +412,10 @@ void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag)
} }
// Bit 4 - 7 Available power sources // Bit 4 - 7 Available power sources
// Bit 0: Permanent mains supply // Bit 0: Permanent mains supply
// Bit 1: Rechargeable battery // Bit 1: Rechargeable battery
// Bit 2: Disposable battery // Bit 2: Disposable battery
// Bit 4: Reserved // Bit 4: Reserved
m_availablePowerSources.clear(); m_availablePowerSources.clear();
if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 4)) { if (ZigbeeUtils::checkBitUint16(m_powerDescriptorFlag, 4)) {
@ -450,19 +452,293 @@ void ZigbeeNode::setPowerDescriptorFlag(quint16 powerDescriptorFlag)
m_powerLevel = PowerLevelFull; m_powerLevel = PowerLevelFull;
} }
// qCDebug(dcZigbeeNode()) << "Node power descriptor (" << ZigbeeUtils::convertUint16ToHexString(m_powerDescriptorFlag) << "):"; // qCDebug(dcZigbeeNode()) << "Node power descriptor (" << ZigbeeUtils::convertUint16ToHexString(m_powerDescriptorFlag) << "):";
// qCDebug(dcZigbeeNode()) << " Power mode:" << m_powerMode; // qCDebug(dcZigbeeNode()) << " Power mode:" << m_powerMode;
// qCDebug(dcZigbeeNode()) << " Available power sources:"; // qCDebug(dcZigbeeNode()) << " Available power sources:";
// foreach (const PowerSource &source, m_availablePowerSources) { // foreach (const PowerSource &source, m_availablePowerSources) {
// qCDebug(dcZigbeeNode()) << " " << source; // qCDebug(dcZigbeeNode()) << " " << source;
// } // }
// qCDebug(dcZigbeeNode()) << " Power source:" << m_powerSource; // qCDebug(dcZigbeeNode()) << " Power source:" << m_powerSource;
// qCDebug(dcZigbeeNode()) << " Power level:" << m_powerLevel; // qCDebug(dcZigbeeNode()) << " Power level:" << m_powerLevel;
} }
void ZigbeeNode::startInitialization() 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) 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() << "ZigbeeNode(" << ZigbeeUtils::convertUint16ToHexString(node->shortAddress());
debug.nospace().noquote() << ", " << node->extendedAddress().toString(); debug.nospace().noquote() << ", " << node->extendedAddress().toString();
debug.nospace().noquote() << ", " << node->nodeType();
debug.nospace().noquote() << ")"; debug.nospace().noquote() << ")";
return debug.space(); return debug.space();
} }

View File

@ -100,6 +100,45 @@ public:
}; };
Q_ENUM(PowerLevel) 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; State state() const;
bool connected() const; bool connected() const;
@ -152,50 +191,11 @@ public:
QList<PowerSource> availablePowerSources() const; QList<PowerSource> availablePowerSources() const;
PowerLevel powerLevel() 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: private:
bool m_connected = false; ZigbeeNode(ZigbeeNetwork *network, quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent = nullptr);
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);
ZigbeeNetwork *m_network; ZigbeeNetwork *m_network;
ZigbeeDeviceObject *m_deviceObject = nullptr; ZigbeeDeviceObject *m_deviceObject = nullptr;
@ -235,9 +235,55 @@ protected:
quint16 powerDescriptorFlag() const; quint16 powerDescriptorFlag() const;
void setPowerDescriptorFlag(quint16 powerDescriptorFlag); void setPowerDescriptorFlag(quint16 powerDescriptorFlag);
// This method starts the node initialization phase (read descriptors and endpoints) bool m_connected = false;
virtual void startInitialization(); State m_state = StateUninitialized;
virtual ZigbeeNodeEndpoint *createNodeEndpoint(quint8 endpointId, QObject *parent) = 0;
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: signals:
void stateChanged(State state); void stateChanged(State state);

View File

@ -110,8 +110,9 @@ bool ZigbeeNodeEndpoint::hasOutputCluster(Zigbee::ClusterId clusterId) const
return m_outputClusters.keys().contains(clusterId); 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), QObject(parent),
m_network(network),
m_node(node), m_node(node),
m_endpointId(endpointId) m_endpointId(endpointId)
{ {
@ -163,10 +164,10 @@ ZigbeeNetworkReply *ZigbeeNodeEndpoint::createNetworkReply(const ZigbeeNetworkRe
return reply; 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_error = error;
reply->m_zigbeeStatus = zigbeeStatus; reply->m_zigbeeApsStatus = zigbeeApsStatus;
reply->finished(); reply->finished();
} }

View File

@ -36,6 +36,7 @@
#include "zigbeenetworkreply.h" #include "zigbeenetworkreply.h"
class ZigbeeNode; class ZigbeeNode;
class ZigbeeNetwork;
class ZigbeeNodeEndpoint : public QObject class ZigbeeNodeEndpoint : public QObject
{ {
@ -74,14 +75,15 @@ public:
bool hasOutputCluster(Zigbee::ClusterId clusterId) const; bool hasOutputCluster(Zigbee::ClusterId clusterId) const;
private: private:
explicit ZigbeeNodeEndpoint(ZigbeeNetwork *network, ZigbeeNode *node, quint8 endpointId, QObject *parent = nullptr);
ZigbeeNetwork *m_network = nullptr;
ZigbeeNode *m_node = nullptr; ZigbeeNode *m_node = nullptr;
quint8 m_endpointId = 0; quint8 m_endpointId = 0;
Zigbee::ZigbeeProfile m_profile = Zigbee::ZigbeeProfileLightLink; Zigbee::ZigbeeProfile m_profile = Zigbee::ZigbeeProfileLightLink;
quint16 m_deviceId = 0; quint16 m_deviceId = 0;
quint8 m_deviceVersion = 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_inputClusters;
QHash<Zigbee::ClusterId, ZigbeeCluster *> m_outputClusters; QHash<Zigbee::ClusterId, ZigbeeCluster *> m_outputClusters;
@ -95,14 +97,14 @@ protected:
void setSoftwareBuildId(const QString &softwareBuildId); void setSoftwareBuildId(const QString &softwareBuildId);
// Cluster commands // 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 addInputCluster(ZigbeeCluster *cluster);
void addOutputCluster(ZigbeeCluster *cluster); void addOutputCluster(ZigbeeCluster *cluster);
// Network reply methods // Network reply methods
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest()); 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: signals:
void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute); void clusterAttributeChanged(ZigbeeCluster *cluster, const ZigbeeClusterAttribute &attribute);

View File

@ -260,15 +260,15 @@ QString ZigbeeUtils::convertUint64ToHexString(const quint64 &value)
return QString("0x%1").arg(convertByteArrayToHexString(data).remove(" ").remove("0x")); return QString("0x%1").arg(convertByteArrayToHexString(data).remove(" ").remove("0x"));
} }
QString ZigbeeUtils::messageTypeToString(const Zigbee::InterfaceMessageType &type) //QString ZigbeeUtils::messageTypeToString(const Zigbee::InterfaceMessageType &type)
{ //{
QMetaObject metaObject = Zigbee::staticMetaObject; // QMetaObject metaObject = Zigbee::staticMetaObject;
QMetaEnum metaEnum = metaObject.enumerator(metaObject.indexOfEnumerator("InterfaceMessageType")); // 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) QString ZigbeeUtils::clusterIdToString(const Zigbee::ClusterId &clusterId)
{ {

View File

@ -61,7 +61,7 @@ public:
static QString convertUint64ToHexString(const quint64 &value); static QString convertUint64ToHexString(const quint64 &value);
// Enum prittify print methods // 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 clusterIdToString(const Zigbee::ClusterId &clusterId);
static QString profileIdToString(const Zigbee::ZigbeeProfile &profileId); static QString profileIdToString(const Zigbee::ZigbeeProfile &profileId);