Raspberry PiでDNLA Music Serverから曲を取得して再生するのこと。
うちの環境にはBuffaloのLinkStationというNASがあって、
こいつがDNLA Media Serverの機能を持っているので、
ミュージックライブラリとして使っていた。
VLCにはUPnP機能があったので、これで再生していた。
しかし、再生するにはパソコンを立ちあげなければいけない。
スマホにもUPnPメディアクライアントはあるけれど、
再生にはスマホを使わないといけない。
というわけで、
サーバーとして24h稼働しているRaspberry Piで
このような音楽の再生ができないかと考えた。
調査の結果、以下のことがわかった。
- DNLAはUPnPの仕様に基づいて作られている。
- UPnP Media Serverのコンテンツを再生するには、Media Rendererの実装が必要である。
- Media ServerとMedia Rendererの操作を行うためにクライアントが必要。
操作のための通信方式がSSPDだったり、SOAPだったりする。
ここまでわかるまで、SSPDやらSOAPやらを叩いて時間を使ってしまった。
これを踏まえて現状を見ると、以下が見えてきた。
- Media Serverはある。→ LinkStation
- Media Rendererはない。→ Raspberry Piに構築。
- Media Clientはない。→ さしあたり、Androidの『BubbleUPnP』が使えそう。
と、こんなことをすでにやっている人がおり、
下記の記述を参考にRaspberry PiにMedia Rendererを構築してみた。
Playing music on a Raspberry Pi using UPnP and DLNA (revisited)
ここの例にあるように、Raspberry PiにGMediaRenderをインストールした。
自動起動については、init.dではなく、systemdを使った。
スマホにインストールしてあるBubleUPnPのレンダラーを
Raspberry Pi上のレンダラーとすることで、
Raspberry Piから音を出すことができた。
しかし、Clientは自作したいな。
現状、スマホからしか操作できないのは不便だ。
参考文献:
http://blog.scphillips.com/posts/2013/07/playing-music-on-a-raspberry-pi-using-upnp-and-dlna-revisited
https://openconnectivity.org/developer/specifications/upnp-resources/upnp
http://www.upnp.org/specs/av/UPnP-av-AVArchitecture-v1.pdf.
Raspberry Piでラジオを鳴らすのこと
Raspberry Piにスピーカーをつけてラジオを鳴らす方法についてのメモ。
おおまかな仕掛けとしては、
Radikoのswfプレイヤーからストリーミングデータをぶっこ抜いて
メディアプレイヤーで再生する方式の模様。
(だから、いつまで使えるかわからんね)
音声を再生するアプリの導入*1
sudo apt-get install mplayer
ストリーミング関係のアプリの導入
sudo apt-get install rtmpdump swftools libxml2-utils
音声出力先の設定
デフォルトではイヤホンジャックかHDMIか自動判定となっている。
HDMIなり、イヤホンジャックなりどちらか固定としたい場合は
rasp-configから設定可能。
設定メニューの[Advance Options] -> [Audio]と追っていき、
[Auto], [Force 3.5mm ('Headphone') jack], [Force HDMI]から選択する。
sudo rasp-config
音量の設定
画面からできるけど、コマンドでやる場合。
下記でコマンドで現在の値を知る。
sudo amixir -M Simple mixer control 'PCM',0 Capabilities: pvolume pvolume-joined pswitch pswitch-joined Playback channels: Mono Limits: Playback -10239 - 400 Mono: Playback 400 [100%] [4.00dB] [on]
下記、コマンドで設定する。
sudo amixir sset PCM 100%
radikoを再生するスクリプトの取得
スクリプトをここから取得
play_nhk-radio.sh · GitHub
play_radiko.sh スクリプトの修正
radiko側の状態が変わっているのだろうが、
再生で使用するplay_radiko.shはそのままだと動かない。
以下の箇所を修正する。
行 | 修正前 | 修正後 |
---|---|---|
28 | playerurl=http://radiko.jp/player/swf/player_3.0.0.01.swf | playerurl=http://radiko.jp/apps/js/flash/myplayer-release.swf |
53 | swfextract -b 14 $playerfile -o $keyfile | swfextract -b 12 $playerfile -o $keyfile |
70 | --header="X-Radiko-App: pc_1" \ | --header="X-Radiko-App: pc_ts" \ |
71 | --header="X-Radiko-App-Version: 2.0.1" \ | --header="X-Radiko-App-Version: 4.0.1" \ |
108 | --header="X-Radiko-App: pc_1" \ | --header="X-Radiko-App: pc_ts" \ |
109 | --header="X-Radiko-App-Version: 2.0.1" \ | --header="X-Radiko-App-Version: 4.0.1" \ |
111 | --header="X-Radiko-Authtoken: ${authtoken}" \ | --header="X-Radiko-AuthToken: ${authtoken}" \ |
112 | --header="X-Radiko-Partialkey: ${partialkey}" \ | --header="X-Radiko-PartialKey: ${partialkey}" \ |
再生する
例えばTBSを再生する場合は以下のようにする。
play_radiko.sh TBS
参考文献:
http://radiko.jp/
http://www.nakatayuki.com/archives/1039468785.html
https://gist.github.com/ihsoy-s/5292735#file-play_radiko-sh-L28
https://qiita.com/komacchi/items/2db61b16c1c81967705f
Raspberry pi Model BでGW-900Dを使うのこと
RaspbianにはPlanexの無線Lan子機 GW-900Dのドライバは用意されていない。
幸いドライバはrtl8812auのオープンソースドライバが利用でき、
ビルドさえすればLinuxでも動作する。
Web上にはこの手の手順がかなりあるものの、
持っているRaspberry piが初期型のためか、
導入にかなり手こずったので自分なりの手順を書いておく。
以下の手順では有線Lanでインターネットに接続している事が前提となる。
rtl8812auドライバのインストール
Raspbianをインストールする
手っ取り早くNOOBSでインストールした。(JESSIE)
OSの最新化
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade
rootパスワードの設定
$ sudo passwd root
ドライバのビルドに必要なもののインストール
rpi-sourceのインストール
Raspbianのソースを取得するためにこのツールをインストールする
$ sudo wget https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source -O /usr/bin/rpi-source
rpi-sourceの実行で必要なもののインストール
sudo apt-get install bc
sudo apt-get install libncurses5-dev
rtl8812auドライバのダウンロード
保存場所へ適時移動してからダウンロードを実行
git clone https://github.com/gnab/rtl8812au.git
ドライバのビルド
ダウンロードしたドライバのディレクトリに移動
Makefileの編集。
ターゲットプラットフォームをPCからARM RPIに変更する。
...
CONFIG_PLATFORM_I386_PC = n
...
CONFIG_PLATFORM_ARM_RPI = y
...
ビルド
変更後、ビルド。
make
ドライバファイルの設置&カーネルモジュールの依存情報の更新
cp 8812au.ko /lib/modules/$(uname -r)/kernel/drivers/net/wireless
depmod
再起動
sudo reboot
まだまだこれから
dmesg でドライバがロードされているか確認。
ネットワークインターフェイス名の固定化
なんだか知らないがネットワークインターフェイス名(eth0とかのアレ)が、
再起動するたびにコロコロ変更されるので、これを固定化する。
MACアドレスとNICのドライバ名の調査。
MACアドレスはifconfigで表示される、etherの値。
NICのドライバ名はethtoolで調べることができる。
ethtool -i ネットワークインターフェイス名
ネットワークインターフェイス名の設定
/etc/udev/rule.d/70-persistent-net.rules を作成
ファイルに以下の要領で定義を追加する。
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="(ドライバ名)", ATTR{address}=="AA:BB:CC:DD:EE:FF(MACアドレス)", NAME="eth0(インターフェイス名)"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="(ドライバ名)", ATTR{address}=="AA:BB:CC:DD:EE:FF(MACアドレス)", NAME="wlan0(インターフェイス名)"
再起動
sudo reboot
ifconfigで確認
ネットワークンターフェイス名が指定通りならOK。
wifiの有効化
アクセスポイントのscan
sudo iwlist wlan0 scan
wpa_supplicant.confの設定
sudo wpa_passphrase (SSID) (パスワード(平文)) >> /etc/wpa_supplicant/wpa_supplicant.conf
wpa_supplicantの起動
sudo wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
接続の確認
ifconfigでIPアドレスが割り当てられていることを確認
wifi自動起動化
システム起動時にwlan0が有効になるようにsystemdに設定する。
# systemctl enable wpa_supplicant@wlan0(インターフェイス名)
Created symlink /etc/systemd/system/multi-user.target.wants/wpa_supplicant@wlan0.service → /lib/systemd/system/wpa_supplicant@.service.
wlan0用のwpa_supplicant.confを作成する。
sudo cp /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
再起動
ifconfigでwifiが自動接続されていることを確認する。
IPアドレス固定設定
検索すると/etc/network/interfacesを編集するってのがよく見つかるけれど、
その方法はもう古い。
JESSIEでは/etc/dhcpcd.confに設定を記述する方式に変わっている。
ちなみにUbuntu 16.04だったらnmtuiを使って設定する。
/etc/dhcpcd.confを編集する。
interface eth0
static ip_address=192.168.10.32/24
static routers=192.168.10.1
static domain_name_servers=192.168.10.1
interface wlan0
static ip_address=192.168.10.33/24
static routers=192.168.10.1
static domain_name_servers=192.168.10.1
再起動
ifconfigでIPが固定化されていることを確認する。
以上
疲れた。
参考文献:
http://www.ckenko25.jp/wordpress/2016/06/raspberry-pi-rtl8812au-driver
http://my-web-site.iobb.net/~yuki/2017-03/raspberry-pi/kernel-modules/
https://github.com/notro/rpi-source/wiki
http://itpro.nikkeibp.co.jp/article/COLUMN/20130909/503314/
http://blog.livedoor.jp/noanoa07/archives/2062436.html
https://www.xmisao.com/2014/01/16/how-to-connect-wpa2-wireless-lan-using-wpa-supplicant.html
http://kreisel.fam.cx/webmaster/clog/2011-01-20-1.html
http://thatsdone-j.blogspot.jp/2012/12/linuxnic.html
http://blue-red.ddo.jp/~ao/wiki/wiki.cgi?page=NIC%A4%CE%A5%C7%A5%D0%A5%A4%A5%B9%CC%BE%A4%F2%B8%C7%C4%EA%A4%B9%A4%EB
http://caad1229.hatenablog.com/entry/2015/04/23/180925
http://qiita.com/ykog/items/a6dbba1c09e870f8f702
https://wiki.archlinuxjp.org/index.php/WPA_supplicant
Djangoをやってみよう。 その8-管理サイトでの操作-
その7のつづき。
その6で作ったWarshipモデルを管理画面に登録してみる。
nagamitsu1976.hatenadiary.jp
作成したモデルを管理画面に登録するには、
アプリケーションディレクトリ配下にあるadmin.pyにモデル管理クラスを作成する必要がある。
warship/admin.pyを開いて下記を追加する。
from django.contrib import admin from warship.models import ShipClass, Warship # Register your models here. class ShipClassAdmin(admin.ModelAdmin): fields = [u"name"] class WarshipAdmin(admin.ModelAdmin): fields = [ u"ship_class", u"name"] list_display = [u"ship_class", u"name"] admin.site.register(ShipClass, ShipClassAdmin) admin.site.register(Warship, WarshipAdmin)
ここではAdminクラスのメンバにfieldsとlist_displayを定義した。
fieldsについてはモデルの編集画面に表示したい項目をリストで定義している。
つまり、ShipClassは"name"をWarshipは"ship_class"と"name"を表示したい、
ということになる。
list_displayについては、モデルの一覧画面で表示したい項目を定義していて、
ここでは仮にWarshipだけ"ship_class"と"name"を定義してみた。
最後に、admin.site.registerを使って管理画面にモデルと管理モデルのひも付けを行って
処理は完了。
サーバを再起動して管理画面を表示しなおしてみると、項目が増えているのがわかる。
Warshipをクリックして一覧を表示してみると、
list_displayで定義した項目が表示されるのがわかる。
一方、前画面に戻ってShipClassを開いてみると。。。
項目がnameになっておらず、__str__()の値がそのまま表示される。
「ADD Ship class」ボタンを押して、編集画面を見てみる。
こちらはfieldsに定義したnameが表示される。
ついでに「軽巡」を入力してSAVEボタンを押してみる。
正しく追加できているのがわかる。
同じように、Warshipの追加ボタンを押して、
編集画面を確認してみる。
項目の順序もfieldsの順番で表示されている。
ついでに登録も試してみる。
とまぁ、こんな感じで簡単にモデルの登録、編集画面ができたとさ。
使い方としてはマスタ編集画面だとかになるんだろうか。
製造時のデバッグデータ、試験データ作成にもいいかも。
なんせ、低コストだし。
といったところで、次回へ続く。
Djangoをやってみよう。 その7-管理サイト-
その6のつづき。
Apache TomcatにWebアプリケーションを登録する時、
管理画面を使ってデプロイすることができる。
これと似たようなもので、Djangoにも管理画面がある。
管理画面を使うには管理者ユーザを作成する必要がある。
と、その前に以下のコマンドを実行して管理画面等、基本機能を使用可能状態にする。
管理テーブルなんかが作られるため、プロジェクト作成後にやってしまえばよかった。
python manage.py migrate
Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions, warship Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying sessions.0001_initial... OK
管理テーブルができたら、管理ユーザ作成コマンドを実行する。
初回はコマンドでユーザを作るが、
以降は管理画面から追加できる。
python manage.py createsuperuser
Username (leave blank to use 'nagamitsu'): Email address: nagamitsu@foo.bar.com Password: Password (again): Superuser created successfully.
ユーザを作成したら、サーバを起動して管理画面を起動してみる。
python manage.py runserver
管理画面のURLはこれだ。
http://127.0.0.1:8000/admin
先ほど作ったユーザでログインしてみる。
ログイン後、管理メニューのようなものが表示される。
Usersなどをクリックしてみるとわかると思うが、
今のところ、管理ユーザの追加・編集程度しかできないが、
定義を加えることで、
作成したアプリのモデルを管理画面から編集することができるようになる。
といったところで、次回へ続く。
Djangoをやってみよう。 その6-Model/DBの操作-
その5の続き。
まだ画面も何もないので、
コンソールからモデルの操作をやってみる。
実行自体は簡単でpythonの対話モードを使う。
ただし、Djangoの機能だったり、
helloサイト上のクラスを正しく使うには、
ちょっとした手順がある。
python manage.py shell
このコマンドを実行するとhelloサイトの設定が読み込まれた状態で
Pythonの対話モードが起動する。
対話モードに入ったらまず、艦種を登録してみる。
>>> from warship.models import ShipClass >>> ship_class = ShipClass() >>> ship_class.name = u'駆逐艦' >>> ship_class.save()
ShipClassをインポートしたあと、ShipClassのインスタンスを作り、
nameに「駆逐艦」を設定したあと、saveメソッドを呼ぶだけ。
これで、DBに対してInsertが走る。
登録されたかどうか、検索してみる。
とりあえず、全件検索の<モデル>.objects.all()を実行してみる。
>>> ShipClass.objects.all() <QuerySet [<ShipClass: ShipClass object>]>
なんか帰ってきたがよくわからんね。
チュートリアルでは「モデルに__str__メソッドを追加するのが重要です。」なんて、
あとに書いてある。
こっちも真似してmodels.pyのクラスを以下のように変えてみる。
from django.db import models # Create your models here. class ShipClass(models.Model): name = models.CharField(max_length=30) def __str__(self): return self.name class Warship(models.Model): ship_class = models.ForeignKey(ShipClass, on_delete=models.CASCADE) name = models.CharField(max_length=30) def __str__(self): return u"{0} - {1}".format(self.ship_class, self.name)
そしたら、一旦、対話モードを終了し、再度、対話モードで実行しなおして
検索を行ってみる。
>>> ShipClass.objects.all() <QuerySet [<ShipClass: 駆逐艦>]>
中身が見えるようになったので、登録されていたことが確認できた。
all()は全件検索なので、絞り込みをやってみよう。
>>> ship_class = ShipClass.objects.filter(name=u"駆逐艦") >>> print(ship_class) <QuerySet [<ShipClass: 駆逐艦>]>
絞り込みはfilter()。
抽出条件をキーワード引数で指定すると、絞り込みを行ってくれる。
ついでに、もう一回登録をやってみる。
今度は、艦船を登録してみる。
>>> ship_class = ShipClass.objects.filter(name=u"駆逐艦")[0] >>> from warship.models import Warship >>> warship = Warship() >>> warship.ship_class = ship_class >>> warship.name = u"暁" >>> warship.save() >>> Warship.objects.all() <QuerySet [<Warship: 駆逐艦 - 暁>]>
とまぁ、うまくできているようだ。
データベースを触らずにテーブル作って、データ登録までできるって
なんて楽なんだろう。
といったところで、次回へ続く。
Djangoをやってみよう。 その5-Modelの追加-
その4のつづき。
前回追加した、warshipアプリにモデルを追加して
データベースを触ってみようと思う。
Modelの作成
warship/models.pyを開いて、ここにクラスの定義を記述する。
from django.db import models # Create your models here. class ShipClass(models.Model): name = models.CharField(max_length=30) class Warship(models.Model): ship_class = models.ForeignKey(ShipClass, on_delete=models.CASCADE) name = models.CharField(max_length=30)
サンプルでは艦種クラスと艦船クラスを作成した。
艦種は「駆逐艦」とか「戦艦」とかそんな種別を表し、艦船は種別と名前を持つ、そんなイメージ。
ここでのモデルは当然、DBから取得した値を格納するためのものであるので、
クラスのメンバもDBに関するものを定義することになる。
ここで登場したものでは、models.CharFieldクラスとForeignKeyクラスがある。
CharFieldはいわゆる、Varchar型、Char型なんかを格納するためのクラス。
ForeignKeyはそのまま、外部キーによる結合を想定している場合に使用するクラスとなっている。
引数に結合するクラスと、削除時にカスケードするかなどの定義を設定できる。
これら以外にも、整数型のためのIntegerFieldクラスだとか、BooleanFieldクラスなんかも当然あるが、
今回は割愛する。
モデルを定義したら、テーブルを作成する。
Djangoはモデルに応じて自動的にテーブルを作ってくれるので楽ちんである。
そのためのコマンドを実行する。
python manage.py makemigrations warship
実行するとアプリケーション内のモデルの変更点を認識し、
適切なコマンドを作ってくれる。
Migrations for 'warship': warship/migrations/0001_initial.py: - Create model ShipClass - Create model Warship
今回は初めてのモデル作成だったのでCreate Tableのコマンドが作られたようだ。
どんなSQLになるかについては、またまたコマンドで確認できる。
python manage.py sqlmigrate warship 0001
BEGIN; -- -- Create model ShipClass -- CREATE TABLE "warship_shipclass" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(30) NOT NULL); -- -- Create model Warship -- CREATE TABLE "warship_warship" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(30) NOT NULL, "ship_class_id" integer NOT NULL REFERENCES "warship_shipclass" ("id")); CREATE INDEX "warship_warship_ab7d680f" ON "warship_warship" ("ship_class_id"); COMMIT;
とまぁ、こんなSQLが実行されるらしい。
中身がわかったところで、テーブル作成を行ってみる。
DBを直接触る必要がなく、Djangoのコマンドで行える。
python manage.py migrate warship 0001
実行後、こんなメッセージがでれば成功。
Operations to perform: Target specific migration: 0001_initial, from warship Running migrations: Applying warship.0001_initial... OK
これでモデルとDBができた。
データ登録、検索ができるか、などについては、次回に続く。