Add philips hue zigbee plugin with hue dimmer switch support
parent
3d365d2c57
commit
10cc4ed8db
|
|
@ -1061,6 +1061,23 @@ Description: nymea.io zigbee plugin for different generic recognizable lights
|
|||
.
|
||||
This package will install the nymea.io plugin for generic recognizable lights
|
||||
|
||||
|
||||
Package: nymea-plugin-zigbee-philipshue
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
libnymea-zigbee1,
|
||||
nymea-plugins-translations,
|
||||
Description: nymea.io zigbee plugin for Philips Hue devices
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
server works like a translator for devices, things and services and
|
||||
allows them to interact.
|
||||
With the powerful rule engine you are able to connect any device available
|
||||
in the system and create individual scenes and behaviors for your environment.
|
||||
.
|
||||
This package will install the nymea.io plugin for Philips Hue zigbee devices
|
||||
|
||||
|
||||
Package: nymea-plugin-zigbee-tradfri
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
|
|
@ -1149,6 +1166,7 @@ Architecture: all
|
|||
Depends: nymea-plugin-zigbee-lumi,
|
||||
nymea-plugin-zigbee-generic,
|
||||
nymea-plugin-zigbee-generic-lights,
|
||||
nymea-plugin-zigbee-philipshue,
|
||||
nymea-plugin-zigbee-tradfri
|
||||
Description: Zigbee plugins for nymea IoT server - meta package for all zigbee replated plugins
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginzigbee-philipshue.so
|
||||
|
|
@ -67,6 +67,7 @@ PLUGIN_DIRS = \
|
|||
zigbee-generic \
|
||||
zigbee-generic-lights \
|
||||
zigbee-lumi \
|
||||
zigbee-philipshue \
|
||||
zigbee-tradfri \
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
{
|
||||
"name": "ZigbeePhilipsHue",
|
||||
"displayName": "Zigbee Philips Hue",
|
||||
"id": "0ca340b7-061a-42e6-ab7d-d7b4fd235d02",
|
||||
"vendors": [
|
||||
{
|
||||
"id": "0ae1e001-2aa6-47ed-b8c0-334c3728a68f",
|
||||
"name": "philips",
|
||||
"displayName": "Philips",
|
||||
"thingClasses": [
|
||||
{
|
||||
"name": "dimmerSwitch",
|
||||
"displayName": "Hue dimmer switch",
|
||||
"id": "b2711164-a848-4715-8ddf-33ca86f9f4cf",
|
||||
"setupMethod": "JustAdd",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": [ "multibutton", "batterylevel", "wirelessconnectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "b221cad1-ef2e-4192-8168-11d0205a43da",
|
||||
"name": "ieeeAddress",
|
||||
"displayName": "IEEE adress",
|
||||
"type": "QString",
|
||||
"defaultValue": "00:00:00:00:00:00:00:00"
|
||||
},
|
||||
{
|
||||
"id": "d2bb97ee-caed-4776-8931-9fc0a04e4e8f",
|
||||
"name": "networkUuid",
|
||||
"displayName": "Zigbee network UUID",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "5ac101b2-4bb7-4b5c-8493-08b1ae7ca0c1",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"cached": false,
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "5a6e325e-a6ee-4a36-b429-f5d8c8adb80b",
|
||||
"name": "signalStrength",
|
||||
"displayName": "Signal strength",
|
||||
"displayNameEvent": "Signal strength changed",
|
||||
"defaultValue": 0,
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"type": "uint",
|
||||
"unit": "Percentage"
|
||||
},
|
||||
{
|
||||
"id": "12139630-668a-4ad8-96fa-781028e9eced",
|
||||
"name": "version",
|
||||
"displayName": "Version",
|
||||
"displayNameEvent": "Version changed",
|
||||
"type": "QString",
|
||||
"cached": true,
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "3e28e0b3-fe23-4293-8876-8384def6c4fb",
|
||||
"name": "batteryLevel",
|
||||
"displayName": "Battery",
|
||||
"displayNameEvent": "Battery changed",
|
||||
"type": "int",
|
||||
"unit": "Percentage",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 100
|
||||
},
|
||||
{
|
||||
"id": "4223a3bc-9616-4ed2-ae50-704b9df62d0e",
|
||||
"name": "batteryCritical",
|
||||
"displayName": "Battery critical",
|
||||
"displayNameEvent": "Battery critical changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
|
||||
],
|
||||
"eventTypes": [
|
||||
{
|
||||
"id": "33bb5816-8479-4995-99e2-cb0443886003",
|
||||
"name": "pressed",
|
||||
"displayName": "Button pressed",
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "c086a247-838f-49c0-b1e4-2ae1ed181b55",
|
||||
"name": "buttonName",
|
||||
"displayName": "Button name",
|
||||
"type": "QString",
|
||||
"allowedValues": ["ON", "OFF", "DIM UP", "DIM DOWN"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "integrationpluginzigbeephilipshue.h"
|
||||
#include "plugininfo.h"
|
||||
#include "hardware/zigbee/zigbeehardwareresource.h"
|
||||
|
||||
IntegrationPluginZigbeePhilipsHue::IntegrationPluginZigbeePhilipsHue()
|
||||
{
|
||||
m_ieeeAddressParamTypeIds[dimmerSwitchThingClassId] = dimmerSwitchThingIeeeAddressParamTypeId;
|
||||
|
||||
m_networkUuidParamTypeIds[dimmerSwitchThingClassId] = dimmerSwitchThingNetworkUuidParamTypeId;
|
||||
|
||||
m_connectedStateTypeIds[dimmerSwitchThingClassId] = dimmerSwitchConnectedStateTypeId;
|
||||
|
||||
m_signalStrengthStateTypeIds[dimmerSwitchThingClassId] = dimmerSwitchSignalStrengthStateTypeId;
|
||||
|
||||
m_versionStateTypeIds[dimmerSwitchThingClassId] = dimmerSwitchVersionStateTypeId;
|
||||
|
||||
}
|
||||
|
||||
QString IntegrationPluginZigbeePhilipsHue::name() const
|
||||
{
|
||||
return "Philips Hue";
|
||||
}
|
||||
|
||||
bool IntegrationPluginZigbeePhilipsHue::handleNode(ZigbeeNode *node, const QUuid &networkUuid)
|
||||
{
|
||||
// Make sure this is from Philips 0x100b
|
||||
if (node->nodeDescriptor().manufacturerCode != Zigbee::Philips)
|
||||
return false;
|
||||
|
||||
bool handled = false;
|
||||
|
||||
if (node->endpoints().count() == 2 && node->hasEndpoint(0x01) && node->hasEndpoint(0x02)) {
|
||||
ZigbeeNodeEndpoint *endpointOne = node->getEndpoint(0x01);
|
||||
ZigbeeNodeEndpoint *endpoinTwo = node->getEndpoint(0x02);
|
||||
|
||||
// Dimmer switch
|
||||
if (endpointOne->profile() == Zigbee::ZigbeeProfileLightLink &&
|
||||
endpointOne->deviceId() == Zigbee::LightLinkDeviceNonColourSceneController
|
||||
&& endpoinTwo->profile() == Zigbee::ZigbeeProfileHomeAutomation &&
|
||||
endpoinTwo->deviceId() == Zigbee::HomeAutomationDeviceSimpleSensor) {
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Handeling Hue dimmer switch" << node << endpointOne << endpoinTwo;
|
||||
createThing(dimmerSwitchThingClassId, networkUuid, node);
|
||||
initDimmerSwitch(node);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeePhilipsHue::handleRemoveNode(ZigbeeNode *node, const QUuid &networkUuid)
|
||||
{
|
||||
Q_UNUSED(networkUuid)
|
||||
|
||||
if (m_thingNodes.values().contains(node)) {
|
||||
Thing *thing = m_thingNodes.key(node);
|
||||
qCDebug(dcZigbeePhilipsHue()) << node << "for" << thing << "has left the network.";
|
||||
m_thingNodes.remove(thing);
|
||||
emit autoThingDisappeared(thing->id());
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeePhilipsHue::init()
|
||||
{
|
||||
hardwareManager()->zigbeeResource()->registerHandler(this, ZigbeeHardwareResource::HandlerTypeVendor);
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeePhilipsHue::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
QUuid networkUuid = thing->paramValue(m_networkUuidParamTypeIds.value(thing->thingClassId())).toUuid();
|
||||
ZigbeeAddress zigbeeAddress = ZigbeeAddress(thing->paramValue(m_ieeeAddressParamTypeIds.value(thing->thingClassId())).toString());
|
||||
ZigbeeNode *node = hardwareManager()->zigbeeResource()->claimNode(this, networkUuid, zigbeeAddress);
|
||||
if (!node) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Zigbee node for" << info->thing()->name() << "not found.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
m_thingNodes.insert(thing, node);
|
||||
|
||||
// Update connected state
|
||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), node->reachable());
|
||||
connect(node, &ZigbeeNode::reachableChanged, thing, [thing, this](bool reachable){
|
||||
thing->setStateValue(m_connectedStateTypeIds.value(thing->thingClassId()), reachable);
|
||||
});
|
||||
|
||||
// Update signal strength
|
||||
thing->setStateValue(m_signalStrengthStateTypeIds.value(thing->thingClassId()), qRound(node->lqi() * 100.0 / 255.0));
|
||||
connect(node, &ZigbeeNode::lqiChanged, thing, [this, thing](quint8 lqi){
|
||||
uint signalStrength = qRound(lqi * 100.0 / 255.0);
|
||||
qCDebug(dcZigbeePhilipsHue()) << thing << "signal strength changed" << signalStrength << "%";
|
||||
thing->setStateValue(m_signalStrengthStateTypeIds.value(thing->thingClassId()), signalStrength);
|
||||
});
|
||||
|
||||
|
||||
// Thing specific setup
|
||||
if (thing->thingClassId() == dimmerSwitchThingClassId) {
|
||||
ZigbeeNodeEndpoint *endpointZll = node->getEndpoint(0x01);
|
||||
ZigbeeNodeEndpoint *endpointHa = node->getEndpoint(0x02);
|
||||
|
||||
// Set the version
|
||||
thing->setStateValue(m_versionStateTypeIds.value(thing->thingClassId()), endpointZll->softwareBuildId());
|
||||
|
||||
|
||||
// Receive on/off commands
|
||||
ZigbeeClusterOnOff *onOffCluster = endpointZll->outputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
|
||||
if (!onOffCluster) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Could not find on/off client cluster on" << thing << endpointZll;
|
||||
} else {
|
||||
connect(onOffCluster, &ZigbeeClusterOnOff::commandSent, thing, [=](ZigbeeClusterOnOff::Command command){
|
||||
if (command == ZigbeeClusterOnOff::CommandOn) {
|
||||
qCDebug(dcZigbeePhilipsHue()) << thing << "pressed ON";
|
||||
emit emitEvent(Event(dimmerSwitchPressedEventTypeId, thing->id(), ParamList() << Param(dimmerSwitchPressedEventButtonNameParamTypeId, "ON")));
|
||||
} else {
|
||||
qCWarning(dcZigbeePhilipsHue()) << thing << "unhandled command received" << command;
|
||||
}
|
||||
});
|
||||
|
||||
connect(onOffCluster, &ZigbeeClusterOnOff::commandOffWithEffectSent, thing, [=](ZigbeeClusterOnOff::Effect effect, quint8 effectVariant){
|
||||
qCDebug(dcZigbeePhilipsHue()) << thing << "OFF button pressed" << effect << effectVariant;
|
||||
emit emitEvent(Event(dimmerSwitchPressedEventTypeId, thing->id(), ParamList() << Param(dimmerSwitchPressedEventButtonNameParamTypeId, "OFF")));
|
||||
});
|
||||
}
|
||||
|
||||
// Receive level control commands
|
||||
ZigbeeClusterLevelControl *levelCluster = endpointZll->outputCluster<ZigbeeClusterLevelControl>(ZigbeeClusterLibrary::ClusterIdLevelControl);
|
||||
if (!levelCluster) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Could not find level client cluster on" << thing << endpointZll;
|
||||
} else {
|
||||
connect(levelCluster, &ZigbeeClusterLevelControl::commandStepSent, thing, [=](ZigbeeClusterLevelControl::FadeMode fadeMode, quint8 stepSize, quint16 transitionTime){
|
||||
qCDebug(dcZigbeePhilipsHue()) << thing << "level button pressed" << fadeMode << stepSize << transitionTime;
|
||||
switch (fadeMode) {
|
||||
case ZigbeeClusterLevelControl::FadeModeUp:
|
||||
qCDebug(dcZigbeePhilipsHue()) << thing << "DIM UP pressed";
|
||||
emit emitEvent(Event(dimmerSwitchPressedEventTypeId, thing->id(), ParamList() << Param(dimmerSwitchPressedEventButtonNameParamTypeId, "DIM UP")));
|
||||
break;
|
||||
case ZigbeeClusterLevelControl::FadeModeDown:
|
||||
qCDebug(dcZigbeePhilipsHue()) << thing << "DIM DOWN pressed";
|
||||
emit emitEvent(Event(dimmerSwitchPressedEventTypeId, thing->id(), ParamList() << Param(dimmerSwitchPressedEventButtonNameParamTypeId, "DIM DOWN")));
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Get battery level changes
|
||||
ZigbeeClusterPowerConfiguration *powerCluster = endpointHa->inputCluster<ZigbeeClusterPowerConfiguration>(ZigbeeClusterLibrary::ClusterIdPowerConfiguration);
|
||||
if (!powerCluster) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Could not find power configuration cluster on" << thing << endpointHa;
|
||||
} else {
|
||||
// Only set the initial state if the attribute already exists
|
||||
if (powerCluster->hasAttribute(ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining)) {
|
||||
thing->setStateValue(dimmerSwitchBatteryLevelStateTypeId, powerCluster->batteryPercentage());
|
||||
thing->setStateValue(dimmerSwitchBatteryCriticalStateTypeId, (powerCluster->batteryPercentage() < 10.0));
|
||||
}
|
||||
|
||||
connect(powerCluster, &ZigbeeClusterPowerConfiguration::batteryPercentageChanged, thing, [=](double percentage){
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Battery percentage changed" << percentage << "%" << thing;
|
||||
thing->setStateValue(dimmerSwitchBatteryLevelStateTypeId, percentage);
|
||||
thing->setStateValue(dimmerSwitchBatteryCriticalStateTypeId, (percentage < 10.0));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeePhilipsHue::executeAction(ThingActionInfo *info)
|
||||
{
|
||||
info->finish(Thing::ThingErrorUnsupportedFeature);
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeePhilipsHue::thingRemoved(Thing *thing)
|
||||
{
|
||||
ZigbeeNode *node = m_thingNodes.take(thing);
|
||||
if (node) {
|
||||
QUuid networkUuid = thing->paramValue(m_networkUuidParamTypeIds.value(thing->thingClassId())).toUuid();
|
||||
hardwareManager()->zigbeeResource()->removeNodeFromNetwork(networkUuid, node);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeePhilipsHue::createThing(const ThingClassId &thingClassId, const QUuid &networkUuid, ZigbeeNode *node)
|
||||
{
|
||||
ThingDescriptor descriptor(thingClassId);
|
||||
QString deviceClassName = supportedThings().findById(thingClassId).displayName();
|
||||
descriptor.setTitle(deviceClassName);
|
||||
|
||||
ParamList params;
|
||||
params.append(Param(m_networkUuidParamTypeIds[thingClassId], networkUuid.toString()));
|
||||
params.append(Param(m_ieeeAddressParamTypeIds[thingClassId], node->extendedAddress().toString()));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared({descriptor});
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeePhilipsHue::initDimmerSwitch(ZigbeeNode *node)
|
||||
{
|
||||
ZigbeeNodeEndpoint *endpointZll = node->getEndpoint(0x01);
|
||||
ZigbeeNodeEndpoint *endpointHa = node->getEndpoint(0x02);
|
||||
|
||||
// Get the current configured bindings for this node
|
||||
ZigbeeReply *reply = node->removeAllBindings();
|
||||
connect(reply, &ZigbeeReply::finished, node, [=](){
|
||||
if (reply->error() != ZigbeeReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to remove all bindings for initialization of" << node;
|
||||
}
|
||||
|
||||
// Read battery, bind and configure attribute reporting for battery
|
||||
if (!endpointHa->hasInputCluster(ZigbeeClusterLibrary::ClusterIdPowerConfiguration)) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to initialize the power configuration cluster because the cluster could not be found" << node << endpointHa;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Read power configuration cluster attributes" << node;
|
||||
ZigbeeClusterReply *readAttributeReply = endpointHa->getInputCluster(ZigbeeClusterLibrary::ClusterIdPowerConfiguration)->readAttributes({ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining});
|
||||
connect(readAttributeReply, &ZigbeeClusterReply::finished, node, [=](){
|
||||
if (readAttributeReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to read power cluster attributes" << readAttributeReply->error();
|
||||
//emit nodeInitialized(node);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Read power configuration cluster attributes finished successfully";
|
||||
|
||||
// Bind the cluster to the coordinator
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind power configuration cluster to coordinator IEEE address";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindIeeeAddress(endpointHa->endpointId(), ZigbeeClusterLibrary::ClusterIdPowerConfiguration,
|
||||
hardwareManager()->zigbeeResource()->coordinatorAddress(node->networkUuid()), 0x01);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to bind power cluster to coordinator" << zdoReply->error();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind power configuration cluster to coordinator finished successfully";
|
||||
|
||||
// Configure attribute rporting for battery remaining (0.5 % changes = 1)
|
||||
ZigbeeClusterLibrary::AttributeReportingConfiguration reportingConfig;
|
||||
reportingConfig.attributeId = ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining;
|
||||
reportingConfig.dataType = Zigbee::Uint8;
|
||||
reportingConfig.minReportingInterval = 300;
|
||||
reportingConfig.maxReportingInterval = 2700;
|
||||
reportingConfig.reportableChange = ZigbeeDataType(static_cast<quint8>(1)).data();
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Configure attribute reporting for power configuration cluster to coordinator";
|
||||
ZigbeeClusterReply *reportingReply = endpointHa->getInputCluster(ZigbeeClusterLibrary::ClusterIdPowerConfiguration)->configureReporting({reportingConfig});
|
||||
connect(reportingReply, &ZigbeeClusterReply::finished, this, [=](){
|
||||
if (reportingReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to configure power cluster attribute reporting" << reportingReply->error();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Attribute reporting configuration finished for power cluster" << ZigbeeClusterLibrary::parseAttributeReportingStatusRecords(reportingReply->responseFrame().payload);
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind on/off cluster to coordinator";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindShortAddress(endpointZll->endpointId(), ZigbeeClusterLibrary::ClusterIdOnOff, 0x0000);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to bind on/off cluster to coordinator" << zdoReply->error();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind on/off cluster to coordinator finished successfully";
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind power level cluster to coordinator";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindShortAddress(endpointZll->endpointId(), ZigbeeClusterLibrary::ClusterIdLevelControl, 0x0000);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to bind level cluster to coordinator" << zdoReply->error();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind level cluster to coordinator finished successfully";
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Read binding table from node" << node;
|
||||
ZigbeeReply *reply = node->readBindingTableEntries();
|
||||
connect(reply, &ZigbeeReply::finished, node, [=](){
|
||||
if (reply->error() != ZigbeeReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to read binding table from" << node;
|
||||
} else {
|
||||
foreach (const ZigbeeDeviceProfile::BindingTableListRecord &binding, node->bindingTableRecords()) {
|
||||
qCDebug(dcZigbeePhilipsHue()) << node << binding;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef INTEGRATIONPLUGINZIGBEEPHILIPSHUE_H
|
||||
#define INTEGRATIONPLUGINZIGBEEPHILIPSHUE_H
|
||||
|
||||
#include "integrations/integrationplugin.h"
|
||||
#include "hardware/zigbee/zigbeehandler.h"
|
||||
#include "plugintimer.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
class IntegrationPluginZigbeePhilipsHue: public IntegrationPlugin, public ZigbeeHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginzigbee-philipshue.json")
|
||||
Q_INTERFACES(IntegrationPlugin)
|
||||
|
||||
public:
|
||||
explicit IntegrationPluginZigbeePhilipsHue();
|
||||
|
||||
QString name() const override;
|
||||
bool handleNode(ZigbeeNode *node, const QUuid &networkUuid) override;
|
||||
void handleRemoveNode(ZigbeeNode *node, const QUuid &networkUuid) override;
|
||||
|
||||
void init() override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
void executeAction(ThingActionInfo *info) override;
|
||||
void thingRemoved(Thing *thing) override;
|
||||
|
||||
private:
|
||||
PluginTimer *m_presenceTimer = nullptr;
|
||||
QHash<Thing*, ZigbeeNode*> m_thingNodes;
|
||||
|
||||
QHash<ThingClassId, ParamTypeId> m_ieeeAddressParamTypeIds;
|
||||
QHash<ThingClassId, ParamTypeId> m_networkUuidParamTypeIds;
|
||||
|
||||
QHash<ThingClassId, StateTypeId> m_connectedStateTypeIds;
|
||||
QHash<ThingClassId, StateTypeId> m_signalStrengthStateTypeIds;
|
||||
QHash<ThingClassId, StateTypeId> m_versionStateTypeIds;
|
||||
|
||||
void createThing(const ThingClassId &thingClassId, const QUuid &networkUuid, ZigbeeNode *node);
|
||||
|
||||
void initDimmerSwitch(ZigbeeNode *node);
|
||||
|
||||
};
|
||||
|
||||
#endif // INTEGRATIONPLUGINZIGBEEPHILIPSHUE_H
|
||||
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE TS><TS version="2.1"></TS>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
include(../plugins.pri)
|
||||
|
||||
PKGCONFIG += nymea-zigbee
|
||||
|
||||
SOURCES += \
|
||||
integrationpluginzigbeephilipshue.cpp
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginzigbeephilipshue.h
|
||||
|
|
@ -394,8 +394,8 @@ void IntegrationPluginZigbeeTradfri::initOnOffSwitch(ZigbeeNode *node, ZigbeeNod
|
|||
ZigbeeClusterLibrary::AttributeReportingConfiguration reportingConfig;
|
||||
reportingConfig.attributeId = ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining;
|
||||
reportingConfig.dataType = Zigbee::Uint8;
|
||||
reportingConfig.minReportingInterval = 60;//300;
|
||||
reportingConfig.maxReportingInterval = 120;//2700;
|
||||
reportingConfig.minReportingInterval = 300;
|
||||
reportingConfig.maxReportingInterval = 2700;
|
||||
reportingConfig.reportableChange = ZigbeeDataType(static_cast<quint8>(1)).data();
|
||||
|
||||
qCDebug(dcZigbeeTradfri()) << "Configure attribute reporting for power configuration cluster to coordinator";
|
||||
|
|
@ -487,8 +487,8 @@ void IntegrationPluginZigbeeTradfri::initRemote(ZigbeeNode *node, ZigbeeNodeEndp
|
|||
ZigbeeClusterLibrary::AttributeReportingConfiguration reportingConfig;
|
||||
reportingConfig.attributeId = ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining;
|
||||
reportingConfig.dataType = Zigbee::Uint8;
|
||||
reportingConfig.minReportingInterval = 60;//300;
|
||||
reportingConfig.maxReportingInterval = 120;//2700;
|
||||
reportingConfig.minReportingInterval = 300;
|
||||
reportingConfig.maxReportingInterval = 2700;
|
||||
reportingConfig.reportableChange = ZigbeeDataType(static_cast<quint8>(1)).data();
|
||||
|
||||
qCDebug(dcZigbeeTradfri()) << "Configure attribute reporting for power configuration cluster to coordinator";
|
||||
|
|
@ -585,8 +585,8 @@ void IntegrationPluginZigbeeTradfri::initPowerConfigurationCluster(ZigbeeNode *n
|
|||
ZigbeeClusterLibrary::AttributeReportingConfiguration reportingConfig;
|
||||
reportingConfig.attributeId = ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining;
|
||||
reportingConfig.dataType = Zigbee::Uint8;
|
||||
reportingConfig.minReportingInterval = 60;//300;
|
||||
reportingConfig.maxReportingInterval = 120;//2700;
|
||||
reportingConfig.minReportingInterval = 300;
|
||||
reportingConfig.maxReportingInterval = 2700;
|
||||
reportingConfig.reportableChange = ZigbeeDataType(static_cast<quint8>(1)).data();
|
||||
|
||||
qCDebug(dcZigbeeTradfri()) << "Configure attribute reporting for power configuration cluster to coordinator";
|
||||
|
|
|
|||
Loading…
Reference in New Issue