RULES: Echo (Alexa) change rollershutters by value (relative)

Hey everybody,

i’ve a simple solution to close the rollershutters by numbers, which is not working for all kind of rollershutters that have only actuators for up and down.

It is not perfect but i think enough for the most. The idea is to set the rollershutters by a given time. So you have to change the time for your rollershutters by looking how long it takes till the the rollershutter is closed.

The rule is needed because the current openhab alexa skill has no functions for all needed rollershutter operations.

The following functions did i make for my special rollershutter actuators which can only move DOWN or UP. You can change the functions for your needs.
My home automation system uses a KNX bus system.

The rule function to move the shutters up.

val org.eclipse.xtext.xbase.lib.Functions$Function3<SwitchItem, Long, Number, Boolean> moveUp = [
	rollerShutterItem, time, receivedCommand |
                rollerShutterItem.sendCommand(UP)
		rollerShutterItem.sendCommand(receivedCommand)
		createTimer(now.plusMilliseconfs(time), [| sendCommand(rollerShutterItem, STOP)]
		true
	]

The rule function to move the shutters down.

val org.eclipse.xtext.xbase.lib.Functions$Function3<SwitchItem, Long, Number, Boolean> moveDown = [
	rollerShutterItem, time, receivedCommand |
		rollerShutterItem.sendCommand(DOWN)
		rollerShutterItem.sendCommand(receivedCommand)
		createTimer(now.plusMilliseconfs(time), [| sendCommand(rollerShutterItem, STOP)]
		true
	]

The following method checks which value you have said to alexa. The values 10, 20, 30, 40 up to 100 are available to let the rollershutters going down for a specific time (10 for about 10%). The values are always relative. So when you want to close your rollershutters to 80% you must be sure that they are fully opened or in case that they are 20% you can close them for 60%.

To let the rollershutters going up you can use the values 5, 15, 25, 35 up to 95.
The value 0 stops the current process.

val org.eclipse.xtext.xbase.lib.Functions$Function5<SwitchItem, Number, Long, org.eclipse.xtext.xbase.lib.Functions$Function3<SwitchItem, Long, Number, Boolean>, org.eclipse.xtext.xbase.lib.Functions$Function3<SwitchItem, Long, Number, Boolean>, Boolean> rollershutterEchoSetFunction = [
	 rollerShutterItem, receivedCommand, maxCloseTime, moveUp, moveDown |
	 	if(receivedCommand == 0) rollerShutterItem.sendCommand(STOP)
                 else {
                     // Calculate whether this is an UP or DOWN command
                     val up = if(receivedCommand % 10 == 0) false else true

                     // Calculate the time
      	            val time = (maxCloseTime / 10) * Math::round((receivedCommand / 10).floatValue)
                    if(up) moveUp.apply(rollerShutterItem, time, receivedCommand)
                    else moveDown.apply(rollerShutterItem, time, receivedCommand)
                 }

		true
	]

The example rule that uses the functions above.

// Rollershutter rules for Amazon Echo FirstFloor.

rule "Rollershutter_ParlorBalcony"
when
Item FF_Rollershutter_ParlorBalcony_ECHO received command
then
var inputValue = receivedCommand as DecimalType
rollershutterEchoSetFunction.apply(FF_Rollershutter_ParlorBalcony, inputValue, 23000L, moveUp, moveDown)
end

23000L is the time which is needed to close the balcony rollershutter completely.

If you have any questions, improvements, ideas please let me know.

Cheers

1 Like

Great posting which should be very helpful to the community. Thanks for posting!

I’ve some comments/improvements to suggest.

A potential sleep of 23 seconds could potentially cause problems in the long run. When you sleep for long periods of time it ties up an execution thread and if you have enough sleeping at the same time your entire Oh can come to a hault.

Luckily it is a very easy fix I think. Replace these two lines in your lambda:

		Thread::sleep(time)
		sendCommand(rollerShutterItem, STOP)

with

		createTimer(now.plusMilliseconfs(time), [| sendCommand(rollerShutterItem, STOP)]

We recommend using the sendCommand.postUpdate methods rather than the Actions where ever possible. For example, replace:

sendCommand(rollerShutterItem, DOWN)

with

rollerShutterItem.sendCommand(DOWN)

This causes OH to do less work in the background and will work in more situations than the Action does.

Your rollershutterEchoSetFunction can be made much shorter using some calculations and checkings up front.

val org.eclipse.xtext.xbase.lib.Functions$Function5<SwitchItem, Number, Long, org.eclipse.xtext.xbase.lib.Functions$Function3<SwitchItem, Long, Number, Boolean>, org.eclipse.xtext.xbase.lib.Functions$Function3<SwitchItem, Long, Number, Boolean>, Boolean> rollershutterEchoSetFunction = [
	 rollerShutterItem, receivedCommand, maxCloseTime, moveUp, moveDown |

                 if(receivedCommand == 0) rollerShutterItem.sendCommand(STOP)
                 else {
                     // Calculate whether this is an UP or DOWN command
                     val up = if(receivedCommand % 10 == 0) false else true

                     // Calculate the time
      	            val time = (maxCloseTime / 10) * Math::round((receivedCommand / 10).floatValue)
                    if(up) moveUp.apply(rollerShutterItem, time, receivedCommand)
                 }

		true
	]

Whenever you find yourself writing the same lines of code over and over again with only small changes to the arguments, there is almost always a better way.

1 Like

Ok, Im not familar enough on using the existing libs of java within rules or lamda functions in the openhab environment. Thank you for the improvements! The mathematic solution is nice!

I’ve added your changes.

oops, I’m missing the else statement at the end of the lambda

             if(up) moveUp.apply(rollerShutterItem, time, receivedCommand)
             else moveDown.apply(rollerShutterItem, time, receivedCommand)
2 Likes

Isn’t there a “)” missing at the end of the line “create timer…”?

Anyway, a really nice solution. Thank you!

Many Regards
Camo