Combining multiple switches with mapping

One quick question which busts my head:
I have two rules which I activate by separate switches.
So my sitemap states:

Switch item=remoteControlClean
Switch item=remoteControlHome

and in my rule it is:

when
Item remoteControlClean changed to ON 
then 
//do something
end

and subsequently:

when 
Item remoteControlHome changed to ON
then 
//do something
end

My goal is to combine the two in my sitemap into something like:

    Switch item=actionControl mappings=[clean="Clean Bin", home"go home] 

AFAIK mappin only works for string items, but how do I include that in a rule?

Try it :

item file :

String actionControl

rule file :

when
Item actionControl received command
then 
switch(receivedCommand) {
        case "clean": {
          //do something
        }
        case "home": {
           //do something
        }
    }
end

sitemap file :

Switch item=actionControl mappings=[clean=“Clean Bin”, home=“go home”]

2 Likes

Wow. How cool. That makes my rule super easy. Thanks a lot.

This is the way it looks now: Much more concise…

Item actionControl received command
then 
switch(receivedCommand) {
        case "clean": {
        logInfo("File", "Moving Natascha Forward to clean dustbin")
        actionCommand.sendCommand('app_rc_start')
        Thread::sleep(10000) // wait until remote control is activated
        actionCommand.sendCommand('app_rc_move[{"omega":0.0, "velocity":0.2, "seqnum":1, "duration":5500}]')
        Thread::sleep(10000)
        actionCommand.sendCommand('app_rc_end')
        remoteControlClean.postUpdate(OFF)
        logInfo("File", "Ready for cleaning dustbin")
        }
    }
end

I just added an additional switch to the actionControl:

    Switch item=actionControl mappings=[vacuum="Saugen", pause="Pause",spot="Spot", dock="nach Hause", clean="Behälter"] icon="none" label="[]"

Those are really long sleeps. They might be fine for now if this is the only rule you have with sleeps and your rule will only ever be triggered once. However, if the rule needs to run multiple instances at the same time or you need to be able to cancel the activity or if you have long Thread::sleeps in other rules you should use Timers instead.

val Timer vacuumTimer = null

rule "Vacuum control"
when
    Item actionControl received command
then
    switch(receivedCommand) {
         case "clean": {
             logInfo("File", "Moving Natascha Forward to clean dustbin")
             actionCommand.sendCommand('app_rc_start')
             // schedule the rest to happen in 10 seconds
             vacuumTimer = createTimer(now.plusSeconds(10), [|
                 actionCommand.sendCommand('app_rc_move[{"omega":0.0, "velocity":0.2, "seqnum":1, "duration":5500}]')

                 // schedule the rest to happen in 10 seconds
                 vacuumTimer = createTimer(now.plusSeconds(10), [|
                     actionCommand.sendCommand('app_rc_end')
                     remoteControlClean.postUpdate(OFF)
                     logInfo("File", "Ready for cleaning dustbin")
                     vacuumTimer = null
                 ]
             ]
         }
         case "cancel": {
             vacuumTimer?.cancel // cancel the timer if it exists
         }
    }
end

In the above, we have a Timer vacuumTimer. Instead of using a Thread::sleep we schedule the code to run in the future. Since you have two sleeps, we create two timers. But if for some reason you need to cancel, you can now cancel the Timer and it won’t execute that code. With Thread::sleep, you would have to wait up to 20 seconds and the actionCommands would execute no matter what.

1 Like

Wow Rich,
thanks. I do not fully understand the timer, but it works like a charm. I think you just missed on two ")"
so I changed “]” into “])”