Simple Exec Binding Curl Command

Greetings, openHAB noob here. I’m trying to just have openHAB execute a simple http request. If first tried the http module, but it was just more complicated than what I needed, and it refused to quit re-executing the http command (I guess it thinks it must poll the url for status, and that’s not at all what I need. I then saw the exec binding option thinking I could just execute a simple “curl ABC.NET” (dummy example, there are 4 possible commands and I was going to build a thing for each). All I’m expecting back is a 200 status code, nothing else. I added “curl” to the whitelist file and rebooted, but I can’t seem to get the thing to execute. I can’t imagine this is that complicated. I can ssh in to by Pi running the latest openhabian, execute the curl, and it works fine. I’ve created the thing, and added it to a model with my “family room”, and tried to execute it via the big giant “null” button, but no joy. I know I’m missing something, after hours or reading docs and trying a myriad of options, I give, I need to phone a friend.

In linux, such as on the PI, everything runs in a “environment”. One of the things about an environment is aliases or the default shortcuts for commonly used commands. When you type curl at the command line the user environment knows that is supposed to mean the binary file at /usr/bin/curl. Commands run by the exec binding run in a different environment than the standard user and don’t typically have access to all those shortcuts, so you probably can’t use jusdt curl and have to use the complete path to the command /usr/bin/curl.

Seems logical, but adding the full path to curl as suggested, didn’t change the result. I also tried adding it to the whitelist as “/usr/bin/curl” which also didn’t help.

You need to add the full command exactly as you send it from openHAB to the whitelist. Did you do that? Are you running on docker? Just want to make sure that you execute the CMD on the same host when you test this.

If you don’t identify your openHAB version correctly, you will get conflicting advice and docs. Both HTTP and Exec changed greatly OH2-3.

My Examples

Thing file

// Binding => Exec Things
// Created: 8-8-2020
// Edited: 8-1-2021
// Version: 3.1


// Populate Drew's Pagerduty status
Thing exec:command:PdDrewCount  "Exec_PD_Drew" @ "EXEC" [command="/etc/openhab/exec/check_pdtriggered.py XXXXXX", interval=60, timeout=5]
Thing exec:command:PdDrewCountACK  "Exec_PD_Drew_ACK" @ "EXEC" [command="/etc/openhab/exec/check_pdacknowledged.py XXXXXX", interval=60, timeout=5]

// Populate Chris's Pagerduty status
Thing exec:command:PdChrisCount "Exec_PD_Chris" @ "EXEC" [command="/etc/openhab/exec/check_pdtriggered.py YYYYYY", interval=60, timeout=5]
Thing exec:command:PdChrisCountACK "Exec_PD_Chris_ACK" @ "EXEC" [command="/etc/openhab/exec/check_pdacknowledged.py YYYYYY", interval=60, timeout=5]

// Populate ISP Statistics
Thing exec:command:ISPCheck      "Exec_ISP_Check" @ "EXEC" [command="/etc/openhab/exec/check_upstream.sh isp", interval=60, timeout=10]
Thing exec:command:IPCheck       "Exec_IP_Check" @ "EXEC" [command="/etc/openhab/exec/check_upstream.sh ip", interval=60, timeout=10]
Thing exec:command:ISPHOSTCheck  "Exec_ISPHOST_Check" @ "EXEC" [command="/etc/openhab/exec/check_upstream.sh host", interval=60, timeout=10]
Thing exec:command:ISPCITYCheck  "Exec_ISPCITY_Check" @ "EXEC" [command="/etc/openhab/exec/check_upstream.sh city", interval=60, timeout=10]
Thing exec:command:ISPDateCheck  "Exec_ISPDATE_Check" @ "EXEC" [command="/etc/openhab/exec/check_upstream.sh update", interval=60, timeout=10]
Thing exec:command:ISPWANCheck   "Exec_ISPWAN_Check" @ "EXEC" [command="/etc/openhab/exec/check_upstream.sh upstream", interval=60, timeout=10]

// Populate theater Roku (roku_info.sh also generates icons on call)
Thing exec:command:RokuTheaterPlugin  "Exec_Roku_Theater_Plugin" @ "EXEC" [command="/etc/openhab/exec/roku_plugin.sh", interval=60, timeout=10]
Thing exec:command:RokuTheaterID  "Exec_Roku_Theater_ID" @ "EXEC" [command="/etc/openhab/exec/roku_id.sh", interval=10, timeout=5]
Thing exec:command:RokuTheaterState  "Exec_Roku_Theater_State" @ "EXEC" [command="/etc/openhab/exec/roku_state.sh", interval=60, timeout=10]
Thing exec:command:RokuTheaterResult "Exec_Roku_Theater_Result" @ "EXEC" [command="/etc/openhab/exec/roku_command.sh", interval=0, timeout=10]
Thing exec:command:RokuTheaterStatus "Exec_Roku_Theater_Status" @ "EXEC" [command="/etc/openhab/exec/roku_info.sh", interval=10, timeout=10]


// Openhab Diagnostic dumps
Thing exec:command:OHchildren  "Exec_OH_Children" @ "EXEC" [command="/etc/openhab/exec/oh_metrics.sh children", interval=30, timeout=10]
Thing exec:command:OHwaiting  "Exec_OH_Waiting" @ "EXEC" [command="/etc/openhab/exec/oh_metrics.sh waiting", interval=30, timeout=10]
Thing exec:command:OHblocked  "Exec_OH_Blocked" @ "EXEC" [command="/etc/openhab/exec/oh_metrics.sh blocked", interval=30, timeout=10]
Thing exec:command:OHrules    "Exec_OH_Rules" @ "EXEC" [command="/etc/openhab/exec/oh_metrics.sh rules", interval=35, timeout=10]
Thing exec:command:OHjava    "Exec_OH_Java" @ "EXEC" [command="/etc/openhab/exec/oh_metrics.sh heap", interval=31, timeout=10]
Thing exec:command:OHjavacom   "Exec_OH_JavaCommit" @ "EXEC" [command="/etc/openhab/exec/oh_metrics.sh java1", interval=31, timeout=10]
Thing exec:command:OHjavamax   "Exec_OH_JavaMax" @ "EXEC" [command="/etc/openhab/exec/oh_metrics.sh java2", interval=31, timeout=10]

// BBS Status
Thing exec:command:BBSStatus    "Exec_BBS_Status" @ "EXEC" [command="curl -s http://bbs.stardoc134.com/scripts/status_item.php", interval=20, timeout=5]

// Hacked DOF string
Thing exec:command:DayWeek     "Exec_DayOfWeek" @ "EXEC" [command="/etc/openhab/exec/oh_metrics.sh day", interval=1200, timeout=5]

And Whitelist

# For security reasons all commands that are used by the exec binding or transformation need to be whitelisted.
# Every command needs to be listed on a separate line below.
# Misc => Exec Whitelist
# Created: 8-8-2020
# Edited: 8-1-2021
# Version: 3.1

/etc/openhab/exec/check_pdtriggered.py XXXXXX
/etc/openhab/exec/check_pdtriggered.py XXXXXX
/etc/openhab/exec/check_pdacknowledged.py YYYYYY
/etc/openhab/exec/check_pdacknowledged.py YYYYYY
/etc/openhab/exec/check_upstream.sh ip
/etc/openhab/exec/check_upstream.sh isp
/etc/openhab/exec/check_upstream.sh host
/etc/openhab/exec/check_upstream.sh city
/etc/openhab/exec/check_upstream.sh update
/etc/openhab/exec/check_upstream.sh wan
/etc/openhab/exec/check_upstream.sh upstream
/etc/openhab/exec/check_ip.sh
/etc/openhab/exec/check_host.sh
/etc/openhab/exec/check_upstream.sh
/etc/openhab/exec/roku_plugin.sh
/etc/openhab/exec/roku_id.sh
/etc/openhab/exec/roku_state.sh
/etc/openhab/exec/oh_metrics.sh children
/etc/openhab/exec/oh_metrics.sh blocked
/etc/openhab/exec/oh_metrics.sh waiting
/etc/openhab/exec/oh_metrics.sh rules
/etc/openhab/exec/oh_metrics.sh tree
/etc/openhab/exec/oh_metrics.sh heap
/etc/openhab/exec/oh_metrics.sh java1
/etc/openhab/exec/oh_metrics.sh java2
curl -s http://bbs.stardoc134.com/scripts/status_item.php
/etc/openhab/exec/roku_command.sh
/etc/openhab/exec/roku_info.sh
/etc/openhab/exec/oh_metrics.sh day

Side note, for whitelists.

There are times when I need to pass a variable or state on to my exec thing. This is not really practical having to whitelist every variation. In cases like the roku, where I want to send a command or payload that varies. I place my payload in a virtual item in Openhab, then execute the script/exec via a rule when it’s contents change. My Bash or python scripts will pull that item out directly from the API, do it’s magic, then return the result as normal via the EXEC binding.

My understanding is that you can set the HTTP binding to not poll using a command Channel instead of a state Channel.

I can guarantee, as you are seeing here, that the Exec binding is not going to be any simpler than the HTTP binding.

Have you considered the use of the sendHttpGetRequest Action in a rule? That would probably be the simplest approach. The executeCommandLine Action in a rule would probably be the second simplest approach overall, though the points brought up byJustinG still are a concern. These commands will be running as the limited rights openhab user in their own environment.

Any time you are working with low level bindings (HTTP, Exec, Serial, MQTT, modbus, Serial, etc.) it’s going to be complicated because there are far fewer assumptions that can be made and you as the user need to have a greater level of knowledge about how the underlying technology works. And bindings like Exec open huge security problems when not implemented properly, which adds additional complexity (e.g. the whitelist) to mitigate.

What does that second part ( seem to get the thing to execute ) mean ?

  • do you know if the execute is triggered at all ?
  • is it a problem of permissions ?
  • is there any error message in the log openhab.log file ?
  • is it executed but may be not reported back as you expect ?
  • what are your configuration details ( OH version; think configuration; … )

You need to add the complete commandline to your whitelist, not just the curl executable…

Folks, first I want to thank you all for the replies. I’ve spent a lot of time trying all of your suggestions. I went back and tried 3 avenues. I should add that I have the latest image of OpenHabian 3.1.0 running on Raspberry Pi 3B, just to address any questions on version. My use case is to open/close/tiltopen/tiltclose blinds which work via very simple https calls to a web services in the form of https://controlsite.com/serialnumber/command. There is no status beyond getting a return code of https 200 if the command was received.

First, I’ve created an HTTP thing with the appropriate base URL. This seems to fire as soon as I enable the rule, so at least that does something. BUT, it seems like no matter what I do, the thing insists on polling the url for status. I don’t know how to make it send the command once and stop. If say I create and allow an open and a close command to be online with any channels linked to them (I tried several kinds), then the command seem to clash as the blinds are going up and down and 1/2 way up and then 1/4 down and on and on in a loop. If it weren’t frustrating, it would be hilarious - like living in a haunted house!

Second, I tried using the exec command to use curl. Several folks rightly pointed out that I had to include the entire command which while I find that very counter intuitive, I did add all 4 full commands I needed in the form of “/usr/bin/curl https://controlsite.com/serialnumber/command”, but I can’t get a peep out of those things. I guess I don’t know what to do beyond creating the things. I tried several permutations of adding channels, but I guess I just don’t get what to setup in OpenHab for that.

Third, I tried creating rules with sendHttpGetRequest. This basically got me to the same place as the exec command. Its all in there, but I don’t know what to do to get it to fire.

What I ultimately want to do is get one of these command methods to be triggered by Alexa if that helps clarify my goal. I know I’m missing some steps, but at least getting one of these things to execute successfully would encourage me that I’m on the right path. Thank you all again.

I would start with something like ( all untested code ) these things:

Thing exec:command:openblinds      "open_blinds"       @ "Home" [command="/etc/openhab/scripts/blinds.sh open",      interval=0, timeout=5, autorun=false]
Thing exec:command:closeblinds     "close_blinds"      @ "Home" [command="/etc/openhab/scripts/blinds.sh close",     interval=0, timeout=5, autorun=false]
Thing exec:command:tiltopenblinds  "tiltopen_blinds"   @ "Home" [command="/etc/openhab/scripts/blinds.sh tiltopen",  interval=0, timeout=5, autorun=false]
Thing exec:command:tiltcloseblinds "tilt_close_blinds" @ "Home" [command="/etc/openhab/scripts/blinds.sh tiltclose", interval=0, timeout=5, autorun=false]

Add items like

Switch Blinds_Open      "Blinds_Open"           {channel="exec:command:openblinds:run"}
Switch Blinds_Close     "Blinds_Close"          {channel="exec:command:closeblinds:run"}
Switch Blinds_TiltOpen  "Blinds_TiltOpen"       {channel="exec:command:tiltopenblinds:run"}
Switch Blinds_TiltClose "Blinds_TiltClose"      {channel="exec:command:tiltcloseblinds:run"}

So that they can be used in a sidemap or widget.

Script could look like:

#!/bin/sh

case $1 in
        open|close|tiltopen|tiltclose)
                COMMAND=$1
                ;;

        *)
                COMMAND="close"
                ;;

/usr/bin/curl  https://controlsite.com/serialnumber/$COMMAND
# checking return codes / returned results would go here

Once the switches are available in e.g. a sitemap they already can be tested.

If you show your Thing’s config it would go a long way to help us help you. My understanding is that there is a way to configure the HTTP thing so it only issues the HTTP call when it is commanded to do so.

It’s a security feature. Anyone or any thing that can access your openHAB instance over the network can execute any arbitrary command on the machine it’s running on without any authentication or authorization. The whitelist of commands helps to mitigate that.

It is also documented. Exec - Bindings | openHAB The examples should make it clear that the full command as it’s configured in the Thing is required but we are always open to discussing improvements to the docs.

It depends on how the Things are configured. For something like this you’d link a Switch Item to the run Channel. When that Item receives an ON command the binding will execute the command line and put the results of the run into the Item linked to the output channel. Again, showing your configs will help us tremendously.

Did you trigger the rule to run? Again, showing your configuration will help us understand. Otherwise all we can really do is say RTFM and make wild guesses as to where you might be going wrong.