Raspberry Pi bluetoothシリアル通信

raspberry piでbluetooth PANを構築したかったのですが現在のBlueZは大分仕様が変更になっているようでうまく動かすことができませんでした。

今回はRaspberry Pi同士でbluetoothシリアル通信の確認ができたので簡単に纏めておきたいと思います。

環境

Raspberry Pi 3 stretch デスクトップ クライアント
Raspberry Pi zero stretch lite ホスト名 piz0
Raspberry Pi zero(w) stretch lite ホスト名 lite
Raspberry Pi 2 stretch lite ホスト名 dip

BTアダプタ

無印 BT2.0アダプタ
CSR 4.0アダプタ
zero(w)は内蔵BTアダプタ

ペアリング

ペアリングについては詳しく紹介されているサイトがあると思うので簡単に!

デスクトップのpi3からbluetoothアイコンをクリックMake Discoverableを実行
Add Deviceダイアログをだします。
zero(w)にログインしてroot権限でbluetoothctlを実行します。
stretch-liteでもBT接続に必要なパッケージはデフォルトでインストールされています。
zero(w)から以下を実行していきます。
power on
discoverable on
agent on
default-agent

1分位待っているとzero(w)のホスト名liteが表示されます。
liteを選択してPairをクリック、pinコードダイアログが出るのでOK
zero(w)はpinコードを確認してyesを入力してペア完了、exitで終了します。
このときpi3側でもターミナルを起動しておいて同様にbluetoothctlだけを実行しておくと通信の様子がよくわかります。

root@lite:~ # bluetoothctl
[NEW] Controller B8:27:EB:6A:xx:xx lite [default]
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# discoverable on
Changing discoverable on succeeded
[CHG] Controller B8:27:EB:6A:xx:xx Discoverable: yes
[bluetooth]# agent on
Agent registered
[bluetooth]# default-agent
Default agent request successful
[CHG] Device B8:27:EB:24:xx:xx UUIDs: 00001101-0000-1000-8000-00805f9b34fb
------- snip -------
[CHG] Device B8:27:EB:24:xx:xx UUIDs: 00001801-0000-1000-8000-00805f9b34fb
[CHG] Device B8:27:EB:24:xx:xx ServicesResolved: yes
[CHG] Device B8:27:EB:24:xx:xx Paired: yes
[CHG] Device B8:27:EB:24:xx:xx ServicesResolved: no
[CHG] Device B8:27:EB:24:xx:xx Connected: no
[CHG] Controller B8:27:EB:6A:xx:xx Discoverable: no
[bluetooth]# exit
Agent unregistered
[DEL] Controller B8:27:EB:6A:xx:xx lite [default]

同様にzero(w)で2個のUSB-BTアダプタのペアリングをします。

無印 BT2.0アダプタ
同様にペアリングは可能ですがPINコードを双方とも指定して打ち込む必要があります。
よく使われるのは0000とか1234という数字ですね。手早くしないとタイムアウトになってやり直しになってしまいます。

CSR 4.0アダプタ
このアダプタは特にPINコードも出ることもなくペアリングが完了します。
但しzero(w)では抜き差しした時点で固まってしまいます。
zero,pi2.pi3では問題ありません。


zero(w)で3個のBTアダプタがペアリングできました。
pi3のBTマネージャーにはペアリングしたデバイスが表示されていますがここからConnectしても接続できません。
これはbluetoothのプロファイルを利用する何かしらのアプリケーションが待ち受けているときに接続できるものと思います。

シリアル通信

シリアル通信はこちらのページが良く纏まっていますね。 Raspberry Pi と Bluetooth 経由でシリアル通信する

Raspberry Pi 3 stretch(デスクトップ)接続元の設定
今回は3台に接続するということで3台分のrfcommを用意します。
/etc/rc.local

if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi
# rfcomm
rfcomm bind 0 00:1A:7D:DA:xx:xx # zero(piz0)
rfcomm bind 1 B8:27:EB:6A:xx:xx # zero(w)(lite)
rfcomm bind 2 00:15:83:0C:xx:xx # pi2(dip)
exit 0

また表示が乱れるのでModemManagerを停止します。

# systemctl stop ModemManager
# systemctl disable ModemManager

シリアル通信のソフトはいろいろありますがscreenとpicocomをインストールしてみました。

# apt install screen picocom

ここで再起動(reboot)
/devには3個のrfcommができているはずです。

$ ls -la /dev/rfcomm*
crw-rw---- 1 root dialout 216, 0  4月 18 16:36 /dev/rfcomm0
crw-rw---- 1 root dialout 216, 1  4月 18 16:37 /dev/rfcomm1
crw-rw---- 1 root dialout 216, 2  4月 18 16:36 /dev/rfcomm2

シリアル通信接続先の設定

zero(w)で3個のBTアダプタを登録しましたがこのペアリング情報はアダプタ固有の情報になるため内臓のBTアダプタ以外はほかのマシンで流用が可能になります。
設定ファイルは/var/lib/bluetooth/以下に保存されています。

# ls -l /var/lib/bluetooth
drwx------ 4 root root 4096  4月 17 18:38 00:15:83:0C:xx:xx
drwx------ 4 root root 4096  4月 17 22:21 00:1A:7D:DA:xx:xx
drwx------ 4 root root 4096  4月 17 22:43 B8:27:EB:6A:xx:xx

各アダプタのID以下にはpi3のペアリング情報が入っています。

直接カードをマウントしてコピーを取る場合の例は

# mount /dev/sda2 /mnt
# cp -rp /var/lib/bluetooth/00:15:83:0C:xx:xx /mnt/var/lib/bluetooth
# cp -rp /var/lib/bluetooth/00:1A:7D:DA:xx:xx /mnt/var/lib/bluetooth

もう1台も同じくコピーします。
これで3台ともペアリングが完了しました。再ペアリングしない限りUSB-BTアダプタはペアリングなしに自由に使い廻しが可能になります。

sdptool設定
[Service]の3行目に-Cを追加、4行目を新規に追加
/lib/systemd/system/bluetooth.service

[Service]
Type=dbus
BusName=org.bluez
ExecStart=/usr/lib/bluetooth/bluetoothd -C
ExecStartPost=/usr/bin/sdptool add SP

待受起動は/etc/rc.localから
シリアルは1接続のみなのでrfcomm0、速度は115200、ホスト名、ユーザーpiのオートログイン
/etc/rc.local

if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi
rfcomm watch 0 1 agetty rfcomm0 115200 lite -a pi > /dev/null 2>&1
exit 0

ここで再起動(reboot)
zero(w)にログインしてsdptoolを実行、Serial Portが見えてたらOK

# sdptool browse local
Service Name: Serial Port
----
  "RFCOMM" (0x0003)
    Channel: 1

ほかの2台もホスト名を変えて同じ設定をします。

bluetoothシリアル通信をしてみる

pi3ディスクトップから3つのターミナルを起動して実行してみましょう。

$ picocom -b 115200 /dev/rfcomm0
$ screen /dev/rfcomm1 115200
$ picocom -b 115200 /dev/rfcomm2


コマンドを実行すると数秒で接続を開始します。1回目で失敗するときもありますが再度実行すると繋がってくれます。
ジョブコントロールが無効なのはシリアルターミナルの仕様と思います。raspi-configなどバックグランドで動かす必要があるコマンドは実行できません。
rfcomm0〜rfcomm2は/etc/rc.localで設定したデバイスIDが使われます。したがってzero(w)の内蔵BTデバイス以外は差し込んだUSB-BTアダプタによってはホストが入れ替わることがあります。
USB-BTアダプタは必要になったとき差し込んでもシリアル通信は可能です。
pi3のBTマネージャーはホスト名を読み取って自動的に変更してくれます。

さてこのbluetoothによるシリアル通信はどんなときに使えば有効かなと考えると通常のLan環境ではあまり出番がないですね。
ですが今回いろいろとネットワークの設定を含めて変更をするとこのシリアル通信の便利さがわかります。繋がらないネットワークを設定しても取り敢えずシリアル通信でなんとかなります。
但し再起動時正常にOSが起動、BTアダプタを認識、/etc/rc.localまで起動しないとシリアル通信も不可になってしまいます。

別の使い途としてraspbianインストール時の補助にも使えそうです。

ddしたディスクにペアリング情報をコピーbluetooth.service,rc.localを編集しておけばシリアル通信は可能になります。
ネットワークを一切設定していないディスクを作成、起動してみました。
無事シリアル通信は繋がってくれました。dhcpでipを取得できなかったときなどはこれで調査、修復も可能と思います。

またシリアル通信では無いのですがraspbianディスクトップインストール時の際にはbluetoothキーボード、マウスのペアリング情報があれば予め/var/lib/bluetoothをコピーしておけば初期設定からペアリングなしに使用ができます。

Raspberry Pi(stretch)フォント設定 noto font

Raspbian Stretch(2018-03-13)がリリースされていますね。

Raspbianをインストールすると一応日本語もきれいに表示してくれます。

デフォルトのシステムフォントはDroidSansFallbackFull.ttfが使われていてandroid端末用の軽量フォントのようです。

$ fc-match sans
DroidSansFallbackFull.ttf: "Droid Sans Fallback" "Regular"
$ fc-match serif
DroidSansFallbackFull.ttf: "Droid Sans Fallback" "Regular"
$ fc-match monospace
DroidSansFallbackFull.ttf: "Droid Sans Fallback" "Regular"

これは日本語フォントをインストールするとすぐ取って代わられる運命にあるものと思います。

今回は少しフォントを変更してnoto(no tofu)フォントをインストールしてみました。
notoフォントはパッケージからもインストールできます。
fonts-notoは全世界用の巨大なパッケージになります。ここはアジア圏のfonts-noto-cjk (China、Japanese、Korea)をインストールします。

# apt install fonts-noto-cjk

インストールが済むとシステムフォントは変更されます。

$ fc-match sans
NotoSansCJK-Medium.ttc: "Noto Sans CJK JP" "Medium"
$ fc-match serif
NotoSansCJK-Medium.ttc: "Noto Sans CJK JP" "Medium"
$ fc-match monospace
NotoSansCJK-Regular.ttc: "Noto Sans Mono CJK JP" "Regular"

パッケージにはserif(明朝体)が含まれてないですね。
Google Noto FontsのページからNoto Serif CJK JPを検索してダウンロードします。ダウンロードしたファイルは展開すると7ファイル(otf)あります。
ファイルはパッケージからインストールしたディレクトリ/usr/share/fonts/opentype/notoに一緒に置くことにします。

$ unzip NotoSerifCJKjp-hinted.zip
# mv *otf /usr/share/fonts/opentype/noto

展開したファイルのパーミッションは640になっていると思います。644に変更しないと読み取ることができません。

# chmod 644 /usr/share/fonts/opentype/noto/*
-rw-r--r-- 1 root root 18604592  6月 17  2015 NotoSansCJK-Black.ttc
--------- snip ---------
-rw-r--r-- 1 root root 22926508  3月 24 13:38 NotoSerifCJKjp-Black.otf
-rw-r--r-- 1 root root 24694400  3月 24 13:38 NotoSerifCJKjp-Bold.otf
-rw-r--r-- 1 root root 21313820  3月 24 13:38 NotoSerifCJKjp-ExtraLight.otf
-rw-r--r-- 1 root root 23468788  3月 24 13:38 NotoSerifCJKjp-Light.otf
-rw-r--r-- 1 root root 23900156  3月 24 13:39 NotoSerifCJKjp-Medium.otf
-rw-r--r-- 1 root root 23624340  3月 24 13:39 NotoSerifCJKjp-Regular.otf
-rw-r--r-- 1 root root 23888120  3月 24 13:39 NotoSerifCJKjp-SemiBold.otf

パッケージからインストールしたfonts-noto-cjkは設定ファイルもインストールされています。
serifの箇所のNoto Sans CJK JPをNoto Serif CJK JPに変更します。
ほかKR,SC,TCも変更しましょう(計4箇所)
/etc/fonts/conf.avail/70-fonts-noto-cjk.conf

-------
<string>serif</string>
---------
<string>Noto Serif CJK JP</string>

インストールしたフォントを読み込みます。notoのところで時間がかかります(5分位)

# fc-cache -fv

Serifも認識されました。

$ fc-match sans
NotoSansCJK-Medium.ttc: "Noto Sans CJK JP" "Medium"
$ fc-match serif
NotoSerifCJKjp-Medium.otf: "Noto Serif CJK JP" "Medium"
$ fc-match monospace
NotoSansCJK-Regular.ttc: "Noto Sans Mono CJK JP" "Regular"


若干、線が細めのところが気になりますがなかなかきれいで可読性も良さそうです。

但し、当サイトの環境ではこのままシステムデフォルトとして使用することができないんですね。
これまでの経緯からlibreofficeなどで作成した文書はipaフォントを使用しておりnotoフォントをつかって見ると崩れてしまいます。
ipaフォントをインストールするとインストールしただけでシステムフォントはipaにいってしまいます。

いろいろ検討したところやはりシステムデフォルトとしてはipaフォントを、ユーザーデフォルトとしてnotoフォントを設定してみることにしました。

ipaフォントの設定

インストールはipafontとipaexfontそしてricty-diminished

# apt install fonts-ipafont fonts-ipaexfont fonts-ricty-diminished

設定ファイル
以下のファイル(拡張子.conf)を/etc/fonts/conf.availにおきます。
65-fonts-ipa-mincho.conf
65-fonts-ipa-pgothic.conf
65-fonts-monospace.conf
リンク作成

# cd /etc/fonts/conf.d
# ln -s ../conf.avail/65-fonts-ipa-mincho.conf
# ln -s ../conf.avail/65-fonts-ipa-pgothic.conf
# ln -s ../conf.avail/65-fonts-monospace.conf
# fc-match sans
ipagp.ttf: "IPA Pゴシック" "Regular"
# fc-match serif
ipamp.ttf: "IPA P明朝" "Regular"
# fc-match monospace
RictyDiminished-Regular.ttf: "Ricty Diminished" "Regular


IPAのプロポーシャナルフォントはnotoフォントと比べると字幅も少ないせいかこぢんまりまとまってこれもなかなかいい感じですね。

ユーザー設定

ユーザーの~/.config/以下にディレクトリfontconfigを作成、新たにfonts.confを作成
monospaceにはRicty Diminishedを設定しています。
fonts.conf

$ fc-match sans
NotoSansCJK-Medium.ttc: "Noto Sans CJK JP" "Medium"
$ fc-match serif
NotoSerifCJKjp-Medium.otf: "Noto Serif CJK JP" "Medium"
$ fc-match monospace
RictyDiminished-Regular.ttf: "Ricty Diminished" "Regular"


Ricty Diminishedのターミナルからシステムデフォルトとユーザーpiの設定を確認

各ユーザーの設定はfonts.confで変更が可能になります。
インストールされているフォント名はfc-listで確認できます。


デフォルトフォントはメニューなどすべてに影響があります。
デフォルトフォント設定後は基本sans,serif,monospaceに割り当てて用途、好みに応じて変更していけば設定も楽になるものと思います。

Raspberry Pi ZERO(stretch-lite)で作るRadiko Player(運用)

前回ではwebサーバーの設定まで済みました。引き続きwebサーバーのチェックをしながら進めていきたいと思います。

当サイトの環境はディスクトップにRaspberry Pi3そしてZERO(radiko)はmoode audioのpulseサーバーから再生した音を出すものとします。
ZEROのhostnameはpiz0、IPアドレスは192.168.0.115に設定してあるのでPi3の/etc/hostsに登録しておきます。

192.168.0.115   piz0

pi3からzeroにブラウザからアクセス

http://piz0/


webサーバーは正常に起動しています。

chromiumブラウザではホスト名だけでアクセスできます。名前解決できない時はIPアドレスでアクセスしましょう。

次に/var/www/htmlにphpinfo.phpを作成してアクセスしてみます。

<?php
  phpinfo();
?>

http://piz0/phpinfo.php

php7.0-fpmもOK

次はSkyBlue CSSを導入します。zeroにsshログインしてダウンロードはホームディレクトリでいいでしょう。

$ wget https://github.com/Stanko/skyblue/archive/gh-pages.zip
$ unzip gh-pages.zip
drwxr-xr-x 6 pi   pi     4096  4月  8  2015 skyblue-gh-pages
$ sudo mv skyblue-gh-pages/* /var/www/html

再度ブラウザからアクセスしてみます。
http://piz0/

今見えているページはダウンロードしたindex.htmlになります。このページにあることがskyblue cssにできることの全てです。試しにindex.html23行目bg-darkの部分をbg-errorに変更するとタイトル背景は赤に変わります。使えるボタンや色は限られていますが軽量、且つ比較的簡単に扱えることが特徴です。AboutにあるようにBootstrapなどを使えばもっと凝ったUIを構築することも可能です。(当サイトは才能がないのでやめておきます)

以上まで正常に確認できればベースとなる部分は終了なのでindex.html,index.nginx-debian.html,phpinfo.phpは適当なディレクトリを作成して退避させておきます。

ラヂオのベースとなるindex.phpを作成していきますが整理しやすいようにスクリプト関係を/var/www/html/bin以下に置くようにしました。またこのディレクトリには再生中の放送局を書き出したファイル(broad.txt)が保存されます。

# mkdir /var/www/html/bin
# chown www-data:www-data /var/www/html/bin

radikoスクリプトも/var/www/html/bin以下においておきます。
/var/www/html/bin/killall.shの作成

#!/bin/sh
killall mplayer > /dev/null 2>&1
killall ffplay > /dev/null 2>&1
killall mpv > /dev/null 2>&1 #必要に応じて
作成したら
# chmod 755 killall.sh

index.phpの作成


sampleは/var/www/htmlにindex.phpのファイル名で置きます。
radikoは聴取制限があるので地域に合わせってリストを作成して下さい。
らじるやCSRA.fmなどは下記のページにまとまっています。
らじる★らじるを録音するWSHです

index.phpは主に前半がphp実行部、後半がhtml部分になっています。
html部でボタンを作成、idを適当に割当て(任意)php部分のcase文で適用します。

編集をする際はphpの記述を間違うと画面は真っ白になるため常にバックアップを取りながら実行していきます。

ボリュームコントロール

デフォルトのボリューム値は環境に合わせて変更します。カードが複数存在する時は下記のようになります。

case "def":
    exec("pactl -- set-sink-volume 0 25% > /dev/null 2>&1");
    exec("pactl -- set-sink-volume 1 25% > /dev/null 2>&1");
break;

ボリューム値の取得(Volume Control)

$ pactl list sinks | grep VolumVolume: front-left: 16384 /  25% / -36.12 dB,   front-right: 16384 /  25% / -36.12 dB
Base Volume: 65536 / 100% / 0.00 dB

上記のコマンドから25%の値を拾っています。
当サイトのカードでは以上の値を出力しますがボリューム値をうまく取得できない時は以下を試して下さい。

<!-- Volume Control -->
    }
    $vol = explode(' ',$vol,10); // スペースごとに10ブロック取得
//print_r($vol); // コメントを外す
    $vol = $vol[5]; // 5番目の値を取得
    $vol = substr($vol,0,3);
    $vol = str_replace('%', '', $vol);
    // VR Limit ボリュームリミット
    if ($vol >= 50) {
        exec("pactl -- set-sink-volume 0 25% > /dev/null 2>&1");
    }


print_r($vol);コメントを外して再読込すると画像のように表示します。
最終的に数値のみ取り出しています。

VR Limitは50以上になったらデフォルト値を設定しています。
表示は一旦50以上を示しますが値はデフォルト値にセットされています。再読込時に正しい値が表示されます。こちらも適当に変更します。

ラジオサイトの表示
選択したラジオサイトは/var/www/html/bin以下のbroad.txtに保存されます。このファイルは勝手に作成されますがbinのパーミッションはwww-dataになっている必要があります。phpのビルトインサーバーを実行しているとroot所有になっている場合があります。この場合は削除してあげます。
アクセス時はこのファイルを読み込むため他の端末からアクセスしても現在実行中のサイトを表示します。

/var/www/html/
drwxr-xr-x 2 www-data www-data 4096  3月 11 21:24 bin/
/var/www/html/bin/
-rw-r--r-- 1 www-data www-data    8  3月 17 12:15 broad.txt

ウインドウを複数開いている時は同期をしていないため即時反映されません。ラジオサイトの隣のZERO文字をクリックすることにより再読込します。
またブラウザのリロードを設定しています。300s(5分)をしてしていますが適当に!

<!-- Refresh -->
<meta http-equiv="Refresh" content="300;URL=./index.php?id=top>"

背景の変更(適当に!)

<!-- bg color -->
    <style type="text/css">
    <!--
    <body{
        background-color:#333333;
        color:#ffffff;
        }
    -->
    </style>

Radiko Mini


surf2を利用して340×100サイズで起動するRadiko Miniタイプを作成してみました。
radiko_s.php

radiko_s.phpも/var/www/htmlにおいておきます。呼ぶ時はradiko_s.phpを指定するだけです。
別ファイルになりますがindex.phpから余計なものを取り除いてラジオサイトも厳選しています。選局もスクロールバーでこのサイズのまま簡単にできます。
通常はMiniで起動しておいて引き伸ばしてグリーンのZEROボタンで通常版を同じウインドウ内で簡単に呼ぶことができます。同じサーバー内なのでどちらのウインドウから操作してもOK

クライアントは基本pavucontrolは起動しておきます。起動しておくことによってpulseサーバーは勝手にkillすることはしません。
pulse audioをkillするとRadikoも音は出なくなりますがRadikoは自動で停止しないので必ずstopする必要があります。/var/tmpにはゴミファイルが残ってRadikoは起動できなくなることがあるので/var/tmp以下のファイルを一切削除してやります。

当サイトのmoode4.0は以前の手法でwww-dataにログインシェルを与えてwww-dataでpulseをスタート、キルしています。但し4.0からは/var/wwwは読み込み専用のsquashfsが採用されているので別の場所にwebサーバーを立てなければいけません。こちらはまた別の機会に!

では快適なラジオライフを!!

Raspberry Pi ZERO(stretch-lite)で作るRadiko Player(準備)

radikoの再生が1分位で停止してしまうという現象はmoode3.1の頃からあったのですがmoode4.0になっていよいよ解消できなくなってしまいました。(rtmpdump廻りでエラー)以前はrootでradikoスクリプトを実行すると以降正常だったのですが!

ファイルサーバー(zero)はだいぶ遊んでいて余裕もあるのでRadiko Playerに仕立ててみたいと思います。zeroには音源カードも搭載していないので音声はpulse serverのmoode audioに飛ばすことにします。
ブラウザは前回導入したsurf2を使っていますが基本レイアウトはこれまでと変わりなくcssを解釈できるブラウザであれば何でもOKですね。

画像はchromium-browserとsurf2(340×480)で見た場合の例です。
自分で作る自分だけのラヂオなのでデザイン、構成を含めて自由に構築できるものと思います。

今回はraspberry pi zero(stretch-lite)外付け音源カードなし、pulseサーバーはmoode audioを対象にしていますが音源カードがあってpulse server & clientとして実行する場合も基本の考え方は同じと思います。(MoOde 4.0(Beta12) Pulse Audioを設定する

インストール
まずはradiko関連をインストール、stretchからはffmpegが使えますね。

# apt install mplayer swftools libxml2-utils rtmpdump ffmpeg

radikoスクリプトはいろいろなサイトで紹介されていると思います。

pulseaudio設定
ディスクトップ版(stretch)ではpulseaudio関連のパッケージはインストール済です。
lite版でもpulseクライアントとしてのライブラリはデフォルトでインストールされています。
~/.config/pulse/client.confを作成

autospawn = no
daemon-binary = /bin/true
default-server = 192.168.xxx.xxx サーバーのアドレス

またコマンドラインから音量コントロールを有効にするためpulseaudio-utilsをインストール(lite)

# apt install pulseaudio-utils
使い方
% pactl -- set-sink-volume 0 22%
% pactl -- set-sink-volume 0 +6dB

コマンドラインから実行する

moode audioのpulseサーバーをスタートしてPi3からzeroにログインradikoスクリプトを実行します。
radikoスクリプト(radiko.sh)のあるディレクトリで

$./radiko.sh -p FMT


PI3はpavucontrolを起動しておいてpulseサーバーの出力装置や音量は適正値にセットされていることを確認してから実行します。

再生タブではmplayerから実行しているのを確認できます。

再生プレーヤーの選択

らじるは配信形式が変更になって現在はm3u8になっていますがmplayerでこのm3u8を再生すると定期的に音が途切れてしまいます。
aptでffmpegをインストールするともれなくffplayが使えるようになります。
X環境のないstretch-liteではオプションに-nodispを指定して実行

$ ffplay -nodisp "https://nhkradiohkfm-i.akamaihd.net/hls/live/512076/1-fm/1-fm-01.m3u8"

ffplayでは動作も軽くかなり安定して再生できます。

もう一つの選択肢としてmpvがあります。確かmplayerの新規開発は終了してmpvに引き継がれていると思います。jessieの頃のPiではかなり重く感じたのですが現在はだいぶ向上しているようです。但しffplayと比べると再生開始が若干遅れてしまいます。

# apt install mpv


mpvで再生すると一部の海外ラジオサイトでは曲情報を取得してくれます。
インストール時は依存でyoutube-dlがインストールされますがバージョンが古くまた更新されることもないため入れ直したほうがいいでしょう。 youtube-dl Download Page

更新は約7日〜10日位で行われているようです。スクリプトに書いてcronから実行するのがいいと思います。

# apt remove youtube-dl
to install
$ sudo curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl
$ sudo chmod a+rx /usr/local/bin/youtube-dl

radikoスクリプトも変更が可能です。
デフォルトはmplayerになっていると思いますが再生可能なプレーヤーを書いといてコメントを入れ替えることで試すことができます。

# Play
play() {
------- snip ------
        mplayer -
#       mpv -
#       ffplay -nodisp -
}

中にはプロトコルによってffplayで再生できないものがmplayerでは再生可能などいろいろあるようです。またクリップ気味のサイトなどもプレーヤーを変更することによって軽減されることもあります。

webサーバーのインストール

webサーバーにはnginxを使いました。

# apt install nginx php7.0-fpm

/etc/nginx/sites-available/defaultの編集

44行目index.php追加
    # Add index.php to the list if you are using PHP
    index index.php index.html index.htm index.nginx-debian.html;

54行目からアンコメント4箇所
    # pass PHP scripts to FastCGI server
    #
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
    #
    #   # With php-fpm (or other unix sockets):
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
    #   # With php-cgi (or other tcp sockets):
    #   fastcgi_pass 127.0.0.1:9000;
    }

シンボリックリンクの作成

# cd /etc/nginx/sites-enabled
# ln -s /etc/nginx/sites-available/default

nginx php7.0-fpm再起動

# systemctl restart nginx php7.0-fpm

www-dataをaudioグループに追加

# gpasswd -a www-data audio

www-dataがpulseaudioにアクセスできるように

# cd /var/www
# mkdir -p .config/pulse
# cp /home/pi/.config/pulse/client.conf .config/pulse
# chown -R www-data:www-data .config

ローカル環境だけなのでphpのビルトインウェブサーバーも使うこともできます。
実行は簡単でターミナルからroot権限で以下を実行するだけ

# php -S 0.0.0.0:80 -t /var/www/html

メリットはphpの記述に問題があればメッセージで教えてくれます。テスト目的にもいいと思います。
rc.localから起動してやればこのまま実用になりそうです。
stretch-liteのzeroは問題なくpulseaudioに接続、音が出るのですがstretchのPi3はpulseaudioで接続拒否されてしまいます。どうも接続先が自身の127.0.0.1に向いているようです。
これはLXDEの仕様かなと思っています。nginxではzero同様問題なく動作します。

zeroはせっかくインストールしたのでやはりここは扱いやすいnginxで運用することとします。

下準備はほぼできたので続きはまた次回で!

Raspberry Pi xdotoolで快適なディスクトップ環境

xdotoolはX上のウインドウやキーボード、マウスをコマンドラインから操作可能なツールです。

Piをディスクトップ環境で利用していると電源投入後起動するアプリケーションとその配置は大体決まってくると思います。LXDE+openboxは以前と比べるとうまく配置してくれますがまぁ必ず並べ替えが必要になってきますね。今回はその並べ替えをxdotoolにお願いしたいと思います。

スクリプトの作り込みによってはウインドウではなくベースのディスクトップ自体が動いてしまうことがあります。再起動または後述する方法で復帰することができます。
一応バックアップを取っておきます。バックアップはcp -r ~/.config ~/.config.bakでいいと思います。
LXDEは基本終了時に現在の状態を保存します。バックアップを復元するにはCLIで起動、バックアップファイルを上書き、置き換えしてやります。

インストール

# apt install xdotool

ウインドウを操作するにはウインドウIDを取得する必要があります。search –nameで取得できたIDでもほとんどが動いてくれません(試した中ではmltermだけOK)manを見ても多くのコマンド(オプション)があってよくわかりません。
ネット情報を見るとgetwindowfocusを使うと良さそうです。
参考にしたサイト xdotoolを使ってコマンドラインからウィンドウを操作する

基本の操作

ウインドウIDの取得

$ xdotool selectwindow
18874828
$ xdotool getwindowfocus
23068676
$ sleep 3 && xdotool getwindowfocus
23068676

xdotool selectwindowを実行するとカーソルがアイマークに変わります。目的のウインドウをクリックして取得します。テストには便利そうです。
テストではターミナル自身のIDを取得していますがsleepを入れて目的のウインドウをクリックすることによりgetwindowfocusでIDを取得できます。
selectwindowとgetwindowfocusでは取得したIDは異なりますがどちらも動かすことができます。

今回の目的は電源投入、OS起動後アプリケーションを起動、並べ替えをするのですがウインドウIDを取得するタイミングをうまく計る必要があります。短くても失敗するし無駄に長いと有り難みが無くなってしまいます。(電源投入後初回起動時の時間が基準)
アプリケーション起動中はいろんなウインドウIDが存在するようです。ウインドウを操作できるIDは起動の最終あたりに取得できるのでアプリケーションごとに適切なsleepを設定します。
設定中には失敗してディスクトップ自体のIDを取得してしまい背景があらぬ方向に移動してしまうこともあります。
その際は再起動または上記の方法でディスクトップ自体のIDを取得(なにもないところでクリック)
$ xdotool windowmove 取得したID 0 0
で戻すことができます。

設定 運用してみる

当サイトの設定例です。
ディスプレイ 1024×768
pcmanfm,lxterminal,mltermを起動並べ替えをしています。
terminalはgeometryでも指定できるのですがここはxdotoolで統一します。
当サイトのopenboxはmoves overでフォーカスを当てているので最初にカーソルを左隅に移動しています。動作はアプリケーションを起動、sleepを入れてウインドウIDを取得、ウインドウサイズを指定、移動位置を指定、順次繰り返します。
アプリケーション起動後のsleepがポイントでしょうか。(ほか必要に応じて)
osのsleepも使えますがxdotool sleepは小数点以下も指定できるようです。
~/bin/pcmanfm.sh

#!/bin/sh
xdotool mousemove 0 0
mlterm &
    xdotool sleep 1
    ID=`xdotool getwindowfocus`
    xdotool sleep 1
    xdotool windowmove $ID 505 420
lxterminal &
    xdotool sleep 1
    ID=`xdotool getwindowfocus`
    xdotool sleep 1
    xdotool windowmove $ID  20 420
pcmanfm &
    xdotool sleep 3
    ID=`xdotool getwindowfocus`
    xdotool sleep 1
    xdotool windowsize $ID 515 365
    xdotool windowmove $ID 505 31
    cd ~/

次は2つのターミナルを起動して1つはサーバーにアクセス、もう1つは自マシンで使用します。
ローカルにおいてあるサーバーはtmuxが起動していて作業を再開できるようになっています。
xdotoolのキー入力を利用してsshでログイン、最初のログ確認コマンドを実行しています。
スクリプトファイルにはpasswordが平文で記載しているのでパーミッション(700 動作確認後は500にしています)そして扱いには慎重に、かつ自己判断で実行します。
(サーバーへのアクセスはログイン程度にとどめてそこからはサーバー側で処理するのがいいと思います)
~/bin/server.sh

#!/bin/sh
xdotool mousemove 0 0
mlterm &
    xdotool sleep 1
    ID=`xdotool getwindowfocus`
    xdotool sleep 1
    xdotool windowsize $ID 490 660
    xdotool windowmove $ID 515  60
lxterminal &
    xdotool sleep 1
    ID=`xdotool getwindowfocus`
    xdotool sleep 1
    xdotool windowmove $ID  30 400
xdotool sleep 2

# server pi2
xdotool mousemove 600 100
xdotool click 1
xdotool sleep 1
xdotool type --delay 100 'ssh hogehoge'
xdotool sleep 0.4
xdotool key Return
xdotool sleep 3
xdotool type --delay 100 'password'
xdotool sleep 0.4
xdotool key Return
xdotool sleep 0.4
xdotool type 'tmux a'
xdotool sleep 0.4
xdotool key Return
xdotool sleep 0.4
xdotool type --delay 100 'cd /var/log'
xdotool sleep 0.4
xdotool key Return
xdotool sleep 0.4
xdotool type --delay 100 'tail fail2ban.log'
xdotool sleep 0.4
xdotool key Return
xdotool key Return
xdotool sleep 2
# pi3
xdotool mousemove 200 500
xdotool sleep 1
xdotool click 1
xdotool type --delay 100 'df'
xdotool sleep 0.4
xdotool key Return
xdotool key Return

次に上記のスクリプトをワークスペースを切り替えながら実行して更にほかに起動したいアプリケーションを登録、実行します。
当サイトではメールクライアントとchromium-browserを登録しています。
set_desktop (0-5)はwork space (1-6)に対応します。
work space6で実行後は先に実行したwork space5と3を5秒づつ確認 work space1に移動してchromium-browserの起動を待ちます。(約5秒後に起動開始)
~/bin/work.sh

#!/bin/sh
xdotool mousemove 0 0
xdotool sleep 1
xdotool set_desktop 2
    /home/pi/bin/pcman.sh
xdotool sleep 3

xdotool set_desktop 4
    /home/pi/bin/server.sh
xdotool sleep 3

xdotool set_desktop 5
   sylpheed &
   xdotool sleep 5
   chromium-browser &
   xdotool sleep 5

xdotool set_desktop 4
xdotool sleep 5
xdotool set_desktop 2
xdotool sleep 5
xdotool set_desktop 0


上記のwork.shはOS起動後1回だけの実行なので誤操作避けるためzenityのquestionダイアログで確認を取ります。

~/bin/desktop.sh

#!/bin/sh
ACTION=$(zenity --question --default-cancel --title "DeskTop" --text "Run DeskTop Programs 実行しますか?");
if [ "$?" = "0" ]; then
    /home/pi/bin/work.sh
else
    echo "cancel"
fi


zenity実行スクリプトはメニューに登録してディスクトップに貼り付けました。
各スクリプトは実行権限が必要です。
実行中はマウスを動かさないようにただ見てるだけです。
sleep時間やウインドウサイズなどは各環境によって違うので参考までに!
まだそれほど使い込んではいませんが今のところ順調に仕事をしてくれます。

ボタン一発で初期起動アプリケーションの実行を代行してくれるのでキーボード操作が下手糞な当サイトにとっては実に快適です。


前回はsurf2で小さい画面を使いましたがaptからインストールしたsurfもxdotoolでサイズを自由に設定できます。逆にsurf2も引き伸ばすこともできますね。

違いはテキストエリアのフォントサイズが少々違うこと、ここから新しいウインドウ開いた際の初期画面はそれぞれのデフォルトの大きさになります。
見え方はサイトによって違ってきます。

Top