Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor poll scheduler legacy code vs. Device code #8074

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
410 changes: 91 additions & 319 deletions de_web_plugin.cpp

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion de_web_plugin_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -1321,7 +1321,6 @@ public Q_SLOTS:
void handleMacDataRequest(const deCONZ::NodeEvent &event);
void addLightNode(const deCONZ::Node *node);
void setLightNodeStaticCapabilities(LightNode *lightNode);
void updatedLightNodeEndpoint(const deCONZ::NodeEvent &event);
void nodeZombieStateChanged(const deCONZ::Node *node);
LightNode *updateLightNode(const deCONZ::NodeEvent &event);
LightNode *getLightNodeForAddress(const deCONZ::Address &addr, quint8 endpoint = 0);
Expand Down
17 changes: 12 additions & 5 deletions device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,10 @@ void DEV_InitStateHandler(Device *device, const Event &event)
if (event.what() == REventStateEnter)
{
d->zdpResult = { };
d->node = DEV_GetCoreNode(device->key()); // always get fresh pointer

if ((event.deviceKey() & 0x00212E0000000000LLU) == 0x00212E0000000000LLU)
{
if (!d->node)
{
d->node = DEV_GetCoreNode(device->key());
}

if (d->node && d->node->isCoordinator())
{
d->setState(DEV_DeadStateHandler);
Expand Down Expand Up @@ -1951,6 +1947,15 @@ void DEV_PollIdleStateHandler(Device *device, const Event &event)
d->setState(DEV_PollNextStateHandler, STATE_LEVEL_POLL);
return;
}
else
{
if (event.what() == REventPoll)
{
DBG_Printf(DBG_DEV, "DEV Poll Idle nothing to poll %s/" FMT_MAC "\n", event.resource(), FMT_MAC_CAST(event.deviceKey()));
// notify DeviceTick to proceed
DEV_EnqueueEvent(device, REventPollDone);
}
}
}
}

Expand All @@ -1972,6 +1977,8 @@ void DEV_PollNextStateHandler(Device *device, const Event &event)
if (d->pollItems.empty())
{
d->setState(DEV_PollIdleStateHandler, STATE_LEVEL_POLL);
// notify DeviceTick to proceed
DEV_EnqueueEvent(device, REventPollDone);
return;
}

Expand Down
61 changes: 54 additions & 7 deletions device_tick.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define TICK_INTERVAL_JOIN 500
#define TICK_INTERVAL_IDLE 1000
#define TICK_INTERVAL_IDLE_OTAU 6000
#define TICK_INTERVAL_POLL_TIMOUT 10000

extern int DEV_ApsQueueSize();
extern bool DEV_OtauBusy();
Expand All @@ -37,6 +38,7 @@ typedef void (*DT_StateHandler)(DeviceTickPrivate *d, const Event &event);
static void DT_StateInit(DeviceTickPrivate *d, const Event &event);
static void DT_StateJoin(DeviceTickPrivate *d, const Event &event);
static void DT_StateIdle(DeviceTickPrivate *d, const Event &event);
static void DT_StatePoll(DeviceTickPrivate *d, const Event &event);

class DeviceTickPrivate
{
Expand All @@ -48,6 +50,9 @@ class DeviceTickPrivate
QTimer *timer = nullptr;
size_t devIter = 0;
const DeviceContainer *devices = nullptr;
// for logging
DeviceKey curDeviceKey = 0;
bool curDeviceManaged = false;
};

/*! Constructor.
Expand Down Expand Up @@ -120,31 +125,37 @@ static void DT_StateInit(DeviceTickPrivate *d, const Event &event)
{
if (event.resource() == RLocal && event.what() == REventStateTimeout)
{
DBG_Printf(DBG_INFO, "DEV Tick.Init: booted after %lld seconds\n", DEV_TICK_BOOT_TIME);
DBG_Printf(DBG_DEV, "DEV Tick.Init: booted after %ld seconds\n", (long)DEV_TICK_BOOT_TIME);
DT_SetState(d, DT_StateIdle);
}
}

/*! Emits REventPoll to the next device in DT_StateIdle.
*/
static void DT_PollNextIdleDevice(DeviceTickPrivate *d)
static bool DT_PollNextIdleDevice(DeviceTickPrivate *d)
{
const auto devCount = d->devices->size();

if (devCount == 0)
{
return;
return false;
}

d->devIter %= devCount;

const auto &device = d->devices->at(d->devIter);
d->devIter++;
Q_ASSERT(device);

if (device->reachable())
{
d->curDeviceKey = device->key();
d->curDeviceManaged = device->managed();
emit d->q->eventNotify(Event(device->prefix(), REventPoll, 0, device->key()));
return true;
}
d->devIter++;

return false;
}

/*! This state is active while Permit Join is disabled for normal idle operation.
Expand All @@ -165,7 +176,11 @@ static void DT_StateIdle(DeviceTickPrivate *d, const Event &event)
int timeout = DEV_OtauBusy() ? TICK_INTERVAL_IDLE_OTAU : TICK_INTERVAL_IDLE;
if (DA_ApsUnconfirmedRequests() < 4)
{
DT_PollNextIdleDevice(d);
if (DT_PollNextIdleDevice(d))
{
DT_SetState(d, DT_StatePoll);
return;
}
}
DT_StartTimer(d, timeout);
}
Expand All @@ -180,6 +195,38 @@ static void DT_StateIdle(DeviceTickPrivate *d, const Event &event)
}
}

/*! Wait for poll state to finish either by timeout or device signaling that nothing needs to be polled.
*/
static void DT_StatePoll(DeviceTickPrivate *d, const Event &event)
{
if (event.what() == REventPermitjoinEnabled)
{
DT_SetState(d, DT_StateJoin);
}
else if (event.resource() == RLocal)
{
if (event.what() == REventStateTimeout)
{
DT_SetState(d, DT_StateIdle);
}
else if (event.what() == REventStateEnter)
{
DBG_Printf(DBG_DEV, "DEV Tick: poll enter " FMT_MAC ", managed = %d\n", FMT_MAC_CAST(d->curDeviceKey), d->curDeviceManaged);
DT_StartTimer(d, TICK_INTERVAL_POLL_TIMOUT);
}
else if (event.what() == REventStateLeave)
{
DBG_Printf(DBG_DEV, "DEV Tick: poll leave " FMT_MAC "\n", FMT_MAC_CAST(d->curDeviceKey));
DT_StopTimer(d);
}
}
else if (event.resource() == RDevices && event.what() == REventPollDone)
{
DBG_Printf(DBG_DEV, "DEV Tick: poll done " FMT_MAC "\n", FMT_MAC_CAST(d->curDeviceKey));
DT_SetState(d, DT_StateIdle);
}
}

/*! Adds a joining device entry to the queue if not already present.
*/
static void DT_RegisterJoiningDevice(DeviceTickPrivate *d, DeviceKey deviceKey, quint8 macCapabilities)
Expand All @@ -197,7 +244,7 @@ static void DT_RegisterJoiningDevice(DeviceTickPrivate *d, DeviceKey deviceKey,
dev.deviceKey = deviceKey;
dev.macCapabilities = macCapabilities;
d->joinDevices.push_back(dev);
DBG_Printf(DBG_INFO, "DEV Tick: fast poll 0x%016llX, mac capabilities: 0x%02X\n", deviceKey, macCapabilities);
DBG_Printf(DBG_DEV, "DEV Tick: fast poll " FMT_MAC ", mac capabilities: 0x%02X\n", FMT_MAC_CAST(deviceKey), macCapabilities);
}
}

Expand Down Expand Up @@ -233,7 +280,7 @@ static void DT_StateJoin(DeviceTickPrivate *d, const Event &event)
}
else if (event.what() == REventDeviceAnnounce)
{
DBG_Printf(DBG_INFO, "DEV Tick.Join: %s\n", event.what());
DBG_Printf(DBG_DEV, "DEV Tick.Join: %s\n", event.what());
DT_RegisterJoiningDevice(d, event.deviceKey(), static_cast<quint8>(event.num()));
}
else if (event.resource() == RLocal)
Expand Down
4 changes: 2 additions & 2 deletions ias_zone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,9 +714,9 @@ void DeRestPluginPrivate::checkIasEnrollmentStatus(Sensor *sensor)

if (iasState == IAS_STATE_READ)
{
DBG_Printf(DBG_IAS, "[IAS ZONE] - 0x%016llX Read IAS zone state and CIE address...\n", sensor->address().ext());
DBG_Printf(DBG_IAS, "[IAS ZONE] - 0x%016llX Read IAS zone state, type and CIE address...\n", sensor->address().ext());

if (readAttributes(sensor, sensor->fingerPrint().endpoint, IAS_ZONE_CLUSTER_ID, {IAS_ZONE_STATE, IAS_CIE_ADDRESS}))
if (readAttributes(sensor, sensor->fingerPrint().endpoint, IAS_ZONE_CLUSTER_ID, {IAS_ZONE_STATE, IAS_ZONE_TYPE, IAS_CIE_ADDRESS}))
{
queryTime = queryTime.addSecs(1);
IAS_SetState(sensor, itemIasState, IAS_STATE_WAIT_READ);
Expand Down
10 changes: 0 additions & 10 deletions permitJoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,6 @@ void DeRestPluginPrivate::permitJoinTimerFired()
i++;
}
}
else if ((gwPermitJoinDuration % 15) == 0) // TODO bad this needs to go
{
for (LightNode &l : nodes)
{
if (l.isAvailable() && l.modelId().isEmpty())
{
queuePollNode(&l);
}
}
}

updateEtag(gwConfigEtag); // update Etag so that webApp can count down permitJoin duration
}
Expand Down
7 changes: 7 additions & 0 deletions poll_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,13 @@ void PollManager::pollTimerFired()
{
pollState = StateIdle;
timer->start(50);

// Notify the DeviceTick manager that legacy code is done polling.
Device *device = DEV_GetDevice(plugin->m_devices, dstAddr.ext());
if (device)
{
emit device->eventNotify(Event(device->prefix(), REventPollDone, 0, device->key()));
}
emit done();
return;
}
Expand Down
1 change: 1 addition & 0 deletions resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const char *REventPermitjoinDisabled = "event/permit.join.disabled";
const char *REventPermitjoinEnabled = "event/permit.join.enabled";
const char *REventPermitjoinRunning = "event/permit.join.running";
const char *REventPoll = "event/poll";
const char *REventPollDone = "event/poll.done";
const char *REventSimpleDescriptor = "event/simple.descriptor";
const char *REventStartTimer = "event/start.timer";
const char *REventStateEnter = "event/state.enter";
Expand Down
1 change: 1 addition & 0 deletions resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ extern const char *REventPermitjoinEnabled;
extern const char *REventPermitjoinDisabled;
extern const char *REventPermitjoinRunning;
extern const char *REventPoll;
extern const char *REventPollDone;
extern const char *REventDDFReload;
extern const char *REventDDFInitRequest;
extern const char *REventDDFInitResponse;
Expand Down