pslaboが試したことの記録

はてなダイヤリーからはてなブログに引っ越してきました

この日記は現在実行中の減量記録を含む個人的なメモとして始めましたが、最近はコンピュータやガジェット、ハック、セキュリティネタのほうがメインになっております。

はてなダイヤリー時代はカテゴリ分けが適当だったのですが、これはそのうち直します。


iPhone/iPadの動画や音楽をAirPlayでカーナビに流すためにRaspberry Pi と raspbmc で環境を作る。

※おそらく、DRMが掛かったコンテンツをこの方法では再生できません。なんでも完璧に流し込みたい場合は素直にAppleTVを買いましょう。また、raspbmc は Pi2 に対応していません。OSMC 向けの同様の試みは気が向いたらやります。

この試みは、iPhoneiPadに保存した動画や音楽を AirPlay 経由でワイヤレスでカーナビに流し込むことを目的としています。

このような環境を構築する場合は通常ならばWiFiアクセスポイントとAppleTVが必要です。カーナビの仕様によってはHDMI→アナログビデオ(RCA)コンバータも使います。そうすると3つのデバイスを扱う必要がでてくるため、いろいろと複雑な構成となります。

しかし Rapsberry Pi なら単体で HDMI とアナログビデオ出力が出来ます。さらにWiFI USBドングルを指して無線LANアクセスポイントとして動かすこともできます。これなら機器は1つで済みます。そしてこのような目的には "raspbmc" というパッケージングが使えます。Raspberry Pi で Kodi (旧 XBMC) を動かすことに特化した専用パッケージです。Kodi は限定的ながら AirPlay に対応しているので、今回の要件にピッタリ合致しています。


さて「raspbmc で AirPlay + WiFiアクセスポイント」という設定事例はいろんな方が実践されています。しかし一通り調べた範囲ではDHCPサーバを普通に立てているケースが多いようです。これは車内でiPhoneでインターネット接続したい場合に不便です。なぜならデフォルトゲートウェイがRaspberry Pi側に向いてしまうためにインターネット向けのパケットが3G側に流れないためです。よってDHCPデフォルトゲートウェイの情報を出さない構成を試行し、さらにそれを自動的に導入できるようにスクリプト化してみました。

車載向けのAirPlay 環境に最低限必要なもの。

  1. iOSからの音楽や動画をAirPlayで受けるデバイス。
  2. iOSデバイスと AirPlay デバイスの間のネットワーク接続。
  3. AirPlay デバイスからカーナビやカーオーディオへの接続。

必須ではないもの。

  1. AirPlay デバイスからのインターネット接続経路。(これが必要な場合は Raspberry Pi をテザリングiPhone に接続するほうがよい)

サマリ

  1. 機材を準備する。
  2. SDカードにraspbmcを焼いて起動し、日本語が使えるようにする。
  3. raspbmcにsshでログインしてロケールタイムゾーンの設定を行う。
  4. WiFi USB ドングルにIPアドレスを割り当てる。
  5. hostapd と isc-dhcp-server をインストールして設定する。

※設定用のスクリプトでは、ロケールタイムゾーンの設定を行った後の作業を一括で処理できます。

機材を準備する。

Raspberry PiとUSB WiFi ドングル、ビデオケーブル等を用意します。一式を初めて揃えるならこんなもんかと。


Raspberry Pi は B+ を使います。Pi2 での動作は確認しておりません。ケースも適当なものを併せて購入しておきます。

Raspberry Pi Model B+ (Plus)

Raspberry Pi Model B+ (Plus)

あと、念の為にヒートシンクも購入しておきます。

サインスマート アルミニウムヒートシンク Raspberry Pi用 3枚入り

サインスマート アルミニウムヒートシンク Raspberry Pi用 3枚入り

USB WIFI ドングルは BUFFARO の WLI-UC-GNM を利用する事例が多いっぽいので、これを選びました。

BUFFALO 無線LAN子機 コンパクトモデル 11n技術・11g/b対応 WLI-UC-GNM

BUFFALO 無線LAN子機 コンパクトモデル 11n技術・11g/b対応 WLI-UC-GNM

ビデオケーブルは4極ミニプラグをRCAに変換するするケーブルが必要です。ちょうどよい長さのものはナカナカ見当たらないのですが、富士パーツ商会のAD-511と、通常のRCA AVケーブルを組み合わせることにします。

フジパーツ 4極ミニプラグ-ピン端子×3変換ケーブル 0.1m AD-511

フジパーツ 4極ミニプラグ-ピン端子×3変換ケーブル 0.1m AD-511

USB電源はAnkerあたりのシガーソケット型USB電源で良いでしょう。1ポートはRasPiで専有するわけですが、どうせそのほかにスマホタブレットの充電でも使うのだから、4ポートくらいは欲しいところ。必要な電源容量についてはテスターで電流量を測定しつつ起動→AirPlayでの動画再生という流れで測定してみると、概ね0.5A以下で推移しています。安全圏のマージンとして1Aを確保していれば特に問題はないでしょう。

あとは、microUSBケーブルとか、microSDHCが必要ですね。microSDHCは2GB以上あれば充分。microUSBケーブルは設置場所までの取り回し分を考えて適当な長さのものを調達します。

セットアップの準備

Raspbmcのイメージは以下のURLからダウンロードできます。
http://www.raspberrypi.org/downloads/ (OSMC への移行のため、ここにはもうありません)
http://mirrors.arizona.edu/raspbmc/downloads/bin/filesystem/prebuilt/

ここで raspbmc-final.img.gz を選びます。

焼き方についてはここでは書きません。これは Raspberry Pi 全般に共通する内容だからです。
手順がわからない方は以下のURL等を参照してください。
http://www.raspberrypi.org/documentation/installation/installing-images/README.md

Raspbmc の基本的なセットアップを行う。

最初に以下2点の作業を行い、表示を日本語に切り替えます。

フォントの種類を "Arial based" に変更します。

SYSTEM->Settings->Appearance->Skin から、Fonts を "Skin default" から "Arial default" に切り替えます。

言語を日本語に変更します。

SYSTEM->Settings->Appearance->Language を "Japanese" に切り替えます。

次に「正しい手順でシャットダウンしなかった場合に、次回利用時に表示される警告メッセージを禁止」する設定を行います。車載AirPlayの場合は正しい手順でOFFにすることは現実的にありえないので、これが毎回表示されるのはとても困るわけです。

プログラム

Raspbmc Settings

System Configuration (左から3つ目の項目)

Disable unsafe shutdown warning

OK

なお、この設定を変更すると Kodi (Raspbmc のユーザ・インタフェース)のリブートがかかります。OSの再起動はありません。


また、AirPlay の設定を以下のメニューで確認して有効化しておきます。

システム

設定

サービス

AirPlay

sshでraspbmcにログインし、初回の設定を行う。

ここからの作業は ssh で機材にログインして行います。ログイン方法は皆様御存知の通り ssh pi@[Raspberry Pi のIPアドレス] ですね。

最初のログインでは、ロケールタイムゾーンの設定が必要です。

ロケールは ja_JP.UTF-8 だけを設定すればよいでしょう。"all locale" を選んでしまうと全ロケールの展開に相当の時間が掛かるため、これはやめましょう。カーソルキーでフォーカスを移動して SPACE で選択できます。選択したら ENTER を押すと次の画面に進みます。

次はデフォルトのロケール選択ですが、これは None のままで OK です。

次にタイムゾーンの設定ですが、Asia→Tokyo を設定します。

導入を自動化するスクリプト

以下のスクリプトのうち、WLAN_SSID と WLAN_PASSPHRASE は必ず変更してください。

必要な設定変更は基本的に diff -u 形式で吐いてます。UNIX系の知識があれば普通に理解できる内容と思いますので詳細な解説は省略します。

#!/bin/sh
#
# Raspbmc を車載用のAirPlayデバイスとするために
# WiFi アクセスポイントの機能を導入するスクリプト。
#
######################################################################
# 実装上のポイント:
# iPhoneで利用する際に、通常のネットワーク通信は3G/LTE側に流しつつ、
# WiFiで音楽や動画をAirPlayで再生できること。
#
#   iPhone を普通の無線LANアクセスポイントに登録すると、
#   すべてのデータ通信は無線LAN側に流れます。
#
#   しかし車載用の AirPlay を目的としたWiFiアクセスポイントでは
#   インターネットへの経路が存在しない閉鎖ネットワークです。
#   このために普通に WiFi AP を立ててしまうと車内にいる間は
#   メール、ウェブ閲覧、その他のインターネットサービスが使えません。
#
#
#   これではあまりにも不便なので以下のいずれかの方法で問題を回避します。
#
#   a) DHCPアドレスリースの際にデフォルトゲートウェイやDNSサーバの
#    情報を配布しない。
#
#   b) DHCPサーバを動かさず、IPアドレスは静的割り当てとする。
#
#   しかし b) では設定が面倒になるので、ここでは a) の設定を提供する。
#

########################################
# 設定調整項目

# 無線LANデバイスのIPアドレス設定
WLAN_IP=172.16.0.1

# WiFi アクセスポイントのSSIDとパスフレーズの設定
WLAN_SSID=raspbmc-airplay
WLAN_PASSPHRASE=raspberry

# 設定調整項目ここまで
########################################

# WLAN デバイス名
# 通常は変更しない
WLAN_DEVICE=wlan0


########################################
# ここから下は意味がわかる方だけいじること
########################################

# isc-dhcp-server がインストールされていない場合は
# 必要なパッケージのインストールを行う
dpkg -l | grep -q "isc-dhcp-server"
if [ $? -ne 0 ]; then
    # パッケージのアップデートを行います。
    # これは AirPlay が正常に利用できないことを防止するため?
    apt-get -y update
    apt-get -y upgrade
    apt-get -y autoremove

    # WiFi アクセスポイントの構築に必要な2つのパッケージをインストールします。
    apt-get -y install hostapd isc-dhcp-server

    # patch コマンドでファイルの更新を行う
    apt-get -y install patch
fi

# dhcpd や hostapd が動いていたら止める
service isc-dhcp-server stop
hostapd_pid=$( pidof hostapd )
if [ "$hostapd_pid" != "" ]; then
    kill $hostapd_pid
fi

# /etc/network/interfaces に wlan0 のネットワーク設定を書き込む処理
# ルーティングは不要なので iptables の設定は省略している。
# このファイルは常に上書きでよい。
(
cat << EOF
allow-hotplug ${WLAN_DEVICE}
iface ${WLAN_DEVICE} inet static
    address   ${WLAN_IP}
    netmask   255.255.255.0
    broadcast ${WLAN_IP%.*}.255
    network   ${WLAN_IP%.*}.0
    post-up   /usr/sbin/hostapd -B /etc/hostapd/hostapd.conf
    post-up   /usr/sbin/service isc-dhcp-server start
    pre-down  kill \`pidof hostapd\`
EOF
) > /etc/network/interfaces

####################
# 設定ファイルのパッチ当てる前のファイルが存在していたら
# それを用いて設定ファイルを復元する。

for file in /etc/dhcp/dhcpd.conf \
            /etc/default/isc-dhcp-server \
            /etc/NetworkManager/NetworkManager.conf \
            /etc/hostapd/hostapd.conf ; do
    if [ -e ${file}.orig ]; then
        mv ${file}.orig ${file}
    fi
done

# 本スクリプトの初回実行時には hostapd.conf は /etc に存在していないため、
# サンプルを展開する。
if [ ! -e /etc/hostapd/hostapd.conf ]; then
    zcat /usr/share/doc/hostapd/examples/hostapd.conf.gz > /etc/hostapd/hostapd.conf
fi

# wlan0 の MAC アドレスを抽出する。
MACADDR=$( /sbin/ifconfig ${WLAN_DEVICE} | head -1 | awk '{ print $5 }' )

####################
# patch に流し込める形式で設定ファイルの差分を作る
#
# (1) /etc/default/isc-dhcp-server
# ・IPアドレスをリースするだけの簡単な設定。
# ・デフォルトゲートウェイは切らない。
# ・DNSサーバ情報も出さない。
#
# (2) /etc/NetworkManager/NetworkManager.conf
# ・wlan0 の MACアドレスを管理除外対象として追記する。
#
# (3) /etc/default/isc-dhcp-server
# ・DHCPのアドレスリースを wlan0 だけに絞る指定を追記する。
#
# (4) /etc/hostapd/hostapd.conf
# ・SSID とパスフレーズを設定する。

(
cat << EOF
--- /etc/dhcp/dhcpd.conf	2012-09-14 12:24:53.000000000 +0900
+++ /etc/dhcp/dhcpd.conf.new	2015-01-31 23:10:32.464728758 +0900
@@ -105,3 +105,10 @@
 #    range 10.0.29.10 10.0.29.230;
 #  }
 #}
+subnet ${WLAN_IP%.*}.0 netmask 255.255.255.0 {
+  range ${WLAN_IP%.*}.50 ${WLAN_IP%.*}.100;
+  option broadcast-address ${WLAN_IP%.*}.255;
+  option domain-name "localnet";
+  default-lease-time 600;
+  max-lease-time 7200;
+}
--- /etc/default/isc-dhcp-server	2015-01-31 23:10:16.445995339 +0900
+++ /etc/default/isc-dhcp-server.new	2015-01-31 23:10:32.504725694 +0900
@@ -18,4 +18,4 @@
 
 # On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
 #	Separate multiple interfaces with spaces, e.g. "eth0 eth1".
-INTERFACES=""
+INTERFACES="${WLAN_DEVICE}"
--- /etc/NetworkManager/NetworkManager.conf	1970-01-01 09:00:24.480000000 +0900
+++ /etc/NetworkManager/NetworkManager.conf.new	2015-01-31 23:10:32.594718800 +0900
@@ -5,3 +5,6 @@
 
 [ifupdown]
 managed=false
+
+[keyfile]
+unmanaged-devices=mac:${MACADDR}
--- /etc/hostapd/hostapd.conf	2015-02-01 15:58:04.163637719 +0900
+++ /etc/hostapd/hostapd.conf.new	2015-02-01 15:59:42.411575746 +0900
@@ -83,12 +83,12 @@
 ##### IEEE 802.11 related configuration #######################################
 
 # SSID to be used in IEEE 802.11 management frames
-ssid=test
+ssid=${WLAN_SSID}
 
 # Country code (ISO/IEC 3166-1). Used to set regulatory domain.
 # Set as needed to indicate country in which device is operating.
 # This can limit available channels and transmit power.
-#country_code=US
+country_code=JP
 
 # Enable IEEE 802.11d. This advertises the country_code and the set of allowed
 # channels and transmit power levels based on the regulatory limits. The
@@ -679,7 +679,7 @@
 # and/or WPA2 (full IEEE 802.11i/RSN):
 # bit0 = WPA
 # bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled)
-#wpa=1
+wpa=2
 
 # WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
 # secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
@@ -688,7 +688,7 @@
 # wpa_psk (dot11RSNAConfigPSKValue)
 # wpa_passphrase (dot11RSNAConfigPSKPassPhrase)
 #wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
-#wpa_passphrase=secret passphrase
+wpa_passphrase=${WLAN_PASSPHRASE}
 
 # Optionally, WPA PSKs can be read from a separate text file (containing list
 # of (PSK,MAC address) pairs. This allows more than one PSK to be configured.
@@ -700,7 +700,7 @@
 # entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
 # added to enable SHA256-based stronger algorithms.
 # (dot11RSNAConfigAuthenticationSuitesTable)
-#wpa_key_mgmt=WPA-PSK WPA-EAP
+wpa_key_mgmt=WPA-PSK
 
 # Set of accepted cipher suites (encryption algorithms) for pairwise keys
 # (unicast packets). This is a space separated list of algorithms:
@@ -856,7 +856,7 @@
 # 0 = WPS disabled (default)
 # 1 = WPS enabled, not configured
 # 2 = WPS enabled, configured
-#wps_state=2
+wps_state=0
 
 # AP can be configured into a locked state where new WPS Registrar are not
 # accepted, but previously authorized Registrars (including the internal one)
EOF
) | patch -b -p0

iOSデバイスを接続してみる。

Raspberry Pi を再起動したら iOS デバイスを Raspberry PI の WiFI アクセスポイントに接続して AirPlay 接続を試します。

今回作成したWiFiアクセスポイントに接続した場合の注意点は「iOSデバイスのステータスバーにWiFiのアイコンが出ない」ことです。ステータスバー上の"LTE/3G/4G/WiFiアイコン"の表示は「インターネット向けのデータ通信に使用するデバイスの種類」を明示しているだけなのです。エンジニア的な用語でいうと「デフォルトゲートウェイがモバイル通信とWiFiのどちらを向いているか」ということです。

よってWiFi"アクセスポイントに接続できているか否かの確認は、設定アプリから行う必要があります。

WiFi接続が正しく行えていたら、写真アプリで写真や動画を AirPlay してみて、Kodi で表示できることを確かめます。