indigo.Dict() within indigo.Dict() ?

Posted on
Tue Jul 25, 2017 11:19 am
autolog offline
Posts: 3988
Joined: Sep 10, 2013
Location: West Sussex, UK [GMT aka UTC]

indigo.Dict() within indigo.Dict() ?

I have something like the following code (summarised):
Code: Select all
  name = 'someData'
  props = dev.pluginProps
  if not 'STORED-DATA' in props:
    props['STORED-DATA'] = indigo.Dict()
  props['STORED-DATA'][name] = indigo.Dict()
  props['STORED-DATA'][name]['mode'] = 'D'
  dev.replacePluginPropsOnServer(props)

I am getting an error on the line setting mode to D ='key someData not found in dict'. It looks like the line:
Code: Select all
props['STORED-DATA'][name] = indigo.Dict()
isn't storing an indigo.Dict.

Am I missing something obvious here? - I probably am :wink:

Posted on
Tue Jul 25, 2017 12:36 pm
matt (support) offline
Site Admin
User avatar
Posts: 21416
Joined: Jan 27, 2003
Location: Texas

Re: indigo.Dict() within indigo.Dict() ?

indigo.Dict()'s are a bit special. In this case the issue is that accessing a value in an indigo.Dict() always returns a copy (not reference) of that object, so the props['STORED-DATA'] part of your props['STORED-DATA'][name] line is returning a copy of the dict and not an editable reference to the actual dict. So adding another indigo.Dict() to key [name] is just adding it to the temporary copy that is immediately destroyed since it wasn't assigned to a variable.

The workaround is to use the Indigo specific API setitem_in_item() as documented here. However, your use case more complicated because you have an indigo.Dict() (dev.pluginProps ) containing an indigo.Dict() (['STORED-DATA']) containing an indigo.Dict() ([name]). That extra level of embedding won't work with setitem_in_item() and there is no setitem_in_item_in_item().

Given that (2 levels deep of dict embedding), I think I would just cast STORED-DATA as a python dict while you manipulate it, then stuff it back into the props when you are done. Something like (untested!):

Code: Select all
  name = 'someData'
  props = dev.pluginProps
  storedData = dict(props['STORED-DATA']) if 'STORED-DATA' in props else dict()
  storedData[name] = dict()   # note if value at key name might already exist then you might have to cast this to a python dict() too: storedData[name] = dict(storedData[name])
  storedData[name]['mode'] = 'D'
  props['STORED-DATA'] = storedData
  dev.replacePluginPropsOnServer(props)


Clear as mud? :twisted:

Image

Posted on
Tue Jul 25, 2017 2:11 pm
autolog offline
Posts: 3988
Joined: Sep 10, 2013
Location: West Sussex, UK [GMT aka UTC]

Re: indigo.Dict() within indigo.Dict() ?

matt (support) wrote:
.... Clear as mud? :twisted:
Well it was thin enough for me to wade through it and using your example code, get it working - Thanks! :D

Posted on
Wed Jul 26, 2017 6:31 am
autolog offline
Posts: 3988
Joined: Sep 10, 2013
Location: West Sussex, UK [GMT aka UTC]

Re: indigo.Dict() within indigo.Dict() ?

The Indigo 7 documentation says:
Enhanced plugin valuesDict handling so that plugin methods that return a valuesDict can modify key/value pairs in an instance's pluginProps attribute even if there are no UI <Field> nodes defined for those pairs inside the Devices.xml, Events.xml, etc.


So following on from this question and loosely related, using Indigo 7 I have tried the following code within a Button press callback method within a device config:
Code: Select all
  qwerty = {}   # Also tried indigo.Dict() without success
  qwerty['A'] = 'A'
  qwerty['B'] = 'B'
  valuesDict['qwerty'] = qwerty
  valuesDict['abcdef'] = 'abcdef'
  return valuesDict
When I subsequently save the config and then print the device to the Indigo log, the qwerty field is missing but the abcdef field is present. Indigo gives no indication/error as to why the qwerty field is omitted.

I discovered that my code (in response to the initial question) wasn't working when I just ran it but confusingly was when I tested it in the debugger. I then realised that the difference was that in the debugger (as I was single stepping code) I was taking so long that the ConfigUI dialogue timed out and so the save didn't happen. I was updating the plugin props in the closeDeviceConfigUi and then these were getting "nuked" when the closeDeviceConfigUi returned to Indigo when it completed the update.
Hence thinking that I should use the ability to update valuesDict instead.

So what I am ideally looking to do is to update the pluginProps in the closeDeviceConfigUi but if I can't then I can do it on a button press by updating the valuesDict if it is possible to define a dictionary to it. The fallback is that I can have a number of fields suffixed with 01, 02, 03, ... 27 (as I know the limit). :)

Posted on
Wed Jul 26, 2017 9:57 am
jay (support) offline
Site Admin
User avatar
Posts: 18212
Joined: Mar 19, 2008
Location: Austin, Texas

Re: indigo.Dict() within indigo.Dict() ?

I think that adding the dict in that method isn't going to work without some code changes on our side.

Maybe a better workaround is to store your dict as a JSON string. That's easy to do:

Code: Select all
  import json
  qwerty = {}   # Also tried indigo.Dict() without success
  qwerty['A'] = 'A'
  qwerty['B'] = 'B'
  valuesDict['qwerty'] = json.dumps(qwerty)
  return valuesDict


Then you just have to remember whenever you use it to recreate the dict:

Code: Select all
import json
qwerty = json.loads(props["qwerty"])

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Jul 26, 2017 11:00 am
autolog offline
Posts: 3988
Joined: Sep 10, 2013
Location: West Sussex, UK [GMT aka UTC]

Re: indigo.Dict() within indigo.Dict() ?

Thanks Jay, that works. :D

I am still having to move the updating of the valuesDict/Props to an Add Button as I can't see how to do this update from the CloseConfig.
I read somewhere that the valuesDict at that stage is read only - so is it not possible in that method?

Posted on
Wed Jul 26, 2017 11:27 am
jay (support) offline
Site Admin
User avatar
Posts: 18212
Joined: Mar 19, 2008
Location: Austin, Texas

Re: indigo.Dict() within indigo.Dict() ?

I think in the close method it might be, but it's definitely not in the validate method, so you could probably do it there.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Jul 26, 2017 11:39 am
autolog offline
Posts: 3988
Joined: Sep 10, 2013
Location: West Sussex, UK [GMT aka UTC]

Re: indigo.Dict() within indigo.Dict() ?

jay (support) wrote:
I think in the close method it might be, but it's definitely not in the validate method, so you could probably do it there.

Good point :oops:

That solves the issues for me , thanks for the help :D

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 1 guest