Improve zigbee api and add serial number

pull/346/head
Simon Stürz 2020-11-05 15:35:45 +01:00
parent 5ed9769427
commit 203badf0c7
9 changed files with 100 additions and 53 deletions

View File

@ -60,9 +60,9 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
zigbeeNetworkDescription.insert("panId", enumValueName(Uint));
zigbeeNetworkDescription.insert("channel", enumValueName(Uint));
zigbeeNetworkDescription.insert("channelMask", enumValueName(Uint));
zigbeeNetworkDescription.insert("permitJoinEnabled", enumValueName(Bool));
zigbeeNetworkDescription.insert("permitJoinDuration", enumValueName(Uint));
zigbeeNetworkDescription.insert("permitJoinRemaining", enumValueName(Uint));
zigbeeNetworkDescription.insert("permitJoiningEnabled", enumValueName(Bool));
zigbeeNetworkDescription.insert("permitJoiningDuration", enumValueName(Uint));
zigbeeNetworkDescription.insert("permitJoiningRemaining", enumValueName(Uint));
zigbeeNetworkDescription.insert("backendType", enumRef<ZigbeeAdapter::ZigbeeBackendType>());
zigbeeNetworkDescription.insert("networkState", enumRef<ZigbeeManager::ZigbeeNetworkState>());
registerObject("ZigbeeNetwork", zigbeeNetworkDescription);
@ -72,9 +72,10 @@ 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 serial port and backend "
description = "Get the list of available Zigbee adapter candidates in order to set up the zigbee network "
"on the desired serial interface. The serialPort property can be used as unique identifier. "
"If an adapter hardware has been recognized as a supported "
"hardware, the \'hardwareRecognized\' property will be true and the baud rate 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>());
@ -82,13 +83,13 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
// AdapterAdded notification
params.clear();
description = "Emitted whenever a new ZigBee adapter candidate has been detected in the system.";
description = "Emitted whenever a new Zigbee adapter candidate has been detected in the system.";
params.insert("adapter", objectRef<ZigbeeAdapter>());
registerNotification("AdapterAdded", description, params);
// AdapterRemoved notification
params.clear();
description = "Emitted whenever a ZigBee adapter has been removed from the system (i.e. unplugged).";
description = "Emitted whenever a Zigbee adapter has been removed from the system (i.e. unplugged).";
params.insert("adapter", objectRef<ZigbeeAdapter>());
registerNotification("AdapterRemoved", description, params);
@ -100,38 +101,42 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
// AddNetwork
params.clear(); returns.clear();
description = "Create a new zigbee network for the given zigbee adapter. "
description = "Create a new Zigbee network for the given serialPort, baud rate and backend type. "
"Get those information from the available Zigbee adapters."
"The channel mask is optional and defaults to all channels [11, 26]. "
"The quietest channel will be picked after a channel scan. "
"The quietest channel from the given channel mask will be picked during network creation. "
"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("serialPort", enumValueName(String));
params.insert("baudRate", enumValueName(Uint));
params.insert("backendType", enumRef<ZigbeeAdapter::ZigbeeBackendType>());
params.insert("o:channelMask", enumValueName(Uint));
returns.insert("zigbeeError", enumRef<ZigbeeManager::ZigbeeError>());
returns.insert("o:networkUuid", enumValueName(Uuid));
registerMethod("AddNetwork", description, params, returns);
// RemoveNetwork
params.clear(); returns.clear();
description = "Remove the zigbee network with the given network uuid";
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.";
description = "Emitted whenever a new Zigbee network has been added.";
params.insert("zigbeeNetwork", objectRef("ZigbeeNetwork"));
registerNotification("NetworkAdded", description, params);
// NetworkRemoved notification
params.clear();
description = "Emitted whenever a new ZigBee network has been removed.";
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.";
description = "Emitted whenever a new Zigbee network has changed.";
params.insert("zigbeeNetwork", objectRef("ZigbeeNetwork"));
registerNotification("NetworkChanged", description, params);
@ -187,7 +192,7 @@ ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) :
connect(m_zigbeeManager, &ZigbeeManager::zigbeeNetworkRemoved, this, [this](const QUuid &networkUuid){
QVariantMap params;
params.insert("networkUuid", networkUuid.toString());
params.insert("networkUuid", networkUuid);
emit NetworkRemoved(params);
});
}
@ -212,10 +217,15 @@ JsonReply *ZigbeeHandler::GetAdapters(const QVariantMap &params)
JsonReply *ZigbeeHandler::AddNetwork(const QVariantMap &params)
{
ZigbeeAdapter adapter = unpack<ZigbeeAdapter>(params.value("adapter"));
ZigbeeManager::ZigbeeError error = m_zigbeeManager->createZigbeeNetwork(adapter);
QString serialPort = params.value("serialPort").toString();
uint baudRate = params.value("baudRate").toUInt();
ZigbeeAdapter::ZigbeeBackendType backendType = enumNameToValue<ZigbeeAdapter::ZigbeeBackendType>(params.value("backendType").toString());
QPair<ZigbeeManager::ZigbeeError, QUuid> result = m_zigbeeManager->createZigbeeNetwork(serialPort, baudRate, backendType);
QVariantMap returnMap;
returnMap.insert("zigbeeError", enumValueName<ZigbeeManager::ZigbeeError>(error));
if (result.first == ZigbeeManager::ZigbeeErrorNoError) {
returnMap.insert("networkUuid", result.second);
}
returnMap.insert("zigbeeError", enumValueName<ZigbeeManager::ZigbeeError>(result.first));
return createReply(returnMap);
}
@ -275,9 +285,9 @@ QVariantMap ZigbeeHandler::packNetwork(ZigbeeNetwork *network)
networkMap.insert("panId", network->panId());
networkMap.insert("channel", network->channel());
networkMap.insert("channelMask", network->channelMask().toUInt32());
networkMap.insert("permitJoinEnabled", network->permitJoiningEnabled());
networkMap.insert("permitJoinDuration", network->permitJoiningDuration());
networkMap.insert("permitJoinRemaining", network->permitJoiningRemaining());
networkMap.insert("permitJoiningEnabled", network->permitJoiningEnabled());
networkMap.insert("permitJoiningDuration", network->permitJoiningDuration());
networkMap.insert("permitJoiningRemaining", network->permitJoiningRemaining());
switch (network->backendType()) {
case Zigbee::ZigbeeBackendTypeDeconz:

View File

@ -57,14 +57,24 @@ void ZigbeeAdapter::setDescription(const QString &description)
m_description = description;
}
QString ZigbeeAdapter::systemLocation() const
QString ZigbeeAdapter::serialPort() const
{
return m_systemLocation;
return m_serialPort;
}
void ZigbeeAdapter::setSystemLocation(const QString &systemLocation)
void ZigbeeAdapter::setSerialPort(const QString &serialPort)
{
m_systemLocation = systemLocation;
m_serialPort = serialPort;
}
QString ZigbeeAdapter::serialNumber() const
{
return m_serialNumber;
}
void ZigbeeAdapter::setSerialNumber(const QString &serialNumber)
{
m_serialNumber = serialNumber;
}
bool ZigbeeAdapter::hardwareRecognized() const
@ -99,7 +109,7 @@ void ZigbeeAdapter::setBaudRate(qint32 baudRate)
bool ZigbeeAdapter::operator==(const ZigbeeAdapter &other) const
{
return m_systemLocation == other.systemLocation()
return m_serialPort == other.serialPort()
&& m_name == other.name()
&& m_description == other.description()
&& m_hardwareRecognized == other.hardwareRecognized()
@ -111,7 +121,7 @@ bool ZigbeeAdapter::operator==(const ZigbeeAdapter &other) const
QDebug operator<<(QDebug debug, const ZigbeeAdapter &adapter)
{
debug.nospace() << "ZigbeeAdapter(" << adapter.name() << " - " << adapter.description();
debug.nospace() << ", " << adapter.systemLocation();
debug.nospace() << ", " << adapter.serialPort();
if (adapter.hardwareRecognized()) {
debug.nospace() << " Hardware recognized: " << adapter.backendType();
debug.nospace() << ", " << adapter.baudRate();

View File

@ -43,7 +43,8 @@ class ZigbeeAdapter
Q_GADGET
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(QString serialPort READ serialPort WRITE setSerialPort)
Q_PROPERTY(QString serialNumber READ serialNumber WRITE setSerialNumber)
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)
@ -63,8 +64,11 @@ public:
QString description() const;
void setDescription(const QString &description);
QString systemLocation() const;
void setSystemLocation(const QString &systemLocation);
QString serialPort() const;
void setSerialPort(const QString &serialPort);
QString serialNumber() const;
void setSerialNumber(const QString &serialNumber);
bool hardwareRecognized() const;
void setHardwareRecognized(bool hardwareRecognized);
@ -80,7 +84,8 @@ public:
private:
QString m_name;
QString m_description;
QString m_systemLocation;
QString m_serialPort;
QString m_serialNumber;
bool m_hardwareRecognized = false;
ZigbeeAdapter::ZigbeeBackendType m_backendType = ZigbeeAdapter::ZigbeeBackendTypeDeconz;
qint32 m_baudRate = 38400;

View File

@ -43,6 +43,17 @@ ZigbeeAdapters::ZigbeeAdapters(const QList<ZigbeeAdapter> &other) :
}
bool ZigbeeAdapters::hasSerialPort(const QString &serialPort)
{
for (int i = 0; i < count(); i++) {
if (at(i).serialPort() == serialPort) {
return true;
}
}
return false;
}
QVariant ZigbeeAdapters::get(int index) const
{
return QVariant::fromValue(at(index));

View File

@ -45,6 +45,7 @@ class ZigbeeAdapters : public QList<ZigbeeAdapter>
public:
ZigbeeAdapters();
ZigbeeAdapters(const QList<ZigbeeAdapter> &other);
bool hasSerialPort(const QString &serialPort);
Q_INVOKABLE QVariant get(int index) const;
Q_INVOKABLE void put(const QVariant &variant);
};

View File

@ -45,10 +45,10 @@ ZigbeeManager::ZigbeeManager(QObject *parent) :
QObject(parent)
{
// Adapter monitor
qCDebug(dcZigbee()) << "Initialize the ZigBee manager";
qCDebug(dcZigbee()) << "Initialize the Zigbee manager";
m_adapterMonitor = new ZigbeeUartAdapterMonitor(this);
if (!m_adapterMonitor->isValid()) {
qCWarning(dcZigbee()) << "Could not initialize the ZigBee adapter monitor.";
qCWarning(dcZigbee()) << "Could not initialize the Zigbee adapter monitor.";
// Lets continue anyways, maybe we can set up existing networks right the way.
}
@ -63,12 +63,15 @@ ZigbeeManager::ZigbeeManager(QObject *parent) :
ZigbeeAdapter adapter = convertUartAdapterToAdapter(uartAdapter);
qCDebug(dcZigbee()) << "Adapter added" << adapter;
m_adapters.append(adapter);
// FIXME: check if serial number available and gets used by a network (adjust serial port if changed)
emit availableAdapterAdded(adapter);
});
connect(m_adapterMonitor, &ZigbeeUartAdapterMonitor::adapterRemoved, this, [this](const ZigbeeUartAdapter &uartAdapter){
foreach (const ZigbeeAdapter &adapter, m_adapters) {
if (adapter.systemLocation() == uartAdapter.systemLocation()) {
if (adapter.serialPort() == uartAdapter.serialPort()) {
qCDebug(dcZigbee()) << "Adapter removed" << adapter;
m_adapters.removeAll(adapter);
emit availableAdapterRemoved(adapter);
@ -102,33 +105,33 @@ QHash<QUuid, ZigbeeNetwork *> ZigbeeManager::zigbeeNetworks() const
return m_zigbeeNetworks;
}
ZigbeeManager::ZigbeeError ZigbeeManager::createZigbeeNetwork(const ZigbeeAdapter &adapter, const ZigbeeChannelMask channelMask)
QPair<ZigbeeManager::ZigbeeError, QUuid> ZigbeeManager::createZigbeeNetwork(const QString &serialPort, const uint baudRate, const ZigbeeAdapter::ZigbeeBackendType backendType, const ZigbeeChannelMask channelMask)
{
qCDebug(dcZigbee()) << "Start creating network for" << adapter << channelMask;
qCDebug(dcZigbee()) << "Start creating network for" << serialPort << baudRate << backendType << channelMask;
// 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 << "because this adapter is already in use for network" << existingNetwork;
return ZigbeeManager::ZigbeeErrorAdapterAlreadyInUse;
if (existingNetwork->serialPortName() == serialPort) {
qCWarning(dcZigbee()) << "Failed to create a network for" << serialPort << "because this adapter is already in use for network" << existingNetwork;
return QPair<ZigbeeManager::ZigbeeError, QUuid>(ZigbeeManager::ZigbeeErrorAdapterAlreadyInUse, QUuid());
}
}
if (!m_adapters.contains(adapter)) {
qCWarning(dcZigbee()) << "Failed to create a network for" << adapter << "because the adapter is not available any more";
return ZigbeeManager::ZigbeeErrorAdapterNotAvailable;
if (!m_adapters.hasSerialPort(serialPort)) {
qCWarning(dcZigbee()) << "Failed to create a network for" << serialPort << "because the adapter is not available any more";
return QPair<ZigbeeManager::ZigbeeError, QUuid>(ZigbeeManager::ZigbeeErrorAdapterNotAvailable, QUuid());
}
ZigbeeNetwork *network = buildNetworkObject(QUuid::createUuid(), adapter.backendType());
ZigbeeNetwork *network = buildNetworkObject(QUuid::createUuid(), backendType);
network->setChannelMask(channelMask);
network->setSerialPortName(adapter.systemLocation());
network->setSerialBaudrate(adapter.baudRate());
network->setSerialPortName(serialPort);
network->setSerialBaudrate(baudRate);
addNetwork(network);
qCDebug(dcZigbee()) << "Starting" << network;
network->startNetwork();
return ZigbeeErrorNoError;
return QPair<ZigbeeManager::ZigbeeError, QUuid>(ZigbeeManager::ZigbeeErrorNoError, network->networkUuid());
}
ZigbeeManager::ZigbeeError ZigbeeManager::removeZigbeeNetwork(const QUuid &networkUuid)
@ -138,12 +141,14 @@ ZigbeeManager::ZigbeeError ZigbeeManager::removeZigbeeNetwork(const QUuid &netwo
return ZigbeeManager::ZigbeeErrorNetworkUuidNotFound;
}
ZigbeeNetwork *network = m_zigbeeNetworks.take(networkUuid);
ZigbeeNetwork *network = m_zigbeeNetworks.value(networkUuid);
qCDebug(dcZigbee()) << "Removing" << network;
// 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
m_zigbeeNetworks.remove(networkUuid);
network->deleteLater();
// Delete network settings
@ -223,6 +228,8 @@ void ZigbeeManager::saveNetwork(ZigbeeNetwork *network)
settings.setValue("networkKey", network->securityConfiguration().networkKey().toString());
settings.setValue("trustCenterLinkKey", network->securityConfiguration().globalTrustCenterLinkKey().toString());
// FIXME: save also the serial number of the port if available.
settings.endGroup(); // networkUuid
settings.endGroup(); // ZigbeeNetworks
}
@ -235,6 +242,8 @@ void ZigbeeManager::loadZigbeeNetworks()
foreach (const QString networkUuidGroupString, settings.childGroups()) {
settings.beginGroup(networkUuidGroupString);
// FIXME: load also the serial number of the port if available and search that serial port
QUuid networkUuid = QUuid(networkUuidGroupString);
QString serialPortName = settings.value("serialPort").toString();
qint32 serialBaudRate = settings.value("baudRate").toInt();
@ -373,8 +382,9 @@ ZigbeeAdapter ZigbeeManager::convertUartAdapterToAdapter(const ZigbeeUartAdapter
{
ZigbeeAdapter adapter;
adapter.setName(uartAdapter.name());
adapter.setSystemLocation(uartAdapter.systemLocation());
adapter.setSerialPort(uartAdapter.serialPort());
adapter.setDescription(uartAdapter.description());
adapter.setSerialNumber(uartAdapter.serialNumber());
adapter.setHardwareRecognized(uartAdapter.hardwareRecognized());
adapter.setBaudRate(uartAdapter.baudRate());
switch (uartAdapter.zigbeeBackend()) {

View File

@ -71,7 +71,7 @@ public:
ZigbeeAdapters availableAdapters() const;
QHash<QUuid, ZigbeeNetwork *> zigbeeNetworks() const;
ZigbeeError createZigbeeNetwork(const ZigbeeAdapter &adapter, const ZigbeeChannelMask channelMask = ZigbeeChannelMask(ZigbeeChannelMask::ChannelConfigurationAllChannels));
QPair<ZigbeeError, QUuid> createZigbeeNetwork(const QString &serialPort, const uint baudRate, const ZigbeeAdapter::ZigbeeBackendType backendType, const ZigbeeChannelMask channelMask = ZigbeeChannelMask(ZigbeeChannelMask::ChannelConfigurationAllChannels));
ZigbeeError removeZigbeeNetwork(const QUuid &networkUuid);
ZigbeeError setZigbeeNetworkPermitJoin(const QUuid &networkUuid, quint16 shortAddress = Zigbee::BroadcastAddressAllRouters, uint duration = 120);
ZigbeeError factoryResetNetwork(const QUuid &networkUuid);

View File

@ -1,5 +1,5 @@
{
"description": "Used for things that have some sort of alert. For instance, light bulbs may be able to blink on alert actions, or speaker might be able to play an alert sound. ZigBee devices for example oftion provide alert actions to identify themselves.",
"description": "Used for things that have some sort of alert. For instance, light bulbs may be able to blink on alert actions, or speaker might be able to play an alert sound. Zigbee devices for example oftion provide alert actions to identify themselves.",
"actions": [
{
"name": "alert"

View File

@ -1,4 +1,4 @@
{
"description": "The gateway interface is used for gateway devices like bridges to other networks. For instance Ethernet to ZigBee bridges, Ethernet to RF bridges or similar. Typically such device classes implement the actual functionality in child devices that will auto-appear after successful connection to the gateway/bridge.",
"description": "The gateway interface is used for gateway devices like bridges to other networks. For instance Ethernet to Zigbee bridges, Ethernet to RF bridges or similar. Typically such device classes implement the actual functionality in child devices that will auto-appear after successful connection to the gateway/bridge.",
"extends": "connectable"
}