Add factory reset network and start implementing permit join mechanism

This commit is contained in:
Simon Stürz 2020-11-01 22:16:57 +01:00
parent 7585f30639
commit 6edf6977a4
4 changed files with 115 additions and 19 deletions

View File

@ -56,6 +56,7 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
zigbeeNetworkDescription.insert("serialPort", enumValueName(String));
zigbeeNetworkDescription.insert("baudRate", enumValueName(Uint));
zigbeeNetworkDescription.insert("macAddress", enumValueName(String));
zigbeeNetworkDescription.insert("firmwareVersion", enumValueName(String));
zigbeeNetworkDescription.insert("panId", enumValueName(Uint));
zigbeeNetworkDescription.insert("channel", enumValueName(Uint));
zigbeeNetworkDescription.insert("channelMask", enumValueName(Uint));
@ -69,9 +70,11 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
// GetAdapters
params.clear(); returns.clear();
description = "Get the list of available ZigBee adapter candidates in order to set up the zigbee network on the desired serial interface."
"If an adapter hardware has been recognized as a supported hardware, the \'hardwareRecognized\' property will be true and "
"the configurations can be used as they where given, otherwise the user might set the backend type and baud rate manually.";
description = "Get the list of available ZigBee adapter candidates in order to set up the zigbee network "
"on the desired serial interface. If an adapter hardware has been recognized as a supported "
"hardware, the \'hardwareRecognized\' property will be true and the serial port and backend "
"configurations can be used as they where given, otherwise the user might set the backend "
"type and baud rate manually.";
returns.insert("adapters", objectRef<ZigbeeAdapters>());
registerMethod("GetAdapters", description, params, returns);
@ -84,19 +87,22 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
// AdapterRemoved notification
params.clear();
description = "Emitted whenever a ZigBee adapter has been removed from the system (i.e. unplugged).";
params.insert("adapters", objectRef<ZigbeeAdapter>());
params.insert("adapter", objectRef<ZigbeeAdapter>());
registerNotification("AdapterRemoved", description, params);
// GetNetworks
params.clear(); returns.clear();
description = "Returns the list of current configured zigbee networks.";
description = "Returns the list of zigbee networks configured in the system.";
returns.insert("zigbeeNetworks", QVariantList() << objectRef("ZigbeeNetwork"));
registerMethod("GetNetworks", description, params, returns);
// AddNetwork
params.clear(); returns.clear();
description = "Create a new zigbee network for the given zigbee adapter. The channel mask is optional and defaults to all channels. "
"The quietest channel will be picked. The channel mask type is a TODO and will probably be a flag.";
description = "Create a new zigbee network for the given zigbee adapter. "
"The channel mask is optional and defaults to all channels [11, 26]. "
"The quietest channel will be picked after a channel scan. "
"The channel mask is a uint32 flag and the the bit number represents the channel which should "
"enabled for scanning. All channels would be the value 0x07fff800.";
params.insert("adapter", objectRef<ZigbeeAdapter>());
params.insert("o:channelMask", enumValueName(Uint));
returns.insert("zigbeeError", enumRef<ZigbeeManager::ZigbeeError>());
@ -127,6 +133,28 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
params.insert("network", objectRef("ZigbeeNetwork"));
registerNotification("NetworkChanged", description, params);
// FactoryResetNetwork
params.clear(); returns.clear();
description = "Factory reset the network with the given networkUuid. The network does not have "
"to be Online for this procedure, and all associated nodes and things will be removed permanently. "
"Make sure the user realy wants to do this because this can not be undone.";
params.insert("networkUuid", enumValueName(Uuid));
returns.insert("zigbeeError", enumRef<ZigbeeManager::ZigbeeError>());
registerMethod("FactoryResetNetwork", description, params, returns);
// SetPermitJoin
params.clear(); returns.clear();
description = "Allow or deny nodes to join the network with the given networkUuid for a specific duration in seconds. "
"If the duration is set to 0 seconds, joining will be disabled immediatly for the entire network. "
"The shortAddress is optional and defaults to the broadcast address (0xfffc) for all routers in the network. "
"If the short address matches the address of a router node in the network, only that router will "
"be able to allow new nodes to join the network. A new node will join to the router with the best LQI.";
params.insert("networkUuid", enumValueName(Uuid));
params.insert("timeout", enumValueName(Uint));
params.insert("o:shortAddress", enumValueName(Uint));
returns.insert("zigbeeError", enumRef<ZigbeeManager::ZigbeeError>());
registerMethod("SetPermitJoin", description, params, returns);
connect(m_zigbeeManager, &ZigbeeManager::availableAdapterAdded, this, [this](const ZigbeeAdapter &adapter){
QVariantMap params;
@ -195,6 +223,29 @@ JsonReply *ZigbeeHandler::RemoveNetwork(const QVariantMap &params)
return createReply(returnMap);
}
JsonReply *ZigbeeHandler::FactoryResetNetwork(const QVariantMap &params)
{
QUuid networkUuid = params.value("networkUuid").toUuid();
ZigbeeManager::ZigbeeError error = m_zigbeeManager->factoryResetNetwork(networkUuid);
QVariantMap returnMap;
returnMap.insert("zigbeeError", enumValueName<ZigbeeManager::ZigbeeError>(error));
return createReply(returnMap);
}
JsonReply *ZigbeeHandler::SetPermitJoin(const QVariantMap &params)
{
QUuid networkUuid = params.value("networkUuid").toUuid();
uint duration = params.value("duration").toUInt();
quint16 shortAddress = static_cast<quint16>(Zigbee::BroadcastAddressAllRouters);
if (params.contains("shortAddress")) {
shortAddress = static_cast<quint16>(params.value("shortAddress").toUInt());
}
ZigbeeManager::ZigbeeError error = m_zigbeeManager->setZigbeeNetworkPermitJoin(networkUuid, shortAddress, duration);
QVariantMap returnMap;
returnMap.insert("zigbeeError", enumValueName<ZigbeeManager::ZigbeeError>(error));
return createReply(returnMap);
}
JsonReply *ZigbeeHandler::GetNetworks(const QVariantMap &params)
{
Q_UNUSED(params)
@ -215,6 +266,7 @@ QVariantMap ZigbeeHandler::packNetwork(ZigbeeNetwork *network)
networkMap.insert("serialPort", network->serialPortName());
networkMap.insert("baudRate", network->serialBaudrate());
networkMap.insert("macAddress", network->macAddress().toString());
networkMap.insert("firmwareVersion", network->firmwareVersion());
networkMap.insert("panId", network->panId());
networkMap.insert("channel", network->channel());
networkMap.insert("channelMask", network->channelMask().toUInt32());

View File

@ -53,6 +53,8 @@ public:
Q_INVOKABLE JsonReply *GetNetworks(const QVariantMap &params);
Q_INVOKABLE JsonReply *AddNetwork(const QVariantMap &params);
Q_INVOKABLE JsonReply *RemoveNetwork(const QVariantMap &params);
Q_INVOKABLE JsonReply *FactoryResetNetwork(const QVariantMap &params);
Q_INVOKABLE JsonReply *SetPermitJoin(const QVariantMap &params);
QVariantMap packNetwork(ZigbeeNetwork *network);

View File

@ -32,6 +32,8 @@
#include "nymeasettings.h"
#include "loggingcategories.h"
#include <zigbeeutils.h>
NYMEA_LOGGING_CATEGORY(dcZigbee, "Zigbee")
// Register debug category from the libnymea-zigbee
@ -52,13 +54,13 @@ ZigbeeManager::ZigbeeManager(QObject *parent) :
qCDebug(dcZigbee()) << "Loading initial adapter list";
foreach(const ZigbeeUartAdapter &uartAdapter, m_adapterMonitor->availableAdapters()) {
ZigbeeAdapter adapter = createAdapterFromUartAdapter(uartAdapter);
ZigbeeAdapter adapter = convertUartAdapterToAdapter(uartAdapter);
qCDebug(dcZigbee()) << "Adapter added" << adapter;
m_adapters.append(adapter);
}
connect(m_adapterMonitor, &ZigbeeUartAdapterMonitor::adapterAdded, this, [this](const ZigbeeUartAdapter &uartAdapter){
ZigbeeAdapter adapter = createAdapterFromUartAdapter(uartAdapter);
ZigbeeAdapter adapter = convertUartAdapterToAdapter(uartAdapter);
qCDebug(dcZigbee()) << "Adapter added" << adapter;
m_adapters.append(adapter);
emit availableAdapterAdded(adapter);
@ -107,7 +109,7 @@ ZigbeeManager::ZigbeeError ZigbeeManager::createZigbeeNetwork(const ZigbeeAdapte
// Make sure we don't have aleardy a network for this adapter
foreach (ZigbeeNetwork *existingNetwork, m_zigbeeNetworks.values()) {
if (existingNetwork->serialPortName() == adapter.systemLocation()) {
qCWarning(dcZigbee()) << "Failed to create a network for" << adapter << "which is already in use for network" << existingNetwork->networkUuid().toString();
qCWarning(dcZigbee()) << "Failed to create a network for" << adapter << "because this adapter is already in use for network" << existingNetwork->networkUuid().toString();
return ZigbeeManager::ZigbeeErrorAdapterAlreadyInUse;
}
}
@ -132,7 +134,7 @@ ZigbeeManager::ZigbeeError ZigbeeManager::createZigbeeNetwork(const ZigbeeAdapte
ZigbeeManager::ZigbeeError ZigbeeManager::removeZigbeeNetwork(const QUuid &networkUuid)
{
if (!m_zigbeeNetworks.keys().contains(networkUuid)) {
qCDebug(dcZigbee()) << "Could not remove network with uuid" << networkUuid.toString() << "because there is no network with this uuid.";
qCWarning(dcZigbee()) << "Could not remove network with uuid" << networkUuid.toString() << "because there is no network with this uuid.";
return ZigbeeManager::ZigbeeErrorNetworkUuidNotFound;
}
@ -144,6 +146,7 @@ ZigbeeManager::ZigbeeError ZigbeeManager::removeZigbeeNetwork(const QUuid &netwo
// Make sure to delete later, so all node removed signals can be processed
network->deleteLater();
// Delete network settings
NymeaSettings settings(NymeaSettings::SettingsRoleZigbee);
settings.beginGroup("ZigbeeNetworks");
settings.beginGroup(network->networkUuid().toString());
@ -155,6 +158,37 @@ ZigbeeManager::ZigbeeError ZigbeeManager::removeZigbeeNetwork(const QUuid &netwo
return ZigbeeManager::ZigbeeErrorNoError;
}
ZigbeeManager::ZigbeeError ZigbeeManager::setZigbeeNetworkPermitJoin(const QUuid &networkUuid, quint16 shortAddress, int duration)
{
if (!m_zigbeeNetworks.keys().contains(networkUuid)) {
qCWarning(dcZigbee()) << "Could not set permit join network" << networkUuid.toString() << "because there is no network with this uuid.";
return ZigbeeManager::ZigbeeErrorNetworkUuidNotFound;
}
ZigbeeNetwork *network = m_zigbeeNetworks.value(networkUuid);
if (network->state() != ZigbeeNetwork::StateRunning) {
qCWarning(dcZigbee()) << "Could not set permit join network" << networkUuid.toString() << "because the network is not running.";
return ZigbeeManager::ZigbeeErrorNetworkOffline;
}
// TODO: set permit join
qCDebug(dcZigbee()) << "Set permit join for network" << networkUuid.toString() << ZigbeeUtils::convertUint16ToHexString(shortAddress) << "to" << duration << "[s] successfully.";
return ZigbeeManager::ZigbeeErrorNoError;
}
ZigbeeManager::ZigbeeError ZigbeeManager::factoryResetNetwork(const QUuid &networkUuid)
{
if (!m_zigbeeNetworks.keys().contains(networkUuid)) {
qCWarning(dcZigbee()) << "Could not factory reset network with uuid" << networkUuid.toString() << "because there is no network with this uuid.";
return ZigbeeManager::ZigbeeErrorNetworkUuidNotFound;
}
ZigbeeNetwork *network = m_zigbeeNetworks.value(networkUuid);
network->factoryResetNetwork();
return ZigbeeManager::ZigbeeErrorNoError;
}
void ZigbeeManager::saveNetwork(ZigbeeNetwork *network)
{
NymeaSettings settings(NymeaSettings::SettingsRoleZigbee);
@ -260,7 +294,7 @@ void ZigbeeManager::addNetwork(ZigbeeNetwork *network)
});
connect(network, &ZigbeeNetwork::errorOccured, this, [network](ZigbeeNetwork::Error error){
qCDebug(dcZigbee()) << "Network error occured for network" << network->networkUuid().toString() << error;
qCWarning(dcZigbee()) << "Network error occured for network" << network->networkUuid().toString() << error;
// TODO: handle error
});
@ -307,19 +341,24 @@ void ZigbeeManager::addNetwork(ZigbeeNetwork *network)
qCDebug(dcZigbee()) << "Network node removed from network" << network->networkUuid().toString() << node;
});
connect(network, &ZigbeeNetwork::firmwareVersionChanged, this, [this, network](const QString &firmwareVersion){
qCDebug(dcZigbee()) << "Network adapter firmware version changed" << network->networkUuid().toString() << firmwareVersion;
emit zigbeeNetworkChanged(network);
});
m_zigbeeNetworks.insert(network->networkUuid(), network);
emit zigbeeNetworkAdded(network);
}
ZigbeeAdapter ZigbeeManager::createAdapterFromUartAdapter(const ZigbeeUartAdapter &uartAdapter)
ZigbeeAdapter ZigbeeManager::convertUartAdapterToAdapter(const ZigbeeUartAdapter &uartAdapter)
{
ZigbeeAdapter adapter;
adapter.setName(uartAdapter.name());
adapter.setSystemLocation(uartAdapter.systemLocation());
adapter.setDescription(uartAdapter.description());
adapter.setHardwareRecognized(uartAdapter.backendSuggestionAvailable());
adapter.setBaudRate(uartAdapter.suggestedBaudRate());
switch (uartAdapter.suggestedZigbeeBackendType()) {
adapter.setHardwareRecognized(uartAdapter.hardwareRecognized());
adapter.setBaudRate(uartAdapter.baudRate());
switch (uartAdapter.zigbeeBackend()) {
case Zigbee::ZigbeeBackendTypeDeconz:
adapter.setBackendType(ZigbeeAdapter::ZigbeeBackendTypeDeconz);
break;
@ -327,7 +366,7 @@ ZigbeeAdapter ZigbeeManager::createAdapterFromUartAdapter(const ZigbeeUartAdapte
adapter.setBackendType(ZigbeeAdapter::ZigbeeBackendTypeNxp);
break;
default:
qCWarning(dcZigbee()) << "Unhandled backend type" << uartAdapter.suggestedZigbeeBackendType() << "which is not implemented in nymea yet.";
qCWarning(dcZigbee()) << "Unhandled backend type" << uartAdapter.zigbeeBackend() << "which is not implemented in nymea yet.";
break;
}
return adapter;

View File

@ -57,7 +57,8 @@ public:
ZigbeeErrorNoError,
ZigbeeErrorAdapterNotAvailable,
ZigbeeErrorAdapterAlreadyInUse,
ZigbeeErrorNetworkUuidNotFound
ZigbeeErrorNetworkUuidNotFound,
ZigbeeErrorNetworkOffline
};
Q_ENUM(ZigbeeError)
@ -71,6 +72,8 @@ public:
ZigbeeError createZigbeeNetwork(const ZigbeeAdapter &adapter, const ZigbeeChannelMask channelMask = ZigbeeChannelMask(ZigbeeChannelMask::ChannelConfigurationAllChannels));
ZigbeeError removeZigbeeNetwork(const QUuid &networkUuid);
ZigbeeError setZigbeeNetworkPermitJoin(const QUuid &networkUuid, quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, int duration = 120);
ZigbeeError factoryResetNetwork(const QUuid &networkUuid);
private:
ZigbeeAdapters m_adapters;
@ -83,7 +86,7 @@ private:
ZigbeeNetwork *buildNetworkObject(const QUuid &networkId, ZigbeeAdapter::ZigbeeBackendType backendType);
void addNetwork(ZigbeeNetwork *network);
ZigbeeAdapter createAdapterFromUartAdapter(const ZigbeeUartAdapter &uartAdapter);
ZigbeeAdapter convertUartAdapterToAdapter(const ZigbeeUartAdapter &uartAdapter);
signals:
void availableAdapterAdded(const ZigbeeAdapter &adapter);