Move common data process mechanism to network base class
This commit is contained in:
parent
3997b5a5de
commit
40d6fdaa90
@ -378,57 +378,6 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication)
|
|
||||||
{
|
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Handle ZDP indication" << indication;
|
|
||||||
|
|
||||||
// Check if this is a device announcement
|
|
||||||
if (indication.clusterId == ZigbeeDeviceProfile::DeviceAnnounce) {
|
|
||||||
QDataStream stream(indication.asdu);
|
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
|
||||||
quint8 sequenceNumber = 0; quint16 shortAddress = 0; quint64 ieeeAddress = 0; quint8 macFlag = 0;
|
|
||||||
stream >> sequenceNumber >> shortAddress >> ieeeAddress >> macFlag;
|
|
||||||
onDeviceAnnounced(shortAddress, ZigbeeAddress(ieeeAddress), macFlag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indication.destinationShortAddress == Zigbee::BroadcastAddressAllNodes ||
|
|
||||||
indication.destinationShortAddress == Zigbee::BroadcastAddressAllRouters ||
|
|
||||||
indication.destinationShortAddress == Zigbee::BroadcastAddressAllNonSleepingNodes) {
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Received unhandled broadcast ZDO indication" << indication;
|
|
||||||
|
|
||||||
// FIXME: check what we can do with such messages like permit join
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
|
|
||||||
if (!node) {
|
|
||||||
qCWarning(dcZigbeeNetwork()) << "Received a ZDO indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
|
||||||
// FIXME: check if we want to create it since the device definitly exists within the network
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let the node handle this indication
|
|
||||||
handleNodeIndication(node, indication);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication)
|
|
||||||
{
|
|
||||||
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(indication.asdu);
|
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Handle ZCL indication" << indication << frame;
|
|
||||||
|
|
||||||
// Get the node
|
|
||||||
ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
|
|
||||||
if (!node) {
|
|
||||||
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
|
||||||
// FIXME: maybe create and init the node, since it is in the network, but not recognized
|
|
||||||
// FIXME: maybe remove this node since we might have removed it but it did not respond, or we not explicitly allowed it to join.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Let the node handle this indication
|
|
||||||
handleNodeIndication(node, indication);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::startNetworkInternally()
|
void ZigbeeNetworkDeconz::startNetworkInternally()
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeNetwork()) << "Start zigbee network internally";
|
qCDebug(dcZigbeeNetwork()) << "Start zigbee network internally";
|
||||||
@ -659,34 +608,6 @@ void ZigbeeNetworkDeconz::onApsDataIndicationReceived(const Zigbee::ApsdeDataInd
|
|||||||
handleZigbeeClusterLibraryIndication(indication);
|
handleZigbeeClusterLibraryIndication(indication);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities)
|
|
||||||
{
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Device announced" << ZigbeeUtils::convertUint16ToHexString(shortAddress) << ieeeAddress.toString() << ZigbeeUtils::convertByteToHexString(macCapabilities);
|
|
||||||
|
|
||||||
// Lets check if this device is in the uninitialized node list, if so, remove it and recreate the device
|
|
||||||
if (hasUninitializedNode(ieeeAddress)) {
|
|
||||||
qCWarning(dcZigbeeNetwork()) << "Device announced but there is already an initialization running for it. Remove the device and restart the initialization.";
|
|
||||||
ZigbeeNode *uninitializedNode = getZigbeeNode(ieeeAddress);
|
|
||||||
removeUninitializedNode(uninitializedNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasNode(ieeeAddress)) {
|
|
||||||
ZigbeeNode *node = getZigbeeNode(ieeeAddress);
|
|
||||||
if (shortAddress == node->shortAddress()) {
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Already known device announced and is reachable again" << node;
|
|
||||||
setNodeReachable(node, true);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Already known device announced with different network address. Removing node and reinitialize...";
|
|
||||||
removeNode(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZigbeeNode *node = createNode(shortAddress, ieeeAddress, macCapabilities, this);
|
|
||||||
addUnitializedNode(node);
|
|
||||||
node->startInitialization();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNetworkDeconz::startNetwork()
|
void ZigbeeNetworkDeconz::startNetwork()
|
||||||
{
|
{
|
||||||
loadNetwork();
|
loadNetwork();
|
||||||
|
|||||||
@ -73,12 +73,6 @@ private:
|
|||||||
|
|
||||||
ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
|
ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
|
||||||
|
|
||||||
// ZDO
|
|
||||||
void handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication);
|
|
||||||
|
|
||||||
// ZCL
|
|
||||||
void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void startNetworkInternally();
|
void startNetworkInternally();
|
||||||
|
|
||||||
@ -89,7 +83,6 @@ private slots:
|
|||||||
void onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm);
|
void onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm);
|
||||||
void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication);
|
void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication);
|
||||||
|
|
||||||
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void startNetwork() override;
|
void startNetwork() override;
|
||||||
|
|||||||
@ -306,55 +306,6 @@ bool ZigbeeNetworkNxp::processVersionReply(ZigbeeInterfaceNxpReply *reply)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkNxp::handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication)
|
|
||||||
{
|
|
||||||
// Check if this is a device announcement
|
|
||||||
if (indication.clusterId == ZigbeeDeviceProfile::DeviceAnnounce) {
|
|
||||||
QDataStream stream(indication.asdu);
|
|
||||||
stream.setByteOrder(QDataStream::LittleEndian);
|
|
||||||
quint8 sequenceNumber = 0; quint16 shortAddress = 0; quint64 ieeeAddress = 0; quint8 macFlag = 0;
|
|
||||||
stream >> sequenceNumber >> shortAddress >> ieeeAddress >> macFlag;
|
|
||||||
onDeviceAnnounced(shortAddress, ZigbeeAddress(ieeeAddress), macFlag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indication.destinationShortAddress == Zigbee::BroadcastAddressAllNodes ||
|
|
||||||
indication.destinationShortAddress == Zigbee::BroadcastAddressAllRouters ||
|
|
||||||
indication.destinationShortAddress == Zigbee::BroadcastAddressAllNonSleepingNodes) {
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Received unhandled broadcast ZDO indication" << indication;
|
|
||||||
|
|
||||||
// FIXME: check what we can do with such messages like permit join
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
|
|
||||||
if (!node) {
|
|
||||||
qCWarning(dcZigbeeNetwork()) << "Received a ZDO indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
|
||||||
// FIXME: check if we want to create it since the device definitly exists within the network
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let the node handle this indication
|
|
||||||
handleNodeIndication(node, indication);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNetworkNxp::handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication)
|
|
||||||
{
|
|
||||||
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(indication.asdu);
|
|
||||||
//qCDebug(dcZigbeeNetwork()) << "Handle ZCL indication" << indication << frame;
|
|
||||||
|
|
||||||
// Get the node
|
|
||||||
ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
|
|
||||||
if (!node) {
|
|
||||||
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
|
||||||
// FIXME: maybe create and init the node, since it is in the network, but not recognized
|
|
||||||
// FIXME: maybe remove this node since we might have removed it but it did not respond, or we not explicitly allowed it to join.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Let the node handle this indication
|
|
||||||
handleNodeIndication(node, indication);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNetworkNxp::onControllerAvailableChanged(bool available)
|
void ZigbeeNetworkNxp::onControllerAvailableChanged(bool available)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeNetwork()) << "Controller is" << (available ? "now available" : "not available any more");
|
qCDebug(dcZigbeeNetwork()) << "Controller is" << (available ? "now available" : "not available any more");
|
||||||
@ -603,36 +554,6 @@ void ZigbeeNetworkNxp::onApsDataIndicationReceived(const Zigbee::ApsdeDataIndica
|
|||||||
handleZigbeeClusterLibraryIndication(indication);
|
handleZigbeeClusterLibraryIndication(indication);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZigbeeNetworkNxp::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities)
|
|
||||||
{
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Device announced" << ZigbeeUtils::convertUint16ToHexString(shortAddress) << ieeeAddress.toString() << ZigbeeUtils::convertByteToHexString(macCapabilities);
|
|
||||||
|
|
||||||
// Lets check if this device is in the uninitialized node list, if so, remove it and recreate the device
|
|
||||||
if (hasUninitializedNode(ieeeAddress)) {
|
|
||||||
qCWarning(dcZigbeeNetwork()) << "Device announced but there is already an initialization running for it. Remove the device and restart the initialization.";
|
|
||||||
ZigbeeNode *uninitializedNode = getZigbeeNode(ieeeAddress);
|
|
||||||
removeUninitializedNode(uninitializedNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasNode(ieeeAddress)) {
|
|
||||||
ZigbeeNode *node = getZigbeeNode(ieeeAddress);
|
|
||||||
if (shortAddress == node->shortAddress()) {
|
|
||||||
qCDebug(dcZigbeeNetwork()) << "Already known device announced and is reachable again" << node;
|
|
||||||
setNodeReachable(node, true);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
qCWarning(dcZigbeeNetwork()) << "Already known device announced with different network address. FIXME: update the network address or reinitialize node...";
|
|
||||||
|
|
||||||
|
|
||||||
//removeNode(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZigbeeNode *node = createNode(shortAddress, ieeeAddress, macCapabilities, this);
|
|
||||||
addUnitializedNode(node);
|
|
||||||
node->startInitialization();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZigbeeNetworkNxp::onNodeLeftIndication(const ZigbeeAddress &ieeeAddress, bool rejoining)
|
void ZigbeeNetworkNxp::onNodeLeftIndication(const ZigbeeAddress &ieeeAddress, bool rejoining)
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeNetwork()) << "Received node left indication" << ieeeAddress.toString() << "rejoining:" << rejoining;
|
qCDebug(dcZigbeeNetwork()) << "Received node left indication" << ieeeAddress.toString() << "rejoining:" << rejoining;
|
||||||
|
|||||||
@ -62,12 +62,6 @@ private:
|
|||||||
int m_reconnectCounter = 0;
|
int m_reconnectCounter = 0;
|
||||||
bool processVersionReply(ZigbeeInterfaceNxpReply *reply);
|
bool processVersionReply(ZigbeeInterfaceNxpReply *reply);
|
||||||
|
|
||||||
// ZDO
|
|
||||||
void handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication);
|
|
||||||
|
|
||||||
// ZCL
|
|
||||||
void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication);
|
|
||||||
|
|
||||||
ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
|
ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
@ -78,7 +72,6 @@ private slots:
|
|||||||
void onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm);
|
void onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm);
|
||||||
void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication);
|
void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication);
|
||||||
|
|
||||||
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
|
|
||||||
void onNodeLeftIndication(const ZigbeeAddress &ieeeAddress, bool rejoining);
|
void onNodeLeftIndication(const ZigbeeAddress &ieeeAddress, bool rejoining);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|||||||
@ -42,6 +42,104 @@ ZigbeeDeviceObject::ZigbeeDeviceObject(ZigbeeNetwork *network, ZigbeeNode *node,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestNetworkAddress()
|
||||||
|
{
|
||||||
|
qCDebug(dcZigbeeDeviceObject()) << "Request network address from" << m_node;
|
||||||
|
|
||||||
|
// Build APS request and make ieee address request
|
||||||
|
ZigbeeNetworkRequest request;
|
||||||
|
request.setRequestId(m_network->generateSequenceNumber());
|
||||||
|
request.setDestinationAddressMode(Zigbee::DestinationAddressModeIeeeAddress);
|
||||||
|
request.setDestinationIeeeAddress(m_node->extendedAddress());
|
||||||
|
request.setDestinationEndpoint(0); // ZDO
|
||||||
|
request.setProfileId(Zigbee::ZigbeeProfileDevice); // ZDP
|
||||||
|
request.setClusterId(ZigbeeDeviceProfile::NetworkAddressRequest);
|
||||||
|
request.setSourceEndpoint(0); // ZDO
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
stream << m_node->extendedAddress().toUInt64();
|
||||||
|
stream << static_cast<quint8>(0); // Note: 0 = single device response, 1 = extended request
|
||||||
|
stream << static_cast<quint8>(0); // Start index
|
||||||
|
|
||||||
|
// 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)) {
|
||||||
|
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::requestIeeeAddress()
|
||||||
|
{
|
||||||
|
qCDebug(dcZigbeeDeviceObject()) << "Request IEEE address from" << m_node;
|
||||||
|
|
||||||
|
// Build APS request
|
||||||
|
ZigbeeNetworkRequest request = buildZdoRequest(ZigbeeDeviceProfile::IeeeAddressRequest);
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
stream << static_cast<quint8>(0); // Note: 0 = single device response, 1 = extended request
|
||||||
|
stream << static_cast<quint8>(0); // Start index
|
||||||
|
|
||||||
|
// 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)) {
|
||||||
|
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::requestNodeDescriptor()
|
ZigbeeDeviceObjectReply *ZigbeeDeviceObject::requestNodeDescriptor()
|
||||||
{
|
{
|
||||||
qCDebug(dcZigbeeDeviceObject()) << "Request node descriptor from" << m_node;
|
qCDebug(dcZigbeeDeviceObject()) << "Request node descriptor from" << m_node;
|
||||||
|
|||||||
@ -43,6 +43,8 @@ public:
|
|||||||
explicit ZigbeeDeviceObject(ZigbeeNetwork *network, ZigbeeNode *node, QObject *parent = nullptr);
|
explicit ZigbeeDeviceObject(ZigbeeNetwork *network, ZigbeeNode *node, QObject *parent = nullptr);
|
||||||
|
|
||||||
// Device and service discovery
|
// Device and service discovery
|
||||||
|
ZigbeeDeviceObjectReply *requestNetworkAddress();
|
||||||
|
ZigbeeDeviceObjectReply *requestIeeeAddress();
|
||||||
ZigbeeDeviceObjectReply *requestNodeDescriptor();
|
ZigbeeDeviceObjectReply *requestNodeDescriptor();
|
||||||
ZigbeeDeviceObjectReply *requestPowerDescriptor();
|
ZigbeeDeviceObjectReply *requestPowerDescriptor();
|
||||||
ZigbeeDeviceObjectReply *requestActiveEndpoints();
|
ZigbeeDeviceObjectReply *requestActiveEndpoints();
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
ZigbeeNetwork::ZigbeeNetwork(const QUuid &networkUuid, QObject *parent) :
|
ZigbeeNetwork::ZigbeeNetwork(const QUuid &networkUuid, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
@ -609,6 +610,84 @@ void ZigbeeNetwork::handleNodeIndication(ZigbeeNode *node, const Zigbee::ApsdeDa
|
|||||||
node->handleDataIndication(indication);
|
node->handleDataIndication(indication);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetwork::handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication)
|
||||||
|
{
|
||||||
|
// Check if this is a device announcement
|
||||||
|
if (indication.clusterId == ZigbeeDeviceProfile::DeviceAnnounce) {
|
||||||
|
QDataStream stream(indication.asdu);
|
||||||
|
stream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
quint8 sequenceNumber = 0; quint16 shortAddress = 0; quint64 ieeeAddress = 0; quint8 macFlag = 0;
|
||||||
|
stream >> sequenceNumber >> shortAddress >> ieeeAddress >> macFlag;
|
||||||
|
onDeviceAnnounced(shortAddress, ZigbeeAddress(ieeeAddress), macFlag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indication.destinationShortAddress == Zigbee::BroadcastAddressAllNodes ||
|
||||||
|
indication.destinationShortAddress == Zigbee::BroadcastAddressAllRouters ||
|
||||||
|
indication.destinationShortAddress == Zigbee::BroadcastAddressAllNonSleepingNodes) {
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "Received unhandled broadcast ZDO indication" << indication;
|
||||||
|
|
||||||
|
// FIXME: check what we can do with such messages like permit join
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
|
||||||
|
if (!node) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Received a ZDO indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
||||||
|
// FIXME: check if we want to create it since the device definitly exists within the network
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the node handle this indication
|
||||||
|
handleNodeIndication(node, indication);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetwork::handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication)
|
||||||
|
{
|
||||||
|
ZigbeeClusterLibrary::Frame frame = ZigbeeClusterLibrary::parseFrameData(indication.asdu);
|
||||||
|
//qCDebug(dcZigbeeNetwork()) << "Handle ZCL indication" << indication << frame;
|
||||||
|
|
||||||
|
// Get the node
|
||||||
|
ZigbeeNode *node = getZigbeeNode(indication.sourceShortAddress);
|
||||||
|
if (!node) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Received a ZCL indication for an unrecognized node. There is no such node in the system. Ignoring indication" << indication;
|
||||||
|
// FIXME: maybe create and init the node, since it is in the network, but not recognized
|
||||||
|
// FIXME: maybe remove this node since we might have removed it but it did not respond, or we not explicitly allowed it to join.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Let the node handle this indication
|
||||||
|
handleNodeIndication(node, indication);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigbeeNetwork::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities)
|
||||||
|
{
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "Device announced" << ZigbeeUtils::convertUint16ToHexString(shortAddress) << ieeeAddress.toString() << ZigbeeUtils::convertByteToHexString(macCapabilities);
|
||||||
|
|
||||||
|
// Lets check if this device is in the uninitialized node list, if so, remove it and recreate the device
|
||||||
|
if (hasUninitializedNode(ieeeAddress)) {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Device announced but there is already an initialization running for it. Remove the device and restart the initialization.";
|
||||||
|
ZigbeeNode *uninitializedNode = getZigbeeNode(ieeeAddress);
|
||||||
|
removeUninitializedNode(uninitializedNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasNode(ieeeAddress)) {
|
||||||
|
ZigbeeNode *node = getZigbeeNode(ieeeAddress);
|
||||||
|
if (shortAddress == node->shortAddress()) {
|
||||||
|
qCDebug(dcZigbeeNetwork()) << "Already known device announced and is reachable again" << node;
|
||||||
|
setNodeReachable(node, true);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
qCWarning(dcZigbeeNetwork()) << "Already known device announced with different network address. FIXME: update the network address or reinitialize node...";
|
||||||
|
//removeNode(node);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZigbeeNode *node = createNode(shortAddress, ieeeAddress, macCapabilities, this);
|
||||||
|
addUnitializedNode(node);
|
||||||
|
node->startInitialization();
|
||||||
|
}
|
||||||
|
|
||||||
ZigbeeNetworkReply *ZigbeeNetwork::createNetworkReply(const ZigbeeNetworkRequest &request)
|
ZigbeeNetworkReply *ZigbeeNetwork::createNetworkReply(const ZigbeeNetworkRequest &request)
|
||||||
{
|
{
|
||||||
ZigbeeNetworkReply *reply = new ZigbeeNetworkReply(request, this);
|
ZigbeeNetworkReply *reply = new ZigbeeNetworkReply(request, this);
|
||||||
|
|||||||
@ -202,6 +202,14 @@ protected:
|
|||||||
|
|
||||||
void handleNodeIndication(ZigbeeNode *node, const Zigbee::ApsdeDataIndication indication);
|
void handleNodeIndication(ZigbeeNode *node, const Zigbee::ApsdeDataIndication indication);
|
||||||
|
|
||||||
|
// ZDO
|
||||||
|
void handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication);
|
||||||
|
|
||||||
|
// ZCL
|
||||||
|
void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication);
|
||||||
|
|
||||||
|
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
|
||||||
|
|
||||||
// Network reply methods
|
// Network reply methods
|
||||||
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
|
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
|
||||||
void setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeApsStatus zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess);
|
void setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeApsStatus zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess);
|
||||||
|
|||||||
@ -58,7 +58,7 @@ ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObj
|
|||||||
{
|
{
|
||||||
m_timer = new QTimer(this);
|
m_timer = new QTimer(this);
|
||||||
m_timer->setSingleShot(true);
|
m_timer->setSingleShot(true);
|
||||||
m_timer->setInterval(8000);
|
m_timer->setInterval(10000);
|
||||||
connect(m_timer, &QTimer::timeout, this, [this](){
|
connect(m_timer, &QTimer::timeout, this, [this](){
|
||||||
m_error = ErrorTimeout;
|
m_error = ErrorTimeout;
|
||||||
emit finished();
|
emit finished();
|
||||||
|
|||||||
Reference in New Issue
Block a user