From acb5dbe9a267ee57c39ceba20c1652a14caf698d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Mon, 7 Jun 2021 15:57:42 +0200 Subject: [PATCH] Update iDM plugin and add network discovery --- idm/idm.cpp | 20 +++++------- idm/idm.h | 2 +- idm/integrationpluginidm.cpp | 58 ++++++++++++++++++++++++++++------- idm/integrationpluginidm.h | 2 +- idm/integrationpluginidm.json | 15 +++++++-- 5 files changed, 69 insertions(+), 28 deletions(-) diff --git a/idm/idm.cpp b/idm/idm.cpp index 6890cae..dc96863 100644 --- a/idm/idm.cpp +++ b/idm/idm.cpp @@ -40,14 +40,10 @@ Idm::Idm(const QHostAddress &address, QObject *parent) : { qCDebug(dcIdm()) << "iDM: Creating iDM connection" << m_hostAddress.toString(); m_modbusMaster = new ModbusTCPMaster(address, 502, this); - - if (m_modbusMaster) { - qCDebug(dcIdm()) << "iDM: Created ModbusTCPMaster"; - connect(m_modbusMaster, &ModbusTCPMaster::receivedHoldingRegister, this, &Idm::onReceivedHoldingRegister); - connect(m_modbusMaster, &ModbusTCPMaster::readRequestError, this, &Idm::onModbusError); - connect(m_modbusMaster, &ModbusTCPMaster::writeRequestError, this, &Idm::onModbusError); - connect(m_modbusMaster, &ModbusTCPMaster::writeRequestExecuted, this, &Idm::writeRequestExecuted); - } + connect(m_modbusMaster, &ModbusTCPMaster::receivedHoldingRegister, this, &Idm::onReceivedHoldingRegister); + connect(m_modbusMaster, &ModbusTCPMaster::readRequestError, this, &Idm::onModbusError); + connect(m_modbusMaster, &ModbusTCPMaster::writeRequestError, this, &Idm::onModbusError); + connect(m_modbusMaster, &ModbusTCPMaster::writeRequestExecuted, this, &Idm::writeRequestExecuted); } Idm::~Idm() @@ -61,21 +57,21 @@ bool Idm::connectDevice() return m_modbusMaster->connectDevice(); } -QHostAddress Idm::getIdmAddress() const +QHostAddress Idm::address() const { return m_hostAddress; } void Idm::getStatus() { - //this request starts an update cycle + // This request starts an update cycle m_modbusMaster->readHoldingRegister(Idm::modbusUnitID, Idm::OutsideTemperature, 2); } QUuid Idm::setTargetTemperature(double targetTemperature) { - QVector value = ModbusHelpers::convertFloatToRegister(targetTemperature); - return m_modbusMaster->writeHoldingRegisters(Idm::modbusUnitID, Idm::RegisterList::RoomTemperatureTargetHeatingEcoHKA, value); + QVector value = ModbusHelpers::convertFloatToRegister(targetTemperature); + return m_modbusMaster->writeHoldingRegisters(Idm::modbusUnitID, Idm::RegisterList::RoomTemperatureTargetHeatingEcoHKA, value); } void Idm::onReceivedHoldingRegister(int slaveAddress, int modbusRegister, const QVector &value) diff --git a/idm/idm.h b/idm/idm.h index 7a70efc..53f1d02 100644 --- a/idm/idm.h +++ b/idm/idm.h @@ -72,7 +72,7 @@ public: ~Idm(); bool connectDevice(); - QHostAddress getIdmAddress() const; + QHostAddress address() const; QUuid setTargetTemperature(double targetTemperature); void getStatus(); diff --git a/idm/integrationpluginidm.cpp b/idm/integrationpluginidm.cpp index 3fac78d..e8be7c9 100644 --- a/idm/integrationpluginidm.cpp +++ b/idm/integrationpluginidm.cpp @@ -28,6 +28,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#include "network/networkdevicediscovery.h" #include "integrationpluginidm.h" #include "plugininfo.h" @@ -36,6 +37,48 @@ IntegrationPluginIdm::IntegrationPluginIdm() } +void IntegrationPluginIdm::discoverThings(ThingDiscoveryInfo *info) +{ + qCDebug(dcIdm()) << "Discovering network..."; + NetworkDeviceDiscoveryReply *discoveryReply = hardwareManager()->networkDeviceDiscovery()->discover(); + connect(discoveryReply, &NetworkDeviceDiscoveryReply::finished, this, [=](){ + ThingDescriptors descriptors; + qCDebug(dcIdm()) << "Discovery finished. Found" << discoveryReply->networkDevices().count() << "devices"; + foreach (const NetworkDevice &networkDevice, discoveryReply->networkDevices()) { + qCDebug(dcIdm()) << networkDevice; + QString title; + if (networkDevice.hostName().isEmpty()) { + title += networkDevice.address().toString(); + } else { + title += networkDevice.address().toString() + " (" + networkDevice.hostName() + ")"; + } + + QString description; + if (networkDevice.macAddressManufacturer().isEmpty()) { + description = networkDevice.macAddress(); + } else { + description = networkDevice.macAddress() + " (" + networkDevice.macAddressManufacturer() + ")"; + } + + ThingDescriptor descriptor(navigator2ThingClassId, title, description); + + // Check if we already have set up this device + Things existingThings = myThings().filterByParam(navigator2ThingMacAddressParamTypeId, networkDevice.macAddress()); + if (existingThings.count() == 1) { + qCDebug(dcIdm()) << "This thing already exists in the system." << existingThings.first() << networkDevice; + descriptor.setThingId(existingThings.first()->id()); + } + + ParamList params; + params << Param(navigator2ThingMacAddressParamTypeId, networkDevice.macAddress()); + params << Param(navigator2ThingIpAddressParamTypeId, networkDevice.address().toString()); + descriptor.setParams(params); + info->addThingDescriptor(descriptor); + } + info->finish(Thing::ThingErrorNoError); + }); +} + void IntegrationPluginIdm::setupThing(ThingSetupInfo *info) { Thing *thing = info->thing(); @@ -57,8 +100,8 @@ void IntegrationPluginIdm::setupThing(ThingSetupInfo *info) qCDebug(dcIdm()) << "User entered address: " << hostAddress.toString(); /* Check, if address is already in use for another device */ - Q_FOREACH (Idm *idm, m_idmConnections) { - if (hostAddress.isEqual(idm->getIdmAddress())) { + foreach (Idm *idm, m_idmConnections) { + if (hostAddress.isEqual(idm->address())) { qCWarning(dcIdm()) << "Address already in use"; info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("IP address already in use")); return; @@ -144,8 +187,7 @@ void IntegrationPluginIdm::executeAction(ThingActionInfo *info) double targetTemperature = thing->stateValue(navigator2TargetTemperatureStateTypeId).toDouble(); QUuid requestId = idm->setTargetTemperature(targetTemperature); m_asyncActions.insert(requestId, info); - connect(info, &ThingActionInfo::aborted, [requestId, this] {m_asyncActions.remove(requestId);}); - + connect(info, &ThingActionInfo::aborted, [requestId, this] (){ m_asyncActions.remove(requestId); }); } else { Q_ASSERT_X(false, "executeAction", QString("Unhandled action: %1").arg(action.actionTypeId().toString()).toUtf8()); } @@ -158,11 +200,8 @@ void IntegrationPluginIdm::update(Thing *thing) { if (thing->thingClassId() == navigator2ThingClassId) { qCDebug(dcIdm()) << "Updating thing" << thing->name(); - Idm *idm = m_idmConnections.value(thing); - if (!idm) { - return; - } + if (!idm) { return; }; idm->getStatus(); } } @@ -170,7 +209,6 @@ void IntegrationPluginIdm::update(Thing *thing) void IntegrationPluginIdm::onStatusUpdated(const IdmInfo &info) { qCDebug(dcIdm()) << "Received status from heat pump"; - Idm *idm = qobject_cast(sender()); Thing *thing = m_idmConnections.key(idm); @@ -205,8 +243,6 @@ void IntegrationPluginIdm::onWriteRequestExecuted(const QUuid &requestId, bool s void IntegrationPluginIdm::onRefreshTimer() { - qCDebug(dcIdm()) << "onRefreshTimer called"; - foreach (Thing *thing, myThings().filterByThingClassId(navigator2ThingClassId)) { update(thing); } diff --git a/idm/integrationpluginidm.h b/idm/integrationpluginidm.h index 808edb8..058988e 100644 --- a/idm/integrationpluginidm.h +++ b/idm/integrationpluginidm.h @@ -33,7 +33,6 @@ #include "integrations/integrationplugin.h" #include "plugintimer.h" - #include "idm.h" #include @@ -48,6 +47,7 @@ class IntegrationPluginIdm: public IntegrationPlugin public: explicit IntegrationPluginIdm(); + void discoverThings(ThingDiscoveryInfo *info) override; void setupThing(ThingSetupInfo *info) override; void postSetupThing(Thing *thing) override; void thingRemoved(Thing *thing) override; diff --git a/idm/integrationpluginidm.json b/idm/integrationpluginidm.json index e66b23e..a17f4d4 100644 --- a/idm/integrationpluginidm.json +++ b/idm/integrationpluginidm.json @@ -1,5 +1,5 @@ { - "name": "Idm", + "name": "idm", "displayName": "iDM", "id": "3968d86d-d51a-4ad1-a185-91faa017e38f", "vendors": [ @@ -12,14 +12,23 @@ "name": "navigator2", "displayName": "Navigator 2.0", "id": "1c95ac91-4eca-4cbf-b0f4-d60d35d069ed", - "createMethods": ["user"], + "createMethods": ["user", "discovery"], "interfaces": ["thermostat", "connectable"], "paramTypes": [ { "id": "05714e5c-d66a-4095-bbff-a0eb96fb035b", "name":"ipAddress", "displayName": "IP address", - "type": "QString" + "inputType": "IPv4Address", + "type": "QString", + "defaultValue": "0.0.0.0" + }, + { + "id": "d178ca29-41a1-4f56-82ec-76a833c1de50", + "name": "macAddress", + "displayName": "MAC address", + "type": "QString", + "defaultValue": "" } ], "stateTypes":[