[SOLVED] Exec commandLine/bash script (Unifi) via rule

Hello,
i have been trying for days to control my unifi controller with a bash script with curl by rule. in the terminal the script also works. i have a switch item that executes a rule. the bash script is also executed, but the curl command in the bash script is not executed correctly. all attempts with “@@” and “” have been unsuccessful so far.
i hope someone can help me!

my rule:

    rule "Switch G-Wlan on or off"
when
    Item WLAN_switch received command
then
        executeCommandLine("/etc/openhab2/scripts/unifi_wlan_guest.sh enable" ,5000)
end

openhab.log:

2019-01-30 21:41:27.788 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine '/etc/openhab2/scripts/unifi_wlan_guest.sh enable'

bash script unifi_wlan_guest.sh:

#!/bin/bash

unifi_username=name
unifi_password='pass'
unifi_controller=https://192.168.x.x:XXXX
wifi_id=abscdsaf654kasfekpj
cookie=/tmp/cookie

curl_cmd="curl -s -S --cookie ${cookie} --cookie-jar ${cookie} --insecure "

unifi_login() {
 # authenticate against unifi controller
 # Mute response by adding > /dev/null
 ${curl_cmd} -H "Content-Type: application/json" -X POST -d "{\"password\":\"$unifi_password\",\"username\":\"$unifi_username\"}" $unifi_controller/api/login > /dev/null
}

unifi_logout() {
 # logout
 ${curl_cmd} $unifi_controller/logout
}

enable_wifi() {
 # enables guest wifi network
 # Mute response by adding > /dev/null
 ${curl_cmd} "$unifi_controller"'/api/s/default/rest/wlanconf/'"$wifi_id" -X PUT --data-binary '{"_id":"'"$site_id"'","enabled":true}' --compressed > /dev/null
}

disable_wifi() {
 # enables guest wifi network
 # Mute response by adding > /dev/null
 ${curl_cmd} "$unifi_controller"'/api/s/default/rest/wlanconf/'"$wifi_id" -X PUT --data-binary '{"_id":"'"$site_id"'","enabled":false}' --compressed > /dev/null
}

check_status() {
 # checks wifi network status
 # Mute response by adding > /dev/null
 response=$(${curl_cmd} "$unifi_controller"'/api/s/default/rest/wlanconf/'"$wifi_id" --compressed)
 status=$(echo $response | jq ".data[0].enabled")
 if [ "$status" == "true" ]; then
 exit 0
 elif [ "$status" == "false" ]; then
 exit 1
 else
 echo exit -1
 fi
}

unifi_login
if [ "$1" == "enable" ]; then
 echo "Enabling WiFi."
 enable_wifi
elif [ "$1" == "disable" ]; then
 echo "Disabling WiFi."
 disable_wifi
elif [ "$1" == "status" ]; then
 check_status
else
 echo "Must include command line parameter [enable|disable|status]."
fi
unifi_logout

Add some echos to your script so it outputs something when the script executes. That will prove its executing.

Add a log to output the results in your executeCommandLine. This will also help show it’s executing and show any errors it might be generating.

Are you aware there is a UniFi Binding?

You could also use the SNMP binding, looking at what your doing with your script. But if there is also a UniFi binding it’s likely to be less effort and more resilient using that instead.

The Unifi binding doesn’t provide the functionality being used in the script.

Perhaps the 5000 ms timeout is not sufficient? Maybe increase it to eliminate it as a potential source of the problem.

the batch script works in the cli as root without any problems. the output is in json format.
when i execute “sudo -u openhab”, i get “login.ok” as output for the function unifi_login() and “error.loginrequired” for the function “enable_wifi()”. so a bit contradictory.
i suppose the curl command in “enable_wifi()” is changed somehow when called.
the answer of the script comes also within one second. i changed the timeout already, unfortunately without success.

case1)
isn’t there a way to execute a bash script as if i were running it with root or another user outside the JVM? so i don’t have to look for “@@” or something like that in the script, e.g. if i use curl? maybe with python?
case2)
or can you migrate the old unifi-binding functions from openhab1 to openhab2 binding? the old binding still had several functions (https://github.com/octa22/org.openhab.binding.unifi)

Well, this might be one problem. OH doesn’t run as root. Your script must run as the openhab user.

Get rid of the pipes to /dev/null so you can see what the curl command is telling you.

You can execute a script outside of OH any way you want. But if you want to do it from OH you need to have a way to have OH call the script or have OH send a message to something else running that can call the script.

You can execute a script as root using sudo as part of your command. But you will have to add the openhab user to sudoers. Google will provide lots of examples.

I wouldn’t spend too much time on this though until after you stop suppressing the output from the curl command so you can see why the command is failing. I’m willing to bet curl is saying exactly why it is failing.

Why can’t you just use the 1.x version of the binding in the first place? You might need to enable “Show Legacy 1.x version bindings” in PaperUI for it to show up in the list. But it will work on OH 2.

Okay, thanks for all your help!
Problem was the following:
the “§site” variable wasn’t set first and second the " ’ " in front and behind had to be deleted. i got this by starting the script with “bash -xv …/unifi_wlan_guest.sh” and then with “sudo -u openhab …/unifi_wlan_guest.sh”.
also: the cookie had to be deleted, because there were old/inconsistent data there. therefore the script gets a “rm $cookie” at the last line.
now everything works as intended.
here is the current working script:

#!/bin/bash

unifi_username=user
unifi_password='pass'
unifi_controller=https://192.168.x.xx:xxxx
wifi_id=dsa4fsda6g46fdsg984
cookie=/tmp/cookie

#site_id=""             // deprecated

curl_cmd="curl -s -S --cookie ${cookie} --cookie-jar ${cookie} --insecure "

unifi_login() {
 # authenticate against unifi controller
 # Mute response by adding > /dev/null
 ${curl_cmd} -H "Content-Type: application/json" -X POST -d "{\"password\":\"$unifi_password\",\"username\":\"$unifi_username\"}" $unifi_controller/api/login #> /dev/null
}

unifi_logout() {
 # logout
 ${curl_cmd} $unifi_controller/logout
}

enable_wifi() {
 # enables guest wifi network
 # Mute response by adding > /dev/null
 ${curl_cmd} "$unifi_controller"'/api/s/default/rest/wlanconf/'"$wifi_id" -X PUT --data-binary '{"_id":"'$site_id'","enabled":true}' --compressed #> /dev/null
}

disable_wifi() {
 # enables guest wifi network
 # Mute response by adding > /dev/null
 ${curl_cmd} "$unifi_controller"'/api/s/default/rest/wlanconf/'"$wifi_id" -X PUT --data-binary '{"_id":"'$site_id'","enabled":false}' --compressed #> /dev/null
}

check_status() {
 # checks wifi network status
 # Mute response by adding > /dev/null
 response=$(${curl_cmd} "$unifi_controller"'/api/s/default/rest/wlanconf/'"$wifi_id" --compressed)
 status=$(echo $response | jq ".data[0].enabled")
 if [ "$status" == "true" ]; then
 exit 0
 elif [ "$status" == "false" ]; then
 exit 1
 else
 echo exit -1
 fi
}

unifi_login
if [ "$1" == "enable" ]; then
 echo "Enabling WiFi."
 enable_wifi
elif [ "$1" == "disable" ]; then
 echo "Disabling WiFi."
 disable_wifi
elif [ "$1" == "status" ]; then
 check_status
else
 echo "Must include command line parameter [enable|disable|status]."
fi
unifi_logout
rm $cookie

1 Like