Add tradfri range extender and fix motion sensor. Start implementing hue outdoor sensor
This commit is contained in:
parent
10cc4ed8db
commit
cb2a6f9f4c
@ -100,6 +100,122 @@
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "outdoorSensor",
|
||||
"displayName": "Hue outdoor sensor",
|
||||
"id": "031c45d1-e782-4f91-9f05-259d6b81c7ef",
|
||||
"setupMethod": "JustAdd",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": [ "presencesensor", "lightsensor", "temperaturesensor", "batterylevel", "wirelessconnectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "a866df99-7e2a-40e1-b82e-529c03846d5e",
|
||||
"name": "ieeeAddress",
|
||||
"displayName": "IEEE adress",
|
||||
"type": "QString",
|
||||
"defaultValue": "00:00:00:00:00:00:00:00"
|
||||
},
|
||||
{
|
||||
"id": "99f4ff28-6d61-4e96-bfc4-c32aa05bb256",
|
||||
"name": "networkUuid",
|
||||
"displayName": "Zigbee network UUID",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "0d0a5ee1-41f2-4b5a-a3c0-7c8cca1c064d",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"cached": false,
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "d4f85c34-896a-4bab-af71-8b80d9889815",
|
||||
"name": "signalStrength",
|
||||
"displayName": "Signal strength",
|
||||
"displayNameEvent": "Signal strength changed",
|
||||
"defaultValue": 0,
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"type": "uint",
|
||||
"unit": "Percentage"
|
||||
},
|
||||
{
|
||||
"id": "18cb67e1-220f-41d7-9145-1816fc5d38d0",
|
||||
"name": "version",
|
||||
"displayName": "Version",
|
||||
"displayNameEvent": "Version changed",
|
||||
"type": "QString",
|
||||
"cached": true,
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "00a4450b-d2fe-4e2b-92c8-1ab3a98d1628",
|
||||
"name": "batteryLevel",
|
||||
"displayName": "Battery",
|
||||
"displayNameEvent": "Battery changed",
|
||||
"type": "int",
|
||||
"unit": "Percentage",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 100
|
||||
},
|
||||
{
|
||||
"id": "9341f65a-b0aa-4648-82eb-e8400779f817",
|
||||
"name": "batteryCritical",
|
||||
"displayName": "Battery critical",
|
||||
"displayNameEvent": "Battery critical changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "66e3b840-4f4c-4f4a-a71a-69fb751f2a3b",
|
||||
"name": "isPresent",
|
||||
"displayName": "Present",
|
||||
"displayNameEvent": "Present changed",
|
||||
"type": "bool",
|
||||
"defaultValue": true,
|
||||
"ioType": "digitalInput"
|
||||
},
|
||||
{
|
||||
"id": "128777a9-75e7-4cc6-b196-691d2ffddbc9",
|
||||
"name": "lastSeenTime",
|
||||
"displayName": "Last seen time",
|
||||
"displayNameEvent": "Last seen time changed",
|
||||
"type": "int",
|
||||
"unit": "UnixTime",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "8077e335-1d18-4e3f-9b5e-6f71af4a33b1",
|
||||
"name": "lightIntensity",
|
||||
"displayName": "Light intensity",
|
||||
"displayNameEvent": "Light intensity changed",
|
||||
"type": "double",
|
||||
"unit": "Lux",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "978f069c-57c0-4e73-a81b-c593bc2e7624",
|
||||
"name": "temperature",
|
||||
"displayName": "Temperature",
|
||||
"displayNameEvent": "Temperature changed",
|
||||
"type": "double",
|
||||
"unit": "DegreeCelsius",
|
||||
"defaultValue": 0.0
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
|
||||
],
|
||||
"eventTypes": [
|
||||
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -36,15 +36,19 @@
|
||||
IntegrationPluginZigbeePhilipsHue::IntegrationPluginZigbeePhilipsHue()
|
||||
{
|
||||
m_ieeeAddressParamTypeIds[dimmerSwitchThingClassId] = dimmerSwitchThingIeeeAddressParamTypeId;
|
||||
m_ieeeAddressParamTypeIds[outdoorSensorThingClassId] = outdoorSensorThingIeeeAddressParamTypeId;
|
||||
|
||||
m_networkUuidParamTypeIds[dimmerSwitchThingClassId] = dimmerSwitchThingNetworkUuidParamTypeId;
|
||||
m_networkUuidParamTypeIds[outdoorSensorThingClassId] = outdoorSensorThingNetworkUuidParamTypeId;
|
||||
|
||||
m_connectedStateTypeIds[dimmerSwitchThingClassId] = dimmerSwitchConnectedStateTypeId;
|
||||
m_connectedStateTypeIds[outdoorSensorThingClassId] = outdoorSensorConnectedStateTypeId;
|
||||
|
||||
m_signalStrengthStateTypeIds[dimmerSwitchThingClassId] = dimmerSwitchSignalStrengthStateTypeId;
|
||||
m_signalStrengthStateTypeIds[outdoorSensorThingClassId] = outdoorSensorSignalStrengthStateTypeId;
|
||||
|
||||
m_versionStateTypeIds[dimmerSwitchThingClassId] = dimmerSwitchVersionStateTypeId;
|
||||
|
||||
m_versionStateTypeIds[outdoorSensorThingClassId] = outdoorSensorVersionStateTypeId;
|
||||
}
|
||||
|
||||
QString IntegrationPluginZigbeePhilipsHue::name() const
|
||||
@ -66,8 +70,8 @@ bool IntegrationPluginZigbeePhilipsHue::handleNode(ZigbeeNode *node, const QUuid
|
||||
|
||||
// Dimmer switch
|
||||
if (endpointOne->profile() == Zigbee::ZigbeeProfileLightLink &&
|
||||
endpointOne->deviceId() == Zigbee::LightLinkDeviceNonColourSceneController
|
||||
&& endpoinTwo->profile() == Zigbee::ZigbeeProfileHomeAutomation &&
|
||||
endpointOne->deviceId() == Zigbee::LightLinkDeviceNonColourSceneController &&
|
||||
endpoinTwo->profile() == Zigbee::ZigbeeProfileHomeAutomation &&
|
||||
endpoinTwo->deviceId() == Zigbee::HomeAutomationDeviceSimpleSensor) {
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Handeling Hue dimmer switch" << node << endpointOne << endpoinTwo;
|
||||
@ -75,6 +79,18 @@ bool IntegrationPluginZigbeePhilipsHue::handleNode(ZigbeeNode *node, const QUuid
|
||||
initDimmerSwitch(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Outdoor sensor
|
||||
if (endpointOne->profile() == Zigbee::ZigbeeProfileLightLink &&
|
||||
endpointOne->deviceId() == Zigbee::LightLinkDeviceOnOffSensor &&
|
||||
endpoinTwo->profile() == Zigbee::ZigbeeProfileHomeAutomation &&
|
||||
endpoinTwo->deviceId() == Zigbee::HomeAutomationDeviceOccupacySensor) {
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Handeling Hue outdoor sensor" << node << endpointOne << endpoinTwo;
|
||||
createThing(outdoorSensorThingClassId, networkUuid, node);
|
||||
initOutdoorSensor(node);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
@ -124,7 +140,6 @@ void IntegrationPluginZigbeePhilipsHue::setupThing(ThingSetupInfo *info)
|
||||
thing->setStateValue(m_signalStrengthStateTypeIds.value(thing->thingClassId()), signalStrength);
|
||||
});
|
||||
|
||||
|
||||
// Thing specific setup
|
||||
if (thing->thingClassId() == dimmerSwitchThingClassId) {
|
||||
ZigbeeNodeEndpoint *endpointZll = node->getEndpoint(0x01);
|
||||
@ -133,7 +148,6 @@ void IntegrationPluginZigbeePhilipsHue::setupThing(ThingSetupInfo *info)
|
||||
// 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) {
|
||||
@ -191,6 +205,81 @@ void IntegrationPluginZigbeePhilipsHue::setupThing(ThingSetupInfo *info)
|
||||
thing->setStateValue(dimmerSwitchBatteryCriticalStateTypeId, (percentage < 10.0));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == outdoorSensorThingClassId) {
|
||||
ZigbeeNodeEndpoint *endpointHa = node->getEndpoint(0x02);
|
||||
|
||||
// Set the version
|
||||
thing->setStateValue(m_versionStateTypeIds.value(thing->thingClassId()), endpointHa->softwareBuildId());
|
||||
|
||||
// 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(outdoorSensorBatteryLevelStateTypeId, powerCluster->batteryPercentage());
|
||||
thing->setStateValue(outdoorSensorBatteryCriticalStateTypeId, (powerCluster->batteryPercentage() < 10.0));
|
||||
}
|
||||
|
||||
connect(powerCluster, &ZigbeeClusterPowerConfiguration::batteryPercentageChanged, thing, [=](double percentage){
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Battery percentage changed" << percentage << "%" << thing;
|
||||
thing->setStateValue(outdoorSensorBatteryLevelStateTypeId, percentage);
|
||||
thing->setStateValue(outdoorSensorBatteryCriticalStateTypeId, (percentage < 10.0));
|
||||
});
|
||||
}
|
||||
|
||||
ZigbeeClusterOccupancySensing *occupancyCluster = endpointHa->inputCluster<ZigbeeClusterOccupancySensing>(ZigbeeClusterLibrary::ClusterIdOccupancySensing);
|
||||
if (!occupancyCluster) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Occupancy cluster not found on" << thing;
|
||||
} else {
|
||||
if (occupancyCluster->hasAttribute(ZigbeeClusterOccupancySensing::AttributeOccupancy)) {
|
||||
thing->setStateValue(outdoorSensorIsPresentStateTypeId, occupancyCluster->occupied());
|
||||
thing->setStateValue(outdoorSensorLastSeenTimeStateTypeId, QDateTime::currentMSecsSinceEpoch() / 1000);
|
||||
}
|
||||
|
||||
connect(occupancyCluster, &ZigbeeClusterOccupancySensing::occupancyChanged, thing, [thing](bool occupancy){
|
||||
qCDebug(dcZigbeePhilipsHue()) << "occupancy changed" << occupancy;
|
||||
// Only change the state if the it changed to true, it will be disabled by the timer
|
||||
if (occupancy) {
|
||||
thing->setStateValue(outdoorSensorIsPresentStateTypeId, occupancy);
|
||||
//m_presenceTimer->start();
|
||||
}
|
||||
thing->setStateValue(outdoorSensorLastSeenTimeStateTypeId, QDateTime::currentMSecsSinceEpoch() / 1000);
|
||||
});
|
||||
|
||||
// if (!m_presenceTimer) {
|
||||
// m_presenceTimer = hardwareManager()->pluginTimerManager()->registerTimer(1);
|
||||
// }
|
||||
|
||||
// connect(m_presenceTimer, &PluginTimer::timeout, thing, [thing](){
|
||||
// if (thing->stateValue(outdoorSensorIsPresentStateTypeId).toBool()) {
|
||||
// int timeout = thing->setting(outdoorSensorSettingsTimeoutParamTypeId).toInt();
|
||||
// QDateTime lastSeenTime = QDateTime::fromMSecsSinceEpoch(thing->stateValue(lumiMotionSensorLastSeenTimeStateTypeId).toULongLong() * 1000);
|
||||
// if (lastSeenTime.addSecs(timeout) < QDateTime::currentDateTime()) {
|
||||
// thing->setStateValue(lumiMotionSensorIsPresentStateTypeId, false);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
ZigbeeClusterTemperatureMeasurement *temperatureCluster = endpointHa->inputCluster<ZigbeeClusterTemperatureMeasurement>(ZigbeeClusterLibrary::ClusterIdTemperatureMeasurement);
|
||||
if (!temperatureCluster) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Could not find the temperature measurement server cluster on" << thing << endpointHa;
|
||||
} else {
|
||||
// Only set the state if the cluster actually has the attribute
|
||||
if (temperatureCluster->hasAttribute(ZigbeeClusterTemperatureMeasurement::AttributeMeasuredValue)) {
|
||||
thing->setStateValue(outdoorSensorTemperatureStateTypeId, temperatureCluster->temperature());
|
||||
}
|
||||
|
||||
connect(temperatureCluster, &ZigbeeClusterTemperatureMeasurement::temperatureChanged, thing, [thing](double temperature){
|
||||
qCDebug(dcZigbeePhilipsHue()) << thing << "temperature changed" << temperature << "°C";
|
||||
thing->setStateValue(outdoorSensorTemperatureStateTypeId, temperature);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -319,3 +408,149 @@ void IntegrationPluginZigbeePhilipsHue::initDimmerSwitch(ZigbeeNode *node)
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeePhilipsHue::initOutdoorSensor(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();
|
||||
} else {
|
||||
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();
|
||||
} else {
|
||||
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();
|
||||
} else {
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Attribute reporting configuration finished for power cluster" << ZigbeeClusterLibrary::parseAttributeReportingStatusRecords(reportingReply->responseFrame().payload);
|
||||
}
|
||||
|
||||
|
||||
// Init occupancy sensing cluster
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind occupancy cluster to coordinator IEEE address";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindIeeeAddress(endpointHa->endpointId(), ZigbeeClusterLibrary::ClusterIdOccupancySensing,
|
||||
hardwareManager()->zigbeeResource()->coordinatorAddress(node->networkUuid()), 0x01);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to bind occupancy cluster to coordinator" << zdoReply->error();
|
||||
} else {
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind occupency cluster to coordinator finished successfully";
|
||||
}
|
||||
|
||||
|
||||
// Configure attribute reporting for temperature
|
||||
ZigbeeClusterLibrary::AttributeReportingConfiguration reportingConfig;
|
||||
reportingConfig.attributeId = ZigbeeClusterTemperatureMeasurement::AttributeMeasuredValue;
|
||||
reportingConfig.dataType = Zigbee::BitMap8;
|
||||
reportingConfig.minReportingInterval = 1;
|
||||
reportingConfig.maxReportingInterval = 10;
|
||||
reportingConfig.reportableChange = ZigbeeDataType(static_cast<quint8>(1)).data();
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Configure attribute reporting for occupancy cluster to coordinator";
|
||||
ZigbeeClusterReply *reportingReply = endpointHa->getInputCluster(ZigbeeClusterLibrary::ClusterIdOccupancySensing)->configureReporting({reportingConfig});
|
||||
connect(reportingReply, &ZigbeeClusterReply::finished, this, [=](){
|
||||
if (reportingReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to configure occupancy cluster attribute reporting" << reportingReply->error();
|
||||
} else {
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Attribute reporting configuration finished for occupancy cluster" << ZigbeeClusterLibrary::parseAttributeReportingStatusRecords(reportingReply->responseFrame().payload);
|
||||
}
|
||||
|
||||
|
||||
// Init temperature measurment cluster
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind temperature cluster to coordinator IEEE address";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindIeeeAddress(endpointHa->endpointId(), ZigbeeClusterLibrary::ClusterIdTemperatureMeasurement,
|
||||
hardwareManager()->zigbeeResource()->coordinatorAddress(node->networkUuid()), 0x01);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to bind temperature cluster to coordinator" << zdoReply->error();
|
||||
} else {
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Bind temperature cluster to coordinator finished successfully";
|
||||
}
|
||||
|
||||
// Read current temperature
|
||||
if (!endpointHa->hasInputCluster(ZigbeeClusterLibrary::ClusterIdTemperatureMeasurement)) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to initialize the temperature cluster because the cluster could not be found" << node << endpointHa;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Read temperature cluster attributes" << node;
|
||||
ZigbeeClusterReply *readAttributeReply = endpointHa->getInputCluster(ZigbeeClusterLibrary::ClusterIdTemperatureMeasurement)->readAttributes({ZigbeeClusterTemperatureMeasurement::AttributeMeasuredValue});
|
||||
connect(readAttributeReply, &ZigbeeClusterReply::finished, node, [=](){
|
||||
if (readAttributeReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to read temperature cluster attributes" << readAttributeReply->error();
|
||||
} else {
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Read temperature cluster attributes finished successfully";
|
||||
}
|
||||
|
||||
// Configure attribute reporting
|
||||
|
||||
// Configure attribute reporting for temperature
|
||||
ZigbeeClusterLibrary::AttributeReportingConfiguration reportingConfig;
|
||||
reportingConfig.attributeId = ZigbeeClusterTemperatureMeasurement::AttributeMeasuredValue;
|
||||
reportingConfig.dataType = Zigbee::Int16;
|
||||
reportingConfig.minReportingInterval = 300;
|
||||
reportingConfig.maxReportingInterval = 600;
|
||||
reportingConfig.reportableChange = ZigbeeDataType(static_cast<qint16>(10)).data();
|
||||
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Configure attribute reporting for temperature cluster to coordinator";
|
||||
ZigbeeClusterReply *reportingReply = endpointHa->getInputCluster(ZigbeeClusterLibrary::ClusterIdTemperatureMeasurement)->configureReporting({reportingConfig});
|
||||
connect(reportingReply, &ZigbeeClusterReply::finished, this, [=](){
|
||||
if (reportingReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeePhilipsHue()) << "Failed to configure temperature cluster attribute reporting" << reportingReply->error();
|
||||
} else {
|
||||
qCDebug(dcZigbeePhilipsHue()) << "Attribute reporting configuration finished for temperature cluster" << ZigbeeClusterLibrary::parseAttributeReportingStatusRecords(reportingReply->responseFrame().payload);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -70,6 +70,7 @@ private:
|
||||
void createThing(const ThingClassId &thingClassId, const QUuid &networkUuid, ZigbeeNode *node);
|
||||
|
||||
void initDimmerSwitch(ZigbeeNode *node);
|
||||
void initOutdoorSensor(ZigbeeNode *node);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -350,6 +350,74 @@
|
||||
],
|
||||
"eventTypes": [
|
||||
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "signalRepeater",
|
||||
"displayName": "TRÅDFRI signal repeater",
|
||||
"id": "ac51f426-195e-472a-837f-4ba7e4666e6e",
|
||||
"setupMethod": "JustAdd",
|
||||
"createMethods": [ "Auto" ],
|
||||
"interfaces": [ "wirelessconnectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "fcaf0646-ef18-4e16-afde-39823437b7f4",
|
||||
"name": "ieeeAddress",
|
||||
"displayName": "IEEE adress",
|
||||
"type": "QString",
|
||||
"defaultValue": "00:00:00:00:00:00:00:00"
|
||||
},
|
||||
{
|
||||
"id": "5ce9a369-545b-4848-a6d7-6d3bc40779a2",
|
||||
"name": "networkUuid",
|
||||
"displayName": "Zigbee network UUID",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "3ff01f62-83dc-4856-a7f0-5605091845cc",
|
||||
"name": "endpointId",
|
||||
"displayName": "Endpoint ID",
|
||||
"type": "uint",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "7415ea93-9b72-4740-b3b1-a2ebb73d1db5",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"cached": false,
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"id": "05758f08-33a8-485b-8572-f87021e3af36",
|
||||
"name": "signalStrength",
|
||||
"displayName": "Signal strength",
|
||||
"displayNameEvent": "Signal strength changed",
|
||||
"defaultValue": 0,
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"type": "uint",
|
||||
"unit": "Percentage"
|
||||
},
|
||||
{
|
||||
"id": "a7ad66f1-7b4c-4458-8a13-e1bb9467bc17",
|
||||
"name": "version",
|
||||
"displayName": "Version",
|
||||
"displayNameEvent": "Version changed",
|
||||
"type": "QString",
|
||||
"cached": true,
|
||||
"defaultValue": ""
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
|
||||
],
|
||||
"eventTypes": [
|
||||
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -39,26 +39,32 @@ IntegrationPluginZigbeeTradfri::IntegrationPluginZigbeeTradfri()
|
||||
m_ieeeAddressParamTypeIds[onOffSwitchThingClassId] = onOffSwitchThingIeeeAddressParamTypeId;
|
||||
m_ieeeAddressParamTypeIds[remoteThingClassId] = remoteThingIeeeAddressParamTypeId;
|
||||
m_ieeeAddressParamTypeIds[motionSensorThingClassId] = motionSensorThingIeeeAddressParamTypeId;
|
||||
m_ieeeAddressParamTypeIds[signalRepeaterThingClassId] = signalRepeaterThingIeeeAddressParamTypeId;
|
||||
|
||||
m_networkUuidParamTypeIds[onOffSwitchThingClassId] = onOffSwitchThingNetworkUuidParamTypeId;
|
||||
m_networkUuidParamTypeIds[remoteThingClassId] = remoteThingNetworkUuidParamTypeId;
|
||||
m_networkUuidParamTypeIds[motionSensorThingClassId] = motionSensorThingNetworkUuidParamTypeId;
|
||||
m_networkUuidParamTypeIds[signalRepeaterThingClassId] = signalRepeaterThingNetworkUuidParamTypeId;
|
||||
|
||||
m_endpointIdParamTypeIds[onOffSwitchThingClassId] = onOffSwitchThingEndpointIdParamTypeId;
|
||||
m_endpointIdParamTypeIds[remoteThingClassId] = remoteThingEndpointIdParamTypeId;
|
||||
m_endpointIdParamTypeIds[motionSensorThingClassId] = motionSensorThingEndpointIdParamTypeId;
|
||||
m_endpointIdParamTypeIds[signalRepeaterThingClassId] = signalRepeaterThingEndpointIdParamTypeId;
|
||||
|
||||
m_connectedStateTypeIds[onOffSwitchThingClassId] = onOffSwitchConnectedStateTypeId;
|
||||
m_connectedStateTypeIds[remoteThingClassId] = remoteConnectedStateTypeId;
|
||||
m_connectedStateTypeIds[motionSensorThingClassId] = motionSensorConnectedStateTypeId;
|
||||
m_connectedStateTypeIds[signalRepeaterThingClassId] = signalRepeaterConnectedStateTypeId;
|
||||
|
||||
m_signalStrengthStateTypeIds[onOffSwitchThingClassId] = onOffSwitchSignalStrengthStateTypeId;
|
||||
m_signalStrengthStateTypeIds[remoteThingClassId] = remoteSignalStrengthStateTypeId;
|
||||
m_signalStrengthStateTypeIds[motionSensorThingClassId] = motionSensorSignalStrengthStateTypeId;
|
||||
m_signalStrengthStateTypeIds[signalRepeaterThingClassId] = signalRepeaterSignalStrengthStateTypeId;
|
||||
|
||||
m_versionStateTypeIds[onOffSwitchThingClassId] = onOffSwitchVersionStateTypeId;
|
||||
m_versionStateTypeIds[remoteThingClassId] = remoteVersionStateTypeId;
|
||||
m_versionStateTypeIds[motionSensorThingClassId] = motionSensorVersionStateTypeId;
|
||||
m_versionStateTypeIds[signalRepeaterThingClassId] = signalRepeaterVersionStateTypeId;
|
||||
}
|
||||
|
||||
QString IntegrationPluginZigbeeTradfri::name() const
|
||||
@ -84,29 +90,20 @@ bool IntegrationPluginZigbeeTradfri::handleNode(ZigbeeNode *node, const QUuid &n
|
||||
if (endpoint->profile() == Zigbee::ZigbeeProfileHomeAutomation && endpoint->deviceId() == Zigbee::HomeAutomationDeviceOnOffSensor) {
|
||||
qCDebug(dcZigbeeTradfri()) << "Handeling TRADFRI motion sensor" << node << endpoint;
|
||||
createThing(motionSensorThingClassId, networkUuid, node, endpoint);
|
||||
initMotionSensor(node, endpoint);
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (endpoint->profile() == Zigbee::ZigbeeProfileLightLink && endpoint->deviceId() == Zigbee::LightLinkDeviceNonColourSceneController) {
|
||||
qCDebug(dcZigbeeTradfri()) << "Handeling TRADFRI remote control" << node << endpoint;
|
||||
createThing(remoteThingClassId, networkUuid, node, endpoint);
|
||||
|
||||
// ZigbeeClusterBasic *basicCluster = endpoint->inputCluster<ZigbeeClusterBasic>(ZigbeeClusterLibrary::ClusterIdBasic);
|
||||
// if (!basicCluster) {
|
||||
// qCWarning(dcZigbeeTradfri()) << "Failed to find basic cluster for performing factory reset to defaults";
|
||||
// initRemote(node, endpoint);
|
||||
// } else {
|
||||
// ZigbeeClusterReply *zclReply = basicCluster->resetToFactoryDefaults();
|
||||
// connect(zclReply, &ZigbeeClusterReply::finished, node, [=](){
|
||||
// if (zclReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
// qCWarning(dcZigbeeTradfri()) << "Failed to perform factory reset on basic cluster on" << endpoint;
|
||||
// }
|
||||
|
||||
// initRemote(node, endpoint);
|
||||
// });
|
||||
// }
|
||||
initRemote(node, endpoint);
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (endpoint->profile() == Zigbee::ZigbeeProfileHomeAutomation && endpoint->deviceId() == Zigbee::HomeAutomationDeviceRangeExtender) {
|
||||
qCDebug(dcZigbeeTradfri()) << "Handeling TRADFRI signal repeater" << node << endpoint;
|
||||
createThing(signalRepeaterThingClassId, networkUuid, node, endpoint);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
@ -170,6 +167,24 @@ void IntegrationPluginZigbeeTradfri::setupThing(ThingSetupInfo *info)
|
||||
|
||||
// Thing specific setup
|
||||
if (thing->thingClassId() == onOffSwitchThingClassId) {
|
||||
// Get battery level changes
|
||||
ZigbeeClusterPowerConfiguration *powerCluster = endpoint->inputCluster<ZigbeeClusterPowerConfiguration>(ZigbeeClusterLibrary::ClusterIdPowerConfiguration);
|
||||
if (!powerCluster) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Could not find power configuration cluster on" << thing << endpoint;
|
||||
} else {
|
||||
// Only set the initial state if the attribute already exists
|
||||
if (powerCluster->hasAttribute(ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining)) {
|
||||
thing->setStateValue(onOffSwitchBatteryLevelStateTypeId, powerCluster->batteryPercentage());
|
||||
thing->setStateValue(onOffSwitchBatteryCriticalStateTypeId, (powerCluster->batteryPercentage() < 10.0));
|
||||
}
|
||||
|
||||
connect(powerCluster, &ZigbeeClusterPowerConfiguration::batteryPercentageChanged, thing, [=](double percentage){
|
||||
qCDebug(dcZigbeeTradfri()) << "Battery percentage changed" << percentage << "%" << thing;
|
||||
thing->setStateValue(onOffSwitchBatteryLevelStateTypeId, percentage);
|
||||
thing->setStateValue(onOffSwitchBatteryCriticalStateTypeId, (percentage < 10.0));
|
||||
});
|
||||
}
|
||||
|
||||
// Receive on/off commands
|
||||
ZigbeeClusterOnOff *onOffCluster = endpoint->outputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
|
||||
if (!onOffCluster) {
|
||||
@ -208,7 +223,9 @@ void IntegrationPluginZigbeeTradfri::setupThing(ThingSetupInfo *info)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == motionSensorThingClassId) {
|
||||
// Get battery level changes
|
||||
ZigbeeClusterPowerConfiguration *powerCluster = endpoint->inputCluster<ZigbeeClusterPowerConfiguration>(ZigbeeClusterLibrary::ClusterIdPowerConfiguration);
|
||||
if (!powerCluster) {
|
||||
@ -216,19 +233,17 @@ void IntegrationPluginZigbeeTradfri::setupThing(ThingSetupInfo *info)
|
||||
} else {
|
||||
// Only set the initial state if the attribute already exists
|
||||
if (powerCluster->hasAttribute(ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining)) {
|
||||
thing->setStateValue(onOffSwitchBatteryLevelStateTypeId, powerCluster->batteryPercentage());
|
||||
thing->setStateValue(onOffSwitchBatteryCriticalStateTypeId, (powerCluster->batteryPercentage() < 10.0));
|
||||
thing->setStateValue(motionSensorBatteryLevelStateTypeId, powerCluster->batteryPercentage());
|
||||
thing->setStateValue(motionSensorBatteryCriticalStateTypeId, (powerCluster->batteryPercentage() < 10.0));
|
||||
}
|
||||
|
||||
connect(powerCluster, &ZigbeeClusterPowerConfiguration::batteryPercentageChanged, thing, [=](double percentage){
|
||||
qCDebug(dcZigbeeTradfri()) << "Battery percentage changed" << percentage << "%" << thing;
|
||||
thing->setStateValue(onOffSwitchBatteryLevelStateTypeId, percentage);
|
||||
thing->setStateValue(onOffSwitchBatteryCriticalStateTypeId, (percentage < 10.0));
|
||||
thing->setStateValue(motionSensorBatteryLevelStateTypeId, percentage);
|
||||
thing->setStateValue(motionSensorBatteryCriticalStateTypeId, (percentage < 10.0));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == motionSensorThingClassId) {
|
||||
// Create plugintimer if required
|
||||
if (!m_presenceTimer) {
|
||||
m_presenceTimer = hardwareManager()->pluginTimerManager()->registerTimer(1);
|
||||
@ -255,41 +270,9 @@ void IntegrationPluginZigbeeTradfri::setupThing(ThingSetupInfo *info)
|
||||
m_presenceTimer->start();
|
||||
});
|
||||
}
|
||||
|
||||
// Get battery level changes
|
||||
ZigbeeClusterPowerConfiguration *powerCluster = endpoint->inputCluster<ZigbeeClusterPowerConfiguration>(ZigbeeClusterLibrary::ClusterIdPowerConfiguration);
|
||||
if (!powerCluster) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Could not find power configuration cluster on" << thing << endpoint;
|
||||
} else {
|
||||
// Only set the initial state if the attribute already exists
|
||||
if (powerCluster->hasAttribute(ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining)) {
|
||||
thing->setStateValue(motionSensorBatteryLevelStateTypeId, powerCluster->batteryPercentage());
|
||||
thing->setStateValue(motionSensorBatteryCriticalStateTypeId, (powerCluster->batteryPercentage() < 10.0));
|
||||
}
|
||||
|
||||
connect(powerCluster, &ZigbeeClusterPowerConfiguration::batteryPercentageChanged, thing, [=](double percentage){
|
||||
qCDebug(dcZigbeeTradfri()) << "Battery percentage changed" << percentage << "%" << thing;
|
||||
thing->setStateValue(motionSensorBatteryLevelStateTypeId, percentage);
|
||||
thing->setStateValue(motionSensorBatteryCriticalStateTypeId, (percentage < 10.0));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == remoteThingClassId) {
|
||||
// Receive on/off commands
|
||||
ZigbeeClusterOnOff *onOffCluster = endpoint->outputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
|
||||
if (!onOffCluster) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Could not find on/off client cluster on" << thing << endpoint;
|
||||
} else {
|
||||
connect(onOffCluster, &ZigbeeClusterOnOff::commandSent, thing, [=](ZigbeeClusterOnOff::Command command){
|
||||
qCDebug(dcZigbeeTradfri()) << thing << "button pressed" << command;
|
||||
if (command == ZigbeeClusterOnOff::CommandToggle) {
|
||||
qCDebug(dcZigbeeTradfri()) << thing << "pressed power";
|
||||
emit emitEvent(Event(remotePressedEventTypeId, thing->id(), ParamList() << Param(remotePressedEventButtonNameParamTypeId, "Power")));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Get battery level changes
|
||||
ZigbeeClusterPowerConfiguration *powerCluster = endpoint->inputCluster<ZigbeeClusterPowerConfiguration>(ZigbeeClusterLibrary::ClusterIdPowerConfiguration);
|
||||
if (!powerCluster) {
|
||||
@ -307,6 +290,20 @@ void IntegrationPluginZigbeeTradfri::setupThing(ThingSetupInfo *info)
|
||||
thing->setStateValue(remoteBatteryCriticalStateTypeId, (percentage < 10.0));
|
||||
});
|
||||
}
|
||||
|
||||
// Receive on/off commands
|
||||
ZigbeeClusterOnOff *onOffCluster = endpoint->outputCluster<ZigbeeClusterOnOff>(ZigbeeClusterLibrary::ClusterIdOnOff);
|
||||
if (!onOffCluster) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Could not find on/off client cluster on" << thing << endpoint;
|
||||
} else {
|
||||
connect(onOffCluster, &ZigbeeClusterOnOff::commandSent, thing, [=](ZigbeeClusterOnOff::Command command){
|
||||
qCDebug(dcZigbeeTradfri()) << thing << "button pressed" << command;
|
||||
if (command == ZigbeeClusterOnOff::CommandToggle) {
|
||||
qCDebug(dcZigbeeTradfri()) << thing << "pressed power";
|
||||
emit emitEvent(Event(remotePressedEventTypeId, thing->id(), ParamList() << Param(remotePressedEventButtonNameParamTypeId, "Power")));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
@ -538,94 +535,74 @@ void IntegrationPluginZigbeeTradfri::initRemote(ZigbeeNode *node, ZigbeeNodeEndp
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeeTradfri::readBindings(ZigbeeNode *node)
|
||||
void IntegrationPluginZigbeeTradfri::initMotionSensor(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint)
|
||||
{
|
||||
qCDebug(dcZigbeeTradfri()) << "Read binding table from node" << node;
|
||||
ZigbeeReply *reply = node->readBindingTableEntries();
|
||||
// Get the current configured bindings for this node
|
||||
ZigbeeReply *reply = node->removeAllBindings();
|
||||
connect(reply, &ZigbeeReply::finished, node, [=](){
|
||||
if (reply->error() != ZigbeeReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to read binding table from" << node;
|
||||
} else {
|
||||
foreach (const ZigbeeDeviceProfile::BindingTableListRecord &binding, node->bindingTableRecords()) {
|
||||
qCDebug(dcZigbeeTradfri()) << node << binding;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (reply->error() != ZigbeeReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to remove all bindings for initialization of" << node;
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeeTradfri::initPowerConfigurationCluster(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint)
|
||||
{
|
||||
if (!endpoint->hasInputCluster(ZigbeeClusterLibrary::ClusterIdPowerConfiguration)) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to initialize the power configuration cluster because the cluster could not be found" << node << endpoint;
|
||||
return;
|
||||
}
|
||||
// Read battery, bind and configure attribute reporting for battery
|
||||
|
||||
qCDebug(dcZigbeeTradfri()) << "Read power configuration cluster attributes" << node;
|
||||
ZigbeeClusterReply *readAttributeReply = endpoint->getInputCluster(ZigbeeClusterLibrary::ClusterIdPowerConfiguration)->readAttributes({ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining});
|
||||
connect(readAttributeReply, &ZigbeeClusterReply::finished, node, [=](){
|
||||
if (readAttributeReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to read power cluster attributes" << readAttributeReply->error();
|
||||
//emit nodeInitialized(node);
|
||||
if (!endpoint->hasInputCluster(ZigbeeClusterLibrary::ClusterIdPowerConfiguration)) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to initialize the power configuration cluster because the cluster could not be found" << node << endpoint;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeTradfri()) << "Read power configuration cluster attributes finished successfully";
|
||||
// Bind the cluster to the coordinator
|
||||
qCDebug(dcZigbeeTradfri()) << "Bind power configuration cluster to coordinator IEEE address";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindIeeeAddress(endpoint->endpointId(), ZigbeeClusterLibrary::ClusterIdPowerConfiguration,
|
||||
hardwareManager()->zigbeeResource()->coordinatorAddress(node->networkUuid()), 0x01);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to bind power cluster to coordinator" << zdoReply->error();
|
||||
qCDebug(dcZigbeeTradfri()) << "Read power configuration cluster attributes" << node;
|
||||
ZigbeeClusterReply *readAttributeReply = endpoint->getInputCluster(ZigbeeClusterLibrary::ClusterIdPowerConfiguration)->readAttributes({ZigbeeClusterPowerConfiguration::AttributeBatteryPercentageRemaining});
|
||||
connect(readAttributeReply, &ZigbeeClusterReply::finished, node, [=](){
|
||||
if (readAttributeReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to read power cluster attributes" << readAttributeReply->error();
|
||||
//emit nodeInitialized(node);
|
||||
return;
|
||||
}
|
||||
qCDebug(dcZigbeeTradfri()) << "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(dcZigbeeTradfri()) << "Read power configuration cluster attributes finished successfully";
|
||||
|
||||
qCDebug(dcZigbeeTradfri()) << "Configure attribute reporting for power configuration cluster to coordinator";
|
||||
ZigbeeClusterReply *reportingReply = endpoint->getInputCluster(ZigbeeClusterLibrary::ClusterIdPowerConfiguration)->configureReporting({reportingConfig});
|
||||
connect(reportingReply, &ZigbeeClusterReply::finished, this, [reportingReply](){
|
||||
if (reportingReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to configure power cluster attribute reporting" << reportingReply->error();
|
||||
// Bind the cluster to the coordinator
|
||||
qCDebug(dcZigbeeTradfri()) << "Bind power configuration cluster to coordinator IEEE address";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindIeeeAddress(endpoint->endpointId(), ZigbeeClusterLibrary::ClusterIdPowerConfiguration,
|
||||
hardwareManager()->zigbeeResource()->coordinatorAddress(node->networkUuid()), 0x01);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to bind power cluster to coordinator" << zdoReply->error();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcZigbeeTradfri()) << "Bind power configuration cluster to coordinator finished successfully";
|
||||
|
||||
qCDebug(dcZigbeeTradfri()) << "Attribute reporting configuration finished for power cluster" << ZigbeeClusterLibrary::parseAttributeReportingStatusRecords(reportingReply->responseFrame().payload);
|
||||
// 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(dcZigbeeTradfri()) << "Configure attribute reporting for power configuration cluster to coordinator";
|
||||
ZigbeeClusterReply *reportingReply = endpoint->getInputCluster(ZigbeeClusterLibrary::ClusterIdPowerConfiguration)->configureReporting({reportingConfig});
|
||||
connect(reportingReply, &ZigbeeClusterReply::finished, this, [=](){
|
||||
if (reportingReply->error() != ZigbeeClusterReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to configure power cluster attribute reporting" << reportingReply->error();
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcZigbeeTradfri()) << "Attribute reporting configuration finished for power cluster" << ZigbeeClusterLibrary::parseAttributeReportingStatusRecords(reportingReply->responseFrame().payload);
|
||||
|
||||
qCDebug(dcZigbeeTradfri()) << "Bind power configuration cluster to coordinator";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindShortAddress(endpoint->endpointId(), ZigbeeClusterLibrary::ClusterIdOnOff, 0x0000);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to bind on/off cluster to coordinator" << zdoReply->error();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcZigbeeTradfri()) << "Bind on/off cluster to coordinator finished successfully";
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeeTradfri::initOnOffCluster(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint)
|
||||
{
|
||||
qCDebug(dcZigbeeTradfri()) << "Bind power configuration cluster to coordinator";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindShortAddress(endpoint->endpointId(), ZigbeeClusterLibrary::ClusterIdOnOff, 0x0000);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to bind on/off cluster to coordinator" << zdoReply->error();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcZigbeeTradfri()) << "Bind on/off cluster to coordinator finished successfully";
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginZigbeeTradfri::initLevelControlCluster(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint)
|
||||
{
|
||||
qCDebug(dcZigbeeTradfri()) << "Bind power level cluster to coordinator";
|
||||
ZigbeeDeviceObjectReply * zdoReply = node->deviceObject()->requestBindShortAddress(endpoint->endpointId(), ZigbeeClusterLibrary::ClusterIdLevelControl, 0x0000);
|
||||
connect(zdoReply, &ZigbeeDeviceObjectReply::finished, node, [=](){
|
||||
if (zdoReply->error() != ZigbeeDeviceObjectReply::ErrorNoError) {
|
||||
qCWarning(dcZigbeeTradfri()) << "Failed to bind level cluster to coordinator" << zdoReply->error();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcZigbeeTradfri()) << "Bind level cluster to coordinator finished successfully";
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -73,12 +73,7 @@ private:
|
||||
|
||||
void initOnOffSwitch(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
|
||||
void initRemote(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
|
||||
|
||||
void readBindings(ZigbeeNode *node);
|
||||
void initPowerConfigurationCluster(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
|
||||
void initOnOffCluster(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
|
||||
void initLevelControlCluster(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
|
||||
|
||||
void initMotionSensor(ZigbeeNode *node, ZigbeeNodeEndpoint *endpoint);
|
||||
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user