2014年2月21日金曜日

UDOOのUbuntuでネットワークに接続できない

ちょっと前にUDOOのWi-Fiモジュールを使ってワイヤレス接続するように設定したんですが、その後、なぜかLANケーブルをつないでもPCからSSH接続ができなくなった。とりあえずワイヤレスでSSHログインしていろいろ調べてみると、DHCPでIPアドレスが取れてない。どうやら/etc/network/interfacesの設定がおかしくなってたっぽい。

UDOOのUbuntuでデフォルトの有線インタフェースのデバイス名はeth2なので、
$ sudo vim /etc/network/interfaces
auto eth2
iface eth2 inet dhcp
の2行をを追加した上で、
$ sudo ifdown eth2
$ sudo ifup eth2
として反映してやると、有線でも接続できるようになりました。

2014年2月19日水曜日

[小技] QEMUの対応マシン一覧を表示するコマンド

QEMUでエミュレートできるマシンの一覧を表示するコマンド。
$ qemu-system-arm -machine help
↓こんな感じで出てきます。
Supported machines are:
none                 empty machine
collie               Collie PDA (SA-1110)
nuri                 Samsung NURI board (Exynos4210)
smdkc210             Samsung SMDKC210 board (Exynos4210)
connex               Gumstix Connex (PXA255)
verdex               Gumstix Verdex (PXA270)
highbank             Calxeda Highbank (ECX-1000)
integratorcp         ARM Integrator/CP (ARM926EJ-S) (default)
kzm                  ARM KZM Emulation Baseboard (ARM1136)
mainstone            Mainstone II (PXA27x)
musicpal             Marvell 88w8618 / MusicPal (ARM926EJ-S)
n800                 Nokia N800 tablet aka. RX-34 (OMAP2420)
n810                 Nokia N810 tablet aka. RX-44 (OMAP2420)
sx1                  Siemens SX1 (OMAP310) V2
sx1-v1               Siemens SX1 (OMAP310) V1
cheetah              Palm Tungsten|E aka. Cheetah PDA (OMAP310)
realview-eb          ARM RealView Emulation Baseboard (ARM926EJ-S)
realview-eb-mpcore   ARM RealView Emulation Baseboard (ARM11MPCore)
realview-pb-a8       ARM RealView Platform Baseboard for Cortex-A8
realview-pbx-a9      ARM RealView Platform Baseboard Explore for Cortex-A9
akita                Akita PDA (PXA270)
spitz                Spitz PDA (PXA270)
borzoi               Borzoi PDA (PXA270)
terrier              Terrier PDA (PXA270)
lm3s811evb           Stellaris LM3S811EVB
lm3s6965evb          Stellaris LM3S6965EVB
tosa                 Tosa PDA (PXA255)
versatilepb          ARM Versatile/PB (ARM926EJ-S)
versatileab          ARM Versatile/AB (ARM926EJ-S)
vexpress-a9          ARM Versatile Express for Cortex-A9
vexpress-a15         ARM Versatile Express for Cortex-A15
xilinx-zynq-a9       Xilinx Zynq Platform Baseboard for Cortex-A9
z2                   Zipit Z2 (PXA27x)
ほかにも
$ qemu-system-arm -machine ?
$ qemu-system-arm -M help
$ qemu-system-arm -M ?
でもおk。

2014年2月16日日曜日

UDOOをワイヤレス化してみた

以前、このブログでRaspberry Piのワイヤレス化にトライしました。そのときに使ったのがBuffaloのWLI-UC-GNMというUSB無線LANアダプタです。Raspbian OSで追加のドライバインストールなしに使えて、簡単な設定だけでワイヤレスコネクティビティを追加でき、小型、しかも安価。ストックしておいて損はないアイテムです。

一方、オンボードのWi-Fiモジュールが搭載されたボードでは、後付けのデバイスなしでもワイヤレス接続をセットアップできます。UDOOの場合、DualおよびQuadモデルにはWi-Fiモジュールが搭載されているので、ボード単体でRaspberry Pi+USB無線LANアダプタの場合と同様にワイヤレス化が実現できます。

で、実際にやってみました。手順は下記のとおりです。OSは公式のUbuntu 12.04です。

ワイヤレスインタフェースを見つける
$ ifconfig
(中略)
wlan6     Link encap:Ethernet  HWaddr 7c:dd:90:42:cf:83
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
wlan6というインタフェースがあることがわかります。なおコマンドは
netstat -i

ip link show
でも可。

wpa_supplicantの設定
$ sudo sh -c "wpa_passphrase '(ESSID)' '事前共有キー' >> /etc/wpa_supplicant/wpa_supplicant.conf"
エディタでちょっと編集
$ sudo vim /etc/wpa_supplicant/wpa_supplicant.conf
network={
        ssid="(入力したESSID)"
        # ここから
        key_mgmt=WPA-PSK
        proto=WPA WPA2
        pairwise=CCMP TKIP
        group=CCMP TKIP WEP104 WEP40
        # ここまでを追加
        #psk="(入力した事前共有キー)"
        psk=(暗号化された事前共有キー)
}
wpa_supplicantの再起動。
$ sudo pkill wpa_supplicant
$ sudo wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlan6 -Dwext &

DHCPによるIPアドレスの取得
$ sudo dhclient -d wlan6
これで接続できるようになるはずです。

ネットワーク設定にワイヤレス接続を追加
再起動時に自動接続されるよう設定しておきます。
/etc/network/interfacesをエディタで開いて編集。
$ sudo vim /etc/network/interfaces
下記を追加
auto wlan6
iface wlan6 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

参考情報

Linux: Show / Display Available Network Interfaces - nixCraft

Rapsberry Piで気温のログ+Google Chartsでグラフ化

以前「気温をつぶやくRaspberry Pi」の記事で、温度センサによる室温測定と、自動でのTwitter投稿をやってみました。cronで30分ごとに定期的に温度を測り、ツイートするようにしたわけですが、せっかく定期実行しているので、温度ログを残すようにしてみました。ログといっても、淡々と羅列された数字を眺めても何も面白くないので、可視化します。

可視化、つまり温度グラフを描画すること、これはいろいろ方法があると思います。たとえば何かの言語の2D描画ライブラリを使って、一つひとつの温度ログを直線で繋いでいくとか。でも、この方法は結構面倒です。横軸はいつからいつまで表示するか、縦軸の温度範囲はどうすれば見やすいか、軸そのものや目盛り、ラベルはどうするか、考えるべきことがたくさん。これらをすべて考慮して実装しても、得られるのは静的な画像が一枚。インタラクティブなUIを作って、拡大縮小なんて、さらに手間がかかります。

そこで今回はGoogle Chartsを使ってみます。 Google Chartsは、温度変化のプロットに適した折れ線グラフのほか、円グラフ、棒グラフなど実に多様なグラフのプリセットを備えたWebベースのデータ可視化ツールです。JavaScriptで利用可能で、拡大縮小などのインタラクティブなUIを生成してくれます。しかも、フリー!Google先生、太っ腹。

気温取得スクリプトにログ機能を追加

まずは前回作った温度測定スクリプトにログ機能を追加します。本来は時刻と気温をシンプルにCSV形式などで記録したほうが汎用性は高いのですが、今回はGoogle Chartsに渡す前提で、HTMLファイルに埋め込むJavaScriptの1行分としてあらかじめ整形してテキストファイルに書き込んでしまいます。
$ vim temperature.py
#!/usr/bin/env python
#!/usr/bin/env python

import os
import os.path

# Get temperature from the sensor
hex_temp = os.popen("/usr/sbin/i2cget -y 1 0x48 0x00 w").read()
hex_temp = hex_temp[4:6] + hex_temp[2:4]
dec_temp = int(hex_temp, 16) / 8 * 0.0625 # 計算結果を変数に入れるよう修正

# ここから下を追加

# Print temperature
print int(dec_temp)

log_file = '/home/pi/path/to/temp_log.txt'
lines = []
if os.path.exists(log_file):
    with open(log_file) as f:
        lines = f.readlines()
        while len(lines) > 20000:
            lines.pop(0)

str = "          [new Date(" + os.popen("date +%Y,").read().rstrip() + os.popen("echo \"$(date +%m) - 1\" | bc").read().rstrip() + os.popen("date +,%d,%H,%M,%S").read().rstrip() + "),  " + str(dec_temp) + "],\n"

lines.append(str)
with open(log_file,'w') as f:
    f.writelines(lines)
ログファイル(temp_log.txt)の中身は、下記のような感じになっています。new Date()はDateオブジェクトのコンストラクタです。monthのみ、1月を0として数え始める点に注意が必要です。上記のPythonスクリプト内ではos.popen()関数でシェルのdateコマンドを読んで日付を取得していますが、月だけ-1しています。
          [new Date(2014,1,05,04,30,01),  23.5],
          [new Date(2014,1,05,05,00,02),  22.75],
          [new Date(2014,1,05,05,30,02),  22.1875],
          [new Date(2014,1,05,06,00,01),  21.75],
          [new Date(2014,1,05,06,30,02),  21.4375],
          [new Date(2014,1,05,07,00,01),  20.75],
          [new Date(2014,1,05,07,30,02),  20.625],
          [new Date(2014,1,05,08,00,02),  21.625],
          [new Date(2014,1,05,08,30,01),  21.6875],
          [new Date(2014,1,05,09,00,02),  21.125],

HTML出力スクリプト

表示用のHTMLを生成するスクリプトを作成します。上記スクリプトで出力したログ行をファイルから読み込んで展開します。ベースとなるHTMLは公式のサンプルなどを参考に。
$ vim write_html.py
#!/usr/bin/env python

import os
import sys

argvs = sys.argv
argc  = len(argvs)
html_path = ''
if(argc == 2):
    html_path = argvs[1] + os.sep

lines = ['']

lines.append("<html>\n")
lines.append("  <head>\n")
lines.append("    \n")
lines.append("    <script src="http://www.google.com/jsapi" type="text/javascript"></script>\n")
lines.append("    <script type="text/javascript">\n")
lines.append("      google.load('visualization', '1', {'packages':['annotatedtimeline']});\n")
lines.append("      google.setOnLoadCallback(drawChart);\n")
lines.append("      function drawChart() {\n")
lines.append("        var data = new google.visualization.DataTable();\n")
lines.append("        data.addColumn('date', 'Date');\n")
lines.append("        data.addColumn('number', 'Temp');\n")
lines.append("        data.addRows([\n")

log_file = '/home/pi/path/to/temp_log.txt'
if os.path.exists(log_file):
    with open(log_file) as f:
        lines.extend(f.readlines())

lines.append("        ]);\n")
lines.append("        var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));\n")
lines.append("        chart.draw(data, {displayAnnotations: true});\n")
lines.append("      }\n")
lines.append("    </script>\n")
lines.append("  </head>\n")
lines.append("  <body>\n")
lines.append("    <div id="chart_div" style="height: 240px; width: 700px;">
</div>
\n")
lines.append("  </body>\n")
lines.append("</html>\n")

with open(html_path + 'index.html','w') as f:
    f.writelines(lines)
で、このスクリプトを実行してHTMLを吐き出させるわけですが、本来はCGI化して、Webアクセスがあったときに動的に実行するほうがかっこいいと思います。温度測定スクリプトと同様、30分おきにcronで実行しますが、測定結果のログ書き込み→HTML生成という動作は特に同期しません。手抜きです。cronに登録したジョブ自体、表記順にスタートこそすれ、他のジョブの終了を待つわけではないらしい(参考)ので。

あ、一つのスクリプトにまとめれば話は早いですよ、もちろん。ただhtmlの出力先をユーザのhomeディレクトリ下のpublic_htmlじゃなくて、/var/wwwの下にしたくて、HTML出力はrootのcronでやる必要があるな、と思って別々のスクリプトにしちゃいました。ですのでcorntabもsudoで。
$ sudo crontab -e
0,30 * * * * /home/pi/work/temperature/write_html.py /var/www
あらかじめWebサーバ(apache2) をインストールしておく必要があります。sudo apt-get install apache2とかやればOKだと思います。たぶん。

あとは、cronが走るなり、スクリプトを手動で実行するなりすれば、所望のHTMLファイルが生成されます。ブラウザからRaspberry Piにアクセスしてやることで、Google Chartsで生成された温度グラフが表示されるはずです。


グラフを特定の期間に絞って引き伸ばして表示してやることもできます。便利。