API Addition: dev.stateListOrDisplayStateIdChanged() method

Posted on
Sat Nov 12, 2011 5:48 pm
matt (support) offline
Site Admin
User avatar
Posts: 21411
Joined: Jan 27, 2003
Location: Texas

API Addition: dev.stateListOrDisplayStateIdChanged() method

The release version of v5.0.0 has a new device instance method: stateListOrDisplayStateIdChanged().

Background: Plugins can subclass the method getDeviceStateList() to provide dynamic state list definition information. The default implementation provides a static solution by retrieving the device state list definition from the Devices.xml file. Likewise, the method getDeviceDisplayStateId() can be used to dynamically determine which device state should be displayed in the State column of the main device table UI.

Problem: The Indigo Server only calls getDeviceStateList() and getDeviceDisplayStateId() at very specific times, like when a plugin device dialog is dismissed. Plugins that need to refresh a device state list definition or display state ID at other times couldn't.

Solution: Call stateListOrDisplayStateIdChanged() on the device instance you need refreshed. Indigo will then automatically call your plugin's getDeviceStateList() and getDeviceDisplayStateId() methods (or use the base implementation of looking up the list from Devices.xml) and update the Indigo Server (and all clients).

This is particularly useful for plugin updates that need to add new device states to existing device instances created by older versions. In this case, the plugin will need to update the device instances by calling stateListOrDisplayStateIdChanged(). A likely place to do this type of instance level upgrading is inside your plugin's deviceStartComm() method.

Example usage:

Code: Select all
dev = indigo.devices["den fixture"]
dev.stateListOrDisplayStateIdChanged()      # will call getDeviceStateList() and getDeviceDisplayStateId()

Image

Posted on
Sun Nov 18, 2012 2:10 pm
bschollnick2 offline
Posts: 1355
Joined: Oct 17, 2004
Location: Rochester, Ny

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

matt (support) wrote:
The release version of v5.0.0 has a new device instance method: stateListOrDisplayStateIdChanged().
Example usage:

Code: Select all
dev = indigo.devices["den fixture"]
dev.stateListOrDisplayStateIdChanged()      # will call getDeviceStateList() and getDeviceDisplayStateId()


Matt,

I have run into a situation with Switchboard, where stateListOrDisplayStateIdChanged () doesn't seem to be updating some devices?

Is there some situation or condition where this might happen? For example, the age of a device?

def deviceStartComm (self, dev):
self.debugLog ("Adding %s to Switchboard Devices List" % dev.name)
dev.stateListOrDisplayStateIdChanged()
....
....

I have not been able to detect any cause or reason for this... But It does seem to be happening....

- Ben

------
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

Posted on
Sun Nov 18, 2012 2:47 pm
matt (support) offline
Site Admin
User avatar
Posts: 21411
Joined: Jan 27, 2003
Location: Texas

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

It only works if the plugin that makes the stateListOrDisplayStateIdChanged() call is the same plugin that owns the device (that is, the pluginIds have to match). For devices that match though it should then trigger calls to the plugin's getDeviceStateList() and getDeviceDisplayStateId() methods. Add some debug logging to the start of those -- does it not get called? Any errors in the Event Log? Also check the console for errors. Sometimes they get logged there if they cannot get pushed to the server.

Image

Posted on
Sun Nov 18, 2012 4:51 pm
bschollnick2 offline
Posts: 1355
Joined: Oct 17, 2004
Location: Rochester, Ny

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

matt (support) wrote:
It only works if the plugin that makes the stateListOrDisplayStateIdChanged() call is the same plugin that owns the device (that is, the pluginIds have to match). For devices that match though it should then trigger calls to the plugin's getDeviceStateList() and getDeviceDisplayStateId() methods. Add some debug logging to the start of those -- does it not get called? Any errors in the Event Log? Also check the console for errors. Sometimes they get logged there if they cannot get pushed to the server.


The plugin_id for those devices hasn't change to my knowledge. It's the Switchboard plugin after all....

And I just checked, those devices are indeed being added via deviceStartComm.... And no additional errors in the console.log....
Where would I verify that the plugin_id hasn't changed for the devices? And is there anyway to normalize the plugin_id, assuming that is the cause of the issue?

I went through the 6 X10 devices that I have in my production switchboard, and as far as I can tell the plugin_id is identical.... And only one of them is updated.... And that was manually updated, when I went into the device, and saved it...

So, how can we debug this further? I have verified that the proper devices.xml file is in the plugin....

The odd issue is that the field is showing up in the Device Configuration page, but the variable & value is not seen in the device's record....

- Ben

------
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

Posted on
Sun Nov 18, 2012 7:47 pm
matt (support) offline
Site Admin
User avatar
Posts: 21411
Joined: Jan 27, 2003
Location: Texas

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

Are you trying to update the pluginProps on the device or the states definition on the device? And to double-check, you did add some debug logging to getDeviceStateList() and getDeviceDisplayStateId() to see if they were being called and they are not?

Image

Posted on
Mon Nov 19, 2012 4:29 am
bschollnick2 offline
Posts: 1355
Joined: Oct 17, 2004
Location: Rochester, Ny

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

matt (support) wrote:
And to double-check, you did add some debug logging to getDeviceStateList() and getDeviceDisplayStateId() to see if they were being called and they are not?


Maybe I misunderstanding something here.... I don't have getDeviceStateList or getDeviceDisplayStateId in use in Switchboard for creating custom states... My understanding is that if your not using custom states-----------

Whoa...

Let's reverse here, and make sure my assumptions are correct.... Because, I just thought about this.

1) This dev.stateListOrDisplayStateIdChanged() definitely updates the state information on the device, does it update anything else?
a) If it only updates state information, is there an equivalent for the field information on the device?

I know I started using it, to solve a state issue, but I've been assuming it causes a full refresh of the device....

To answer your other question, I added a field record to the device.... After adding getDeviceStateList and getDeviceDisplayStateId, I seriously thought about the function as something other than a refresh mechanism....

So is there someway to refresh the device's fields without having a user go through manually edit each device, and then save it?

- Ben

------
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

Posted on
Mon Nov 19, 2012 10:59 am
jay (support) offline
Site Admin
User avatar
Posts: 18199
Joined: Mar 19, 2008
Location: Austin, Texas

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

getDeviceStateList() is called when we build the list of available states for a device. The default implementation just returns what's in the Devices.xml. You can of course override the method if you like.

That method is generally only called when the device is first created. You can call the dev.stateListOrDisplayStateIdChanged() method to cause the state list to be rebuilt - so if you add or remove a state from the Devices.xml file then calling that method will force Indigo to rebuild the list for the device.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Mon Nov 19, 2012 11:28 am
matt (support) offline
Site Admin
User avatar
Posts: 21411
Joined: Jan 27, 2003
Location: Texas

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

bschollnick2 wrote:
a) If it only updates state information, is there an equivalent for the field information on the device?

No, but that is because your plugin can update the pluginProps at anytime it wants (on plugin start, when deviceStartComm() is called, etc.) The state definition list (not state values themselves) are different and cannot be updated by the plugin via a push. Instead the client/server pulls the state information from the plugin when it is needed. Therefore, we had to add the stateListOrDisplayStateIdChanged() method to let the server/client know that the state definition has changed and needs to be pulled from the plugin again.

bschollnick2 wrote:
So is there someway to refresh the device's fields without having a user go through manually edit each device, and then save it?

I would do it at plugin startup time or deviceStartComm. Or often times the best approach is to access values via get() instead of the bracket syntax since you can specify a default. So instead of:

Code: Select all
foo = dev.pluginProps["someNewKeyThatMayNotExist"]

which will throw an error if the key doesn't exist, use:

Code: Select all
foo = dev.pluginProps.get("someNewKeyThatMayNotExist", 0 or some other default value)

Image

Posted on
Mon Nov 19, 2012 11:33 am
jay (support) offline
Site Admin
User avatar
Posts: 18199
Joined: Mar 19, 2008
Location: Austin, Texas

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

Sorry, I totally wasn't making the fields=properties leap with you...

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Mon Nov 19, 2012 11:44 am
bschollnick2 offline
Posts: 1355
Joined: Oct 17, 2004
Location: Rochester, Ny

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

jay (support) wrote:
Sorry, I totally wasn't making the fields=properties leap with you...


Jay,

I think we're slightly misunderstanding each other here....?

I added this to the devices.xml.... And restarted the plugin...

<Field type="checkbox" id="IgnoreHeartbeats">
<Label>Turn Off Heartbeat Warnings</Label>
<Description></Description>
</Field>

This field, shows up in the devices configuration screen... But when I look at the device in python:

>>> print indigo.devices[1646055197]
address : 105
buttonGroupCount : 0
description :
deviceTypeId : X10Device
enabled : True
errorState :
folderId : 833197598
globalProps : MetaProps : (dict)
com.schollnick.indigoplugin.switchboard : (dict)
DeviceCode : 2 (string)
HouseCode : J (string)
IgnoreDevice : false (bool)
IgnoreOrphan : false (bool)
OverrideHeartbeatTimeOut : true (bool)
X10HeartBeatTimeOut : 200 (string)
X10Security : 105 (string)
address : 105 (string)
simpleSeparator1 : (string)
simpleSeparator2 : (string)
simpleSeparator3 : (string)
id : 1646055197
lastChanged : 2000-01-01 00:00:00
model : X10 Monitored Device
name : test X10
pluginId : com.schollnick.indigoplugin.switchboard
pluginProps : emptyDict : (dict)
protocol : Plugin
remoteDisplay : True
states : States : (dict)
Display_onState : false (bool)
Last_Triggered : (string)
Last_Updated : (string)
Last_X10Command : (string)
Last_X10HeartBeat : (string)
onState : false (bool)
supportsAllLightsOnOff : False
supportsAllOff : False
supportsStatusRequest : False
version : 0

Note the lack of IgnoreHeartsbeats.....?

Now a newly created device, will have that field in GlobalProps.... And if I have the users, enter the Device Record, edit it, Save it, and Close the device record the field will be there as well.

(Same device after reserving)

>>> >>> print indigo.devices[1646055197]
address : 105
buttonGroupCount : 0
description :
deviceTypeId : X10Device
enabled : True
errorState :
folderId : 833197598
globalProps : MetaProps : (dict)
com.schollnick.indigoplugin.switchboard : (dict)
DeviceCode : 2 (string)
HouseCode : J (string)
IgnoreDevice : false (bool)
IgnoreHeartbeats : false (bool)
IgnoreOrphan : false (bool)
OverrideHeartbeatTimeOut : true (bool)
X10HeartBeatTimeOut : 200 (string)
X10Security : 105 (string)
address : 105 (string)
simpleSeparator1 : (string)
simpleSeparator2 : (string)
simpleSeparator3 : (string)
id : 1646055197
lastChanged : 2000-01-01 00:00:00
model : X10 Monitored Device
name : test X10
pluginId : com.schollnick.indigoplugin.switchboard
pluginProps : emptyDict : (dict)
protocol : Plugin
remoteDisplay : True
states : States : (dict)
Display_onState : false (bool)
Last_Triggered : (string)
Last_Updated : (string)
Last_X10Command : (string)
Last_X10HeartBeat : (string)
onState : false (bool)
supportsAllLightsOnOff : False
supportsAllOff : False
supportsStatusRequest : False
version : 0

I had made the assumption that dev.stateListOrDisplayStateIdChanged() would force a refresh on that as well....

But Switchboard can have 10-15 devices... And I can't rely on the users forcing a refresh of all those devices....
Is there *any* way that I can programatically do this? Or request some API manner to do this?

- Ben

------
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

Posted on
Mon Nov 19, 2012 11:50 am
jay (support) offline
Site Admin
User avatar
Posts: 18199
Joined: Mar 19, 2008
Location: Austin, Texas

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

Check Matt's post. You can add properties directly any time you want. Fields in the config ui are just properties.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Mon Nov 19, 2012 8:39 pm
bschollnick2 offline
Posts: 1355
Joined: Oct 17, 2004
Location: Rochester, Ny

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

jay (support) wrote:
Check Matt's post. You can add properties directly any time you want. Fields in the config ui are just properties.


Okay, just to clarify, this is in the GlobalProps category, since these are custom devices.

I see the example on that Matt gives, but those changes aren't propagated to the server, and replacePluginPropsOnServer is throwing an error....

Switchboard IgnoreHeartbeats
Switchboard Error exception in deviceStartComm(Rec Room - Backyard Door): Python argument types in
Dict.__setitem__(Dict, type, bool)

Setting the property to True / False / 0 / 1 doesn't seem to work....
Code: Select all
   def   verify_device_properties ( self, dev, propertyname, boolean = False) :
      if indigo.devices[dev].globalProps[plugin_id].has_key (propertyname):
         return
      else:
         #indigo.devices[dev].globalProps[plugin_id][propertyname] = None
         indigo.server.log ("%s" % propertyname)
         newProps = dev.globalProps[plugin_id]
         if boolean:
            newProps[property] = True
         else:
            newProps[property] = ""
         
         dev.replacePluginPropsOnServer(newProps)

      if dev.deviceTypeId == "X10Device":
         self.verify_device_properties (dev, "IgnoreDevice", boolean = True)
         self.verify_device_properties (dev, "IgnoreOrphan", boolean = True)
         self.verify_device_properties (dev, "IgnoreHeartbeats", boolean = True)
         self.verify_device_properties (dev, "OverrideHeartbeatTimeout", boolean = True)
         self.verify_device_properties (dev, "X10HeartBeatTimeOut")
         # self.X10List [ <X10 Sensor ID> ] = X10 Monitored Device ID
         #
         #   Get Security ID from the device
         #
         X10Security = str(indigo.devices[dev].globalProps[plugin_id]["X10Security"]).upper()



Should work, but as I mentioned, the boolean code doesn't seem to be working quite right...

Using get in this case, doesn't solve the problem. It doesn't write the field to the globalProps, it masks the problem, due to the default value... Since the value disappears once the server or plugin is reset...

- 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

Posted on
Mon Nov 19, 2012 8:48 pm
jay (support) offline
Site Admin
User avatar
Posts: 18199
Joined: Mar 19, 2008
Location: Austin, Texas

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

pluginProps are where properties defined in the config ui show up. globalProps are for adding arbitrary properties to devices not owned by your plugin.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Mon Nov 19, 2012 8:50 pm
matt (support) offline
Site Admin
User avatar
Posts: 21411
Joined: Jan 27, 2003
Location: Texas

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

pluginProps are both where you should put your properties and where the ConfigUI properties are automatically inserted.

globalProps is the global dictionary of all pluginProps. It should not be modified. Plugins should modify their pluginProps instead via replacePluginPropsOnServer(). See this explanation for the details including examples of using replacePluginPropsOnServer().

Image

Posted on
Mon Nov 19, 2012 8:53 pm
matt (support) offline
Site Admin
User avatar
Posts: 21411
Joined: Jan 27, 2003
Location: Texas

Re: API Addition: dev.stateListOrDisplayStateIdChanged() met

And if replacePluginPropsOnServer() is throwing an error, then what is the error (the above has an exception log, but it looks incomplete)? And is the exact code above what causes the error?

Image

Who is online

Users browsing this forum: No registered users and 2 guests