diff --git a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp index 9bbe543..b0953b3 100644 --- a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp +++ b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.cpp @@ -46,10 +46,6 @@ ZigbeeNetworkDeconz::ZigbeeNetworkDeconz(const QUuid &networkUuid, QObject *pare m_pollNetworkStateTimer->setSingleShot(false); connect(m_pollNetworkStateTimer, &QTimer::timeout, this, &ZigbeeNetworkDeconz::onPollNetworkStateTimeout); - m_permitJoinRefreshTimer = new QTimer(this); - m_permitJoinRefreshTimer->setInterval(250 * 1000); - m_permitJoinRefreshTimer->setSingleShot(false); - connect(m_permitJoinRefreshTimer, &QTimer::timeout, this, &ZigbeeNetworkDeconz::onPermitJoinRefreshTimout); } ZigbeeBridgeController *ZigbeeNetworkDeconz::bridgeController() const @@ -95,7 +91,60 @@ ZigbeeNetworkReply *ZigbeeNetworkDeconz::sendRequest(const ZigbeeNetworkRequest return reply; } -ZigbeeNetworkReply *ZigbeeNetworkDeconz::setPermitJoin(quint16 shortAddress, quint8 duration) +void ZigbeeNetworkDeconz::setPermitJoining(quint8 duration, quint16 address) +{ + if (duration > 0) { + qCDebug(dcZigbeeNetwork()) << "Set permit join for" << duration << "s on" << ZigbeeUtils::convertUint16ToHexString(address); + } else { + qCDebug(dcZigbeeNetwork()) << "Disable permit join on"<< ZigbeeUtils::convertUint16ToHexString(address); + } + + // Note: will be reseted if permit join will not work + setPermitJoiningEnabled(duration > 0); + setPermitJoiningDuration(duration); + setPermitJoiningRemaining(duration); + + // Note: since compliance version >= 21 the value 255 is not any more endless. + // We need to refresh the command on timeout repeatedly if the duration is longer than 254 s + + ZigbeeNetworkReply *reply = requestSetPermitJoin(address, duration); + connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply, duration, address](){ + if (reply->zigbeeApsStatus() != Zigbee::ZigbeeApsStatusSuccess) { + qCWarning(dcZigbeeNetwork()) << "Could not set permit join to" << duration << ZigbeeUtils::convertUint16ToHexString(address) << reply->zigbeeApsStatus(); + setPermitJoiningEnabled(false); + setPermitJoiningDuration(duration); + return; + } + qCDebug(dcZigbeeNetwork()) << "Permit join request finished successfully"; + + setPermitJoiningEnabled(duration > 0); + setPermitJoiningDuration(duration); + setPermitJoiningRemaining(duration); + if (duration > 0) { + m_permitJoinTimer->start(); + } else { + m_permitJoinTimer->stop(); + } + + // Set the permit joining timeout network configuration parameter + QByteArray parameterData; + QDataStream stream(¶meterData, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << duration; + + ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterPermitJoin, parameterData); + connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [reply](){ + if (reply->statusCode() != Deconz::StatusCodeSuccess) { + qCWarning(dcZigbeeController()) << "Request" << reply->command() << "finished with error" << reply->statusCode(); + return; + } + + qCDebug(dcZigbeeNetwork()) << "Set permit join configuration request finished" << reply->statusCode(); + }); + }); +} + +ZigbeeNetworkReply *ZigbeeNetworkDeconz::requestSetPermitJoin(quint16 shortAddress, quint8 duration) { // Get the power descriptor ZigbeeNetworkRequest request; @@ -305,7 +354,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo m_database->saveNode(m_coordinatorNode); m_initializing = false; setState(StateRunning); - setPermitJoiningInternal(false); + setPermitJoining(0); return; } @@ -318,7 +367,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode; m_initializing = false; setState(StateRunning); - setPermitJoiningInternal(false); + setPermitJoining(0); return; } }); @@ -380,67 +429,10 @@ void ZigbeeNetworkDeconz::handleZigbeeClusterLibraryIndication(const Zigbee::Aps handleNodeIndication(node, indication); } -void ZigbeeNetworkDeconz::setPermitJoiningInternal(bool permitJoining) -{ - quint8 duration = 0; - if (permitJoining == true) { - duration = 254; - } - - // Note: since compliance version >= 21 the value 255 is not any more Qt::endless. - // we need to refresh the command on timeout - - ZigbeeNetworkReply *reply = setPermitJoin(Zigbee::BroadcastAddressAllRouters, duration); - connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply, permitJoining, duration](){ - if (reply->zigbeeApsStatus() != Zigbee::ZigbeeApsStatusSuccess) { - qCDebug(dcZigbeeNetwork()) << "Could not set permit join to" << duration; - if (m_permitJoining != false) { - m_permitJoining = false; - emit permitJoiningChanged(m_permitJoining); - } - return; - } - qCDebug(dcZigbeeNetwork()) << "Permit join request finished successfully"; - if (permitJoining) { - m_permitJoinRefreshTimer->start(); - } else { - m_permitJoinRefreshTimer->stop(); - } - - if (m_permitJoining != permitJoining) { - m_permitJoining = permitJoining; - emit permitJoiningChanged(m_permitJoining); - } - - // Set the permit joining timeout network configuration parameter - QByteArray parameterData; - QDataStream stream(¶meterData, QIODevice::WriteOnly); - stream.setByteOrder(QDataStream::LittleEndian); - stream << duration; - - ZigbeeInterfaceDeconzReply *reply = m_controller->requestWriteParameter(Deconz::ParameterPermitJoin, parameterData); - connect(reply, &ZigbeeInterfaceDeconzReply::finished, this, [reply](){ - if (reply->statusCode() != Deconz::StatusCodeSuccess) { - qCWarning(dcZigbeeController()) << "Request" << reply->command() << "finished with error" << reply->statusCode(); - // FIXME: set an appropriate error - return; - } - - qCDebug(dcZigbeeNetwork()) << "Set permit join configuration request finished" << reply->statusCode(); - }); - }); -} - void ZigbeeNetworkDeconz::startNetworkInternally() { qCDebug(dcZigbeeNetwork()) << "Start zigbee network internally"; - if (!m_database) { - QString networkDatabaseFileName = settingsDirectory().absolutePath() + QDir::separator() + QString("zigbee-network-%1.db").arg(networkUuid().toString().remove('{').remove('}')); - qCDebug(dcZigbeeNetwork()) << "Using ZigBee network database" << QFileInfo(networkDatabaseFileName).fileName(); - m_database = new ZigbeeNetworkDatabase(this, networkDatabaseFileName, this); - } - m_createNewNetwork = false; // Check if we have to create a pan ID and select the channel if (panId() == 0 || !m_coordinatorNode) { @@ -525,7 +517,7 @@ void ZigbeeNetworkDeconz::startNetworkInternally() if (m_controller->networkState() == Deconz::NetworkStateConnected) { qCDebug(dcZigbeeNetwork()) << "The network is already running."; m_initializing = false; - setPermitJoining(false); + setPermitJoiningEnabled(false); // Set the permit joining timeout network configuration parameter QByteArray parameterData; QDataStream stream(¶meterData, QIODevice::WriteOnly); @@ -563,18 +555,11 @@ void ZigbeeNetworkDeconz::onControllerAvailableChanged(bool available) qCWarning(dcZigbeeNetwork()) << "Hardware controller is not available any more."; setError(ErrorHardwareUnavailable); m_initializing = false; - if (m_permitJoining != false) { - m_permitJoining = false; - emit permitJoiningChanged(m_permitJoining); - } + setPermitJoiningEnabled(false); setState(StateOffline); } else { m_error = ErrorNoError; - if (m_permitJoining != false) { - m_permitJoining = false; - emit permitJoiningChanged(m_permitJoining); - } - emit permitJoiningChanged(m_permitJoining); + setPermitJoiningEnabled(false); setState(StateStarting); qCDebug(dcZigbeeNetwork()) << "Hardware controller is now available."; startNetworkInternally(); @@ -651,11 +636,6 @@ void ZigbeeNetworkDeconz::onPollNetworkStateTimeout() } } -void ZigbeeNetworkDeconz::onPermitJoinRefreshTimout() -{ - setPermitJoiningInternal(true); -} - void ZigbeeNetworkDeconz::onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm) { ZigbeeNetworkReply *reply = m_pendingReplies.value(confirm.requestId); @@ -705,22 +685,17 @@ void ZigbeeNetworkDeconz::startNetwork() loadNetwork(); if (!m_controller->enable(serialPortName(), serialBaudrate())) { - m_permitJoining = false; - emit permitJoiningChanged(m_permitJoining); + setPermitJoiningEnabled(false); setState(StateOffline); setCreateNetworkState(CreateNetworkStateIdle); setError(ErrorHardwareUnavailable); return; } - if (m_permitJoining != false) { - m_permitJoining = false; - emit permitJoiningChanged(m_permitJoining); - } + setPermitJoiningEnabled(false); + m_initializing = true; // Note: wait for the controller available signal and start the initialization there - - m_initializing = true; } void ZigbeeNetworkDeconz::stopNetwork() diff --git a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.h b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.h index bbdd5a2..47a41f5 100644 --- a/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.h +++ b/libnymea-zigbee/backends/deconz/zigbeenetworkdeconz.h @@ -57,7 +57,7 @@ public: // Sending an APSDE-DATA.request, will be finished on APSDE-DATA.confirm ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override; - ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe); + void setPermitJoining(quint8 duration, quint16 address = Zigbee::BroadcastAddressAllRouters) override; private: ZigbeeBridgeControllerDeconz *m_controller = nullptr; @@ -66,13 +66,13 @@ private: bool m_createNewNetwork = false; bool m_initializing = false; - QTimer *m_permitJoinRefreshTimer = nullptr; - QHash m_pendingReplies; QTimer *m_pollNetworkStateTimer = nullptr; void setCreateNetworkState(CreateNetworkState state); + ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe); + // ZDO void handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication); @@ -80,13 +80,11 @@ private: void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication); protected: - void setPermitJoiningInternal(bool permitJoining) override; void startNetworkInternally(); private slots: void onControllerAvailableChanged(bool available); void onPollNetworkStateTimeout(); - void onPermitJoinRefreshTimout(); void onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm); void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication); diff --git a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp index 47bafa4..ad17e04 100644 --- a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp +++ b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.cpp @@ -55,13 +55,6 @@ ZigbeeNetworkNxp::ZigbeeNetworkNxp(const QUuid &networkUuid, QObject *parent) : setState(StateUpdating); } }); - - m_permitJoinRefreshTimer = new QTimer(this); - m_permitJoinRefreshTimer->setInterval(250 * 1000); - m_permitJoinRefreshTimer->setSingleShot(false); - connect(m_permitJoinRefreshTimer, &QTimer::timeout, this, [this](){ - setPermitJoiningInternal(true); - }); } ZigbeeBridgeController *ZigbeeNetworkNxp::bridgeController() const @@ -118,7 +111,79 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re return reply; } -ZigbeeNetworkReply *ZigbeeNetworkNxp::setPermitJoin(quint16 shortAddress, quint8 duration) +void ZigbeeNetworkNxp::setPermitJoining(quint8 duration, quint16 address) +{ + if (duration > 0) { + qCDebug(dcZigbeeNetwork()) << "Set permit join for" << duration << "s on" << ZigbeeUtils::convertUint16ToHexString(address); + } else { + qCDebug(dcZigbeeNetwork()) << "Disable permit join on"<< ZigbeeUtils::convertUint16ToHexString(address); + } + + // Note: will be reseted if permit join will not work + setPermitJoiningEnabled(duration > 0); + setPermitJoiningDuration(duration); + setPermitJoiningRemaining(duration); + + if (address == 0x0000) { + // Only the coordinator is allowed to join the network + qCDebug(dcZigbeeNetwork()) << "Set permit join in the coordinator node only to" << duration << "[s]"; + ZigbeeInterfaceNxpReply *reply = m_controller->requestSetPermitJoinCoordinator(duration); + connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [this, reply, duration](){ + qCDebug(dcZigbeeNetwork()) << "Set permit join in the coordinator finished" << reply->status(); + if (reply->status() != Nxp::StatusSuccess) { + qCWarning(dcZigbeeNetwork()) << "Failed to set permit join status in coordinator"; + setPermitJoiningEnabled(false); + setPermitJoiningDuration(duration); + } else { + setPermitJoiningEnabled(duration > 0); + setPermitJoiningDuration(duration); + setPermitJoiningRemaining(duration); + if (duration > 0) { + m_permitJoinTimer->start(); + } + } + }); + + return; + } + + // Note: since compliance version >= 21 the value 255 is not any more endless. + // We need to refresh the command on timeout if the duration is longer + + ZigbeeNetworkReply *reply = requestSetPermitJoin(address, duration); + connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply, duration, address](){ + if (reply->zigbeeApsStatus() != Zigbee::ZigbeeApsStatusSuccess) { + qCWarning(dcZigbeeNetwork()) << "Could not set permit join to" << duration << ZigbeeUtils::convertUint16ToHexString(address) << reply->zigbeeApsStatus(); + setPermitJoiningEnabled(false); + setPermitJoiningDuration(duration); + m_permitJoinTimer->stop(); + return; + } + + qCDebug(dcZigbeeNetwork()) << "Permit join request finished successfully"; + setPermitJoiningEnabled(duration > 0); + setPermitJoiningDuration(duration); + setPermitJoiningRemaining(duration); + if (duration > 0) { + m_permitJoinTimer->start(); + } else { + m_permitJoinTimer->stop(); + } + + if (address == Zigbee::BroadcastAddressAllRouters || address == 0x0000) { + qCDebug(dcZigbeeNetwork()) << "Set permit join in the coordinator node to" << duration << "[s]"; + ZigbeeInterfaceNxpReply *reply = m_controller->requestSetPermitJoinCoordinator(duration); + connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [reply](){ + qCDebug(dcZigbeeNetwork()) << "Set permit join in the coordinator finished" << reply->status(); + if (reply->status() != Nxp::StatusSuccess) { + qCWarning(dcZigbeeNetwork()) << "Failed to set permit join status in coordinator"; + } + }); + } + }); +} + +ZigbeeNetworkReply *ZigbeeNetworkNxp::requestSetPermitJoin(quint16 shortAddress, quint8 duration) { // Get the power descriptor ZigbeeNetworkRequest request; @@ -325,7 +390,7 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr qCDebug(dcZigbeeNetwork()) << "We already have the coordinator node. Network starting done."; m_database->saveNode(m_coordinatorNode); - setPermitJoiningInternal(false); + setPermitJoining(0); setState(StateRunning); return; } @@ -338,7 +403,7 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr if (state == ZigbeeNode::StateInitialized) { qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode; setState(StateRunning); - setPermitJoiningInternal(false); + setPermitJoining(0); return; } }); @@ -500,62 +565,11 @@ void ZigbeeNetworkNxp::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress iee node->startInitialization(); } -void ZigbeeNetworkNxp::setPermitJoiningInternal(bool permitJoining) -{ - qCDebug(dcZigbeeNetwork()) << "Set permit join internal" << permitJoining; - - quint8 duration = 0; - if (permitJoining) { - duration = 255; - } - - // Note: since compliance version >= 21 the value 255 is not any more Qt::endless. - // we need to refresh the command on timeout - - - ZigbeeNetworkReply *reply = setPermitJoin(Zigbee::BroadcastAddressAllRouters, duration); - connect(reply, &ZigbeeNetworkReply::finished, this, [this, reply, permitJoining, duration](){ - if (reply->zigbeeApsStatus() != Zigbee::ZigbeeApsStatusSuccess) { - qCDebug(dcZigbeeNetwork()) << "Could not set permit join to" << duration; - if (m_permitJoining != false) { - m_permitJoining = false; - emit permitJoiningChanged(m_permitJoining); - } - return; - } - - qCDebug(dcZigbeeNetwork()) << "Permit join request finished successfully"; - if (permitJoining) { - m_permitJoinRefreshTimer->start(); - } else { - m_permitJoinRefreshTimer->stop(); - } - - if (m_permitJoining != permitJoining) { - m_permitJoining = permitJoining; - emit permitJoiningChanged(m_permitJoining); - } - - qCDebug(dcZigbeeNetwork()) << "Set permit join in the coordinator node to" << duration << "[s]"; - ZigbeeInterfaceNxpReply *reply = m_controller->requestSetPermitJoinCoordinator(duration); - connect(reply, &ZigbeeInterfaceNxpReply::finished, this, [reply](){ - qCDebug(dcZigbeeNetwork()) << "Set permit join in the coordinator finished" << reply->status(); - if (reply->status() != Nxp::StatusSuccess) { - qCWarning(dcZigbeeNetwork()) << "Failed to set permit join status in coordinator"; - } - - }); - }); -} - void ZigbeeNetworkNxp::startNetwork() { loadNetwork(); - if (m_permitJoining != false) { - m_permitJoining = false; - emit permitJoiningChanged(m_permitJoining); - } + setPermitJoiningEnabled(false); if (!m_controller->enable(serialPortName(), serialBaudrate())) { setState(StateOffline); diff --git a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.h b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.h index bac935e..1c28582 100644 --- a/libnymea-zigbee/backends/nxp/zigbeenetworknxp.h +++ b/libnymea-zigbee/backends/nxp/zigbeenetworknxp.h @@ -45,7 +45,8 @@ public: ZigbeeBridgeController *bridgeController() const override; Zigbee::ZigbeeBackendType backendType() const override; ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) override; - ZigbeeNetworkReply *setPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe); + + void setPermitJoining(quint8 duration, quint16 address = Zigbee::BroadcastAddressAllRouters) override; private: ZigbeeBridgeControllerNxp *m_controller = nullptr; @@ -53,8 +54,6 @@ private: QHash m_pendingReplies; int m_reconnectCounter = 0; - QTimer *m_permitJoinRefreshTimer = nullptr; - bool processVersionReply(ZigbeeInterfaceNxpReply *reply); // ZDO @@ -63,6 +62,8 @@ private: // ZCL void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication); + ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe); + private slots: void onControllerAvailableChanged(bool available); void onControllerStateChanged(ZigbeeBridgeControllerNxp::ControllerState controllerState); @@ -73,8 +74,6 @@ private slots: void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities); -protected: - void setPermitJoiningInternal(bool permitJoining) override; signals: diff --git a/libnymea-zigbee/zigbeeaddress.cpp b/libnymea-zigbee/zigbeeaddress.cpp index fa72309..da96a16 100644 --- a/libnymea-zigbee/zigbeeaddress.cpp +++ b/libnymea-zigbee/zigbeeaddress.cpp @@ -111,6 +111,6 @@ bool ZigbeeAddress::operator!=(const ZigbeeAddress &other) const QDebug operator<<(QDebug debug, const ZigbeeAddress &address) { - debug.nospace() << address.toString(); - return debug.space(); + debug << address.toString(); + return debug; } diff --git a/libnymea-zigbee/zigbeenetwork.cpp b/libnymea-zigbee/zigbeenetwork.cpp index f778cf6..94adbd1 100644 --- a/libnymea-zigbee/zigbeenetwork.cpp +++ b/libnymea-zigbee/zigbeenetwork.cpp @@ -38,7 +38,18 @@ ZigbeeNetwork::ZigbeeNetwork(const QUuid &networkUuid, QObject *parent) : QObject(parent), m_networkUuid(networkUuid) { - + m_permitJoinTimer = new QTimer(this); + m_permitJoinTimer->setInterval(1000); + m_permitJoinTimer->setSingleShot(false); + connect(m_permitJoinTimer, &QTimer::timeout, this, [this](){ + m_permitJoiningRemaining--; + if (m_permitJoiningRemaining <= 0) { + m_permitJoinTimer->stop(); + setPermitJoining(0); + } else { + setPermitJoiningRemaining(m_permitJoiningRemaining); + } + }); } QUuid ZigbeeNetwork::networkUuid() const @@ -191,14 +202,51 @@ void ZigbeeNetwork::setSecurityConfiguration(const ZigbeeSecurityConfiguration & emit securityConfigurationChanged(m_securityConfiguration); } -bool ZigbeeNetwork::permitJoining() const +bool ZigbeeNetwork::permitJoiningEnabled() const { - return m_permitJoining; + return m_permitJoiningEnabled; } -void ZigbeeNetwork::setPermitJoining(bool permitJoining) +quint8 ZigbeeNetwork::permitJoiningDuration() const { - setPermitJoiningInternal(permitJoining); + return m_permitJoiningDuration; +} + +quint8 ZigbeeNetwork::permitJoiningRemaining() const +{ + return m_permitJoiningRemaining; +} + +void ZigbeeNetwork::setPermitJoiningEnabled(bool permitJoiningEnabled) +{ + if (m_permitJoiningEnabled == permitJoiningEnabled) + return; + + m_permitJoiningEnabled = permitJoiningEnabled; + emit permitJoiningEnabledChanged(m_permitJoiningEnabled); + + if (!m_permitJoiningEnabled) { + m_permitJoinTimer->stop(); + setPermitJoiningRemaining(0); + } +} + +void ZigbeeNetwork::setPermitJoiningDuration(quint8 duration) +{ + if (m_permitJoiningDuration == duration) + return; + + m_permitJoiningDuration = duration; + emit permitJoinDurationChanged(m_permitJoiningDuration); +} + +void ZigbeeNetwork::setPermitJoiningRemaining(quint8 remaining) +{ + if (m_permitJoiningRemaining == remaining) + return; + + m_permitJoiningRemaining = remaining; + emit permitJoinRemainingChanged(m_permitJoiningRemaining); } quint8 ZigbeeNetwork::generateSequenceNumber() @@ -407,7 +455,7 @@ void ZigbeeNetwork::clearSettings() if (!m_database->wipeDatabase()) { qCWarning(dcZigbeeNetwork()) << "Failed to wipe the network database" << m_database->databaseName(); } - m_database->deleteLater(); + delete m_database; m_database = nullptr; } @@ -417,6 +465,7 @@ void ZigbeeNetwork::clearSettings() setChannel(0); setSecurityConfiguration(ZigbeeSecurityConfiguration()); setState(StateUninitialized); + setPermitJoiningEnabled(false); m_nodeType = ZigbeeDeviceProfile::NodeTypeCoordinator; } @@ -582,11 +631,11 @@ void ZigbeeNetwork::onNodeClusterAttributeChanged(ZigbeeCluster *cluster, const QDebug operator<<(QDebug debug, ZigbeeNetwork *network) { - debug.nospace().noquote() << "ZigbeeNetwork(" << network->macAddress() << ", " + debug.nospace().noquote() << "ZigbeeNetwork(" << network->macAddress().toString() << ", " << network->networkUuid().toString() << ", " << network->backendType() << ", " << "Channel: " << network->channel() << ", " << network->state() - << ")"; - return debug.space(); + << ") "; + return debug; } diff --git a/libnymea-zigbee/zigbeenetwork.h b/libnymea-zigbee/zigbeenetwork.h index e4a7e3c..40862d1 100644 --- a/libnymea-zigbee/zigbeenetwork.h +++ b/libnymea-zigbee/zigbeenetwork.h @@ -107,9 +107,10 @@ public: ZigbeeSecurityConfiguration securityConfiguration() const; void setSecurityConfiguration(const ZigbeeSecurityConfiguration &securityConfiguration); - bool permitJoining() const; - void setPermitJoining(bool permitJoining); - + bool permitJoiningEnabled() const; + quint8 permitJoiningDuration() const; + quint8 permitJoiningRemaining() const; + virtual void setPermitJoining(quint8 duration, quint16 address = Zigbee::BroadcastAddressAllRouters) = 0; quint8 generateSequenceNumber(); @@ -161,13 +162,21 @@ private: protected: Error m_error = ErrorNoError; ZigbeeNode *m_coordinatorNode = nullptr; - bool m_permitJoining = false; ZigbeeSecurityConfiguration m_securityConfiguration; ZigbeeNetworkDatabase *m_database = nullptr; 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; + + // Permit join + QTimer *m_permitJoinTimer = nullptr; + bool m_permitJoiningEnabled = false; + quint8 m_permitJoiningDuration = 120; + quint8 m_permitJoiningRemaining = 0; + + void setPermitJoiningEnabled(bool permitJoiningEnabled); + void setPermitJoiningDuration(quint8 duration); + void setPermitJoiningRemaining(quint8 remaining); void loadNetwork(); void clearSettings(); @@ -208,7 +217,10 @@ signals: void nodeAdded(ZigbeeNode *node); void nodeRemoved(ZigbeeNode *node); - void permitJoiningChanged(bool permitJoining); + void permitJoiningEnabledChanged(bool permitJoiningEnabled); + void permitJoinDurationChanged(quint8 duration); + void permitJoinRemainingChanged(quint8 remaining); + void errorOccured(Error error); void stateChanged(State state);