Does the smartthings cloud run on a model of eventual consistency? I’m really confused about the runtime environment.
In the following simulator output is the debug output from a smartapp which is a bit like the ‘gentle wakeup’ app. Every 5 seconds, it is supposed to update the state.level by +5 percent, and set that level in the dimmer. Things seem ok until I start to look at the dimmer value via a subscription to the “level” attribute.
In the app:
- “increment” updates the state.level and calls “setAllDimmers”
- “checkLevel” outputs the state.level and the dimmer level
- “setAllDimmers” sets the level on all the configured dimmers
21:09:01: debug in setAllDimmers: setting dimmer to level 15 21:09:01: debug in increment: calling setAllDimmers with level 15 21:09:01: debug in increment: state level is 15 21:09:07: debug in checkLevel: current state of Dimmer Switch is on: 15 21:09:07: debug in checkLevel: state level 10 21:08:56: debug in checkLevel: current state of Dimmer Switch is on: 10 21:08:56: debug in checkLevel: state level 10 21:08:52: trace Scheduling 'increment' for InstalledSmartApp: 9e7ebd73-309b-42a0-8d2f-85dc4868ef93 21:08:51: trace Deleting scheduled job 'increment' for InstalledSmartApp: 9e7ebd73-309b-42a0-8d2f-85dc4868ef93 21:08:51: debug in increment: calling runIn with duration 5 and function 'increment' 21:08:50: debug in setAllDimmers: setting dimmer to level 10 21:08:50: debug in increment: calling setAllDimmers with level 10 21:08:50: debug in increment: state level is 10
In log order:
- state level is set to 10, dimmer is set to 10
- subscription fires, and state and dimmer are 10 (so far so good)
- subscription fires, state is 10, dimmer is 15 (huh?)
- state level is set to 15, dimmer is set to 15
In time order:
- state level is set to 10, dimmer is set to 10
- subscription fires, and state and dimmer are 10
- state level is set to 15, dimmer is set to 15
- subscription fires, state is 10, dimmer is 15 (huh?)
Neither of these event orderings makes sense to me. Does anyone have any insight?
Here’s the code, if anyone is interested:
preferences {
section("When I touch the app, turn on slowly...") {
input "dimmers", "capability.switchLevel", title: "Which lights to slowly raise?", description: "Tap to select lights", multiple: true
input "startLevel", "number", title: "What level should the lights start at?", description: "0 (default)", required: false
input "stepSize", "number", title: "What percent should the lights change?", description: "5 (default)", required: false
input "numSteps", "number", title: "How many steps should be taken?", description: "10 (default)", required: false
input "stepDuration", "number", title: "How long should each step take in seconds?", description: "5 (default)", required: false
}
}
def installed() {
defaultState()
}
def updated() {
unsubscribe()
defaultState()
}
def defaultState() {
state.startLevel = startLevel ?: 0
state.stepSize = stepSize ?: 5
state.numSteps = numSteps ?: 10
state.stepDuration = stepDuration ?: 5
state.level = state.startLevel
state.endLevel = state.startLevel + (state.stepSize * state.numSteps)
subscribe(app, appTouch)
subscribe(dimmers, "level", checkLevel)
debug "...state reset."
}
def checkLevel(event) {
debug "in checkLevel: state level ${state.level}"
// Check that all the dimmers are at the desired state
dimmers.each { dimmer ->
int current_level = dimmer.currentValue("level")
String status = dimmer.currentValue("switch")
debug "in checkLevel: current state of ${dimmer.name} is ${status}: ${current_level}"
}
}
def appTouch(event) {
debug event
debug "app was touched."
debug "Initiating sunrise..."
increment()
}
def increment() {
state.level = state.level + state.stepSize
debug "in increment: state level is ${state.level}"
if (state.level > state.endLevel) {
debug "done"
return
}
debug "in increment: calling setAllDimmers with level ${state.level}"
setAllDimmers(state.level)
debug "in increment: calling runIn with duration ${state.stepDuration} and function 'increment'"
runIn(state.stepDuration, "increment")
}
def setAllDimmers(level) {
dimmers.each { dimmer ->
debug "in setAllDimmers: setting dimmer to level ${level}"
dimmer.setLevel(level)
}
}
private debug(message) {
log.debug message
}