This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
powersync-core/libnymea-core/hardware/zwave/zwavehardwareresourceimplementation.cpp
2025-11-17 16:42:41 +01:00

178 lines
6.3 KiB
C++

// SPDX-License-Identifier: LGPL-3.0-or-later
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
*
* This file is part of nymea.
*
* nymea is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* nymea 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 nymea. If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "zwavehardwareresourceimplementation.h"
#include "zwave/zwavemanager.h"
#include "zwave/zwavenetwork.h"
#include "loggingcategories.h"
Q_DECLARE_LOGGING_CATEGORY(dcZWave)
namespace nymeaserver
{
ZWaveHardwareResourceImplementation::ZWaveHardwareResourceImplementation(ZWaveManager *zwaveManager, QObject *parent):
ZWaveHardwareResource(parent),
m_zwaveManager(zwaveManager)
{
connect(m_zwaveManager, &ZWaveManager::networkStateChanged, this, &ZWaveHardwareResourceImplementation::onNetworkStateChanged);
connect(m_zwaveManager, &ZWaveManager::nodeInitialized, this, &ZWaveHardwareResourceImplementation::onNodeInitialized);
connect(m_zwaveManager, &ZWaveManager::nodeRemoved, this, &ZWaveHardwareResourceImplementation::onNodeRemoved);
// connect(m_zigbeeManager, &ZigbeeManager::availableChanged, this, &ZigbeeHardwareResourceImplementation::onZigbeeAvailableChanged);
}
bool ZWaveHardwareResourceImplementation::available() const
{
return m_zwaveManager->available();
}
bool ZWaveHardwareResourceImplementation::enabled() const
{
return m_zwaveManager->enabled();
}
void ZWaveHardwareResourceImplementation::setEnabled(bool enabled)
{
m_zwaveManager->setEnabled(enabled);
}
void ZWaveHardwareResourceImplementation::registerHandler(ZWaveHandler *handler, HandlerType type)
{
qCDebug(dcZWave()) << "Registering new Z-Wave handler" << handler->name() << "with type" << type;
m_handlers.insert(type, handler);
}
ZWaveNode *ZWaveHardwareResourceImplementation::claimNode(ZWaveHandler *handler, const QUuid &networkUuid, quint8 nodeId)
{
if (!m_handlers.values().contains(handler)) {
qCWarning(dcZWave()) << "Handler" << handler->name() << "is not registered. Not allowing node to be claimed.";
return nullptr;
}
ZWaveNetwork *network = m_zwaveManager->network(networkUuid);
if (!network) {
qCWarning(dcZWave()) << "Network" << networkUuid << "not found.";
return nullptr;
}
ZWaveNode *node = network->node(nodeId);
if (!node) {
qCWarning(dcZWave()) << "Node with ID" << nodeId << "not found in ZWave network" << networkUuid.toString();
return nullptr;
}
if (m_nodeHandlers.contains(node) && m_nodeHandlers.value(node) != handler) {
qCWarning(dcZWave()) << "Node with ID" << nodeId << "is already claimed by another handler (" << m_nodeHandlers.value(node)->name() << "). Not allowing node to be reclaimed.";
return nullptr;
}
m_nodeHandlers[node] = handler;
return node;
}
void ZWaveHardwareResourceImplementation::thingsLoaded()
{
m_thingsLoaded = true;
qCDebug(dcZWave) << "Things loaded. Checking for unhandled nodes...";
// We can assume here that all handled nodes have been claimed by plugins
// In case we started up and loaded new Z-Wave plugins, let's try to get all previously joined nodes handled now...
foreach (ZWaveNetwork *network, m_zwaveManager->networks()) {
foreach (ZWaveNode *node, network->nodes()) {
// Ignore the controller node
if (node->nodeId() == network->controllerNodeId())
continue;
if (!m_nodeHandlers.contains(node)) {
qCDebug(dcZWave()) << "Node" << node << "is not yet handled by any plugin. Trying to find a suitable plugin.";
handleNewNode(node);
}
}
}
}
void ZWaveHardwareResourceImplementation::onNetworkStateChanged(ZWaveNetwork *network)
{
// If the network is now ready and things have been loaded already, check if there are
// unclaimed nodes that might be handled now. This might happen if a node joins the network
// but no appropriate plugin had been installed at the time. If additional plugins have
// been installed now, such nodes might be handled by them now.
if (network->networkState() == ZWaveNetwork::ZWaveNetworkStateOnline && m_thingsLoaded) {
foreach (ZWaveNode *node, network->nodes()) {
// Ignore the controller node
if (node->nodeId() == network->controllerNodeId())
continue;
if (!m_nodeHandlers.contains(node)) {
handleNewNode(node);
}
}
}
}
void ZWaveHardwareResourceImplementation::onNodeInitialized(ZWaveNode *node)
{
if (!m_thingsLoaded) {
return;
}
handleNewNode(node);
}
void ZWaveHardwareResourceImplementation::onNodeRemoved(ZWaveNode *node)
{
qCDebug(dcZWave()) << "Node removed from the network";
ZWaveHandler *handler = m_nodeHandlers.value(node);
if (handler) {
handler->handleRemoveNode(node);
}
}
void ZWaveHardwareResourceImplementation::handleNewNode(ZWaveNode *node)
{
ZWaveNetwork *network = m_zwaveManager->network(node->networkUuid());
if (node->nodeId() == network->controllerNodeId()) {
// Not forwarding the controller node to plugins...
return;
}
qCDebug(dcZWave()) << "Node" << node->nodeId() << "added to the network:" << node->networkUuid().toString();
ZWaveHandler *handler = nullptr;
foreach (ZWaveHandler *tmp, m_handlers) {
if (tmp->handleNode(node)) {
handler = tmp;
m_nodeHandlers.insert(node, handler);
qCDebug(dcZWave()) << "Node" << node->nodeId() << "taken by handler" << handler->name();
break;
}
}
if (!handler) {
qCInfo(dcZWave()) << "No Z-Wave handler available to handle node" << node;
return;
}
}
}