Mac で SORACOM Air で接続している時に特定のルートだけ SORACOM 経由にしてそれ以外は Wi-Fi 経由にする方法

タイトルが若干長いですが、やりたいことは以下のとおりです。

1. 通常は Wi-Fi などでインターネットに接続している
2. SORACOM Air 入りの USB 3G/LTE モデムを Mac に挿した時、SORACOM が提供するサービスには SORACOM Air 経由でアクセスしたいが、それ以外のネットワーク通信は通常通り Wi-Fi 側で行いたい

私の場合は soracom-sdk-go のテストの中で metadata.soracom.io へのアクセスがあり、そこだけ SORACOM Air 経由にしたいという個人的な事情がありました。

他にも SORACOM Beam や SORACOM Endorse、SORACOM Funnel などのサービスへのアクセスも同様にルーティングしたい場合があるかもしれませんし、SORACOM Canal や SORACOM Direct で接続したプライベート環境へのルーティングも同様に行いたい場合があるかもしれません。

設定手順はおおまかに以下の2ステップです。

1. システム環境設定 > ネットワーク で Wi-Fi と USB モデムの優先順位を設定
2. ダイアルアップ時に実行されるスクリプトを書いてルーティング設定を追加


ではスクリーンショットなどを交えながら具体的に説明していきます。

1. ネットワークインターフェースの優先順位を設定

システム環境設定からネットワークの設定を開きます。
左側のインターフェースのリストの下部に歯車アイコンがあり、それを押すとメニューが現れます。
その中から「サービスの順序」を選択します。
f:id:bearmini:20160328161022j:plain
(画像はメニューなどが英語になっていますが日本語でも同様の項目があるはずです)

サービスの順序のリストが出てきますので、Wi-Fi などの通常使いたいものの方が上になるように設定します。(ドラッグアンドドロップで項目を移動させます)
f:id:bearmini:20160328161434j:plain

並び替えたら OK を押して閉じます。

ちなみに上図の私の環境では FOMA L05A xxx というのが 3G モデムです。

以下のサイトの説明にしたがってセットアップしたものになります。

oshiire.to

余談になるかもしれませんが、以下のサイトで説明されている手順が L-05A にも適用できて、CD を毎回 Eject する手間が省けます。

trtr.hatenablog.jp

2. ダイアルアップ時のルーティング設定を追加

/etc/ppp/ip-up という名前のファイルを以下の内容で作成し、所有者: root 、ファイルのパーミッション:755 とします。
(ファイル名が if-up ではなく ip-up であることに注意してください)

#!/bin/sh

/sbin/route add -net 100.64.0.0/10 10.64.64.64

この route コマンドにより、100.64.0.0/10 宛てのパケットを全て SORACOM Airゲートウェイ(10.64.64.64)に向ける設定が行われます。
(ネットワークのアドレスは 100、ゲートウェイのアドレスは 10 で始まることに注意してください)

SORACOM の各サービスは 100.x.x.x というアドレス(ISP Shared Address)にて提供されています。
例えば SORACOM Beam(beam.soracom.io)は 100.127.127.100 というアドレスを持っていますし、SORACOM Airメタデータサービスは 100.127.100.127 というアドレスでアクセスできます。

なお、ここで追加したルーティング設定は、disconnect 時に自動的に消えるようなので明示的に消さなくても良いようです。

これで beam.soracom.io などに ping が通れば成功です。

$ ping beam.soracom.io
PING beam.soracom.io (100.127.127.100): 56 data bytes
64 bytes from 100.127.127.100: icmp_seq=0 ttl=64 time=399.464 ms
64 bytes from 100.127.127.100: icmp_seq=1 ttl=64 time=435.335 ms
64 bytes from 100.127.127.100: icmp_seq=2 ttl=64 time=394.338 ms
  :

万が一設定を失敗していると、SORACOM 宛てのパケットだけでなく全てのトラフィックが SORACOM 経由になってしまって課金が大変なことになってしまう恐れがありますので、ユーザーコンソールを開いて想定外のトラフィックが流れていないか目視で確認したり、イベントハンドラーを設定するなどして通信量を監視するとよいでしょう。

高度な設定としては、SORACOM Endorse へのトラフィックも SORACOM Air 経由にするために、上記スクリプト(/etc/ppp/ip-up)に以下のような設定を入れておくと良いでしょう。

endorse_ip=$( dig +noall +answer endorse.soracom.io | \grep -oE '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' )
/sbin/route add -host $endorse_ip 10.64.64.64

これは、endorse.soracom.io は 100.64.0.0/10 に属するアドレスを持っていないためです。dig コマンドで endorse.soracom.io のアドレスを解決して、そのアドレス宛てのルートを 10.64.64.64 へ向けています。

長時間かかったコマンドの実行完了を bash でも terminal-notifier でお知らせしたい

[2016.02.19 追記]
スクリプトにバグがあったので修正しました
[追記ここまで]

世の中には CLI から OS X の通知を出せる terminal-notifier という素晴らしいツールがありまして、

github.com

これを brew でインストールしたりなんかすると

$ terminal-notifier -message test

とかやるだけで

f:id:bearmini:20160216215515p:plain

こんな感じにお知らせが出ます。

一方、何かコマンドを実行したら結果が出るまでに10分かかるとか1時間かかるとかそういうことってたまにありますよね。

「ビルドを開始したらちょっと休憩しよう」とか「デプロイを開始したらお昼ごはん行ってこよう」とか「これが終わるまで Twitter でも眺めてるか」ってこと、よくあると思います。

休憩したりお昼ごはんに行ってくるだけならだいたい目論見通りの時間で帰ってくることができますが、Twitter やら Facebook やらを見に行ったりしちゃったが最後、コマンドの実行はとっくに終わってるのになかなか帰ってこれなくて気づいたらすごい時間が経ってしまっていた・・・ってこともよくあると思います。

コマンドの実行が完了したらわかりやすく通知してくれればいいのに、と何度も思いました。

調べてみると、zsh では terminal-notifier を使ってそういうことを実現している方がたくさんいらっしゃるようです。

僕も zsh に改宗・・・と一瞬心が揺らぎましたが、bash でもできないかどうか調べてみました。

すると、こんなものを発見。

github.com

説明に書いてあるとおり、zsh の preexec と precmd をエミュレートするものです。
これがあれば、
preexec でタイムスタンプを保存
precmd でそのタイムスタンプと現在時刻の差を調べ、一定以上の時間が経っていたら terminal-notifier で通知を出す
という処理をすれば望んだ処理が実現できそうです。

ということで ~/.bashrc の末尾あたりに以下のようなコードを書いてみました。

[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh
_tn_timestamp=`date +%s`
_tn_cmd=''
preexec() {
    _tn_timestamp=`date +%s`
    _tn_cmd=$1
}
precmd() {
    now=`date +%s`
    dur=$(( $now - $_tn_timestamp ))
    if [[ $_tn_cmd == "" ]]; then
        return
    fi
    if [[ $dur -gt 60 ]]; then
        terminal-notifier -message "Finished: $_tn_cmd"
        echo elapsed time: $dur seconds
    fi
    _tn_cmd=''
}

preexec はコマンド実行直前に呼ばれる関数で、precmd はコマンド完了後(より厳密には、プロンプト表示直前)に呼ばれる関数です。
プロンプトで何も入力せずに Enter だけ押すと preexec が呼ばれずに precmd が呼ばれたりしますのでそれを回避するコードが入ってたりします。

これで、実行開始して 60 秒以上経ってから実行が完了したら通知が表示されるようになりました。

しかし問題もあって、たとえば vim で何かのファイルを編集して 1 分以上経過して戻ってきたら通知が出ちゃったり、ssh で他のホストにログインして 1 分以上作業してからログアウトして戻ってきたりすると通知が出ちゃったりします。
ブラックリスト的に vim とか ssh だったら通知を出さないというような処理も入れる必要があるかもしれません。

今のところは vimssh の後に通知が表示されてもそれほど困ってないので放置してありますが、何か良い解決策をお持ちの方・思いついた方はお知らせいただければと思います。

SORACOM Air が使える IoT 向け基板のまとめ

さて、前回の記事では SORACOM Air が使える USB 3G/LTE モデムや Wi-Fi ルータをまとめましたが、今回はより IoT に特化した基板で SORACOM Air が使えるもの(動作報告がネット上で見つかったもの)をまとめてみたいと思います。例によって動作保証ではありませんのでそのあたりはご理解ください。

また記載した情報が間違っている可能性もあります。お気づきのことがありましたらコメント等でお知らせください。

続きを読む

SORACOM Air が使える USB 3G/LTE モデム、WiFi ルーターのまとめ

SORACOM Air とは、ひとことで言うと IoT (Internet of Things) 向けの SIM です。
API で通信速度のコントロールができたり、データ通信量の情報を取得できたりする特徴があります。

SORACOM Airdocomo の MVNO の SIM なので、docomo 端末もしくは SIM フリー端末で使えるはずです。
スマホでも使えるみたいですが、ここでは IoT の実験をするときの本命として Raspberry Pi との組み合わせで使いやすい、USB モデム(USB ドングル)、WiFi ルーターをメインにまとめてみたいと思います。

以下、ネット上で動作報告があったデバイスを紹介していきますが、動作保証ではありませんのでそのあたりはご理解ください。
また記載した情報が間違っている可能性もあります。お気づきのことがありましたらコメント等でお知らせください。

文中で記載している価格は 2015年12月30日時点のものです。

続きを読む

Go で DynamoDB Local を使った時にいろいろハマったのでメモ

AWS 公式の Go 言語用 SDK がありますが、Developer Preview ということもあってかドキュメントがちょっと不足しているように思います。

github.com


私は Go のプログラムから DynamoDB を使いたかったのですが、検索するときのキーの指定の仕方とかがだいぶ特殊な感じだったので最初は苦労しましたが、とはいえ、AWS のマネージドサービスとしての DynamoDB を使う分には検索したりすれば多少情報が出てきますのでなんとかなります。

しかし DynamoDB Local を使うとなるとまったく情報がなく、だいぶつまづきました。

以下、いくつかハマったところと解決方法をメモしておきます。

1. 接続先として Endpoint を指定する必要がある

var ac aws.Config
ac.Endpoint = aws.String("hostname:port") 

という感じで DynamoDB Local が動いているアドレスを指定します。
これを指定しないと AWS の DynamoDB に接続しに行ってしまいます。

2. Region を指定する必要がある

これはたしか指定しないとエラーが起きていたはずなので、エラーメッセージにしたがって Region を指定しましょう。

DynamoDB Local ではリージョンとか関係ないはずなのですが、なんでも良いので指定する必要があります。

ac.Region = aws.String("ap-northeast-1")

という感じです。

3. SSL を Disable する必要がある

これはよくよく考えたら当然なのですが、DynamoDB Local には証明書とかを入れてないので SSL なしで接続します。

ac.DisableSSL = aws.Bool(true)

を設定します。


ここまできて、ようやく DynamoDB Local に接続できるようになったはずですが、もう一つ注意点があります。

4. 正しい Credentials を指定する必要がある

私の場合は、DynamoDB Local を Docker コンテナ上で実行しており、その DynamoDB Local に aws コマンドを使ってテスト用のデータを populate する際に、ダミーでもよいので AWS の Credentials 情報(~/.aws/credentials)が存在していないといけなかったので

[default]
aws_access_key_id = dummy
aws_secret_access_key = dummy

という内容のファイルを作成していました。

そしてその populate したデータを Go のプログラムから参照しようとすると、これと同じ内容を aws.Config.Credentials に設定しておかないといけませんでした。
(さもなければ、作ったはずのテーブルが存在しないというエラーになったりします)

ac.Credentials = credentials.NewStaticCredentials("dummy", "dummy", "dummy")

(第3引数の token は指定しなくても良さそうでしたが入れてみました)

これは DynamoDB Local には接続できているのにデータが見えないという挙動になるので、すごく悩みました。

なお、AWS 上の DynamoDB に接続するときは EC2 Instance Role を使ったので Credentials を指定する必要がありませんでした。


Amazon Web Services クラウドデザインパターン設計ガイド 改訂版

Amazon Web Services クラウドデザインパターン設計ガイド 改訂版

最近のCygwinでbashのプロンプトにgitのブランチ名を表示する方法

以前はgit-completionパッケージをインストールして/etc/bash_completionをsourceすればよかっただけのような気がするのですが、最近はこれだとgitコマンドの補完は効くけどプロンプトに表示する__git_ps1が定義されていないようです。

解決策としては、GitHub上のgitのリポジトリにある/contrib/completion/git-prompt.shを使う必要があるようです。

GitHub - git/git: Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.

リポジトリごとcloneして定期的に最新に追随するもよし、Rawファイルをダウンロードしてきてどこか適当なところにおいて使うもよしです。

git-prompt.shの使い方はファイルの中を見るとコメントで懇切丁寧に書かれていますので難しくないと思います。
zshでも同じファイルが使えるようです。


15時間でわかるGit集中講座

15時間でわかるGit集中講座

ドライブレコーダー Transcend D200 をコストコで購入

前から欲しかったドライブレコーダー
Transcendの製品が安い割に評判が良かったようなので買うならTranscendにしようと思っていたところ、コストコで税込み11,800円で売られているのを発見。当時の価格.comの最安値よりも1,000円ほど安かったので購入を決断。

取り付けは簡単にできましたが、最初に取り付けた位置がルームミラーに近すぎて干渉してしまったので、強力な両面テープを頑張って剥がして再度位置をちゃんと調節して取り付けし直すハメになりました。(製品は何も悪くありません。私が間抜けだっただけです)

私の車は比較的大きい方ですが、電源配線はAピラーやダッシュボードの下あたりを通してコンソールパネル付近のシガーソケットまで充分に届く長さのものが付属していました。むしろ小さい車だと長すぎてだいぶ余るかもしれません。

車のシガーソケットにもともと FM トランスミッタを装着していたので、それも同時に使うにはシガーソケットの分配器が必要でした。
分配器ももともと持っていたのですが使っていなかったので、これを期に引っ張り出してきて有効活用しました。
(↓は私の持ってるのとは違うけど、イマドキな感じならスマホの充電などに便利な USB ポート付きを買うといいと思います。)

D200 のセットアップは簡単にできました。
D200 自体が WiFi アクセスポイントになってスマホと接続してスマホに映像をダウンロードできたりします。WiFiSSID とパスワードはデフォルトのままだと恥ずかしいのでさっそく変更しました。

私の車ではシガーソケットの電源はエンジンと連動しているので、エンジンを掛けると録画が開始され、エンジンを切ると録画終了です。説明書にも書いてありましたが、車種によってはここが連動してないこともあるらしいのでバッテリ上がりにご注意。

スマホに専用アプリをダウンロードすると、ドライブレコーダーのカメラ映像をライブビューをしたりできます。

少しドライブして、ちゃんと録画出来ているかどうか確認します。

録画した動画を先ほどインストールしたアプリでスマホにダウンロードできたりしますが、WiFI 経由でのダウンロードは結構時間がかかります。それにスマホの記憶領域を消費します。しかも D200 に電源を供給した状態でそういったことをしないといけないので、エンジンを掛けたままだとガソリンがもったいないし、エンジンを切ったままアクセサリーだけONにして使っているとなんとなくバッテリーが心配です。大したことないのかもしれないけど。そんなわけで、ちょっとだけスマホ連携を試したら D200 から SD カードを抜いて自宅の PC で動画を再生することにしました。

動画ファイルは1分ごとに別ファイルとなっており、SD カードの領域がいっぱいになったら古い方のファイルから順番に消されていくようです。
最初から付属していた SD カードは 16 GB だったと思いますが、1分で大体 100MB 以上消費するようなので録画できる時間は2時間強といったところでしょうか。
画質のモードを変えたりしたらもっと長時間撮れるかもしれません。

ファイルが1分ごとに細切れになっているので、連続再生するには VLC を使うと便利です。
VLC はあるフォルダに入っている動画を連続再生する機能を持っていますのでそれを利用して再生します。

ドライブレコーダーの映像が必要になるような事故などのシーンには出会いたくありませんが、近頃はドライブレコーダーでたまたま撮れたおもしろ映像とか貴重なシーンなどがたくさんあるようなので、そういう映像が撮れるといいなと思います。

$0書き換えが流行っているようなので一つ流行に乗っかってみるか

以下の記事では $0 での偽装を見破るため ps コマンドに c オプションを指定して /proc/<pid>/commを表示させればよいというようなことが書いてあると思いますが、/proc/<pid>/commも容易に書き換え可能みたいですのであまりあてにしないほうが良いでしょう。(偽装されていないかどうか知りたい場合)


細かすぎて伝わらないPerlと$0変数 - コマンド名偽装 - ろば電子が詰まっている


/procファイルシステムについて解説した以下のドキュメントを読むと、
https://www.kernel.org/doc/Documentation/filesystems/proc.txt

3.6	/proc/<pid>/comm  & /proc/<pid>/task/<tid>/comm
--------------------------------------------------------
These files provide a method to access a tasks comm value. It also allows for
a task to set its own or one of its thread siblings comm value. The comm value
is limited in size compared to the cmdline value, so writing anything longer
then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated
comm value.

だそうです。 It also allows for a task to set its own or one of its thread siblings comm value. つまり、/proc/<pid>/commは書き込み可能だということ。

実際、

$ echo $$
8837
$ ls -l /proc/$$/comm
-rw-r--r-- 1 xxxx xxxx 0  Jan 16 14:58 /proc/8837/comm  # <- ownerは書き込み可能
$ cat /proc/$$/comm
bash
$ ps c
  PID TTY      STAT   TIME COMMAND
 8837 pts/1    Ss     0:00 bash
 8906 pts/1    R+     0:00 ps
$ ps x | \grep $$
 8837 pts/1    Ss     0:00 bash
 8912 pts/1    S+     0:00 grep 8837
$ echo -n 'hoge' > /proc/$$/comm        # <- 書き換えてみる
$ cat /proc/$$/comm
hoge                                    # <- はい書き換わったー
$ ps c
  PID TTY      STAT   TIME COMMAND
 8837 pts/1    Ss     0:00 hoge         # <- 偽装されている (/proc/<pid>/commに設定した値が表示されている)
 8926 pts/1    R+     0:00 ps
$ ps x | \grep $$
 8837 pts/1    Ss     0:00 bash         # <- こちらは $0 で偽装可能なほう
 8932 pts/1    S+     0:00 grep 8837

ということで、/proc/<pid>/comm/proc/<pid>/cmdline も偽装されるので良い子のみんなは使っちゃダメだよ、ということになる。



上記ブログでは pstree を使えば /proc/<pid>/statを見るので安全って書いてたけど

$ cat /proc/$$/stat
8059 (hoge) S 5118 8059 8059 34847 8549 4218880 4300 26818 0 5 6 4 27 40 20 0 1 0 27809766 29687808 1731 18446744073709551615 4194304 5184116 140734649026160 140734649024840 139834224170140 0 65536 3670020 1266777851 18446744071579312278 0 0 17 0 0 0 0 0 0 7282160 7319112 34164736 140734649034557 140734649034562 140734649034562 140734649036782 0
$ pstree | \grep hoge
     |         |         |         |                |-hoge-+-grep

どう見ても書き換えられてます。

じゃあ解決策はないのかというと、ぱっと思いついたところだと

$ file /proc/$$/exe
/proc/8059/exe: symbolic link to `/bin/bash'

という感じで/proc/<pid>/exeを見るしかないかなぁ。
これもなにか回避策がありそうだけど。


ちなみにこちらの環境は

$ uname -s -r -v -m -p -i -o
Linux 3.16.0-28-generic #38-Ubuntu SMP Fri Dec 12 17:37:40 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.10
DISTRIB_CODENAME=utopic
DISTRIB_DESCRIPTION="Ubuntu 14.10"

こんな感じです。

現場からは以上です。

Intel Edison の Ubilinux をシングルユーザモードで起動する方法

Intel EdisonをUbilinuxに入れ替えて遊んでいたら、起動スクリプトの書き方を間違えたせいでEdisonが起動しなくなってしまいました。

Intel Edison Kit for Arduino

Intel Edison Kit for Arduino


正確には、途中までは起動するのですが起動途中でブロックしてしまうようになり、しばらく経つとWatchdogが発動してリセットされてしまうようになりました。

ログインプロンプトも出てこないしsshdが起動する前にブロックしてしまっているようなのでログインすることができません。なので修復もできない・・・!
こういうときは焦らずにシングルユーザモードですね。

しかし、ubootでシングルユーザモードってどうやるんだろう・・・(汗)

以下の手順は、試行錯誤のすえに見つけ出したシングルユーザモードに到達する手順です。

続きを読む

Intel Edison に InfluxDB をインストールする方法

http://influxdb.com/download/から最新版をダウンロードします。
Go もインストールしてあるのでソースからビルドしても良いかと思ったのですが、意外とビルド方法が難しそうだったので linux/386 版のバイナリパッケージを利用することにしました。

パッケージをダウンロードしたら、それを /home/root/opt/influxdb 以下に展開します。
(Edison は / 以下は容量が少ないので、容量の多い /home 以下にダウンロードして展開する必要があります。また、あとで設定ファイルを編集する手間のことを考えると ~~/opt/influxdb というディレクトリになるようにしておいたほうが良いと思います。ということで私は /home/root/opt/influxdb 以下に展開しました。)

展開したら、以下の様なツリー構造になります。

~/opt/influxdb# tree
.
|-- benchmark_config.toml
|-- config.toml
|-- influxdb
|-- influxdb-benchmark
|-- scripts
|   |-- influxdb-daemon.sh
|   |-- init.sh
|   `-- post_install.sh
`-- shared
    |-- data
    |   |-- db
    |   |   `-- shard_db_v2
    |   |-- raft
    |   |   |-- conf
    |   |   |-- log
    |   |   |-- name
    |   |   `-- snapshot
    |   `-- wal
    |       `-- bookmark
    `-- log.txt

(tree コマンドは The Tree Command for Linux Homepage からダウンロードして make して使用しました)


展開したら、influxdb という実行ファイルがあるのでそれを実行してみましょう。
おそらく、libbz2.so.1 が見つからないとかでエラーになってしまうはずです。

ldd コマンドで確認してみても、

# ldd influxdb
	linux-gate.so.1 (0xb777f000)
	librt.so.1 => /lib/librt.so.1 (0x41815000)
	libm.so.6 => /lib/libm.so.6 (0x417c6000)
	libz.so.1 => /lib/libz.so.1 (0x417ae000)
	libbz2.so.1 => not found
	libpthread.so.0 => /lib/libpthread.so.0 (0x41790000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x41a3f000)
	libc.so.6 => /lib/libc.so.6 (0x41618000)
	/lib/ld-linux.so.2 (0x415e9000)

という具合に not found になっています。

Edison には opkg で bzip2 や libbz2 などがすでにインストールされていたのですが、find コマンドで検索してみても libbz2.so.1 というファイルは見つかりません。

bzip2 コマンドは正常に動作しているので libbz2 はインストールされているはずなのですが、、、

試しに bzip2 コマンドを ldd で確認してみると

# ldd /usr/bin/bzip2
	linux-gate.so.1 (0xb773c000)
	libbz2.so.0 => /usr/lib/libbz2.so.0 (0x41b48000)
	libc.so.6 => /lib/libc.so.6 (0x41618000)
	/lib/ld-linux.so.2 (0x415e9000)

となっていましたので、どうやら libbz2.so.0 は存在しますが libbz2.so.1 が存在しないようです。

仕方がないので古いバージョンの libbz2.so.0 で新しいバージョンの libbz2.so.1 を肩代わりさせてみましょう・・・

# ls -la /usr/lib/libbz2.so*
lrwxrwxrwx    1 root     root            15 Oct 14 13:32 libbz2.so -> libbz2.so.0.0.0
lrwxrwxrwx    1 root     root            15 Oct 14 13:32 libbz2.so.0 -> libbz2.so.0.0.0
-rwxr-xr-x    1 root     root         76100 Oct  9 09:11 libbz2.so.0.0.0
# cd /usr/lib && ln -s libbz2.so.0.0.0 libbz2.so.1
# ls -la /usr/lib/libbz2.so*
lrwxrwxrwx    1 root     root            15 Oct 14 13:32 /usr/lib/libbz2.so -> libbz2.so.0.0.0
lrwxrwxrwx    1 root     root            15 Oct 14 13:32 /usr/lib/libbz2.so.0 -> libbz2.so.0.0.0
-rwxr-xr-x    1 root     root         76100 Oct  9 09:11 /usr/lib/libbz2.so.0.0.0
lrwxrwxrwx    1 root     root            15 Dec 25 09:31 /usr/lib/libbz2.so.1 -> libbz2.so.0.0.0

influxdb を展開したディレクトリに戻り、

# influxdb
Couldn't parse configuration file: config.sample.toml
[12/25/14 09:31:56] [INFO] Loading configuration file config.sample.toml
open config.sample.toml: no such file or directory

一応動きました・・・が、これがちゃんと期待通りに動くという保証はありません。
それに、config.sample.toml というファイルが見つからないというエラーになってしまいました。

そこで、config ファイルを用意します。

influxdb の実行ファイルと同じディレクトリに config.toml というファイルがありますので、これを開いて編集し、ファイルの内容で /opt/influxdb/〜〜 というパスになっている箇所をすべて /home/root/opt/influxdb/〜〜 に書き換えます。(/home/root を付け加える)

編集したら、以下のように config ファイルをオプションで指定して起動します。

~/opt/influxdb# ./influxdb -config ./config.toml
[12/28/14 14:36:42] [INFO] Loading configuration file ./config.toml

+---------------------------------------------+
|  _____        __ _            _____  ____   |
| |_   _|      / _| |          |  __ \|  _ \  |
|   | |  _ __ | |_| |_   ___  _| |  | | |_) | |
|   | | | '_ \|  _| | | | \ \/ / |  | |  _ <  |
|  _| |_| | | | | | | |_| |>  <| |__| | |_) | |
| |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/  |
+---------------------------------------------+

上記のようにロゴのバナーが現れたら成功です。

この状態で Web ブラウザを開、Edison のアドレスの 8083 番ポートにアクセスしてみましょう。
f:id:bearmini:20141229002521p:plain

このような管理画面が現れれば成功です。
あとは Series にデータを追加したりしていきましょう。

Intel Edison で動かした Arduino のスケッチを停止・削除する方法

Edison を入手して、「"Lチカ" してみました!」という記事は世の中に履いて捨てるほどありますが、じゃあそのアップロードしたプログラムを消去したい場合はどうすればよいの?と思って調べてみるも、なかなか第一次情報ソースに行き当たりません。

Intel Edison Kit for Arduino

Intel Edison Kit for Arduino

ですが、Edison のコンソールに接続して top コマンドなどを見るとすぐにどうすればよいかがわかります。

/sketch/sketch.elf というファイルが実行されており、CPUを多少消費しているではありませんか。
すぐにそのプロセスを kill して、/sketch/sketch.elf を削除(ついでに/sketch/sketch.elf.old というファイルもあったので削除)しました。

本当にこの方法で良いかどうかはわかりませんが、とりあえず大丈夫そうです。


空のスケッチを書き込めば良いと書いていた記事もありましたが、それをやってみたところ /sketch/sketch.elf の CPU 使用率が50% になってしまいました!
これは、Edison の持っている 2 つの CPU コアのうち 1 つを無駄に空の無限ループで使いきってしまっているということを意味します。空のスケッチを実行するということはそういうことになりますよね。
ということでこの方法は使えません。

Intel Edison に Go をインストールする方法

Go はクロスコンパイルが簡単で、出来上がったバイナリの配布も簡単なので、わざわざ Edison 上で Go コンパイラを動かす必要もないのですが、、、
やってみたかったからやってみただけです。

Intel Edison Kit for Arduino

Intel Edison Kit for Arduino


大まかに分けて以下の3ステップでインストールを行います。
Edison 自体のセットアップは終わっているという人は 0. は飛ばして 1. からやってください。

0. Edison 自体のセットアップ
1. 依存パッケージのインストール
2. Go のインストール

0. Edison 自体のセットアップ

Edison のセットアップは、組み込み機器と考えるとかなりラクな方で、

公式サイト


スタートアップ Intel Edison - Qiita

Kindle 本 The Hands-on Intel Edison Manual Lab (English Edition)

The Hands-on Intel Edison Manual Lab (English Edition)

The Hands-on Intel Edison Manual Lab (English Edition)

あたりの手順にしたがってセットアップすれば特に難しいことはないと思います。

私の環境は Windows だったので、まずは PC にドライバをインストールして、USB ケーブル2本を Edison に接続(一本は電源供給+USBメモリのようなデバイスとして見るため、もう一本はUSBシリアルでコンソールにつなぐため)、最新版のファームウェアに更新します。

ファームウェアの更新方法はいたって簡単で、Edison と PC を USB で接続、Edison という名前の外付けドライブとして見えますのでそこに Intel のサイトからダウンロードしてきた最新版のファームを展開し、シリアルコンソールから

$ reboot ota

というコマンドを実行してしばらく待つのみです。

Edison が勝手に再起動したらファームが最新版になってるはずなので、同じくシリアルコンソールで

$ cat /etc/version
$ configure_edison --version

などで確認します。

最後に

$ configure_edison --setup

を実行して、ホスト名/root のパスワード/WiFi 接続 のセットアップを行います。

この時点で nodejs とか python とかが使える状態です。
PC から Edison に ssh で接続もできるはずです。
(名前解決に mDNS を使うので、Windows であれば iTunes をインストールする必要があるかもしれません。iTunes 本体は不要なのですが、一緒にインストールされる Bonjour が必要です。)

以下の作業は ssh 経由でもシリアルコンソールでもどちらで実施しても構わないと思います。

1. 依存パッケージのインストール

Go をソースからビルドしてインストールするには bash スクリプトを動かす必要があるのですが、bash はデフォルトでは Edison にインストールされていません。 (標準では ash というシェルがインストールされ使われているようです)
Edison には opkg というパッケージマネージャが用意されていますのでそれを用いてインストールします。

ということで、まずは opkg 自体をセットアップします。opkg コマンド自体は最初からインストールされていますが、opkg が参照するリポジトリの設定をする必要があります。
以下の2つのファイルを編集して(なければ作成して)以下のような内容にします。

/etc/opkg/base-feeds.conf

src/gz all http://repo.opkg.net/edison/repo/all
src/gz edison http://repo.opkg.net/edison/repo/edison
src/gz core2-32 http://repo.opkg.net/edison/repo/core2-32

/etc/opkg/intel-iotdk.conf

src intel-iotdk http://iotdk.intel.com/repos/1.1/intelgalactic
src intel-all http://iotdk.intel.com/repos/1.1/iotdk/all
src intel-i586 http://iotdk.intel.com/repos/1.1/iotdk/i586
src intel-x86 http://iotdk.intel.com/repos/1.1/iotdk/x86

以下のコマンドを実行します。

$ opkg update
$ opkg upgrade
$ opkg install bash

2. Go をインストール

まず Go のソース(linux/386)をダウンロードします。
Edisonは / の空き容量が少ないため、空き容量の大きい /home 以下で作業を行う必要があります。
ダウンロード先もインストール先も /home 以下にする必要があります。(以下の例では /home/root にダウンロードして /home/root/go に展開・インストールされます)

$ cd /home/root
$ wget https://storage.googleapis.com/golang/go1.4.linux-386.tar.gz
$ tar xzf go1.4.linux-386.tar.gz

この記事を書いた時点では 1.4 が最新なので上記のファイル名になります。新しいバージョンがでたら新しいバージョンで適宜読み替えてください。

Go のビルドを行います。

$ cd go/src
$ ./make.bash

ビルドに成功したら、あとはパスを通して・・・

$ vi ~/.profile
export PATH=$PATH:~/go/bin
$ . .profile

go コマンドを実行します。

$ go version
go version go1.4 linux/386

Android L Preview のデバイスで Heads-up Notification を表示する方法

注:この記事は 2014年 7 月上旬現在の Android L Preview の ROM イメージおよび SDK の内容に基づいて書かれています。Android L が正式バージョンとしてリリースされるまでの間に、この記事の内容は obsolete になるかもしれません。


Android L Preview では新しい通知の種類として Heads-up Notification が追加されました。
Heads-up Notification についての詳細は以下のページ内で "Heads-up Notification" を検索してみてください。
https://developer.android.com/preview/notifications.html

さて、この Heads-up Notification は電話着信時に出ることがわかっていますが、自分のアプリからも出したい場合どうすればよいかということがまだ公式のドキュメントには書かれていないようです。
いろいろやって調べた結果、そもそも必要な定数が @hide されていたり API リファレンスに載っているメソッド名が間違っていたりしたので大変でしたが 自分のアプリから Heads-up Notification を出すことができましたのでその方法を紹介します。

手順としては、以下の様な感じになります。

  1. 実行環境の API Level から、そもそも Heads-up Notification を出せるかどうかを調べる。
  2. Notification.Builder で Notification を構築する。このとき、設定しなければならないパラメータに一定の決まりがある。
  3. NotificationManager で表示する。

大事なのは、Notification を構築するときに与えるオプションですね。
今のところ、Notification.Builder で以下のメソッドの呼び出しが必須であることがわかっています。

  • 通常の Notification を出すために最低限必要なオプション
    • setContentTitle()
    • setContentText()
    • setSmallIcon()
  • Heads-up Notification を出すために最低限必要なオプション
    • setPriority()
    • setFullScreenIntent()
    • setOngoing()
    • setExtras()

この中で、手強いのは setPriority() と setExtras() です。setFullScreenIntent() に指定するのは空のインテントでも良いようです。

まず、setPriority() には Notification.PRIORITY_HIGH を指定する必要があるのですが、どうも Eclipse ADT で開発しているとこのような値は認識されていないようでビルドできません。SDK も ADT も最新バージョン(r23.0.2)に上げているのですが・・・
仕方ないので AOSP のソースを見るとその値が 1 であることがわかるのでそれを直接指定します。

次に setExtras() ですが、これはこのようなメソッドは無いと言われますのでリフレクションで呼び出します。(ちなみに、API リファレンスには addExtras() という違う名前のメソッドが載っています。これも Eclipse からは認識されていません)
setExtras() の引数には Bundle を指定します。Bundle の中身としては、Notification.EXTRA_AS_HEADS_UP をキーとして int 型の値 Notification.HEADS_UP_REQUESTED を指定します。しかし、これらの値もお察しの通り存在しないと言われてしまいます(これは AOSP を見ると @hide が指定されているので明示的に隠されています)のでこれまた AOSP のソースを見てそれぞれ "headsup" および 2 という値を知り、それらを直接指定します。

@SuppressLint("NewApi")
private void showHeadsupNotification(int id) {
    if (Build.VERSION.SDK_INT < 20) {
        Log.i(TAG, "Heads-up Notification is not supported.");
        return;
    }

    Bundle b = new Bundle();
    b.putInt(/* Notification.EXTRA_AS_HEADS_UP */"headsup", /* HEADS_UP_REQUESTED */2);
    Notification.Builder nb = new Notification.Builder(getApplicationContext());
    try {
        Method m = Notification.Builder.class.getMethod("setExtras", Bundle.class);
        m.invoke(nb, b);
    } catch (NoSuchMethodException e) {
        Log.e(TAG, e.getMessage(), e);
    } catch (IllegalArgumentException e) {
        Log.e(TAG, e.getMessage(), e);
    } catch (IllegalAccessException e) {
        Log.e(TAG, e.getMessage(), e);
    } catch (InvocationTargetException e) {
        Log.e(TAG, e.getMessage(), e);
    }

    Notification n = nb
            .setContentTitle("Test Title " + Integer.toString(id))
            .setContentText("test test test")
            .setSmallIcon(R.drawable.ic_launcher)
            .setPriority(1 /* Notification.PRIORITY_HiGH */)
            .setAutoCancel(true)
            .setFullScreenIntent(
                    PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), 0),
                    true).setOngoing(true).build();
    NotificationManager nm = (NotificationManager) getApplicationContext().getSystemService(
            Context.NOTIFICATION_SERVICE);
    nm.notify(id, n);
}    

setExtras() を呼ぶところが不必要に複雑に見えますが、それ以外は特に難しいことはありません。

上記の関数を呼んで表示させた Heads-up Notification がこちら:
f:id:bearmini:20140711152303p:plain


Heads-up Notification は同時に表示されるのは 1 つだけで、あとから表示したほうが勝つようです。(先に表示されていたものは、ステータスバーに引っ込みます)

たとえば電話がかかってきて着信の Heads-up Notification が表示されているときに自分のアプリから Heads-up Notification を出すと、着信のほうが消えて(ステータスバーに格納されて)自分のものが表示されます。

自分のアプリ内で2個以上出そうとしても同様です。最後に表示したものだけが表示されています。
プルダウンするとすべての通知を見ることができます。


ちなみに Android L Preview は Nexus 5 に入れて試しました。


Vim で数のインクリメントやデクリメントをするキーバインド

Vim には Ctrl-A (以後 C-a) を押すとその時カーソルの下にある数をインクリメントしてくれるというプログラマに嬉しいキーバインドがあります。(C-x でデクリメント)

これはたとえば 1 という文字の上で C-a を押すとその文字が 2 になり、続けて押していくと 3, 4, ... と増えていきます。9 の上で C-a を押すと 10 になり、続けて押していくと 11, 12, ... となります。また、3C-a と押すと一気に 3 増やしてくれます。なかなか賢いですね。

それから、-1 の上で C-a を押すと -2 ではなく 0 になるということに今日気づきました。

というのも、1−2 みたいなテキストの上で、2 を 3 に増やそうとして C-a を押したら 1-1 になったのでびっくりして気づいたわけです。(ちなみにそのまま C-a を押し続けると、1-2 => 1-1 => 10 => 11 ってなりました)

あまり内容が無いですが、ちょっと面白かったので書いてみました。

Vim 使いなら誰もが通る道なのかな。