Problem to update states list

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
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
User avatar
Juju
Posts: 108
Joined: Wed Aug 31, 2011 10:16 am
Location: Toulouse - FRANCE

Problem to update states list

Post by Juju »

Hello,

I would like to define custom states for a device depending the data it send through a serial port. For that, I decided to define a new property into pluginProps, which is a list containing all states keys. The method getDeviceStateList() just read this property and build an indigo.List() with all states.
First question : my approach is correct ?

The following code is the method analyzing data read from the serial port :

Code: Select all

def	updateDeviceStates(self, dev, tramesTeleinfo):
		for element in tramesTeleinfo.items():
			keyState = element[0]
			valueState = element[1]
			self.debugLog(u"Clé: " + keyState + ", valeur: " + valueState)
			if not keyState in dev.states:
				updatedPluginProps = dev.pluginProps
				if not 'statesKeys' in updatedPluginProps:
					updatedPluginProps[u'statesKeys'] = []
				updatedPluginProps[u'statesKeys'].append(keyState)
				indigo.server.log(u'StatesKeys after update :\n%s' % updatedPluginProps[u'statesKeys'])
				dev.replacePluginPropsOnServer(updatedPluginProps)

				dev.stateListOrDisplayStateIdChanged()

			dev.updateStateOnServer(key=keyState, value=valueState)
It seems "updatedPluginProps[u'statesKeys'].append(keyState)" doesn't do anything ... The next line log the updatedPluginProps[u'statesKeys'] status, but the list is always empty ... What's my problem ?
User avatar
matt (support)
Site Admin
Posts: 21542
Joined: Mon Jan 27, 2003 1:17 pm
Location: Texas
Contact:

Re: Problem to update states list

Post by matt (support) »

Your approach sounds okay.

dev.pluginProps returns a special Indigo dictionary which has some subtle differences compared to a normal python dictionary. One of which being that key accessed items are not returned by reference, but by value. So this line:

updatedPluginProps[u'statesKeys'].append(keyState)

is actually appending the keyState to a temporary object returned by the evaluation of updatedPluginProps[u'statesKeys']. That is, it isn't really modifying the dictionary but a transient copy of the dictionary.

We might improve this some day, but in the mean time the solution is to append your keyState to a local variable array, then assign that to the updatedPluginProps. Something like:

Code: Select all

            updatedPluginProps = dev.pluginProps
            if not 'statesKeys' in updatedPluginProps:
               keyList = []
            else:
               keyList = updatedPluginProps[u'statesKeys']
            keyList.append(keyState)
            updatedPluginProps[u'statesKeys'] = keyList
            indigo.server.log(u'StatesKeys after update :\n%s' % updatedPluginProps[u'statesKeys'])
            dev.replacePluginPropsOnServer(updatedPluginProps)
Image
User avatar
Juju
Posts: 108
Joined: Wed Aug 31, 2011 10:16 am
Location: Toulouse - FRANCE

Re: Problem to update states list

Post by Juju »

OK, thanks Matt, that's the solution.

Complementary question : I would like to populate pluginProps[u'statesKeys'] directly from the device configuration UI using a button. Methods associated to buttons are formated as following : myMethod(self, valuesDict, typeId, devId). I haven't problem with existing device

Code: Select all

dev = indigo.devices[devId]
devProperties = dev.pluginProps[u'statesKeys']
but for a new device, devId is equal to 0. So how can I have access to pluginProps ?
User avatar
jay (support)
Site Admin
Posts: 19232
Joined: Wed Mar 19, 2008 11:52 am
Location: Austin, Texas
Contact:

Re: Problem to update states list

Post by jay (support) »

pluginProps don't exist for new devices because the device hasn't been saved yet. Rather, you should catch the deviceCreated(self,dev) method (described in the plugin.py section of the docs). You will get the completed dev instance in that method and you can add new states, etc., based on the plugin's config. There is also a deviceUpdated(self, dev) method that you can implement as well which will handle edits.

I have to ask - why would you want to save a states list in a property when the states are already part of the object - that seems unnecessarily redundant.
Jay (Indigo Support)
Twitter | Facebook | LinkedIn
User avatar
Juju
Posts: 108
Joined: Wed Aug 31, 2011 10:16 am
Location: Toulouse - FRANCE

Re: Problem to update states list

Post by Juju »

As explained, I catch the custom states by reading data through a serial port. This process is started by clicking a button in the device config UI. So the necessary data is available when the device config UI is open, but not after. Perhaps I could store the data inside the plugin instance as a property, and treat it in the deviceCreated() method when the device is created and its ID defined.

I will try to answer to your question Jay. The device states are updated when the method getDeviceStateList() is called. When this method is executed, I haven't the necessary data to build the custom states, as I have to (and I can't) read it through the serial port (it is already opened by the communication thread with the device).
So I make this with 2 steps :
1) the communication thread analyse and treat continuously data sent by the device, and specialy maintain an up to date states list in the device properties (and warn when the states need to be refreshed by calling stateListOrDisplayStateIdChanged() )
2) when the getDeviceStateList() is called, I have just to read the appropriate device property, and return a well formated states list.
User avatar
jay (support)
Site Admin
Posts: 19232
Joined: Wed Mar 19, 2008 11:52 am
Location: Austin, Texas
Contact:

Re: Problem to update states list

Post by jay (support) »

I think the easiest thing to do would be to add a hidden field to the device config ui - then have your button method add the necessary data to that field. If it's complex data, then just encode/decode it in XML or JSON - we include simplejson and XML is built in to Python. JSON is particularly easy to use (IMO) for these types of ad-hoc object-to-string-to-object conversions. Anyway, use the hidden field to store your states list for later processing.
Jay (Indigo Support)
Twitter | Facebook | LinkedIn
User avatar
berkinet
Posts: 3441
Joined: Tue Nov 18, 2008 2:08 pm
Location: Berkeley, CA, USA & Mougins, France

Re: Problem to update states list

Post by berkinet »

Juju wrote:... I haven't the necessary data to build the custom states, as I have to (and I can't) read it through the serial port (it is already opened by the communication thread with the device). ...
I think there may be another approach you might try. When you first open your serial communications channel, provide a method in that thread that you can call to get the information you need. I have posted a brief description on how I did this in another discussion.
User avatar
Juju
Posts: 108
Joined: Wed Aug 31, 2011 10:16 am
Location: Toulouse - FRANCE

Re: Problem to update states list

Post by Juju »

Jay, I think your idea is the best one. I will try this.
Locked

Return to “Extending Indigo with Plugins and Python”