As promised here some kind of tutorial how I set up my shutters:
I have openHABian 3.0.1 on a Raspberry Pi running.
Some generell command:
- The RTS protocol used by Somfy is a one way protocol. This means you can only send commands to the motor, but there will never be any feedback.
*Programming the motors only means that the controller in the shutter will add/remove the address from the list of addresses the motor will react if a command is send
- One Adresse can be used with different shutters at the same time
- The so called
RollingCode
is just a number, telling the motor which command is the current one to execute
- This is to avoid double execution of commands, but one has to keep the
RollingCode
up to date
I did it without any binding, but via the Python script.
Therefore the gnu.io is required. To do so I installed it, via the karaf console.
Therefore I connect to my OpenHAB and opened a second ssh conection to the karaf console
ssh -p 8101 openhab@localhost
The standard passphrase is habopen.
Running the command
feature:install openhab-transport-serial
will install the package. To prevent the reset of the serial connection, I added the modifications suggested by Chacha
The definition of my items, is in the item File under /etc/openhab/items
here I have a file named Meine_Items.items
. The file name is free of choice, but the ending must be items
.
Switch CUL_PROG_SWITCH "Shutter Programmieren" <switch>
Number rollingNumber_Arbeitszimmer "Befehlcounter Arbeitszimmer" <CULRollingNumber> (RollerCommandCounter)
the code to Python code to program a motor is in the file NewShutter.py
stored under /etc/openhab/scripts
#!/usr/bin/python
import serial
import argparse
# Baudrate used by Somfy
BaudRate = 38400 #In my case 38400 but I found 9600, too. But it was not working so it is just try and error
# Fixed Address the shutter will be programmed, Choose a unique one, for each Shutter or set of Shutters
address='00001A'
#Encryptionkey Somfy
encryptionKey = 'A1'
#Schnittstelle zum CUL
ser = serial.Serial('/dev/ttyUSB0', BaudRate, timeout=.1)
#Current RollingCode -> 0 if this is a new Shutter
INTRollingCode = 0
#Parse RollingCode to integer
STRRollingCode=hex(INTRollingCode)[2:].zfill(4).upper()
# Command (1 = My, 2 = Up, 4 = Down, 8 = Prog)
C="8"
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
ser.close()
If you program a new motor, the Address
in the NewShutter.py
must be a new one as well as the Number rollingNumber_Arbeitszimmer "Befehlcounter Arbeitszimmer" <CULRollingNumber> (RollerCommandCounter)
must be replace by a new one, with a different name.
Take care of your Addresses and the corresponding number items
The python script is triggered by a rule, stored under /etc/openhab/rules
in file with the ending .rules
rule "PROG SHUTTER"
when
Item CUL_PROG_SWITCH received command ON
then
logInfo("Python-Cul","Program")
val result =executeCommandLine(Duration.ofSeconds(1),"python", "/etc/openhab/scripts/NewShutter.py")
rollingNumber_Arbeitszimmer.postUpdate(1)
logInfo("Python-Cul",result)
end
In this rule you must put the number item in, which later keeps the rolling counter. I use the HabPanel. I just put the switch there and let it change to ON
. The Switch will not appear under the screen at the PaperUI. The reason is, that there is no Channel connected. You have to put it to a HabPanel or the BasicUI.
To trigger the programming, one must start the process by pressing the PROG Button on the remote. Keep it pressed until the shutter move up and down. Than press the Button. The shutters should now move up and down, too. If this is not the case:
- The Port is not
/dev/ttyUSB0
: Try different ports like /dev/ttyUSB1
or /dev/ttyUSB2
- Maybe the Baudrate is wrong: So check in the Python file.
- The Address was used before and the motor has a different RollingCode: This is hard to find; maybe it is better to just choose a different Address
To move my shutters now. I have one script to open them. To make them move up completely I send the command twice. If I send the command only once, my shutters only move a small step.
#!/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()
# Address you used to program the shutter before
address='00000A'
#Encryptionkey Somfy
encryptionKey = 'A1'
# Baudrate used by Somfy
BaudRate = 38400 #In my case 38400 but I found 9600, too. But it was not working so it is just try and error
#Schnittstelle zum CUL
ser = serial.Serial('/dev/ttyUSB0', BaudRate, timeout=.1)
#Parse RollingCode to integer
Introllingcode=int(args.rollingCode)
# Command (1 = My, 2 = Up, 4 = Down, 8 = Prog)
C="2"
#Parse integer RollingCode to HEX String with length 4 and without leading 0x an uppercase letters
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
time.sleep(.5)
Introllingcode=Introllingcode+1 # increment rollingCode for the next command to sen
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
ser.close()
print("Executet: <UP> on " + address + " with last Rolling Code " + STRRollingCode)
Here you have to replace the Address
and Baudrate
by the values you choose before. To trigger the script I use another button, defined in the same item file used before:
Switch MyShutterButton "Shutter moving" <switch> #Ofcourse you can reuse the first button, by just changing the rule
And for this item I defined a rule in the rule file before:
rule "Shutter UP"
when
Item MyShutterButton received command ON
then
val result =executeCommandLine(Duration.ofSeconds(2),"python", "/etc/openhab/scripts/OpenAllShutter.py", (rollingNumber_Arbeitszimmer.state as DecimalType).intValue.toString)
rollingNumber_Arbeitszimmer.postUpdate(2 + (rollingNumber_Arbeitszimmer.state as DecimalType))
logInfo("Python-Cul",result)
end
The rollingCode is incremented in the python script once, but I have to update the number item, too. This is done with the second line. This time by 2 because, I send to commands.
Moving the shutters down I use the following script:
#!/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()
#Fixe Adresse fuer alle Shutter
address='00000A'
#Encryptionkey Somfy
encryptionKey = 'A1'
# Baudrate used by Somfy
BaudRate = 38400 #In my case 38400 but I found 9600, too. But it was not working so it is just try and error
#Schnittstelle zum CUL
ser = serial.Serial('/dev/ttyUSB0', BaudRate, timeout=.1)
#Parse RoolingCode to integer
Introllingcode=int(args.rollingCode)
# Command (1 = My, 2 = Up, 4 = Down, 8 = Prog)
C="4"
#Parse integer RollingCode to HEX String with lengh 4 and without leading 0x an uppercase letters
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
time.sleep(.5)
Introllingcode=Introllingcode+1 #1
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
time.sleep(7)
C="1"
Introllingcode=Introllingcode+1 #2
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
time.sleep(.5)
C="2"
Introllingcode=Introllingcode+1 #3
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
time.sleep(.5)
Introllingcode=Introllingcode+1 #4
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
time.sleep(2)
C="1"
Introllingcode=Introllingcode+1 #5
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
time.sleep(.5)
C="4"
Introllingcode=Introllingcode+1 #6
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
time.sleep(.5)
Introllingcode=Introllingcode+1 #7
STRRollingCode=hex(Introllingcode)[2:].zfill(4).upper()
command = 'Ys' + encryptionKey + C + '0' + STRRollingCode + address + "\n"
ser.write(command)
ser.close()
print("Executed: <DOWN> on " + address + " with last Rolling Code " + STRRollingCode)
I use this script to completely close my shutters and change the angle of the blinds to close. I move up some time to make the script work, even if the shutter already moved to the lowest position. Than I move down, up and down again. his way my blinds change their angle to close.
The script is triggered by the rule:
rule "Shutter Down"
when
Item MyShutterButton received command OFF
then
val result =executeCommandLine(Duration.ofSeconds(30),"python", "/etc/openhab/scripts/CloseAllShutter.py", (rollingNumber_Arbeitszimmer.state as DecimalType).intValue.toString)
rollingNumber_Arbeitszimmer.postUpdate(8 + (rollingNumber_Arbeitszimmer.state as DecimalType))
logInfo("Python-Cul",result)
end
Since I send so many commands, I have to update the RollingCode by 8.
Final remark: To enable persistence:
Final Remark II: With the last update, the following lines were not working anymore. It seems that Openhab integrated/activated an standard service for persisted items. I had to remove the file rrd4j.persist.
I installed the rrd4j feature via Paper UI. I created the file rrd4j.persist
under /etc/openhab/persistence
. Here the name of the file is important. The content is:
```
Strategies {
Items {
- CULRollingNumber : strategy = restoreOnStartup*
}
```
This will work, if the group of the number items is CULRollingNumber
, a I defined it in my item file.
I hope this helps someone, to get started.