気の向くままに辿るIT/ICT/IoT
webzoit.net
PC

いろいろなOSでBluetoothスピーカーを使う

ウェブ造ホーム前へ次へ
サイト内検索
カスタム検索
周辺機器を使う

いろいろなOSでBluetoothスピーカーを使う

いろいろなOSでBluetoothスピーカーを使う

2021/11/26

 PC周辺機器の1つにスピーカーが、無線のスピーカーには、Bluetoothスピーカーがあります。

Daiso 1000円BluetoothスピーカーWS001 White

 今回は、スマホ、パソコンのOS Debian GNU/Linux bullseye、Raspberry Pi 3B+のRaspberry Pi OS Raspbian bullseyeで100均ダイソーの1000円BluetoothスピーカーWS001 Whiteを使って再生させてみました。

 我が家では、現時点でRaspberry Pi 3B+は2台あり、自作スマートスピーカーデスクトップ周辺機器を使ったサブパソコンとして使っています。

 Bluetoothについて自身は、セキュリティ面でなんとなく抵抗がありつつ、WiFiタイプのワイヤレスキーボードやワイヤレスマウスは使っているのですが、これまでガッツリBluetooth機器を使ったことはなく、検証としてパソコンとスマホ、パソコンとESP32ガジェットのペアリングをしたことがある程度です。

 Bluetoothスピーカーについては、深く考えることもなく、パソコンやスマホのスピーカーとBluetoothスピーカー同時に再生することはできないんだろうね、それだとつまらないなという思いもありました。

 一方、ちょこちょこ種類が増える100円ショップのダイソーのBluetoothスピーカーも、ちょっと手にとって見た時、2〜3時間!?というバッテリ駆動の再生時間の短さと同じくらいかかるらしき充電時間に絶句して関心がなかったのですが、1000円Bluetoothスピーカーをよく見ると連続再生14時間!こりゃ買いでしょということで検証魂が疼いたのでした。

 他にBluetooth 5.0、充電3.5時間、高音域+低音域用Wスピーカーで重低音も特徴らしく、2台でステレオ再生可能、USB-AポートとmicroSD/TFカードスロットを備え、USBメモリ/microSD/TFカードの音源再生も可能...他、結構な仕様で高コスパなWS001。

外付けスピーカー購入歴

 かくいう自身が、これまで買った外付けスピーカーは、今では自作スマートスピーカーのスピーカーとして使っているLogicool Z120、もう当該ノート自体ないので使っていないものの、以前、内蔵スピーカーがいかれた古いノートPCで使っていたセリア2個でステレオのアンプなしスピーカーと現在メインのノートPCで使っているダイソー300円スピーカーくらい、そして今回、無線、ダイソーの1000円Bluetoothスピーカー。

 このように音に格別のこだわりはない自身ですが、確か1500円程度だったLogicool Z120もダイソーの300円のUSBスピーカーも1000円のBluetoothスピーカーも音質からして、とてもコスパが良いなと思っています。

[2021/11/30] Cando500円USBミニスピーカーも仲間入り。

目的

 今回、検証を兼ねつつ、実用的な使用目的としては、ただでさえ心地良いバスタイムに、より一層のリラクゼーションを求めてダイニングキッチンに置いてある自作スマートスピーカーから主に音楽を流すことです。

 そのままだと、風呂の扉を開けて静かに湯船に浸かっているなど音を立てなければ、微かに音が聴こえるかな程度なので。

 もちろん、音量を上げれば、聴こえるでしょうが、ダイニングキッチンに居られないほどの大音量では困るので。

Androidスマホ/Android 10でダイソー1000円Bluetoothスピーカーを再生

 スマホでは、[設定]からBluetoothを有効にしてペアリングするだけで、あっさり、音源再生できました。

 一度、ペアリングが完了した後は、圏内にあるWS001の電源を投入すれば、自動接続されます。

 到達範囲は、10mくらいはいけてます。

パソコン/Debian bullseyeでダイソー1000円Bluetoothスピーカーを再生

debian:~$ sudo apt install -y bluez pulseaudio-module-bluetooth
debian:~$ bluetoothctl
[bluetooth]# power on
[bluetooth]# agent on
[bluetooth]# devices
[bluetooth]# scan on
Discovery started
...
[NEW] Device AA:11:BB:22:xE:xE DAISO_WS001
...
[bluetooth]# pair AA:11:BB:22:xE:xE
Attempting to pair with AA:11:BB:22:xE:xE
...
Pairing successful
[bluetooth]# paired-devices
Device AA:11:BB:22:xE:xE DAISO_WS001
[DAISO_WS001]# connect AA:11:BB:22:xE:xE
Attempting connect to AA:11:BB:22:xE:xE
Connection successful
...
[DAISO_WS001]# quit
debian:~$

 Debianでもbluetoothctlで(噂によるとpower on、agent on、続いて)scan on、[DAISO_WS001]のMACアドレスをpair、続いてconnect、デスクトップ上で[PulseAudio音量調節]の出力タブで[DAISO_WS001]をデフォルトに設定することで、あっさり、再生できました。

 これも到達範囲は、10mくらいは余裕でいけてます。

 自身の場合、Debian Stretchの頃だったか使ったことがあったからでしょう、すでにLinuxでBluetooth接続と言えばというほどのbluezが入っており、bluetoothctlコマンドが使える状態でした。

 また、その頃すでにPulseAudioを常用していたからか、pulseaudio-module-bluetoothも入っていました。

 これらがない場合、インストールする必要があります。

 よく見るとmetapackageとなっているbluetoothの他、bluemanパッケージも入っていますが、後者は、たぶん、GUI操作に必要なパッケージの1つかも。

 以前は、bluez-utilsなどもあったようですが、今は変わっているようなので環境に合わせて他にも必要なものがあれば見繕ってください。

 尚、scan onしてエラーになる場合は、scan offしてからscan onし直すと結果表示されました。

 ちなみにデバイスプロンプト[DAISO_WS001]#でquitやexitしても[bluetooth]#に戻ること無く、ホストプロンプトに返ってきました。

debian:~$ sudo vi /lib/systemd/system/bluetooth.service
...
ExecStart=/usr/libexec/bluetooth/bluetoothd --noplugin=sap
...
(:wq)
debian:~$ killall pulseaudio
debian:~$ pulseaudio --start
debian:~$ sudo systemctl daemon-reload
debian:~$ sudo systemctl restart bluetooth.service
debian:~$ bluetoothctl
[bluetooth]# devices
[bluetooth]# scan on
Discovery started
...
[NEW] Device AA:11:BB:22:xE:xE DAISO_WS001
...
[bluetooth]# pair AA:11:BB:22:xE:xE
Attempting to pair with AA:11:BB:22:xE:xE
...
Pairing successful
[DAISO_WS001]# connect AA:11:BB:22:xE:xE
Attempting connect to AA:11:BB:22:xE:xE
Connection successful
...
[DAISO_WS001]# quit
debian:~$

 が、一転、bluetoothctl disconnect/removeしたり、他デバイスと接続したりして、改めてDebianでつなごうと思ったら、後述のRaspbianでもあったsap系のエラーに見舞われました。

 よってbluetoothctlをquitかexitで抜けて、同じ対策[/lib/systemd/system/bluetooth.service](/lib/でなく/etc/のケースもあるかも)ファイルの[ExecStart=...]行の末尾に半角スペースを空けて[--noplugin-sap]を追記、killall pulseaudio、pulseaudio --start、sudo systemctl daemon-reload、sudo systemctl restart bluetooth.serviceする必要がありました。

debian:~$ bluetoothctl
[DAISO_WS001]# remove AA:11:BB:22:xE:xE
...
[bluetooth]# pair AA:11:BB:22:xE:xE
...
[DAISO_WS001]# connect AA:11:BB:22:xE:xE
...
Attempting connect to AA:11:BB:22:xE:xE
Connection successful
...
[DAISO_WS001]# quit
debian:~$

 それでもつながらない場合は、一度、bluetoothctlで[DAISO_WS001]のMACアドレスをdisconnect/removeして再度pair/connectすることでつながるはずです。

bluetooth trustで表示されなくなる接続時の許可/拒否ポップアップパネル

 ペアリング後、PC起動(再起動)後か起動中かに関わらず、WS001の電源を投入すると自動認識、自動接続しようとし、接続前に、このように[常に許可]/[許可する]/[拒否]の3択がデスクトップ上にポップアップされることがありましたが、bluetoothctlで当該機器をtrustしたところ、表示されなくなりました。

 ただ、/etc/bluetooth/main.confで[AutoEnable=true]や[DiscoverableTimeout = 0]しているからか、最初にPulseAudio音量調節というGUIパネルでデフォルトに設定したからか、PC起動中にこのBluetoothスピーカーの電源を入れると自動ペアリングというか、自動コネクトしてくれるのですが、即、切断されてしまうんですよね...英語のソースには同症状の人がいますが、解決した人がいても、え?それじゃ解決しないけど...という状態で解決策が見つからない...。

 もちろん、CLIかGUIでconnectすればつながる状態となり、その後、勝手に切断されることはないんですけど。

 これってつながったままににできないもの?っていうか、なんで、せっかく自動接続したのに、わざわざ切れるのか?

 実は、RaspberryPi OS Raspbianでもそうなのですが、スマホ(しかもLinux系のAndroid)だと何の問題もなくできていることなのでDebian系?bullseye?特有の症状?それとも相性でもある?一説にはPulseAudioのバグって話も...。

 自動接続時にスクリプトを割り込ませれば...と思いますが、初回の切断時のみ再接続ってどうやって...。

[2022/07/18] cron対応スクリプトは後述。

解決できたかも?な方法
debian_raspberrypi:~$ cat .force_ws001_bt_con.sh
#!/bin/bash
 
a=`echo info AA:BB:CC:DD:EE:FF | bluetoothctl | grep Connected | awk -F" " '{print $2}'`
if [ $a=="no" ];then echo connect AA:BB:CC:DD:EE:FF | bluetoothctl;fi
echo "try connect first"
sleep 10
b=`echo info AA:BB:CC:DD:EE:FF | bluetoothctl | grep Connected | awk -F" " '{print $2}'`
echo "try comfirm second"
sleep 15
if [ $b == "yes" ];then
  echo "connected first"
  pactl set-sink-volume bluez_sink.AA_BB_CC_DD_EE_FF.a2dp_sink 70%
  pacmd list-cards | grep "active profile: "
  if [ $? = 1 ];then
    echo "a2dp none"
    echo "retry connect"
    killall pulseaudio
    for i in {1..2}
    do
      echo disconnect AA:BB:CC:DD:EE:FF | bluetoothctl
      sleep 2
      echo connect AA:BB:CC:DD:EE:FF | bluetoothctl
      sleep 5
    done
  fi
  echo "maybe connected"
  echo "or"
else
  echo "OFF"
fi  
debian_raspberrypi:~$ crontab -e
0-59 * * * * /path/to/force_target_bt_con.sh
*/2 * * * * /path/to/force_target_bt_con.sh
debian_raspberrypi:~$
[2022/07/12]

 やっと解決したかな?な方法がこれ。

 たまに1回空振ることもありますが、cronしていれば、その場合でも次のタイミングでつながるはず。

 ただし、微妙なのが、同じスクリプトでもシステムディスクとして4年ほど使っていたUSBメモリではダメで新品のSSDに差し替えたらできたこと。

 2週間ほど前の6/27、一度システムが訳わからない状態になったものの、upgrade前後のタイミングだったのでシステムに起因するものと判断し、同じUSBメモリに焼き直したのですが、USBメモリ自体に問題があった可能性も否定しきれず。

 これが原因なのか、以後、bluetoothスピーカーを接続すると最初はうまくいっても、しばらくすると音源が途切れスマートスピーカーからの再生となり、bluetoothスピーカーは接続状態となったまま。

 bluetoothctl操作しようにもdisconnectはうまくいくものの、その後、connectしようとすると[Failed to connect: org.bluez.Error.NotReady]。

 こうなるとラズパイを再起動しないと直らず、必ず再発する始末。

 ちなみに接続状態のままconnectすると成功したと言うものの、状況は全く変わらず、disconnectしようとするとプロンプトは返ってくるが実際切断されることなく変化なし。

 このBluetoothスピーカー、通常は、20分程度すると電源OFFする仕様も接続状態になっているからか自動OFFせず。

 そこで.hcdファイルの入れ替え対処後、うまくいったかと思いきや最初だけで、すぐに再発。

 続いて[Solved] Bluetooth down and hciconfig hci0 up timeoutの対処を施すも、マシンを再起動せずにやってみても再起動後に試しても、やはり、再発。

 使用していたUSBメモリだと何れにせよ、その状況下でsystem restart bluetoothすると[Loading LTKs timed out for hci0]となってしまうという状況でした。

 ともあれSSDに替えてみてうまくいったスクリプト概要としてはこんな感じ。

  • Bluetoothスピーカーの接続を2回確認、1回めはnoなら試しにONにしてみる、2回めがyesなら、スピーカーの電源がONと判断、電源ONなら、
    • 必要に応じてpactl set-sink-volumeで音量を設定。
    • pacmd list-cardsの出力から[active profile: <a2dp_sink>]行があることを確認。
      • 当該行がなければ、
        • pulseaudioをkillallしてpulseaudioを起動。
        • 念の為、Bluetoothスピーカーを切断、接続(再接続)を2回繰り返す。

 スピーカー再接続を2回繰り返しているのは、1度だとなぜか失敗することが頻発したため。

 冒頭述べた通り、スリープ調整をしてみても、たいていは当該スクリプトの初回実行で接続、再生されますが、時々、初回空振り、(cron)2回めに接続、再生されることがあります。

 あとスクリプトによっては、それでもできたこともありましたし、稀なケースだとは思いますが、スピーカー自体の自動接続と当該スクリプト実行が同時に重なった場合は、自動接続できませんが、cronなら次回うまくいくはず。

 2回を超えることはない模様なので、これを許容できれば、解決と言えると思います。

 1箇所くらいは要らないかもしれませんが、ほかは秒数はともかく、スクリプト内のsleepは必要だと思います。

 尚、cronで自動化していれば運用時そういうことはないとは思いますが、端末操作しつつ、スクリプトが終了する前にBluetoothスピーカーの電源を落とすとタイミングによってはスクリプト通り、disconnect/connectを2回繰り返すことがありますが、その後、終了するので無視して良いはずです。

 さて、以後も例外なく、毎回ちゃんと機能しますように...(祈)。

[2022/07/15]

 解決したかと思ったら、スクリプト単独ではいける、cronするとなんか変、bluetoothctlでの操作でも、systemctl status bluetoothでも芋づる式にエラー発生、しまいには、マシンを再起動させないとダメになる...原因調査中...わがんねけど...。

 1分ごとに実行していたものを2分ごとにしたら...と思いきや、それでもダメ。

 一度は接続され、正常に再生されているかと思いきや、いつの間にかスマートスピーカー側のスピーカーに切り替わってはいるのですが、Bluetoothスピーカは接続状態(青LED点灯)のままフリーズ...。

 なんで?

 とりあえず、cronは使わず、都度、スクリプト実行で。

[解決]cronではスクリプト内のコマンドもフルパスで
debian_raspberrypi:~$ cat .force_ws001_bt_con.sh
#!/bin/bash
 
a=`/bin/echo info AA:BB:CC:DD:EE:FF | /bin/bluetoothctl | /bin/grep Connected | /bin/awk -F" " '{print $2}'`
if [ $a=="no" ];then /bin/echo connect AA:BB:CC:DD:EE:FF | /bin/bluetoothctl;fi
/bin/echo "try connect first"
/bin/sleep 10
b=`/bin/echo info AA:BB:CC:DD:EE:FF | /bin/bluetoothctl | /bin/grep Connected | /bin/awk -F" " '{print $2}'`
/bin/echo "try comfirm second"
/bin/sleep 15
if [ $b == "yes" ];then
  /bin/echo "connected first"
  /bin/pactl set-sink-volume bluez_sink.AA_BB_CC_DD_EE_FF.a2dp_sink 70%
  /bin/pacmd list-cards | /bin/grep "active profile: "
  if [ $? = 1 ];then
    /bin/echo "a2dp none"
    /bin/echo "retry connect"
    /bin/killall /bin/pulseaudio
    for i in {1..2}
    do
      /bin/echo disconnect AA:BB:CC:DD:EE:FF | /bin/bluetoothctl
      /bin/sleep 2
      /bin/echo connect AA:BB:CC:DD:EE:FF | /bin/bluetoothctl
      /bin/sleep 5
    done
  fi
  /bin/echo "maybe connected"
  /bin/echo "or"
else
  /bin/echo "OFF"
fi  
debian_raspberrypi:~$
[2022/07/18]

 わ、わかっちゃったかも...凡ミスを犯し...cronから呼ぶスクリプト内のコマンド、フルパスで書くの忘れてました...。

 cronが、どれを認識してどれが認識できないか、よく知らないため、全てのコマンドをフルパスにしましたが。

 /bin/killallするpulseaudioをも/bin/pulseaudioに(これ重要だったみたい、ここだけ変えなかったら、同症状に見舞われた...)。

 Bluetoothスピーカーが切断され、スマートスピーカー側のスピーカーに切り替わったりすることもなく、cron設定の1分ごとに何かおかしなことが起きることもなく、どうやら、大丈夫そうです。

[2022/07/24]

 SSD換装後も、音源切断、スマートスピーカーに切り替わるも、Bluetoothデバイスを見失った模様、マシン再起動後、正常になる状況が再発。

 通販のダンボールを筐体としたラズパイスマートスピーカーのみで検証しており、夏に入ったタイミングで熱暴走に起因する可能性もあるか?

 ということで現在、筐体のフタを開放・検証中...。

 結果、今までの同症状の時より、明らかに長い時間、再生が続いており、経過良好っぽい...。

 続いて側面4面に窓を作り、上部フタを閉めて検証中...。

 これも経過良好っぽい...。

 ラズパイケースにファン搭載済みな一方、安全を見て更に夏場限定で良さげながら追加でUSBファン等の導入を試みる予定。

自作スマートスピーカーに熱暴走対策で追加のDC20Vファン
[2022/07/26]

 一昨日は、8時間程度?は再生できたものの、充電切れを懸念し、途中、USB給電し始めて1時間程度?で同じ症状に見舞われました。

 以前から、最初からでも、途中でもUSB給電しながらだと短時間で切断されるような気がしてますが、気のせいか、たまたま、そのタイミングで気温上昇著しく落ちたのか...。

 今日も蒸し暑く、USB給電しても、しなくても超短時間で同症状に見舞われました。

 何れにせよ、追加冷却は必要そうということで市販の小さなUSBファンを探したらダイソーですら500円か700円商品、各種通販では1000円前後〜、何れも筐体に収まりそうなものはなさ気。

 というわけで、これも市販品もありましたが、部品取りしてあったと思しき、手持ちのDC20V仕様のPC用?冷却ファンを、とりあえず、昇圧せずにプラグコネクタを介したACアダプターDC12Vにつなぎ、ラズパイケース上に載せ、ラズパイスマートスピーカー用電源を分岐、給電して様子見中。

 尚、ラズパイスマートスピーカーの筐体フタは閉、ダイソー1000円BluetoothスピーカーWS001は、USB給電しながら再生。

 ちなみに写真のファンは、撮影用の代用で3線 DC20Vの別物ですが、実際に使った2線ファンもサイズは、これと同じ80mmx80mm、XHプラグ付きでしたが、2線XHコネクタの手持ちがなかったこともあり、切断。

 今日も7時間超えたあたりで切断、スマートスピーカー側に切り替わり、bluetoothctlでconnectしてみると[Failed to connect: org.bluez.Error.NotReady]...再発。

 タイミング的には、スマートスピーカーの音源をパネルメニューから再生させたノートPCのフタを閉じ、サスペンドに入った直後...ですが、以後、何度、同じ状況でやってみても再現なし。

 途中、風が吹き、涼しくもあったり、その後、再度、蒸し、エアコンの冷房をつけ、スマートスピーカーのあるダイニングが涼しくなるかならないかの一方、料理中の熱気が充満...。

 この熱の影響かな...、直前までは快調だったのですが...。

 それでも毎回、その後のスマートスピーカーの音源再生自体は、何ら問題ないのですが。

 んー、長時間に渡り、環境整えるの難しいので熱暴走かも検証については、涼しくなるまで先送りかな...。

 あ、今日のは、USBケーブルのUSBプラグの接触不良が原因だった模様...これまでのUSB給電の印象も、これによる可能性が高そうです。

 気に入って使っていた長めで白くてフラットな100均USBケーブルの接触を確認したところ、パカパカ...。

[2022/07/29]

 その後、聞き取れないほどの酷い音切れに見舞われ、解決したのですが、これにも起因していたのかも?

ボツな方法
debian:~$ chmod u+x force_target_bt_con.sh
debian:~$ cat force_target_bt_con.sh
#!/bin/sh
 
a=`/bin/echo info MAC_ADDRESS | /bin/bluetoothctl | /bin/grep Connected | /bin/awk -F" " '{print $2}'`
if [ $a = no ];then /bin/echo connect MAC_ADDRESS | /bin/bluetoothctl;fi
/bin/pactl set-card-profile CARD PROFILE
debian:~$ crontab -e
* 19-22 * * * /path/to/force_target_bt_con.sh
debian:~$

 仕方ないので、ちょっと強引ではありますが、幸い入浴時間帯はたいていある程度限られますし...

 こんな風に当該時間帯だけとか、Connected noの場合にBluetooth接続するスクリプトをcronで1分間隔とかで走らせればよいかな...(/binや/usr/binくらいはあるでしょうが、cron実行時点でPATHなど環境変数の設定値が限られるのでそれに応じて、もしくはコマンドはすべてフルパス指定しておくのが無難)。

 本来は、スマホやパソコンに依存することなく、ヘッドレスマシンである自作スマートスピーカーとつなぎたいので。

 実際にそうなりますが、その際、Bluetoothスピーカーの電源を入れたら、システム内蔵スピーカーから自動的にBluetoothスピーカーに切り替え、Bluetoothスピーカーの電源を落としたら、システム内蔵スピーカーに自動的に切り替えてほしいので。

 そのためには、当該Bluetoothスピーカーの電源が入った状態でPulseAudio音量調節GUIパネル(pavucontrol)の出力タブでBluetoothスピーカーをデフォルトに設定しておく必要があるようで、1度設定すれば、その後は、電源ONでBluetoothスピーカーが、電源OFFで内部オーディオがデフォルトになります。(ただし、内部オーディオが複数ある場合は、設定タブで不要なものはオフにしておかないと不要なものに切り替わってしまうことがあるので注意)。

 立て続けに電源入れ直してると、なぜか、たまに失敗することもありますが、その際は、改めてBluetoothスピーカーの電源を入れ直すといけるので良しとしようかと。

 あれ、全然接続されず、killall pulseaudio(pulseaudio -kも可?)、systemctl restart blutoothしないとダメなこともあるっぽい、というか、その方が多いっぽい。

 これcronで実行すると、しかも1分ごとに...プツッ(pulseauidoが切れる・再起動する音)がしますし、なんらかの方法でsystemctl restartをユーザー操作するか、cron自体rootで登録しないと...んーーーー、使えない。

 ん?PulseAudio音量調節GUIパネルの設定タブやCLIでpacmd list-cardsとして表示されるデバイスのprofile:の値が、オフやoffになっていて自動切り替えされないことがある...。

 これは、cron登録のスクリプトでデバイス接続後に/bin/pactl set-card-profile CARD PROFILEすればよさそうかな?

 CARDは、pacmd list-cardsで出力される当該デバイスのid値かname値、または、pactl list short cardsの1項めか2項め、CARD PROFILEは、pacmd list-cards結果の当該デバイスのprofiles:の何れかで自身の場合、今回は、a2dp_sink。

 仮に初回失敗しても、毎分チェックしてあれば、cronのチェックが毎回xx時0分の1分ごとなのでスピーカーの電源ONタイミングに応じて1分以内にスクリプトが実行されるので良さげ。

 もしかして、これがOFFになってるから接続されても即切れるとか、接続されなくなったりするのかな?だとしたら、これで解決か...な?

 あ、いや、DebianやRaspbianを(再)起動した初回は、うまくいかないっぽい...。

 あとBluetoothスピーカーの電源が入っている状態でPCを再起動しても自動接続しないのは仕様なのでしょうかね?

 あ、そっか、PC起動中に接続中の(電源が入ったままの)Bluetoothスピーカーを端末側で手動でOFFした後と同じってことですかね(この状況ですら自動接続してしまうとスピーカー側の電源を落とさない限り、端末側で切断する度に接続されてしまって迷惑ですもんね)。

 untrustしておけば自動接続はされないのでヘッドレスやCLIなら良いですが、GUIだと前述のポップアップが煩わしいかも?

グッドっぽい方法
debian:~$ chmod u+x force_target_bt_con.sh
debian:~$ cat force_target_bt_con.sh
#!/bin/sh
 
a=`echo info AA:BB:CC:DD:EE:FF | bluetoothctl | grep Connected | awk -F" " '{print $2}'` > /dev/null 2>&1 \
&& if [ $a = no ];then echo connect AA:BB:CC:DD:EE:FF | bluetoothctl > /dev/null 2>&1;fi \
&& pacmd list-cards | grep "name: <bluez_card.AA_BB_CC_DD_EE_FF>" > /dev/null 2>&1 \
&& if [ $? = 0 ];then
 pacmd list-cards | grep "active profile: <a2dp_sink>" > /dev/null 2>&1 \
 && if [ $? = 1 ];then
  pactl set-card-profile bluez_card.AA_BB_CC_DD_EE_FF a2dp_sink
 fi
else
 sudo killall pulseaudio \
 && sudo systemctl restart bluetooth.service \
 && echo connect AA:BB:CC:DD:EE:FF | bluetoothctl > /dev/null 2>&1 \
 && pulseaudio --start \
 && pacmd list-cards | grep "name: <bluez_card.AA_BB_CC_DD_EE_FF>" > /dev/null 2>&1 \
 && if [ $? = 0 ];then
  pacmd list-cards | grep "active profile: <a2dp_sink>" > /dev/null 2>&1 \
  && if [ $? = 1 ];then
   pactl set-card-profile bluez_card.AA_BB_CC_DD_EE_FF a2dp_sink
  fi
 fi
fi
debian:~$ crontab -e
* * * * * /path/to/force_target_bt_con.sh
debian:~$

 おっ!これグッドっしょ!!!試行錯誤してやっとできた。

 ペアリングとtrust設定してあることは前提だけど。

 bluetoothctlのinfo MAC_ADDRESS結果のConnected行がnoならconnect、pacmd list-cardsのname:行に当該デバイス名があれば、active profile: <a2dp_sink>行をチェック、なければ、offと判断し、pactl set-card-profileでa2dp_sinkに設定。

 他方、pacmd list-cardsのname:行に当該デバイス名がなければ、pulseaudioのプロセスを全部切断、bluetoothサービスファイルを再起動、当該デバイスにbluetoothctl connect、pulseaudioを開始後、やはり、pacmd list-cardsのname:行、そして<a2dp_sink>行をチェック、name:に当該デバイスがあって<a2dp_sink>行がなければ、offと判断し、pactl set-card-profileでa2dp_sinkに設定。

 やってることは、Bluetoothスピーカーが上手く接続できない場合に手動でやる必要のあったことをスクリプトで自動化しただけです。

 それより、ここでのポイントは、以下の点でしょうか。

  • 適宜、&&でつないで順次処理待ちし、それぞれ実行すること
  • /etc/sudoers.d以下のファイルあたりでcron実行ユーザーにおいてsystemctl、killallのsudoにおいてNOPASSWDで実行する・できるように設定すること
  • 2度書くなんて冗長じゃん!と思えても、そこをグッと堪えてname行及び<a2dp_sink>行チェックと設定をまとめて最後に書かず、それぞれで行なうこと
  • できれば出力を/dev/nullに捨てること

 運用上、スマートスピーカーもBluetoothスピーカーも毎日24時間電源を入れっぱなしにしているわけではない、これらが何れも電源ONでも何もしない場合もあると思われるので毎日毎分実行することにしました。

 これが良いのは、Bluetoothスピーカーの電源オン直後にconnectして即disconnectするという当初あった謎の事象がなくなったこと、スマートスピーカーの電源が入った状態でBluetoothスピーカーの電源をON/OFFした時に内部スピーカーとBluetoothスピーカーを自動切り替えするのはもちろんのこと、Bluetoothスピーカーの電源をONにした状態でスマートスピーカーを再起動した場合、Bluetoothスピーカーで再生してくれる点。

 ヘッドレスの自作スマートスピーカー+Bluetoothスピーカーが本命だけに、そこそも、こういう挙動でないと困りますから良かったです。

 前述のようにBluetoothスピーカーがONの時、端末、ここではスマートスピーカー側でOFFにしてる場合にcronで再接続されるのは迷惑かとも思いましたが、よく考えたら、この運用においては、そういうケースは、まずないので問題ありませんでした。

 また、この方法だと初回起動時にPulseAudio音量調節パネルの出力タブなどでBluetoothスピーカーをデフォルトに設定しておく必要もないかと。

 微妙なのは、状況によって極稀にsystemctl restart bluetoothに異様に時間がかかることがあり、時にcronチェック最小1分間以内に間に合わないこともありそうな点とテスト的に端末でスクリプトを実行するとその後のスピーカー切り替えは上手くいく、普段は普通に通るのに、時になぜかテスト演算子[]あたりで警告が出ること。

 まぁ、運用の煩わしさがなくなったので良しとしますが。

 尚、グループはよくわからなかったのでpulseとbluetoothと名の付くグループには、usermod -aG GROUP USERでユーザーを全て追加しておきました。

 もし、これらグループ追加もしてあり、パスワードなしsudo対処済み、スクリプトに実行権限を与えてあり、端末で実行してもエラーや警告など余計な出力もなく、少なくともcron内のそのままでは最小限のPATHに存在しないパスのコマンドはフルパス指定してあり、crontabで指定の*の数や実行ファイルパス含むファイル名に間違いがないのに上手くいかない場合は、電波障害があるか、距離の問題と思われるので障害のない確実に電波の届く範囲にスピーカーを持っていく、なんなら、そこで電源を入れ直せばつながるはずです。

 まぁ、そうでなくても、ちょっと間を置いて電源入れ直せば、つながるかと。

2022/01/04

 ん?グッドっぽいスクリプトでもうまくいかないケースがありました。

 a2dpをアクティブに設定する際に入出力エラーとなるケースを確認していますが、対処したつもりのスクリプトでもダメっぽい...が、それらコマンドを1つ1つを実行していくといけるという状況に...。

 直後だろうが、翌日だろうが、充電した後(通電したUSBケーブルから抜いた後)に必ずと言っていいほど起きるんですが、なんで?

 また、そうなった場合、手動でelse文のコマンドを順に実行していくとconnectする前にbluetooth.serviceをrestartした時点でBluetoothスピーカーにつながることも。

 というわけで万能策が見つかるのか定かではありませんが、いろいろ試し中...。

2022/01/27

 そもそもスクリプト要らなかったっぽいです...。

 Ubuntu 18.04でデフォルトのオーディオ出力デバイスを設定するにはどうすればよいですか?によれば、PulseAudioの設定で出力先を固定できるとのこと。

 リンク先の話を総合すると/etc/pulse/default.paで[load-module module-switch-on-connect]をコメントアウト、末尾のset-default-sinkに設定する引数をコマンドpactl list short sinksで見つけ、idではなく、name値で設定・編集、更に/home/xxx/.config/pulseをまるごと削除、再起動した後、一度だけGUIかCLIでその対象(今回はスピーカー)をデフォルト設定すればよいとのこと。

 自身は、なんとなく、ホームディレクトリの/home/xxx/.config/pulseの中身を一切削除することなく、そこにあるdefault.paを先の通り、編集してみることにしました。

 何度か試してみる必要はあるものの、今のところ、うまくいっているっぽいです。

2022/01/29

 あれ?これだと、自動接続しなかったり、しても出力先が異なったり、より悪化?何か間違えたかな...、結局、systemctl restart bluetoothする羽目に...。

システムトレイ上のBluetoothアイコン

 今回、CLI操作でできたわけですが、システムトレイ上のBluetoothアイコンからGUI操作を試みるとデバイスの登録と接続は別に行なう必要があるようでした。

デバイス登録用なのか、毎回接続できないエラーとなるDebian上のBluetooth GUIパネル

 システムトレイ上のBluetoothアイコンを左クリック、[新しいデバイスを設定する(S)...]で表示されるポッアップパネルからウィザード形式で進めるGUI操作では、デバイスの追加はできたけど、接続エラーになっちゃった状態でうまくいきませんでした。

 これは、実は、ペアリングとデバイス登録するだけの機能かもと思ってみたり?

デバイス登録後に接続できるDebian上のBluetooth GUIパネル

 一方、デバイスが登録された後、同様にシステムトレイ上のBluetoothアイコンを左クリック、[デバイス(D)...]で表示されるポッアップパネル上にBluetooth機器がリストアップされ、待機状態になっている必要な機器を選択してからメニューの[デバイス(D)...] => [接続(C)]をクリックすると接続に成功しました。

 この時、機器の準備が整っていないと接続できませんが、少し待ってから再度試すと接続できるでしょう。

 ちなみに、この画像では見えませんが、信頼する/しないの星マーク、黃点灯状態が信頼しない、グレー状態が信頼するってわかりにくい...普通逆でしょう...って地域や文化によって違うのかな?

 と思ったら、当該デバイスを選択し、アイコンバー?にある黃点灯の星マークをクリックすると、これがグレーになると同時に当該デバイスアイコン(自身の場合、左下)に黃色の星が付く(逆をやると星が消える)んですね...。

 複数デバイスがある場合、1つのデバイスに対してアイコンバー上の星の色が変わってたら、どれに対してかわからなくなりますもんね...なるほど。

自作ラズパイスマートスピーカー/Raspbian bullseyeでダイソー1000円Bluetoothスピーカーを再生

 本命の自作スマートスピーカーで使っているラズベリーパイ3B+/RaspbianでもDebianと同様にやってみたところ、2点対応が必要でした。

raspbian:~$ sudo apt install -y pulseaudio-module-bluetooth
raspbian:~$ sudo vi /lib/systemd/system/bluetooth.service
...
ExecStart=/usr/libexec/bluetooth/bluetoothd --noplugin=sap
...
(:wq)
raspbian:~$ killall pulseaudio
raspbian:~$ pulseaudio --start
raspbian:~$ sudo systemctl daemon-reload
raspbian:~$ sudo systemctl restart bluetooth.service
raspbian:~$ bluetoothctl
[bluetooth]# devices
[bluetooth]# scan on
Discovery started
...
[NEW] Device AA:11:BB:22:xE:xE DAISO_WS001
...
[bluetooth]# pair AA:11:BB:22:xE:xE
Attempting to pair with AA:11:BB:22:xE:xE
...
Pairing successful
[DAISO_WS001]# connect AA:11:BB:22:xE:xE
Attempting connect to AA:11:BB:22:xE:xE
Connection successful
...
[DAISO_WS001]# quit
raspbian:~$

 1つは、pulseaudio-module-bluetoothパッケージがインストールされていなのでインストール、もう1つは、sapプラグインなるもののエラーで、これを無効にすることでした。

 前者をインストール、/lib/systemd/system/bluetooth.serviceファイル(/etc/systemd/system/bluetooth.serviceの場合もあるかも)で[ExecStart=]の末尾に半角スペースを入れて[--noplugin-sap]を追記。

 それからkillall pulseaudio、pulseaudio --start、sudo systemctl daemon-reload、sudo systemctl restart bluetooth.service。

[参考]

 その後、bluetoothctl、pair、connectすれば、[DAISO_WS001]#プロンプトが表示されました。

 加えて自作スマートスピーカーの方はVNC設定していない中、簡単にGUI操作すべく、ディスプレイのある端末から同じ(仮想)ディスプレイを使えるようにssh -Xでアクセス、ログイン後、そのまま端末上でpavucontrolとしてGUIパネルを起動、出力タブでDAISO_WS001をデフォルトに設定する必要がありましたが。

 と思ったら、再度、ssh -X、pavucontrolしようと思ったら、pulseaudio系のエラーにハマり、結局、tightvncserverをインストールし、VNCアクセスすることになりました。

 が、しかーーーーーーーーし、ここで問題発生、これを使おうと思っていた自作ラズパイスマートスピーカー、ラズパイのBluetooth信号が弱すぎるのか、10cm〜20cmの距離に置いても少し途切れる、もっと離すと常時短時間でブツ切れ状態となり、どんなに素晴らしい楽曲も耳障りな雑音でしかない状態に...。

 内蔵Wi−Fi通信のノートPCを同じ場所に持っていっても、PCは別部屋に置いてBluetoothスピーカーを自作ラズパイスマートスピーカーの近くに持っていくとダメですが、少し離せばバッチリ再生できるのでラズパイのBluetoothチップかドライバ、はたまた冷蔵庫の上というのが、ネックなのか...。

 以前、混雑していたのか、Wi-Fiも少し途切れがちになったことがあり、その時もノートPCの内蔵Wi-Fiでは何事もなかったので、ラズパイのチップかドライバか...。

 仕方ない、入浴時は、パソコンにも入れてある自作スマートスピーカー機能からYouTubeやinternet-radio.com、radiko等々の各チャンネルからの音源をこのBluetoothスピーカーで流すしかなさそうです。

 パソコンを起動させておかなければいけませんが、ほぼ、毎回入浴前後にはパソコンの電源はONなので、自身の場合、特に問題にはなりません。

 と思ったのも束の間、自作スマートスピーカーの設置場所に問題がありそう?

 ラズパイパソコンがあるのは、ノートPCがある自室、自作スマートスピーカーが設置してあるのは、同フロアのダイニングキッチンの冷蔵庫の上。

 試しにパソコン用のラズパイの音源を再生させながら、Bluetoothスピーカーを持って移動してみたところ、電源が入っている冷蔵庫、炊飯器、たぶん電源を入れていれば電子レンジに近づくと雑音やらブツ切れ音やらでうまく再生できませんでしたが、そこを少し離れると正常に再生されるようになりました。

 つまり、そもそもラズパイスマートスピーカーの設置位置がWi-FiやBluetoothの電波の障害になる場所だった可能性が...。

 それでもONUやルーターも自室にある状態で、99%問題なく、スマートスピーカーにおけるWi-Fiを介したストリーミング再生やスマートスピーカーからのESP32による各種自作スマート家電操作もできているんですが、Bluetoothにとっては常に耐え難い場所だったわけですね。

 やはり、ラズパイのWiFiやBluetoothは、少なくとも手持ちのスマホやパソコンと比べると環境に左右されやすいのか、電波が、やや弱いようです。

 となるとベストなのは、自作スマートスピーカーの設置場所を変えることなのでしょうか...。

 というわけで場所を変えて食器棚の上にしてみたところ、小1時間程度は良い感じだったものの、ノイズがかなり入ったり、数秒、無音になったり、無音があまりに続くこともあり、接続が切れたのでしょう、bluetooth.serviceでエラーが出ており、restartする必要があることも...。

 今度はテレビが近くにあるからか...、TVの電源を落としたら、多少マシになったようなと思ったものの、そうでもない...、そう言えば、以前電磁波測った時、スイッチ付き電源のOFFでは、まだ放出量が結構あり、プラグを抜いたら、ほぼなくなったことが...となると電磁波!?

 と思いきや、スピーカーをタップにくっつけても大丈夫なので関係なさそう。

 スピーカーを自室のノートPCやラズパイパソコンのあるデスク周辺に置くとノイズだらけ...。

 そもそも冷蔵庫や炊飯器に近づけてもくっつけてもなんともない...が、そもそも、そこまで電波が届かないことも...。

 基本、1.5m以内程度じゃないとまともに聴取できない...。

 んーーーーーー、Bluetooth...、繊細すぎるぞ...。

 ただ、後述のようにラズパイPCの音源再生では、8mを超えなければ、どこでも再生できることを考えると...自作スマートスピーカーで使っているラズパイのWi-Fi/Bluetoothチップが原因か...。

 ならば、ラズパイPCと自作スマートスピーカーのラズパイを入れ替えてみるか...。

 というわけで入れ替えてみたところ...。

 家電の影響はなさげ、壁があると音源が途切れがち、見通しの良いところで到達距離3〜4mほどとで範囲内では良好と改善されているのでラズパイというかBluetoothチップ個体の問題の可能性大ですかね...。

 他方、入れ替え後も、やはり、デスク周りというか、6口電源タップが3〜4個、それぞれに相応に接続してあるものの、デスク上だと無線が遮断されるようでスピーカーもdisconnectされ、pulseaudio -kやらsystemctl restart bluetooth.serviceやら、スピーカーのconnectやら、やらないとつながらない気が...。

 繰り返しになりますが、そのデスク上のラズパイPCだと距離範囲内ならなんともない、その距離も8m程度までOKというのが、また不思議...。

 となると入れ替え後のラズパイPC+Bluetoothスピーカーの検証をしてみないとダメか...。

 というわけでやってみたところ、安定してるのは5〜6m程度...、何れにせよ、やはり、ラズパイのBluetoothチップみたいですね...。

 それにしてもスマホやノートPCの良好さを考えるとラズパイの電波自体、障害に弱いというか、電波が弱いというか、そういう傾向はありそう...。

 接続できないことや接続後、自動切り替えされないことがある問題もこんなスクリプトをcron登録で解消かと思いきや、PCやラズパイの初回起動時は素直に行かない...と思ったら、改善スクリプトをcron登録で解決したっぽく、距離的、音源再生という意味でも自作ラズパイ/Julius/Open JTalkスマートスピーカーとBluetoothスピーカーで入浴中に音楽に浸るという目的は達成でき、終わりよければ全て良しということで、と思ったら、更にこっちのスクリプトがベターでした

 ここでは、cronの実行時間帯を指定してはいますが、Bluetoothスピーカーの電源が入っていなければ、チェックするのみで何もしないわけですし、そもそもラズパイスマートスピーカー自体電源が入っていない場合は、そのチェックすらしないわけで時間制限しなくても良いかもしれません。

Raspberry Pi 3B+パソコン/Raspbian bullseyeでダイソー1000円Bluetoothスピーカーを再生

 ラズパイパソコンの方も自作スマートスピーカー同様、ラズベリーパイ3B+なので試す気力も失せようかというもの、しかも、こっちは、なぜか、WiFiにつながらなくなることが多いので尚更。

 でも、万が一にもラズパイ自体の設置場所に依存するかもしれないし...とダメ元で試してみたところ、まさにその通りだったようでスマホやパソコンと遜色なく、聴取することができました。

 同一チップ上に実装されているはずのWi-FiにIPが振られない状態ですが、特に問題があるわけじゃないようでBluetooth接続には何ら影響ありませんでした。

 距離的には、8m程度で限界のようです。

 自室からお風呂場までは、8m以上、完全防水ではないのでしませんが、ノートPCやスマホなら浴室内でもいけるものの、ラズパイだと無理。

 が、それでもBluetoothスピーカーWS001を風呂場付近の少し手前の電波が正常なところに置いても、ダイニングキッチンにも聴こえますし、入浴中は、やはり、扉を開けて静かに湯船に浸かっていれば、バッチリ聴こえるのでノートPCだけでなく、ラズパイパソコンの音源も届くことになります。

 とは言え、サブのラズパイパソコンは、あまり起動することはないのでなんですが...。

 前述の通り、自作スマートスピーカーのラズパイと入れ替えたら、こっちでは使わないので良いですが、Bluetoothスピーカーの聴取に支障がでて、本来使いたいスマートスピーカーの方は、安定して聴取できる範囲が広がりました。

 そんなラズパイ入れ替え後のラズパイPCでも、たまに接続できない問題があったわけですが、改良スクリプトをcron登録で解消したっぽいので、めでたしめでたし。

Raspberry Pi 400パソコン/Raspberry Pi OS bullseyeでダイソー1000円Bluetoothスピーカーを再生

2022/10/13

 Raspberry Pi 3B+パソコンでWS001を再生した翌年にあたる今年2月にラズパイ400を購入、3B+から移行してRaspberry Pi 400パソコンをサブというか、メインにしました。

 それから、まただいぶ経ちましたが、ここにきてRaspberry Pi 400でもダイソーのWS001 Bluetoothスピーカーを再生させてみました。

 結果、ラズパイ400においてもパッケージ追加はするまでもなかったものの、自作ラズパイスマートスピーカー/Raspbian bullseyeと同じ段取りで再生できました。

PulseAudioのスピーカー音量調整CLIコマンド pactl set-sink-volume

 PulseAudioにおいてCLIでスピーカーの音量調整をする場合、第1引数にインデックス値(val)またはデバイス名(name)、第2引数にいくつかの方法で音量(volume)を指定したpactl set-sink-volumeを使うことができます。

 インデックス値は、接続数や状況によって変動するので第1引数についてはデバイス名(name)が、第2引数は、百分率(%)指定が簡便で妥当だと思います。

 が、デバイス名(name)は、当該スピーカーが、実際に接続、再生できる状況で(そうじゃないと次のコマンド結果に表示されない)、端末でpacmd list-cardsして得られるbluez_sink.MACアドレスをアンダースコア(_)でつないだもの.a2dp_sinkのようになる(先頭はbluez_cardではない、MACアドレス内はドット接続ではない、末尾にはドット.に続き、プロファイル名_sinkが要る)ので注意。

 どうしても、これを表示できないときは、改良スクリプト&cronのelse文のkillall pulseaudioから順に実行すれば、いけるでしょう。

 ちなみにa2dpは、Advanced Audio Distribution Profileの通称で標準仕様Bluetoothプロファイルの1つ

コスパ高く総評としては良いが...野菜とか物理的障害物に弱い?

 スクリプト&cronで使い勝手も普通になり、コスパ良好で素晴らしいのですが、到達距離ギリギリながら途切れず再生できる場所において、野菜をそばに置くと途端に電波が悪くなるのは、なぜ...。

 他の物を置いても人が立ちふさがっても影響ないのに、なぜ野菜...。

マルチペアリング対応

 あと、Daisoの1000円Bluetoothスピーカー、端末によると書いてはありつつ、マルチペアリング対応とあるものの、ラズパイでもノートでもスマホでも1台つながってると他は、接続エラーに、その1台から解放すると即つながる状態に...。

 自身は、スマートスピーカーからしか使わないので良いですけどね。

 あ、いろんなデバイスが同時につながって同時に音流したら気色悪いか...、いろいろなデバイスでペアリングしておけて他に競合がないか、優先度が高ければ、即つながることこそ、マルチペアリングであって?これでいいのか...な?

Daiso 1100円Bluetoothスピーカーをもう1台買ってステレオ再生してみた

2022/01/25

 今日、ダイソー1100円Bluetoothスピーカー追加購入してステレオ再生させてみました。

 取説に2台電源投入後、一方で再生ボタンを2クリックとあったので何度か、ポン・ポンとやってみましたが、できず、ポポンッとダブルクリック気味にやってみたらいけました。

 YouTube公式のミュージックビデオの1つの音源を再生してみましたが、左右というより、同じ音がダブルの同時再生・連動再生のように思えますが、音源によるのか、それはそれでステレオというのか、オーディオ関連全くのズブの素人なのでわかりませんが。

 でも、当然、1台より迫力はあり、置き場所はもとより、向きを変えるなどして聴取エリアを広げるのにもよいし、1台ずつ別個に使うのもよしで良質な音を探し求めるタイプではない自身にとっては、良い感じです。

突然激しく音切れ発生!hci0ダウンが原因と判明・解決

2022/07/29

 ここ数日、自作ラズパイ3B+スマートスピーカーと併せて使っていて快調だったダイソー1000円Bluetoothスピーカーの音切れが激しく、音源が何かさっぱりわからないほどの症状が、あっさり解決した話。

 スマホやDebian GNU/Linux PCだと正常に機能するのでBluetoothスピーカーではなく、ラズパイに起因するものと断定。

 systemctl status bluetoothしてみると、hci0のupがfailedとか、Failed to set privacy: Rejected (0x0b)とかエラーが出てる。

 sudo systemctl restart bluetoothしてもダメ。

 bluetooth/bluetoothd自体は、active (running)にはなっているものの、statusを見ると

 profilles/audio/avdtp.c:avdtp_connect_cb() connect to MAC_ADDRESS: Host is down (112)とか。

 profilles/audio/avdtp.c:avdtp_parse_rej() START request rejected: Bad State (49)とか。

 sudo hciconfig -aしてみるとDOWNの文字が、sudo hciconfig hci0 downはしてもsudo hciconfig hci0 upするとエラー。

 そんな折り、regression from 0.8 to 0.9 -- BLE connection fails until bluetooth service is restarted #8にたどり着き、chickenburgers氏のおかげで解決。

 それは[systemctl start sys-subsystem-bluetooth-devices-hci0.device; hciconfig hci0 down; systemctl start bluetooth]。

 これを実行するとhciconfig hci0 upも正常に機能し、[UP RUNNING]に。

 [sys-subsystem-bluetooth-devices-hci0.device]なんてものがあったとは。

 何事もなかったかのように音切れもなくなり、快調に戻りましたとさ、ありがたや、ありがたや。

 ん?ただ、その後もsystemctl status bluetoothしてみるとFailed to set privacy: Rejected (0x0b)が赤い字で出てるけど、いいのか?これ...。

 一方、数時間再生していたBluetoothスピーカーが突如、切断された場合は、この方法でもhci0はupできず、マシン再起動を要しますが...。

ウェブ造ホーム前へ次へ