Hello,
I’ve spent a lot of time searching for a time based shutter control, although I found bits and pieces I made a code myself - with half success. As there are no sensors to know at which positions my shutters are (and I can’t mount a rotary encoder on them) the only thing I can use is “time” to track the positions of the shutters.
I’m using currently Openhab 1.8, I’ve tried 2.0 but there none of my rules (code) work.
A short summary how my system is made.
Raspberry PI connected to two Arduinos.
One Arduino is for inputs (eg. tracks which switch was pressed and for how long). Returns a value to openhab:
- when shutter switch pressed: s-3-1
- when shutter switch released s-3-0-542223
s stands for shutter, I have thermostats (t) and switches (b), that’s why I differentiate between them.
-3- stand for the button which is pressed
1 or 0 if it’s pressed or released
542223 is the milliseconds of how long that button was pressed, with this I can calculate a percentage (basically the position of my shutter)
The other Arduino controls the outputs (eg. Relays).
I can control my shutter from my tablet, or by pressing a switch. The position is displayed in percentage.
My code:
It might seem long, basically there are 7 shutters, so the code is repeated for each. Functions could simplify it, but I did not have time to look it up, how to make it.
import java.util.concurrent.locks.ReentrantLock
import org.openhab.core.library.types.*
import org.openhab.core.library.items.*
import org.openhab.binding.exec.*
import org.joda.time.DateTime
import org.openhab.core.library.types.*
import org.joda.time.*
import org.openhab.model.script.actions.Timer
import java.util.List
import java.util.ArrayList
import java.math
import java.util.Date
var java.util.concurrent.locks.ReentrantLock lock = new java.util.concurrent.locks.ReentrantLock()
val List<Integer> shutterOldState = newArrayList(0,0,0,0,0,0,0)
var Integer presstime = 0
var Integer pinID = 0
var Integer onoff = 0
var Number[] SHUTTER_FULL_UP_TIME = newArrayList(20000, 20000, 20000, 20000, 20000, 20000, 20000)
var Number[] SHUTTER_FULL_DOWN_TIME = newArrayList(20000, 20000, 20000, 20000, 20000, 20000, 20000)
var Timer timer0 = null
var Timer timer10 = null
var Timer timer2 = null
var Timer timer30 = null
var Timer timer4 = null
var Timer timer50 = null
var Timer timer6 = null
var boolean run = true
val List<boolean> shutw = newArrayList(true, true, true, true, true, true, true)
rule "Arduino input handler" // what this does is it breaks up the "s-3-0-542223" code
when
Item Arduino_input changed
then
var String[] check = Arduino_input.state.toString.split("-")
if (check.get(0) == "b")
{
pinID = new Integer (check.get(1))
val String itemName = "LightSwitch" + pinID
Lights?.allMembers.filter(s | s.name.equals(itemName)).forEach[item|
if(item.state==OFF) postUpdate(itemName, "ON")
else postUpdate(itemName, "OFF")]
}
if (check.get(0) == "t")
{
pinID = new Integer (check.get(1))
val String itemName = "Thermostat" + pinID
val String itemValue = check.get(2)
Thermostat?.allMembers.filter(s | s.name.equals(itemName)).forEach[item|
if(itemValue=="1") postUpdate(itemName, "OFF")
else postUpdate(itemName, "ON")]
}
if (check.get(0) == "s") //while running from web, functions can not be executed
{
run = false //will not enter the shutter run program
pinID = new Integer (check.get(1))
onoff = new Integer (check.get(2))
if (onoff == 0) presstime = new Integer (check.get(3))
else presstime = 0
if (pinID <= 9/* && shutterOldState.get(pinID-3) != 0*/)
{
//aka shutter in living room button to move up
if (onoff == 1) sendCommand (Arduino ,pinID + "-1s") //starts moving up
else
{
sendCommand (Arduino ,pinID + "-0s")
run = true //stops
}
}
if (pinID >= 10 /*&& shutterOldState.get(pinID-10) != 100*/)
{
//aka shutter in living room button to move down
if (onoff == 1) sendCommand (Arduino ,pinID + "-1s") //starts moving down
else
{
sendCommand (Arduino ,pinID + "-0s")
run = true //stops
}
}
//
check = null
// below code calculates the percentage (position) of the shutter, when the command was received from a switch
if (pinID < 10) shutterOldState.add(pinID-3, Math::round((shutterOldState.get(pinID-3) - presstime / SHUTTER_FULL_UP_TIME.get(pinID-3) * 100).intValue))
else if (pinID >= 10) shutterOldState.add(pinID - 10, Math::round((shutterOldState.get(pinID-10) + presstime / SHUTTER_FULL_DOWN_TIME.get(pinID-10) * 100).intValue))
if (pinID < 10)
if (shutterOldState.get(pinID-3) <= 0) shutterOldState.add(pinID-3, 0)
if (pinID >= 10)
if (shutterOldState.get(pinID-10) >= 100) shutterOldState.add(pinID-10, 100)
if (onoff == 0) {
val String itemName2 = "Shutter_" + (if (pinID<10) pinID.intValue else if (pinID>=10) (pinID-7).intValue)
gShutter?.allMembers.filter(s | s.name.equals(itemName2)).forEach[item|
postUpdate(itemName2, (shutterOldState.get(if (pinID<10) pinID-3 else if (pinID>=10) pinID-10)).toString)]
}
}
end
rule "Shutter Living Room 3"
when
Item Shutter_3 received command
then
if (run) {
lock.lock() try {
if (timer0 ==null) {
if ((shutterOldState.get(0).intValue - (Shutter_3.state as DecimalType).intValue) > 0 && shutw.get(0)) {
val upMin = ((shutterOldState.get(0) - (Shutter_3.state as DecimalType).intValue)* SHUTTER_FULL_UP_TIME.get(0) / 100).intValue
println(upMin)
sendCommand (Arduino ,"3-1s") //goes up
shutw.add(0, false)
timer0 = createTimer(now.plusMillis(upMin)) [|
sendCommand (Arduino ,"3-0s")
timer0 = null
shutw.add(0, true)
]
}
if ((shutterOldState.get(0).intValue - (Shutter_3.state as DecimalType).intValue) < 0 && shutw.get(0)) {
val dnMin = (((Shutter_3.state as DecimalType).intValue - shutterOldState.get(0))* SHUTTER_FULL_DOWN_TIME.get(0) / 100).intValue
println(dnMin)
sendCommand (Arduino ,"10-1s") //goes down
shutw.add(0, false)
timer0 = createTimer(now.plusMillis(dnMin)) [|
sendCommand (Arduino ,"10-0s")
timer0 = null
shutw.add(0, true)
]
}
shutterOldState.add(0, (Shutter_3.state as DecimalType).intValue)
}
else { postUpdate(Shutter_3, shutterOldState.get(0).intValue) shutw.add(0, false)}
} finally { lock.unlock() }
}
end
rule "Shutter Living Room 4"
when
Item Shutter_4 received command
then
if (run) {
lock.lock() try {
if (timer10 ==null) {
if ((shutterOldState.get(1).intValue - (Shutter_4.state as DecimalType).intValue) > 0 && shutw.get(1)) {
val upMin = ((shutterOldState.get(1) - (Shutter_4.state as DecimalType).intValue)* SHUTTER_FULL_UP_TIME.get(1) / 100).intValue
println(upMin)
sendCommand (Arduino ,"4-1s") //goes up
shutw.add(1, false)
timer10 = createTimer(now.plusMillis(upMin)) [|
sendCommand (Arduino ,"4-0s")
timer10 = null
shutw.add(1, true)
]
}
if ((shutterOldState.get(1).intValue - (Shutter_4.state as DecimalType).intValue) < 0 && shutw.get(1)) {
val dnMin = (((Shutter_4.state as DecimalType).intValue - shutterOldState.get(1))* SHUTTER_FULL_DOWN_TIME.get(1) / 100).intValue
println(dnMin)
sendCommand (Arduino ,"11-1s") //goes down
shutw.add(1, false)
timer10 = createTimer(now.plusMillis(dnMin)) [|
sendCommand (Arduino ,"11-0s")
timer10 = null
shutw.add(1, true)
]
}
shutterOldState.add(1, (Shutter_4.state as DecimalType).intValue)
}
else { postUpdate(Shutter_4, shutterOldState.get(1).intValue) shutw.add(1, false)}
} finally { lock.unlock() }
}
end
rule "Shutter Living Room 5"
when
Item Shutter_5 received command
then
if (run) {
lock.lock() try {
if (timer2 ==null) {
if ((shutterOldState.get(2).intValue - (Shutter_5.state as DecimalType).intValue) > 0 && shutw.get(2)) {
val upMin = ((shutterOldState.get(2) - (Shutter_5.state as DecimalType).intValue)* SHUTTER_FULL_UP_TIME.get(2) / 100).intValue
println(upMin)
sendCommand (Arduino ,"5-1s") //goes up
shutw.add(2, false)
timer2 = createTimer(now.plusMillis(upMin)) [|
sendCommand (Arduino ,"5-0s")
timer2 = null
shutw.add(2, true)
]
}
if ((shutterOldState.get(2).intValue - (Shutter_5.state as DecimalType).intValue) < 0 && shutw.get(2)) {
val dnMin = (((Shutter_5.state as DecimalType).intValue - shutterOldState.get(2))* SHUTTER_FULL_DOWN_TIME.get(2) / 100).intValue
println(dnMin)
sendCommand (Arduino ,"12-1s") //goes down
shutw.add(2, false)
timer2 = createTimer(now.plusMillis(dnMin)) [|
sendCommand (Arduino ,"12-0s")
timer2 = null
shutw.add(2, true)
]
}
shutterOldState.add(2, (Shutter_5.state as DecimalType).intValue)
}
else { postUpdate(Shutter_5, shutterOldState.get(2).intValue) shutw.add(2, false) }
} finally { lock.unlock() }
}
end
rule "Shutter Living Room 6"
when
Item Shutter_6 received command
then
if (run) {
lock.lock() try {
if (timer30 ==null) {
if ((shutterOldState.get(3).intValue - (Shutter_6.state as DecimalType).intValue) > 0 && shutw.get(3)) {
val upMin = ((shutterOldState.get(3) - (Shutter_6.state as DecimalType).intValue)* SHUTTER_FULL_UP_TIME.get(3) / 100).intValue
println(upMin)
sendCommand (Arduino ,"6-1s") //goes up
shutw.add(3, false)
timer30 = createTimer(now.plusMillis(upMin)) [|
sendCommand (Arduino ,"6-0s")
timer30 = null
shutw.add(3, true)
]
}
if ((shutterOldState.get(3).intValue - (Shutter_6.state as DecimalType).intValue) < 0 && shutw.get(3)) {
val dnMin = (((Shutter_6.state as DecimalType).intValue - shutterOldState.get(3))* SHUTTER_FULL_DOWN_TIME.get(3) / 100).intValue
println(dnMin)
sendCommand (Arduino ,"14-1s") //goes down
shutw.add(3, false)
timer30 = createTimer(now.plusMillis(dnMin)) [|
sendCommand (Arduino ,"14-0s")
timer30 = null
shutw.add(3, true)
]
}
shutterOldState.add(3, (Shutter_6.state as DecimalType).intValue)
}
else { postUpdate(Shutter_6, shutterOldState.get(3).intValue) shutw.add(3, false) }
} finally { lock.unlock() }
}
end
rule "Shutter Living Room 7"
when
Item Shutter_7 received command
then
if (run) {
lock.lock() try {
if (timer4 ==null) {
if ((shutterOldState.get(4).intValue - (Shutter_7.state as DecimalType).intValue) > 0 && shutw.get(4)) {
val upMin = ((shutterOldState.get(4) - (Shutter_7.state as DecimalType).intValue)* SHUTTER_FULL_UP_TIME.get(4) / 100).intValue
println(upMin)
sendCommand (Arduino ,"7-1s") //goes up
shutw.add(4, false)
timer4 = createTimer(now.plusMillis(upMin)) [|
sendCommand (Arduino ,"7-0s")
timer4 = null
shutw.add(4, true)
]
}
if ((shutterOldState.get(4).intValue - (Shutter_7.state as DecimalType).intValue) < 0 && shutw.get(4)) {
val dnMin = (((Shutter_7.state as DecimalType).intValue - shutterOldState.get(4))* SHUTTER_FULL_DOWN_TIME.get(4) / 100).intValue
println(dnMin)
sendCommand (Arduino ,"15-1s") //goes down
shutw.add(4, false)
timer4 = createTimer(now.plusMillis(dnMin)) [|
sendCommand (Arduino ,"15-0s")
timer4 = null
shutw.add(4, true)
]
}
shutterOldState.add(4, (Shutter_7.state as DecimalType).intValue)
}
else { postUpdate(Shutter_7, shutterOldState.get(4).intValue) shutw.add(4, false) }
} finally { lock.unlock() }
}
end
rule "Shutter Living Room 8"
when
Item Shutter_8 received command
then
if (run) {
lock.lock() try {
if (timer50 ==null) {
if ((shutterOldState.get(5).intValue - (Shutter_8.state as DecimalType).intValue) > 0 && shutw.get(5)) {
val upMin = ((shutterOldState.get(5) - (Shutter_8.state as DecimalType).intValue)* SHUTTER_FULL_UP_TIME.get(5) / 100).intValue
println(upMin)
sendCommand (Arduino ,"8-1s") //goes up
shutw.add(5, false)
timer50 = createTimer(now.plusMillis(upMin)) [|
sendCommand (Arduino ,"8-0s")
timer50 = null
shutw.add(5, true)
]
}
if ((shutterOldState.get(5).intValue - (Shutter_8.state as DecimalType).intValue) < 0 && shutw.get(5)) {
val dnMin = (((Shutter_8.state as DecimalType).intValue - shutterOldState.get(5))* SHUTTER_FULL_DOWN_TIME.get(5) / 100).intValue
println(dnMin)
sendCommand (Arduino ,"16-1s") //goes down
shutw.add(5, false)
timer50 = createTimer(now.plusMillis(dnMin)) [|
sendCommand (Arduino ,"16-0s")
timer50 = null
shutw.add(5, true)
]
}
shutterOldState.add(5, (Shutter_8.state as DecimalType).intValue)
}
else { postUpdate(Shutter_8, shutterOldState.get(5).intValue) shutw.add(5, false) }
} finally { lock.unlock() }
}
end
rule "Shutter Living Room 9"
when
Item Shutter_9 received command
then
if (run) {
lock.lock() try {
if (timer6 ==null) {
if ((shutterOldState.get(6).intValue - (Shutter_9.state as DecimalType).intValue) > 0 && shutw.get(6)) {
val upMin = ((shutterOldState.get(6) - (Shutter_9.state as DecimalType).intValue)* SHUTTER_FULL_UP_TIME.get(6) / 100).intValue
println(upMin)
sendCommand (Arduino ,"9-1s") //goes up
shutw.add(6, false)
timer6 = createTimer(now.plusMillis(upMin)) [|
sendCommand (Arduino ,"9-0s")
timer6 = null
shutw.add(6, true)
]
}
if ((shutterOldState.get(6).intValue - (Shutter_9.state as DecimalType).intValue) < 0 && shutw.get(6)) {
val dnMin = (((Shutter_9.state as DecimalType).intValue - shutterOldState.get(6))* SHUTTER_FULL_DOWN_TIME.get(6) / 100).intValue
println(dnMin)
sendCommand (Arduino ,"17-1s") //goes down
shutw.add(6, false)
timer6 = createTimer(now.plusMillis(dnMin)) [|
sendCommand (Arduino ,"17-0s")
timer6 = null
shutw.add(6, true)
]
}
shutterOldState.add(6, (Shutter_9.state as DecimalType).intValue)
}
else { postUpdate(Shutter_9, shutterOldState.get(6).intValue) shutw.add(6, false) }
} finally { lock.unlock() }
}
end
And now comes my problem, which I could not resolve and I’d like to ask for your help.
The problem I face is “simple”. My code works, but not for every shutter rule… and I do not get it why. It’s the same code with different variables.
Ex:
2017-05-07 07:43:06 - Shutter_3 received command 53
2017-05-07 07:43:09 - Arduino received command 10-1s
2017-05-07 07:43:20 - Arduino received command 10-0s
…works fine…
2017-05-07 07:44:03 - Shutter_4 received command 38
…does nothing…
If someone has some time to give me a hint how to make this with a function, to simplify my code, it would be cool.
Thanks in advance!