This is a example thread to show how the exec binding 2.x works with detailed explanations.
This tutorial only works since openHAB 2.3.0 Build #1212.
I set up a fresh installation of “Raspbian GNU/Linux 9 (stretch)” and installed OpenHAB just followed my own thread and found some more information i missed at the first time. It is based on the Tutorial from here.
First make sure you connect your transmitter with the Raspberry like follows. Have a look at the RPI pinout.
Pin ATAD Data to 11 - GPIO17
Pin GND to 6 - GND
Pin VCC to 4 - +5V
As RPi_utils send
uses wiringpi make sure it is installed.
gpio -v
gpio readall
If this does not work install wiringpi as described by Gordons Projects. Or use apt-get system as described in the wiringPi package
Now we need some executable program which controls the transmitter. We can use the RPi_utils send
for that. It has to be fetch from the git repo and build, if you change the directory make sure you do it everywhere.
mkdir src
cd src
git clone --recurse-submodules https://github.com/ninjablocks/433Utils.git
cd 433Utils/RPi_utils
make send
make codesend
Sidenote: If you encounter this error
make: *** No rule to make target '../rc-switch/RCSwitch.o', needed by 'send'. Stop.
Got to the root of the project :~/src/433Utils/
initialize the depending submodules and update them.
git submodule update --init --recursive
This is the remote which is delivered with the power plugs, it can control 4 devices A, B, C, D.
I configured my device to match the Address 10010 and the device B(2) as seen in the picture. Replace the Address and the device number to match your setting.
Try sending a command to your device with ./send <Address> <Device Number> <On/Off>
.
./send 10010 2 1
Now the user privileges for openhab has to be set.
Add openhab to the usergroup gpio so it is allowed to acces the gpio of the RPI and then try to use the send command as user openhab. This line expects the terminal to be in the folder containing src
.
sudo adduser openhab gpio
sudo -u openhab src/raspberry-remote/send 10010 2 1
Then the exec Binding and regex transformation have to be installed i use the Karaf console.
ssh -p 8101 openhab@localhost
Password:habopen
feature:install openhab-binding-exec
feature:install openhab-transformation-regex
logout
Now everything should be ready for setting up the OpenHAB UI.
I recommend that you had allready opened the UI of OpenHAB once before configuring the basic UI, which this tutorial explains. Try to open it in your browser, edit localhost to the IP of you RPI if you open the page from an other device.
http://localhost:8080/start/index
Back to the shell we start with a thing to connect to the exec binding. This will contain the command without or with parts of the arguments. This file will be at “/etc/openhab2/things/exec.things”. I called it “exec” like the binding.
sudo nano /etc/openhab2/things/exec.things
Thing exec:command:remote-send [
command="/home/pi/src/raspberry-remote/send %2$s",
interval=0,
autorun=true]
- “exec:command” refers to the binding. “:remote-send” is an arbitrary name.
- “command=…” is the command line to execute, “%2$s” will be replaced by the command send to the input channel. Which connects an item to this thing. It Is transformed by the “openhab-transformation-regex”.
- “interval=0” disables periodic execution
- “autorun=true” immediatly execute the command when the input channel got an command.
To connect the thing to the switch on the sitemap we need items. They are located at “/etc/openhab2/items/powerplugs.items”
sudo nano /etc/openhab2/items/powerplugs.items
// RF Socket Items
Group:Switch:OR(OFF, ON) Gplugs <poweroutlet>
Switch Power_Plug_Socket_1 <poweroutlet> (Gplugs)
Switch Power_Plug_Socket_2 <poweroutlet> (Gplugs)
Switch Power_Plug_Socket_3 <poweroutlet> (Gplugs)
Switch Power_Plug_Socket_4 <poweroutlet> (Gplugs)
String PlaceHolder ""
Switch Remote_Send { channel="exec:command:remote-send:run" }
String Remote_Send_Args { channel="exec:command:remote-send:input" }
String Remote_Send_Out { channel="exec:command:remote-send:output" }
- A group for all power sockets. We will use this as trigger in the rule.
- 4 switch items [Power_Plug_Socket_1 - 4] with an arbitrary name and the icon of a poweroutlet. This are used to define the layout of the UI later and store the state of the UI.
- A Switch item connected to the run channel of our thing, this will contain information about the status of the thing, like is it running or not.
- A String item connected to the input channel of our thing. This can contain the arguments which will replace the “%2$s” at the thing definition.
- A String item connected to the output channel of our thing, This will contain the return value of the executed command.
To have an visual representation of our switch we need an sitemap. This is located at “/etc/openhab2/sitemaps/powerplugs.sitemap” and has to be named same as the sitemap, here “powerplugs”.
sudo nano /etc/openhab2/sitemaps/powerplugs.sitemap
sitemap powerplugs label="Wireless Poweroutlets"
{
Frame label="Poweroutlets"
{
Switch item=Gplugs label="All Power Plugs"
Text item=PlaceHolder label="" icon="none"
Switch item=Power_Plug_Socket_1 label="Power Plug A"
Switch item=Power_Plug_Socket_2 label="Power Plug B"
Switch item=Power_Plug_Socket_3 label="Power Plug C"
Switch item=Power_Plug_Socket_4 label="Power Plug D"
}
}
This is explained in detail in the tutorials. Major detail is “item=Power_Plug_Socket_X” this connects the UI to the switch item which was defined previously.
Last thing to do is defining some rules which triggers desired actions. The rules are located at “/etc/openhab2/rules/powerplugs.rules”.
This Rule only works since openHAB 2.3.0 Build #1212. Before that the Member of trigger was not availabel.
sudo nano /etc/openhab2/rules/powerplugs.rules
import java.util.concurrent.locks.ReentrantLock
val ReentrantLock transmitter = new ReentrantLock
rule "Single Plug"
when
Member of Gplugs received command
// Item Power_Plug_Socket_1 received command or
// Item Power_Plug_Socket_2 received command or
// Item Power_Plug_Socket_3 received command or
// Item Power_Plug_Socket_4 received command
then
logInfo("Power_Plug", "Member " + triggeringItem.name + " to " + receivedCommand)
try {
// Lock transmitter so other executed rules dont't use it at the same time.
// Concurrent calls of the rule will wait till the resource is free again.
transmitter.lock()
// Get the item which triggered the rule
// Split the name and get the second part, the number to set as command.
val num = triggeringItem.name.toString.split("Power_Plug_Socket_").get(1)
// Set the command which should be executed to the output channel
// Auto trigger will then execute the Thing.
if(receivedCommand == ON){
Remote_Send_Args.sendCommand("10010 " + num +" 1")
}else{
Remote_Send_Args.sendCommand("10010 " + num +" 0")
}
// Wait for the command to complete
while(Remote_Send.state != OFF){
Thread::sleep(100)
}
// Mulltiple trigger do not work if there is no break here
// maybe external skript needs some time to properly free resources.
Thread::sleep(400)
logInfo("Power_Plug", Remote_Send_Out.state.toString.replaceAll("\r|\n"," ") )
}catch(Throwable t) {}
finally {
// Free the resource for the next call.
transmitter.unlock()
}
end
Rules are also explained in the tutorials. Basic thing to get some action is “Remote_Send_Args.sendCommand(“10010 2 1”)” sending a command to the input channel. This will set the state of the item Remote_Send_Args to “10010 2 1” and the autorun defined in the thing will cause an execution of the command line. While the thing is in action the state of the item Remote_Send will reflect this by beeing “ON”. After the command is executed the item Remote_Send_Out will contain the last return value of the executed command.
Try to open the page to display the switches, access it via following command, edit localhost to the IP of your RPI if you open the page from an other device.
http://localhost:8080/basicui/app
Additional:
Logging can be done with
ssh -p 8101 openhab@localhost
Password:habopen
openhab> log:tail
A side note: in the the OpenHab terminal the items can be listet with the command “smarthome:items”.
openhab>smarthome:items list
Power_Plug_Socket_1 (Type=SwitchItem, State=OFF, Label=null, Category=poweroutlet)
Remote_Send (Type=SwitchItem, State=OFF, Label=null, Category=null)
Remote_Send_Args (Type=StringItem, State=10010 2 0, Label=null, Category=null)
Remote_Send_Out (Type=StringItem, State=using pin 0
sending systemCode[10010] unitCode[2] command[0], Label=null, Category=null)
Thank you @rlkoshak and @steve1 for your assistance. Hopefully this helps others understand how things work.
Also @twolthaus and @domeninini for pointing out minor typos and privilege specification wich leaded me to the group permissions for the openhab user and the gpio, which is the best solution i could think of, in place of root for openhab.
Frequent seen logging
[ERROR] [hab.binding.exec.handler.ExecHandler] - An exception occurred while formatting the command line with the current time and input values : 'Format specifier '%2$s''
This Error is displayed when in the command the transformation of the input channel is use. So having %2$s
in the command and the command is triggered before there is an value in the input channel.
Or when the exec binding is triggered by .sendCommand to the run channel instead of the input channel.
[ERROR] [.script.engine.ScriptExecutionThread] - Rule 'Poweroutlet B': An error occurred during the script execution: The name '<unkown>' cannot be resolved to an item or type.
After i edited the items and rules for all 3 GUI switches i had this error. Restarting the RPI got it runningn
[hab.binding.exec.handler.ExecHandler] - Couldn’t transform response because transformationService of type ‘REGEX’ is unavailable
You forgot to install the regex transformation service.
LED Stripes
Additionally i post my solution for some LEDs stripes.
This is the LED controller and the RF remote.
I decoded the commands which the remote sends with RFSniffer from 433Utils which also contains send and sendcode to controll the transceiver.
So getting it done is then straight forward, just add a thing, items, a sitemap and a rule to controll the LED stripe.
exec.things
Thing exec:command:remote-codesend [
command="/home/pi/src/433Utils/RPi_utils/codesend %2$s",
interval=0,
autorun=false]
ledStripe.itmes
...
Items for RF Plugs
...
String PlaceHolder ""
// LED Stripe 433MHz
Group:Switch:OR(OFF, ON) GledStripe_1
Switch LED_Stripe_OnOff (GledStripe_1)
Switch LED_Stripe_LightMode (GledStripe_1)
Switch LED_Stripe_BrightUp (GledStripe_1)
Switch LED_Stripe_BrightDown (GledStripe_1)
Switch LED_Stripe_100 (GledStripe_1)
Switch LED_Stripe_50 (GledStripe_1)
Switch LED_Stripe_25 (GledStripe_1)
Switch LED_Stripe_ModeNext (GledStripe_1)
Switch LED_Stripe_ModePrev (GledStripe_1)
Switch LED_Stripe_faster (GledStripe_1)
Switch LED_Stripe_slower (GledStripe_1)
Switch Remote_CodeSend { channel="exec:command:remote-codesend:run" }
String Remote_CodeSend_Args { channel="exec:command:remote-codesend:input" }
String Remote_CodeSend_Out { channel="exec:command:remote-codesend:output" }
ledStripe.sitemap
sitemap ledStripelabel="Wireless ledStripe"
{
Frame label="LED Stripe"
{
Switch item=LED_Stripe_OnOff label="ON/OFF"
Switch item=LED_Stripe_LightMode label="Light"
Switch item=LED_Stripe_100 label="100%"
Switch item=LED_Stripe_50 label=" 50%"
Switch item=LED_Stripe_25 label=" 25%"
Text item=PlaceHolder label="" icon="none"
Switch item=LED_Stripe_BrightUp label="Brightness +"
Switch item=LED_Stripe_BrightDown label="Brightness -"
Switch item=LED_Stripe_ModeNext label="Mode Up"
Switch item=LED_Stripe_ModePrev label="Mode Down"
Switch item=LED_Stripe_faster label="Speed Up"
Switch item=LED_Stripe_slower label="Speed Down"
}
}
ledStripe.rules
This Rule only works since openHAB 2.3.0 Build #1212. Before that the Member of trigger was not availabel.
import java.util.concurrent.locks.ReentrantLock
val ReentrantLock transmitter = new ReentrantLock
...php
rules for RF sockets
...
rule "LED Stripe 1"
when
Member of GledStripe_1 received command
// Item LED_Stripe_OnOff received command or
// Item LED_Stripe_LightMode received command or
// Item LED_Stripe_BrightUp received command or
// Item LED_Stripe_BrightDown received command or
// Item LED_Stripe_100 received command or
// Item LED_Stripe_50 received command or
// Item LED_Stripe_25 received command or
// Item LED_Stripe_ModeNext received command or
// Item LED_Stripe_ModePrev received command or
// Item LED_Stripe_faster received command or
// Item LED_Stripe_slower received command
then
//logInfo("LED_Stripe", "Member " + triggeringItem.name + " to " + receivedCommand)
try {
// Lock transmitter so other executed rules dont't use it at the same time
transmitter.lock()
// Manual reset, somehow it get stuck sometimes.
// This avoids a lock when state of Remote_CodeSend is not updated properly.
Remote_CodeSend.sendCommand(OFF)
switch triggeringItem.name {
case "LED_Stripe_OnOff" : Remote_CodeSend_Args.sendCommand("11607809")
case "LED_Stripe_LightMode" : Remote_CodeSend_Args.sendCommand("11607812")
case "LED_Stripe_BrightUp" : Remote_CodeSend_Args.sendCommand("11607813")
case "LED_Stripe_BrightDown": Remote_CodeSend_Args.sendCommand("11607814")
case "LED_Stripe_100" : Remote_CodeSend_Args.sendCommand("11607815")
case "LED_Stripe_50" : Remote_CodeSend_Args.sendCommand("11607816")
case "LED_Stripe_25" : Remote_CodeSend_Args.sendCommand("11607817")
case "LED_Stripe_ModeNext" : Remote_CodeSend_Args.sendCommand("11607819")
case "LED_Stripe_ModePrev" : Remote_CodeSend_Args.sendCommand("11607821")
case "LED_Stripe_faster" : Remote_CodeSend_Args.sendCommand("11607823")
case "LED_Stripe_slower" : Remote_CodeSend_Args.sendCommand("11607825")
default : logInfo("LED", "Error in switch!")
}
// Manual trigger transmitter
// If Remote_CodeSend_Args is set to the same value it does not trigger
// when autorun=true, so set autorun=false and use manual trigger to be
// able to trigger one command multiple times.
Remote_CodeSend.sendCommand(ON)
// Wait for the command to complete.
while(Remote_CodeSend.state != OFF){
Thread::sleep(100)
}
//logInfo("LED_Stripe",
// Remote_CodeSend_Out.state.toString.replaceAll("\r|\n"," ") )
// Reset switch signalize command is finished.
triggeringItem.postUpdate(OFF)
}catch(Throwable t) {}
finally {
transmitter.unlock()
}
end
For more funny stuff have a look here: