Also make actions work. add a cache so we don't always start

with the wrong ip
master
Michael Zanetti 2020-09-02 17:30:35 +02:00
parent 1c09440ca9
commit 84a4a7c3a4
11 changed files with 101 additions and 113 deletions

View File

@ -29,6 +29,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "huebridge.h"
#include <QJsonDocument>
HueBridge::HueBridge(QObject *parent) :
QObject(parent),
@ -117,16 +118,6 @@ void HueBridge::setZigbeeChannel(const int &zigbeeChannel)
m_zigbeeChannel = zigbeeChannel;
}
QList<HueLight *> HueBridge::lights() const
{
return m_lights;
}
void HueBridge::addLight(HueLight *light)
{
m_lights.append(light);
}
QPair<QNetworkRequest, QByteArray> HueBridge::createDiscoverLightsRequest()
{
QNetworkRequest request(QUrl("http://" + hostAddress().toString() + "/api/" + apiKey() + "/lights/"));

View File

@ -33,14 +33,13 @@
#include <QObject>
#include <QHostAddress>
#include "huelight.h"
#include <QNetworkRequest>
class HueBridge : public QObject
{
Q_OBJECT
public:
explicit HueBridge(QObject *parent = 0);
explicit HueBridge(QObject *parent = nullptr);
QString name() const;
void setName(const QString &name);
@ -66,9 +65,6 @@ public:
int zigbeeChannel() const;
void setZigbeeChannel(const int &zigbeeChannel);
QList<HueLight *> lights() const;
void addLight(HueLight *light);
QPair<QNetworkRequest, QByteArray> createDiscoverLightsRequest();
QPair<QNetworkRequest, QByteArray> createSearchLightsRequest(const QString &deviceId);
QPair<QNetworkRequest, QByteArray> createSearchSensorsRequest();
@ -84,9 +80,6 @@ private:
QString m_apiVersion;
QString m_softwareVersion;
int m_zigbeeChannel;
QList<HueLight *> m_lights;
};
#endif // HUEBRIDGE_H

View File

@ -30,8 +30,9 @@
#include "huedevice.h"
HueDevice::HueDevice(QObject *parent) :
QObject(parent)
HueDevice::HueDevice(HueBridge *bridge, QObject *parent) :
QObject(parent),
m_bridge(bridge)
{
}
@ -46,6 +47,16 @@ void HueDevice::setId(const int &id)
m_id = id;
}
QHostAddress HueDevice::hostAddress() const
{
return m_bridge->hostAddress();
}
QString HueDevice::apiKey() const
{
return m_bridge->apiKey();
}
QString HueDevice::name() const
{
return m_name;
@ -56,16 +67,6 @@ void HueDevice::setName(const QString &name)
m_name = name;
}
QHostAddress HueDevice::hostAddress() const
{
return m_hostAddress;
}
void HueDevice::setHostAddress(const QHostAddress hostAddress)
{
m_hostAddress = hostAddress;
}
QString HueDevice::uuid()
{
return m_uuid;
@ -76,16 +77,6 @@ void HueDevice::setUuid(const QString &uuid)
m_uuid = uuid;
}
QString HueDevice::apiKey() const
{
return m_apiKey;
}
void HueDevice::setApiKey(const QString &apiKey)
{
m_apiKey = apiKey;
}
QString HueDevice::modelId() const
{
return m_modelId;

View File

@ -37,27 +37,27 @@
#include <QNetworkRequest>
#include <QJsonDocument>
#include "huebridge.h"
class HueDevice : public QObject
{
Q_OBJECT
public:
explicit HueDevice(QObject *parent = nullptr);
explicit HueDevice(HueBridge *bridge, QObject *parent = nullptr);
int id() const;
void setId(const int &id);
QHostAddress hostAddress() const;
QString apiKey() const;
QString name() const;
void setName(const QString &name);
QHostAddress hostAddress() const;
void setHostAddress(const QHostAddress hostAddress);
QString uuid();
void setUuid(const QString &uuid);
QString apiKey() const;
void setApiKey(const QString &apiKey);
QString modelId() const;
void setModelId(const QString &modelId);
@ -73,10 +73,9 @@ public:
static QString getBaseUuid(const QString &uuid);
private:
HueBridge *m_bridge = nullptr;
int m_id;
QString m_name;
QHostAddress m_hostAddress;
QString m_apiKey;
QString m_modelId;
QString m_uuid;
QString m_type;

View File

@ -31,8 +31,8 @@
#include "huelight.h"
#include "extern-plugininfo.h"
HueLight::HueLight(QObject *parent) :
HueDevice(parent)
HueLight::HueLight(HueBridge *bridge, QObject *parent) :
HueDevice(bridge, parent)
{
}
@ -215,9 +215,9 @@ void HueLight::processActionResponse(const QVariantList &responseList)
emit stateChanged();
}
QPair<QNetworkRequest, QByteArray> HueLight::createSetPowerRequest(const bool &power)
QPair<QNetworkRequest, QByteArray> HueLight::createSetPowerRequest(bool power)
{
qCDebug(dcPhilipsHue()) << "Create power request" << power;
qCDebug(dcPhilipsHue()) << "Creating power request for power" << (power ? "on" : "off");
QVariantMap requestMap;
requestMap.insert("on", power);
@ -232,7 +232,7 @@ QPair<QNetworkRequest, QByteArray> HueLight::createSetPowerRequest(const bool &p
QPair<QNetworkRequest, QByteArray> HueLight::createSetColorRequest(const QColor &color)
{
qCDebug(dcPhilipsHue()) << "Create color request" << color.toRgb();
qCDebug(dcPhilipsHue()) << "Creating color request" << color.toRgb();
QVariantMap requestMap;
requestMap.insert("hue", color.hue() * 65535 / 360);
@ -247,9 +247,9 @@ QPair<QNetworkRequest, QByteArray> HueLight::createSetColorRequest(const QColor
return QPair<QNetworkRequest, QByteArray>(request, jsonDoc.toJson());
}
QPair<QNetworkRequest, QByteArray> HueLight::createSetBrightnessRequest(const int &brightness)
QPair<QNetworkRequest, QByteArray> HueLight::createSetBrightnessRequest(int brightness)
{
qCDebug(dcPhilipsHue()) << "Create brightness request" << brightness;
qCDebug(dcPhilipsHue()) << "Creating brightness request" << brightness;
QVariantMap requestMap;
requestMap.insert("bri", brightness);
@ -269,7 +269,7 @@ QPair<QNetworkRequest, QByteArray> HueLight::createSetBrightnessRequest(const in
QPair<QNetworkRequest, QByteArray> HueLight::createSetEffectRequest(const QString &effect)
{
qCDebug(dcPhilipsHue()) << "Create effect request" << effect;
qCDebug(dcPhilipsHue()) << "Creating effect request" << effect;
QVariantMap requestMap;
if (effect == "none") {
@ -286,9 +286,9 @@ QPair<QNetworkRequest, QByteArray> HueLight::createSetEffectRequest(const QStrin
return QPair<QNetworkRequest, QByteArray>(request, jsonDoc.toJson());
}
QPair<QNetworkRequest, QByteArray> HueLight::createSetTemperatureRequest(const int &colorTemp)
QPair<QNetworkRequest, QByteArray> HueLight::createSetTemperatureRequest(int colorTemp)
{
qCDebug(dcPhilipsHue()) << "Create color temperature request" << colorTemp;
qCDebug(dcPhilipsHue()) << "Creating color temperature request" << colorTemp;
QVariantMap requestMap;
requestMap.insert("ct", colorTemp);
@ -304,7 +304,7 @@ QPair<QNetworkRequest, QByteArray> HueLight::createSetTemperatureRequest(const i
QPair<QNetworkRequest, QByteArray> HueLight::createFlashRequest(const QString &alert)
{
qCDebug(dcPhilipsHue()) << "Create flash request" << alert;
qCDebug(dcPhilipsHue()) << "Creating flash request" << alert;
QVariantMap requestMap;
if (alert == "flash") {

View File

@ -53,7 +53,7 @@ public:
ColorModeCT
};
explicit HueLight(QObject *parent = 0);
explicit HueLight(HueBridge* bridge, QObject *parent = nullptr);
bool power() const;
void setPower(const bool &power);
@ -89,11 +89,11 @@ public:
void processActionResponse(const QVariantList &responseList);
// create action requests
QPair<QNetworkRequest, QByteArray> createSetPowerRequest(const bool &power);
QPair<QNetworkRequest, QByteArray> createSetPowerRequest(bool power);
QPair<QNetworkRequest, QByteArray> createSetColorRequest(const QColor &color);
QPair<QNetworkRequest, QByteArray> createSetBrightnessRequest(const int &brightness);
QPair<QNetworkRequest, QByteArray> createSetBrightnessRequest(int brightness);
QPair<QNetworkRequest, QByteArray> createSetEffectRequest(const QString &effect);
QPair<QNetworkRequest, QByteArray> createSetTemperatureRequest(const int &colorTemp);
QPair<QNetworkRequest, QByteArray> createSetTemperatureRequest(int colorTemp);
QPair<QNetworkRequest, QByteArray> createFlashRequest(const QString &alert);
private:

View File

@ -33,8 +33,8 @@
#include <QtMath>
HueMotionSensor::HueMotionSensor(QObject *parent) :
HueDevice(parent)
HueMotionSensor::HueMotionSensor(HueBridge *bridge, QObject *parent) :
HueDevice(bridge, parent)
{
m_timeout.setInterval(10000);
connect(&m_timeout, &QTimer::timeout, this, [this](){

View File

@ -41,7 +41,7 @@ class HueMotionSensor : public HueDevice
{
Q_OBJECT
public:
explicit HueMotionSensor(QObject *parent = nullptr);
explicit HueMotionSensor(HueBridge *bridge, QObject *parent = nullptr);
virtual ~HueMotionSensor() = default;
void setTimeout(int timeout);
@ -115,7 +115,7 @@ class HueIndoorSensor: public HueMotionSensor
{
Q_OBJECT
public:
HueIndoorSensor(QObject *parent = nullptr): HueMotionSensor(parent) {}
HueIndoorSensor(HueBridge *bridge, QObject *parent = nullptr): HueMotionSensor(bridge, parent) {}
StateTypeId connectedStateTypeId() const override { return motionSensorConnectedStateTypeId; }
StateTypeId temperatureStateTypeId() const override { return motionSensorTemperatureStateTypeId; }
@ -131,7 +131,7 @@ class HueOutdoorSensor: public HueMotionSensor
{
Q_OBJECT
public:
HueOutdoorSensor(QObject *parent = nullptr): HueMotionSensor(parent) {}
HueOutdoorSensor(HueBridge *bridge, QObject *parent = nullptr): HueMotionSensor(bridge, parent) {}
StateTypeId connectedStateTypeId() const override { return outdoorSensorConnectedStateTypeId; }
StateTypeId temperatureStateTypeId() const override { return outdoorSensorTemperatureStateTypeId; }

View File

@ -31,8 +31,8 @@
#include "hueremote.h"
#include "extern-plugininfo.h"
HueRemote::HueRemote(QObject *parent) :
HueDevice(parent)
HueRemote::HueRemote(HueBridge *bridge, QObject *parent) :
HueDevice(bridge, parent)
{
}

View File

@ -44,7 +44,7 @@ class HueRemote : public HueDevice
{
Q_OBJECT
public:
explicit HueRemote(QObject *parent = nullptr);
explicit HueRemote(HueBridge *bridge, QObject *parent = nullptr);
int battery() const;
void setBattery(const int &battery);

View File

@ -83,7 +83,8 @@ void IntegrationPluginPhilipsHue::init()
m_zeroConfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_hue._tcp");
connect(m_zeroConfBrowser, &ZeroConfServiceBrowser::serviceEntryAdded, this, [=](const ZeroConfServiceEntry &entry){
if (entry.protocol() == QAbstractSocket::IPv4Protocol) {
qCDebug(dcPhilipsHue()) << "service entry added!" << entry;
if (entry.protocol() != QAbstractSocket::IPv4Protocol) {
return;
}
QString bridgeId = normalizeBridgeId(entry.txt("bridgeid"));
@ -93,6 +94,9 @@ void IntegrationPluginPhilipsHue::init()
return;
}
thing->setParamValue(bridgeThingHostParamTypeId, entry.hostAddress().toString());
pluginStorage()->beginGroup(thing->id().toString());
pluginStorage()->setValue("hostCache", entry.hostAddress().toString());
pluginStorage()->endGroup();
HueBridge *bridge = m_bridges.key(thing);
bridge->setHostAddress(entry.hostAddress());
});
@ -282,6 +286,7 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
pluginStorage()->beginGroup(thing->id().toString());
QString apiKey = pluginStorage()->value("apiKey").toString();
QString hostCache = pluginStorage()->value("hostCache").toString();
pluginStorage()->endGroup();
// For legacy reasons we might not have the api key in the pluginstorage yet. Check if there is a key in the thing params.
@ -297,19 +302,35 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Not authenticated to bridge. Please reconfigure the bridge."));
return;
}
HueBridge *bridge;
if (m_bridges.values().contains(thing)) {
qCDebug(dcPhilipsHue()) << "Re-Discovery, not creating new bridge" << thing->name();
bridge = m_bridges.key(thing);
bridge->setApiKey(apiKey);
bridge->setHostAddress(QHostAddress(thing->paramValue(bridgeThingHostParamTypeId).toString()));
} else {
HueBridge *bridge = m_bridges.key(thing);
if (!bridge) {
bridge = new HueBridge(this);
bridge->setId(thing->paramValue(bridgeThingIdParamTypeId).toString());
bridge->setApiKey(apiKey);
bridge->setHostAddress(QHostAddress(thing->paramValue(bridgeThingHostParamTypeId).toString()));
m_bridges.insert(bridge, thing);
}
bridge->setApiKey(apiKey);
QHostAddress zeroconfAddress;
foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) {
if (entry.protocol() == QAbstractSocket::IPv4Protocol && normalizeBridgeId(entry.txt("bridgeid")) == thing->paramValue(bridgeThingIdParamTypeId).toString()) {
zeroconfAddress = entry.hostAddress();
}
}
if (!zeroconfAddress.isNull()) {
qCDebug(dcPhilipsHue()) << "Using IP address from zeroconf:" << zeroconfAddress.toString();
bridge->setHostAddress(zeroconfAddress);
pluginStorage()->beginGroup(thing->id().toString());
pluginStorage()->setValue("hostCache", zeroconfAddress.toString());
pluginStorage()->endGroup();
} else if (!hostCache.isEmpty()) {
qCDebug(dcPhilipsHue()) << "Using last known IP:" << hostCache;
bridge->setHostAddress(QHostAddress(hostCache));
} else {
// Let's keep this for now for backward compatibility... But probably can go away at some point.
// Bridge v1 didn't have zeroconf...
QString host = thing->paramValue(bridgeThingHostParamTypeId).toString();
qCDebug(dcPhilipsHue()) << "Using IP from params:" << host;
bridge->setHostAddress(QHostAddress(host));
}
discoverBridgeDevices(bridge);
return info->finish(Thing::ThingErrorNoError);
}
@ -322,15 +343,11 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
return;
}
// Hue color light
if (thing->thingClassId() == colorLightThingClassId) {
qCDebug(dcPhilipsHue) << "Setup Hue color light" << thing->params();
HueBridge *bridge = m_bridges.key(myThings().findById(thing->parentId()));
HueLight *hueLight = new HueLight(this);
hueLight->setHostAddress(bridge->hostAddress());
hueLight->setApiKey(bridge->apiKey());
HueLight *hueLight = new HueLight(bridge, this);
hueLight->setId(thing->paramValue(colorLightThingLightIdParamTypeId).toInt());
hueLight->setModelId(thing->paramValue(colorLightThingModelIdParamTypeId).toString());
hueLight->setUuid(thing->paramValue(colorLightThingUuidParamTypeId).toString());
@ -348,10 +365,7 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
if (thing->thingClassId() == colorTemperatureLightThingClassId) {
qCDebug(dcPhilipsHue) << "Setup Hue color temperature light" << thing->params();
HueBridge *bridge = m_bridges.key(myThings().findById(thing->parentId()));
HueLight *hueLight = new HueLight(this);
hueLight->setHostAddress(bridge->hostAddress());
hueLight->setApiKey(bridge->apiKey());
HueLight *hueLight = new HueLight(bridge, this);
hueLight->setId(thing->paramValue(colorTemperatureLightThingLightIdParamTypeId).toInt());
hueLight->setModelId(thing->paramValue(colorTemperatureLightThingModelIdParamTypeId).toString());
hueLight->setUuid(thing->paramValue(colorTemperatureLightThingUuidParamTypeId).toString());
@ -369,10 +383,7 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
if (thing->thingClassId() == dimmableLightThingClassId) {
qCDebug(dcPhilipsHue) << "Setup Hue white light" << thing->params();
HueBridge *bridge = m_bridges.key(myThings().findById(thing->parentId()));
HueLight *hueLight = new HueLight(this);
hueLight->setHostAddress(bridge->hostAddress());
hueLight->setApiKey(bridge->apiKey());
HueLight *hueLight = new HueLight(bridge, this);
// Migrate thing parameters after changing param type UUIDs in 0.14.
QMap<QString, ParamTypeId> migrationMap;
@ -415,10 +426,7 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
if (thing->thingClassId() == remoteThingClassId) {
qCDebug(dcPhilipsHue) << "Setup Hue remote" << thing->params() << thing->thingClassId();
HueBridge *bridge = m_bridges.key(myThings().findById(thing->parentId()));
HueRemote *hueRemote = new HueRemote(this);
hueRemote->setHostAddress(bridge->hostAddress());
hueRemote->setApiKey(bridge->apiKey());
HueRemote *hueRemote = new HueRemote(bridge, this);
// Migrate thing parameters after changing param type UUIDs in 0.14.
QMap<QString, ParamTypeId> migrationMap;
@ -458,7 +466,7 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
// Hue tap
if (thing->thingClassId() == tapThingClassId) {
HueRemote *hueTap = new HueRemote(this);
HueRemote *hueTap = new HueRemote(bridge, this);
hueTap->setName(thing->name());
hueTap->setId(thing->paramValue(tapThingSensorIdParamTypeId).toInt());
hueTap->setModelId(thing->paramValue(tapThingModelIdParamTypeId).toString());
@ -473,7 +481,7 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
// Hue smart button
if (thing->thingClassId() == smartButtonThingClassId) {
HueRemote *smartButton = new HueRemote(this);
HueRemote *smartButton = new HueRemote(bridge, this);
smartButton->setName(thing->name());
smartButton->setId(thing->paramValue(smartButtonThingSensorIdParamTypeId).toInt());
smartButton->setModelId(thing->paramValue(smartButtonThingModelIdParamTypeId).toString());
@ -490,7 +498,7 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
if (thing->thingClassId() == motionSensorThingClassId) {
qCDebug(dcPhilipsHue) << "Setup Hue motion sensor" << thing->params();
HueIndoorSensor *motionSensor = new HueIndoorSensor(this);
HueIndoorSensor *motionSensor = new HueIndoorSensor(bridge, this);
motionSensor->setTimeout(thing->setting(motionSensorSettingsTimeoutParamTypeId).toUInt());
motionSensor->setUuid(thing->paramValue(motionSensorThingUuidParamTypeId).toString());
motionSensor->setModelId(thing->paramValue(motionSensorThingModelIdParamTypeId).toString());
@ -522,7 +530,7 @@ void IntegrationPluginPhilipsHue::setupThing(ThingSetupInfo *info)
if (thing->thingClassId() == outdoorSensorThingClassId) {
qCDebug(dcPhilipsHue) << "Setup Hue Outdoor sensor" << thing->params();
HueMotionSensor *outdoorSensor = new HueOutdoorSensor(this);
HueMotionSensor *outdoorSensor = new HueOutdoorSensor(bridge, this);
outdoorSensor->setTimeout(thing->setting(outdoorSensorSettingsTimeoutParamTypeId).toUInt());
outdoorSensor->setUuid(thing->paramValue(outdoorSensorThingUuidParamTypeId).toString());
outdoorSensor->setModelId(thing->paramValue(outdoorSensorThingModelIdParamTypeId).toString());
@ -1254,7 +1262,7 @@ void IntegrationPluginPhilipsHue::refreshSensors(HueBridge *bridge)
void IntegrationPluginPhilipsHue::discoverBridgeDevices(HueBridge *bridge)
{
Thing *thing = m_bridges.value(bridge);
qCDebug(dcPhilipsHue) << "Discover bridge devices" << bridge->hostAddress();
qCDebug(dcPhilipsHue) << "Asking bridge for new devices" << bridge->hostAddress();
QPair<QNetworkRequest, QByteArray> lightsRequest = bridge->createDiscoverLightsRequest();
QNetworkReply *lightsReply = hardwareManager()->networkManager()->get(lightsRequest.first);
@ -1270,7 +1278,7 @@ void IntegrationPluginPhilipsHue::discoverBridgeDevices(HueBridge *bridge)
void IntegrationPluginPhilipsHue::searchNewDevices(HueBridge *bridge, const QString &serialNumber)
{
Thing *thing = m_bridges.value(bridge);
qCDebug(dcPhilipsHue) << "Discover bridge devices" << bridge->hostAddress();
qCDebug(dcPhilipsHue) << "Triggering ZigBee scan on bridge" << bridge->hostAddress();
QPair<QNetworkRequest, QByteArray> request = bridge->createSearchLightsRequest(serialNumber);
QNetworkReply *reply = hardwareManager()->networkManager()->post(request.first, request.second);
@ -1422,6 +1430,12 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th
return;
}
HueBridge *bridge = m_bridges.key(thing);
if (!bridge) {
qCWarning(dcPhilipsHue()) << "Received a reply for a bridge we don't have any more.";
return;
}
// Create sensors if not already added
QVariantMap sensorsMap = jsonDoc.toVariant().toMap();
QHash<QString, HueMotionSensor *> motionSensors;
@ -1502,9 +1516,9 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th
// Create an outdoor sensor
HueMotionSensor *motionSensor = nullptr;
if (model == "SML001") {
motionSensor = new HueIndoorSensor(this);
motionSensor = new HueIndoorSensor(bridge, this);
} else {
motionSensor = new HueOutdoorSensor(this);
motionSensor = new HueOutdoorSensor(bridge, this);
}
motionSensor->setModelId(model);
motionSensor->setUuid(baseUuid);
@ -1525,9 +1539,9 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th
// Create an outdoor sensor
HueMotionSensor *motionSensor = nullptr;
if (model == "SML001") {
motionSensor = new HueIndoorSensor(this);
motionSensor = new HueIndoorSensor(bridge, this);
} else {
motionSensor = new HueOutdoorSensor(this);
motionSensor = new HueOutdoorSensor(bridge, this);
}
motionSensor->setModelId(model);
motionSensor->setUuid(baseUuid);
@ -1548,9 +1562,9 @@ void IntegrationPluginPhilipsHue::processBridgeSensorDiscoveryResponse(Thing *th
// Create an outdoor sensor
HueMotionSensor *motionSensor = nullptr;
if (model == "SML001") {
motionSensor = new HueIndoorSensor(this);
motionSensor = new HueIndoorSensor(bridge, this);
} else {
motionSensor = new HueOutdoorSensor(this);
motionSensor = new HueOutdoorSensor(bridge, this);
}
motionSensor->setModelId(model);
motionSensor->setUuid(baseUuid);