0

This is a great solution as far as it goes:

How to use bluetoothctl like hcitool lescan to report repeated proximity beacons

I want to take it one step further though: instead of printing the beacon detections to the terminal, I want to pipe each detected beacon's MAC address to a command that publishes it to a Mosquitto broker. This would be useful for adding the beacons to HomeAssistant, for example, for presence detection of a key fob attached to a person's house keys. I managed to get this idea to work by modifying the last two lines of the script above but it only publishes the first detection ... then no more. I guess somehow the scan is being turned off or aborted by trying to run the mosquitto_pub command. (something to do with interrupting the thread or subshells????)

Here are the last lines of the script with the MAC addresses of my TWO TEST BEACONS obfuscated. You can see the full script that I modified at the link above.

) | sed --unbuffered --quiet --expression 's/^.*Device //p' \
| grep --line-buffered -E 'FF:FF::::|FF:GG::::' \
| stdbuf -oL cut -c 1-17 \
| { read topic; mosquitto_pub -d -u username -P password -m ON -t monitor/$topic; }

Note: | stdbuf -oL cut -c 1-17 \ trims the output down to just the MAC address - e.g. FF:GG::::

The last line publishes the ON command to an unique state topic ending in the beacon's MAC address e.g. 'monitor/FF:GG::::'.

If I remove that last line the detections are added as they occur to the terminal console in an ever growing list as time goes by. But once I add the last line it only works once, then goes dead.

How can the script be made to respond to each detection, not just the first one? And why exactly does it only respond to the first detection then hang?

  • It seems to be that `bluetoothctl` was never designed to work in this way and the depth of your command pipes make it very difficult to debug and maintain. The scanning for Bluetooth beacons can be accessed through the BlueZ D-Bus API from most languages. Here is a [python example](https://stackoverflow.com/a/66480222/7721752) . There are also [MQTT clients](http://www.eclipse.org/paho/index.php?page=downloads.php) for various languages. – ukBaz Mar 09 '21 at 13:19

1 Answers1

0

The command line tools of BlueZ are not designed for this purpose, so it makes them very difficult to pipe scan results reliably. In my experience, processes die or hang, and you end up with broken pipes.

The C APIs of BlueZ are much more stable. I wrote a simple command line program in C that you could use instead of bluetoothctl for this purpose:

https://gist.github.com/davidgyoung/0a18028b4338ff6cb201fba274502662

That program must be compiled with cc scanner.c -lbluetooth -o scanner, after which you can start the scanner with just scanner. The output of the program will be something like this:

B8:27:EB:1F:93:4D -68 02 01 06 11 06 82 75 25 D9 37 9D D7 8F 5F 4A F4 20 00 00 75 30
71:5C:23:9D:BC:7F -68 02 01 1A 02 0A 0C 0B FF 4C 00 10 06 03 1A 3B D4 B2 EB
B8:27:EB:1F:93:4D -68 02 01 06 11 06 82 75 25 D9 37 9D D7 8F 5F 4A F4 20 00 00 75 30
4A:53:7F:64:71:EC -91 03 03 9F FE 17 16 9F FE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
69:0D:FF:7B:75:65 -73 02 01 1A 02 0A 0C 0A FF 4C 00 10 05 03 1C 27 BB 63
61:39:71:E9:1D:C9 -93 02 01 1A 02 0A 18 0A FF 4C 00 10 05 01 18 3B 24 12
B8:27:EB:1F:93:4D -68 02 01 06 11 06 82 75 25 D9 37 9D D7 8F 5F 4A F4 20 00 00 75 30

Each line above shows the MAC address of the detected bluetooth device, followed by the signal strength RSSI, then the hex bytes of the advertisement.

I use this program to pipe into other shell scripts, and have found it to be reliable over many days. Feel free to use it if helpful.

davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • Thanks for your time and interest. This really is a knotty problem! I tried your script and it worked as expected but it seems to hang or crash after anything from a few seconds to one or two minutes. I tried to pipe the results to the MQTT publish command but, again, it only works on the first detection then returns to the command prompt so I guess it has either crashed or hung? – davidhit Mar 09 '21 at 22:43
  • You will need to repeatedly spawn the command when it exits. It is designed to exit after a fixed number of detections. You can modify the source to make it not do that if you wish — it is pretty simple. – davidgyoung Mar 11 '21 at 00:35