Move common data process mechanism to network base class

pull/10/head
Simon Stürz 2020-12-09 10:53:33 +01:00
parent 3997b5a5de
commit 40d6fdaa90
9 changed files with 188 additions and 173 deletions

View File

@ -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()
{
qCDebug(dcZigbeeNetwork()) << "Start zigbee network internally";
@ -659,34 +608,6 @@ void ZigbeeNetworkDeconz::onApsDataIndicationReceived(const Zigbee::ApsdeDataInd
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()
{
loadNetwork();

View File

@ -73,12 +73,6 @@ private:
ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
// ZDO
void handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication);
// ZCL
void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication);
protected:
void startNetworkInternally();
@ -89,7 +83,6 @@ private slots:
void onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm);
void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication);
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
public slots:
void startNetwork() override;

View File

@ -306,55 +306,6 @@ bool ZigbeeNetworkNxp::processVersionReply(ZigbeeInterfaceNxpReply *reply)
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)
{
qCDebug(dcZigbeeNetwork()) << "Controller is" << (available ? "now available" : "not available any more");
@ -603,36 +554,6 @@ void ZigbeeNetworkNxp::onApsDataIndicationReceived(const Zigbee::ApsdeDataIndica
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)
{
qCDebug(dcZigbeeNetwork()) << "Received node left indication" << ieeeAddress.toString() << "rejoining:" << rejoining;

View File

@ -62,12 +62,6 @@ private:
int m_reconnectCounter = 0;
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);
private slots:
@ -78,7 +72,6 @@ private slots:
void onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm);
void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication);
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
void onNodeLeftIndication(const ZigbeeAddress &ieeeAddress, bool rejoining);
signals:

View File

@ -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()
{
qCDebug(dcZigbeeDeviceObject()) << "Request node descriptor from" << m_node;

View File

@ -43,6 +43,8 @@ public:
explicit ZigbeeDeviceObject(ZigbeeNetwork *network, ZigbeeNode *node, QObject *parent = nullptr);
// Device and service discovery
ZigbeeDeviceObjectReply *requestNetworkAddress();
ZigbeeDeviceObjectReply *requestIeeeAddress();
ZigbeeDeviceObjectReply *requestNodeDescriptor();
ZigbeeDeviceObjectReply *requestPowerDescriptor();
ZigbeeDeviceObjectReply *requestActiveEndpoints();

View File

@ -34,6 +34,7 @@
#include <QDir>
#include <QFileInfo>
#include <QDataStream>
ZigbeeNetwork::ZigbeeNetwork(const QUuid &networkUuid, QObject *parent) :
QObject(parent),
@ -609,6 +610,84 @@ void ZigbeeNetwork::handleNodeIndication(ZigbeeNode *node, const Zigbee::ApsdeDa
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 *reply = new ZigbeeNetworkReply(request, this);

View File

@ -202,6 +202,14 @@ protected:
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
ZigbeeNetworkReply *createNetworkReply(const ZigbeeNetworkRequest &request = ZigbeeNetworkRequest());
void setReplyResponseError(ZigbeeNetworkReply *reply, Zigbee::ZigbeeApsStatus zigbeeApsStatus = Zigbee::ZigbeeApsStatusSuccess);

View File

@ -58,7 +58,7 @@ ZigbeeNetworkReply::ZigbeeNetworkReply(const ZigbeeNetworkRequest &request, QObj
{
m_timer = new QTimer(this);
m_timer->setSingleShot(true);
m_timer->setInterval(8000);
m_timer->setInterval(10000);
connect(m_timer, &QTimer::timeout, this, [this](){
m_error = ErrorTimeout;
emit finished();