I am using Raspbian Stretch 9.4 on a Zero W. The goal is to deploy it headless for long periods of time where it will broadcast a specified bluetooth signal. When someone tries to connect to it, it will automatically pair, log the connected/paired mac address to a file along with an info request out of bluetoothctl. Then it's going to sit and wait for the next request and do the same thing in a loop.
I know this likely involves using dbus and likely an agent in bluez but truth be told I'm drowning trying to understand these scripts and cannot find one that works off stretch to do what I want.
I've tried making an expect script to automate the setup features but couldn't control when a device pairs how to isolate the mac (to send the info command on whatever device connected). I could also use a << EOF setup but again I couldn't figure out how to isolate the MAC of a connected device.
My googling lead me to monitoring the dbus but I have no idea how to get things setup using it. It's way over my head.
So far this is the script I'm working with but it did not log a pairing of an android phone while the script was running:
#!/usr/bin/python
import os
import sys
import signal
import logging
import logging.handlers
import dbus
import dbus.service
import dbus.mainloop.glib
import gobject
#LOG_LEVEL = logging.INFO
LOG_LEVEL = logging.DEBUG
LOG_FILE = "/home/pi/pylog.log"
LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s"
BLUEZ_DEV = "org.bluez.MediaControl1"
def device_property_changed_cb(property_name, value, path, interface, device_path):
global bus
if property_name != BLUEZ_DEV:
return
device = dbus.Interface(bus.get_object("org.bluez", device_path), "org.freedesktop.DBus.Properties")
properties = device.GetAll(BLUEZ_DEV)
logger.info("Getting dbus interface for device: %s interface: %s property_name: %s" % (device_path, interface, property_name))
if properties["Connected"]:
bt_addr = "_".join(device_path.split('/')[-1].split('_')[1:])
logger.INFO("MAC Found: %s" % bt_addr)
#cmd = "" % bt_addr
#logger.info("Running cmd: %s" % cmd)
#os.system(cmd)
else:
bt_addr = "_".join(device_path.split('/')[-1].split('_')[1:])
logger.info("Device: %s has disconnected" % bt_addr)
# cmd = "for i in $(pactl list short modules | grep module-loopback | grep source=bluez_source.%s | cut -f 1); do pactl unload-module $i; done" % bt_addr
# logger.info("Running cmd: %s" % cmd)
# os.system(cmd)
def shutdown(signum, frame):
mainloop.quit()
if __name__ == "__main__":
# shut down on a TERM signal
signal.signal(signal.SIGTERM, shutdown)
# start logging
logger = logging.getLogger("bt_auto_loader")
logger.setLevel(LOG_LEVEL)
#logger.addHandler(logging.handlers.SysLogHandler(address = "/home/pi/pylog.log"))
logger.info("Starting to monitor Bluetooth connections")
# Get the system bus
try:
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
except Exception as ex:
logger.error("Unable to get the system dbus: '{0}'. Exiting. Is dbus running?".format(ex.message))
sys.exit(1)
# listen for signals on the Bluez bus
bus.add_signal_receiver(device_property_changed_cb, bus_name="org.bluez", signal_name="PropertiesChanged", path_keyword="device_path", interface_keyword="interface")
try:
mainloop = gobject.MainLoop()
mainloop.run()
except KeyboardInterrupt:
pass
except:
logger.error("Unable to run the gobject main loop")
sys.exit(1)
logger.info("Shutting down")
sys.exit(0)
Log returned:
INFO:bt_auto_loader:Starting to monitor Bluetooth connections
INFO:bt_auto_loader:Shutting down
This is what dbus monitor is showing when I click pair on an android phone:
signal time=1554344215.452003 sender=:1.3 -> destination=(null destination) serial=351 path=/org/bluez/hci0; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
string "org.bluez.Adapter1"
array [
dict entry(
string "Discoverable"
variant boolean true
)
]
array [
]
signal time=1554344240.507939 sender=:1.3 -> destination=(null destination) serial=352 path=/org/bluez/hci0/dev_F8_F1_B6_E2_BB_06; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
string "org.bluez.Device1"
array [
dict entry(
string "Connected"
variant boolean true
)
]
array [
]
signal time=1554344240.527694 sender=:1.0 -> destination=(null destination) serial=3088 path=/org/freedesktop/systemd1; interface=org.freedesktop.systemd1.Manager; member=UnitNew
string "sys-devices-platform-soc-20201000.serial-tty-ttyAMA0-hci0-hci0:11.device"
object path "/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dsoc_2d20201000_2eserial_2dtty_2dttyAMA0_2dhci0_2dhci0_3a11_2edevice"
signal time=1554344240.531963 sender=:1.0 -> destination=(null destination) serial=3089 path=/org/freedesktop/systemd1; interface=org.freedesktop.systemd1.Manager; member=UnitNew
string "sys-subsystem-bluetooth-devices-hci0:11.device"
object path "/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dbluetooth_2ddevices_2dhci0_3a11_2edevice"
signal time=1554344246.427736 sender=:1.3 -> destination=(null destination) serial=353 path=/org/bluez/hci0/dev_F8_F1_B6_E2_BB_06; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
string "org.bluez.Device1"
array [
dict entry(
string "Connected"
variant boolean false
)
]
array [
]
signal time=1554344246.466625 sender=:1.0 -> destination=(null destination) serial=3090 path=/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dbluetooth_2ddevices_2dhci0_3a11_2edevice; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
string "org.freedesktop.systemd1.Device"
array [
dict entry(
string "SysFSPath"
variant string "/sys/devices/platform/soc/20201000.serial/tty/ttyAMA0/hci0/hci0:11"
)
]
array [
]
signal time=1554344246.478715 sender=:1.0 -> destination=(null destination) serial=3091 path=/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dbluetooth_2ddevices_2dhci0_3a11_2edevice; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
string "org.freedesktop.systemd1.Unit"
array [
dict entry(
string "ActiveState"
variant string "inactive"
)
dict entry(
string "SubState"
variant string "dead"
)
dict entry(
string "StateChangeTimestamp"
variant uint64 1554344246457571
)
dict entry(
string "StateChangeTimestampMonotonic"
variant uint64 1488121717330
)
dict entry(
string "InactiveExitTimestamp"
variant uint64 1554344240525803
)
dict entry(
string "InactiveExitTimestampMonotonic"
variant uint64 1488115785558
)
dict entry(
string "ActiveEnterTimestamp"
variant uint64 1554344240525803
)
dict entry(
string "ActiveEnterTimestampMonotonic"
variant uint64 1488115785558
)
dict entry(
string "ActiveExitTimestamp"
variant uint64 1554344246457571
)
dict entry(
string "ActiveExitTimestampMonotonic"
variant uint64 1488121717330
)
dict entry(
string "InactiveEnterTimestamp"
variant uint64 1554344246457571
)
dict entry(
string "InactiveEnterTimestampMonotonic"
variant uint64 1488121717330
)
dict entry(
string "Job"
variant struct {
uint32 0
object path "/"
}
)
dict entry(
string "ConditionResult"
variant boolean false
)
dict entry(
string "AssertResult"
variant boolean false
)
dict entry(
string "ConditionTimestamp"
variant uint64 0
)
dict entry(
string "ConditionTimestampMonotonic"
variant uint64 0
)
dict entry(
string "AssertTimestamp"
variant uint64 0
)
dict entry(
string "AssertTimestampMonotonic"
variant uint64 0
)
]
array [
]
signal time=1554344246.490121 sender=:1.0 -> destination=(null destination) serial=3092 path=/org/freedesktop/systemd1; interface=org.freedesktop.systemd1.Manager; member=UnitRemoved
string "sys-subsystem-bluetooth-devices-hci0:11.device"
object path "/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dbluetooth_2ddevices_2dhci0_3a11_2edevice"
signal time=1554344246.492135 sender=:1.0 -> destination=(null destination) serial=3093 path=/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dsoc_2d20201000_2eserial_2dtty_2dttyAMA0_2dhci0_2dhci0_3a11_2edevice; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
string "org.freedesktop.systemd1.Device"
array [
dict entry(
string "SysFSPath"
variant string "/sys/devices/platform/soc/20201000.serial/tty/ttyAMA0/hci0/hci0:11"
)
]
array [
]
signal time=1554344246.493270 sender=:1.0 -> destination=(null destination) serial=3094 path=/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dsoc_2d20201000_2eserial_2dtty_2dttyAMA0_2dhci0_2dhci0_3a11_2edevice; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged
string "org.freedesktop.systemd1.Unit"
array [
dict entry(
string "ActiveState"
variant string "inactive"
)
dict entry(
string "SubState"
variant string "dead"
)
dict entry(
string "StateChangeTimestamp"
variant uint64 1554344246457643
)
dict entry(
string "StateChangeTimestampMonotonic"
variant uint64 1488121717400
)
dict entry(
string "InactiveExitTimestamp"
variant uint64 1554344240525883
)
dict entry(
string "InactiveExitTimestampMonotonic"
variant uint64 1488115785639
)
dict entry(
string "ActiveEnterTimestamp"
variant uint64 1554344240525883
)
dict entry(
string "ActiveEnterTimestampMonotonic"
variant uint64 1488115785639
)
dict entry(
string "ActiveExitTimestamp"
variant uint64 1554344246457643
)
dict entry(
string "ActiveExitTimestampMonotonic"
variant uint64 1488121717400
)
dict entry(
string "InactiveEnterTimestamp"
variant uint64 1554344246457643
)
dict entry(
string "InactiveEnterTimestampMonotonic"
variant uint64 1488121717400
)
dict entry(
string "Job"
variant struct {
uint32 0
object path "/"
}
)
dict entry(
string "ConditionResult"
variant boolean false
)
dict entry(
string "AssertResult"
variant boolean false
)
dict entry(
string "ConditionTimestamp"
variant uint64 0
)
dict entry(
string "ConditionTimestampMonotonic"
variant uint64 0
)
dict entry(
string "AssertTimestamp"
variant uint64 0
)
dict entry(
string "AssertTimestampMonotonic"
variant uint64 0
)
]
array [
]
signal time=1554344246.507212 sender=:1.0 -> destination=(null destination) serial=3095 path=/org/freedesktop/systemd1; interface=org.freedesktop.systemd1.Manager; member=UnitRemoved
string "sys-devices-platform-soc-20201000.serial-tty-ttyAMA0-hci0-hci0:11.device"
object path "/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dsoc_2d20201000_2eserial_2dtty_2dttyAMA0_2dhci0_2dhci0_3a11_2edevice"