Defining custom device properties?

Posted on
Tue Dec 04, 2018 11:19 am
geoffsharris offline
Posts: 21
Joined: Nov 26, 2012

Defining custom device properties?

Hi,

Trying my first attempt at making a plugin with custom devices type. I am wondering if there is a way to add to the base list of device properties or additional properties can only be done in the ownerProps?

For example, I would like to add an access token as a device property so I could access it as dev.accessToken rather than setting it as a dev.ownerProps['accessToken']. (I have a good reason to do this on a per device basis rather than as a global plugin setting)

If there is currently not a way, what would it take to add a <Props> <Prop id "name of prop> </Prop></Props> type of configuration added to the device xml import function? Obviously additional properties can be added as they are for the sprinkler and other indigo device types.

Thanks,

Geoff

Posted on
Tue Dec 04, 2018 12:16 pm
jay (support) offline
Site Admin
User avatar
Posts: 15005
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Defining custom device properties?

Device (and subclass) instance properties are not expandable/extendable by developers. This was a conscious decision so as to avoid namespace conflicts. The states and props dictionaries are the places where you can expand.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Tue Dec 04, 2018 2:32 pm
geoffsharris offline
Posts: 21
Joined: Nov 26, 2012

Re: Defining custom device properties?

Thanks Jay.

Makes sense. In the future would there be a way to also have a deviceProps? Makes sense why you chose to have a separate object for developers so they don't create namespace issues (I suspect address would be high on the list of name conflicts). However, ownerProps isn't all that intuitive to me vs. deviceProps. Also using the pluginProps again is not intuitive (at least to me) as you are using the plugin to define properties of a plugin device, not the plugin itself.

I'm a pretty mediocre python hacker. Is there a way for me to make an alias for either ownerProps or pluginProps in my plugin code so I could use deviceProps for access and pluginDeviceProps to update them?

Thanks,

Geoff

Posted on
Wed Dec 05, 2018 10:38 am
jay (support) offline
Site Admin
User avatar
Posts: 15005
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Defining custom device properties?

geoffsharris wrote:
In the future would there be a way to also have a deviceProps? Makes sense why you chose to have a separate object for developers so they don't create namespace issues (I suspect address would be high on the list of name conflicts). However, ownerProps isn't all that intuitive to me vs. deviceProps.


ownerProps are for device instance properties. More specifically, every device instance has a globalProps dictionary. Inside that dictionary are properties added by your plugin (the owner) and potentially properties added by other plugins (the Global Property Manager plugin uses this technique to add random properties to device instances for instance). The key is the ID of the plugin that "owns" that particular dictionary. Any props your plugin adds (as the owner of the device) are added to globalProps using the plugin's ID as the key. The ownerProps instance property is just a shortcut. Only the plugin that owns the dict can make changes, thus making them safe from tampering from other locations.

So, in fact, if we were to use deviceProps, it would make more sense for it to represent what we currently call globalProps since it's all potential properties added to a device instance by any plugin. Leaving ownerProps as the shortcut way of getting to only those properties that are managed by the owner of the device instance.

geoffsharris wrote:
Also using the pluginProps again is not intuitive (at least to me) as you are using the plugin to define properties of a plugin device, not the plugin itself.


Device-specific properties shouldn't be stored in pluginProps. That dict should only be used for global settings for the operation of your plugin and not specific to devices, actions, etc.

geoffsharris wrote:
I'm a pretty mediocre python hacker. Is there a way for me to make an alias for either ownerProps or pluginProps in my plugin code so I could use deviceProps for access and pluginDeviceProps to update them?


My recommendation is to use the API as specified. If you ever need help with an issue in your plugin (or you allow open-source contributions), it'll be much easier for others to help/contribute if they don't have to understand all the API wrappers/modifications you've made in your code. This is really just best practices for any type of software development IMO - only create your own internal API when it actually augments functionality in some way.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Dec 05, 2018 6:39 pm
geoffsharris offline
Posts: 21
Joined: Nov 26, 2012

Re: Defining custom device properties?

Hi Jay,

Thanks for your patience. Just to use a concrete example. I'm working on a plugin to connect to to multiple IoT cloud connected devices. I use a device token to connect to the cloud that is stored as a pluginPref. Since there could be other devices accessed with a different token, I would like to find a location where I can store the access token for each individual device rather than for the plugin as a whole. I also have a list of functions and variables that are accessible through the cloud API that I would like to store on a per device basis. I would like these to be persistent with the device, ie not refreshed every time the plugin is restarted and I can easily make an "action" to refresh them if it is needed. I do not need or think it is very helpful to the user to have them stored as device states, but I would like them to be accessible to the plugin so I can make the API calls. If it was you, how/where would you go about storing this info? I apologize if this is a read the manual situation, but I haven't found a clear answer to where to store persistent information on a per device basis that is for device function rather than as user accessible states.

Thanks,

Geoff

Posted on
Thu Dec 06, 2018 1:32 pm
jay (support) offline
Site Admin
User avatar
Posts: 15005
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Defining custom device properties?

Sorry, I got wrapped around the terminology in my previous reply (note to self, pluginPrefs != pluginProps). To clarify, from within your plugin's code:

  1. In the __init__ method, pluginPrefs are the global plugin properties that are defined in the plugin's config dialog (or added directly by you at any time for that matter)
  2. Where dev is an Indigo instance of one of your devices defined in Devices.xml, dev.pluginProps (and dev.ownerProps) are just shortcuts to globalProps["your.plugin.id"] and are specific to the device instance.
  3. Where anotherdevice is an Indigo device instance not owned by your plugin, anotherdevice.pluginProps are a shortcut to globalProps["your.plugin.id"] (which you can modify at will) and anotherdevice.ownerProps are a shortcut to globalProps["owners.plugin.id"] (which may only be modified by the owner of the plugin)

Hopefully this clarifies. So, any config item that's specific to a device instance should be stored in your device instance's pluginProps (which is the same shortcut as ownerProps when used from inside your plugin). These aren't editable by anything except your plugin and aren't visible to users in the UI (but they can open a scripting shell and inspect an instance and see them there but not change them). In your example, this is where you'd store the token since it's specific to the device instance.

geoffsharris wrote:
I also have a list of functions and variables that are accessible through the cloud API that I would like to store on a per device basis. I would like these to be persistent with the device, ie not refreshed every time the plugin is restarted and I can easily make an "action" to refresh them if it is needed. I do not need or think it is very helpful to the user to have them stored as device states, but I would like them to be accessible to the plugin so I can make the API calls. If it was you, how/where would you go about storing this info? I apologize if this is a read the manual situation, but I haven't found a clear answer to where to store persistent information on a per device basis that is for device function rather than as user accessible states.


I'm not clear on what you mean by "store on a per device basis", but I'm going to guess that you mean a specific device type (not Indigo device type but some type defined on the remote system). If that's the case, then I'd create my own Python class(es) to represent those device types. You could then instantiate an instance of the appropriate type every time an Indigo device that you define is started (in the deviceStartComm method). Pass in whatever you need from the Indigo instance into your custom device (like the token) and store a plugin-wide map that maps an Indigo instance to your instance.

Then, when any of the Indigo API defined actions (or your custom actions) get called with an Indigo device instance, you look up the associated custom object instance and call the appropriate methods on it to perform the action.

When the deviceStopComm method is called, delete that from your map.

So your class is a proxy object for the Indigo device instance object, one that knows how to do the specifics for your device type. I think this (or a similar) pattern is what's used by many developers (and by several of our internal plugins).

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Thu Dec 06, 2018 3:34 pm
geoffsharris offline
Posts: 21
Joined: Nov 26, 2012

Re: Defining custom device properties?

Ok this is great and clear. Thank you. Per device instance properties can be stored in globalProps and pluginProps and ownerProps alias to the same location. If I want to add them I use pluginProps and they can be accessed from within the plugin by ownerProps, pluginProps or globalProps.

Got it.

The devices is a prototype device with a list of variables and functions that are unique to each device. The accessToken is a per account basis, so several unique devices with unique functions and variables may have the same accessToken, but other devices may have their own tokens. I've set up a plugin preference that stores the token that can then be used to look up the cloud unique device IDs. When I create a device in indigo I want to store the cloud deviceID, cloudDeviceName, a list of functions and a list of variables and the specific accessToken that can be used to access that device. That way if I look up another cloud account with a different accessToken, I can create new devices, and store that different access token in the pluginProps for that device. This way every device instance has the necessary info to access the cloud API.

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 2 guests