ソフトウエア詳細(Software)

こちらのページでは、Piceiver のソフトウエア構成について説明します。

開発時期が2014年であるため、利用する各ソフトウエアのバージョンはその当時の最新のものと なっています。

前提条件

開発に利用する各ソフトウエアのバージョンは下記の通りでです。開発時(2014年)当時の 最新のものとなっています。それぞれのソフトウエアがどういうものかは追って説明します。

やりたいこととその実現方法を考える

※注 本実装では、IPサイマルラジオ radiko は、対象としていません。 raspberry pi での radiko の再生を実現している方もいらっしゃるようですので、 きちっと実装すれば piceiver でも再生する事はできるはずですがまだ試していません。

実現したいことは勿論「インターネットラジオを簡単に聞きたい」ですが、ソフトを実装する上では もっと具体的な要件に落とし込んでいかなければなりません。もうちょっと掘り下げて考えて いきます。

核となるプレイヤーソフトですが、既成のマルチメディアプレイヤーから検討した上、 「mplayer」を使うことにしました。このソフトは、コマンドラインから インターネットラジオのストリームURLやプレイリストURLを指定して再生でき、また、 インタラクティブな操作が要求されない slave モードと いうのがあって、オリジナルスクリプトから利用するのに扱いやすそうです。 こちらのソフトを使って全体の機器の動作をコントロールするためにスクリプトを組むことにします。 スクリプト言語は個人の趣味で Python を使うことにします。

ユーザーインターフェース観点でもいろいろ考えてみます。 ハードウエアの項目で説明した通り、ユーザーインターフェースは、「電源スイッチ」と 「電源インジケータLED」、選曲の為の「ロータリースイッチ」、そして「ボリューム」だけです。 インターネットラジオ受信専用機なので、電源オンして、受信用ソフトエアが自動的に立ち上がるように 設定してあげればいいですね。電源オフは、いちいちRaspberry Pi のシャットダウンなんてしたくないので、 直接電源をスナップスイッチで切っておしまいとしたいです。Raspberry Pi はデフォルトでは、常に SD に書き込みの可能性がありますから、 電源スイッチ断のタイミングが悪いとファイルシステムが壊れてしまう為、なんらかの対策が必要です。 比較的頻繁に書き込みがあるシステムログの書き込みをSDカードでは なくメインメモリ上に書くことで対処します。いわゆる RAMDISKってやつです。完全な対策ではありませんが、 実用上これで十分のようです。

選曲は1回路12接点のロータリースイッチで行います。このスイッチは12の電極の他に共通電極があり これと12か所の接点のうちの「一つ」がスイッチを回転することによって導通になる構造です。 共通電極をグランドに、12接点は Raspberry Pi の GPIO に1本づつ接続すれば、ソフトから ロータリースイッチの位置が読み取れそうです。これを選曲の情報とすれば良いですね。 幸い使用しようとしているスクリプト言語 Python には、GPIO を簡単に扱える RPIO と呼ばれる モジュールが存在しますのでこれを活用します。

ロータリースイッチで12局まで選局できるまではいいのですが、実際のインターネットラジオの ストリームURLを各チャンネルに割り当てるにはどうしたら良いでしょう?あらかじめすべて固定で 設定していてもいいのですが、変更するときにわざわざLinuxにログインしてシコシコやるのは嫌ですね。 かといって、このためにLCDディスプレイつけてキー操作でってのもシンプルではありません。 ここは割り切りですが、Piceiver に WEBサーバーを持たせてネットワークを共有している他の パソコンなどからWEBブラウザ経由で設定することにします。12チャンネル分の入力フォームを持った ページがあれば対応できそうです。こちらもスクリプト言語の Python による CGI で実現することに します。webサーバーと言えば、「Apache」が有名ですが、より軽量で設定の簡単な「lighttpd」 を採用します。

と、ちょっと散漫ながら気になることを書き連ねてきましたが、実現すべき事をまとめると以下の3点になります。

  1. ロータリースイッチで指定したインターネットラジオ局の再生の仕組み
    • 再生自体は mplayer に任せる
    • 選局局情報は、ロータリースイッチの値をGPIOで読み取る
    • 以上の機能をスクリプトで実装する(python)
    • システムブート時に自動的に起動する
  2. 各チャンネルのプリセット局情報の設定、変更の仕組み
    • ウェブサーバーを立てる サーバーは、lighttpd
    • 入力フォーム付きのページを表示する Python CGI を使う
  3. 電源スイッチによる電源断のファイルシステム保護対策
    • RAMDISK の導入
    • ログをRAMDISKに置く設定を行う

ソフトウエアの全体構成

slide

そして、こちらが実現したソフトウエアの構成です。 プロのソフト屋ではないので、アーキの説明の手法が拙いですが、どうぞ容赦ください。

細かいところは追って説明いたしますが、まずは図の見方から。 それぞれの角の丸い□は、スクリプトや設定ファイルなどの実ファイルを 示しています。矢印はコントロールや参照を意味します。 オレンジ色の四角がフルスクラッチで組んだスクリプト。水色の四角がカスタムの設定ファイル。 赤色の四角が既存のソフトウエア。紫色の四角が修正を加えたOSの設定ファイルです。

メインのスクリプトは、piciever.py でこちらは、システムがブートすると rc.local から自動で 呼び出され立ち上がります。ロータリースイッチの位置情報を読み取って、そのチャンネルに対応するラジオ局の URL情報を pi_station.txt から読み取り、mplayer にそのURLからのオーディオストリームの受信を 依頼します。mplayer は指定した URLからオーディオストリームを受け再生します。

ウェブページでのプリセット局の変更に関しては、ウエブサーバーのlighttpd が、クライアントに index.html を渡しますが、実際には form.py が呼ばれこちらがプリセット局の変更入力フォームページを 作ります。ここでプリセット局の変更が入力された場合、現在のプリセット局が列記されているファイル pi_station.txt のURLが入力の指定のとおり変更されます。また、設定情報の初期化を指示された場合、 pi_station_bak.txt からすべてのチャンネルのURL情報を読み取り、pi_station.txtファイルへ 上書きします。いわゆるファクトリーリセットですね。

1.メインコントロールスクリプト

1.1ソフトウエアの説明

slide

Piceiver の中核となるメインコントロールスクリプト、piceiver.py は、まず、ロータリースイッチの 値をGPIO経由で読み出します。そして、その値に対応するチャンネルに設定されているインターネットラジオ局の プレイリストURLを設定情報リスト pi_station.txt から選び出します。 最後に、外部ソフトウエアの mplayer に対して、URLを引数として再生を指示します。

PythonでGPIOの操作を行う為に、RPIO という python モジュールをインポートします。また、外部ソフトエア mplayer を起動するために os というモジュールをインポートします。 そして、os.system("xxxx") という 関数を利用して mplayer を呼び出します。

全体の流れをフローチャートで示すと下記の通りです。

slide

まず、外部ファイル pi_station.txt に記載されている「ロータリースイッチの読み値」と 「インターネットラジオ局のプレイリストURL」の対応表を作成してスクリプト内部で保持します。 そして、アンプのミュートをGPIO経由で解除した後、ロータリースイッチを読み取り、そのチャンネルポジションが 変わっていれば、そのチャンネルに対応した局のプレイリストURLを外部ソフトウエアの mplayer に渡して再生させる という仕組みです。プレイリストURLは、先に説明した通り、 pi_station.txt に列挙しておきます。このpi_station.txtへのURLの記録形式は単純で、1行1局でURLを 記入しておくだけです。1列目がチャンネル1、12列目がチャンネル12。(ちなみにロータリースイッチの 位置との対応はアナログ時計と一緒にしてあります)

ロータリースイッチの変更の検知は、御覧のとおり、ポーリングで行っています。RPIO は、割り込みも使えるので そちらの方法の方がスマートなんですが、すこし試したのですがちゃんと動かす事ができず断念しました。(涙)

ソースコードは下記のとおりです。スクリプトおよび局リストファイルは、 /usr/local/bin 以下に配置 します。

/usr/local/bin/piceier.pyimport RPIO as GPIO
import time
import os
import sys

# NEED station.txt to specify the preset stations. if it does not exist embedded preset will be used

class piceiver():
	def __init__(self):
#               # version , auther description
		self.version = "10.0"
		self.auther = "takkie3g@gmail.com"

#               # location of station list file
		self.default_list = "/usr/local/bin/pi_station.txt"

#               # if station list does not exists use following url
		self.default_station = " http://yp.shoutcast.com/sbin/tunein-station.m3u?id=1582220"

#               # player command and opitions, note place space at each strings
		self.player_cmd = " mplayer"
		self.player_cmd_option = " -cache-min 60 -slave -really-quiet -playlist"

#               # BCM type pin number using
		self.pin_list = [4, 17, 18, 27, 22, 23, 24, 10, 9, 25, 8, 7]

#               # for timing adjustment
		self.sleep_sec = 0.8

#               # pin number selected
		self.pin = 4
		self.pin_old = 0

#               # GPIO setting for all pins which are used
		GPIO.setmode(GPIO.BCM)
		for pin_number in self.pin_list:
			GPIO.setup(pin_number, GPIO.IN, pull_up_down=GPIO.PUD_UP)

#               # for mute function LOW=MUTE, HIGH=OUT
		GPIO.setup(11, GPIO.OUT, initial=GPIO.LOW)		

#               # initial statement
		print("\n********** piceiver version %s by %s **********"  % (self.version, self.auther) )

#               # making dictionary for url or chennel(knob position)
		self.station_url ={}
		self.channel ={}

#               # channel(knob position) resistration mostly for debug
		i = 1;
		for pin_number in self.pin_list:
			self.channel[pin_number] = i
			i = i + 1

#               # if default station list exsits 
		if os.path.exists(self.default_list):
			print "#PICEIVER# default station list exists" 
			f = open (self.default_list, 'r')
			for pin_number in self.pin_list:
				station = ' ' + f.readline()
				station = station.rstrip("\n")
				self.station_url[pin_number] = station
			f.close()

#               # if default station list did not exist, use default station 
		else:
			print "#PICEIVER# default station list not exist, use default"
			for pin_number in self.pin_list:
				self.station_url[pin_number] = self.default_station



#       # polling to know which channel got sellected
	def polling(self):
		for pin_number in self.pin_list:
			if GPIO.input(pin_number)==0:
				self.pin = pin_number


#       # main 
	def main(self):
#               # first get mute off (enable out put)  by pin 11 to get TRUE (HIGH)
		GPIO.output(11, True)		
#               # loop for channel change
		while True:
			self.polling()
			if self.pin != self.pin_old:
				os.system("killall -9" + self.player_cmd + " > /dev/null 2>&1 ")
				os.system( self.player_cmd + self.player_cmd_option + self.station_url[self.pin] + " > /dev/null 2>&1 &")
				print('#PICEIVER# playing ch:%02d gpio:%02d url:%s \n' % (self.channel[self.pin], self.pin, self.station_url[self.pin]))
			self.pin_old = self.pin
			time.sleep(self.sleep_sec)
		GPIO.cleanup()
		GPIO.output(11, False)		

if __name__ == '__main__':
	pi=piceiver()
	pi.main()

さて、核になるプログラムができましたので、これを Piceiver の電源スイッチオンで 自動的に立ち上がるように設定したいと思います。

/etc/rc.local から piceiver.py を起動するように、記述しても構わないのですが、 init※のしきたりにちょっと従って、起動スクリプトを介して起動するようにしたいと思います。 このスクリプトは、/etc/init.d の下に piceiver という名前で配置します。引数は、start, stop, status のみとした単純な bash スクリプトです。

(※記事を公開した2017年時点で、Rasbian のシステム起動のコントロールは、init から systemd へ移行しています。 勿論、systemdでは全然やり方が違います。)

/etc/init.d/piceiver#!/bin/bash
NAME=piceiver
DAEMON=/usr/sbin/$NAME
#DAEMON_ARGS="--options args"
#PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

start() {
    echo -n "Starting piceiver: "
    sudo /usr/bin/python /usr/local/bin/piceiver.py &
    return 0
}
stop() {
    echo -n "Stopping piceiver: "
    sudo pkill -f 'mplayer'
    sudo pkill -f 'python'
    return 0
}
status() {
    echo -n "Status piceiver: "
    sudo pgrep -l 'mplayer'
    sudo pgrep -l 'python'
    return 0
}
case "$1" in
    start)
	start
	;;
    stop)
	stop
	;;
    status)
	status
	;;
    restart)
	stop
	sleep 1
	start
	;;
    *)
	echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
	exit 3
esac

そして、piceiver.py をこのinit.d スクリプト経由で システム起動時の最後に起動するように /etc/rc.local の最後に一行を追加します。

※ /etc/rc.local の最後に init.d スクリプトで piceiver を起動する設定を追加する

/etc/rc.local 追加例sudo /etc/init.d/piceiver start > /dev/ttyAMA0 2>&1 & 

これで、Piceiver のシステムが起動し OS が立ち上がった後自動的に piceiver.py が立ち上がり、 インターネットラジオの再生が始まります。

1.2プレイリストURLとは

これまでの説明の中、「ストリームURL」とか「プレイリストURL」とかいう言葉が出てきていましたが、 これって、そもそも何でしょう?どこからその情報ってどこで見つけたらよいのでしょう? 「ストリームURL」は、インターネットラジオのオーディオストリームを送出しているサーバーそのもの のURLです。「プレイリストURL」は、インターネットラジオのオーディオストリームを送出しているサーバー の情報をプレイリスト形式で返してくれるサーバーのURLです。プレイヤソフトの mplayer はどちらの形式の URLも対応していますが、プレイリストURLを指定する場合、コマンドラインに --playlist のオプションが 必要になります。

さて、このURL情報ですが、一番手っ取り早く探したいのであれば、 SHOUTcastのウエブページ を見るのが 良いでしょう。

slide

SHOUTcast のウエブサイトは、インターネットラジオ局がディレクトリになっており好きなジャンルの局を 選ぶことが簡単にできるようになっています。お好きなジャンルの局一覧を表示してこれと決めた局の ダウンロードのアイコンを左クリックすると、ポップアップでプレイリストの形式が現れますので Any Player(.m3u) を右クリックして「リンクアドレスをコピー」とします。すると、下記のようなURLがコピーされます。

http://yp.shoutcast.com/sbin/tunein-station.m3u?id=xxxxxxxxx (xxxxxxxは様々 idらしい)

このURLを pi_station.txt へ1行づつ記載するわけです。なお、ウェブブラウザで上記のプレイリストを アクセスすると実際のプレイリストがダウンロードされますが、その中にストリームURLが記載されて います。実際のストリームを配信しているサーバーのURLですね。最終的に mplayer はこのストリームURLの情報を 得てラジオ局のストリームを受け取ります。

2.ブラウザによるチャンネル設定変更

slide

2.1ユーザーインターフェースの説明

「ブラウザによるチャンネル設定変更」とは、詰まる所、現在の局リストファイル pi_station.txt をウェブ経由で どのように変更するかという所ですが、 まずはどのようなユーザーインターフェースでこの機能を実現するのかというのを決めたいと思います。

インターネットラジオの局は、局自体がある日突然なくなってしまったり、プレイリストURLが変更になったり、 します。そのため、プレイリストURLのプリセットを変更する仕組みは必須です。固定で変更できないのは使い勝手が 悪いです。 とは言え、メインのフィーチャーではありませんので、あまり凝らないでシンプルに実現しようと思います。

そこで、Piceiver にウェブサーバーを持たせて、同じネットワークの別のPCからウェブブラウザで操作する方法としました。 こんな画面構成です。

slide

ウェブサーバーにアクセスすると12チャンネル分のプレイリストURLの入力フォームを表示されるので、 そこに先ほど説明した SHOUTcat のウエブサイトで見つけた プレイリストURLをコピー&ペーストして更新すると いったものです。

各行は STATION 01 ~ STATION 12 と名付けられているようにチャンネルを示しています。 Piceiver中央にあるチャンネルのつまみの方向でチャンネルを区別します。つまみ位置とチャンネルナンバーの関係は、 アナログ時計と同じです。STATION 01 は1時の方向 STATION 12 は、12時の方向です。

そのチャンネル名の隣にURLの入力フォームがあります。すでにURLが表示されていますが、これは現在の設定値になります。 変更したい場合、このフォームに上書きします。そして、下にある「submit」ボタンを押すと設定が変更され、 下に赤字で Submission Sucseeded! などと設定変更が成功した旨を表示してくれます。

「reset」ボタンは、途中まで記入しようとしたものの更新を中止する際に押します。途中まで記入した URLが無視され、現在の局リストが再表示されます。

「set default」は、いわゆるファクトリーリセットです。機器内部で持っているデフォルト設定の 局リストファイル(pi_station_bak.txt)の内容が現在の局リストのファイル(pi_station.txt)へ上書きされます。

さて、アクセスする際にブラウザに設定するウエブサーバーのアドレスですが、raspberry pi のOS(raspbian)は、 デフォルトで Avahi という Apple Bonjour 互換のローカル名前解決のデーモンが動いています。そのおかげで piceiver で設定されているホスト名でアクセスが可能です。アクセスしようとするPCが MAC であればそのまま Windowsでも、iTunes がインストールされていればOKの様です。

例えば、ホスト名が、raspberrypi であれば、PCのブラウザのwebアドレスとして

http://raspberrypi.local

を指定すれば接続できます。あるいは Piceiver 本体でip アドレスを確認して指示してあげても良いです。例えば、

http://192.168.127.127 

のようにアクセスすることもできます。

2.2 webサーバーの実装

さて、ユーザーインターフェースの仕様は決まったので具体的にどう実装していくのか考えていきます。 まず、webサーバーを選択しなければなりませんが、Piceiverのチャンネル設定変更は本機の 主たる機能ではありませんし、求められる負荷も軽いのでなるべく簡単にいきたいものです。 そういった観点で軽量で設定の簡単な lighttpd を選択しました。

lighttpd のインストールと設定を行っていきます。入力フォームの実現に CGI を利用します。 lighttpd で CGI を利用する場合、cgi か fastcgi のどちらかを選択する必要があるのですが、 今回はパフォーマンスが低いですが圧倒的に設定が簡単な cgi を使うことにします。

まず、apt-get install でインストールします。その際に CGI で python が使えるようにライブラリ関係も インストールします。

$ sudo apt-get install lighttpd
$ sudo apt-get --no-install-recommends install python-flup
$ sudo apt-get install lighttpd-fastcgi

基本の設定ファイルは、/etc/lighttpd/lighttpd.conf ですが、この辺の設定はデフォルトで使うので いじりませんでした。この場合、index.htmlを置くドキュメントルートは、/var/www です。

cgi に python を使えるように設定するには、別の方法で設定が必要です。これは、cgiの設定ファイル /etc/lighttpd/conf-available/10-cgi.conf に python を利用するよう変更を行い、 /etc/lighttpd/conf-enabled/ にリンクを張ることによって有効にします。

$ sudo nano /etc/lighttpd/conf-available/10-cgi.conf
---
cgi.assign = ( ".py"  => "/usr/bin/python" ) # を追加
---
$ sudo ln -s /etc/lighttpd/conf-available/10-cgi.conf /etc/lighttpd/conf-enabled/

cgi は、/var/www/cgi-bin/ に置くことにしますので、このディレクトリを別途作成しておきます。

ここまでが、下準備になります。

コンテンツとして、トップページになる index.html とフォームを作成する form.py スクリプトを作成して それぞれ、下記に配置します。

/var/www/index.html

/var/www/cgi-bin/form.py

index.html は、単に form.py を呼び出しているだけの HTML ファイルになります。核は、form.py です。

/var/www/index.html<html>
<head><title> Piceiver Test Page </title>
<frameset>
<frame src="cgi-bin/form.py" >
</frameset>
</body> 

2.3入力フォーム生成CGI form.py の説明

設定変更用のウェブページを生成している、form.py の説明をします。 先に説明のとおり、Piceiver は、「現在の局リスト」pi_station.txt と 「デフォルトの局リスト」pi_station_bak.txt をファイルとして持っています。これらのファイルの情報をもとにウェブフォームからの入力指示を実行 する事により、適切に現在の局リスト pi_station.txt を変更するのがお仕事となります。 下が CGI form.py のフローチャートとなります。

slide

まず、「現在の局リスト」をファイル pi_station.txt から、「デフォルトの局リスト」 を ファイル pi_station_bak.txt から読み出し、スクリプト内のデータとして保持します。

次にボタン押下の確認を一通り行います。 「Submit」が押されたら、ユーザーがフォームに記入されているURLで「現在の局リスト」を上書きします。 「Default」が押されたら、スクリプト内部で持っている「デフォルトの局リスト」を スクリプト内部で持っている「現在の局リスト」へ上書きします。 なお、自明ですがこのページへの最初のアクセスでは、「Submit」「Default」を押された時の処理は パスされることになります。

次に、スクリプト内部で持っている「現在の局リスト」を外部ファイル pi_station.txtに書き出します。 そして、ウエブページの最上段部分の表示をしたあと、フォームを繰り返し処理で12行出力します。 この時、URL欄のフォームには、あらかじめ取り込んだ「現在の局リスト」に基づく情報が表示されます。

そして、アクションの結果に基づいたメッセージを出力し、最後に最下部に配置した三つのボタン 「submit」「reset」「default」を表示します。

本スクリプトでは、URL記述の構文エラーチェックおよびリンク切れの確認等は行っていません。

実際のスクリプトは以下になります。

/var/www/cgi-bin/form.py#!/usr/bin/python
# -*- coding: utf-8 -*-

# form5.py base


# import
import cgitb
cgitb.enable()
import cgi
import os

# filepath for station setting file
station_filepath = "/usr/local/bin/pi_station.txt"
station_def_filepath = "/usr/local/bin/pi_station_bak.txt"

# html templates
html_top = '''Content-Type: text/html
<html><head><meta content="text/html; charset=UTF-8" />
<title>Raspberry Pi</title>
<body>

<form method="post" action="form.py">

<h1>Piceiver Station Setting</h1>

<p>
Enter the station play list URL you want to set to text fileld of each channel and press submit.
Then Piceiver refletct your request to its setting and restats the receiver. Enjoy!
<p>

<strong>Channel:     URL
</p>
'''
html_middle = '''

<p>STATION %02d: 
<input type="text" name="st%02d" value="%s" size="60" >
</p>
'''

html_message = '''
<p>
<strong>%s
</p>
'''

html_bottom = '''
<p>
<input type="submit" name="submit" value="submit" >    
<input type="reset" value="reset" >    
<input type="submit" name="default" value="set default" >
</p>

</form>
</body>
</html>
'''

# 
# main cgi program starts here
#

# read stations setting file
current_stations=[]
if os.path.exists(station_filepath):
    f = open (station_filepath, 'r')
    for num in range(1,13):
        current_stations.append(f.readline())
    f.close()

# read factory default stations setting file

def_stations=[]
if os.path.exists(station_def_filepath):
    f = open (station_def_filepath, 'r')
    for num in range(1,13):
        def_stations.append(f.readline())
    f.close()


# getting cgi form
form = cgi.FieldStorage()
message = ""

# get button event and station urls which users entered
debug1 = 0


# if some urls are submitted, do below
if form.has_key('submit'):
    for num in range(1,13):
        current_stations[num-1] = form.getvalue('st%02d' % (num)) + "\n"
    debug1 = 1
    message = "Submittion Suceeded!"
elif form.has_key('default'):
    for num in range(1,13):
        current_stations[num-1] = def_stations[num-1]
    debug1 = 2
    message = "Set to Factory Default Suceeded!"

# reflect the submitted request to the setting file
f = open(station_filepath, 'w')
for num in range(1,13):
    f.write(current_stations[num-1])
f.close()


# send out html file
print html_top
for num in range(1,13):
    print html_middle % ( num, num, current_stations[num-1] )
print html_message % message
print html_bottom

#next lines are for debug purpose
# print debug1, current_stations , def_stations
#for num in range(1,13):
#    print current_stations[num-1]
#   print ' xxx '

3.電源スイッチによる電源断のファイルシステム保護対策

Piceiver を実現している Raspberry Pi は、raspbian という Linux OS を利用していますが、 この OS は、SD カードを読み書き可能な形でマウントしており、常時書き込みが発生します。 なので、もし、書き込みの最中に強制的に電源断が起きた場合、ファイルシステムの不整合が起こり 、場合によっては起動不良になる可能性もあります。

この対策のため、RAMDISK というメインメモリに置くファイルシステムの仕組みを導入します。 そして、比較的頻繁に読み書きするログファイルの吐き出し場所を RAMDISK に設定することにより、 ファイルシステム不整合を避けることにします。 ただし、RAMDISKはメインメモリ上にある為、電源断でそれらのログファイルは消えてしまいます。 ですが、本システムでは通常動作時に過去のログ内容を必要とする事はありませんので問題ありません。

なお、SD上にあるファイルシステムを read only でマウントして利用する UNIONFS という手法もあり、 試していたのですが、read only と write 可能の切り替えがうまくいかず断念しました。 (書き込みが必要なければ良かったのですが、プリセットの局リストの修正をする際に SD 上にある現在の局リスト を pi_station.txt へ上書きするため、一時的にも書き込み可能にする必要がありました。)

RAMDISK(tmpfs)自体は、デフォルトでイネーブルになっているので、各種ログファイルのマウントの設定 を tmpfs にするだけです。マウントの設定は、 /etc/fstab ですね。/tmp, /var/tmp, /var/log を tmpfs でマウントする設定にします。

/etc/fstab 該当部分の設定例tmpfs           /tmp            tmpfs   defaults,size=32m,noatime,mode=1777      0       0
tmpfs           /var/tmp        tmpfs   defaults,size=16m,noatime,mode=1777      0       0
tmpfs           /var/log        tmpfs   defaults,size=32m,noatime,mode=0755      0       0

また、デーモンによっては、動作時にログのディレクトリやファイルが存在しないとエラーになるものが ありますので、/etc/rc.local で起動時に作成するようにします。

/etc/rc.local 該当部分の設定例# for RAMDISK 
# create directory points
    mkdir -p /var/log/ConsoleKit
    mkdir -p /var/log/samba
    mkdir -p /var/log/fsck
    mkdir -p /var/log/apt
    mkdir -p /var/log/ntpstats
    mkdir -p /var/log/lighttpd
    chown root.ntp /var/log/ntpstats
    chown root.adm /var/log/samba
#    chown www-data.www-data /var/log/lighttpd

# create empty file
    touch /var/log/lastlog
    touch /var/log/wtmp
    touch /var/log/btmp
    touch /var/log/lighttpd/error.log
    touch /var/log/lighttpd/access.log
    chown root.utmp /var/log/lastlog
    chown root.utmp /var/log/wtmp
    chown root.utmp /var/log/btmp
    chown www-data.www-data /var/log/lighttpd/error.log
    chown www-data.www-data /var/log/lighttpd/access.log
    chmod 744 /var/log/lighttpd/error.log
    chmod 744 /var/log/lighttpd/access.log

なお、ウエブサーバーの lighttpd ですが、「起動時」にログファイルが存在していないと 正常起動しないため、インストールされたときに自動で設定されたinit.d での起動をやめ、 rc.local の最後に起動するように設定し直します。

※init.d での起動をやめる(例)$ sudo chkconfig lighttpd off 

※/etc/rc.local 末尾で起動するように設定$ sudo /etc/init.d/lighttpd start > /dev/ttyAMA0 2>&1 &

以上、RAMDISK の設定でした。

なお、メインメモリが足りなくなったときに、SD にメモリ内容を一時的に退避させる swap file も電源断の際に不具合を引き起こす原因になります。 Piceiver はメモリをあまり消費しないので、通常 swap が発生することはありません。逆に必要も無いと いうことで、念の為、swap file の機能を落としておきます。やらなくても特に問題は無いとは思いますが。

※ swap file を disableにする$ sudo insserv -r dphys-swapfile

4.その他の対応

デフォルトオーディオデバイスの変更

Raspberry Pi は、アナログオーディオ出力が装備されていてデフォルトでは、こちらから 出力してしまいます。Piceiver ではUSB DAC 出力しか使用しませんので、デフォルトの出力先 をこちらに変えてしまいます。/etc/asound.conf に設定します。 詳しくは解説しませんが、設定すべきデバイスのidは、aplay -l で見つけます。

※ /etc/asound.confpcm.!default {
 type hw
 card 1
 device 0
}

上記と同じ設定であれば、mplayer アプリを呼び出す際に "-ao alsa:device=hw=1.0" のような オプションを引数で渡しても変更できますが、デフォルトを変えたほうがシンプルですね。

5.関連ファイル

最後にまとめてとして、これまで説明してきた作成や修正が必要なファイルのロケーションを列挙しておきます。

以上、Picever のソフトウエア実装の大部分について解説してみました。完璧に全てを記したわけでは無く、 抜けや認識違い、誤記があるやもしれませんがご容赦願います。

トップに戻る

 
inserted by FC2 system