Is there value in implementing the Refresh standard capability in your Edge device profile? I put it in originally like some of the examples, and fired it on a timer. After some refactoring I ended up with the true “refresh” being done via a different timer routine, and I left the registered “Refresh” in (without a timer routine) just to see if it was ever called. So far I haven’t seen anything in my logs. I saw a reference in a post about “pulling down to refresh” (common on phone app behavior) but my ST app (I’m on the new app) it doesn’t seem to have a “pull down” behavior and I didn’t see “refresh” in any of the options.
Is is just a convention to implement a standard capability Refresh even though all of the code is unique to the driver, or did I miss something?
Pull down to refresh (at least on android) requires that you pull down in the controls area. If you pull down by the name, it doesn’t work.
I only see the refresh just after device init and on pulldown. Giving up for the night, but wondering if device:refresh() may trigger that commands on LAN devices. I am forcefully injecting it at the moment when my device comes online.
I think it is simply that if you can conceive of ever needing to call your ‘refresh’ code manually, or by an automation, then you might as well call the command refresh and use the refresh capability as it is pretty widely understood that is what it is for.
With tagging capabilities like actuator, sensor and bridge being deprecated, the refresh capability is also a useful ‘does no harm’ capability to have around. Such things are useful when developing device presentations. Also it is a free command for debugging purposes.
Thanks for the help @blueyetisoftware@philh30@orangebucket. I confirmed that if I pull down IN THE CONTROLS area of the page it does generate a refresh command, which is useful. This does seem a little counter intuitive to me, since I avoid hitting controls when trying to “pull down refresh” since it is easy to accidentally hit a control and cause it to respond when what you were trying to do was cause a refresh. I always try to use a blank part of the page to do a “pull down”.
Adding to this thread since it is related. I am seeing irregular behavior on device initialization. Most of the time,refresh is automatically called on new devices, but not always. I have been unable to find a pattern. @nayelyz Do you know when the platform decides to send a refresh command to new devices? Other than manually refreshing the devices, this is the only time I ever see the platform do it automatically and it doesn’t always happen.
Hi, @blueyetisoftware. The team mentioned that we shouldn’t expect any automatic refresh, so we should send initial state events explicitly.
You can call device:refresh() which will execute the refresh function defined in the capability defaults.
Also, you can define your own refresh function and call it when you need it.
Thank you for sharing what you experienced, we will be monitoring the behavior to see if we can find out more.
@nayelyz I think I may have just noticed a pattern. I see the automatic refresh on LAN device that are also successfully initialized. If you remember, @rossetyler and I also reported that devices aren’t always initialized after being added. The refresh looks like it only happens when the device was also initialized. I’m not 100% on this pattern, but it seems to be correlated. No init == No automatic refresh
This post is exactly describing problems I’m currently seeing with a LAN driver:
INIT lifecycle is not getting called for every device discovered
Unexpected Refresh commands are getting invoked during device creation
So I’d be interested if you have gotten any more insights on either of these issues since this post?
I have run into this on multiple occasions with drivers that are discovering/creating/initializing numerous devices in rapid succession. It seems that if you get too many ADD/INIT cycles going at once, that INIT calls start to get dropped. I know the conventional answer to this issue is that you probably have something that is blocking, and indeed, for LAN-based devices you’re always going to have a certain amount of socket activity while initializing a device - typically in the INIT lifecycle. So I’m curious to hear from others on best practices for handling this. For example, would it always be prudent to use a device.thread:queue_event() to run device INIT communications functions? I think otherwise, everything would be running in the discovery ‘thread’, which could bog things down.
I have also successfully resolved this problem for some drivers by using a semaphore to ensure that device creation is serialized, to prevent too many device creation sequences from happening.
The frustration of this one has caused me on many occasions to abandon the use of the refresh capability in LAN drivers and instead provide an explicit button for user-invoked refresh requests. The problem is that these platform-induced refresh commands seem to get invoked at odd times: during device creation/initialization, and even during shutdown cycles, although the latter may no longer be the case with recent firmware, since I haven’t seen it in a while. But just today for example, during onboarding of multiple devices, I could see in the log that not only were INIT lifecycles being dropped, but a refresh was being invoked at very weird times - in one case even prior to the ADD lifecycle being invoked for the device!
Aside from that strange anomaly, you could say that a refresh request should not cause any harm. But they can result in duplicate requests to the physical LAN device when received at less-than-optimal times. I just want to know from the SmartThings team, what exactly are the rules for when the platform is invoking the refresh command? For a LAN device, I should have a way to determine if the refresh was user vs. platform initiated so that I can handle it appropriately: i.e. I would probably ignore the platform-initiated ones. A LAN driver should know when device refreshes need to take place…
I still see the extraneous refresh events during device creation. If it were up to me, I would prefer ST never send a refresh event unless it is user generated or I call device:refresh() explicitly. I already have the added, init and doConfigure callbacks that can grab initial values if needed. I can also trigger a refresh if I want on my own.
In light of the irregular timing, I have resorted to making sure the refresh calls are either very light, or queue an event in case I get them in quick succession. If the team implemented it as described above, those workarounds would no longer be needed.
FYI - I have found this to not necessarily be the case. I’m looking at a log right now where the refresh command was invoked for 3 devices that never got their INIT lifecycle invoked. And as I mentioned, one of those was even before the ADD lifecycle got invoked. Of course this anomaly could be due to other blocking issues.
I don’t think I’ve seen a refresh during device creation before. Not unless its being called by the default Zigbee or Zwave added handlers. For instance, ZigBee has its default doConfigure handler do a refresh to get the status of the device.
Looking at st/driver.lua: Driver:lifecycle_message_handler(lifecycle_channel), I don’t see where the init/added specifically queue up a refresh anywhere.
And I’ve not see init’s get dropped but refreshes get called…
I do see the throttling of try_create_device() and try_update_metadata() in LAN drivers. It seems you can issue about 4 or 5 at once before some start getting dropped (they don’t return failure, always true). For Mira I issue any of these commands in a priority queue, with a short wait inbetween each execution (I think 2 or 3 seconds). After doing this I can create/update 50+ devices in a row and I’ve not seen any be dropped.
Maybe it’s handled differently between LAN and zigbee/zwave devices?
How are you doing the wait? My understanding is that the discovery ‘thread’ (I’m using the term thread here, which is really a coroutine) is separate from the main driver thread, and therefore it should be safe to use socket.sleep().
I use call_with_delay(). First push onto the queue starts the chain. Each execution off the queue does another call_with_delay() if there are more entries on the queue. Final entry cleans up. Works great.
I do this in one driver with a 3 second wait between devices and it works fine as well.
Since starting that, I don’t see issues with the init, but do still get the extra refresh sometimes. I stopped looking at it, but last time I gave it some thought, I had a theory that it was based on device type or capabilities, since I don’t see it on all devices.