How can i retrieve those two lines:
Changing discoverable off succeeded [CHG] Controller 64:6E:69:F4:9E:72 Discoverable: no
Basically grabbing the output or other possible error outputs and discarding the rest of the garbage
I’m attempting to do a fork of a very simple bluethooth dmenu bash script, and I am being somewhat successful at it, but since I’ve considered releasing it to the public, it has to have error handling and be a generally rounded script, etc…
What im trying to now do is when i echo “power off” | bluethothctl i want to get the messages it sends internally like: Changing discoverable off succeeded, org.bluez.something is blocked, etc…
I’ve tried while read -r debug, putting it to a $( ) and then debugging it with notify or echo but i always get either the outside garbage(like Agent registered, [IFROGZ] discoverable off, etc..)
Is there a way i can grab those delicious internal message’s bluetoothctl sends internally to a variable without boogaloo tactics(like outputting everything to a file and then reading it)
I think what i said above is the only thing you hopefully solve this question for me but just because previously i’ve been downvoted for not showing code here’s a part of it
finalArgs[inc++]=" " finalArgs[inc++]=$(echo show | _bluetoothctl | grep -m 1 "Powered:" | cut -c2- | sed -e "s/Powered/Power/") finalArgs[inc++]=$(echo show | _bluetoothctl | grep -m 1 "Discoverable:"| cut -c2-) finalArgs[inc++]=$(echo show | _bluetoothctl | awk "/Pairable:/{i++}i==2{print; exit}"| cut -c2-) name=$(printf '%sn' "${finalArgs[@]}" | dmenu -l ${#finalArgs[@]} -p "btmenu") [[ $name ]] || return mac=${name:format+2:-1} if [[ ${name:1:1} != " " ]]; then #avoiding a if here #echo $name #echo $name notify "Changing $name" mac=$(echo "$name" | sed -e "s/: yes/ off/") if [[ $mac =~ "$name" ]]; then mac=$(echo "$name" | sed -e "s/: no/ on/") fi debug=$(echo ${mac,,} | _bluetoothctl) echo $debug #notify $debug #notify "" exit else (...)
whats weird is that i use the same tactic for getting the show elements but it doesnt work for those specific “debugging messages”
Advertisement
Answer
I am not sure that bluetoothctl
was intended to be used in this way. BlueZ has a documented API that uses DBus bindings available for most languages at:
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/
This can be done from the bash command line below:
pi@raspberry:~ $ busctl get-property org.bluez /org/bluez/hci0 org.bluez.Adapter1 Discoverable b false pi@raspberry:~ $ busctl set-property org.bluez /org/bluez/hci0 org.bluez.Adapter1 Discoverable b true pi@raspberry:~ $ busctl get-property org.bluez /org/bluez/hci0 org.bluez.Adapter1 Discoverable b true pi@raspberry:~ $
This can also be done with language bindings. For example using pydbus in Python:
pi@raspberry:~ $ python3 Python 3.7.3 (default, Jul 25 2020, 13:03:44) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import pydbus >>> bus = pydbus.SystemBus() >>> dongle = bus.get('org.bluez', '/org/bluez/hci0') >>> dongle.Discoverable True >>> dongle.Discoverable = False >>> dongle.Discoverable False >>>
If you want to catch the changes then you need to connect into the event loop. For example:
from time import sleep import pydbus from gi.repository import GLib bus = pydbus.SystemBus() dongle = bus.get('org.bluez', '/org/bluez/hci0') def print_change(iface, prop_changed, prop_removed): print('Adapter prop changed:', iface, prop_changed, prop_removed) def toggle_discoverable(state): dongle.Discoverable = state def toggle_power(state): dongle.Powered = state dongle.onPropertiesChanged = print_change mainloop = GLib.MainLoop() GLib.timeout_add_seconds(3, toggle_discoverable, True) GLib.timeout_add_seconds(5, toggle_discoverable, False) GLib.timeout_add_seconds(8, toggle_power, False) GLib.timeout_add_seconds(10, toggle_power, True) try: mainloop.run() except KeyboardInterrupt: mainloop.quit()
Which gives the output:
$ python3 print_bluez_change.py Adapter prop changed: org.bluez.Adapter1 {'Discoverable': True} [] Adapter prop changed: org.bluez.Adapter1 {'Discoverable': False} [] Adapter prop changed: org.bluez.Adapter1 {'Powered': False, 'Discovering': False, 'Class': 0} [] Adapter prop changed: org.bluez.Adapter1 {'Class': 4980736} [] Adapter prop changed: org.bluez.Adapter1 {'Powered': True} []