Skip to content

Commit

Permalink
Skip more legacy code for DDF devices (#7571)
Browse files Browse the repository at this point in the history
The old code loops over all sensors and lights until one is found which needs to be queried. With more DDFs this code uses more CPU since almost nothing is to be done here. The PR skips some parts for DDF devices and also breaks up the loops to only process max. 5 sensors and 5 lights at a time, so it scales independent of network size.
  • Loading branch information
manup committed Feb 3, 2024
1 parent 65ad66d commit 875e280
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 66 deletions.
5 changes: 5 additions & 0 deletions bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ bool DeRestPluginPrivate::readBindingTable(RestNodeBase *node, quint8 startIndex
if (node->mgmtBindSupported())
{
}
else if (!node->mgmtBindSupported())
{
node->clearRead(READ_BINDING_TABLE);
return false;
}
else if (existDevicesWithVendorCodeForMacPrefix(node->address(), VENDOR_DDEL))
{
}
Expand Down
147 changes: 81 additions & 66 deletions de_web_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9902,35 +9902,30 @@ bool DeRestPluginPrivate::processZclAttributes(LightNode *lightNode)

QTime tNow = QTime::currentTime();

if (lightNode->mustRead(READ_BINDING_TABLE) && tNow > lightNode->nextReadTime(READ_BINDING_TABLE))
const Device *device = static_cast<Device*>(lightNode->parentResource());
const bool devManaged = device && device->managed();

if (!devManaged)
{
if (readBindingTable(lightNode, 0))
if (lightNode->mustRead(READ_BINDING_TABLE) && tNow > lightNode->nextReadTime(READ_BINDING_TABLE))
{
// only read binding table once per node even if multiple devices/sensors are implemented
std::vector<LightNode>::iterator i = nodes.begin();
std::vector<LightNode>::iterator end = nodes.end();

for (; i != end; ++i)
if (readBindingTable(lightNode, 0))
{
if (i->address().ext() == lightNode->address().ext())
{
i->clearRead(READ_BINDING_TABLE);
}
lightNode->clearRead(READ_BINDING_TABLE);
processed++;
}
processed++;
}
}

if (lightNode->mustRead(READ_VENDOR_NAME) && tNow > lightNode->nextReadTime(READ_VENDOR_NAME))
{
if (!lightNode->manufacturer().isEmpty())
{
lightNode->clearRead(READ_VENDOR_NAME);
processed++;
}
else
if (lightNode->mustRead(READ_VENDOR_NAME) && tNow > lightNode->nextReadTime(READ_VENDOR_NAME))
{
std::vector<uint16_t> attributes;
if (!lightNode->manufacturer().isEmpty())
{
lightNode->clearRead(READ_VENDOR_NAME);
processed++;
}
else
{
std::vector<uint16_t> attributes;
attributes.push_back(0x0004); // Manufacturer name

if (readAttributes(lightNode, lightNode->haEndpoint().endpoint(), BASIC_CLUSTER_ID, attributes))
Expand All @@ -9948,15 +9943,16 @@ bool DeRestPluginPrivate::processZclAttributes(LightNode *lightNode)
lightNode->clearRead(READ_MODEL_ID);
processed++;
}
else
{
std::vector<uint16_t> attributes;
attributes.push_back(0x0005); // Model identifier

if (readAttributes(lightNode, lightNode->haEndpoint().endpoint(), BASIC_CLUSTER_ID, attributes))
else
{
lightNode->clearRead(READ_MODEL_ID);
processed++;
std::vector<uint16_t> attributes;
attributes.push_back(0x0005); // Model identifier

if (readAttributes(lightNode, lightNode->haEndpoint().endpoint(), BASIC_CLUSTER_ID, attributes))
{
lightNode->clearRead(READ_MODEL_ID);
processed++;
}
}
}
}
Expand Down Expand Up @@ -10000,6 +9996,11 @@ bool DeRestPluginPrivate::processZclAttributes(Sensor *sensorNode)

if (!sensorNode->node())
{
if (sensorNode->type().startsWith(QLatin1String("ZGP"))) // ZGP nothing to be done here
{
return false;
}

deCONZ::Node *node = getNodeForAddress(sensorNode->address().ext());
if (node)
{
Expand Down Expand Up @@ -10039,17 +10040,20 @@ bool DeRestPluginPrivate::processZclAttributes(Sensor *sensorNode)

QTime tNow = QTime::currentTime();

// FIXME: Need check that end device is awake.
const Device *device = static_cast<Device*>(sensorNode->parentResource());
const bool devManaged = device && device->managed();

if (sensorNode->mustRead(READ_BINDING_TABLE) && tNow > sensorNode->nextReadTime(READ_BINDING_TABLE))
if (!devManaged)
{
bool ok = false;
// only read binding table of chosen sensors
// whitelist by Model ID
if (sensorNode->manufacturer().startsWith(QLatin1String("BEGA")))
if (sensorNode->mustRead(READ_BINDING_TABLE) && tNow > sensorNode->nextReadTime(READ_BINDING_TABLE))
{
ok = true;
}
bool ok = false;
// only read binding table of chosen sensors
// whitelist by Model ID
if (sensorNode->manufacturer().startsWith(QLatin1String("BEGA")))
{
ok = true;
}

if (!ok)
{
Expand Down Expand Up @@ -10098,30 +10102,29 @@ bool DeRestPluginPrivate::processZclAttributes(Sensor *sensorNode)
}

if (sensorNode->mustRead(READ_SWBUILD_ID) && tNow > sensorNode->nextReadTime(READ_SWBUILD_ID))
{
std::vector<uint16_t> attributes;
attributes.push_back(0x4000); // Software build identifier

if (readAttributes(sensorNode, sensorNode->fingerPrint().endpoint, BASIC_CLUSTER_ID, attributes))
{
sensorNode->clearRead(READ_SWBUILD_ID);
processed++;
}
}

std::vector<uint16_t> attributes;
attributes.push_back(0x4000); // Software build identifier

if (sensorNode->mustRead(READ_OCCUPANCY_CONFIG) && tNow > sensorNode->nextReadTime(READ_OCCUPANCY_CONFIG))
{
if (sensorNode->modelId().startsWith(QLatin1String("lumi.sensor_motion")))
{
sensorNode->clearRead(READ_OCCUPANCY_CONFIG);
if (readAttributes(sensorNode, sensorNode->fingerPrint().endpoint, BASIC_CLUSTER_ID, attributes))
{
sensorNode->clearRead(READ_SWBUILD_ID);
processed++;
}
}
else

if (sensorNode->mustRead(READ_OCCUPANCY_CONFIG) && tNow > sensorNode->nextReadTime(READ_OCCUPANCY_CONFIG))
{
std::vector<uint16_t> attributes;
attributes.push_back(0x0010); // occupied to unoccupied delay
if (sensorNode->modelId().startsWith(QLatin1String("lumi.sensor_motion")))
{
sensorNode->clearRead(READ_OCCUPANCY_CONFIG);
}
else
{
std::vector<uint16_t> attributes;
attributes.push_back(0x0010); // occupied to unoccupied delay

if (readAttributes(sensorNode, sensorNode->fingerPrint().endpoint, OCCUPANCY_SENSING_CLUSTER_ID, attributes))
if (readAttributes(sensorNode, sensorNode->fingerPrint().endpoint, OCCUPANCY_SENSING_CLUSTER_ID, attributes))
{
sensorNode->clearRead(READ_OCCUPANCY_CONFIG);
processed++;
Expand Down Expand Up @@ -10211,16 +10214,20 @@ bool DeRestPluginPrivate::processZclAttributes(Sensor *sensorNode)
if (writeAttribute(sensorNode, sensorNode->fingerPrint().endpoint, XIAOMI_CLUSTER_ID, attr, VENDOR_XIAOMI))
{
sensorNode->setNextReadTime(WRITE_SENSITIVITY, tNow.addSecs(3300)); // Default special reporting intervall
processed++;
processed++;
}
}
}
}
else
{
sensorNode->clearRead(WRITE_SENSITIVITY);
else
{
sensorNode->clearRead(WRITE_SENSITIVITY);
}
}
}

// TODO(mpi): is following code already handled by DDF, so we can skip if devManaged?


if (sensorNode->mustRead(READ_THERMOSTAT_STATE) && tNow > sensorNode->nextReadTime(READ_THERMOSTAT_STATE))
{
std::vector<uint16_t> attributes;
Expand Down Expand Up @@ -10270,7 +10277,7 @@ bool DeRestPluginPrivate::processZclAttributes(Sensor *sensorNode)
}
}

if (sensorNode->mustRead(READ_BATTERY) && tNow > sensorNode->nextReadTime(READ_BATTERY))
if (!devManaged && sensorNode->mustRead(READ_BATTERY) && tNow > sensorNode->nextReadTime(READ_BATTERY))
{
std::vector<uint16_t> attributes;
attributes.push_back(0x0020); // battery level
Expand All @@ -10281,9 +10288,6 @@ bool DeRestPluginPrivate::processZclAttributes(Sensor *sensorNode)
}
}

auto *device = DEV_GetDevice(m_devices, sensorNode->address().ext());
const bool devManaged = device && device->managed();

if (!DEV_TestStrict() && !devManaged)
{
if (sensorNode->mustRead(READ_TIME) && tNow > sensorNode->nextReadTime(READ_TIME))
Expand Down Expand Up @@ -15712,6 +15716,8 @@ void DeRestPlugin::checkZclAttributeTimerFired()
return;
}

int count = 0;

if (d->lightAttrIter >= d->nodes.size())
{
d->lightAttrIter = 0;
Expand All @@ -15721,10 +15727,12 @@ void DeRestPlugin::checkZclAttributeTimerFired()
{
LightNode *lightNode = &d->nodes[d->lightAttrIter];
d->lightAttrIter++;
count++;

if (d->getUptime() < WARMUP_TIME)
{
// warmup phase
break;
}
else if (d->processZclAttributes(lightNode))
{
Expand All @@ -15733,13 +15741,17 @@ void DeRestPlugin::checkZclAttributeTimerFired()
d->processTasks();
break;
}

if (count > 5)
break;
}

if (d->sensorAttrIter >= d->sensors.size())
{
d->sensorAttrIter = 0;
}

count = 0;
while (d->sensorAttrIter < d->sensors.size())
{
Sensor *sensorNode = &d->sensors[d->sensorAttrIter];
Expand All @@ -15752,6 +15764,9 @@ void DeRestPlugin::checkZclAttributeTimerFired()
d->processTasks();
break;
}

if (count > 5)
break;
}

startZclAttributeTimer(checkZclAttributesDelay);
Expand Down

0 comments on commit 875e280

Please sign in to comment.