SendEvent and currentValue


#1

I have a modified on/off button device type that has the following functions:

def on() {
def last = device.currentValue(“lastState”)
sendEvent(name: “lastState”, value: last)
sendEvent(name: “switch”, value: “on”)
}

def off() {
//def last = device.currentValue(“lastState”)
sendEvent(name: “lastState”, value: device.latestValue(“lastState”))
sendEvent(name: “switch”, value: “off”)
}

Within a smartapp I have one line that print to the log file:

log.debug “*** function onHandler **** event has received the command [ON] when the current state of the device is ${device.currentValue(‘lastState’)}”

as well as

log.debug “*** function offHandler **** event has received the command [OFF] when the CURRENT state of the device is ${device.currentValue(‘lastState’)}”

In the above example, the currentValue(‘lastState’) always prints what ever the first sendEvent(name: “lastState”, value: last) was set to. Once this value has been set, nothing seems to change it EXCEPT

def on() {
sendEvent(name: “lastState”, value: “off”)
sendEvent(name: “switch”, value: “on”)
}

def off() {
sendEvent(name: “lastState”, value:"on)
sendEvent(name: “switch”, value: “off”)
}

By hard-coding a value into the sendEvent, the output shown by the SmartApp is always correct. I dont understand how device.currentValue(‘lastState’) shows the correct (changed) value within the SmartApp but that def last = device.currentValue(“lastState”) within the device type only gets the initial value.

Confused and need help


Device attribute syntax from within a device type - revisited
(Bruce) #2

Where in the device type do you set lastState? It won’t magically get a value.


#3

here is all the code for the device type

metadata {
// Automatically generated. Make future change here.
definition (name: “On/Off Button Tile Trial”, namespace: “smartthings”, author: “SmartThings”) {
attribute “lastState”, "string"
capability "Actuator"
capability "Switch"
capability “Sensor”
}

// simulator metadata
simulator {
}

// UI tile definitions
tiles {
standardTile(“button”, “device.switch”, width: 2, height: 2, canChangeIcon: true) {
state “off”, label: ‘Off’, action: “switch.on”, icon: “st.switches.switch.off”, backgroundColor: “#ffffff”, nextState: "on"
state “on”, label: ‘On’, action: “switch.off”, icon: “st.switches.switch.on”, backgroundColor: “#79b821”, nextState: "off"
state “wemoS”
}
main "button"
details “button”
}
}

def parse(String description) {
}

def on() {
def last = device.currentValue(“lastState”)
sendEvent(name: “lastState”, value: last) // does not work correctly
sendEvent(name: “lastState”, value: “off”) // works everytime

sendEvent(name: “switch”, value: “on”)
}

def off() {
def last = device.latesttValue(“lastState”)
sendEvent(name: “lastState”, value: last) // does not work correctly
sendEvent(name: “lastState”, value: “on”) // works everytime
sendEvent(name: “switch”, value: “off”)
}


#4

In addition to the above, a Smartapp contains this code

def onHandler(evt) {
def device = switches.find { evt.deviceId == it.id }
// The next statement will always display either on or off for the ${device.currentValue(‘lastState’)} when within the Device type code I have sendEvent(name: “lastState”, value: last) but will display off if I change the device type code to sendEvent(name: “lastState”, value: “off”)
log.debug “*** function onHandler **** event has received the command [ON] when the CURRENT state of the device is ${device.currentValue(‘lastState’)}”
}

def offHandler(evt) {
def device = switches.find { evt.deviceId == it.id }
// The next statement will always display either on or off for the ${device.currentValue(‘lastState’)} when within the Device type code I have sendEvent(name: “lastState”, value: last) but will display on if I change the device type code to sendEvent(name: “lastState”, value: “on”)
log.debug “*** function offHandler **** event has received the command [OFF] when the CURRENT state of the device is ${device.currentValue(‘lastState’)}”
}


(John S) #5

I know this seems odd, but try

def last = "" + device.latestValue("lastState")

for both on() and off()


(Bruce) #6

Minor, typo in your code for latesttValue. Try this:

def last = device.currentValue("switch")

instead of device.currentValue("lastState")

That sends the value that existed before the most recent on or off.


(Bruce) #7

Why are you trying to send the prior state? Why track it in the device type, instead of in the app? With an on/off device, don’t you always know it’s prior state? Doesn’t make much sense out of context.


#8

Thanks but unfortuantely it made no difference. When I toggled the switch on,off,on and off, this is what the log showed for the SmartApp

2:28:35 PM: debug *** function offHandler **** event has received the command [OFF] when the CURRENT state of the device is ON
2:28:32 PM: debug *** function onHandler **** event has received the command [ON] when the CURRENT state of the device is ON
2:28:17 PM: debug *** function offHandler **** event has received the command [OFF] when the CURRENT state of the device is ON
2:28:06 PM: debug *** function onHandler **** event has received the command [ON] when the CURRENT state of the device is ON

The fact that the log showed [state of the device is ON] regardless of which entry in the log you lok at is puzzling as the uppercase ON value was one I set hours ago and have never been able to change it unless I hardcode the value field in the sendEvent


#9

Only in the Post. I actually used currentValue in both but wanted to show I did try latestValue as well. Neither worked.

Exactly. The smartapp has an endpoint api receiving on/off events from Wemo . The app also sends on/off events to wemo. Problem. sometimes the same device gets duplicate on or off events.

Using state values are totally unstable. Somewhere I have another post about their use and problems but in brief.
In the smartapp

def caller(){
funct1()
funct2()
}

def funct1() {
state.lastState=1
}

def funct2() {
log.debug “State=${state.lastState}”
// the output may show 1 as set above BUT that is totally unreliable. Sometime the log print “state=0”
}
}


(Bruce) #10

I didn’t try your app. I just watched the log for the device itself, and put log.debug commands in the device type. What I saw was lastState “off” when the device was turned on, and vice versa. Isn’t that what you wanted?


#11

exactly…can you showe me what you did in the code


(Bruce) #12

Here is the code that works for me:

def on() {
def last = device.currentValue("switch")
log.debug("On lastState = '$last'")
sendEvent(name: "lastState", value: last) // does not work correctly
//sendEvent(name: "lastState", value: "off") // works everytime

sendEvent(name: "switch", value: "on")
}

def off() {
def last = device.latestValue("switch")
log.debug("Off lastState = '$last'")
sendEvent(name: "lastState", value: last) // does not work correctly
//sendEvent(name: "lastState", value: "on") // works everytime
sendEvent(name: "switch", value: "off")
}

And here is the log:

11:46:42 AM MST: debug On lastState = 'off’
11:46:40 AM MST: debug Off lastState = 'on’
11:46:37 AM MST: debug On lastState = 'off’
11:46:32 AM MST: debug Off lastState = 'on’
11:46:25 AM MST: debug On lastState = ‘null’


(Bruce) #13

And one thing more: If you show the device in the IDE, you can see it’s current state for both “switch” and “lastState”. You have to refresh the page after each event, but it does show the correct values for both (one opposite the other).


(Eric R) #14

The difference that mattered, I think, was the lastState vs switch


(Bruce) #15

Yea, otherwise lastState is in a circular loop. The little test app works now as well.


#16

Thank you, thank you,thank you,thank you,thank you,thank you,thank you,thank you,thank you and thank you. I got it working in my smartapp as well :smile:


#17

for those who care, here is the clean code for device type :smile:

def on() {
def last = device.currentValue(“switch”)
log.debug(“On lastState = ‘$last’”)
sendEvent(name: “lastState”, value: last)
sendEvent(name: “switch”, value: “on”)
}

def off() {
def last = device.currentValue(“switch”)
log.debug(“On lastState = ‘$last’”)
sendEvent(name: “lastState”, value: last)
sendEvent(name: “switch”, value: “off”)
}


#18

One more question. So now that I can set lastState in the device type code, can I change it within a Smartapp as well. If so, how??


(Eric R) #19

You could create another command:

def setLastState(last) {
    sendEvent(name: "lastState", value: last)
}

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

Having a SmartApp “directlymess with the internal “State” of a physical device makes me queasy. I know there must be some very valid use cases, it just violates the paradigm, I think, IMHO.

A Device Instance that represents a physical device should know it’s own physical state, and the responsibility for managing the state value should be isolated to the Device Handler (and Service Manager SmartApp, but not other SmartApps…).

Or am I missing something that makes this a common use case?