Accessing State Variable from Another SmartApp, Possible?


(Patrick Stuart [@pstuart]) #1

So, I want to get a value from one SmartApp that I’m storing in a state variable from another SmartApp.

Besides creating an OAUTH endpoint and querying it via an HTTPGET, is there any other way to get a variable from another smartapp?

Was thinking of setting up a virtual devicetype as a child, setting the attributes and then reading the attributes from the other app, but this creates a nightmare for testing…

Anyway, anyone know if you can access a state variable from one installed app to another?


(Brian Smith) #2

I do not…but I like the possibilities this discussion will open up. Where’s the Dr. Evil emoticon?


(Chuck Pearce) #3

From my experience, each smartapp and device type hold a unique container set by their ID. Device types that are children of a parent smartapp can access their state variables but can not modify them directly or only via calling a sendEvent after being subscribed to the device.

You should be able to do this if you subscribe to the device type, have it emit a state, then handle that event via the subscription handler.


(Keith Croshaw) #4

When I first discovered state variables I think someone specifically told me no. I can’t remember if it was Jim or not. I’d reach out to him for the official word. I wish you could at the very least hardcode in that long string of characters that represents your SmartApp in ST’s eyes.


(Bruce) #5

What about using a virtual dimmer – you could pass a small int that way.


(Mike Maxwell) #6

using a virtual device would work, and it’s doesn’t need to be a child device of a smart app.
app 1 calls a custom device method including the state variable as parameter to the custom method.
The custom device method uses sendEvent with the data key and app 1’s value in the map to update app 2.


(Patrick Stuart [@pstuart]) #7

yeah, virtual device seems the only way without using OAUTH across the two smartApps


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #8

SmartApps can’t directly access each other’s data and nor can Devices. This is to highly granular security isolation… A lighting SmartApp can’t access the state of a lock or alarm SmartApp.

Any device, however, including virtual ones of arbitrary types, can be selected by the user in multiple SmartApps, so devices are perfect as shared data (Attribute) storeage. I even suggest that a Capability “sharedDataStorage” or similar, would be handy to delineate such virtual Devices with this purpose.

*Of course, the platform could also be enhanced to allow the definition of “shared memory” SmartApps… ie, families that obviously are interconnected, sub-routine SmartApps, etc… *


(Bruce) #9

Yea, and potentially buy yourself a world of headache with asynchronicity. Asynchronous processes that talk to each other through shared memory can be a big mess. Of course, none of us would do that…


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #10

Good point.

Well… Perhaps they an “App Family” message passing system (message / event queue) that doesn’t require an intermediary Device… i.e., mulit-thread safe inter-app communication).

For now, I’m fine with using Virtual Devices, but I recommend using approximate device names and ad hoc Attribute names. Create multiple instances too, rather than sharing unrelated Virtual Devices.


(Patrick Stuart [@pstuart]) #11

The more I think about it, maybe the OAUTH2 endpoint idea is a far better solution.

SmartApp 1 creates endpoints that respond to request with any internally stored var that we want to make available.

SmartApp 2 calls the API endpoint for SmartApp1 and requests and receives the variable.

This saves the end user from a confusing “Virtual” device that has no real purpose other than storing data. On top of it, this data is now available to the end user, which might not be ideal.

I think I have my theoretical answer, now to put it into action and figure out how to ask the user to do the OAUTH2 handshake inside SmartApp 2, configuration window.

Think it will work, will write a proof of concept soon. Thoughts?


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #12

Hmmm…

I guess there are pros and cons to both methods (Virtual “Data Storage” Device(s)) vs. OAUTH2 end points in the related SmartApps, so now I’m ambivalent. Perhaps it depends on the use case, and both are appropriate for different circumstances.

I have less experience with the latter, so I can’t compare them well. I think the OAUTH method could seem more complicated or risky to some programmers, as it is establishing direct data access via a web URL (no?), and that may seem unnecessary for a otherwise entirely “internal” SmartApps.

The former method isn’t exactly simple at the moment due to the need to instantiate the Virtual Device(s) manually in the IDE. Sometimes these may make extra sense though, IF the Attribute(s) can carry some meaning in their value that is shareable and can be depicted in the Things view. For example, a Virtual Binary Switch showing “armed” / “disarmed” for an Zone Alarm mode is rather useful, and is safer than using the location.mode global, since location.mode has no security on it (any SmartApp in the account can read and modify Mode!!!), and Mode is used for many different overlapping purposes. Using a Virtual Device for this example shared data (i.e., Zone Armed State) makes the state immediately visible and can even let the user directly alter the state by clicking the Virtual Switch. There are more exotic examples – the general principle being that if the “shared data” (the data to be communicated between SmartApps) has some clear and secure meaning to users, then a Virtual Device that represents and even manipulates, this data, is possibly a useful construct and a strong “pro” for this method vs. OAUTH.


(Patrick Stuart [@pstuart]) #13

Yeah, the virtual device can be deleted and would break the usage case I am talking about.

Simply uninstalling either smartApp would break the other, but in this case, two smartApps can be tied together providing OUATH2 level security and user authentication token.

Yeah, it seems overkill compared to a functional equivalent of this:

def x = smartApp.guid.state.varname

This should really be doable, what is the harm to the end user or platform?

Instead, I need to roundtrip an API call and expose that var. Granted, it shouldn’t route outside the cloud platform, but still, it should be much easier to exchange states between smartApps.


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #14

The risk is primarily security related. SmartApps are granted access to individual specific Device instances (for both read / write purposes – read Attributes / call Commands), explicitly by the user at installation time. A SmartApp that controls lights cannot open locks unless that lock was requested by Capability in preferences{ input } and subsequently granted by the user’s checkbox selection.

If one SmartApp could arbitrarily read the state variables of another SmartApp, then SmartThings would need to add another granular security authorization mechanism (i.e., in addition to Device Instance Authorization by SmartApp, and OAUTH for URL based access).


(Bruce) #15

Why can’t you combine the two SmartApps into one?


(Patrick Stuart [@pstuart]) #16

Well, a couple of reasons,

One, code simplicity, to get what I want from a subscribed device and then look up a value via a database online via httpget should be just stored in one location and then be accessible to various other smartapps as needed.

Two, no need to call this multiple times, having to insert the call in each smartapp, or expand the smartApp functionality.

The reality is ST doesn’t have any reusable code blocks available to developers across apps. This would be a way to get around that.

Have a master SmartApp that contains simple, reusable functions, call them via an API call and get the result, even pass in variables via the API.

One spot for the code, many SmartApps can then take advantage of it. One spot to fix the code as well, versus finding said function across dozens of simple SmartApps.


(Bruce) #17

I had a similar idea, although much simpler than what you’re describing.

The granularity of SmartApps is appealing for many reasons. But it would be useful to have someway to have “master apps” that hold some information available to other apps. The user sets some “master preferences” in the “master app”, and then when the user needs an instance of a functional app, it can reference the “master preferences”.

Would a global state variable do it for you? globalState.thisVar Location specific.


(Bruce) #18

Replying to myself: A host of issues arise, e.g. garbage collection. Who maintains the globalState? How is it edited? etc…


(Patrick Stuart [@pstuart]) #19

Yeah, essentially turning the master SmartApp into an API endpoint for other SmartApps to access would be the ideal state, but complicates it with the challenge of hooking up to the API, authorization, etc. Painful for the end user, simple for the developer…

I doubt a global state var would ever be allowed, but a hub or location state would be nice to have.

Right now, about a dozen of my smartapps have the same damn functions. I hate having to copy and paste 5 different functions to all those apps and recently, due to a platform change, I needed to update one of those functions on every smartapp.

There has to be a better way to reuse code and share variables across smartapps (and devices)


(Bruce) #20

Yeah, I meant hub or location “global”. But that has lots of problems, and I can see reasons to stay away from it.

Maybe that leads to “publicState”, a state variable specific to an app (which solves the ownership problem), but is available outside the app. It would be something an app could subscribe to from a user preference (name of app?), some way to create a linkage (detect SmartApp using SmartApp for uninstall safety). The biggest problem I see with this is that there is no app object, no way to select an app with a preference. One could just use a string, but that seems hokey.