When an Edge device is moved from one driver to another, it appears that it loses any data stored with the device:set_field() method, even if the persistent option is specified. This is really a bummer when the device needs to retain this metadata when getting transferred to another driver.
So firstly, I’d request to SmartThings that they consider fixing this - at LEAST retain the persistent data. (BTW what happens to that persistent data today?? Hopefully it gets cleaned up when the device get transferred!).
Secondly, is there a best practice or alternative for accomplishing the retention of data associated with the device? I’m considering creating a non-displayed field with a custom capability, but I need it to be an object so I can store a table of values. Any recommended way of doing this?
I’ll check more details about that with the team. This includes your other question below:
What do you mean by “cleaned up”? After the driver change, you cannot access those values and you’re wondering if they are “removed” to stop consuming resources?
Yes, I’m hoping that the flash memory gets released for that persistent data that seemingly disappeared.
I agree. This is a big problem I highlighted earlier also. With locks for example the persistent codes need to be retained when drivers are changed because the locks still have the codes programmed in them and for some locks there is no way to retrieve it (eg Schalge) so there’s no way for the new driver to know what codes are programmed and report it to upstream apps. To further complicate matters some locks (like some Schlage models) don’t accept reprogramming the same code, so in this scenario when the driver is changed the new driver has no idea about existing codes and with the current lock architecture it will report no codes programmed to upstream apps. So the apps will try to reprogram the codes but it will fail because some locks won’t accept reprogramming existing codes. All in all it will be a total mess and failure requiring a complete reset of the lock.
DTH’s don’t have this issue because they retain the device specific data when DTH’s are changed.
Use the datastore directly for the driver. You can store any table you want. Just read and write
driver.datastore. I utilize this to store data found in discovery so I can reuse it when the device is initialized.
Have you confirmed that it persists when the device gets moved to another driver?
EDIT: Wait… this stores data against the driver itself and not the device? I’m not sure this would apply to device-specific data, would it?
It does if you key your own data by device ID. It is just a generic datastore. For example, you may want to keep a running table of IP addresses assigned to your devices, stored by device_network_id:
datastore.ips[dni] = some_ip
device.id are the two attributes that might work for you. I utilize this for IPs and port numbers so I can share them between discovery and devices. I also utilize it for devices connected through a secondary hub. They can access the info for their hub parent device.
It also works for shared auth tokens for a connected hub network
Thanks for the info. I’m still uncertain whether this would work when you are transferring a device from one driver to another, since this datastore is attached to the driver itself, not the device.
What am I missing?!
Sorry, I was answering this part of your question about storing an arbitrary table of data. I didn’t address persistence directly. If you remove a device from your driver, it won’t remove data from your datastore. That data is in the driver’s storage space. It isn’t a device field. As long as the driver remains installed, I’m pretty sure it will stick.
Devices A and B are running in MyDriver. I save something in the datastore. Both devices can see that by going through the driver.
Then if I move Device A to YourDriver, the data still exists in MyDriver which is still running. If you move Device A back, the data should be there.
I need the data to follow the device to the other driver
I thought you were worried about the round trip case of someone leaving your driver and coming back. When would a totally different driver ever need your data? How would it even know it was there?
I don’t see a use case unless there is some standardization around field names. Even with @RBoy 's example. If he and I both write a lock driver and store the codes, how would I know what field names he used? We wouldn’t likely use the same fields unless there was a standard established for locks.
Could be a future release of the ‘same’ driver. This is the way you want your users to upgrade to future enhanced drivers that you may need to (for certain reason) release as a new driver. You don’t want them to have to recreate their devices and have to re-do all their associated automation routines.
But to do this, you may need to be able to retain the device’s data that was save in persistent storage with the device:set_field method.
Another, more unique case that I’m experimenting with now is this: One can use a dynamic discovery mechanism to automatically find devices on your LAN. But there are cases where you may also need to provide a way to manually define those devices (via IP address, for example). So one way to solve that is to create a simple “manual creator” driver. Once you create those devices, you just move them to your main driver for final initialization and ongoing operation. The obvious alternative way to accomplish this is to just combine the auto discovery and manual discovery into one driver, but I kind of liked the idea splitting them up since only a few people would ever need the manual device creation capability.
Yeah. Transferring your OWN driver makes sense since you know the established scheme. I have had a few cases where I wanted to do that with a new driver, but ended up “upgrading” the stored data to move it around.
To my mind, the set_field() method is the way you store device-specific data and keep it with the device. Given that there is an option to make it persistent, it seems to me that it should follow the device to a new driver if a user moves it. Seems to me to be an oversight that it gets lost.
Possibly. I see the argument, but it could also corrupt a driver that happens to use the same name with slightly different intent. For example, I may make a
host field that is the
ip:port while you make a
host that is just the
ip. On a clean install, your driver would be fine, but on a swap, this mismatch could choke your driver.
So, the team mentioned “losing” the persistent storage when we change the device’s driver is expected. We cannot know if the new driver will be “an update” or even from the same developer. This could leave private information in the open for another driver to use which is a risk.
If you save the information in a capability, the value won’t be in the driver’s cache either but it would be still shown in the app (if it’s something you’d display).
Once we switch the driver, all the data stored is removed as well to avoid saving unused info.
Yea, I would never move a device to a driver that wasn’t developed for it!
Can you show me the best way to do that? I think it would entail creating a custom capability with an object attribute?
And no, I would not want to display the data. It would have to be a capability that is omitted from the presentation.
As long as both devices used that capability, I would expect it to be available. Waiting with interest on this one