/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright 2013 - 2020, nymea GmbH * Contact: contact@nymea.io * * This file is part of nymea. * This project including source code and documentation is protected by * copyright law, and remains the property of nymea GmbH. All rights, including * reproduction, publication, editing and translation, are reserved. The use of * this project is subject to the terms of a license agreement to be concluded * with nymea GmbH in accordance with the terms of use of nymea GmbH, available * under https://nymea.io/license * * GNU General Public License Usage * Alternatively, this project may be redistributed and/or modified under the * terms of the GNU General Public License as published by the Free Software * Foundation, GNU version 3. This project is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with * this project. If not, see . * * For any further details and any questions please contact us under * contact@nymea.io or see our FAQ/Licensing Information on * https://nymea.io/license/faq * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "zigbeemanager.h" #include "nymeasettings.h" #include "loggingcategories.h" #include #include #include NYMEA_LOGGING_CATEGORY(dcZigbee, "Zigbee") // Register debug category from the libnymea-zigbee NYMEA_LOGGING_CATEGORY(dcZigbeeNetworkLibNymeaZigbee, "ZigbeeNetwork") namespace nymeaserver { ZigbeeManager::ZigbeeManager(QObject *parent) : QObject(parent) { // Adapter monitor qCDebug(dcZigbee()) << "Initialize the Zigbee manager"; m_adapterMonitor = new ZigbeeUartAdapterMonitor(this); if (!m_adapterMonitor->isValid()) { qCWarning(dcZigbee()) << "Could not initialize the Zigbee adapter monitor."; // Lets continue anyways, maybe we can set up existing networks right the way. } qCDebug(dcZigbee()) << "Loading initial adapter list"; foreach(const ZigbeeUartAdapter &uartAdapter, m_adapterMonitor->availableAdapters()) { 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 = convertUartAdapterToAdapter(uartAdapter); qCDebug(dcZigbee()) << "Adapter added" << adapter; m_adapters.append(adapter); if (m_autoSetupAdapters) { if (networkExistsForAdapter(uartAdapter)) { qCDebug(dcZigbee()) << "Auto setup enabled. There is already a network configured for" << uartAdapter; } else { qCDebug(dcZigbee()) << "Auto setup enabled. No network for" << uartAdapter << "created yet. Creating network..."; ZigbeeNetwork *network = createPlatformNetwork(uartAdapter.serialPort(), uartAdapter.baudRate(), uartAdapter.zigbeeBackend()); if (!uartAdapter.serialNumber().isEmpty()) network->setSerialNumber(uartAdapter.serialNumber()); addNetwork(network); network->startNetwork(); } } // 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.serialPort() == uartAdapter.serialPort()) { qCDebug(dcZigbee()) << "Adapter removed" << adapter; m_adapters.removeAll(adapter); emit availableAdapterRemoved(adapter); } } }); // Load zigbee networks from settings loadZigbeeNetworks(); // Check if we have a zigbee platform configuration and if we have to create the platform network automatically checkPlatformConfiguration(); // Check if auto setup recognized adapters is enabled if (m_autoSetupAdapters) { qCDebug(dcZigbee()) << "Auto setup enabled. Verify existing networks and adapters..."; foreach(const ZigbeeUartAdapter &uartAdapter, m_adapterMonitor->availableAdapters()) { if (networkExistsForAdapter(uartAdapter)) { qCDebug(dcZigbee()) << "Network for adapter" << uartAdapter << "already created."; } else { qCDebug(dcZigbee()) << "Auto setup enabled and there is no network for" << uartAdapter << "created yet. Creating network..."; ZigbeeNetwork *network = createPlatformNetwork(uartAdapter.serialPort(), uartAdapter.baudRate(), uartAdapter.zigbeeBackend()); if (!uartAdapter.serialNumber().isEmpty()) network->setSerialNumber(uartAdapter.serialNumber()); addNetwork(network); } } } // Start all loaded networks foreach (ZigbeeNetwork *network, m_zigbeeNetworks.values()) { network->startNetwork(); } } bool ZigbeeManager::available() const { return m_available; } bool ZigbeeManager::enabled() const { return true;//m_zigbeeNetwork && m_zigbeeNetwork->state() != ZigbeeNetwork::StateUninitialized; } ZigbeeAdapters ZigbeeManager::availableAdapters() const { return m_adapters; } QHash ZigbeeManager::zigbeeNetworks() const { return m_zigbeeNetworks; } QPair ZigbeeManager::createZigbeeNetwork(const QString &serialPort, uint baudRate, ZigbeeAdapter::ZigbeeBackendType backendType, ZigbeeChannelMask channelMask) { qCDebug(dcZigbee()) << "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() == serialPort) { qCWarning(dcZigbee()) << "Failed to create a network for" << serialPort << "because this adapter is already in use for network" << existingNetwork; return QPair(ZigbeeManager::ZigbeeErrorAdapterAlreadyInUse, QUuid()); } } 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::ZigbeeErrorAdapterNotAvailable, QUuid()); } QString serialNumber; foreach (const ZigbeeAdapter &adapter, m_adapters) { if (adapter.serialPort() == serialPort && !adapter.serialNumber().isEmpty()) { serialNumber = adapter.serialNumber(); } } ZigbeeNetwork *network = buildNetworkObject(QUuid::createUuid(), backendType); network->setChannelMask(channelMask); network->setSerialPortName(serialPort); network->setSerialBaudrate(baudRate); network->setSerialNumber(serialNumber); addNetwork(network); qCDebug(dcZigbee()) << "Starting" << network; network->startNetwork(); return QPair(ZigbeeManager::ZigbeeErrorNoError, network->networkUuid()); } ZigbeeManager::ZigbeeError ZigbeeManager::removeZigbeeNetwork(const QUuid &networkUuid) { if (!m_zigbeeNetworks.keys().contains(networkUuid)) { qCWarning(dcZigbee()) << "Could not remove network with uuid" << networkUuid.toString() << "because there is no network with this uuid."; return ZigbeeManager::ZigbeeErrorNetworkUuidNotFound; } 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 NymeaSettings settings(NymeaSettings::SettingsRoleZigbee); settings.beginGroup("ZigbeeNetworks"); settings.beginGroup(network->networkUuid().toString()); settings.remove(""); settings.endGroup(); // networkUuid settings.endGroup(); // ZigbeeNetworks qCDebug(dcZigbee()) << "Network removed successfully"; return ZigbeeManager::ZigbeeErrorNoError; } ZigbeeManager::ZigbeeError ZigbeeManager::setZigbeeNetworkPermitJoin(const QUuid &networkUuid, quint16 shortAddress, uint 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; } if (duration > 255) { qCWarning(dcZigbee()) << "The given duration for permit join is out of range. Only values between 0 and 255 are allowed."; return ZigbeeManager::ZigbeeErrorDurationOutOfRange; } ZigbeeNetwork *network = m_zigbeeNetworks.value(networkUuid); if (network->state() != ZigbeeNetwork::StateRunning) { qCWarning(dcZigbee()) << "Could not set permit join in" << network << "because the network is not running."; return ZigbeeManager::ZigbeeErrorNetworkOffline; } qCDebug(dcZigbee()) << "Set permit joining in network" << network << "to" << duration << "seconds" << ZigbeeUtils::convertUint16ToHexString(shortAddress); network->setPermitJoining(duration, shortAddress); // Notify all clients about the new configuration emit zigbeeNetworkChanged(network); 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); qCDebug(dcZigbee()) << "Start factory resetting" << network; network->factoryResetNetwork(); return ZigbeeManager::ZigbeeErrorNoError; } void ZigbeeManager::saveNetwork(ZigbeeNetwork *network) { NymeaSettings settings(NymeaSettings::SettingsRoleZigbee); settings.beginGroup("ZigbeeNetworks"); settings.beginGroup(network->networkUuid().toString()); settings.setValue("serialPort", network->serialPortName()); settings.setValue("baudRate", network->serialBaudrate()); switch (network->backendType()) { case Zigbee::ZigbeeBackendTypeDeconz: settings.setValue("backendType", static_cast(ZigbeeAdapter::ZigbeeBackendTypeDeconz)); break; case Zigbee::ZigbeeBackendTypeNxp: settings.setValue("backendType", static_cast(ZigbeeAdapter::ZigbeeBackendTypeNxp)); break; default: qCWarning(dcZigbee()) << "Unhandled backend type" << network->backendType() << "which is not implemented in nymea yet."; break; } 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()); if (!network->serialNumber().isEmpty()) { settings.setValue("serialNumber", network->serialNumber()); } settings.endGroup(); // networkUuid settings.endGroup(); // ZigbeeNetworks } void ZigbeeManager::loadZigbeeNetworks() { NymeaSettings settings(NymeaSettings::SettingsRoleZigbee); qCDebug(dcZigbee()) << "Loading zigbee networks from" << settings.fileName(); settings.beginGroup("ZigbeeNetworks"); 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(); QString serialNumber = settings.value("serialNumber").toString(); qint32 serialBaudRate = settings.value("baudRate").toInt(); ZigbeeAdapter::ZigbeeBackendType backendType = static_cast(settings.value("backendType").toInt()); quint16 panId = static_cast(settings.value("panId", 0).toUInt()); quint8 channel = settings.value("channel", 0).toUInt(); ZigbeeChannelMask channelMask = ZigbeeChannelMask(static_cast(settings.value("channelMask").toUInt())); ZigbeeAddress macAddress = ZigbeeAddress(settings.value("macAddress").toString()); ZigbeeSecurityConfiguration securityConfiguration; ZigbeeNetworkKey netKey(settings.value("networkKey", QString()).toString()); if (netKey.isValid()) { securityConfiguration.setNetworkKey(netKey); } ZigbeeNetworkKey tcKey(settings.value("trustCenterLinkKey", QString("5A6967426565416C6C69616E63653039")).toString()); if (!tcKey.isValid()) { securityConfiguration.setGlobalTrustCenterlinkKey(tcKey); } ZigbeeNetwork *network = buildNetworkObject(networkUuid, backendType); network->setSerialPortName(serialPortName); network->setSerialBaudrate(serialBaudRate); network->setSerialNumber(serialNumber); network->setMacAddress(macAddress); network->setPanId(panId); network->setChannel(channel); network->setChannelMask(channelMask); network->setSecurityConfiguration(securityConfiguration); settings.endGroup(); // networkUuid // Load the nodes before adding the network internally, so the loaded nodes will not generate added signals network->loadNetwork(); // Add the network internally addNetwork(network); } settings.endGroup(); // ZigbeeNetworks if (m_zigbeeNetworks.isEmpty()) { qCDebug(dcZigbee()) << "There are no zigbee networks configured yet."; return; } } void ZigbeeManager::checkPlatformConfiguration() { /* Example platform configurations * * serialPort=/dev/ttymxc2 * baudRate=115200 * backend=nxp * autoSetup=false * * serialPort=/dev/ttyS0 * baudRate=38400 * backend=deconz * autoSetup=false * * autoSetup=true */ QFileInfo platformConfigurationFileInfo(NymeaSettings::settingsPath() + QDir::separator() + "zigbee-platform.conf"); if (platformConfigurationFileInfo.exists()) { qCDebug(dcZigbee()) << "Found zigbee platform configuration" << platformConfigurationFileInfo.absoluteFilePath(); QSettings platformSettings(platformConfigurationFileInfo.absoluteFilePath(), QSettings::IniFormat); QString serialPort = platformSettings.value("serialPort").toString(); qint32 baudRate = platformSettings.value("baudRate").toUInt(); QString backendString = platformSettings.value("backend").toString(); m_autoSetupAdapters = platformSettings.value("autoSetup").toBool(); Zigbee::ZigbeeBackendType backenType = Zigbee::ZigbeeBackendTypeNxp; if (backendString.toLower().contains("deconz")) { backenType = Zigbee::ZigbeeBackendTypeDeconz; } if (serialPort.isEmpty()) { qCWarning(dcZigbee()) << "The serial port is not specified correctly in the platform configuration file" << platformConfigurationFileInfo.absoluteFilePath() << "The platform based network will not be created."; return; } if (!m_adapterMonitor->hasAdapter(serialPort)) { qCWarning(dcZigbee()) << "Could not find platform specific serial port" << serialPort << "on this system. Please check the wiring or the port configuration. The platform based network will not be created."; return; } bool alreadyCreated = false; foreach (ZigbeeNetwork *network, m_zigbeeNetworks.values()) { if (network->serialPortName() == serialPort && network->serialBaudrate() == baudRate && network->backendType() == backenType) { qCDebug(dcZigbee()) << "Network based on platform configuration already created" << network; alreadyCreated = true; break; } } if (!alreadyCreated) { qCDebug(dcZigbee()) << "Network based on platform configuration has not been created yet."; ZigbeeNetwork *network = createPlatformNetwork(serialPort, baudRate, backenType); addNetwork(network); // Note: it will be saved once the network has started successfully } } else { qCDebug(dcZigbee()) << "No platform configuration specified."; } } bool ZigbeeManager::networkExistsForAdapter(const ZigbeeUartAdapter &uartAdapter) { bool networkCreated = false; foreach (ZigbeeNetwork *network, m_zigbeeNetworks) { // Use the serial number if possible as refference if (!uartAdapter.serialNumber().isEmpty()) { if (network->serialNumber() == uartAdapter.serialNumber()) { networkCreated = true; break; } } // Otherwise check the serial port if (network->serialPortName() == uartAdapter.serialPort()) { networkCreated = true; break; } } return networkCreated; } ZigbeeNetwork *ZigbeeManager::createPlatformNetwork(const QString &serialPort, uint baudRate, Zigbee::ZigbeeBackendType backendType, ZigbeeChannelMask channelMask) { qCDebug(dcZigbee()) << "Creating platform network on" << serialPort << baudRate << backendType << channelMask; ZigbeeNetwork *network = ZigbeeNetworkManager::createZigbeeNetwork(QUuid::createUuid(), backendType); network->setSettingsDirectory(QDir(NymeaSettings::settingsPath())); network->setChannelMask(channelMask); network->setSerialPortName(serialPort); network->setSerialBaudrate(baudRate); return network; } ZigbeeNetwork *ZigbeeManager::buildNetworkObject(const QUuid &networkId, ZigbeeAdapter::ZigbeeBackendType backendType) { ZigbeeNetwork *network = nullptr; switch (backendType) { case ZigbeeAdapter::ZigbeeBackendTypeDeconz: network = ZigbeeNetworkManager::createZigbeeNetwork(networkId, Zigbee::ZigbeeBackendTypeDeconz, this); break; case ZigbeeAdapter::ZigbeeBackendTypeNxp: network = ZigbeeNetworkManager::createZigbeeNetwork(networkId, Zigbee::ZigbeeBackendTypeNxp, this); break; } network->setSettingsDirectory(QDir(NymeaSettings::settingsPath())); return network; } void ZigbeeManager::addNetwork(ZigbeeNetwork *network) { connect(network, &ZigbeeNetwork::stateChanged, this, [this, network](ZigbeeNetwork::State state){ Q_UNUSED(state) qCDebug(dcZigbee()) << "Network state changed" << network; evaluateZigbeeAvailable(); emit zigbeeNetworkChanged(network); }); connect(network, &ZigbeeNetwork::errorOccured, this, [this, network](ZigbeeNetwork::Error error){ qCWarning(dcZigbee()) << "Network error occured for" << network << error; evaluateZigbeeAvailable(); // TODO: handle error }); connect(network, &ZigbeeNetwork::panIdChanged, this, [this, network](quint16 panId){ qCDebug(dcZigbee()) << "Network PAN ID changed for" << network << panId; saveNetwork(network); emit zigbeeNetworkChanged(network); }); connect(network, &ZigbeeNetwork::channelChanged, this, [this, network](quint8 channel){ qCDebug(dcZigbee()) << "Network channel changed for" << network << channel; saveNetwork(network); emit zigbeeNetworkChanged(network); }); connect(network, &ZigbeeNetwork::macAddressChanged, this, [this, network](const ZigbeeAddress &macAddress){ qCDebug(dcZigbee()) << "Network MAC address changed for" << network << macAddress.toString(); saveNetwork(network); emit zigbeeNetworkChanged(network); }); connect(network, &ZigbeeNetwork::securityConfigurationChanged, this, [this, network](const ZigbeeSecurityConfiguration &securityConfiguration){ qCDebug(dcZigbee()) << "Network security configuration changed for" << network << securityConfiguration.networkKey().toString() << securityConfiguration.globalTrustCenterLinkKey().toString(); saveNetwork(network); }); connect(network, &ZigbeeNetwork::channelMaskChanged, this, [this, network](const ZigbeeChannelMask &channelMask){ qCDebug(dcZigbee()) << "Network channel mask changed for" << network << channelMask; saveNetwork(network); emit zigbeeNetworkChanged(network); }); connect(network, &ZigbeeNetwork::permitJoiningEnabledChanged, this, [this, network](bool permitJoiningEnabled){ qCDebug(dcZigbee()) << "Network permit joining changed" << network->networkUuid().toString() << permitJoiningEnabled; emit zigbeeNetworkChanged(network); }); connect(network, &ZigbeeNetwork::nodeAdded, this, [this, network](ZigbeeNode *node){ qCDebug(dcZigbee()) << "Node added to" << network << node; // The plugin don't need to see the coordinator node if (node->shortAddress() == 0) { return; } qCDebug(dcZigbee()) << "-->" << node; foreach (ZigbeeNodeEndpoint *endpoint, node->endpoints()) { qCDebug(dcZigbee()) << " " << endpoint; if (!endpoint->manufacturerName().isEmpty()) qCDebug(dcZigbee()) << " Manufacturer:" << endpoint->manufacturerName(); if (!endpoint->modelIdentifier().isEmpty()) qCDebug(dcZigbee()) << " Model" << endpoint->modelIdentifier(); if (!endpoint->softwareBuildId().isEmpty()) qCDebug(dcZigbee()) << " Version" << endpoint->softwareBuildId(); qCDebug(dcZigbee()) << " Input clusters (" << endpoint->inputClusters().count() << ")"; foreach (ZigbeeCluster *cluster, endpoint->inputClusters()) { qCDebug(dcZigbee()) << " -" << cluster; foreach(const ZigbeeClusterAttribute &attribute, cluster->attributes()) { qCDebug(dcZigbee()) << " - " << attribute; } } qCDebug(dcZigbee()) << " Output clusters (" << endpoint->outputClusters().count() << ")"; foreach (ZigbeeCluster *cluster, endpoint->outputClusters()) { qCDebug(dcZigbee()) << " -" << cluster; foreach(const ZigbeeClusterAttribute &attribute, cluster->attributes()) { qCDebug(dcZigbee()) << " - " << attribute; } } } emit nodeAdded(network->networkUuid(), node); }); connect(network, &ZigbeeNetwork::nodeRemoved, this, [this, network](ZigbeeNode *node){ qCDebug(dcZigbee()) << "Node removed from" << network->networkUuid().toString() << node; // The plugin don't need to see the coordinator node if (node->shortAddress() == 0) { return; } emit nodeRemoved(network->networkUuid(), node); }); connect(network, &ZigbeeNetwork::nodeJoined, this, [this, network](ZigbeeNode *node){ // The node has joined but is still initializing. Once the node has been initialized by the stack, the node added signal will be emitted. qCDebug(dcZigbee()) << "Node joined the network" << network->networkUuid().toString() << node; emit nodeJoined(network->networkUuid(), node); setupNodeSignals(node); }); connect(network, &ZigbeeNetwork::firmwareVersionChanged, this, [this, network](const QString &firmwareVersion){ qCDebug(dcZigbee()) << "Network adapter firmware version changed for" << network << firmwareVersion; emit zigbeeNetworkChanged(network); }); m_zigbeeNetworks.insert(network->networkUuid(), network); emit zigbeeNetworkAdded(network); qCDebug(dcZigbee()) << "Network added" << network; foreach (ZigbeeNode *node, network->nodes()) { qCDebug(dcZigbee()) << "-->" << node; foreach (ZigbeeNodeEndpoint *endpoint, node->endpoints()) { qCDebug(dcZigbee()) << " " << endpoint; if (!endpoint->manufacturerName().isEmpty()) qCDebug(dcZigbee()) << " Manufacturer:" << endpoint->manufacturerName(); if (!endpoint->modelIdentifier().isEmpty()) qCDebug(dcZigbee()) << " Model" << endpoint->modelIdentifier(); if (!endpoint->softwareBuildId().isEmpty()) qCDebug(dcZigbee()) << " Version" << endpoint->softwareBuildId(); qCDebug(dcZigbee()) << " Input clusters (" << endpoint->inputClusters().count() << ")"; foreach (ZigbeeCluster *cluster, endpoint->inputClusters()) { qCDebug(dcZigbee()) << " -" << cluster; foreach(const ZigbeeClusterAttribute &attribute, cluster->attributes()) { qCDebug(dcZigbee()) << " - " << attribute; } } qCDebug(dcZigbee()) << " Output clusters (" << endpoint->outputClusters().count() << ")"; foreach (ZigbeeCluster *cluster, endpoint->outputClusters()) { qCDebug(dcZigbee()) << " -" << cluster; foreach(const ZigbeeClusterAttribute &attribute, cluster->attributes()) { qCDebug(dcZigbee()) << " - " << attribute; } } } } foreach (ZigbeeNode *node, network->nodes()) { setupNodeSignals(node); } } ZigbeeAdapter ZigbeeManager::convertUartAdapterToAdapter(const ZigbeeUartAdapter &uartAdapter) { ZigbeeAdapter adapter; adapter.setName(uartAdapter.name()); adapter.setSerialPort(uartAdapter.serialPort()); adapter.setDescription(uartAdapter.description()); adapter.setSerialNumber(uartAdapter.serialNumber()); adapter.setHardwareRecognized(uartAdapter.hardwareRecognized()); adapter.setBaudRate(uartAdapter.baudRate()); switch (uartAdapter.zigbeeBackend()) { case Zigbee::ZigbeeBackendTypeDeconz: adapter.setBackendType(ZigbeeAdapter::ZigbeeBackendTypeDeconz); break; case Zigbee::ZigbeeBackendTypeNxp: adapter.setBackendType(ZigbeeAdapter::ZigbeeBackendTypeNxp); break; default: qCWarning(dcZigbee()) << "Unhandled backend type" << uartAdapter.zigbeeBackend() << "which is not implemented in nymea yet."; break; } return adapter; } void ZigbeeManager::evaluateZigbeeAvailable() { bool zigbeeAvailable = false; if (!m_zigbeeNetworks.isEmpty()) { foreach (ZigbeeNetwork *network, m_zigbeeNetworks.values()) { if (network->state() == ZigbeeNetwork::StateRunning) { zigbeeAvailable = true; break; } } } if (m_available == zigbeeAvailable) return; qCDebug(dcZigbee()) << "Zigbee is" << (zigbeeAvailable ? "now available" : "not available any more."); m_available = zigbeeAvailable; emit availableChanged(m_available); } void ZigbeeManager::setupNodeSignals(ZigbeeNode *node) { // Connect signals while joining for initializing connect(node, &ZigbeeNode::shortAddressChanged, this, [=](){ emit nodeChanged(node->networkUuid(), node); }); connect(node, &ZigbeeNode::stateChanged, this, [=](){ emit nodeChanged(node->networkUuid(), node); }); connect(node, &ZigbeeNode::manufacturerNameChanged, this, [=](){ emit nodeChanged(node->networkUuid(), node); }); connect(node, &ZigbeeNode::modelNameChanged, this, [=](){ emit nodeChanged(node->networkUuid(), node); }); connect(node, &ZigbeeNode::versionChanged, this, [=](){ emit nodeChanged(node->networkUuid(), node); }); connect(node, &ZigbeeNode::lqiChanged, this, [=](){ emit nodeChanged(node->networkUuid(), node); }); connect(node, &ZigbeeNode::lastSeenChanged, this, [=](){ emit nodeChanged(node->networkUuid(), node); }); connect(node, &ZigbeeNode::reachableChanged, this, [=](){ emit nodeChanged(node->networkUuid(), node); }); } }