Raspberry PiとVolumioを使ってNFC対応ジュークボックスを作る
オシャレだと思ったので作った。
何番煎じかわからんけど、やってる人がいるはずの割に、ハードルの低い具体的な解説がなかったのと、STAY HOMEの連休中に暇を潰す良い機会だったのでやってみた。
<オーディオ環境を作る>
■最初に用意したもの■
・Rasberry Pi 4 Model B(4GB)
・JustBoom DAC HAT
・オーディオ用RCAケーブル
・microSD(32GB)
・USB-C対応ケーブルと電源アダプタ
ラズパイは欲張って4GBモデル買っちゃったけど用途的に2GBでも良かったと思う。まぁ飽きたら他の遊び方するつもりやし。
サウンドカードにJustBoomを選んだのはRSコンポーネンツだとそこまで高くなかったのと、即日出荷対応していたから。音にこだわりたい人はもっと上等なやつ選んでもいいと思うよ。
https://jp.rs-online.com/web/p/signal-conversion-development-kits/1228179/
RCAケーブルはDACとアンプを接続するだけ。よくある赤白黄3色ケーブルの2本だけ使っても代用できる。音にこだわりたい人は(ry
miscroSDはラズパイ推奨のメーカーとかあるらしいけど、最近キオクシアに社名変更した東芝の32GB。これも保存媒体で音が変わるとかほざ…仰ってる人おるけどホンマか?(耳ほじ)
Raspberry Pi 4の電源はUSB-Cのポートから供給される。5V2.4Aでも一応動くけど、5V3A推奨らしい。ラズパイ本体に電源スイッチはないから、こういうケーブルがあると便利だよ。
・最初にやること
1.Raspberry Pi公式からRaspberry Pi Imagerを入手
2.Volumio公式からラズパイ用OSイメージを入手
3.microSDにOSイメージを書き込み
ラズパイのOS書き込みの解説はググればそこら中にあるので、それ見てやればできると思う。やれ。
モノが揃ったらRaspberry PiにサウンドカードとmicroSDを差し込んで完成。サウンドカードはGPIO端子にぶっ刺すだけ。microSDは基盤の裏面。
初回起動時にWi-Fi用のホットスポットが立ち上がるので、"volumio2"で接続するとブラウザで初期設定画面が開く。
今回はサウンドカードを装着したので対応したやつを選択。JustBoomは公式でどれを選べばいいか紹介してくれている。
ついでにWi-Fiの設定もNetworkの項目からできるので必要ならその辺もしておく。設定が完了すればラズパイを再起動。
細かい話は省くけどmDNSという機能のおかげで再起動後はブラウザから http://volumio.local/ にアクセスすると、操作画面が表示される。
Wi-Fi端末がない人は有線でやろう。
のはずなんだけど諸事情で初期化したらmDNSが上手く機能しなくなったので、そういう場合はIPアドレス直打ちで対応。
USBキーボードとマイクロHDMIがあればラズパイに差し込んで操作できる。ディスプレイポートは0番、ユーザーとパス共に"volumio"でログイン可。
コンソールで"ifconfig"と打ち込んでエンターを押せばネットワーク状態を表示できるので、出てきたIPアドレス(赤線部)をブラウザのアドレス欄に打ち込めばいい。「volumio.local」が使えない人は代わりにIPアドレス直打ちで対応しよう。
ネットワーク経由でコンソール操作できたほうが後々便利なので、まずはSSHを有効にしておく。
http://volumio.local/dev/ にアクセスしてSSHの「ENABLE」を一回押すだけ。見た目何か起きるわけじゃないけどこれでSSHが有効になる。画像のアドレスはmDNSの件があるから気にしないで。
SSHを使う場合はターミナルソフトを使って「volumio@volumio.local」にアクセス、パスワードは"volumio"で接続できる。
ここでSSHの説明まですると長くなるので、他で解説しているサイトを見てもらったほうが早い。できると後々便利なので勉強しておいて損はないよ。
■音楽の再生■
音を出すだけならメニュー画面のウェブラジオから適当な放送局選べばテストできる。
手持ちのオーディオファイルを再生したい場合は、データを入れたUSBメモリを差し込む、ネットワークドライブ(NAS)経由、内部ストレージに直接放り込むの3つ。
とりあえずモノがなくてもできる内部ストレージに放り込む方法。
Windowsの場合はエクスプローラーのアドレス欄に「\\volumio.local」といれるだけでアクセスできる。ユーザ名とパスワードはどちらも"volumio"でOK。
「Internal Strage」にオーディオファイルを放り込めばいいんだけど、後で他のデータも入れたいので「music」フォルダを作ってそっちに入れた。
LinuxはSambaというソフトウェアを使って他OSと互換性のあるファイル共有をしているので、WindowsからLinuxのファイル操作するときは大体Sambaって覚えておこう。
放り込んだらVolumioのメニューから「設定」→「Souces」を開くとマイミュージックのところの数字が増えているはずなので、一応「再スキャン」でデータベースを生成。
これで音楽ライブラリ他メニューから音楽を再生できるようになる。
ちなみにSoucesの中からメニューの表示項目を選ぶことができるので、不要なやつはここからオフにしておくとスッキリする。
<ディスプレイの追加>
次の日にタッチスクリーンとヒートシンクが届いたのでこれを追加する。
ヒートシンクを取り付けた場所は、熱を持ちやすいCPU、メモリ、USB制御チップ、有線LAN制御チップとWi-Fiアンテナの5個所。Wi-Fiは特に電波干渉の心配はなかった。裏のシール剥がしてペタるだけ。
ディスプレイはカナダ企業の7インチタッチパネル。選定理由はDSIポートから直接電力供給できる(配線が一つで済む)点と値段、公式より安い。
あと丁寧な取り付け手順書もある。
付属のスペーサーは両端ともメス。基盤を複数追加するのが難しいので、これは前に余らしてた公式ディスプレイのスペーサーに置き換えた。
ラズパイの取付穴はM2.6規格なので多分ホムセンとかでも売ってる。
FFCケーブルは公式ディスプレイと違って同一面に端子がついてる。一応、電圧は同じ60Vなんだけど試しに繋げてみたら動かなかった。基盤壊す可能性あるからみんなはやっちゃダメだぞ。
うっかりラズパイ側DSIポートのツメが折ってしまったけど、電気的な部分には影響がないので無問題。これで取り付けは完了。
とりあえず配線しても普通にコンソール画面が表示されるだけなので、次はブラウザと同じGUIを使えるようにする。
別の端末を使ってVolumioのメニューから「プラグイン」→「Miscellanea」に「Toch Display Plugin」があるのでこれをインストール。結構時間がかかる。
完了後「Enable」を押すと繋げたディスプレイにVolumioの操作画面が表示される。まぁChromiumでフルスクリーン表示してるだけっぽいけど。
「インストール済みのプラグイン」からディスプレイの動作設定もできるので、自動で画面オフとかいらない人はここから設定しよう。
ただ、非公式のためかプラグイン設定の「Rotate Screen Content」は上手く動作しなかった。(micrSDカード内のconfig.txtを直接書き換えることで対応可能)
あとディスプレイ表示のプラグインはそのままだと文字化けが起こる。
対応したフォントを入れると直るが、操作はコンソールから行うのでプラグインを一度オフにするか、SSHで接続しないといけない。
sudo apt-get update
apt-get install -y fonts-ipafont
ついでにロケール(地域設定)も日本語にしておく
sudo apt-get install -y locales
sudo dpkg-reconfigure loceles
キーボードの↑↓で項目を移動して「ja_JP.UTF-8」と別になくていいと思うけど「ja_JP.EUC-JP」でスペースを押してチェックを入れておく。
TABキーでカーソルが移るのでOKのところで「Enter」を押すと言語設定がされる。
これ、本来はプラグイン入れる前にやったほうがいいんだけど、あえて後でやったほうが理解が深まると思うんだ。
あとフォントとロケール設定したのに文字化けする現象があった。
これはオーディオファイルにあるタグ内の文字コードが原因だったのでmp3の場合v2.3、UTF-16に置き換えると正常に表示された。WMPで取り込むと上手くいかんらしい。
液晶が梱包されていた段ボールがディスプレイスタンドとして優秀だった。
オーディオ用タブレットとしてはここでひとまず完成。
ここからはカードリーダーとNFCタグを使ってアルバム情報を呼び出す機能を追加する。プログラミングが必要になるので、やりたい人だけやってね。
<カードリーダーの追加>
今回の主目的。ハイレゾ環境はオマケ。
やりたいことはNFCから情報を読み取って対応したアルバムを流す。
こんなの部屋にあったら絶対モテるでしょ。
用意したのはSONYのRC-S380。USBで差し込むだけ、簡単。
「業務用途専用」って書いてあるけど普通に買えちゃったので仕方ない。自分は給付金絡みで価格高騰する直前に買えたけど、今買うとさすがにアホ臭いので他で探そう
あとサンワサプライのNFCタグ。これに情報を書き込んでアルバムケースに仕込む。
Linux + Python環境でNFCを扱う方法はネットで情報が色々あるので、それでいこうと思う。
PythonでNFCを扱うにはnfcpyのライブラリを追加する。
けどそのためのpipコマンドが入っていないので、最初にpipをインストールしてからnfcpyを入れる。
sudo apt-get update
sudo apt-get install -y python-pip
sudo pip install nfcpy
カードリーダーを繋げて動作テスト。ちゃんと認識されていたらデバイスが表示される。
sudo python -m nfc
ここからがコードの記入。Volumioの操作はAPIからも操作できるのでこれを活用する。
コマンドラインでは細かい操作ができないらしいので、WebSocketかREST APIを使った方法になる。
WebSocketを使うならJavaScript環境みたいな偏見を持ってるので、PythonからWebAPIであるREST APIを使う方向でいきたい。
ライブラリの os や subprocess でコマンドラインを呼び出すか、urllib や requests とかで直接叩く方法になると思う。
全部コード内で処理させたほうがスマートな気はするけど、別に好みでいいんじゃない。知らんけど。
そして一応出来上がったタグに情報を書き込むやつ。
nfc_write.py
#!/bin/bash python
import nfc
import ndef
import requests
clf = nfc.ContactlessFrontend('usb')
print(clf)
if clf:
Tag_nfc = clf.connect(rdwr={'on-connect': lambda Tag_nfc: False})
Volumio_apiurl = "http://127.0.0.1:3000/api/v1/"
Json_Uri = requests.get(Volumio_apiurl + "getState").json()['uri']
Json_Album = requests.get(Volumio_apiurl + "getState").json()['album']
Uri = Json_Uri[0:Json_Uri.rfind("/")+1].replace("music-library","mnt")
print(Tag_nfc)
Nfc_records = [ndef.SmartposterRecord(Uri, Json_Album)]
Tag_nfc.ndef.records = Nfc_records
print(Nfc_records[0].resource.uri)
print(Nfc_records[0].title)
clf.close()
再生中のステータス情報からURIを抜き取って、それを書き込む。
ついで他の情報も抜き出せるけど多分使わんかな。
日本語でいれてみたら上手くいかなかったけど、マルチバイト文字を扱いたい場合は binascii とか使えばいけると思う。誰かやってみて。
そしてこっちがタグ情報の読み取り。
nfc_read.py
#!/bin/bash python
import nfc
import ndef
import glob
import requests
import time
import types
while True:
try:
clf = nfc.ContactlessFrontend('usb')
print("Touch NFC...")
print("CTRL + C to quit")
Tag_nfc = clf.connect(rdwr={'on-connect': lambda Tag_nfc: False})
if type(Tag_nfc.ndef) is not types.NoneType:
Tag_records = Tag_nfc.ndef.records
Album_resource= Tag_records[0].resource.uri
Album_title =Tag_records[0].title
clf.close()
Volumio_apiurl = "http://127.0.0.1:3000/api/v1/"
Json_Uri = requests.get(Volumio_apiurl + "getState").json()['uri']
Current_Uri = Json_Uri[0:Json_Uri.rfind("/")+1].replace("music-library","mnt")
if Current_Uri != Album_resource:
Qfiles = []
Qfiles = glob.glob("/"+ Album_resource + "/*.mp3")
Qfiles.sort()
Api_Q = ""
for Queue in Qfiles:
Api_Q = Api_Q + "{\"uri\":\"" + Queue.lstrip("/") + "\"},"
Q_payload = "{\"list\": [" + Api_Q.rstrip(",") + "],\"index\": 0}"
requests.post(Volumio_apiurl+"replaceAndPlay",headers = {"Content-Type":"application/json"},data = Q_payload)
requests.get(Volumio_apiurl+"commands/?cmd=repeat&value=true")
print(Album_resource)
print(Album_title)
time.sleep(3)
else:
print("Read NFC error.")
except KeyboardInterrupt:
print("Quit")
clf.close()
break
except IOError:
print("IOError")
clf.close()
pass
URIのレコードからペイロード情報を作ってAPIに投げて再生させる。同じアルバムだった場合はスルー。リピート機能も追加したけど、いらないなら削っちゃってもいい。
ついでにCtrl+Cで終了と、読み取りエラーの場合はループするようにした。
どうもネットに転がってるようにmesssageやprettyの属性値が上手くいかず、リファレンスを確認したところndef.records と ndef.SmartposterRecord を使えば書き込めるっぽいので、そっちで何とかした。
せっかくなので読み込み機能を起動時に自動実行するようにしておく。
rc.localいじればいいんだけど、いつものvi入ってないやんけ!
となったのでviを使えるところから設定する必要があった。
sudo apt-get update
sudo apt-get install -y vim
sudo vi /etc/rc.local
「exit 0」の前に1行追加。プログラム自体はWindowsからも直接編集しやすいようにsmbの共有ディレクトリに置いた。
sudo python /mnt/INTERNAL/py/nfc_read.py
これで電源を入れたら自動でNFCリーダーが機能する。
最初にあったこれが完成する。やったね!
同じことやってる人はいるはずなんだけど、ゼロからの具体的な解説が見当たらなかったので自分でやってみた。
電子工作なんてほとんどやった事なかったんだけど、ネジ締め程度で本格的なガジェットが作れるのは良い時代になったね。
あとこれが部屋にあっても別にモテない。
■追記■
最初の方で初期化したきっかけはapt-get upgradeを行ったせい。Volumioでupgradeをするとサウンドカードが正常に認識されなくなったり、データベースが正常に機能しなくなった。
apt-get updateはパッケージ本体でなくパッケージ情報だけを更新するので多分大丈夫。
※noteを使ったのは初めてなので、至らぬ点があったらその都度補足させていただきます。