LoginSignup
5
4

More than 5 years have passed since last update.

send-dbus で bluez とおしゃべり

Last updated at Posted at 2017-10-31

Linux の Bluetooth ドライバ bluez には、色々なツールが付属しているが、対話的に使う正式な方法は bluetoothctl コマンドで、プログラム的には bluetoothd の提供する DBus API を使うのが正しい方法らしい。なので BT の動作を確認するために send-dbus を使ってみた。

まず、BT Adapter があるかどうか調べる。dbus-send がターミナルで dbus と対話するコマンドだが、オプションの意味は以下の通り。

  • --print-reply: 応答を待って返す。=literal を付けると応答をそのまま表示するので整形したりするのに便利。--type=method_call が指定されたとみなされる。
  • --system: DBus には全ユーザ共通の system bus と各ユーザごとの session bus という二つのバスがある。bluez は system bus しかないので --system を指定する。
  • --dest=org.bluez: 接続先
  • /org/bluez: オブジェクトパス
  • org.freedesktop.DBus.Introspectable.Introspect: インタフェース.メンバ (メソッドやシグナルの名前)
  • | xmllint --format -: 読みやすく整形します。

オブジェクト指向的に考えると、接続先とオブジェクトパスの組み合わせでレシーバを指定して、インタフェース.メンバがメッセージという事になる。

# dbus-send --print-reply=literal --system --dest=org.bluez /org/bluez org.freedesktop.DBus.Introspectable.Introspect | xmllint --format -
<?xml version="1.0"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
  <interface name="org.freedesktop.DBus.Introspectable">
    <method name="Introspect">
      <arg name="xml" type="s" direction="out"/>
    </method>
  </interface>
  <interface name="org.bluez.AgentManager1">
    <method name="RegisterAgent">
      <arg name="agent" type="o" direction="in"/>
      <arg name="capability" type="s" direction="in"/>
    </method>
    <method name="UnregisterAgent">
      <arg name="agent" type="o" direction="in"/>
    </method>
    <method name="RequestDefaultAgent">
      <arg name="agent" type="o" direction="in"/>
    </method>
  </interface>
  <interface name="org.bluez.ProfileManager1">
    <method name="RegisterProfile">
      <arg name="profile" type="o" direction="in"/>
      <arg name="UUID" type="s" direction="in"/>
      <arg name="options" type="a{sv}" direction="in"/>
    </method>
    <method name="UnregisterProfile">
      <arg name="profile" type="o" direction="in"/>
    </method>
  </interface>
  <node name="hci0"/>
</node>

最後の <node name="hci0"/> が BT Adapter を表す。

ここで使ったメソッド org.freedesktop.DBus.Introspectable.Introspect は DBus で共通に使われるメソッドで、オブジェクトパスの内容を調べるのに使う。この応答を見ると、/org/bluez/ では org.bluez.AgentManager1 などのインタフェースが使えたり、子要素 hci0 がある事が分かる。API については bluez のドキュメントに解説がある。例えば org.bluez.AgentManager1 なら agent-api.txt に書いてある。

次に、ペアリングされたデバイスを探す。device-api.txt によると、デバイスを表すオブジェクトは /org/bluez/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX に出てくるので /org/bluez/hci0 を Introspect する。

# dbus-send --print-reply=literal --system --dest=org.bluez /org/bluez/hci0 org.freedesktop.DBus.Introspectable.Introspect | xmllint --format -
...
  <node name="dev_B8_8A_60_E6_20_61"/>
  <node name="dev_D4_0B_1A_F2_FE_DC"/>
</node>

ここで表示されるデバイスのうち、ペアリングされているかどうかを示す情報は Properties として実装されている

boolean Paired [readonly]

ので、とりあえず全部のプロパティを表示する org.freedesktop.DBus.Properties.GetAll を使う。

# dbus-send --print-reply=literal --system --dest=org.bluez /org/bluez/hci0/dev_D4_0B_1A_F2_FE_DC org.freedesktop.DBus.Properties.GetAll string:org.bluez.Device1
   array [
      dict entry(
         Address         variant             D4:0B:1A:F2:FE:DC      )
      dict entry(
         Name         variant             M00213      )
      dict entry(
         Alias         variant             M00213      )
      dict entry(
         Class         variant             uint32 5898764
      )
      dict entry(
         Icon         variant             phone      )
      dict entry(
         Paired         variant             boolean true
      )
...

これで、このデバイスが接続中である事が分かる。DBus.Properties.html によると、GetAll を使うには引数としてインターフェース名を指定する。Introspect すると分かるが、dev_XX_XX_XX_XX_XX_XX で使えるインタフェースには org.freedesktop.DBus.Introspectable、org.bluez.Device1、org.freedesktop.DBus.Properties、org.bluez.Network1、org.bluez.MediaControl1 があってそれぞれにプロパティがあるので、必要なインタフェースを指定しなくてはならない。

ちなみに dbus-send の引数を指定する時は string:org.bluez.Device1 のように型を指定する。

実際のプログラムでは GetAll では無く freedesktop.DBus.Properties.Get でプロパティの一つを取ってくる機会が多いと思う。

# dbus-send --print-reply=literal --system --dest=org.bluez /org/bluez/hci0/dev_D4_0B_1A_F2_FE_DC org.freedesktop.DBus.Properties.Get string:org.bluez.Device1 string:Paired
   variant       boolean true

参考

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4