Basic network adding and removing working

This commit is contained in:
Simon Stürz 2020-10-29 18:12:28 +01:00
parent a7cb0e4e26
commit 7585f30639
6 changed files with 220 additions and 74 deletions

View File

@ -31,6 +31,7 @@
#include "zigbeehandler.h"
#include "zigbee/zigbeemanager.h"
#include "zigbee/zigbeeadapters.h"
#include "loggingcategories.h"
#include <zigbeeuartadapter.h>
@ -40,6 +41,9 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
JsonHandler(parent),
m_zigbeeManager(zigbeeManager)
{
qRegisterMetaType<nymeaserver::ZigbeeAdapter>();
qRegisterMetaType<nymeaserver::ZigbeeAdapter::ZigbeeBackendType>();
registerEnum<ZigbeeManager::ZigbeeNetworkState>();
registerEnum<ZigbeeAdapter::ZigbeeBackendType>();
registerEnum<ZigbeeManager::ZigbeeError>();
@ -48,7 +52,16 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
// Network object describing a network instance
QVariantMap zigbeeNetworkDescription;
zigbeeNetworkDescription.insert("uuid", enumValueName(Uuid));
zigbeeNetworkDescription.insert("networkUuid", enumValueName(Uuid));
zigbeeNetworkDescription.insert("serialPort", enumValueName(String));
zigbeeNetworkDescription.insert("baudRate", enumValueName(Uint));
zigbeeNetworkDescription.insert("macAddress", enumValueName(String));
zigbeeNetworkDescription.insert("panId", enumValueName(Uint));
zigbeeNetworkDescription.insert("channel", enumValueName(Uint));
zigbeeNetworkDescription.insert("channelMask", enumValueName(Uint));
zigbeeNetworkDescription.insert("permitJoin", enumValueName(Bool));
zigbeeNetworkDescription.insert("backendType", enumRef<ZigbeeAdapter::ZigbeeBackendType>());
zigbeeNetworkDescription.insert("networkState", enumRef<ZigbeeManager::ZigbeeNetworkState>());
registerObject("ZigbeeNetwork", zigbeeNetworkDescription);
QVariantMap params, returns;
@ -56,7 +69,9 @@ 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 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);
@ -72,21 +87,46 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
params.insert("adapters", objectRef<ZigbeeAdapter>());
registerNotification("AdapterRemoved", description, params);
// GetNetworks
params.clear(); returns.clear();
description = "Get the status of the current network.";
returns.insert("available", enumValueName(Bool));
returns.insert("enabled", enumValueName(Bool));
returns.insert("configured", enumValueName(Bool));
returns.insert("serialPort", enumValueName(String));
returns.insert("baudRate", enumValueName(Uint));
returns.insert("backend", enumRef<Zigbee::ZigbeeBackendType>());
returns.insert("firmwareVersion", enumValueName(String));
returns.insert("networkIeeeeAddress", enumValueName(String));
returns.insert("networkPanId", enumValueName(Uint));
returns.insert("channel", enumValueName(Uint));
returns.insert("permitJoin", enumValueName(Bool));
returns.insert("networkState", enumRef<ZigbeeManager::ZigbeeNetworkState>());
registerMethod("GetNetworkStatus", description, params, returns);
description = "Returns the list of current configured zigbee networks.";
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.";
params.insert("adapter", objectRef<ZigbeeAdapter>());
params.insert("o:channelMask", enumValueName(Uint));
returns.insert("zigbeeError", enumRef<ZigbeeManager::ZigbeeError>());
registerMethod("AddNetwork", description, params, returns);
// RemoveNetwork
params.clear(); returns.clear();
description = "Remove the zigbee network with the given network uuid";
params.insert("networkUuid", enumValueName(Uuid));
returns.insert("zigbeeError", enumRef<ZigbeeManager::ZigbeeError>());
registerMethod("RemoveNetwork", description, params, returns);
// NetworkAdded notification
params.clear();
description = "Emitted whenever a new ZigBee network has been added.";
params.insert("network", objectRef("ZigbeeNetwork"));
registerNotification("NetworkAdded", description, params);
// NetworkRemoved notification
params.clear();
description = "Emitted whenever a new ZigBee network has been removed.";
params.insert("networkUuid", enumValueName(Uuid));
registerNotification("NetworkRemoved", description, params);
// NetworkChanged notification
params.clear();
description = "Emitted whenever a new ZigBee network has changed.";
params.insert("network", objectRef("ZigbeeNetwork"));
registerNotification("NetworkChanged", description, params);
connect(m_zigbeeManager, &ZigbeeManager::availableAdapterAdded, this, [this](const ZigbeeAdapter &adapter){
QVariantMap params;
@ -100,32 +140,23 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
emit AdapterRemoved(params);
});
/* 1. GetNetworks
* 2. Setup network if the is no network configured
* - GetAdapters
* - AddNetwork (adapter, channelmask)
* -
*/
connect(m_zigbeeManager, &ZigbeeManager::zigbeeNetworkAdded, this, [this](ZigbeeNetwork *network){
QVariantMap params;
params.insert("zigbeeNetwork", packNetwork(network));
emit NetworkAdded(params);
});
// GetNetworkStatus
// NetworkStatusChanged
// SetupNetwork(network, uart, baudrate, backendtype)
// PermitJoin(time, o:nwk address)
// FactoryResetNetwork
// GetNodes [Node(mac, nwkAddress, name, manufacturer, type, descriptors, associacted device, state, reachable)]
// NodeAdded
// NodeChanged (state, node base information, associated deviceId)
// RemoveNode
// NodeRemoved
// GetGroups
// GroupChanged
// AddGroup
// GroupAdded
// RemoveGroup
// GroupRemoved
connect(m_zigbeeManager, &ZigbeeManager::zigbeeNetworkChanged, this, [this](ZigbeeNetwork *network){
QVariantMap params;
params.insert("zigbeeNetwork", packNetwork(network));
emit NetworkChanged(params);
});
connect(m_zigbeeManager, &ZigbeeManager::zigbeeNetworkRemoved, this, [this](const QUuid &networkUuid){
QVariantMap params;
params.insert("networkUuid", networkUuid.toString());
emit NetworkRemoved(params);
});
}
QString ZigbeeHandler::name() const
@ -133,26 +164,6 @@ QString ZigbeeHandler::name() const
return "Zigbee";
}
JsonReply *ZigbeeHandler::GetNetworkStatus(const QVariantMap &params)
{
Q_UNUSED(params)
QVariantMap ret;
// if (m_zigbeeManager->zigbeeNetwork()) {
// ret.insert("available", m_zigbeeManager->available());
// ret.insert("enabled", m_zigbeeManager->enabled());
// ret.insert("configured", true);
// ret.insert("networkState", m_zigbeeManager->zigbeeNetwork()->state());
// } else {
// ret.insert("available", m_zigbeeManager->available());
// ret.insert("enabled", m_zigbeeManager->enabled());
// ret.insert("configured", false);
// ret.insert("state", ZigbeeNetwork::StateUninitialized);
// }
return createReply(ret);
}
JsonReply *ZigbeeHandler::GetAdapters(const QVariantMap &params)
{
Q_UNUSED(params)
@ -166,4 +177,77 @@ JsonReply *ZigbeeHandler::GetAdapters(const QVariantMap &params)
return createReply(returnMap);
}
JsonReply *ZigbeeHandler::AddNetwork(const QVariantMap &params)
{
ZigbeeAdapter adapter = unpack<ZigbeeAdapter>(params.value("adapter"));
ZigbeeManager::ZigbeeError error = m_zigbeeManager->createZigbeeNetwork(adapter);
QVariantMap returnMap;
returnMap.insert("zigbeeError", enumValueName<ZigbeeManager::ZigbeeError>(error));
return createReply(returnMap);
}
JsonReply *ZigbeeHandler::RemoveNetwork(const QVariantMap &params)
{
QUuid networkUuid = params.value("networkUuid").toUuid();
ZigbeeManager::ZigbeeError error = m_zigbeeManager->removeZigbeeNetwork(networkUuid);
QVariantMap returnMap;
returnMap.insert("zigbeeError", enumValueName<ZigbeeManager::ZigbeeError>(error));
return createReply(returnMap);
}
JsonReply *ZigbeeHandler::GetNetworks(const QVariantMap &params)
{
Q_UNUSED(params)
QVariantMap returnMap;
QVariantList networkList;
foreach (ZigbeeNetwork *network, m_zigbeeManager->zigbeeNetworks().values()) {
networkList.append(packNetwork(network));
}
returnMap.insert("zigbeeNetworks", networkList);
return createReply(returnMap);
}
QVariantMap ZigbeeHandler::packNetwork(ZigbeeNetwork *network)
{
QVariantMap networkMap;
networkMap.insert("networkUuid", network->networkUuid());
networkMap.insert("serialPort", network->serialPortName());
networkMap.insert("baudRate", network->serialBaudrate());
networkMap.insert("macAddress", network->macAddress().toString());
networkMap.insert("panId", network->panId());
networkMap.insert("channel", network->channel());
networkMap.insert("channelMask", network->channelMask().toUInt32());
networkMap.insert("permitJoin", network->permitJoining());
switch (network->backendType()) {
case Zigbee::ZigbeeBackendTypeDeconz:
networkMap.insert("backendType", enumValueName<ZigbeeAdapter::ZigbeeBackendType>(ZigbeeAdapter::ZigbeeBackendTypeDeconz));
break;
case Zigbee::ZigbeeBackendTypeNxp:
networkMap.insert("backendType", enumValueName<ZigbeeAdapter::ZigbeeBackendType>(ZigbeeAdapter::ZigbeeBackendTypeNxp));
break;
}
switch (network->state()) {
case ZigbeeNetwork::StateOffline:
case ZigbeeNetwork::StateStopping:
networkMap.insert("networkState", enumValueName<ZigbeeManager::ZigbeeNetworkState>(ZigbeeManager::ZigbeeNetworkStateOffline));
break;
case ZigbeeNetwork::StateStarting:
networkMap.insert("networkState", enumValueName<ZigbeeManager::ZigbeeNetworkState>(ZigbeeManager::ZigbeeNetworkStateStarting));
break;
case ZigbeeNetwork::StateRunning:
networkMap.insert("networkState", enumValueName<ZigbeeManager::ZigbeeNetworkState>(ZigbeeManager::ZigbeeNetworkStateOnline));
break;
case ZigbeeNetwork::StateUpdating:
networkMap.insert("networkState", enumValueName<ZigbeeManager::ZigbeeNetworkState>(ZigbeeManager::ZigbeeNetworkStateUpdating));
break;
case ZigbeeNetwork::StateUninitialized:
networkMap.insert("networkState", enumValueName<ZigbeeManager::ZigbeeNetworkState>(ZigbeeManager::ZigbeeNetworkStateError));
break;
}
return networkMap;
}
}

View File

@ -49,8 +49,12 @@ public:
QString name() const override;
Q_INVOKABLE JsonReply *GetNetworkStatus(const QVariantMap &params);
Q_INVOKABLE JsonReply *GetAdapters(const QVariantMap &params);
Q_INVOKABLE JsonReply *GetNetworks(const QVariantMap &params);
Q_INVOKABLE JsonReply *AddNetwork(const QVariantMap &params);
Q_INVOKABLE JsonReply *RemoveNetwork(const QVariantMap &params);
QVariantMap packNetwork(ZigbeeNetwork *network);
private:
ZigbeeManager *m_zigbeeManager = nullptr;
@ -58,6 +62,9 @@ private:
signals:
void AdapterAdded(const QVariantMap &params);
void AdapterRemoved(const QVariantMap &params);
void NetworkAdded(const QVariantMap &params);
void NetworkRemoved(const QVariantMap &params);
void NetworkChanged(const QVariantMap &params);
};

View File

@ -113,7 +113,7 @@ QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter)
debug.nospace() << "ZigbeeAdapter(" << adapter.name() << " - " << adapter.description();
debug.nospace() << ", " << adapter.systemLocation();
if (adapter.hardwareRecognized()) {
debug.nospace() << "Hardware recognized: " << adapter.backendType();
debug.nospace() << " Hardware recognized: " << adapter.backendType();
debug.nospace() << ", " << adapter.baudRate();
}

View File

@ -41,12 +41,12 @@ namespace nymeaserver {
class ZigbeeAdapter
{
Q_GADGET
Q_PROPERTY(QString name READ name)
Q_PROPERTY(QString description READ description)
Q_PROPERTY(QString systemLocation READ systemLocation)
Q_PROPERTY(bool hardwareRecognized READ hardwareRecognized)
Q_PROPERTY(ZigbeeAdapter::ZigbeeBackendType backendType READ backendType)
Q_PROPERTY(qint32 baudRate READ baudRate)
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QString description READ description WRITE setDescription)
Q_PROPERTY(QString systemLocation READ systemLocation WRITE setSystemLocation)
Q_PROPERTY(bool hardwareRecognized READ hardwareRecognized WRITE setHardwareRecognized)
Q_PROPERTY(nymeaserver::ZigbeeAdapter::ZigbeeBackendType backendType READ backendType WRITE setBackendType)
Q_PROPERTY(qint32 baudRate READ baudRate WRITE setBaudRate)
public:
enum ZigbeeBackendType {
@ -91,6 +91,7 @@ QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter);
}
Q_DECLARE_METATYPE(nymeaserver::ZigbeeAdapter)
Q_DECLARE_METATYPE(nymeaserver::ZigbeeAdapter::ZigbeeBackendType)
#endif // ZIGBEEADAPTER_H

View File

@ -95,6 +95,11 @@ ZigbeeAdapters ZigbeeManager::availableAdapters() const
return m_adapters;
}
QHash<QUuid, ZigbeeNetwork *> ZigbeeManager::zigbeeNetworks() const
{
return m_zigbeeNetworks;
}
ZigbeeManager::ZigbeeError ZigbeeManager::createZigbeeNetwork(const ZigbeeAdapter &adapter, const ZigbeeChannelMask channelMask)
{
qCDebug(dcZigbee()) << "Start creating network for" << adapter << channelMask;
@ -124,6 +129,32 @@ ZigbeeManager::ZigbeeError ZigbeeManager::createZigbeeNetwork(const ZigbeeAdapte
return ZigbeeErrorNoError;
}
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.";
return ZigbeeManager::ZigbeeErrorNetworkUuidNotFound;
}
qCDebug(dcZigbee()) << "Removing network" << networkUuid.toString();
ZigbeeNetwork *network = m_zigbeeNetworks.take(networkUuid);
// Note: destroy will remove all nodes from the network and wipe/delete the database
network->destroyNetwork();
emit zigbeeNetworkRemoved(network->networkUuid());
// Make sure to delete later, so all node removed signals can be processed
network->deleteLater();
NymeaSettings settings(NymeaSettings::SettingsRoleZigbee);
settings.beginGroup("ZigbeeNetworks");
settings.beginGroup(network->networkUuid().toString());
settings.remove("");
settings.endGroup();
settings.endGroup();
qCDebug(dcZigbee()) << "Network removed successfully" << networkUuid.toString();
return ZigbeeManager::ZigbeeErrorNoError;
}
void ZigbeeManager::saveNetwork(ZigbeeNetwork *network)
{
NymeaSettings settings(NymeaSettings::SettingsRoleZigbee);
@ -144,7 +175,7 @@ void ZigbeeManager::saveNetwork(ZigbeeNetwork *network)
}
settings.setValue("panId", network->panId());
settings.setValue("channel", network->channel());
settings.setValue("macAddress", network->macAddress().toString());
settings.setValue("channelMask", network->channelMask().toUInt32());
settings.setValue("networkKey", network->securityConfiguration().networkKey().toString());
settings.setValue("trustCenterLinkKey", network->securityConfiguration().globalTrustCenterLinkKey().toString());
@ -168,7 +199,7 @@ void ZigbeeManager::loadZigbeeNetworks()
quint16 panId = static_cast<quint16>(settings.value("panId", 0).toUInt());
quint8 channel = settings.value("channel", 0).toUInt();
ZigbeeChannelMask channelMask = ZigbeeChannelMask(static_cast<quint32>(settings.value("channelMask").toUInt()));
ZigbeeAddress macAddress = ZigbeeAddress(settings.value("macAddress").toString());
ZigbeeSecurityConfiguration securityConfiguration;
ZigbeeNetworkKey netKey(settings.value("networkKey", QString()).toString());
if (netKey.isValid()) {
@ -183,6 +214,7 @@ void ZigbeeManager::loadZigbeeNetworks()
ZigbeeNetwork *network = buildNetworkObject(networkUuid, backendType);
network->setSerialPortName(serialPortName);
network->setSerialBaudrate(serialBaudRate);
network->setMacAddress(macAddress);
network->setPanId(panId);
network->setChannel(channel);
network->setChannelMask(channelMask);
@ -245,6 +277,12 @@ void ZigbeeManager::addNetwork(ZigbeeNetwork *network)
emit zigbeeNetworkChanged(network);
});
connect(network, &ZigbeeNetwork::macAddressChanged, this, [this, network](const ZigbeeAddress &macAddress){
qCDebug(dcZigbee()) << "Network MAC address changed" << network->networkUuid().toString() << macAddress.toString();
saveNetwork(network);
emit zigbeeNetworkChanged(network);
});
connect(network, &ZigbeeNetwork::securityConfigurationChanged, this, [this, network](const ZigbeeSecurityConfiguration &securityConfiguration){
qCDebug(dcZigbee()) << "Network security configuration changed" << network->networkUuid().toString() << securityConfiguration.networkKey().toString();
saveNetwork(network);
@ -256,6 +294,19 @@ void ZigbeeManager::addNetwork(ZigbeeNetwork *network)
emit zigbeeNetworkChanged(network);
});
connect(network, &ZigbeeNetwork::permitJoiningChanged, this, [this, network](bool permitJoiningChanged){
qCDebug(dcZigbee()) << "Network permit joining changed" << network->networkUuid().toString() << permitJoiningChanged;
emit zigbeeNetworkChanged(network);
});
connect(network, &ZigbeeNetwork::nodeAdded, this, [network](ZigbeeNode *node){
qCDebug(dcZigbee()) << "Network node added to network" << network->networkUuid().toString() << node;
});
connect(network, &ZigbeeNetwork::nodeRemoved, this, [network](ZigbeeNode *node){
qCDebug(dcZigbee()) << "Network node removed from network" << network->networkUuid().toString() << node;
});
m_zigbeeNetworks.insert(network->networkUuid(), network);
emit zigbeeNetworkAdded(network);
}

View File

@ -46,6 +46,7 @@ class ZigbeeManager : public QObject
public:
enum ZigbeeNetworkState {
ZigbeeNetworkStateOffline,
ZigbeeNetworkStateStarting,
ZigbeeNetworkStateUpdating,
ZigbeeNetworkStateOnline,
ZigbeeNetworkStateError
@ -55,7 +56,8 @@ public:
enum ZigbeeError {
ZigbeeErrorNoError,
ZigbeeErrorAdapterNotAvailable,
ZigbeeErrorAdapterAlreadyInUse
ZigbeeErrorAdapterAlreadyInUse,
ZigbeeErrorNetworkUuidNotFound
};
Q_ENUM(ZigbeeError)
@ -65,13 +67,14 @@ public:
bool enabled() const;
ZigbeeAdapters availableAdapters() const;
QHash<QUuid, ZigbeeNetwork *> zigbeeNetworks() const;
ZigbeeError createZigbeeNetwork(const ZigbeeAdapter &adapter, const ZigbeeChannelMask channelMask = ZigbeeChannelMask());
ZigbeeError createZigbeeNetwork(const ZigbeeAdapter &adapter, const ZigbeeChannelMask channelMask = ZigbeeChannelMask(ZigbeeChannelMask::ChannelConfigurationAllChannels));
ZigbeeError removeZigbeeNetwork(const QUuid &networkUuid);
private:
ZigbeeAdapters m_adapters;
ZigbeeUartAdapterMonitor *m_adapterMonitor = nullptr;
QHash<QUuid, ZigbeeNetwork *> m_zigbeeNetworks;
void saveNetwork(ZigbeeNetwork *network);
@ -87,7 +90,7 @@ signals:
void availableAdapterRemoved(const ZigbeeAdapter &adapter);
void zigbeeNetworkAdded(ZigbeeNetwork *zigbeeNetwork);
void zigbeeNetworkRemoved(ZigbeeNetwork *zigbeeNetwork);
void zigbeeNetworkRemoved(const QUuid networkUuid);
void zigbeeNetworkChanged(ZigbeeNetwork *zigbeeNetwork);
};