/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright 2013 - 2022, 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 "zwavehandler.h" namespace nymeaserver { ZWaveHandler::ZWaveHandler(ZWaveManager *zwaveManager, QObject *parent): JsonHandler(parent), m_zwaveManager(zwaveManager) { registerEnum(); registerObject(); registerEnum(); registerEnum(); registerEnum(); registerEnum(); QVariantMap networkDescription; networkDescription.insert("networkUuid", enumValueName(Uuid)); networkDescription.insert("serialPort", enumValueName(String)); networkDescription.insert("networkState", enumRef()); networkDescription.insert("homeId", enumValueName(Uint)); networkDescription.insert("isZWavePlus", enumValueName(Bool)); networkDescription.insert("isStaticUpdateController", enumValueName(Bool)); networkDescription.insert("isPrimaryController", enumValueName(Bool)); networkDescription.insert("isBridgeController", enumValueName(Bool)); networkDescription.insert("waitingForNodeAddition", enumValueName(Bool)); networkDescription.insert("waitingForNodeRemoval", enumValueName(Bool)); registerObject("ZWaveNetwork", networkDescription); QVariantMap nodeDescription; nodeDescription.insert("nodeId", enumValueName(Uint)); nodeDescription.insert("networkUuid", enumValueName(Uuid)); nodeDescription.insert("initialized", enumValueName(Bool)); nodeDescription.insert("reachable", enumValueName(Bool)); nodeDescription.insert("failed", enumValueName(Bool)); nodeDescription.insert("sleeping", enumValueName(Bool)); nodeDescription.insert("linkQuality", enumValueName(Uint)); nodeDescription.insert("securityMode", enumValueName(Uint)); nodeDescription.insert("nodeType", enumRef()); nodeDescription.insert("role", enumRef()); nodeDescription.insert("deviceType", enumRef()); nodeDescription.insert("productType", enumValueName(Uint)); nodeDescription.insert("productId", enumValueName(Uint)); nodeDescription.insert("productName", enumValueName(String)); nodeDescription.insert("manufacturerId", enumValueName(Uint)); nodeDescription.insert("manufacturerName", enumValueName(String)); nodeDescription.insert("version", enumValueName(String)); nodeDescription.insert("isZWavePlusDevice", enumValueName(Bool)); nodeDescription.insert("isSecurityDevice", enumValueName(Bool)); nodeDescription.insert("isBeamingDevice", enumValueName(Bool)); registerObject("ZWaveNode", nodeDescription); QVariantMap params, returns; QString description; params.clear(); returns.clear(); description = "Query if the Z-Wave subsystem is available at all."; returns.insert("available", enumValueName(Bool)); registerMethod("IsZWaveAvailable", description, params, returns); params.clear(); returns.clear(); description = "Get the list of available serial ports from the host system."; returns.insert("serialPorts", objectRef()); registerMethod("GetSerialPorts", description, params, returns); params.clear(); returns.clear(); description = "Get all the Z-Wave networks in the system."; returns.insert("networks", QVariantList() << objectRef("ZWaveNetwork")); registerMethod("GetNetworks", description, params, returns); params.clear(); returns.clear(); description = "Add a new Z-Wave network with the given serial port."; params.insert("serialPort", enumValueName(String)); returns.insert("o:networkUuid", enumValueName(Uuid)); returns.insert("zwaveError", enumRef()); registerMethod("AddNetwork", description, params, returns); params.clear(); returns.clear(); description = "Remove the given Z-Wave network from the system."; params.insert("networkUuid", enumValueName(Uuid)); returns.insert("zwaveError", enumRef()); registerMethod("RemoveNetwork", description, params, returns); params.clear(); returns.clear(); description = "Start the node inclusion procedure for the given Z-Wave network."; params.insert("networkUuid", enumValueName(Uuid)); returns.insert("zwaveError", enumRef()); registerMethod("AddNode", description, params, returns); params.clear(); returns.clear(); description = "Start the node removal procedure for the given Z-Wave network."; params.insert("networkUuid", enumValueName(Uuid)); returns.insert("zwaveError", enumRef()); registerMethod("RemoveNode", description, params, returns); params.clear(); returns.clear(); description = "Cancel any running node inclusion or removal procedure for the given Z-Wave network."; params.insert("networkUuid", enumValueName(Uuid)); returns.insert("zwaveError", enumRef()); registerMethod("CancelPendingOperation", description, params, returns); params.clear(); returns.clear(); description = "Remove the given failed node from the given Z-Wave network. This will not work if node is not marked as failed."; params.insert("networkUuid", enumValueName(Uuid)); params.insert("nodeId", enumValueName(Uint)); returns.insert("zwaveError", enumRef()); registerMethod("RemoveFailedNode", description, params, returns); params.clear(); returns.clear(); description = "Factory reset the controller for the given Z-Wave network."; params.insert("networkUuid", enumValueName(Uuid)); returns.insert("zwaveError", enumRef()); registerMethod("FactoryResetNetwork", description, params, returns); params.clear(); returns.clear(); description = "Get the list of nodes in a network"; params.insert("networkUuid", enumValueName(Uuid)); returns.insert("zwaveError", enumRef()); returns.insert("o:nodes", QVariantList() << objectRef("ZWaveNode")); registerMethod("GetNodes", description, params, returns); // Notifications params.clear(); description = "Emitted whenever a new Z-Wave network has been added to the system."; params.insert("network", objectRef("ZWaveNetwork")); registerNotification("NetworkAdded", description, params); params.clear(); description = "Emitted whenever a Z-Wave network has been removed from the system."; params.insert("networkUuid", enumValueName(Uuid)); registerNotification("NetworkRemoved", description, params); params.clear(); description = "Emitted whenever a Z-Wave network changes."; params.insert("network", objectRef("ZWaveNetwork")); registerNotification("NetworkChanged", description, params); params.clear(); description = "Emitted whenever a Z-Wave node is added."; params.insert("networkUuid", enumValueName(Uuid)); params.insert("node", objectRef("ZWaveNode")); registerNotification("NodeAdded", description, params); params.clear(); description = "Emitted whenever a Z-Wave node has changed."; params.insert("networkUuid", enumValueName(Uuid)); params.insert("node", objectRef("ZWaveNode")); registerNotification("NodeChanged", description, params); params.clear(); description = "Emitted whenever a Z-Wave node is removed."; params.insert("networkUuid", enumValueName(Uuid)); params.insert("nodeId", enumValueName(Uint)); registerNotification("NodeRemoved", description, params); connect(m_zwaveManager, &ZWaveManager::networkAdded, this, &ZWaveHandler::onNetworkAdded); connect(m_zwaveManager, &ZWaveManager::networkChanged, this, &ZWaveHandler::onNetworkChanged); connect(m_zwaveManager, &ZWaveManager::networkStateChanged, this, &ZWaveHandler::onNetworkChanged); connect(m_zwaveManager, &ZWaveManager::networkRemoved, this, &ZWaveHandler::onNetworkRemoved); connect(m_zwaveManager, &ZWaveManager::nodeAdded, this, &ZWaveHandler::onNodeAdded); connect(m_zwaveManager, &ZWaveManager::nodeChanged, this, &ZWaveHandler::onNodeChanged); connect(m_zwaveManager, &ZWaveManager::nodeRemoved, this, &ZWaveHandler::onNodeRemoved); } QString ZWaveHandler::name() const { return "ZWave"; } JsonReply *ZWaveHandler::IsZWaveAvailable(const QVariantMap ¶ms) { Q_UNUSED(params) return createReply({{"available", m_zwaveManager->available()}}); } JsonReply *ZWaveHandler::GetSerialPorts(const QVariantMap ¶ms) { Q_UNUSED(params) QVariantList portList; foreach (const SerialPort &serialPort, m_zwaveManager->serialPorts()) { portList << pack(serialPort); } return createReply({{"serialPorts", portList}}); } JsonReply *ZWaveHandler::GetNetworks(const QVariantMap ¶ms) { Q_UNUSED(params) QVariantList networkList; foreach (ZWaveNetwork *network, m_zwaveManager->networks()) { networkList.append(packNetwork(network)); } return createReply({{"networks", networkList}}); } JsonReply *ZWaveHandler::AddNetwork(const QVariantMap ¶ms) { QPair status = m_zwaveManager->createNetwork(params.value("serialPort").toString()); QVariantMap returns; returns.insert("zwaveError", enumValueName(status.first)); if (status.first == ZWave::ZWaveErrorNoError) { returns.insert("networkUuid", status.second); } return createReply(returns); } JsonReply *ZWaveHandler::RemoveNetwork(const QVariantMap ¶ms) { QUuid networkUuid = params.value("networkUuid").toUuid(); ZWave::ZWaveError status = m_zwaveManager->removeNetwork(networkUuid); return createReply({{"zwaveError", enumValueName(status)}}); } JsonReply *ZWaveHandler::FactoryResetNetwork(const QVariantMap ¶ms) { QUuid networkUuid = params.value("networkUuid").toUuid(); ZWave::ZWaveError status = m_zwaveManager->factoryResetNetwork(networkUuid); return createReply({{"zwaveError", enumValueName(status)}}); } JsonReply *ZWaveHandler::AddNode(const QVariantMap ¶ms) { ZWaveReply *zwaveReply = m_zwaveManager->addNode(params.value("networkUuid").toUuid()); JsonReply *jsonReply = createAsyncReply("AddNode"); connect(zwaveReply, &ZWaveReply::finished, jsonReply, [jsonReply](ZWave::ZWaveError status) { jsonReply->setData({{"zwaveError", enumValueName(status)}}); jsonReply->finished(); }); return jsonReply; } JsonReply *ZWaveHandler::GetNodes(const QVariantMap ¶ms) { QUuid networkUuid = params.value("networkUuid").toUuid(); ZWaveNetwork *network = m_zwaveManager->network(networkUuid); if (!network) { return createReply({{"zwaveError", enumValueName(ZWave::ZWaveErrorNetworkUuidNotFound)}}); } ZWaveNodes nodes = m_zwaveManager->network(networkUuid)->nodes(); QVariantList nodeList; foreach (ZWaveNode *node, nodes) { nodeList.append(packNode(node)); } return createReply({ {"zwaveError", enumValueName(ZWave::ZWaveErrorNoError)}, {"nodes", nodeList} }); } JsonReply *ZWaveHandler::RemoveNode(const QVariantMap ¶ms) { QUuid networkUuid = params.value("networkUuid").toUuid(); JsonReply *jsonReply = createAsyncReply("RemoveNode"); ZWaveReply *zwaveReply = m_zwaveManager->removeNode(networkUuid); connect(zwaveReply, &ZWaveReply::finished, jsonReply, [jsonReply](ZWave::ZWaveError status) { jsonReply->setData({{"zwaveError", enumValueName(status)}}); jsonReply->finished(); }); return jsonReply; } JsonReply *ZWaveHandler::RemoveFailedNode(const QVariantMap ¶ms) { QUuid networkUuid = params.value("networkUuid").toUuid(); quint8 nodeId = params.value("nodeId").toUInt(); m_zwaveManager->removeFailedNode(networkUuid, nodeId); return createReply({{"zwaveError", enumValueName(ZWave::ZWaveErrorNoError)}}); } JsonReply *ZWaveHandler::CancelPendingOperation(const QVariantMap ¶ms) { QUuid networkUuid = params.value("networkUuid").toUuid(); m_zwaveManager->cancelPendingOperation(networkUuid); return createReply({{"zwaveError", enumValueName(ZWave::ZWaveErrorNoError)}}); } void ZWaveHandler::onNetworkAdded(ZWaveNetwork *network) { emit NetworkAdded({{"network", packNetwork(network)}}); } void ZWaveHandler::onNetworkChanged(ZWaveNetwork *network) { emit NetworkChanged({{"network", packNetwork(network)}}); } void ZWaveHandler::onNetworkRemoved(const QUuid &networkUuid) { emit NetworkRemoved({{"networkUuid", networkUuid.toString()}}); } void ZWaveHandler::onNodeAdded(ZWaveNode *node) { emit NodeAdded({{"networkUuid", node->networkUuid()}, {"node", packNode(node)}}); } void ZWaveHandler::onNodeChanged(ZWaveNode *node) { emit NodeChanged({{"networkUuid", node->networkUuid()}, {"node", packNode(node)}}); } void ZWaveHandler::onNodeRemoved(ZWaveNode *node) { emit NodeRemoved({{"networkUuid", node->networkUuid()}, {"nodeId", node->nodeId()}}); } QVariantMap ZWaveHandler::packNetwork(ZWaveNetwork *network) { return { {"networkUuid", network->networkUuid()}, {"serialPort", network->serialPort()}, {"networkState", enumValueName(network->networkState())}, {"homeId", network->homeId()}, {"isZWavePlus", network->isZWavePlus()}, {"isPrimaryController", network->isPrimaryController()}, {"isStaticUpdateController", network->isStaticUpdateController()}, {"isBridgeController", network->isBridgeController()}, {"waitingForNodeAddition", network->waitingForNodeAddition()}, {"waitingForNodeRemoval", network->waitingForNodeRemoval()} }; } QVariantMap ZWaveHandler::packNode(ZWaveNode *node) { return { {"nodeId", node->nodeId()}, {"networkUuid", node->networkUuid()}, {"initialized", node->initialized()}, {"reachable", node->reachable()}, {"failed", node->failed()}, {"sleeping", node->sleeping()}, {"linkQuality", node->linkQuality()}, {"securityMode", node->securityMode()}, {"nodeType", enumValueName(node->nodeType())}, {"role", enumValueName(node->role())}, {"deviceType", enumValueName(node->deviceType())}, {"productType", node->productType()}, {"productId", node->productId()}, {"productName", node->productName()}, {"manufacturerId", node->manufacturerId()}, {"manufacturerName", node->manufacturerName()}, {"version", node->version()}, {"isZWavePlusDevice", node->isZWavePlusDevice()}, {"isSecurityDevice", node->isSecurityDevice()}, {"isBeamingDevice", node->isBeamingDevice()} }; } }