// SPDX-License-Identifier: GPL-3.0-or-later /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2013 - 2024, nymea GmbH * Copyright (C) 2025, ETM-Schurig SARL * * This file is part of nymea-plugins-modbus. * * nymea-plugins-modbus is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * nymea-plugins-modbus 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 nymea-plugins-modbus. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "integrationplugineastron.h" #include "plugininfo.h" IntegrationPluginEastron::IntegrationPluginEastron() { } void IntegrationPluginEastron::init() { connect(hardwareManager()->modbusRtuResource(), &ModbusRtuHardwareResource::modbusRtuMasterRemoved, this, [=](const QUuid &modbusUuid) { qCDebug(dcEastron()) << "Modbus RTU master removed:" << modbusUuid.toString(); foreach (Thing *thing, myThings()) { ThingClassId classId = thing->thingClassId(); if (classId == sdm630ThingClassId || classId == sdm630ConsumerThingClassId || classId == sdm630ProducerThingClassId) { if (thing->paramValue(sdm630ThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm630ConnectedStateTypeId, false); delete m_sdm630Connections.take(thing); } } else if (classId == sdm630ConsumerThingClassId) { if (thing->paramValue(sdm630ConsumerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm630ConsumerConnectedStateTypeId, false); delete m_sdm630Connections.take(thing); } } else if (classId == sdm630ProducerThingClassId) { if (thing->paramValue(sdm630ProducerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm630ProducerConnectedStateTypeId, false); delete m_sdm630Connections.take(thing); } } else if (classId == sdm72ThingClassId) { if (thing->paramValue(sdm72ThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm72ConnectedStateTypeId, false); delete m_sdm72Connections.take(thing); } } else if (classId == sdm72ConsumerThingClassId) { if (thing->paramValue(sdm72ConsumerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm72ConsumerConnectedStateTypeId, false); delete m_sdm72Connections.take(thing); } } else if (classId == sdm72ProducerThingClassId) { if (thing->paramValue(sdm72ProducerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm72ProducerConnectedStateTypeId, false); delete m_sdm72Connections.take(thing); } } else if (classId == sdm120ThingClassId) { if (thing->paramValue(sdm120ThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm120ConnectedStateTypeId, false); delete m_sdm120Connections.take(thing); } } else if (classId == sdm120ConsumerThingClassId) { if (thing->paramValue(sdm120ConsumerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm120ConsumerConnectedStateTypeId, false); delete m_sdm120Connections.take(thing); } } else if (classId == sdm120ProducerThingClassId) { if (thing->paramValue(sdm120ProducerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm120ProducerConnectedStateTypeId, false); delete m_sdm120Connections.take(thing); } } else if (classId == sdm220ThingClassId) { if (thing->paramValue(sdm220ThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm220ConnectedStateTypeId, false); delete m_sdm120Connections.take(thing); } } else if (classId == sdm220ConsumerThingClassId) { if (thing->paramValue(sdm220ConsumerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm220ConsumerConnectedStateTypeId, false); delete m_sdm120Connections.take(thing); } } else if (classId == sdm220ProducerThingClassId) { if (thing->paramValue(sdm220ProducerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm220ProducerConnectedStateTypeId, false); delete m_sdm120Connections.take(thing); } } else if (classId == sdm230ThingClassId) { if (thing->paramValue(sdm230ThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm230ConnectedStateTypeId, false); delete m_sdm120Connections.take(thing); } } else if (classId == sdm230ConsumerThingClassId) { if (thing->paramValue(sdm230ConsumerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm230ConsumerConnectedStateTypeId, false); delete m_sdm120Connections.take(thing); } } else if (classId == sdm230ProducerThingClassId) { if (thing->paramValue(sdm230ProducerThingModbusMasterUuidParamTypeId) == modbusUuid) { thing->setStateValue(sdm230ProducerConnectedStateTypeId, false); delete m_sdm120Connections.take(thing); } } } }); } void IntegrationPluginEastron::discoverThings(ThingDiscoveryInfo *info) { ThingClassId classId = info->thingClassId(); QString modelName; ParamTypeId discoverySlaveParamTypeId; ParamTypeId thingSlaveParamTypeId; ParamTypeId thingMasterUuidParamTypeId; if (classId == sdm630ThingClassId) { modelName = "SDM630"; discoverySlaveParamTypeId = sdm630DiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm630ThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm630ThingModbusMasterUuidParamTypeId; } else if (classId == sdm630ConsumerThingClassId) { modelName = "SDM630"; discoverySlaveParamTypeId = sdm630ConsumerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm630ConsumerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm630ConsumerThingModbusMasterUuidParamTypeId; } else if (classId == sdm630ProducerThingClassId) { modelName = "SDM630"; discoverySlaveParamTypeId = sdm630ProducerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm630ProducerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm630ProducerThingModbusMasterUuidParamTypeId; } else if (classId == sdm72ThingClassId) { modelName = "SDM72"; discoverySlaveParamTypeId = sdm72DiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm72ThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm72ThingModbusMasterUuidParamTypeId; } else if (classId == sdm72ConsumerThingClassId) { modelName = "SDM72"; discoverySlaveParamTypeId = sdm72ConsumerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm72ConsumerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm72ConsumerThingModbusMasterUuidParamTypeId; } else if (classId == sdm72ProducerThingClassId) { modelName = "SDM72"; discoverySlaveParamTypeId = sdm72ProducerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm72ProducerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm72ProducerThingModbusMasterUuidParamTypeId; } else if (classId == sdm120ThingClassId) { modelName = "SDM120"; discoverySlaveParamTypeId = sdm120DiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm120ThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm120ThingModbusMasterUuidParamTypeId; } else if (classId == sdm120ConsumerThingClassId) { modelName = "SDM120"; discoverySlaveParamTypeId = sdm120ConsumerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm120ConsumerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm120ConsumerThingModbusMasterUuidParamTypeId; } else if (classId == sdm120ProducerThingClassId) { modelName = "SDM120"; discoverySlaveParamTypeId = sdm120ProducerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm120ProducerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm120ProducerThingModbusMasterUuidParamTypeId; } else if (classId == sdm220ThingClassId) { modelName = "SDM220"; discoverySlaveParamTypeId = sdm220DiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm220ThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm220ThingModbusMasterUuidParamTypeId; } else if (classId == sdm220ConsumerThingClassId) { modelName = "SDM220"; discoverySlaveParamTypeId = sdm220ConsumerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm220ConsumerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm220ConsumerThingModbusMasterUuidParamTypeId; } else if (classId == sdm220ProducerThingClassId) { modelName = "SDM220"; discoverySlaveParamTypeId = sdm220ProducerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm220ProducerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm220ProducerThingModbusMasterUuidParamTypeId; } else if (classId == sdm230ThingClassId) { modelName = "SDM230"; discoverySlaveParamTypeId = sdm230DiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm230ThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm230ThingModbusMasterUuidParamTypeId; } else if (classId == sdm230ConsumerThingClassId) { modelName = "SDM230"; discoverySlaveParamTypeId = sdm230ConsumerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm230ConsumerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm230ConsumerThingModbusMasterUuidParamTypeId; } else if (classId == sdm230ProducerThingClassId) { modelName = "SDM230"; discoverySlaveParamTypeId = sdm230ProducerDiscoverySlaveAddressParamTypeId; thingSlaveParamTypeId = sdm230ProducerThingSlaveAddressParamTypeId; thingMasterUuidParamTypeId = sdm230ProducerThingModbusMasterUuidParamTypeId; } else { info->finish(Thing::ThingErrorThingClassNotFound); return; } discoverRtuDevices(info, modelName, discoverySlaveParamTypeId, thingSlaveParamTypeId, thingMasterUuidParamTypeId); } void IntegrationPluginEastron::discoverRtuDevices(ThingDiscoveryInfo *info, const QString &modelName, const ParamTypeId &discoverySlaveParamTypeId, const ParamTypeId &thingSlaveParamTypeId, const ParamTypeId &thingMasterUuidParamTypeId) { if (hardwareManager()->modbusRtuResource()->modbusRtuMasters().isEmpty()) { info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("No Modbus RTU interface available. Please set up the Modbus RTU interface first.")); return; } uint slaveAddress = info->params().paramValue(discoverySlaveParamTypeId).toUInt(); if (slaveAddress == 0 || slaveAddress > 254) { info->finish(Thing::ThingErrorInvalidParameter, QT_TR_NOOP("The Modbus slave address must be a value between 1 and 254.")); return; } foreach (ModbusRtuMaster *modbusMaster, hardwareManager()->modbusRtuResource()->modbusRtuMasters()) { qCDebug(dcEastron()) << "Found RTU master" << modbusMaster << "connected:" << modbusMaster->connected(); if (!modbusMaster->connected()) continue; ThingDescriptor descriptor(info->thingClassId(), modelName, QString::number(slaveAddress) + " " + modbusMaster->serialPort()); ParamList params; params << Param(thingSlaveParamTypeId, slaveAddress); params << Param(thingMasterUuidParamTypeId, modbusMaster->modbusUuid()); descriptor.setParams(params); info->addThingDescriptor(descriptor); } info->finish(Thing::ThingErrorNoError); } void IntegrationPluginEastron::setupThing(ThingSetupInfo *info) { ThingClassId classId = info->thing()->thingClassId(); if (classId == sdm630ThingClassId || classId == sdm630ConsumerThingClassId || classId == sdm630ProducerThingClassId) { setupSdm630(info); } else if (classId == sdm72ThingClassId || classId == sdm72ConsumerThingClassId || classId == sdm72ProducerThingClassId) { setupSdm72(info); } else if (classId == sdm120ThingClassId || classId == sdm120ConsumerThingClassId || classId == sdm120ProducerThingClassId || classId == sdm220ThingClassId || classId == sdm220ConsumerThingClassId || classId == sdm220ProducerThingClassId || classId == sdm230ThingClassId || classId == sdm230ConsumerThingClassId || classId == sdm230ProducerThingClassId) { setupSdm120(info); } else { info->finish(Thing::ThingErrorThingClassNotFound); } } void IntegrationPluginEastron::setupSdm630(ThingSetupInfo *info) { Thing *thing = info->thing(); ThingClassId classId = thing->thingClassId(); ParamTypeId slaveParamTypeId; ParamTypeId masterUuidParamTypeId; StateTypeId connectedStateTypeId; if (classId == sdm630ThingClassId) { slaveParamTypeId = sdm630ThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm630ThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm630ConnectedStateTypeId; } else if (classId == sdm630ConsumerThingClassId) { slaveParamTypeId = sdm630ConsumerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm630ConsumerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm630ConsumerConnectedStateTypeId; } else { slaveParamTypeId = sdm630ProducerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm630ProducerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm630ProducerConnectedStateTypeId; } uint address = thing->paramValue(slaveParamTypeId).toUInt(); if (address == 0 || address > 254) { qCWarning(dcEastron()) << "Setup failed, invalid slave address" << address; info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus address not valid. It must be a value between 1 and 254.")); return; } QUuid uuid = thing->paramValue(masterUuidParamTypeId).toUuid(); if (!hardwareManager()->modbusRtuResource()->hasModbusRtuMaster(uuid)) { qCWarning(dcEastron()) << "Setup failed, Modbus RTU master not available"; info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus RTU interface not available.")); return; } if (m_sdm630Connections.contains(thing)) m_sdm630Connections.take(thing)->deleteLater(); Sdm630ModbusRtuConnection *connection = new Sdm630ModbusRtuConnection( hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid), address, this); connect(connection, &Sdm630ModbusRtuConnection::reachableChanged, this, [=](bool reachable) { thing->setStateValue(connectedStateTypeId, reachable); }); if (classId == sdm630ThingClassId) { connect(connection, &Sdm630ModbusRtuConnection::voltagePhaseAChanged, this, [=](float v) { thing->setStateValue(sdm630VoltagePhaseAStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::voltagePhaseBChanged, this, [=](float v) { thing->setStateValue(sdm630VoltagePhaseBStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::voltagePhaseCChanged, this, [=](float v) { thing->setStateValue(sdm630VoltagePhaseCStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::currentPhaseAChanged, this, [=](float v) { thing->setStateValue(sdm630CurrentPhaseAStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::currentPhaseBChanged, this, [=](float v) { thing->setStateValue(sdm630CurrentPhaseBStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::currentPhaseCChanged, this, [=](float v) { thing->setStateValue(sdm630CurrentPhaseCStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::totalCurrentPowerChanged, this, [=](float v) { thing->setStateValue(sdm630CurrentPowerStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::powerPhaseAChanged, this, [=](float v) { thing->setStateValue(sdm630CurrentPowerPhaseAStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::powerPhaseBChanged, this, [=](float v) { thing->setStateValue(sdm630CurrentPowerPhaseBStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::powerPhaseCChanged, this, [=](float v) { thing->setStateValue(sdm630CurrentPowerPhaseCStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::frequencyChanged, this, [=](float v) { thing->setStateValue(sdm630FrequencyStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::totalEnergyConsumedChanged, this, [=](float v) { thing->setStateValue(sdm630TotalEnergyConsumedStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::totalEnergyProducedChanged, this, [=](float v) { thing->setStateValue(sdm630TotalEnergyProducedStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::energyConsumedPhaseAChanged, this, [=](float v) { thing->setStateValue(sdm630EnergyConsumedPhaseAStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::energyConsumedPhaseBChanged, this, [=](float v) { thing->setStateValue(sdm630EnergyConsumedPhaseBStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::energyConsumedPhaseCChanged, this, [=](float v) { thing->setStateValue(sdm630EnergyConsumedPhaseCStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::energyProducedPhaseAChanged, this, [=](float v) { thing->setStateValue(sdm630EnergyProducedPhaseAStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::energyProducedPhaseBChanged, this, [=](float v) { thing->setStateValue(sdm630EnergyProducedPhaseBStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::energyProducedPhaseCChanged, this, [=](float v) { thing->setStateValue(sdm630EnergyProducedPhaseCStateTypeId, v); }); } else if (classId == sdm630ConsumerThingClassId) { connect(connection, &Sdm630ModbusRtuConnection::totalCurrentPowerChanged, this, [=](float v) { thing->setStateValue(sdm630ConsumerCurrentPowerStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::totalEnergyConsumedChanged, this, [=](float v) { thing->setStateValue(sdm630ConsumerTotalEnergyConsumedStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::frequencyChanged, this, [=](float v) { thing->setStateValue(sdm630ConsumerFrequencyStateTypeId, v); }); } else { // sdm630Producer connect(connection, &Sdm630ModbusRtuConnection::totalCurrentPowerChanged, this, [=](float v) { thing->setStateValue(sdm630ProducerCurrentPowerStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::totalEnergyProducedChanged, this, [=](float v) { thing->setStateValue(sdm630ProducerTotalEnergyProducedStateTypeId, v); }); connect(connection, &Sdm630ModbusRtuConnection::frequencyChanged, this, [=](float v) { thing->setStateValue(sdm630ProducerFrequencyStateTypeId, v); }); } m_sdm630Connections.insert(thing, connection); info->finish(Thing::ThingErrorNoError); } void IntegrationPluginEastron::setupSdm72(ThingSetupInfo *info) { Thing *thing = info->thing(); ThingClassId classId = thing->thingClassId(); ParamTypeId slaveParamTypeId; ParamTypeId masterUuidParamTypeId; StateTypeId connectedStateTypeId; if (classId == sdm72ThingClassId) { slaveParamTypeId = sdm72ThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm72ThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm72ConnectedStateTypeId; } else if (classId == sdm72ConsumerThingClassId) { slaveParamTypeId = sdm72ConsumerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm72ConsumerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm72ConsumerConnectedStateTypeId; } else { slaveParamTypeId = sdm72ProducerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm72ProducerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm72ProducerConnectedStateTypeId; } uint address = thing->paramValue(slaveParamTypeId).toUInt(); if (address == 0 || address > 254) { qCWarning(dcEastron()) << "Setup failed, invalid slave address" << address; info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus address not valid. It must be a value between 1 and 254.")); return; } QUuid uuid = thing->paramValue(masterUuidParamTypeId).toUuid(); if (!hardwareManager()->modbusRtuResource()->hasModbusRtuMaster(uuid)) { qCWarning(dcEastron()) << "Setup failed, Modbus RTU master not available"; info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus RTU interface not available.")); return; } if (m_sdm72Connections.contains(thing)) m_sdm72Connections.take(thing)->deleteLater(); Sdm72ModbusRtuConnection *connection = new Sdm72ModbusRtuConnection( hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid), address, this); connect(connection, &Sdm72ModbusRtuConnection::reachableChanged, this, [=](bool reachable) { thing->setStateValue(connectedStateTypeId, reachable); }); if (classId == sdm72ThingClassId) { connect(connection, &Sdm72ModbusRtuConnection::voltagePhaseAChanged, this, [=](float v) { thing->setStateValue(sdm72VoltagePhaseAStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::voltagePhaseBChanged, this, [=](float v) { thing->setStateValue(sdm72VoltagePhaseBStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::voltagePhaseCChanged, this, [=](float v) { thing->setStateValue(sdm72VoltagePhaseCStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::currentPhaseAChanged, this, [=](float v) { thing->setStateValue(sdm72CurrentPhaseAStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::currentPhaseBChanged, this, [=](float v) { thing->setStateValue(sdm72CurrentPhaseBStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::currentPhaseCChanged, this, [=](float v) { thing->setStateValue(sdm72CurrentPhaseCStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::totalCurrentPowerChanged, this, [=](float v) { thing->setStateValue(sdm72CurrentPowerStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::powerPhaseAChanged, this, [=](float v) { thing->setStateValue(sdm72CurrentPowerPhaseAStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::powerPhaseBChanged, this, [=](float v) { thing->setStateValue(sdm72CurrentPowerPhaseBStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::powerPhaseCChanged, this, [=](float v) { thing->setStateValue(sdm72CurrentPowerPhaseCStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::frequencyChanged, this, [=](float v) { thing->setStateValue(sdm72FrequencyStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::totalEnergyConsumedChanged, this, [=](float v) { thing->setStateValue(sdm72TotalEnergyConsumedStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::totalEnergyProducedChanged, this, [=](float v) { thing->setStateValue(sdm72TotalEnergyProducedStateTypeId, v); }); } else if (classId == sdm72ConsumerThingClassId) { connect(connection, &Sdm72ModbusRtuConnection::totalCurrentPowerChanged, this, [=](float v) { thing->setStateValue(sdm72ConsumerCurrentPowerStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::totalEnergyConsumedChanged, this, [=](float v) { thing->setStateValue(sdm72ConsumerTotalEnergyConsumedStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::frequencyChanged, this, [=](float v) { thing->setStateValue(sdm72ConsumerFrequencyStateTypeId, v); }); } else { // sdm72Producer connect(connection, &Sdm72ModbusRtuConnection::totalCurrentPowerChanged, this, [=](float v) { thing->setStateValue(sdm72ProducerCurrentPowerStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::totalEnergyProducedChanged, this, [=](float v) { thing->setStateValue(sdm72ProducerTotalEnergyProducedStateTypeId, v); }); connect(connection, &Sdm72ModbusRtuConnection::frequencyChanged, this, [=](float v) { thing->setStateValue(sdm72ProducerFrequencyStateTypeId, v); }); } m_sdm72Connections.insert(thing, connection); info->finish(Thing::ThingErrorNoError); } void IntegrationPluginEastron::setupSdm120(ThingSetupInfo *info) { Thing *thing = info->thing(); ThingClassId classId = thing->thingClassId(); ParamTypeId slaveParamTypeId; ParamTypeId masterUuidParamTypeId; StateTypeId connectedStateTypeId; StateTypeId voltageStateTypeId; StateTypeId currentStateTypeId; StateTypeId powerStateTypeId; StateTypeId frequencyStateTypeId; StateTypeId totalEnergyConsumedStateTypeId; StateTypeId totalEnergyProducedStateTypeId; bool isEnergyMeter = false; if (classId == sdm120ThingClassId) { slaveParamTypeId = sdm120ThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm120ThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm120ConnectedStateTypeId; voltageStateTypeId = sdm120VoltagePhaseAStateTypeId; currentStateTypeId = sdm120CurrentPhaseAStateTypeId; powerStateTypeId = sdm120CurrentPowerStateTypeId; frequencyStateTypeId = sdm120FrequencyStateTypeId; totalEnergyConsumedStateTypeId = sdm120TotalEnergyConsumedStateTypeId; totalEnergyProducedStateTypeId = sdm120TotalEnergyProducedStateTypeId; isEnergyMeter = true; } else if (classId == sdm120ConsumerThingClassId) { slaveParamTypeId = sdm120ConsumerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm120ConsumerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm120ConsumerConnectedStateTypeId; powerStateTypeId = sdm120ConsumerCurrentPowerStateTypeId; frequencyStateTypeId = sdm120ConsumerFrequencyStateTypeId; totalEnergyConsumedStateTypeId = sdm120ConsumerTotalEnergyConsumedStateTypeId; } else if (classId == sdm120ProducerThingClassId) { slaveParamTypeId = sdm120ProducerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm120ProducerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm120ProducerConnectedStateTypeId; powerStateTypeId = sdm120ProducerCurrentPowerStateTypeId; frequencyStateTypeId = sdm120ProducerFrequencyStateTypeId; totalEnergyProducedStateTypeId = sdm120ProducerTotalEnergyProducedStateTypeId; } else if (classId == sdm220ThingClassId) { slaveParamTypeId = sdm220ThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm220ThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm220ConnectedStateTypeId; voltageStateTypeId = sdm220VoltagePhaseAStateTypeId; currentStateTypeId = sdm220CurrentPhaseAStateTypeId; powerStateTypeId = sdm220CurrentPowerStateTypeId; frequencyStateTypeId = sdm220FrequencyStateTypeId; totalEnergyConsumedStateTypeId = sdm220TotalEnergyConsumedStateTypeId; totalEnergyProducedStateTypeId = sdm220TotalEnergyProducedStateTypeId; isEnergyMeter = true; } else if (classId == sdm220ConsumerThingClassId) { slaveParamTypeId = sdm220ConsumerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm220ConsumerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm220ConsumerConnectedStateTypeId; powerStateTypeId = sdm220ConsumerCurrentPowerStateTypeId; frequencyStateTypeId = sdm220ConsumerFrequencyStateTypeId; totalEnergyConsumedStateTypeId = sdm220ConsumerTotalEnergyConsumedStateTypeId; } else if (classId == sdm220ProducerThingClassId) { slaveParamTypeId = sdm220ProducerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm220ProducerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm220ProducerConnectedStateTypeId; powerStateTypeId = sdm220ProducerCurrentPowerStateTypeId; frequencyStateTypeId = sdm220ProducerFrequencyStateTypeId; totalEnergyProducedStateTypeId = sdm220ProducerTotalEnergyProducedStateTypeId; } else if (classId == sdm230ThingClassId) { slaveParamTypeId = sdm230ThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm230ThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm230ConnectedStateTypeId; voltageStateTypeId = sdm230VoltagePhaseAStateTypeId; currentStateTypeId = sdm230CurrentPhaseAStateTypeId; powerStateTypeId = sdm230CurrentPowerStateTypeId; frequencyStateTypeId = sdm230FrequencyStateTypeId; totalEnergyConsumedStateTypeId = sdm230TotalEnergyConsumedStateTypeId; totalEnergyProducedStateTypeId = sdm230TotalEnergyProducedStateTypeId; isEnergyMeter = true; } else if (classId == sdm230ConsumerThingClassId) { slaveParamTypeId = sdm230ConsumerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm230ConsumerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm230ConsumerConnectedStateTypeId; powerStateTypeId = sdm230ConsumerCurrentPowerStateTypeId; frequencyStateTypeId = sdm230ConsumerFrequencyStateTypeId; totalEnergyConsumedStateTypeId = sdm230ConsumerTotalEnergyConsumedStateTypeId; } else { // sdm230Producer slaveParamTypeId = sdm230ProducerThingSlaveAddressParamTypeId; masterUuidParamTypeId = sdm230ProducerThingModbusMasterUuidParamTypeId; connectedStateTypeId = sdm230ProducerConnectedStateTypeId; powerStateTypeId = sdm230ProducerCurrentPowerStateTypeId; frequencyStateTypeId = sdm230ProducerFrequencyStateTypeId; totalEnergyProducedStateTypeId = sdm230ProducerTotalEnergyProducedStateTypeId; } uint address = thing->paramValue(slaveParamTypeId).toUInt(); if (address == 0 || address > 254) { qCWarning(dcEastron()) << "Setup failed, invalid slave address" << address; info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus address not valid. It must be a value between 1 and 254.")); return; } QUuid uuid = thing->paramValue(masterUuidParamTypeId).toUuid(); if (!hardwareManager()->modbusRtuResource()->hasModbusRtuMaster(uuid)) { qCWarning(dcEastron()) << "Setup failed, Modbus RTU master not available"; info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("The Modbus RTU interface not available.")); return; } if (m_sdm120Connections.contains(thing)) m_sdm120Connections.take(thing)->deleteLater(); Sdm120ModbusRtuConnection *connection = new Sdm120ModbusRtuConnection( hardwareManager()->modbusRtuResource()->getModbusRtuMaster(uuid), address, this); connect(connection, &Sdm120ModbusRtuConnection::reachableChanged, this, [=](bool reachable) { thing->setStateValue(connectedStateTypeId, reachable); }); connect(connection, &Sdm120ModbusRtuConnection::activePowerChanged, this, [=](float v) { thing->setStateValue(powerStateTypeId, v); }); connect(connection, &Sdm120ModbusRtuConnection::frequencyChanged, this, [=](float v) { thing->setStateValue(frequencyStateTypeId, v); }); if (isEnergyMeter) { connect(connection, &Sdm120ModbusRtuConnection::voltageChanged, this, [=](float v) { thing->setStateValue(voltageStateTypeId, v); }); connect(connection, &Sdm120ModbusRtuConnection::currentChanged, this, [=](float v) { thing->setStateValue(currentStateTypeId, v); }); connect(connection, &Sdm120ModbusRtuConnection::totalEnergyConsumedChanged, this, [=](float v) { thing->setStateValue(totalEnergyConsumedStateTypeId, v); }); connect(connection, &Sdm120ModbusRtuConnection::totalEnergyProducedChanged, this, [=](float v) { thing->setStateValue(totalEnergyProducedStateTypeId, v); }); } else { // Consumer or producer: connect only the relevant energy direction bool isProducer = (classId == sdm120ProducerThingClassId || classId == sdm220ProducerThingClassId || classId == sdm230ProducerThingClassId); if (isProducer) { connect(connection, &Sdm120ModbusRtuConnection::totalEnergyProducedChanged, this, [=](float v) { thing->setStateValue(totalEnergyProducedStateTypeId, v); }); } else { connect(connection, &Sdm120ModbusRtuConnection::totalEnergyConsumedChanged, this, [=](float v) { thing->setStateValue(totalEnergyConsumedStateTypeId, v); }); } } m_sdm120Connections.insert(thing, connection); info->finish(Thing::ThingErrorNoError); } void IntegrationPluginEastron::postSetupThing(Thing *thing) { qCDebug(dcEastron()) << "Post setup thing" << thing->name(); if (!m_refreshTimer) { m_refreshTimer = hardwareManager()->pluginTimerManager()->registerTimer(2); connect(m_refreshTimer, &PluginTimer::timeout, this, [this] { foreach (Thing *thing, myThings()) { if (m_sdm630Connections.contains(thing)) m_sdm630Connections.value(thing)->update(); else if (m_sdm72Connections.contains(thing)) m_sdm72Connections.value(thing)->update(); else if (m_sdm120Connections.contains(thing)) m_sdm120Connections.value(thing)->update(); } }); qCDebug(dcEastron()) << "Refresh timer started"; m_refreshTimer->start(); } } void IntegrationPluginEastron::thingRemoved(Thing *thing) { qCDebug(dcEastron()) << "Thing removed" << thing->name(); if (m_sdm630Connections.contains(thing)) m_sdm630Connections.take(thing)->deleteLater(); else if (m_sdm72Connections.contains(thing)) m_sdm72Connections.take(thing)->deleteLater(); else if (m_sdm120Connections.contains(thing)) m_sdm120Connections.take(thing)->deleteLater(); if (myThings().isEmpty() && m_refreshTimer) { hardwareManager()->pluginTimerManager()->unregisterTimer(m_refreshTimer); m_refreshTimer = nullptr; qCDebug(dcEastron()) << "Refresh timer stopped"; } }