Skip to content

Commit 0f56415

Browse files
committed
Improve multi endpoint ZCL value handling
Some devices have the same clusters and attributes on multiple endpoints. This commit lets book keep the data specific for an endpoint.
1 parent edf380f commit 0f56415

File tree

9 files changed

+122
-100
lines changed

9 files changed

+122
-100
lines changed

bindings.cpp

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ void DeRestPluginPrivate::handleZclConfigureReportingResponseIndication(const de
473473
continue;
474474
}
475475

476-
DBG_Printf(DBG_INFO, "ZCL configure reporting rsp seq: %u 0x%016llX for cluster 0x%04X attr 0x%04X status 0x%02X\n", zclFrame.sequenceNumber(), ind.srcAddress().ext(), ind.clusterId(), val.attributeId, status);
476+
DBG_Printf(DBG_INFO, "ZCL configure reporting rsp seq: %u 0x%016llX for ep: 0x%02X cluster: 0x%04X attr: 0x%04X status: 0x%02X\n", zclFrame.sequenceNumber(), ind.srcAddress().ext(), ind.srcEndpoint(), ind.clusterId(), val.attributeId, status);
477477

478478
// mark as succefully configured
479479
if (status == deCONZ::ZclSuccessStatus)
@@ -496,10 +496,10 @@ void DeRestPluginPrivate::handleZclConfigureReportingResponseIndication(const de
496496
stream >> direction;
497497
stream >> attrId;
498498

499-
NodeValue &val = restNode->getZclValue(ind.clusterId(), attrId);
499+
NodeValue &val = restNode->getZclValue(ind.clusterId(), attrId, ind.srcEndpoint());
500500
if (val.zclSeqNum == zclFrame.sequenceNumber() && val.clusterId == ind.clusterId())
501501
{
502-
DBG_Printf(DBG_INFO, "ZCL configure reporting rsp seq: %u 0x%016llX for cluster 0x%04X attr 0x%04X status 0x%02X\n", zclFrame.sequenceNumber(), ind.srcAddress().ext(), ind.clusterId(), val.attributeId, status);
502+
DBG_Printf(DBG_INFO, "ZCL configure reporting rsp seq: %u 0x%016llX for ep: 0x%02X cluster: 0x%04X attr: 0x%04X status: 0x%02X\n", zclFrame.sequenceNumber(), ind.srcAddress().ext(), ind.srcEndpoint(), ind.clusterId(), val.attributeId, status);
503503

504504
if (status == deCONZ::ZclSuccessStatus)
505505
{
@@ -550,7 +550,7 @@ void DeRestPluginPrivate::handleBindAndUnbindRspIndication(const deCONZ::ApsData
550550

551551
if (status == deCONZ::ZdpSuccess)
552552
{
553-
DBG_Printf(DBG_INFO, "%s response success for 0x%016llx cluster 0x%04X\n", what, i->binding.srcAddress, i->binding.clusterId);
553+
DBG_Printf(DBG_INFO, "%s response success for 0x%016llx ep: 0x%02X cluster: 0x%04X\n", what, i->binding.srcAddress, i->binding.srcEndpoint, i->binding.clusterId);
554554
if (ind.clusterId() == ZDP_BIND_RSP_CLID)
555555
{
556556
if (sendConfigureReportingRequest(*i))
@@ -561,7 +561,7 @@ void DeRestPluginPrivate::handleBindAndUnbindRspIndication(const deCONZ::ApsData
561561
}
562562
else
563563
{
564-
DBG_Printf(DBG_INFO, "%s response failed with status 0x%02X for 0x%016llx cluster 0x%04X\n", what, status, i->binding.srcAddress, i->binding.clusterId);
564+
DBG_Printf(DBG_INFO, "%s response failed with status 0x%02X for 0x%016llx ep: 0x%02X cluster: 0x%04X\n", what, status, i->binding.srcAddress, i->binding.srcEndpoint, i->binding.clusterId);
565565
}
566566

567567
i->state = BindingTask::StateFinished;
@@ -692,7 +692,7 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt, const s
692692

693693
for (const ConfigureReportingRequest &rq : requests)
694694
{
695-
NodeValue &val = bt.restNode->getZclValue(bt.binding.clusterId, rq.attributeId);
695+
NodeValue &val = bt.restNode->getZclValue(bt.binding.clusterId, rq.attributeId, bt.binding.srcEndpoint);
696696
if (val.clusterId == bt.binding.clusterId)
697697
{
698698
// value exists
@@ -727,7 +727,7 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt, const s
727727
// values doesn't exist, create
728728
deCONZ::NumericUnion dummy;
729729
dummy.u64 = 0;
730-
bt.restNode->setZclValue(NodeValue::UpdateByZclReport, bt.binding.clusterId, rq.attributeId, dummy);
730+
bt.restNode->setZclValue(NodeValue::UpdateByZclReport, bt.binding.srcEndpoint, bt.binding.clusterId, rq.attributeId, dummy);
731731
val.zclSeqNum = zclSeqNum;
732732
val.minInterval = rq.minInterval;
733733
val.maxInterval = rq.maxInterval;
@@ -860,9 +860,9 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
860860
// add values if not already present
861861
deCONZ::NumericUnion dummy;
862862
dummy.u64 = 0;
863-
if (bt.restNode->getZclValue(bt.binding.clusterId, 0x0000).clusterId != bt.binding.clusterId)
863+
if (bt.restNode->getZclValue(bt.binding.clusterId, 0x0000, bt.binding.srcEndpoint).clusterId != bt.binding.clusterId)
864864
{
865-
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.clusterId, 0x0000, dummy);
865+
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.srcEndpoint, bt.binding.clusterId, 0x0000, dummy);
866866
}
867867

868868
rq.dataType = deCONZ::Zcl8BitBitMap;
@@ -879,9 +879,9 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
879879
const Sensor *sensor = static_cast<Sensor *>(bt.restNode);
880880
if (sensor && sensor->modelId().startsWith(QLatin1String("SML00"))) // Hue motion sensor
881881
{
882-
if (bt.restNode->getZclValue(bt.binding.clusterId, 0x0030).clusterId != bt.binding.clusterId)
882+
if (bt.restNode->getZclValue(bt.binding.clusterId, 0x0030, bt.binding.srcEndpoint).clusterId != bt.binding.clusterId)
883883
{
884-
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.clusterId, 0x0030, dummy);
884+
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.srcEndpoint, bt.binding.clusterId, 0x0030, dummy);
885885
}
886886
ConfigureReportingRequest rq2;
887887
rq2.dataType = deCONZ::Zcl8BitUint;
@@ -911,9 +911,9 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
911911
// add values if not already present
912912
deCONZ::NumericUnion dummy;
913913
dummy.u64 = 0;
914-
if (bt.restNode->getZclValue(bt.binding.clusterId, IAS_ZONE_CLUSTER_ATTR_ZONE_STATUS_ID).clusterId != bt.binding.clusterId)
914+
if (bt.restNode->getZclValue(bt.binding.clusterId, IAS_ZONE_CLUSTER_ATTR_ZONE_STATUS_ID, bt.binding.srcEndpoint).clusterId != bt.binding.clusterId)
915915
{
916-
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.clusterId, IAS_ZONE_CLUSTER_ATTR_ZONE_STATUS_ID, dummy);
916+
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.srcEndpoint, bt.binding.clusterId, IAS_ZONE_CLUSTER_ATTR_ZONE_STATUS_ID, dummy);
917917
}
918918
rq.minInterval = 1;
919919
rq.maxInterval = 300;
@@ -1166,12 +1166,12 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
11661166
// add values if not already present
11671167
deCONZ::NumericUnion dummy;
11681168
dummy.u64 = 0;
1169-
if (bt.restNode->getZclValue(POWER_CONFIGURATION_CLUSTER_ID, rq.attributeId).attributeId != rq.attributeId)
1169+
if (bt.restNode->getZclValue(POWER_CONFIGURATION_CLUSTER_ID, rq.attributeId, bt.binding.srcEndpoint).attributeId != rq.attributeId)
11701170
{
1171-
bt.restNode->setZclValue(NodeValue::UpdateInvalid, POWER_CONFIGURATION_CLUSTER_ID, rq.attributeId, dummy);
1171+
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.srcEndpoint, POWER_CONFIGURATION_CLUSTER_ID, rq.attributeId, dummy);
11721172
}
11731173

1174-
NodeValue &val = bt.restNode->getZclValue(POWER_CONFIGURATION_CLUSTER_ID, rq.attributeId);
1174+
NodeValue &val = bt.restNode->getZclValue(POWER_CONFIGURATION_CLUSTER_ID, rq.attributeId, bt.binding.srcEndpoint);
11751175

11761176
if (val.timestampLastReport.isValid() && (val.timestampLastReport.secsTo(now) < val.maxInterval * 1.5))
11771177
{
@@ -1441,17 +1441,17 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
14411441
deCONZ::NumericUnion dummy;
14421442
dummy.u64 = 0;
14431443
// add usertest value if not already present
1444-
if (bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x0032).attributeId != 0x0032)
1444+
if (bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x0032, bt.binding.srcEndpoint).attributeId != 0x0032)
14451445
{
1446-
bt.restNode->setZclValue(NodeValue::UpdateInvalid, BASIC_CLUSTER_ID, 0x0032, dummy);
1446+
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.srcEndpoint, BASIC_CLUSTER_ID, 0x0032, dummy);
14471447
}
14481448
// ledindication value if not already present
1449-
if (bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x0033).attributeId != 0x0033)
1449+
if (bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x0033, bt.binding.srcEndpoint).attributeId != 0x0033)
14501450
{
1451-
bt.restNode->setZclValue(NodeValue::UpdateInvalid, BASIC_CLUSTER_ID, 0x0033, dummy);
1451+
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.srcEndpoint, BASIC_CLUSTER_ID, 0x0033, dummy);
14521452
}
14531453

1454-
NodeValue &val = bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x0032);
1454+
NodeValue &val = bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x0032, bt.binding.srcEndpoint);
14551455

14561456
if (val.timestampLastReport.isValid() && (val.timestampLastReport.secsTo(now) < val.maxInterval * 1.5))
14571457
{
@@ -1485,12 +1485,12 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
14851485
deCONZ::NumericUnion dummy;
14861486
dummy.u64 = 0;
14871487
// 'sw build id' value if not already present
1488-
if (bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x4000).attributeId != 0x4000)
1488+
if (bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x4000, bt.binding.srcEndpoint).attributeId != 0x4000)
14891489
{
1490-
bt.restNode->setZclValue(NodeValue::UpdateInvalid, BASIC_CLUSTER_ID, 0x4000, dummy);
1490+
bt.restNode->setZclValue(NodeValue::UpdateInvalid, bt.binding.srcEndpoint, BASIC_CLUSTER_ID, 0x4000, dummy);
14911491
}
14921492

1493-
NodeValue &val = bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x4000);
1493+
NodeValue &val = bt.restNode->getZclValue(BASIC_CLUSTER_ID, 0x4000, bt.binding.srcEndpoint);
14941494

14951495
if (val.timestampLastReport.isValid() && (val.timestampLastReport.secsTo(now) < val.maxInterval * 1.5))
14961496
{
@@ -1521,8 +1521,8 @@ bool DeRestPluginPrivate::sendConfigureReportingRequest(BindingTask &bt)
15211521
val.u64 = 0;
15221522

15231523
// mark button event binding as resolved
1524-
sensor->setZclValue(NodeValue::UpdateByZclReport, VENDOR_CLUSTER_ID, 0x0000, val);
1525-
NodeValue &val2 = bt.restNode->getZclValue(VENDOR_CLUSTER_ID, 0x0000);
1524+
sensor->setZclValue(NodeValue::UpdateByZclReport, bt.binding.srcEndpoint, VENDOR_CLUSTER_ID, 0x0000, val);
1525+
NodeValue &val2 = bt.restNode->getZclValue(VENDOR_CLUSTER_ID, 0x0000, bt.binding.srcEndpoint);
15261526
if (val2.maxInterval == 0)
15271527
{
15281528
val2.maxInterval = 60 * 60 * 8; // prevent further check for 8 hours
@@ -2111,13 +2111,13 @@ bool DeRestPluginPrivate::checkSensorBindingsForAttributeReporting(Sensor *senso
21112111
if (val.timestampLastReport.isValid() &&
21122112
val.timestampLastReport.secsTo(now) < maxInterval) // got update in timely manner
21132113
{
2114-
DBG_Printf(DBG_INFO_L2, "binding for attribute reporting of cluster 0x%04X seems to be active\n", (*i));
2114+
DBG_Printf(DBG_INFO_L2, "binding for attribute reporting of ep: 0x%02X cluster 0x%04X seems to be active\n", val.endpoint, *i);
21152115
continue;
21162116
}
21172117

21182118
if (!sensor->node()->nodeDescriptor().receiverOnWhenIdle() && sensor->lastRx().secsTo(now) > 3)
21192119
{
2120-
DBG_Printf(DBG_INFO, "skip binding for attribute reporting of cluster 0x%04X (end-device might sleep)\n", (*i));
2120+
DBG_Printf(DBG_INFO, "skip binding for attribute reporting of ep: 0x%02X cluster 0x%04X (end-device might sleep)\n", val.endpoint, *i);
21212121
return false;
21222122
}
21232123

database.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2997,7 +2997,7 @@ static int sqliteLoadAllSensorsCallback(void *user, int ncols, char **colval , c
29972997
// TODO write and recover min/max to db
29982998
deCONZ::NumericUnion dummy;
29992999
dummy.u64 = 0;
3000-
sensor.setZclValue(NodeValue::UpdateInvalid, clusterId, 0x0000, dummy);
3000+
sensor.setZclValue(NodeValue::UpdateInvalid, sensor.fingerPrint().endpoint, clusterId, 0x0000, dummy);
30013001
NodeValue &val = sensor.getZclValue(clusterId, 0x0000);
30023002
val.minInterval = 1; // value used by Hue bridge
30033003
val.maxInterval = 300; // value used by Hue bridge

de_otau.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ void DeRestPluginPrivate::otauDataIndication(const deCONZ::ApsDataIndication &in
9494
deCONZ::NumericUnion val = {0};
9595
val.u32 = swVersion;
9696

97-
lightNode->setZclValue(NodeValue::UpdateByZclRead, OTAU_CLUSTER_ID, OTAU_SWVERSION_ID, val);
97+
lightNode->setZclValue(NodeValue::UpdateByZclRead, ind.srcEndpoint(), OTAU_CLUSTER_ID, OTAU_SWVERSION_ID, val);
9898

9999
if (lightNode->swBuildId().isEmpty())
100100
{

0 commit comments

Comments
 (0)