From 14f0519547e08383fed18fa36cf135bdd0259cef Mon Sep 17 00:00:00 2001 From: "bernhard.trinnes" Date: Tue, 9 Jun 2020 10:35:00 +0200 Subject: [PATCH 1/5] added mDNS discovery --- philipshue/integrationpluginphilipshue.cpp | 57 +++++++++++++++++++++- philipshue/integrationpluginphilipshue.h | 9 ++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/philipshue/integrationpluginphilipshue.cpp b/philipshue/integrationpluginphilipshue.cpp index 1b2fe8ab..3b2d2064 100644 --- a/philipshue/integrationpluginphilipshue.cpp +++ b/philipshue/integrationpluginphilipshue.cpp @@ -36,6 +36,9 @@ #include "network/upnp/upnpdiscovery.h" #include "network/upnp/upnpdiscoveryreply.h" +#include "platform/platformzeroconfcontroller.h" +#include "network/zeroconf/zeroconfservicebrowser.h" + #include #include #include @@ -78,11 +81,29 @@ void IntegrationPluginPhilipsHue::init() } }); + m_zeroConfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_hue._tcp._local"); + connect(m_zeroConfBrowser, &ZeroConfServiceBrowser::serviceEntryAdded, this, [=](const ZeroConfServiceEntry &entry){ + foreach (Thing *thing, myThings().filterByThingClassId(bridgeThingClassId)) { + QString thingId = thing->paramValue(bridgeThingIdParamTypeId).toString(); + if (entry.protocol() == QAbstractSocket::IPv4Protocol) { + + foreach (const QString &txtEntry, entry.txt()) { + QStringList parts = txtEntry.split('='); + if (parts.length() == 2 && parts.first() == "uuid" && parts.last() == thingId) { + thing->setParamValue(bridgeThingHostParamTypeId, entry.hostAddress().toString()); + HueBridge *bridge = m_bridges.key(thing); + bridge->setHostAddress(entry.hostAddress()); + //TODO also add upnp to update the address + } + } + } + } + }); } void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) { - // We're starting a UpnpDiscovery and a NUpnpDiscovery. + // We're starting a mDNS-, Upnp- and a NUpnpDiscovery. // For that, we create a tracking object holding pointers to both of those discoveries. // Both discoveries add their results to a temporary list. // Once a discovery is finished, it will remove itself from the tracking object. @@ -98,6 +119,38 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) delete m_discoveries.take(info); }); + foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) { + + /* + * Philips Hue - xxxxxx._hue._tcp._local + * protocol: tcp + * service: hue + * name: Philips Hue - xxxxxx where xxxxxx are the last 6 digits of the bridge ID. + */ + if (!entry.serviceType().contains("_hue._tcp._local")) { + continue; + } + qCDebug(dcPhilipsHue()) << "Zeroconf entry:" << entry; + + QString name = entry.name().split(" - ").first(); + QString id = entry.name().split(" - ").last(); + QHostAddress address = entry.hostAddress(); + + ParamList params; + params.append(Param(bridgeThingHostParamTypeId, address.toString())); + params.append(Param(bridgeThingIdParamTypeId, id)); + + ThingDescriptor descriptor(bridgeThingClassId, "Philips Hue Bridge", address.toString()); + descriptor.setParams(params); + + foreach (Thing *thing, myThings()) { + if (thing->paramValue(bridgeThingIdParamTypeId).toString() == id) { + descriptor.setThingId(thing->id()); + break; + } + } + discovery->results.append(descriptor); + } qCDebug(dcPhilipsHue()) << "Starting UPnP discovery..."; UpnpDiscoveryReply *upnpReply = hardwareManager()->upnpDiscovery()->discoverDevices("libhue:idl"); @@ -139,7 +192,7 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) qCDebug(dcPhilipsHue) << "Starting N-UPNP discovery..."; - QNetworkRequest request(QUrl("https://www.meethue.com/api/nupnp")); + QNetworkRequest request(QUrl(" https://discovery.meethue.com ")); QNetworkReply *nUpnpReply = hardwareManager()->networkManager()->get(request); discovery->nUpnpReply = nUpnpReply; diff --git a/philipshue/integrationpluginphilipshue.h b/philipshue/integrationpluginphilipshue.h index bbece57d..465863f3 100644 --- a/philipshue/integrationpluginphilipshue.h +++ b/philipshue/integrationpluginphilipshue.h @@ -41,6 +41,9 @@ #include "plugintimer.h" #include "network/networkaccessmanager.h" #include "network/upnp/upnpdiscovery.h" +#include "network/zeroconf/zeroconfservicebrowser.h" +#include "network/zeroconf/zeroconfserviceentry.h" + class QNetworkReply; @@ -90,6 +93,7 @@ private: QNetworkReply* nUpnpReply; ThingDescriptors results; }; + ZeroConfServiceBrowser *m_zeroConfBrowser = nullptr; QHash m_discoveries; void finishDiscovery(DiscoveryJob* job); @@ -108,8 +112,6 @@ private: QHash m_bridgeSensorsDiscoveryRequests; QHash m_bridgeSearchDevicesRequests; - QHash > m_asyncActions; - QHash m_bridges; QHash m_lights; QHash m_remotes; @@ -135,7 +137,6 @@ private: void processLightsRefreshResponse(Thing *thing, const QByteArray &data); void processSensorsRefreshResponse(Thing *thing, const QByteArray &data); void processSetNameResponse(Thing *thing, const QByteArray &data); - void processActionResponse(Thing *thing, const ActionId actionId, const QByteArray &data); void bridgeReachableChanged(Thing *thing, const bool &reachable); @@ -149,4 +150,4 @@ private: void abortRequests(QHash requestList, Thing* thing); }; -#endif // INTEGRATIONPLUGINBOBLIGHT_H +#endif // INTEGRATIONPLUGINPHILIPSHUE_H From 1071bcb34bc6216f639ace4437fa7796425a9756 Mon Sep 17 00:00:00 2001 From: "bernhard.trinnes" Date: Tue, 9 Jun 2020 10:42:38 +0200 Subject: [PATCH 2/5] fixed n-upnp discovery --- philipshue/integrationpluginphilipshue.cpp | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/philipshue/integrationpluginphilipshue.cpp b/philipshue/integrationpluginphilipshue.cpp index 3b2d2064..0e4fe3ed 100644 --- a/philipshue/integrationpluginphilipshue.cpp +++ b/philipshue/integrationpluginphilipshue.cpp @@ -87,14 +87,14 @@ void IntegrationPluginPhilipsHue::init() QString thingId = thing->paramValue(bridgeThingIdParamTypeId).toString(); if (entry.protocol() == QAbstractSocket::IPv4Protocol) { - foreach (const QString &txtEntry, entry.txt()) { - QStringList parts = txtEntry.split('='); - if (parts.length() == 2 && parts.first() == "uuid" && parts.last() == thingId) { - thing->setParamValue(bridgeThingHostParamTypeId, entry.hostAddress().toString()); - HueBridge *bridge = m_bridges.key(thing); - bridge->setHostAddress(entry.hostAddress()); - //TODO also add upnp to update the address - } + QString name = entry.name().split(" - ").first(); + QString id = entry.name().split(" - ").last(); + + if (thingId.contains(id)) { + thing->setParamValue(bridgeThingHostParamTypeId, entry.hostAddress().toString()); + HueBridge *bridge = m_bridges.key(thing); + bridge->setHostAddress(entry.hostAddress()); + //TODO also add upnp to update the address } } } @@ -192,7 +192,7 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) qCDebug(dcPhilipsHue) << "Starting N-UPNP discovery..."; - QNetworkRequest request(QUrl(" https://discovery.meethue.com ")); + QNetworkRequest request(QUrl("https://discovery.meethue.com")); QNetworkReply *nUpnpReply = hardwareManager()->networkManager()->get(request); discovery->nUpnpReply = nUpnpReply; @@ -1424,9 +1424,9 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th QString uuid = sensorMap.value("uniqueid").toString(); QString model = sensorMap.value("modelid").toString(); -// qCDebug(dcPhilipsHue()) << "Found sensor on bridge:" << model << uuid; + // qCDebug(dcPhilipsHue()) << "Found sensor on bridge:" << model << uuid; foreach (HueRemote* remote, remotesToRemove) { -// qCDebug(dcPhilipsHue()) << " - Checking remote to remove" << remote->modelId() << remote->uuid(); + // qCDebug(dcPhilipsHue()) << " - Checking remote to remove" << remote->modelId() << remote->uuid(); if (remote->uuid() == uuid) { remotesToRemove.removeAll(remote); break; @@ -1454,7 +1454,7 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th emit autoThingsAppeared({descriptor}); qCDebug(dcPhilipsHue) << "Found new remote" << sensorMap.value("name").toString() << model; - // Smart Button + // Smart Button } else if (model == "ROM001") { ThingDescriptor descriptor(smartButtonThingClassId, sensorMap.value("name").toString(), "Philips Hue Smart Button", thing->id()); ParamList params; @@ -1466,7 +1466,7 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th emit autoThingsAppeared({descriptor}); qCDebug(dcPhilipsHue) << "Found new smart button" << sensorMap.value("name").toString() << model; - // Hue Tap + // Hue Tap } else if (sensorMap.value("type").toString() == "ZGPSwitch") { ThingDescriptor descriptor(tapThingClassId, sensorMap.value("name").toString(), "Philips Hue Tap", thing->id()); ParamList params; From 5760025af31f375af983d6d262ee7f90db78e45e Mon Sep 17 00:00:00 2001 From: "bernhard.trinnes" Date: Tue, 9 Jun 2020 11:14:33 +0200 Subject: [PATCH 3/5] fixed mDNS discovery bridgeId --- philipshue/integrationpluginphilipshue.cpp | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/philipshue/integrationpluginphilipshue.cpp b/philipshue/integrationpluginphilipshue.cpp index 0e4fe3ed..bd1f785c 100644 --- a/philipshue/integrationpluginphilipshue.cpp +++ b/philipshue/integrationpluginphilipshue.cpp @@ -87,14 +87,13 @@ void IntegrationPluginPhilipsHue::init() QString thingId = thing->paramValue(bridgeThingIdParamTypeId).toString(); if (entry.protocol() == QAbstractSocket::IPv4Protocol) { - QString name = entry.name().split(" - ").first(); - QString id = entry.name().split(" - ").last(); - - if (thingId.contains(id)) { - thing->setParamValue(bridgeThingHostParamTypeId, entry.hostAddress().toString()); - HueBridge *bridge = m_bridges.key(thing); - bridge->setHostAddress(entry.hostAddress()); - //TODO also add upnp to update the address + foreach (const QString &txtEntry, entry.txt()) { + QStringList parts = txtEntry.split('='); + if (parts.length() == 2 && parts.first() == "bridgeid" && parts.last().toLower() == thingId) { + thing->setParamValue(bridgeThingHostParamTypeId, entry.hostAddress().toString()); + HueBridge *bridge = m_bridges.key(thing); + bridge->setHostAddress(entry.hostAddress()); + } } } } @@ -127,13 +126,20 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) * service: hue * name: Philips Hue - xxxxxx where xxxxxx are the last 6 digits of the bridge ID. */ - if (!entry.serviceType().contains("_hue._tcp._local")) { + if (!entry.serviceType().contains("_hue._tcp._local") || entry.protocol() != QAbstractSocket::IPv4Protocol) { continue; } qCDebug(dcPhilipsHue()) << "Zeroconf entry:" << entry; - QString name = entry.name().split(" - ").first(); - QString id = entry.name().split(" - ").last(); + QString id; + foreach (const QString &txt, entry.txt()) { + QString field = txt.split("=").first(); + QString value = txt.split("=").last(); + if (field == "bridgeid") { + id = value; + break; + } + } QHostAddress address = entry.hostAddress(); ParamList params; From 3e8451dd5611f2cd0ba2c178da52967b8986adc9 Mon Sep 17 00:00:00 2001 From: "bernhard.trinnes" Date: Tue, 9 Jun 2020 11:16:46 +0200 Subject: [PATCH 4/5] fixed mDNS discovery bridgeId --- philipshue/integrationpluginphilipshue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/philipshue/integrationpluginphilipshue.cpp b/philipshue/integrationpluginphilipshue.cpp index bd1f785c..39ed5b82 100644 --- a/philipshue/integrationpluginphilipshue.cpp +++ b/philipshue/integrationpluginphilipshue.cpp @@ -136,7 +136,7 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) QString field = txt.split("=").first(); QString value = txt.split("=").last(); if (field == "bridgeid") { - id = value; + id = value.toLower(); break; } } From 7adc6ee0807d39f88a11c2b0bc7c636bb7ff8c77 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 9 Jun 2020 14:22:51 +0200 Subject: [PATCH 5/5] fix zeroconf discovery --- philipshue/integrationpluginphilipshue.cpp | 26 ++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/philipshue/integrationpluginphilipshue.cpp b/philipshue/integrationpluginphilipshue.cpp index 39ed5b82..84082b6d 100644 --- a/philipshue/integrationpluginphilipshue.cpp +++ b/philipshue/integrationpluginphilipshue.cpp @@ -81,7 +81,7 @@ void IntegrationPluginPhilipsHue::init() } }); - m_zeroConfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_hue._tcp._local"); + m_zeroConfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_hue._tcp"); connect(m_zeroConfBrowser, &ZeroConfServiceBrowser::serviceEntryAdded, this, [=](const ZeroConfServiceEntry &entry){ foreach (Thing *thing, myThings().filterByThingClassId(bridgeThingClassId)) { QString thingId = thing->paramValue(bridgeThingIdParamTypeId).toString(); @@ -126,10 +126,9 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) * service: hue * name: Philips Hue - xxxxxx where xxxxxx are the last 6 digits of the bridge ID. */ - if (!entry.serviceType().contains("_hue._tcp._local") || entry.protocol() != QAbstractSocket::IPv4Protocol) { + if (!entry.serviceType().contains("_hue._tcp") || entry.protocol() != QAbstractSocket::IPv4Protocol) { continue; } - qCDebug(dcPhilipsHue()) << "Zeroconf entry:" << entry; QString id; foreach (const QString &txt, entry.txt()) { @@ -140,6 +139,12 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) break; } } + + // For some reason the UPnP api returns serial numbers withouot a "fffe" in the middle. For backwards compatiblity adjust to that + if (id.indexOf("fffe") == 6) { + id.remove(6, 4); + } + QHostAddress address = entry.hostAddress(); ParamList params; @@ -155,6 +160,7 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) break; } } + qCDebug(dcPhilipsHue()) << "mDNS: Found Hue bridge:" << id << address.toString(); discovery->results.append(descriptor); } @@ -179,6 +185,8 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) ThingDescriptor descriptor(bridgeThingClassId, "Philips Hue Bridge", upnpDevice.hostAddress().toString()); ParamList params; QString bridgeId = upnpDevice.serialNumber().toLower(); + + // We need to add it, check if this bridge is already set up foreach (Thing *existingThing, myThings()) { if (existingThing->paramValue(bridgeThingIdParamTypeId).toString() == bridgeId) { descriptor.setThingId(existingThing->id()); @@ -188,7 +196,7 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) params.append(Param(bridgeThingHostParamTypeId, upnpDevice.hostAddress().toString())); params.append(Param(bridgeThingIdParamTypeId, bridgeId)); descriptor.setParams(params); - qCDebug(dcPhilipsHue()) << "UPnP: Found Hue bridge:" << bridgeId; + qCDebug(dcPhilipsHue()) << "UPnP: Found Hue bridge:" << bridgeId << upnpDevice.hostAddress().toString(); discovery->results.append(descriptor); } } @@ -224,18 +232,22 @@ void IntegrationPluginPhilipsHue::discoverThings(ThingDiscoveryInfo *info) } foreach (const QVariant &bridgeVariant, jsonDoc.toVariant().toList()) { + + QVariantMap bridgeMap = bridgeVariant.toMap(); ThingDescriptor descriptor(bridgeThingClassId, "Philips Hue Bridge", bridgeMap.value("internalipaddress").toString()); ParamList params; QString bridgeId = bridgeMap.value("id").toString().toLower(); - // For some reason the N-UPnP api returns serial numbers with a "fffe" in the middle... + QString address = bridgeMap.value("internalipaddress").toString(); + + // For some reason the UPnP api returns serial numbers withouot a "fffe" in the middle. For backwards compatiblity adjust to that if (bridgeId.indexOf("fffe") == 6) { bridgeId.remove(6, 4); } - params.append(Param(bridgeThingHostParamTypeId, bridgeMap.value("internalipaddress").toString())); + params.append(Param(bridgeThingHostParamTypeId, address)); params.append(Param(bridgeThingIdParamTypeId, bridgeId)); descriptor.setParams(params); - qCDebug(dcPhilipsHue()) << "N-UPnP: Found Hue bridge:" << bridgeId; + qCDebug(dcPhilipsHue()) << "N-UPnP: Found Hue bridge:" << bridgeId << address; discovery->results.append(descriptor); }