Assistance with exec binding in openhab 3

Hi guys,

I’m still running openhab 1.9. The last couple of years I didn’t spend much time on my domotics. But I feel it’s time to take a giant leap forward.

My old openhab setup controls several programmable relays (Zelio Schneider). About ten year ago’s someone provided me some C-programs which are able to read from and write to these relays. To do this I use the exec binding.

Basically 90 percent of my home is controlled with items like this:

Switch Light_Kitchen “Kitchen Light” (GF_Kitchen, Lights)
{ exec="
<[/home/scripts/ison ttyUSB0 10:1000:REGEX((.*?))]
>[OFF:/home/scripts/setstate ttyUSB0 10 0]
>[ON:/home/scripts/setstate ttyUSB0 10 1]
" }

Thus the first ‘ison’ command reads the state every second. I am not sure what the added value is from the REGEX in this one.
And the ‘setstate’ commands enable to switch lights on and off.

Today I just started with openhab3 … but I don’t have a clue how to integrate these commands. Can someone show me the way? Some examples of similar setups (switches managed via exec commands) might be useful.

Thanks already

Bert

The exec v-1 required a transformation of some kind, that one is a no-op.

Start with something simpler,like Astro or Weather, to familiarise with Things, channels, and their links to Items.
Then have a look at Exec binding docs.
Because your “ins” and “outs” are completely different, you might set up a read-only Thing to poll for device status.
When that’s working, you might set up another Thing to pass out ON/OFF commands. You can link more than one channel to the same Item.

Yes I was the original author of the zelio.c program
Good news, I managed to integrate the whole zelio communication protocol with the OpenHAB serial binding. Not super trivial, and so far only 1 light is done seton/setoff and report status and only with a serial cable connected to the zelio as the Serial binding doesnt like(ERROR: COMM) the usb-generic loaded pl2303 chip from the microcontroller in the USB zelio cable yet, will dive in the code to see whats going on. If anyone knows a way?

What I did was in summary: A SerialBridge Thing per Zelio, a SerialDevice Thing connected to this bridge per Output (Q1 - Qx) you want to control, and two Items per output: A Switch and a Light Bulb. Where the switch sends a command ON/OFF through the link to the Thing, that has a configured onValue/offValue equal to the zelio command that you use through the zelio serial port.

This brings seton/off to work, and then to set the state of an output if an internal in-house switch is used?
I have one more SerialDevice thing connected to the bridge ‘ReadZelio2States’, which sends the read output states command, and is triggered from a rule every 5 seconds. The stateRead then updates the state of the outputs through a regex transformation.

The core trick for me to debug the serial communication protocol was to create a virtual serial device that openhab talks to, then forward it to the real serial port while dumping output on the console.
socat -d -d -v pty,raw,echo=0 /dev/ttyUSB1,raw,echo=0

Let me know if still interested.

Currently have 1 light working, still a little issue after desync switch/openhab setting, but will get there.

Always interested. My openhab activities have been on a pause for a while. But the idea is to pick this up again soon.

Hi Bert - A slight diversion from your question of managing this via the exec binding…

I also had zelio’s managed via the exact same process , using a adaption of the same c program that @Jeroen_Ost wrote, which served me well for many many years.

When I moved to OH3, I started experiencing numerous issues with the exec binding seeming to choreograph all the item updates to overlap in the same millisecond as the others, causing intermittent errors/state inconsistencies. See OH3 Exec Binding with Serial Port - Port Locking due to overlapping item reads for details. I only had around 8 items…

I have just posted up a Zelio->MQTT service example (see: Zelio Integration to OpenHAB via MQTT but this is probably not much use to you yet, as I have not yet created the MQTT->Zelio (Write) function…

Just be aware of this locking issue with multiple items reading from the same device… I suspect you could run into this, once you solve your original question, especially with a one second update interval.

So here is how I did it.

Part 1: Getting the serial binding to work.

I have 3 zelio’s, 2 of them are connected with a serial cable, the third one is connected with a USB cable. The serial cables work fine, the usb cable version fails on some of the ioctls that the serial binding does by default to set baud rate, parity etc and so fails to initialize.
For that I had to patch the serial binding. If you dont use the USB cable you dont need to do this.

If I find the time I might submit a proper pull request where not all serial port options are mandatory to set , and so the failing ioctl’s are not a blocking problem

I Installed Openhab 3.2.0 and patch addons 3.2.0

git checkout https://github.com/openhab/openhab-addons
cd openhab-addons
git checkout 3.2.0
patch -R -p1 < /tmp/patch-SerialBridgeHandler.java.diff.txt

patch-SerialBridgeHandler.java.diff.txt (2.3 KB)

Follow build instructions for openhab modules GitHub - openhab/openhab-addons: Add-ons for openHAB (need maven and jdk installed)
For mac:

brew install openjdk@11 
export JAVA_HOME=/opt/homebrew/opt/openjdk@11 

Equivalent for linux/windows…
Then build the serial binding with this patch

mvn install -DskipChecks -DskipTests -pl :org.openhab.binding.serial

copy the file bundles/org.openhab.binding.serial/target/org.openhab.binding.serial-3.2.0.jar to your openhab system in ‘/tmp/openhab-upgrade’ (create folder if it doesnt exist yet mkdir /tmp/openhab-upgrade)
On the openhab system

cd /tmp/openhab-upgrade
sha1sum org.openhab.binding.serial-3.2.0.jar > org.openhab.binding.serial-3.2.0.jar.sha1

On the openhab system, login to the console (The Console | openHAB)
type list and look for the id (first column) of ‘openHAB Add-ons :: Bundles :: Serial Binding’
bundle:update <id>
In another terminal, restart openhab
sudo systemctl restart openhab

Part 2: Configuring

Go to the visual admin ui
For every Zelio: (change the number in the item names)

  • Create a thing ‘Zelio1SerialBridge’ from Serial binding with serial:serialBridge and set the serial port of that Zelio. Use show advanced to set baud rate 115200, data bits 7, parity none, stop bits 1

  • Create a thing ‘Zelio1ReadStatesThing’. The purpose if this thing is to have a cronjob to read states and determine if lights are on/off. Connect it to the bridge from previous step. In the configuration field put for Pattern match: :010302.* This is a regular expression that means: only update the state of the outputs in the zelio IF the response you read from the bridge starts with this answer. This is necessary because when we set outputs from openhab, the set commands, also trigger a response, but it starts with a different prefix. To prevent output state to incorrectly get updated, we filter here. Open the newly created thing, and click channels, add channel. Name and label it stateRead1, Click string, and in stringFormat you enter :01030000FF1802E4\r\n (the command to send to read the states of all outputs)

  • Create an item Zelio1StateReadItem to hold the value read. Give it channel link to Zelio1ReadStatesThing, tag point. This item will hold the output state. The channel link has profile ‘standard’ This is an item that holds the output state string , as obtained from the read state reponse, could be ’ * :01030200807B’ etc. We can use this value in our items later (lights etc) to determine if they are on or off.

  • Create an item Zelio1SerialBridgeLastWrite of type ‘DateTime’ and add a channel link to Zelio1SerialBridge , with profile ‘timestamp on change’. We use this item to be able to figure out when a button was pressed last. It’s a workaround for a polling read and button press race condition.

  • Create a thing called ‘Zelio1ClearButtonStatesThing’ on the Zelio1SerialBridge with pattern match .* = everything and add a channel clearButtonStatesChannel type serial:string, with commandFormat :01100000FF00020000EF\r\n and stateTransformation regex .*=cleared . The reason we need this is that when you set outputs from a light, the bits to set the output remain set. They need to be cleared later async. We do this in a 5 sec cronjob that also polls for output state. The command to clear all bits is the one given here.

  • Create an item ‘Zelio1ClearButtonStatesItem’ linked to the channel from previous step. Call the link ‘clearButtonState’ and Profile=standard. A write to this item will cause the Zelio to receive the command in ClearButtonStatesThing to reset command state.
    Create an item Zelio1ClearButtonStatesItem with channel link

  • Click rules, create rule for every 5 seconds (0/5 * * * * ? *), When the system has reached start level 100, Then: Send command readState to ReadZelio1_stateRead + Send command clearButtonState to Zelio1ClearButtonStates_clearButtonStatesChannel, But Only if: a given script evaluates to true, and the script to enter:
    (SerialBridge2_lastwrite.state != NULL) && (SerialBridge2_lastwrite.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli < now.toInstant.toEpochMilli - 500
    This causes the system to poll every 5 seconds except if less than 500 millisends ago a button was pressed, in which case an output state could be from the past.

This is the basis configuration for every zelio. We now have

  • A communication channel to write outputs to → Zelio1SerialBridge.
  • An item to have all output states which refreshes every 5 seconds → Zelio1StateReadItem
  • Mechanism to prevent some issues with synchronisation and to poll item state.

All that is left, is adding item by item now and configuring it.

Part 3 Adding items
Example: lightbulb with switch in the kitchen, to be controlled from binding or existing physical switches connected to Zelio.

  • Create a Thing type serialBridge:serialDevice labeled ‘Light kitchen’ bridged to Zelio1SerialBridge. In the configuration, for pattern match set :0103.* - we are only interested in state updates from the cron rule above, not in zelio responses as a result of write commands. Add a channel ‘Light_kitchen_channel’ type switch. Set onValue=01100000FF00020010DF\r\n and offValue=:01100000FF00020020CF\r\n or whatever is appropriate for your device and how you configured it. Here it’s the third output Q3 that is being set (00 01 = Q1 on, 00 02 = Q1 off, 00 04 = Q2 on, 00 08 = Q2 off, 01 00 = Q3 on, etc… ) See zelio manual SLin/SLout, or use the old zelio command line tool to see what string is generated to set an output. For statetransformation, that is the hardest part. Given the response from the zelio output states, we need to build a regular expression that maps it to ON or OFF. Because the response contains 3 hex bytes after ‘:010302’, we have 6 hex characters. The last 2 are a byte checksum which we can ignore. Every output has 1 bit set. So we need to map the bit number from the response to the correct state. In this example, we are setting the third output. So we are interested in the third least important bit in the last byte if we throw away the checksum byte. That is in the 4th hex digit after :010302 and bit 3 should be set (a logical and with 0x4 should be 1). We dont have logical and in a regex, but since there are 3 other bits that can be set (from other outputs) in this hex digit , we can list what values are on, it’s: 4,5,6,7,C,D,E,F because those 8 hex digits all have the third bit set. The regex becomes:
    s/:010302...([4567CDEF]).*/ON/∩REGEX:s/:010302...([012389AB]).*/OFF/
    Every item write to this serialdevice with an ON/OFF command will write the string onValue or offValue and every bridge write with a read output state response will be mapped through the regex into ON/OFF value. We’re almost there!

  • Create an item ‘Light Kitchen’, type switch, icon lightbulb, put it in a openhab location you created (e.g. Kitchen) add a channel link to Light Kitchen Thing, Profile standard.

All done. Clicking the switch, will set zelio output. Pressing the physical button will update output state (after a delay of max 5 sec).

Repeat for other items.

Still have to do dimmers etc. But same principle.