/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 Lesser General Public License Usage * Alternatively, this project may be redistributed and/or modified under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation; 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "zigbeehandler.h" #include "zigbee/zigbeemanager.h" #include "zigbee/zigbeeadapters.h" #include "loggingcategories.h" #include namespace nymeaserver { ZigbeeHandler::ZigbeeHandler(ZigbeeManager *zigbeeManager, QObject *parent) : JsonHandler(parent), m_zigbeeManager(zigbeeManager) { qRegisterMetaType(); qRegisterMetaType(); registerEnum(); registerEnum(); registerEnum(); registerObject(); // Network object describing a network instance QVariantMap zigbeeNetworkDescription; zigbeeNetworkDescription.insert("networkUuid", enumValueName(Uuid)); 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)); zigbeeNetworkDescription.insert("permitJoiningEnabled", enumValueName(Bool)); zigbeeNetworkDescription.insert("permitJoiningDuration", enumValueName(Uint)); zigbeeNetworkDescription.insert("permitJoiningRemaining", enumValueName(Uint)); zigbeeNetworkDescription.insert("backendType", enumRef()); zigbeeNetworkDescription.insert("networkState", enumRef()); registerObject("ZigbeeNetwork", zigbeeNetworkDescription); QVariantMap params, returns; QString description; // 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. 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()); registerMethod("GetAdapters", description, params, returns); // AdapterAdded notification params.clear(); description = "Emitted whenever a new Zigbee adapter candidate has been detected in the system."; params.insert("adapter", objectRef()); registerNotification("AdapterAdded", description, params); // AdapterRemoved notification params.clear(); description = "Emitted whenever a Zigbee adapter has been removed from the system (i.e. unplugged)."; params.insert("adapter", objectRef()); registerNotification("AdapterRemoved", description, params); // GetNetworks params.clear(); returns.clear(); 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 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 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("serialPort", enumValueName(String)); params.insert("baudRate", enumValueName(Uint)); params.insert("backendType", enumRef()); params.insert("o:channelMask", enumValueName(Uint)); returns.insert("zigbeeError", enumRef()); 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."; params.insert("networkUuid", enumValueName(Uuid)); returns.insert("zigbeeError", enumRef()); registerMethod("RemoveNetwork", description, params, returns); // NetworkAdded notification params.clear(); 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."; params.insert("networkUuid", enumValueName(Uuid)); registerNotification("NetworkRemoved", description, params); // NetworkChanged notification params.clear(); description = "Emitted whenever a new Zigbee network has changed."; params.insert("zigbeeNetwork", 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()); 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. " "The duration values has to be between 0 and 255 seconds. The permitJoinDuration indicates how long permit " "has been enabled and the permitJoinDuration indicates the rest of the time. Those values can be used to " "show a countdown or progressbar. This method can be recalled for resetting the timeout. " "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 link quality index (LQI)."; params.insert("networkUuid", enumValueName(Uuid)); params.insert("duration", enumValueName(Uint)); params.insert("o:shortAddress", enumValueName(Uint)); returns.insert("zigbeeError", enumRef()); registerMethod("SetPermitJoin", description, params, returns); connect(m_zigbeeManager, &ZigbeeManager::availableAdapterAdded, this, [this](const ZigbeeAdapter &adapter){ QVariantMap params; params.insert("adapter", pack(adapter)); emit AdapterAdded(params); }); connect(m_zigbeeManager, &ZigbeeManager::availableAdapterRemoved, this, [this](const ZigbeeAdapter &adapter){ QVariantMap params; params.insert("adapter", pack(adapter)); emit AdapterRemoved(params); }); connect(m_zigbeeManager, &ZigbeeManager::zigbeeNetworkAdded, this, [this](ZigbeeNetwork *network){ QVariantMap params; params.insert("zigbeeNetwork", packNetwork(network)); emit NetworkAdded(params); }); 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); emit NetworkRemoved(params); }); } QString ZigbeeHandler::name() const { return "Zigbee"; } JsonReply *ZigbeeHandler::GetAdapters(const QVariantMap ¶ms) { Q_UNUSED(params) QVariantMap returnMap; QVariantList adapterList; foreach (const ZigbeeAdapter &adapter, m_zigbeeManager->availableAdapters()) { adapterList << pack(adapter); } returnMap.insert("adapters", adapterList); return createReply(returnMap); } JsonReply *ZigbeeHandler::AddNetwork(const QVariantMap ¶ms) { QString serialPort = params.value("serialPort").toString(); uint baudRate = params.value("baudRate").toUInt(); ZigbeeAdapter::ZigbeeBackendType backendType = enumNameToValue(params.value("backendType").toString()); QPair result = m_zigbeeManager->createZigbeeNetwork(serialPort, baudRate, backendType); QVariantMap returnMap; if (result.first == ZigbeeManager::ZigbeeErrorNoError) { returnMap.insert("networkUuid", result.second); } returnMap.insert("zigbeeError", enumValueName(result.first)); return createReply(returnMap); } JsonReply *ZigbeeHandler::RemoveNetwork(const QVariantMap ¶ms) { QUuid networkUuid = params.value("networkUuid").toUuid(); ZigbeeManager::ZigbeeError error = m_zigbeeManager->removeZigbeeNetwork(networkUuid); QVariantMap returnMap; returnMap.insert("zigbeeError", enumValueName(error)); return createReply(returnMap); } JsonReply *ZigbeeHandler::FactoryResetNetwork(const QVariantMap ¶ms) { QUuid networkUuid = params.value("networkUuid").toUuid(); ZigbeeManager::ZigbeeError error = m_zigbeeManager->factoryResetNetwork(networkUuid); QVariantMap returnMap; returnMap.insert("zigbeeError", enumValueName(error)); return createReply(returnMap); } JsonReply *ZigbeeHandler::SetPermitJoin(const QVariantMap ¶ms) { QUuid networkUuid = params.value("networkUuid").toUuid(); uint duration = params.value("duration").toUInt(); quint16 shortAddress = static_cast(Zigbee::BroadcastAddressAllRouters); if (params.contains("shortAddress")) { shortAddress = static_cast(params.value("shortAddress").toUInt()); } ZigbeeManager::ZigbeeError error = m_zigbeeManager->setZigbeeNetworkPermitJoin(networkUuid, shortAddress, duration); QVariantMap returnMap; returnMap.insert("zigbeeError", enumValueName(error)); return createReply(returnMap); } JsonReply *ZigbeeHandler::GetNetworks(const QVariantMap ¶ms) { 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("firmwareVersion", network->firmwareVersion()); networkMap.insert("panId", network->panId()); networkMap.insert("channel", network->channel()); networkMap.insert("channelMask", network->channelMask().toUInt32()); networkMap.insert("permitJoiningEnabled", network->permitJoiningEnabled()); networkMap.insert("permitJoiningDuration", network->permitJoiningDuration()); networkMap.insert("permitJoiningRemaining", network->permitJoiningRemaining()); switch (network->backendType()) { case Zigbee::ZigbeeBackendTypeDeconz: networkMap.insert("backendType", enumValueName(ZigbeeAdapter::ZigbeeBackendTypeDeconz)); break; case Zigbee::ZigbeeBackendTypeNxp: networkMap.insert("backendType", enumValueName(ZigbeeAdapter::ZigbeeBackendTypeNxp)); break; } switch (network->state()) { case ZigbeeNetwork::StateOffline: case ZigbeeNetwork::StateStopping: networkMap.insert("networkState", enumValueName(ZigbeeManager::ZigbeeNetworkStateOffline)); break; case ZigbeeNetwork::StateStarting: networkMap.insert("networkState", enumValueName(ZigbeeManager::ZigbeeNetworkStateStarting)); break; case ZigbeeNetwork::StateRunning: networkMap.insert("networkState", enumValueName(ZigbeeManager::ZigbeeNetworkStateOnline)); break; case ZigbeeNetwork::StateUpdating: networkMap.insert("networkState", enumValueName(ZigbeeManager::ZigbeeNetworkStateUpdating)); break; case ZigbeeNetwork::StateUninitialized: networkMap.insert("networkState", enumValueName(ZigbeeManager::ZigbeeNetworkStateError)); break; } return networkMap; } }