SendEvent and currentValue

I dont see a whole lot of difference between setting the value of an attribute or calling a method such as device.on();. Both make changes to that particular device. In my case the attribute is really a placeholder for the name of the last action/activity that changed the state of the switch. What ever its value is set at does not change in any way the behavior of the device.

The above example was used to keep it simple. What my ultimate goal is to know how/what changed the switch.
The app has 2 main purposes

  1. Using the ST app, a virtual switch turns on/off a wemo switch via httpGet
  2. Receives on/off commands from Wemo to update the ST switch so that it reflect the true state of the Wemo.

Problems.

  1. When a Wemo is changed via outside app or manual switched on/off, my app receives the device id that changed and updates the ST virtual switch which causes the onEvent to trigger which causes my app to fire of httpGet. Wemo does not change anything if the state it received is the same as the current state of the switch however, it does trigger an event which is once again sent back to my ST app.
  2. When my app changes the virtual switch it does the httpGet to turn on/of the Wemo which responds with sendHTTP which my app picks up and most of the time it is discarded. If not, it returns the same event back to the wemo…

Both these problems would never be noticed if one simply does not press a switch two or more times in rapid succession . Even then thing may behave perfectly well but when they dont… :frowning:

To make it go whacky…

With my ST SmartApp, press a Switch on then off in quick succession.
App turns on the ST virtual switch and send on command to Wemo App.
Wemo receives/process on command
App turns off the ST virtual switch and send off command to Wemo App.
Wemo app triggers sendHTTP event in response to the on commandwhich is sent back to ST smart app.
Wemo receives/process off command
Considering the virtual switch was off, the ST app responds and turns on the ST virtual switch which triggers an on event which sends the command back to Wemo app.
Wemo app triggers sendHTTP event in response to the off command which is sent back to ST smart app.
repeat and rinse :flushed:

I use it to store / update custom attributes and to ensure that my hue bulbs immediately show the correct state (without having to wait for or cause an additional poll of the hue bridge).

Do you update these attributes via a SmartApp? If so, do you have an example?

Yes - but the code in the smartapp just calls a function of the custom device type code. The real magic is in the code for the device. For example, I have a custom device type for Hue Bulbs. I added custom attributes, such as “attribute offTime” (a number), “attribute sceneName” (a string) and a few others. I then added custom commands, such as “saveScene()”, which is used to save values for these custom attributes. Here’s the code for the “saveScene()” command in my custom Hue Bulb device:

def saveScene(inValue, String inMode, Number inOffTime) {

log.debug “APHbulb: saveScene:”

if ( inMode ) {
  log.debug "sceneName to: ${inMode}"
  sendEvent(name: "sceneName", value: inMode, isStateChange: true)
}	
if ( inOffTime ) {
  	if ( inOffTime == 0 ) {
  	log.debug "Setting offTime to: default 30 b/c inOffTime is 0."
      sendEvent(name: "offTime", value: 30, isStateChange: true)
	} else {
  	log.debug "Setting offTime to: ${inOffTime}"
      sendEvent(name: "offTime", value: inOffTime, isStateChange: true)
	}	

}
if (!inValue.transitiontime) {
inValue << [transitiontime: 3]
}

if (inValue.hue && inValue.saturation) {
    sendEvent(name: "sceneHue", value: inValue.hue)  
    log.debug "Setting sceneHue to: ${inValue.hue}."
  sendEvent(name: "sceneSat", value: inValue.saturation)
    log.debug "Setting sceneSat to: ${inValue.saturation}."

}

if (inValue.level) {
sendEvent(name: “sceneLevel”, value: inValue.level)
log.debug “Setting sceneLevel to: ${inValue.level}.”
}

}

As you can see, I save the incoming value for inMode to the “sceneName” attribute by calling sendEvent (tip: I’ve found that you need to include isStateChange: true if you want the data to be immediately reflected in the device tiles). Same for for inOffTime, which I save to the “offTime” attribute. The “inValue” value is an array that contains 3 values that I then save to 3 different attributes (sceneLevel, sceneSat, and sceneHue).

Once you have added custom attributes and commands to your device type, any SmartApp can then call it like any other command for that device. An example of how to use the “saveScene()” command discussed above would be:

hues?.each {
it.saveScene([level: 80, saturation: 100, hue: 70, transitiontime: 3], “Daytime”, 30)
}

Any SmartApp can then pull the data from a custom attribute just like you would normally. For example, if I want to know the value for “offTime”:

def myOffTime = theHue.currentValue(“offTime”)

Hope this helps.

-Tony

PS: Also - I plan to post (within the next day or so) the complete code for the smartapps and devices I created. Basically, I use these custom attributes & commands to share variables between multiple SmartApps

3 Likes

This is very cool, and solves many issues in a clean way. Sharing global context information between apps is sometimes needed. Having multiple apps select the same “specialized” device to gain access to its attributes works well. Thanks!!

1 Like

Very nice indeed. Over the next few days I’ll modify my on/off button device type to (hopefully) address issues I have between my SmartApp and external Wemo apps. :thumbsup:

1 Like

Custom Attributes (which I call “ad hoc Attributes” to differentiate them from the official Attributes that are in the Capability definitions…), are more likely to have good cases for modification by one or more SmartApps.

For example, I 100% agree with Bruce…

And the Custom Device you’ve written for Hue Bulb is an excellent example. :star:

In most cases, calling a Device’s Command (“device.on()”) does more than just change the value of an Attribute … it actually performs an action (i.e., such as sending a message to the physical device to switch it on).

If you use other methods to directly change “physically-related Attributes”, then you are bypassing the functionality of the official contracted Command.

The concept is very similar to the rule (convention?) in Object Oriented programming that says Attributes should not be public, but should only be manipulated internally and/or by setter methods, so that these methods can immediately “handle” the implications of changing the Attribute value.

But as we’ve seen from the above examples, there’s nothing wrong with manipulating Attribute values internally (entirely inside the Device Handler), since the Device Handler knows what it is doing. And Service Manager SmartApps are just extensions of the Device Handler, so that is fine too.

And, to repeat the concept of the beginning of this post, what you do with “ad hoc / custom Attributes” is, presently, free form and undefined in SmartThings. I think it would be good if ST provided more ways to manage these (and added more official Capabilities, actually, and added “optional” extended Attributes and Commands to existing Capabilities, etc., etc.); but there’s no use throwing away the great power of the flexibility we have in the meantime.


I fear that the free-formness of all this, however, will make it more difficult for SmartThings to “certify” submitted Device Types and SmartApps for publication. As ST studies the creative stuff we come up with, it would be helpful for them to at least document more recommended best practices and certification rules.

I posted my apps and devices that I mentioned a few days ago. If you’re still interested, check out FLEXi Lighting - a flexible system for lighting scenes (Hues, dimmers, and switches) - #2 by tslagle13

2 Likes

i was working on trying to build something like this to solve custom settings communication across different smartapps. a specialized DH that is a virtual device that stores these global custom attributes for various things that other apps can access by subscribing to attributes published as events which are both subscribed and published by this DH. may not have used all the right terms … but, something like that. :slight_smile:

have almost no experience building DH or smartapps. any pointers would be much appreciated.

thanks!

1 Like

This is a great idea and has been discussed a few times on the Forum.

In a way, every “Virtual Switch” is used for this purpose, though it only contains a single binary (boolean) value: switch( on, off ).

There are some alternative approaches, CoRE, for example, publishes Events via the Location object. It’s unofficial, but seems to work. Since every SmartApp has access to Location, there is no need to use a DH between SmartApps; but this is a less secure approach.

thank you. sounds like it might be worth figuring out something like this in a standardized way. :smile:

thanks, will take a look at webcore code. though i use webcore extensively havent had a reason to dig in before. :slight_smile:

thinking about this a bit more … while this works for core/webcore and exchanging data within the webcore framework … seems like it wouldnt work for custom attributes if i wanted to exchange data between my own custom smartapps and webcore pistons.

though … i could easily be missing something here? :slight_smile:

thank you.

I have a feeling that webCoRE is flexible enough to handle it (or could be enhanced…), but I’m not sufficiently familiar to know for certain.

Ask on the webCoRE forum. :slight_smile:

will do. thank you.