I am hoping that someone else has used this feature, since I can't seem to get this to work properly...
I have spent a good portion of today trying to finish the device preferences on the security script... And I am forced to say that something isn't right here... Probably my code, but I can't find enough documentation on the Wiki site to prove this or help resolve the issue...
Now to try to explain this....
--- Devices.xml fragment ----
<Field id="Device_List" type="list">
<Label>Add these devices to the Zone:</Label>
<List class="self" method="return_eligible_devices"/>
</Field>
<Field id="Add_to_Zone"
type="button"
tooltip="Add a device to the Zone">
<CallbackMethod>add_device_to_zone</CallbackMethod>
<Title>Add to Zone</Title>
</Field>
<Field id="RegisteredDevices" type="list">
<Label>Registered Devices for
this Zone:</Label>
<List class="self" method="return_devices_in_zone"/>
</Field>
<Field id="StoredDeviceList" type="textfield" defaultValue="" hidden="Yes">
</Field>
<Field id="Remove_from_Zone"
type="button"
tooltip="Remove a device to the Zone">
<CallbackMethod>Remove_from_Zone</CallbackMethod>
<Title>Remove From Security Zone</Title>
</Field>
-------------
In english...
"Device_List" is a list of all the devices registered in Indigo, both X10 and Insteon.
Add_To_Zone is a button that will move the device from Device_List to RegisteredDevices (And add an in StoredDeviceList)
Remove_from_Zone is a button that will move the device from RegisteredDevices to Device_List.
Now, according to the documentation that I have from the last email discussion with Jay... (Way back from June, so I really suspect I am working from outdated information here).
def add_device_to_zone ( self, configscreen, typeId, devId):
configscreen["Device_List"] = [ ("123", "abc"), ("456", "def") ]
return configscreen
Should change the Device_List list box to show "abc" and "def", but that doesn't work...
As per the Wiki, I suspect it should be:
return (True, configscreen)
Why? Because that's the return from the validationmethods, which the wiki states to use as a reference for this...
But that doesn't work either.... It returns an C++ error...
Security Devices Error Error in plugin execution UiAction:
Traceback (most recent call last):
<type 'exceptions.TypeError'>: No registered converter was able to extract a C++ reference to type CXmlDict from this Python object of type bool
So any suggestions on where I have goofed this up, because I'm spinning my wheels here in neutral.
- Benjamin
Trouble with Dynamic updating of lists in user preferences..
Forum rules
This is a legacy forum which is locked for new topics. New topics should be started in one of the other forums under Extending Indigo
This is a legacy forum which is locked for new topics. New topics should be started in one of the other forums under Extending Indigo
-
bschollnick2
- Posts: 1355
- Joined: Sun Oct 17, 2004 8:21 am
- Location: Rochester, Ny
- Contact:
Trouble with Dynamic updating of lists in user preferences..
------
My Plugins for Indigo (v4, v5, and v6) - http://bit.ly/U8XxPG
Security Script for v4 - http://bit.ly/QTgclf
for v5 - http://bit.ly/T6WBKu
Support Forum(s) - http://www.perceptiveautomation.com/userforum/viewforum.php?f=33
My Plugins for Indigo (v4, v5, and v6) - http://bit.ly/U8XxPG
Security Script for v4 - http://bit.ly/QTgclf
for v5 - http://bit.ly/T6WBKu
Support Forum(s) - http://www.perceptiveautomation.com/userforum/viewforum.php?f=33
- matt (support)
- Site Admin
- Posts: 21542
- Joined: Mon Jan 27, 2003 1:17 pm
- Location: Texas
- Contact:
Re: Trouble with Dynamic updating of lists in user preferenc
I tried to find the example code Jay wrote a while back that does this and couldn't find it, but I am pretty sure you don't want the boolean in the return. It should just be:
So I'm not sure why your first example code snippet didn't work.
How do you have return_devices_in_zone() defined? It has to be defined correctly to look at "Device_List" to know how to build the list to return, I believe.
Code: Select all
return configscreenHow do you have return_devices_in_zone() defined? It has to be defined correctly to look at "Device_List" to know how to build the list to return, I believe.
-
bschollnick2
- Posts: 1355
- Joined: Sun Oct 17, 2004 8:21 am
- Location: Rochester, Ny
- Contact:
Re: Trouble with Dynamic updating of lists in user preferenc
What do you mean by it has to be defined correctly to look at "Device_List"? The code for return_devices_in_zone() right now is a skeleton code, since I am using some logging statements to see if anything is being updated... The problem really seems to be add_device_to_zone, since that doesn't seem to be updating the listbox that it manages ("Device_List").support wrote:I tried to find the example code Jay wrote a while back that does this and couldn't find it, but I am pretty sure you don't want the boolean in the return. It should just be:
So I'm not sure why your first example code snippet didn't work.Code: Select all
return configscreen
How do you have return_devices_in_zone() defined? It has to be defined correctly to look at "Device_List" to know how to build the list to return, I believe.
The remove_device_to_zone manages ("RegisteredDevices"), and I haven't done anything with that yet... Since I don't have the add_device_to_zone / Add_to_Zone button working properly...
I have some fragments from Jay, but I can't seem to find a up to date, working example of this system.... Do we know of a plugin that is actually using an dynamically updated, list? Not just a dynamically generated list.....
- Benjamin
------
My Plugins for Indigo (v4, v5, and v6) - http://bit.ly/U8XxPG
Security Script for v4 - http://bit.ly/QTgclf
for v5 - http://bit.ly/T6WBKu
Support Forum(s) - http://www.perceptiveautomation.com/userforum/viewforum.php?f=33
My Plugins for Indigo (v4, v5, and v6) - http://bit.ly/U8XxPG
Security Script for v4 - http://bit.ly/QTgclf
for v5 - http://bit.ly/T6WBKu
Support Forum(s) - http://www.perceptiveautomation.com/userforum/viewforum.php?f=33
- matt (support)
- Site Admin
- Posts: 21542
- Joined: Mon Jan 27, 2003 1:17 pm
- Location: Texas
- Contact:
Re: Trouble with Dynamic updating of lists in user preferenc
That isn't what add_device_to_zone does. It updates the Device_List value, but then return_devices_in_zone() has to use that value to return the correct list. It sounds like you are thinking more is being handled under-the-hood than is. You have to manage adding items to the list, and you have to supply the method that returns the list.bschollnick2 wrote:The problem really seems to be add_device_to_zone, since that doesn't seem to be updating the listbox that it manages ("Device_List").
Below is the example XML and .py code with comments. I just checked it and it seems to be working with 5.0.
Code: Select all
<ConfigUI>
<Field id="sourceDeviceMenu" type="menu">
<Label>Select a device to add to list:</Label>
<List class="self" method="sourceDevices" dynamicReload="yes"/>
</Field>
<Field id="addDevice" type="button">
<Label/>
<Title>Add Device</Title>
<CallbackMethod>addDevice</CallbackMethod>
</Field>
<Field id="sep1" type="separator"/>
<Field id="memberDeviceList" type="list">
<Label>Devices in scene:</Label>
<List class="self" method="memberDevices" dynamicReload="yes"/>
</Field>
<Field id="deleteDevices" type="button">
<Label/>
<Title>Delete Devices</Title>
<CallbackMethod>deleteDevices</CallbackMethod>
</Field>
<Field id="memberDevices" type="textfield" hidden="yes">
<Label/>
</Field>
</ConfigUI>Code: Select all
########################################
# Buttons and dynamic list methods defined for the scenes custom device
#
# Overview of scene devices:
# Scene devices are custom devices that will contain multiple devices.
# We implement this custom device by storing a comma-delimited list of
# device IDs which is manipulated by clicking Add and Delete buttons
# in the device config dialog. There are two dynamic list controls in
# the dialog:
# 1) one popup button control on which the user selects a device
# to add then clicks the Add Device button.
# 2) one list control which shows all the devices that have already
# been added to the scene and in which the user can select devices
# and click the Delete Devices button
# There is a hidden field "memberDevices" that stores a comma-delimited
# list of device ids for each member of the scene. The addDevice and
# deleteDevices methods will take the selections from the respective
# dynamic lists and do the right thing with the list.
# Finally, there are the two methods that build the dynamic lists.
# The method that builds the source list will inspect the "memberDevices"
# field and won't include those devices in the source list (so the user
# won't be confused by seeing a device that's already in the member list
# in the source list). The method that builds the member list of course
# uses "memberDevices" to build the list.
#
# One other thing that should be done probably - in the deviceStartComm
# method (or the appropriate CRUD methods if you're using them instead)
# you should check the IDs to make sure they're still around and if not
# remove them from the device id list.
#
# The device id list property ("memberDevices") could, of course, be
# formatted in some other way besides a comma-delimited list of ids
# if you need to store more information. You could, for instance, store
# some kind of formatted text like JSON or XML that had much more
# information.
####################
# This is the method that's called by the Add Device button in the scene
# device config UI.
####################
def addDevice(self, valuesDict, typeId, devId):
self.debugLog(u"addDevice called")
# just making sure that they have selected a device in the source
# list - it shouldn't be possible not to but it's safer
if "sourceDeviceMenu" in valuesDict:
# Get the device ID of the selected device
deviceId = valuesDict["sourceDeviceMenu"]
if deviceId == "":
return
# Get the list of devices that have already been added to the "scene"
# If the key doesn't exist then return an empty string indicating
# no devices have yet been added. "memberDevices" is a hidden text
# field in the dialog that holds a comma-delimited list of device
# ids, one for each of the devices in the scene.
selectedDevicesString = valuesDict.get("memberDevices","")
self.debugLog("Adding device: %s to %s" % (deviceId, selectedDevicesString))
# If no devices have been added then just set the selected device string to
# the device id of the device they selected in the popup
if selectedDevicesString == "":
selectedDevicesString = deviceId
# Otherwise append it to the end separated by a comma
else:
selectedDevicesString += "," + str(deviceId)
# Set the device string back to the hidden text field that contains the
# list of device ids that are in the scene
valuesDict["memberDevices"] = selectedDevicesString
self.debugLog("valuesDict = " + str(valuesDict))
# Delete the selections on both dynamic lists since we don't
# want to preserve those across dialog runs
if "memberDeviceList" in valuesDict:
del valuesDict["memberDeviceList"]
if "sourceDeviceMenu" in valuesDict:
del valuesDict["sourceDeviceMenu"]
# return the new dict
return valuesDict
####################
# This is the method that's called by the Delete Device button in the scene
# device config UI.
####################
def deleteDevices(self, valuesDict, typeId, devId):
self.debugLog(u"deleteDevices called")
if "memberDevices" in valuesDict:
# Get the list of devices that are already in the scene
devicesInScene = valuesDict.get("memberDevices","").split(",")
# Get the devices they've selected in the list that they want
# to remove
selectedDevices = valuesDict.get("memberDeviceList", [])
# Loop through the devices to be deleted list and remove them
for deviceId in selectedDevices:
self.debugLog("remove deviceId: " + deviceId)
if deviceId in devicesInScene:
devicesInScene.remove(deviceId)
# Set the "memberDevices" field back to the new list which
# has the devices deleted from it.
valuesDict["memberDevices"] = ",".join(devicesInScene)
# Delete the selections on both dynamic lists since we don't
# want to preserve those across dialog runs
if "memberDeviceList" in valuesDict:
del valuesDict["memberDeviceList"]
if "sourceDeviceMenu" in valuesDict:
del valuesDict["sourceDeviceMenu"]
return valuesDict
####################
# This is the method that's called to build the source device list. Note
# that valuesDict is read-only so any changes you make to it will be discarded.
####################
def sourceDevices(self, filter="", valuesDict=None, typeId="", targetId=0):
self.debugLog("sourceDevices called with filter: %s typeId: %s targetId: %s" % (filter, typeId, str(targetId)))
returnList = list()
# if valuesDict doesn't exist yet - if this is a brand new device
# then we just create an empty dict so the rest of the logic will
# work correctly. Many other ways to skin that particular cat.
if not valuesDict:
valuesDict = {}
# Get the member device id list, loop over all devices, and if the device
# id isn't in the member list then include it in the source list.
deviceList = valuesDict.get("memberDevices","").split(",")
for devId in indigo.devices.iterkeys():
if str(devId) not in deviceList:
returnList.append((str(devId),indigo.devices.get(devId).name))
return returnList
####################
# This is the method that's called to build the member device list. Note
# that valuesDict is read-only so any changes you make to it will be discarded.
####################
def memberDevices(self, filter="", valuesDict=None, typeId="", targetId=0):
self.debugLog("memberDevices called with filter: %s typeId: %s targetId: %s" % (filter, typeId, str(targetId)))
returnList = list()
# valuesDict may be empty or None if it's a brand new device
if valuesDict and "memberDevices" in valuesDict:
# Get the list of devices
deviceListString = valuesDict["memberDevices"]
self.debugLog("memberDeviceString: " + deviceListString)
deviceList = deviceListString.split(",")
# Iterate over the list and if the device exists (it could have been
# deleted) then add it to the list.
for devId in deviceList:
if int(devId) in indigo.devices:
returnList.append((devId, indigo.devices[int(devId)].name))
return returnList
########################################
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"] = ""
return (True, valuesDict)-
bschollnick2
- Posts: 1355
- Joined: Sun Oct 17, 2004 8:21 am
- Location: Rochester, Ny
- Contact:
Re: Trouble with Dynamic updating of lists in user preferenc
Thank you. The example, highlighted the two things that they sample code I had from Jay didn't show. The main issue was that the XML declaration wasn't discussed in the email chain that I was using...support wrote: That isn't what add_device_to_zone does. It updates the Device_List value, but then return_devices_in_zone() has to use that value to return the correct list. It sounds like you are thinking more is being handled under-the-hood than is. You have to manage adding items to the list, and you have to supply the method that returns the list.
Below is the example XML and .py code with comments. I just checked it and it seems to be working with 5.0.
So far, the user interface is mostly done. I am now starting to look at the X10 / Insteon integration with the new API. The main hold up was the X10 portion since I only have a couple of Insteon triggerlincs. Compared to the 8 - 10 X10 DS10a's that consist of the majority of my security sensors.
------
My Plugins for Indigo (v4, v5, and v6) - http://bit.ly/U8XxPG
Security Script for v4 - http://bit.ly/QTgclf
for v5 - http://bit.ly/T6WBKu
Support Forum(s) - http://www.perceptiveautomation.com/userforum/viewforum.php?f=33
My Plugins for Indigo (v4, v5, and v6) - http://bit.ly/U8XxPG
Security Script for v4 - http://bit.ly/QTgclf
for v5 - http://bit.ly/T6WBKu
Support Forum(s) - http://www.perceptiveautomation.com/userforum/viewforum.php?f=33
