add support for the Hue Tap button
This commit is contained in:
parent
f07031e589
commit
9d175bcfb9
@ -2,6 +2,7 @@
|
||||
* *
|
||||
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
|
||||
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* Copyright (C) 2018 Michael Zanetti <michael.zanetti@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
@ -114,8 +115,9 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev
|
||||
bridge->setName(device->paramValue(hueBridgeBridgeNameParamTypeId).toString());
|
||||
bridge->setMacAddress(device->paramValue(hueBridgeBridgeMacParamTypeId).toString());
|
||||
bridge->setZigbeeChannel(device->paramValue(hueBridgeBridgeZigbeeChannelParamTypeId).toInt());
|
||||
|
||||
m_bridges.insert(bridge, device);
|
||||
|
||||
discoverBridgeDevices(bridge);
|
||||
return DeviceManager::DeviceSetupStatusSuccess;
|
||||
}
|
||||
|
||||
@ -173,7 +175,7 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev
|
||||
|
||||
// hue remote
|
||||
if (device->deviceClassId() == hueRemoteDeviceClassId) {
|
||||
qCDebug(dcPhilipsHue) << "Setup Hue remote" << device->params();
|
||||
qCDebug(dcPhilipsHue) << "Setup Hue remote" << device->params() << device->deviceClassId();
|
||||
|
||||
HueRemote *hueRemote = new HueRemote(this);
|
||||
hueRemote->setId(device->paramValue(hueRemoteSensorIdParamTypeId).toInt());
|
||||
@ -195,6 +197,24 @@ DeviceManager::DeviceSetupStatus DevicePluginPhilipsHue::setupDevice(Device *dev
|
||||
return DeviceManager::DeviceSetupStatusSuccess;
|
||||
}
|
||||
|
||||
// hue tap
|
||||
if (device->deviceClassId() == hueTapDeviceClassId) {
|
||||
HueRemote *hueTap = new HueRemote(this);
|
||||
hueTap->setName(device->name());
|
||||
hueTap->setId(device->paramValue(hueTapSensorIdParamTypeId).toInt());
|
||||
hueTap->setBridgeId(DeviceId(device->paramValue(hueTapBridgeParamTypeId).toString()));
|
||||
hueTap->setModelId(device->paramValue(hueTapModelIdParamTypeId).toString());
|
||||
device->setParentId(hueTap->bridgeId());
|
||||
|
||||
connect(hueTap, &HueRemote::stateChanged, this, &DevicePluginPhilipsHue::remoteStateChanged);
|
||||
connect(hueTap, &HueRemote::buttonPressed, this, &DevicePluginPhilipsHue::onRemoteButtonEvent);
|
||||
|
||||
m_remotes.insert(hueTap, device);
|
||||
return DeviceManager::DeviceSetupStatusSuccess;
|
||||
}
|
||||
|
||||
qCWarning(dcPhilipsHue()) << "Unhandled setupDevice call" << device->deviceClassId();
|
||||
|
||||
return DeviceManager::DeviceSetupStatusFailure;
|
||||
}
|
||||
|
||||
@ -212,7 +232,7 @@ void DevicePluginPhilipsHue::deviceRemoved(Device *device)
|
||||
light->deleteLater();
|
||||
}
|
||||
|
||||
if (device->deviceClassId() == hueRemoteDeviceClassId) {
|
||||
if (device->deviceClassId() == hueRemoteDeviceClassId || device->deviceClassId() == hueTapDeviceClassId) {
|
||||
HueRemote *remote = m_remotes.key(device);
|
||||
m_remotes.remove(remote);
|
||||
remote->deleteLater();
|
||||
@ -366,7 +386,7 @@ void DevicePluginPhilipsHue::networkManagerReplyReady()
|
||||
|
||||
// check HTTP status code
|
||||
if (status != 200 || reply->error() != QNetworkReply::NoError) {
|
||||
if (device->stateValue(hueRemoteConnectedStateTypeId).toBool()) {
|
||||
if (device->stateValue(hueRemoteConnectedStateTypeId).toBool() || device->stateValue(hueTapConnectedStateTypeId).toBool()) {
|
||||
qCWarning(dcPhilipsHue) << "Refresh Hue sensors request error:" << status << reply->errorString();
|
||||
bridgeReachableChanged(device, false);
|
||||
}
|
||||
@ -399,6 +419,8 @@ void DevicePluginPhilipsHue::networkManagerReplyReady()
|
||||
return;
|
||||
}
|
||||
processSetNameResponse(device, reply->readAll());
|
||||
} else {
|
||||
qCWarning(dcPhilipsHue()) << "Unhandled bridge reply" << reply->readAll();
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
@ -548,18 +570,27 @@ void DevicePluginPhilipsHue::remoteStateChanged()
|
||||
qCWarning(dcPhilipsHue) << "Could not find device for remote" << remote->name();
|
||||
return;
|
||||
}
|
||||
|
||||
device->setStateValue(hueRemoteConnectedStateTypeId, remote->reachable());
|
||||
device->setStateValue(hueRemoteBatteryLevelStateTypeId, remote->battery());
|
||||
device->setStateValue(hueRemoteBatteryCriticalStateTypeId, remote->battery() < 5);
|
||||
if (device->deviceClassId() == hueTapDeviceClassId) {
|
||||
device->setStateValue(hueTapConnectedStateTypeId, remote->reachable());
|
||||
} else {
|
||||
device->setStateValue(hueRemoteConnectedStateTypeId, remote->reachable());
|
||||
device->setStateValue(hueRemoteBatteryLevelStateTypeId, remote->battery());
|
||||
device->setStateValue(hueRemoteBatteryCriticalStateTypeId, remote->battery() < 5);
|
||||
}
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::onRemoteButtonEvent(const int &buttonCode)
|
||||
{
|
||||
HueRemote *remote = static_cast<HueRemote *>(sender());
|
||||
Device *device = m_remotes.value(remote);
|
||||
|
||||
Param param(hueRemoteButtonNameParamTypeId);
|
||||
EventTypeId id;
|
||||
Param param;
|
||||
if (device->deviceClassId() == hueRemoteDeviceClassId) {
|
||||
param = Param(hueRemoteButtonNameParamTypeId);
|
||||
} else if (device->deviceClassId() == hueTapDeviceClassId) {
|
||||
param = Param(hueTapButtonNameParamTypeId);
|
||||
}
|
||||
|
||||
// TODO: Legacy events should be removed eventually
|
||||
switch (buttonCode) {
|
||||
@ -603,6 +634,22 @@ void DevicePluginPhilipsHue::onRemoteButtonEvent(const int &buttonCode)
|
||||
param.setValue("OFF");
|
||||
id = hueRemoteLongPressedEventTypeId;
|
||||
break;
|
||||
case HueRemote::TapButton1Pressed:
|
||||
param.setValue("•");
|
||||
id = hueTapPressedEventTypeId;
|
||||
break;
|
||||
case HueRemote::TapButton2Pressed:
|
||||
param.setValue("••");
|
||||
id = hueTapPressedEventTypeId;
|
||||
break;
|
||||
case HueRemote::TapButton3Pressed:
|
||||
param.setValue("•••");
|
||||
id = hueTapPressedEventTypeId;
|
||||
break;
|
||||
case HueRemote::TapButton4Pressed:
|
||||
param.setValue("•••••");
|
||||
id = hueTapPressedEventTypeId;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -879,7 +926,6 @@ void DevicePluginPhilipsHue::processBridgeSensorDiscoveryResponse(Device *device
|
||||
}
|
||||
|
||||
// create sensors if not already added
|
||||
QList<DeviceDescriptor> sensorDescriptors;
|
||||
QVariantMap sensorsMap = jsonDoc.toVariant().toMap();
|
||||
foreach (QString sensorId, sensorsMap.keys()) {
|
||||
QVariantMap sensorMap = sensorsMap.value(sensorId).toMap();
|
||||
@ -890,7 +936,6 @@ void DevicePluginPhilipsHue::processBridgeSensorDiscoveryResponse(Device *device
|
||||
if (sensorAlreadyAdded(uuid))
|
||||
continue;
|
||||
|
||||
// check if this is a white light
|
||||
if (model == "RWL021" || model == "RWL020") {
|
||||
DeviceDescriptor descriptor(hueRemoteDeviceClassId, "Philips Hue Remote", sensorMap.value("name").toString());
|
||||
ParamList params;
|
||||
@ -903,14 +948,22 @@ void DevicePluginPhilipsHue::processBridgeSensorDiscoveryResponse(Device *device
|
||||
params.append(Param(hueRemoteUuidParamTypeId, uuid));
|
||||
params.append(Param(hueRemoteSensorIdParamTypeId, sensorId));
|
||||
descriptor.setParams(params);
|
||||
sensorDescriptors.append(descriptor);
|
||||
emit autoDevicesAppeared(hueRemoteDeviceClassId, {descriptor});
|
||||
qCDebug(dcPhilipsHue) << "Found new remote" << sensorMap.value("name").toString() << model;
|
||||
} else if (model == "ZGPSWITCH") {
|
||||
DeviceDescriptor descriptor(hueTapDeviceClassId, "Hue Tap", sensorMap.value("name").toString());
|
||||
ParamList params;
|
||||
params.append(Param(hueTapBridgeParamTypeId, device->id().toString()));
|
||||
params.append(Param(hueTapUuidParamTypeId, uuid));
|
||||
params.append(Param(hueTapModelIdParamTypeId, model));
|
||||
params.append(Param(hueTapSensorIdParamTypeId, sensorId));
|
||||
descriptor.setParams(params);
|
||||
emit autoDevicesAppeared(hueTapDeviceClassId, {descriptor});
|
||||
qCDebug(dcPhilipsHue()) << "Found hue tap:" << sensorMap << hueTapDeviceClassId;
|
||||
} else {
|
||||
qCDebug(dcPhilipsHue()) << "Found unknown sensor:" << model;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sensorDescriptors.isEmpty())
|
||||
emit autoDevicesAppeared(hueRemoteDeviceClassId, sensorDescriptors);
|
||||
|
||||
}
|
||||
|
||||
void DevicePluginPhilipsHue::processLightRefreshResponse(Device *device, const QByteArray &data)
|
||||
@ -1045,7 +1098,7 @@ void DevicePluginPhilipsHue::processSensorsRefreshResponse(Device *device, const
|
||||
QVariantMap sensorMap = sensorsMap.value(sensorId).toMap();
|
||||
foreach (HueRemote *remote, m_remotes.keys()) {
|
||||
if (remote->id() == sensorId.toInt() && remote->bridgeId() == device->id()) {
|
||||
//qCDebug(dcPhilipsHue) << "update remote" << remote->id() << remote->name();
|
||||
qCDebug(dcPhilipsHue) << "update remote" << remote->id() << remote->name();
|
||||
remote->updateStates(sensorMap.value("state").toMap(), sensorMap.value("config").toMap());
|
||||
}
|
||||
}
|
||||
@ -1225,7 +1278,11 @@ void DevicePluginPhilipsHue::bridgeReachableChanged(Device *device, const bool &
|
||||
foreach (HueRemote *remote, m_remotes.keys()) {
|
||||
if (remote->bridgeId() == device->id()) {
|
||||
remote->setReachable(false);
|
||||
m_remotes.value(remote)->setStateValue(hueRemoteConnectedStateTypeId, false);
|
||||
if (m_remotes.value(remote)->deviceClassId() == hueRemoteDeviceClassId) {
|
||||
m_remotes.value(remote)->setStateValue(hueRemoteConnectedStateTypeId, false);
|
||||
} else if (m_remotes.value(remote)->deviceClassId() == hueTapDeviceClassId) {
|
||||
m_remotes.value(remote)->setStateValue(hueTapConnectedStateTypeId, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1269,6 +1326,11 @@ bool DevicePluginPhilipsHue::sensorAlreadyAdded(const QString &uuid)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (device->deviceClassId() == hueTapDeviceClassId) {
|
||||
if (device->paramValue(hueTapUuidParamTypeId).toString() == uuid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"name": "buttonName",
|
||||
"displayName": "Button name",
|
||||
"type": "QString",
|
||||
"possibleValues": ["ON", "OFF", "DIM UP", "DIM DOWN"]
|
||||
"allowedValues": ["ON", "OFF", "DIM UP", "DIM DOWN"]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -610,7 +610,101 @@
|
||||
"name": "buttonName",
|
||||
"displayName": "Button name",
|
||||
"type": "QString",
|
||||
"possibleValues": ["ON", "OFF", "DIM UP", "DIM DOWN"]
|
||||
"allowedValues": ["ON", "OFF", "DIM UP", "DIM DOWN"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2b8c1fb8-67ee-42e9-947b-16e0a09f0d4e",
|
||||
"name": "hueTap",
|
||||
"displayName": "Hue Tap",
|
||||
"deviceIcon": "Switch",
|
||||
"interfaces": ["simplemultibutton", "connectable"],
|
||||
"createMethods": ["auto"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "3d450f00-b521-4a2c-985f-046fad5122cb",
|
||||
"name": "name",
|
||||
"displayName": "name",
|
||||
"type" : "QString",
|
||||
"inputType": "TextLine"
|
||||
},
|
||||
{
|
||||
"id": "c9e7483b-2f4e-4280-a437-8471f4dc9b22",
|
||||
"name": "bridge",
|
||||
"displayName": "bridge",
|
||||
"type" : "QString",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "62d92175-db3a-4da2-a72b-f58f34cb6911",
|
||||
"name": "modelId",
|
||||
"displayName": "model id",
|
||||
"type" : "QString",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "eace85b9-5369-466f-89eb-46c4de718305",
|
||||
"name": "type",
|
||||
"displayName": "type",
|
||||
"type" : "QString",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "25cf4167-6c28-4497-9fa9-3d02faf4f3ed",
|
||||
"name": "uuid",
|
||||
"displayName": "uuid",
|
||||
"type" : "QString",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "fb507641-9c78-4a28-937d-711775454e90",
|
||||
"name": "apiKey",
|
||||
"displayName": "api key",
|
||||
"type" : "QString",
|
||||
"inputType": "TextLine",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "6be56a1b-f64a-4188-a052-1fab11e01718",
|
||||
"name": "host",
|
||||
"displayName": "host address",
|
||||
"type" : "QString",
|
||||
"inputType": "IPv4Address",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"id": "5eca2b24-8986-4487-bc12-50e91d023d97",
|
||||
"name": "sensorId",
|
||||
"displayName": "sensor id",
|
||||
"type" : "int",
|
||||
"readOnly": true
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "5e21b032-1230-4e93-8543-0c4773da17d3",
|
||||
"name": "connected",
|
||||
"displayName": "reachable",
|
||||
"displayNameEvent": "reachable changed",
|
||||
"defaultValue": false,
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"eventTypes": [
|
||||
{
|
||||
"id": "c45dd703-7cbd-48f7-88dc-31045cc3d39c",
|
||||
"name": "pressed",
|
||||
"displayName": "Button pressed",
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "8ed643c0-1b8a-4709-8abf-717cf213f4a4",
|
||||
"name": "buttonName",
|
||||
"displayName": "Button name",
|
||||
"type": "QString",
|
||||
"allowedValues": ["•", "••", "•••", "••••"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -40,7 +40,13 @@ void HueRemote::setBattery(const int &battery)
|
||||
|
||||
void HueRemote::updateStates(const QVariantMap &statesMap, const QVariantMap &configMap)
|
||||
{
|
||||
setReachable(configMap.value("reachable", false).toBool());
|
||||
if (configMap.contains("reachable")) {
|
||||
setReachable(configMap.value("reachable", false).toBool());
|
||||
} else {
|
||||
// Hue Tap doesn't have a reachable property as it's a ultra low power device. Let's mark it reachable by default as we only
|
||||
// get this response if the bridge is reachable.
|
||||
setReachable(true);
|
||||
}
|
||||
setBattery(configMap.value("battery", 0).toInt());
|
||||
|
||||
emit stateChanged();
|
||||
|
||||
@ -44,7 +44,11 @@ public:
|
||||
DimDownLongPressed = 3001,
|
||||
DimDownPressed = 3002,
|
||||
OffLongPressed = 4001,
|
||||
OffPressed = 4002
|
||||
OffPressed = 4002,
|
||||
TapButton1Pressed = 34,
|
||||
TapButton2Pressed = 16,
|
||||
TapButton3Pressed = 17,
|
||||
TapButton4Pressed = 18
|
||||
};
|
||||
|
||||
explicit HueRemote(QObject *parent = 0);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user