Rework permit join mechanism and remove infinit joining

This commit is contained in:
Simon Stürz 2020-11-02 15:14:22 +01:00
parent 3d62162f5e
commit e46630f9e2
7 changed files with 223 additions and 176 deletions

View File

@ -46,10 +46,6 @@ ZigbeeNetworkDeconz::ZigbeeNetworkDeconz(const QUuid &networkUuid, QObject *pare
m_pollNetworkStateTimer->setSingleShot(false); m_pollNetworkStateTimer->setSingleShot(false);
connect(m_pollNetworkStateTimer, &QTimer::timeout, this, &ZigbeeNetworkDeconz::onPollNetworkStateTimeout); 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 ZigbeeBridgeController *ZigbeeNetworkDeconz::bridgeController() const
@ -95,7 +91,60 @@ ZigbeeNetworkReply *ZigbeeNetworkDeconz::sendRequest(const ZigbeeNetworkRequest
return reply; 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(&parameterData, 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 // Get the power descriptor
ZigbeeNetworkRequest request; ZigbeeNetworkRequest request;
@ -305,7 +354,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
m_database->saveNode(m_coordinatorNode); m_database->saveNode(m_coordinatorNode);
m_initializing = false; m_initializing = false;
setState(StateRunning); setState(StateRunning);
setPermitJoiningInternal(false); setPermitJoining(0);
return; return;
} }
@ -318,7 +367,7 @@ void ZigbeeNetworkDeconz::setCreateNetworkState(ZigbeeNetworkDeconz::CreateNetwo
qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode; qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode;
m_initializing = false; m_initializing = false;
setState(StateRunning); setState(StateRunning);
setPermitJoiningInternal(false); setPermitJoining(0);
return; return;
} }
}); });
@ -380,67 +429,10 @@ void ZigbeeNetworkDeconz::handleZigbeeClusterLibraryIndication(const Zigbee::Aps
handleNodeIndication(node, indication); 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(&parameterData, 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() void ZigbeeNetworkDeconz::startNetworkInternally()
{ {
qCDebug(dcZigbeeNetwork()) << "Start zigbee network internally"; 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; m_createNewNetwork = false;
// Check if we have to create a pan ID and select the channel // Check if we have to create a pan ID and select the channel
if (panId() == 0 || !m_coordinatorNode) { if (panId() == 0 || !m_coordinatorNode) {
@ -525,7 +517,7 @@ void ZigbeeNetworkDeconz::startNetworkInternally()
if (m_controller->networkState() == Deconz::NetworkStateConnected) { if (m_controller->networkState() == Deconz::NetworkStateConnected) {
qCDebug(dcZigbeeNetwork()) << "The network is already running."; qCDebug(dcZigbeeNetwork()) << "The network is already running.";
m_initializing = false; m_initializing = false;
setPermitJoining(false); setPermitJoiningEnabled(false);
// Set the permit joining timeout network configuration parameter // Set the permit joining timeout network configuration parameter
QByteArray parameterData; QByteArray parameterData;
QDataStream stream(&parameterData, QIODevice::WriteOnly); QDataStream stream(&parameterData, QIODevice::WriteOnly);
@ -563,18 +555,11 @@ void ZigbeeNetworkDeconz::onControllerAvailableChanged(bool available)
qCWarning(dcZigbeeNetwork()) << "Hardware controller is not available any more."; qCWarning(dcZigbeeNetwork()) << "Hardware controller is not available any more.";
setError(ErrorHardwareUnavailable); setError(ErrorHardwareUnavailable);
m_initializing = false; m_initializing = false;
if (m_permitJoining != false) { setPermitJoiningEnabled(false);
m_permitJoining = false;
emit permitJoiningChanged(m_permitJoining);
}
setState(StateOffline); setState(StateOffline);
} else { } else {
m_error = ErrorNoError; m_error = ErrorNoError;
if (m_permitJoining != false) { setPermitJoiningEnabled(false);
m_permitJoining = false;
emit permitJoiningChanged(m_permitJoining);
}
emit permitJoiningChanged(m_permitJoining);
setState(StateStarting); setState(StateStarting);
qCDebug(dcZigbeeNetwork()) << "Hardware controller is now available."; qCDebug(dcZigbeeNetwork()) << "Hardware controller is now available.";
startNetworkInternally(); startNetworkInternally();
@ -651,11 +636,6 @@ void ZigbeeNetworkDeconz::onPollNetworkStateTimeout()
} }
} }
void ZigbeeNetworkDeconz::onPermitJoinRefreshTimout()
{
setPermitJoiningInternal(true);
}
void ZigbeeNetworkDeconz::onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm) void ZigbeeNetworkDeconz::onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm)
{ {
ZigbeeNetworkReply *reply = m_pendingReplies.value(confirm.requestId); ZigbeeNetworkReply *reply = m_pendingReplies.value(confirm.requestId);
@ -705,22 +685,17 @@ void ZigbeeNetworkDeconz::startNetwork()
loadNetwork(); loadNetwork();
if (!m_controller->enable(serialPortName(), serialBaudrate())) { if (!m_controller->enable(serialPortName(), serialBaudrate())) {
m_permitJoining = false; setPermitJoiningEnabled(false);
emit permitJoiningChanged(m_permitJoining);
setState(StateOffline); setState(StateOffline);
setCreateNetworkState(CreateNetworkStateIdle); setCreateNetworkState(CreateNetworkStateIdle);
setError(ErrorHardwareUnavailable); setError(ErrorHardwareUnavailable);
return; return;
} }
if (m_permitJoining != false) { setPermitJoiningEnabled(false);
m_permitJoining = false; m_initializing = true;
emit permitJoiningChanged(m_permitJoining);
}
// Note: wait for the controller available signal and start the initialization there // Note: wait for the controller available signal and start the initialization there
m_initializing = true;
} }
void ZigbeeNetworkDeconz::stopNetwork() void ZigbeeNetworkDeconz::stopNetwork()

View File

@ -57,7 +57,7 @@ public:
// Sending an APSDE-DATA.request, will be finished on APSDE-DATA.confirm // 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 = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe); void setPermitJoining(quint8 duration, quint16 address = Zigbee::BroadcastAddressAllRouters) override;
private: private:
ZigbeeBridgeControllerDeconz *m_controller = nullptr; ZigbeeBridgeControllerDeconz *m_controller = nullptr;
@ -66,13 +66,13 @@ private:
bool m_createNewNetwork = false; bool m_createNewNetwork = false;
bool m_initializing = false; bool m_initializing = false;
QTimer *m_permitJoinRefreshTimer = nullptr;
QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies; QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies;
QTimer *m_pollNetworkStateTimer = nullptr; QTimer *m_pollNetworkStateTimer = nullptr;
void setCreateNetworkState(CreateNetworkState state); void setCreateNetworkState(CreateNetworkState state);
ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
// ZDO // ZDO
void handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication); void handleZigbeeDeviceProfileIndication(const Zigbee::ApsdeDataIndication &indication);
@ -80,13 +80,11 @@ private:
void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication); void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication);
protected: protected:
void setPermitJoiningInternal(bool permitJoining) override;
void startNetworkInternally(); void startNetworkInternally();
private slots: private slots:
void onControllerAvailableChanged(bool available); void onControllerAvailableChanged(bool available);
void onPollNetworkStateTimeout(); void onPollNetworkStateTimeout();
void onPermitJoinRefreshTimout();
void onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm); void onApsDataConfirmReceived(const Zigbee::ApsdeDataConfirm &confirm);
void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication); void onApsDataIndicationReceived(const Zigbee::ApsdeDataIndication &indication);

View File

@ -55,13 +55,6 @@ ZigbeeNetworkNxp::ZigbeeNetworkNxp(const QUuid &networkUuid, QObject *parent) :
setState(StateUpdating); 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 ZigbeeBridgeController *ZigbeeNetworkNxp::bridgeController() const
@ -118,7 +111,79 @@ ZigbeeNetworkReply *ZigbeeNetworkNxp::sendRequest(const ZigbeeNetworkRequest &re
return reply; 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 // Get the power descriptor
ZigbeeNetworkRequest request; ZigbeeNetworkRequest request;
@ -325,7 +390,7 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr
qCDebug(dcZigbeeNetwork()) << "We already have the coordinator node. Network starting done."; qCDebug(dcZigbeeNetwork()) << "We already have the coordinator node. Network starting done.";
m_database->saveNode(m_coordinatorNode); m_database->saveNode(m_coordinatorNode);
setPermitJoiningInternal(false); setPermitJoining(0);
setState(StateRunning); setState(StateRunning);
return; return;
} }
@ -338,7 +403,7 @@ void ZigbeeNetworkNxp::onControllerStateChanged(ZigbeeBridgeControllerNxp::Contr
if (state == ZigbeeNode::StateInitialized) { if (state == ZigbeeNode::StateInitialized) {
qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode; qCDebug(dcZigbeeNetwork()) << "Coordinator initialized successfully." << coordinatorNode;
setState(StateRunning); setState(StateRunning);
setPermitJoiningInternal(false); setPermitJoining(0);
return; return;
} }
}); });
@ -500,62 +565,11 @@ void ZigbeeNetworkNxp::onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress iee
node->startInitialization(); 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() void ZigbeeNetworkNxp::startNetwork()
{ {
loadNetwork(); loadNetwork();
if (m_permitJoining != false) { setPermitJoiningEnabled(false);
m_permitJoining = false;
emit permitJoiningChanged(m_permitJoining);
}
if (!m_controller->enable(serialPortName(), serialBaudrate())) { if (!m_controller->enable(serialPortName(), serialBaudrate())) {
setState(StateOffline); setState(StateOffline);

View File

@ -45,7 +45,8 @@ public:
ZigbeeBridgeController *bridgeController() const override; ZigbeeBridgeController *bridgeController() const override;
Zigbee::ZigbeeBackendType backendType() const override; Zigbee::ZigbeeBackendType backendType() const override;
ZigbeeNetworkReply *sendRequest(const ZigbeeNetworkRequest &request) 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: private:
ZigbeeBridgeControllerNxp *m_controller = nullptr; ZigbeeBridgeControllerNxp *m_controller = nullptr;
@ -53,8 +54,6 @@ private:
QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies; QHash<quint8, ZigbeeNetworkReply *> m_pendingReplies;
int m_reconnectCounter = 0; int m_reconnectCounter = 0;
QTimer *m_permitJoinRefreshTimer = nullptr;
bool processVersionReply(ZigbeeInterfaceNxpReply *reply); bool processVersionReply(ZigbeeInterfaceNxpReply *reply);
// ZDO // ZDO
@ -63,6 +62,8 @@ private:
// ZCL // ZCL
void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication); void handleZigbeeClusterLibraryIndication(const Zigbee::ApsdeDataIndication &indication);
ZigbeeNetworkReply *requestSetPermitJoin(quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, quint8 duration = 0xfe);
private slots: private slots:
void onControllerAvailableChanged(bool available); void onControllerAvailableChanged(bool available);
void onControllerStateChanged(ZigbeeBridgeControllerNxp::ControllerState controllerState); void onControllerStateChanged(ZigbeeBridgeControllerNxp::ControllerState controllerState);
@ -73,8 +74,6 @@ private slots:
void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities); void onDeviceAnnounced(quint16 shortAddress, ZigbeeAddress ieeeAddress, quint8 macCapabilities);
protected:
void setPermitJoiningInternal(bool permitJoining) override;
signals: signals:

View File

@ -111,6 +111,6 @@ bool ZigbeeAddress::operator!=(const ZigbeeAddress &other) const
QDebug operator<<(QDebug debug, const ZigbeeAddress &address) QDebug operator<<(QDebug debug, const ZigbeeAddress &address)
{ {
debug.nospace() << address.toString(); debug << address.toString();
return debug.space(); return debug;
} }

View File

@ -38,7 +38,18 @@ ZigbeeNetwork::ZigbeeNetwork(const QUuid &networkUuid, QObject *parent) :
QObject(parent), QObject(parent),
m_networkUuid(networkUuid) 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 QUuid ZigbeeNetwork::networkUuid() const
@ -191,14 +202,51 @@ void ZigbeeNetwork::setSecurityConfiguration(const ZigbeeSecurityConfiguration &
emit securityConfigurationChanged(m_securityConfiguration); 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() quint8 ZigbeeNetwork::generateSequenceNumber()
@ -407,7 +455,7 @@ void ZigbeeNetwork::clearSettings()
if (!m_database->wipeDatabase()) { if (!m_database->wipeDatabase()) {
qCWarning(dcZigbeeNetwork()) << "Failed to wipe the network database" << m_database->databaseName(); qCWarning(dcZigbeeNetwork()) << "Failed to wipe the network database" << m_database->databaseName();
} }
m_database->deleteLater(); delete m_database;
m_database = nullptr; m_database = nullptr;
} }
@ -417,6 +465,7 @@ void ZigbeeNetwork::clearSettings()
setChannel(0); setChannel(0);
setSecurityConfiguration(ZigbeeSecurityConfiguration()); setSecurityConfiguration(ZigbeeSecurityConfiguration());
setState(StateUninitialized); setState(StateUninitialized);
setPermitJoiningEnabled(false);
m_nodeType = ZigbeeDeviceProfile::NodeTypeCoordinator; m_nodeType = ZigbeeDeviceProfile::NodeTypeCoordinator;
} }
@ -582,11 +631,11 @@ void ZigbeeNetwork::onNodeClusterAttributeChanged(ZigbeeCluster *cluster, const
QDebug operator<<(QDebug debug, ZigbeeNetwork *network) QDebug operator<<(QDebug debug, ZigbeeNetwork *network)
{ {
debug.nospace().noquote() << "ZigbeeNetwork(" << network->macAddress() << ", " debug.nospace().noquote() << "ZigbeeNetwork(" << network->macAddress().toString() << ", "
<< network->networkUuid().toString() << ", " << network->networkUuid().toString() << ", "
<< network->backendType() << ", " << network->backendType() << ", "
<< "Channel: " << network->channel() << ", " << "Channel: " << network->channel() << ", "
<< network->state() << network->state()
<< ")"; << ") ";
return debug.space(); return debug;
} }

View File

@ -107,9 +107,10 @@ public:
ZigbeeSecurityConfiguration securityConfiguration() const; ZigbeeSecurityConfiguration securityConfiguration() const;
void setSecurityConfiguration(const ZigbeeSecurityConfiguration &securityConfiguration); void setSecurityConfiguration(const ZigbeeSecurityConfiguration &securityConfiguration);
bool permitJoining() const; bool permitJoiningEnabled() const;
void setPermitJoining(bool permitJoining); quint8 permitJoiningDuration() const;
quint8 permitJoiningRemaining() const;
virtual void setPermitJoining(quint8 duration, quint16 address = Zigbee::BroadcastAddressAllRouters) = 0;
quint8 generateSequenceNumber(); quint8 generateSequenceNumber();
@ -161,13 +162,21 @@ private:
protected: protected:
Error m_error = ErrorNoError; Error m_error = ErrorNoError;
ZigbeeNode *m_coordinatorNode = nullptr; ZigbeeNode *m_coordinatorNode = nullptr;
bool m_permitJoining = false;
ZigbeeSecurityConfiguration m_securityConfiguration; ZigbeeSecurityConfiguration m_securityConfiguration;
ZigbeeNetworkDatabase *m_database = nullptr; ZigbeeNetworkDatabase *m_database = nullptr;
ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent); ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, QObject *parent);
ZigbeeNode *createNode(quint16 shortAddress, const ZigbeeAddress &extendedAddress, quint8 macCapabilities, 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 loadNetwork();
void clearSettings(); void clearSettings();
@ -208,7 +217,10 @@ signals:
void nodeAdded(ZigbeeNode *node); void nodeAdded(ZigbeeNode *node);
void nodeRemoved(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 errorOccured(Error error);
void stateChanged(State state); void stateChanged(State state);