is this the correct syntax to pass a parameter in runIn?
def speech1(msg) {
notify.speech(msg)
runIn(2,speech2, [data:msg])
}
def speech2(data) {
notify.speech(data)
}
is this the correct syntax to pass a parameter in runIn?
def speech1(msg) {
notify.speech(msg)
runIn(2,speech2, [data:msg])
}
def speech2(data) {
notify.speech(data)
}
Yes, as long as msg
is a Map
(the required data type for the data
parameter/value itself), which is not enforced in your code but isn't a problem if you know that's what you need.
See: Common Methods | Hubitat Documentation
Note that technically the handler method name is documented as a string, so runIn(2,speech2, [data:msg])
should be runIn(2,"speech2", [data:msg])
, but you'll normally find that this gets converted automatically, so it shouldn't be a problem either way.
MSG is a string. So do I need to do anything else with it?
What I am trying to do, I have HomePods that announce things. When more than one is selected they donβt talk at the same time. I want to make one particular one first, so delaying the other
Yes, you would need to put it in a Map
, as these are different data types, and required type is a Map
. There is an example in the docs I linked to that shows an example exactly like what you'd need, though there are many other ways you can do this (in terms of naming the keys or structuring the data -- it just has to be a Map
and not a String
, so the easiest thing is to make a key in the map with your desired string as the value, then retrieve that key from the map in your handler).
Im trying to pass a specific device across.
pick a device at random from a map, pass it to another method,
other method turn device on or off.
a) how do i pick the device details out of the map
b) is there any way to make the map smaller
void lightSwitching(){
log.debug "${app.label} lightSwitching - Running = $state.running"
if (state.running == true){
log.info "${app.label} lightSwitching True - running the Sim"
//random time
int randomTime = (0 - timeRan) + (Math.random() * (timeRan*2))
randomTime = randomTime + state.timeMin
log.debug "random time $randomTime"
int randomDev = Math.random() * lightControl.size()
log.debug "random device number $randomDev, ${lightControl.get(randomDev)}"
runIn(randomTime, switchControlOn, [data: [dev:lightControl.get(randomDev)]])
//runIn(randomTime*2, switchControlOff, [data: [dev:lightControl.get(randomDev)]])
}
else {
log.info "${app.label} lightSwitching false - no action"
}
}
void switchControlOn(data){
log.debug "${app.label} switchControlOn - $data.dev.currentStates.deviceId , $data.dev.label"
it = data.dev.currentStates.deviceId
it.on()
}
sorted it just passed the devices position in the map
int randomDev = Math.random() * lightControl.size() // pick random device from the list
runIn(randomTime, switchControlOn, [data: [dev:randomDev]])
then used that
void switchControlOn(data){
if(state.running == true) {
lightControl.get(data.dev).on()
if(logEnable == true) log.info "${app.label} switchControlOn - ${lightControl.get(data.dev)} switched on"
}
else {
//log.debug "master switch must be off"
}
}
This isn't going to work, and the error gives you a hint as to why. The deviceId
property is a string, so then you're calling on()
on a string (not the device object). You don't want to call this on the property but rather the device object itself, just as you would anyee else in your code.
They being said, I don't really like to pass that kind of thing around in a handler, anyway, and it's posible it still won't work (if it does, you just want data.dev.on()
). The device ID or DNI or some other unique property of the device is small and easy to pass, then you can look up the actual device (e.g., maybe find it in the input/setting where it was selected, like mySettingName.find { it.deviceId == myId}
).
The position as you found looks like it works, too, but I'm not sure that List is guaranteed to be consistently sorted in any specific way, so I avoid that as well for that reason (and if it's not called quickly, this could definitely be the case if the user adds or removes a selection in the meantime).
This might help. I get my devices in a "multiple" input for all light devices in the room.
Then I make a state map of them in initialize() that I can use to get the index of the device names in the multiple input array, so I can find the device to use it.
In addition, I also use that in another a method to return the device object to send commands to it:
get you point about the is changing
struggling now with you find suggestion i cant get the find to work.
void switchControlOn(data){ //data.dev == device ID
if(state.running == true) {
log.debug data.dev
lightControl.find {it.deviceId == data.dev}
log.debug it
Maybe add a log.debug lightControl
line to help figure things out..
void switchControlOn(data){ //data.dev == device ID
if(state.running == true) {
log.debug data.dev
log.debug lightControl
lightControl.find {it.deviceId == data.dev}
log.debug it
void switchControlOn(data){ //data.dev == device ID
if(state.running == true) {
log.debug data.dev
log.debug lightControl.deviceId
lightControl.find {it.deviceId == data.dev}
log.debug it
Try log.debug getObjectClassName(data.dev)
-- wondering if one is a Number and one is a String (the property on the actual device object is a String, though there's also idAsLong
).
its an int
That's it, then, as the other property is a String. You could force them both to strings or use idAsLong
(I don't think comparing to an int
will be a problem in Groovy...), among other options.
sorry you will have to explain where to put that
There are lots of possibilities.
But here's an easy one:
lightControl.find {it.deviceId == "${data.dev}"}
still not playing ball, 'it' is still null
log.debug data.dev
log.debug lightControl
log.debug lightControl.deviceId
log.debug getObjectClassName("${data.dev}")
log.debug getObjectClassName(lightControl.deviceId)
lightControl.find {it.deviceId == "${data.dev}"}
log.debug it
is there a way to pass the data in the runIn command as a string instead of a map
Still strugling
String dev = data.dev.toString()
log.debug dev
log.debug getObjectClassName(dev)
lightControl.find {it.deviceId == dev }
log.debug it
Looks like you never set it
to anything? (Also probably not a variable name I'd explicitly pick, though it should work...)