jay (support) wrote:Ok. So, first things first: you can store arbitrarily complex hierarchies of Indigo Lists and Dicts along with python primitives in a device's plugin props (just take a look at a Z-Wave device's ownerProps - they are pretty complex). So I'm not sure why you couldn't get that working (if in fact that was the issue). It may be that the Z-Wave plugin builds those in a different way, but as Matt's the Z-Wave dude I can't really answer that. He might be able to jump in here in the next few days.
I can get that working (saving complex hierarchies in plugin props), just not from within validateDeviceConfigUi() or closedDeviceConfigUi(). I couldn't even write a simple string directly to plugin props from either of those methods. It's certainly possible I was doing something wrong, but the exact same code is working from within deviceUpdated().
As a test, I just modified "Example Device - Custom" with only the following code change in validateDeviceConfigUi():
- Code: Select all
def validateDeviceConfigUi(self, valuesDict, typeId, devId):
# If the typeId is "scene", we want to clear the selections on both
# dynamic lists so that they're not stored since we really don't
# care about those.
self.debugLog(u"validateDeviceConfigUi: typeId: %s devId: %s" % (typeId, str(devId)))
if typeId == "scene":
if "memberDeviceList" in valuesDict:
valuesDict["memberDeviceList"] = ""
if "sourceDeviceMenu" in valuesDict:
valuesDict["sourceDeviceMenu"] = ""
# Added code here
dev = indigo.devices[devId]
localPropsCopy = dev.pluginProps
localPropsCopy['testProp'] = u"ABCD"
dev.replacePluginPropsOnServer(localPropsCopy)
# End of added code
return (True, valuesDict)
The property 'testProp' does not get saved in the devices pluginProps. It fooled me at first because after dev.replacePluginPropsOnServer, I refreshed the dev from server and checked for the property. It was there! However, from the scripting shell, it does NOT show up if you print the dev.
- Code: Select all
>>> dev = indigo.devices[810913725] # "ABC"
>>> print dev
jay (support) wrote:I would recommend using a UI that's similar to the Global Property Manager's Manage Global Device Properties menu item. It's not for a plugin specified device, but if you think about each device selected in the top popup as representing the graph device, then you can envision the rest of the dialog managing each series but in the device edit dialog for your graph device type. Feel free do dig through that plugin's source, though it's really quite small/simple. That might be a good starting framework for what you're looking to do. It stores the necessary stuff as properties on the device itself and not as part of a device that's created by the plugin, but I think the concepts might help you along a bit.
That UI is just another way for working around the fact that you can't locate buttons side-by-side or open up a separate dialog to enter additional information. Personally, I much prefer the UI in HomeKit Bridge over this UI. Believe me, I've looked at the UI (and code) in a lot of plugins to see how lists are implemented. There is a standard way (in computing) of editing a list of: properties, contacts, songs, graph series, or whatever, that you just can't do with the current implementation of Indigo.
A perfect example of the standard way of editing a list is the main Indigo window. There's a "New..." button, an "Edit.." button and a "Delete..." button. There's even a bonus "Duplicate..." button. The buttons are side-by-side. The idea being that if you click "New...", a separate dialog opens up for the user to enter all of the information for the new Device (or Trigger, etc.). The user can either save that device or cancel. If instead the user selects an existing device and clicks "Edit...", the same dialog pops up, and information specific to the existing device can be edited. And of course "Delete..." deletes the item.
As I mentioned earlier in this thread, I would like to request new features that would allow what I'm calling a standard way of editing a list. The first two feature requests would be positioning buttons side-by-side and being able to open another dialog box for editing data, with "Save" and "Cancel" buttons side-by-side.
There are a couple of things that I don't particularly care for in Global Property Manager's UI. First, it states that "Note that all changes made in this dialog are immediately stored and can't be undone." So basically, when you click the "Add Property" button, it is stored. One main goal (which I started this thread with) is to be able to cancel all edits by clicking the Cancel button when closing the Edit Device Settings UI. That's why I am using valuesDict to store the complex data type (as a json string) until I later write it as a property in pluginProps. This happens after the user presses the Save button when closing the Edit Device Settings UI.
The other thing is that once you select a device, you then use the 3rd section of the dialog (bottom section) to add a property. That's not intuitive to me. I would expect to use the 2nd section (middle section). But then the second section is used to edit the list of global properties that are already defined.
I'm not saying this UI is bad in any way, I just prefer the UI in HomeKit Bridge because it most closely resembles the standard way of editing a list of things.
The UI I'm creating is mostly working now. I still have a few more things to do. Since this thread has gone is so many directions, here's a summary of the important things I've learned through the thread:
- You can't save complex properties to valuesDict (Ex. a list of dicts).
- If you need to save a complex property to valuesDict, use json to create a string to save.
- json does not work with indigo.List() or indigo.Dict().
- You can only update device plugin properties using valuesDict from within validateDeviceConfigUi() or closedDeviceConfigUi(). You cannot update them directly with dev.replacePluginPropsOnServer().
And finally, deviceStartComm() is not being called when the user edits an existing device. I'm still trying to figure this out because FlyingDiver says it should be called.