OpenHAB CULfw for Somfy RTS Rollershutters

Hi @Daniel_Weisser and a happy Christmas :slight_smile: ,

i just tried to revive my CUL and also try out openhab3 after more than 1 year of having no time to play with this.

But i am struggling to get it running, I think it may be due to OH3 using Java11 maybe…

when using the version u linked the last time here https://community.openhab.org/t/openhab-culfw-for-somfy-rts-rollershutters/18905/80
I always get

2020-12-25 18:08:20.440 [WARN ] [org.apache.felix.fileinstall ] - Error while starting bundle: file:/usr/share/openhab/addons/org.openhab.binding.somfycul-2.5.0.jar
org.osgi.framework.BundleException: Could not resolve module: org.openhab.binding.somfycul [22]
Unresolved requirement: Import-Package: org.eclipse.smarthome.config.core

    at org.eclipse.osgi.container.Module.start(Module.java:444) ~[org.eclipse.osgi-3.12.100.jar:?]
    at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:383) ~[org.eclipse.osgi-3.12.100.jar:?]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1260) [bundleFile:3.6.4]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1233) [bundleFile:3.6.4]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.startAllBundles(DirectoryWatcher.java:1221) [bundleFile:3.6.4]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.doProcess(DirectoryWatcher.java:515) [bundleFile:3.6.4]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:365) [bundleFile:3.6.4]
    at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:316) [bundleFile:3.6.4]

With the lastest OH2.5 it shows the Binding correctly.

Thanks,
Sebastian

Are you trying to use an openHAB 2.5.x binding with openHAB 3 ?
This is not going to work, cause of renamed classes.

1 Like

Thanks for the reply, thats the problem then…
as long as someone does not convert that binding to OH3 then, i will have to stay at 2.5 or try the new Outpost concept…

Hi @Sebastian_D ,

I’m currently on vacation but I’ve planned to upgrade the SomfyCUL binding once I start upgrading my OpenHAB installation.

Cheers
Daniel

1 Like

Hi @Daniel_Weisser,

is there any update on this topic (update binding to 3.0)? I really appreciate all the work you’ve done and closely watched this thread. Just wanted to ask.

Thanks in advance!
Florian

Hello,

first of all I have to say thanks for the effort you put in here. I used the Somfy Thahoma Box all the time. Therefore I had to rely on the Somfy Server, since all the commands will run over their server. Unfortunately it seems that Friday evening someone pulls the plug of the server. Leading to not working shutters till Monday. So I downgraded my Openhabian from 3.0 to 2.5 and got This Cul

After some days of trail and error I got the binding, things and items working.
Current Setup:
Openhab 2.5
Raspberry Pi4 8GB
Habian 64bit
Binding: org.openhab.binding.somfycul-2.5.0 placed in the Addon Folder

somfycul:culdevice:cul [ port="/dev/ttyUSB0", baudrate="38400" ]
somfycul:somfydevice:ShutterArbeitszimmer (somfycul:culdevice:cul)

I followed the procedure with a Switch first and then changing to Rollershutter.

Now the bindings woks. I can send a command to my shutters via the Rollershutter item and they move. But they only move a small step and not to the end.

Rollershutter ProgrammShutterArbeitszimmer "Shutter Arbeitszimmer" (somfyFF) {channel="somfycul:somfydevice:ShutterArbeitszimmer:position"}

The Shutter Control has now the following parts:

Free to set number: Without function since it is not supported by my somfy motors
Up Arrow: Moves some small distance up
Down Arrow: Moves some distance down
Stop (MY): No function

somfycul_somfydevice_ShutterArbeitszimmer.properties file changes:

#Last command changes to up or down
#<Time> is changing as well to the time stamp of the last command
rollingCode is changing
adress is constant

Should the Stop or My Button not been seen there as well?

Is this the expected behavior?
How can I make them move completely to any end position?

Thanks in advance,
Christoph

Hi!

I have another working solution for OH3!
I’ve created a python script to control the nanoCUL(raw version, no error handling, no logging).
/etc/openhab/scripts/somfy.py

#!/usr/bin/python
import serial
import argparse

parser = argparse.ArgumentParser(description="Sends SOMFY RTS commands with the nanoCUL on the selected port")
parser.add_argument("shutter", help="The number of the shutter", type=str, choices=["Item1Name", "Item2Name", "Item3Name"])
parser.add_argument("command", help="The command to send", type=str.upper, choices=["UP", "DOWN", "STOP", "MY"])
args = parser.parse_args()

# Command (1 = My, 2 = Up, 4 = Down, 8 = Prog)
C="1"
if args.command == "UP":
    C="2"
elif args.command == "DOWN":
    C="4"

encryptionKey = 'A1'

if args.shutter == "Item1Name":
    rollingCode='AAA1'
    address='000001'
elif args.shutter == "Item2Name":
    rollingCode='BBB2'
    address='000002'
elif args.shutter == "Item3Name":
    rollingCode = 'CCC3'
    address = '000003'

command = 'Ys' + encryptionKey + C + '0' + rollingCode + address + "\n"
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
ser.write(command)
ser.close()

Modify it according to your configuration:

  1. Edit the name of the Items (Item1Name, Item2Name, …)
  2. Change rolling codes, and addresses. The actual codes can be found in the SomfyCUL configuration files in /var/lib/openhab/somfycul/ (Thanks @Daniel_Weisser )
  3. Edit port (/dev/ttyUSB0)

For the script to work:

  1. pyserial should be installed: https://pythonhosted.org/pyserial/pyserial.html#installation
  2. Because Arduino resets on serial connect (check this), I’ve edited the /etc/rc.local file on my Raspberry pi to clear the hupcl setting on the port. I’ve added these lines:
# Clear the hupcl setting to prevent Arduino from reset on serial connect
stty -F /dev/ttyUSB0 -hupcl

Another solution could be to wait 2 seconds in the script after serial connect for the Arduino to restart.

The rule to call the python script:

rule "Somfy binding"
    when
	Item Item1Name received command or
	Item Item2Name received command or
	Item Item3Name received command
    then
    executeCommandLine(Duration.ofSeconds(3),"python", "/etc/openhab/scripts/somfy.py", triggeringItemName, receivedCommand.toString)
end

Hope this helps someone!

Hi Chacha,

I gave it a try on my OH3 system. Beside the fact that I am not able to trigger the python rule, it worked fine one time. For test reasons I just start the script via command line.

The reason is for this one time only is, that the rolling code is constant in your case.

How do you handle the

rollingCode

increment after each time you run the script?

Sorry I started OH one month ago. All my skills are C# and OH is trial and error.

Thanks in advance.

Hi Christoph,

I do not change the rolling code, but somehow it just works. :grinning:
I thought I should but it works without changing it.

Hi Chacha,

ok, I will give it a new try tomorrow. I had to update it each run.

One idea is, to have it as argument in the rule.

If you’ve never used the SomfyCUL to control your devices, you have to program the device with the help of your existing remote to accept the new “remote” (rollingCode+address).

Hi Chacha,

yes I did this. This is how I got it running on my Openhab 2.5 System:

As you state:

I copied the values from the files. This way I could send one single command. The solution to send more than one was to increment the rolling code.

encryptionKey = 'A1'
rollingCode='01FE'
address='000006'
ser = serial.Serial('/dev/ttyUSB0', 38400, timeout=1)
command = 'Ys' + encryptionKey + C + '0' + rollingCode + address + "\n"
ser.write(command)
time.sleep(.5)
rollingCode='01FF'
command = 'Ys' + encryptionKey + C + '0' + rollingCode + address + "\n"
ser.write(command)
ser.close()

I have to send the Command twice to make my shutters go completely to an end position.

I’m glad that you’ve made it work!
You can put a print ser.readline() after the line ser.write(command), to see if the nanoCUL receives the command.
I don’t know why I don’t have to increment the rolling code. I thought the nanoCUL takes care of it.

Thank you.

As I thought about the idea to put this parameter into a rule. I realized it will not work, that easy. E.g. a restart of the PI will reset the rule and the rollingCode. If I got it correctly it needs to be somehow an Item-State. Therefore may I ask you to the give some more details?

  • Item Setup which you use to trigger the rule?
  • Have you done the items via PaperUI? Is there a source code for your item?
  • Which Binding do you use, to connect the Items to a channel?

Sorry, for asking so much. You gave sniped of working code. But I am unable to see the hole context.

Thanks in advance,
Christoph

The Items just simple rollershutter items. You can define it anywhere. The rule is triggered, when one of the items’ switch is pressed (UP, DOWN or STOP), or the item received a command. There’s no binding associated with them. Earlier it was the SomfyCUL binding.

Rollershutter Item1Name "Displayname" <rollershutter>

It took some days, but I found no way to not increment the rollingCode, each time I send a command. And this makes sense. Because the RTS Protocol is one-way only. So the motor will only do the commands ones if they have a unique identifier. To not do a command twice, it will only to the command with the correct rollingCode once. This is at least my theory. But if it works like this there is a weak point. What if for some reason one command got lost. Like for example if the receiving motor lost power. Since RTS is one-way only, the remote will not recognize.

Anyhow I found a solution. I added a counter for each address in the *.item file
Number rollingNumber_AllShutter "Befehlcounter alle Shutter" (RollerCommandCounter)

In the rule I send the counter to the python script and increment it, too. Again my increment is by 2 because I have to send the command "UP" twice to make my shutters move the complete way. If I do it only once the shutter only moves up some centimetre.

rule "AllShutter UP"
    when
    Item AllShutter received command OFF
    then
    executeCommandLine(Duration.ofSeconds(2),"python", "/etc/openhab/scripts/OpenAllShutter.py", rollingNumber_AllShutter.state.toString)
    rollingNumber_AllShutter.postUpdate(2 + (rollingNumber_AllShutter.state as DecimalType)) 
end

But this approach has a big weakness. What if the python script for some reasons does not run as expected? So the

command = 'Ys' + encryptionKey + C + '0' + Str_rollingCode + address + "\n"
ser.write(command)

is only called once?

I have no idea how to handle this. How to increase a Number item out of the Python script? This would provide an option to count in a not fully failure proof way, but much better than incrementing the Number item later.

I am open for ideas.

My python script looks like this now:

#!/usr/bin/python
import serial
import argparse
import time

parser = argparse.ArgumentParser(description="Sends SOMFY RTS commands with the nanoCUL on the selected port")
parser.add_argument("rollingCode", help="The rollingCode", type=str)

args = parser.parse_args()

# Fixed Address for all Shutter together 
address='00000A'

#Encryptionkey Somfy
encryptionKey = 'A1'

#Interface for CUL
ser = serial.Serial('/dev/ttyUSB0', 38400, timeout=.1)

#Parse RollingCode to integer
Int_rollingcode=int(args.rollingCode)

# Command (1 = My, 2 = Up, 4 = Down, 8 = Prog)
C="2"

#Parse integer RollingCode to HEX String with lengh 4 and without leading 0x an uppercase letters
Str_rollingCode=hex(Int_rollingcode)[2:].zfill(4).upper()
#Build command
command = 'Ys' + encryptionKey + C + '0' + Str_rollingCode + address + "\n"
#Write/Send Command
ser.write(command)

time.sleep(.5) #wait half a second

# increment rollingCode for the next command to send
Int_rollingcode=Int_rollingcode+1 
#Parse integer RollingCode to HEX String with lengh 4 and without leading 0x an uppercase letters
Str_rollingCode=hex(Int_rollingcode)[2:].zfill(4).upper()
#Build command
command = 'Ys' + encryptionKey + C + '0' + Str_rollingCode + address + "\n"
#Write/Send Command
ser.write(command)
#Close Interface to CUL
ser.close()

Hi Christoph!
I don’t think that you have to be sure, that a command is sent before incrementing rolling code. In a one-way communication you never can be sure that the receiver will get the message, but this shouldn’t have to brake communication. Imagine the situation when a remote sends a command, but the receiver is out of range.
On wikipedia you can find this about rolling code:
A typical implementation compares within the next 256 codes in case receiver missed some transmitted keypresses.

You may want to have a look at this implementation:

Works perfectly for me…

You were faster than me…

First of all, @chacha: thank you for this wonderful code. I got it working on the command line!!! After 2 months of research… :slight_smile: Finally!

My setup is also the same: OH3 with openhabian 3, rasperry pi 4, and the same CUL-Stick as you have.

@Christoph_Bergmann my code is a little bit less advanced than yours. But I have the same problem, that you have. I can only control the shutters when I increase the rolling code by 1. I don’t think that you need to see my type of code, because you seem to be far more experienced in Python than I am… but for documentation’s sake and debugging reasons (and if someone is as desperate as I was), here it is. One explanation before:

I made 2 files, where each file holds the rolling code for each of my shutters (two files = two shutters).
rollingCode_Schlafzimmer:

0x1000

rollingCode_BueroFlo:

0x0800

The actual python script:

#!/usr/bin/python
import serial
import argparse

parser = argparse.ArgumentParser(description="Sends SOMFY RTS commands with the nanoCUL on the selected port")
parser.add_argument("shutter", help="The number of the shutter", type=str, choices=["Somfy-Rollade_Schlafzimmer", "Somfy-Rollade_BueroFlo"])
parser.add_argument("command", help="The command to send", type=str.upper, choices=["UP", "DOWN", "STOP", "MY", "PROG"])
args = parser.parse_args()

#Open file with rolling code, read the content and put it in the variable
with open('rollingCode_Schlafzimmer', 'r') as file:
    rollingCode1 = file.readline()

with open('rollingCode_BueroFlo', 'r') as file:
    rollingCode2 = file.readline()

# Command (1 = My, 2 = Up, 4 = Down, 8 = Prog)
C="1"
if args.command == "UP":
    C="2"
elif args.command == "DOWN":
    C="4"
elif args.command == "PROG":
    C="8"

encryptionKey = 'A1'

#Strip rolling code of leading "0x"
if args.shutter == "Somfy-Rollade_Schlafzimmer":
    rollingCode = rollingCode1[2:].rstrip("\n")
    address='000029'
elif args.shutter == "Somfy-Rollade_BueroFlo":
    rollingCode = rollingCode2[2:].rstrip("\n")
    address='000029'

command = 'Ys' + encryptionKey + C + '0' + str(rollingCode) + address + "\n"
ser = serial.Serial('/dev/ttyUSB0', 38400, timeout=1)
ser.write(command)
ser.close()

#AFTER the command execution, increase the variable by 1 hex value)
if args.shutter == "Somfy-Rollade_Schlafzimmer":
    with open('rollingCode_Schlafzimmer', 'r+') as file:
        rollingCode1 = int(file.read(),16)
        file.seek(0)
        file.write(hex(rollingCode1 + 1))
elif args.shutter == "Somfy-Rollade_BueroFlo":
    with open('rollingCode_BueroFlo', 'r+') as file:
        rollingCode2 = int(file.read(),16)
        file.seek(0)
        file.write(hex(rollingCode2 + 1))

@Christoph_Bergmann
I will test your version of the code next week.

@DrRSatzteil
I will also test this implementation. Hopefully it helps…

One last question @chacha and @Christoph_Bergmann:
How do I implement the shutters via PaperUI? I am not quite sure… I implemented the CUL-Stick as Serial Bridge, and after that I got lost, honestly… Sorry, if this question sounds dumb.