I have a set of rules devices and items to controll a Gate. I want to show how I realized it.
So a requirement was to not make any changes to the gate. It has multiple encrypted remotes. So yeah, maybe I could have just progrmmed a pi on it or so, but for that I would have to make changes and therefore must ask my dad ^^.
So I used a construction out of Fischertechnik pneumatics and an ESP32 with a relay. So I built a holder for the remote and some pneumatics on top of that.
That is then connected to the relay which is controlled by the ESP.
On the ESP is a sketch that subscribes to a MQTT topic for the button and triggers the press of the button to control the gate. So with that we have the control part.
But there is a problem: The remote has exactly one button for three actions:
- Open
- Close
- Stop
So when you are pressing it, it either opens OR closes. When you press while it moves it stops.
So I needed to know in which state the gate is.
I ended up using an ultrasonic sensor mounted on the pile of the gate. Since no WLAN is available at this position, I used an old telephone cable that was luckily going from the cellar to the gate. So then I spend an afternoon getting the cable out of the dirt and find the cable pairs.
In the cellar I now have another ESP32 reading the ultrasonic sensor.
All that was left is to create a proxy item to link them and a smart rule to position the gate with a slider.
In OH2 I was using an external python script communicating with openhab through the HTTP API.
But as I migrated OH3 (yesterday, and I actually did a clean setup, no migration) I used Jython to do it.
Here is the rule:
import time
def invert_position(pos):
return 100 - pos
target = int(float(str(ir.getItem("gate").state)))
def get_current():
return invert_position(int(float(str(ir.getItem("gate_status").state))))
def is_ok():
return get_current() in range(target - 5, target + 5)
def press_button():
events.sendCommand('gate_button', 'ON')
if is_ok():
events.sendCommand('stdout', "OK.")
else:
events.sendCommand('gate_working', "working...")
press_button()
# keep checking if posititon reached press button again
# when position is 0 or 100 press button again.
# TODO: Cancel after 5 tries or so to prevent bugs
iterations = 0
while True:
iterations = iterations + 1
if is_ok():
if get_current() > 98 or get_current() < 3:
break
press_button()
break
if iterations > 90:
press_button()
iterations = 0
continue
current = get_current()
if current > 98 or current < 2:
time.sleep(4)
if get_current() > 98 or get_current() < 2:
press_button()
iterations = 0
time.sleep(0.5)
events.sendCommand('gate_working', "ready!")
The stdout thing is just for debugging. (BTW, errors in the WebUI for python scripts or logs would be cool. Currently it all just fails silently.)
Then I have two more rules:
triggers:
- id: "1"
configuration:
itemName: gate_working
state: ""
previousState: ""
type: core.ItemStateChangeTrigger
conditions: []
actions:
- inputs: {}
id: "2"
configuration:
type: application/vnd.openhab.dsl.rule
script: gate.label = "Tor (" + gate_working.state.toString + ")"
type: script.ScriptAction
This one updates the label (not working with openHAB 3 UI, the label does not live update. I will create an Issue for this.) so you always know if the gate is still moving. I will later implement a lock feature in it so I don’t have the rule running twice (Or is there a better way?)
Gate proxy state updater:
triggers:
- id: "1"
configuration:
itemName: gate_status
previousState: ""
type: core.ItemStateChangeTrigger
conditions: []
actions:
- inputs: {}
id: "2"
configuration:
type: application/vnd.openhab.dsl.rule
script: if(gate.state != gate_status.state) gate.postUpdate((100 -
gate_status.state as DecimalType).toString)
type: script.ScriptAction
This just inverts the position from the sensor and applies it to the proxy.