2015年10月30日金曜日

RaspberryPi に WringPi をインストール

概要

WringPi とは RaspberryPi 上の GPIO を簡単に扱うためのツールです

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 8.0 (Jessie)
  • Kernel Version 4.1.7+

インストール方法

  • sudo apt-get install libi2c-dev
  • cd work
  • git clone git://git.drogon.net/wiringPi
  • cd wiringPi/
  • ./build

試す

  • gpio -g mode 24 out
  • gpio -g write 24 1
  • gpio -g read 24
  • gpio -g write 24 0

「-g」オプションで論理 PIN 番号 (BCM-GPIO) 指定ができて
「-1」オプションで物理 PIN 番号 指定ができるみたいです
つまり

  • gpio -g write 24 1
  • gpio -1 write 18 1

は同じことになります
終了する場合は

  • gpio unexport 24

あとの細かい使い方は help か公式 を見てください

参考サイト

2015年10月29日木曜日

gatttool を使って SensorTag CC2650 の KeyPressState の Notification を受信してみた

概要

bluez の gatttool と SensorTag CC2650 を使って SensorTag 側のボタンが押されたことを gatttool 側で受信してみました
たぶんこんなニッチな記事を日本語で書いているのはこれくらいだと思う、、、

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 8.0 (Jessie)
  • Kernel Version 4.1.7+
  • BlueZ 5.23-2+b1

事前作業

RaspberryPi の構築 や bluez のインストール を実施して gatttool が使えるようになるようにしてください

そもそも notification とは

Bluetooth Low Energy のデバイスから情報 (GATT) を読み込みするための方法の 1 つです
読み込みするには、他に read という方法がありこれはデバイスに対して直接データを読み込みにいく方法です
対して notification はデバイス側からデータをプッシュすることで受け取り側にデータを読みこませる方法です

notification のポイントとしては初めにデバイス側に notification の受信要求を実施させる必要がある点です
この受信要求はどうやっているかと言うとデバイス側のある書き込み可能領域に 0 or 1 のフラグを書き込みます
書き込みに成功すると書き込んだ側に対して初めて notification を送信することができます

  • read
    enter image description here

  • notification
    enter image description here

gatttool で notification の受信

前置きが長くなりましたが試していきます
まずは SensorTag の電源を ON にして connection 待機状態 (Advertising) にしましょう
CC2650 であれば緑の LED が点灯すれば OK です

では gatttool で接続していきます
コマンドは以下の通りです

  • gatttool -t public -b xx:xx:xx:xx:xx:xx --char-write-req --handle=0x4a --value=0100 --listen

「-b」のあとには Mac アドレスが入るので持っている SensorTag の Mac アドレスを入力してください
その他のパラメータはそのまま使ってください

簡単に説明すると --char-write-req で notification のための書き込み要求をしています
--handle で書き込みをするアドレスを指定して、そのアドレスに--value で書き込む値を指定します
最後に --listen することで書き込み後にデバイスからの notification を待つようにしています

コマンドを実行すると以下のように書き込みが成功した旨が表示されます

Characteristic value was written successfully

これが表示されれば notification を受け取る準備ができました
SensorTag の横にある (電源とは逆の方向にある) ボタンを押してみましょう
すると以下のようにボタンが押されたイベントを受信することができると思います

Notification handle = 0x0049 value: 01
Notification handle = 0x0049 value: 00

gatttool の場合は handle と value が表示されるだけのようです
0x0049 はボタンが押されたときの状態を管理するアドレスです
value の 00, 01 はそれぞれ「ボタンから離れた時の状態」「ボタンが押された時の状態」になります
長押ししてから話すと状態の遷移の様子がよくわかると思います

そもそも、その handler が書き込めるってどうやって発見したんだ

notification の仕組み自体を理解するまでも大変でしたが、0x0049 のハンドラに書き込みを行うことでなぜボタンを押したイベントを notification で受け取れるのか・・・
ということをどうやって知ったかですが正直いろいろ調べて試しました
その経験上こうやってやると、うまく調べられるという方法も紹介します

まず BLE 機器には「ここのこのアドレスに read するとこんな値が取れるよ」というアドレス一覧表みたいなのがあります
SensorTag の一覧表は以下になります
http://processors.wiki.ti.com/images/a/a8/BLE_SensorTag_GATT_Server.pdf

SensorTag に触ったことがある人であればこの表は一度は見たことがあると思います
で、実はこの表は CC2650 には完全に当てはまりません
例えば 0x73 というハンドラは表で見ると「Test Config」とあって RW で書き込めるはずですが、実際に書き込んでみると書き込めません

ではハンドラを探す方法ですがまずこの表の中で「Key Press State」を管理している UUID を探します
すると UUID は「0xFFE1」だということがわかります
find_key_press.png

そしてその下に「Client Characteristic Configuration」が RW で存在していると思います
Client Characteristic Configuration はクライアントが書き込み可能な領域として定義されているものです
そしてその Client Characteristic Configuration の UUID を見てみると「0x2902」だということがわかります
※もしかしたら UUID も SensorTag の型で違う可能性がありますが、経験上 UUID は他の型でも同じ場合が多いです

とりあえずこの UUID を覚えておきましょう
次に primary コマンドを使って SensorTag が持つサービスの一覧を表示します
その中で Key Press State を管理するサービスを探します

attr handle: 0x0047, end grp handle: 0x004b uuid: 0000ffe0-0000-1000-8000-00805f9b34fb

「これが何で Key Press State のサービスってわかるんだ」と思う方もいると思いますが、先ほどの表で「ffe0」で検索すると「Simple Key Service」というのがあると思います
「ffe0」はどこから持ってきたかというと primary コマンドで、ずらっと表示された中に uuid が 0000ffe0 で始まるものを探しました

サービスがわかったら、このサービスが持つハンドラの範囲 (0x0047 - 0x004b) に存在する UUID を更に調べます
調べるには char-desc というコマンドを使います

  • char-desc 0x47 0x4b

すると以下のような結果が返ってくると思います

handle: 0x0047, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0048, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0049, uuid: 0000ffe1-0000-1000-8000-00805f9b34fb
handle: 0x004a, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x004b, uuid: 00002901-0000-1000-8000-00805f9b34fb

この中に先ほど調べた「Client Characteristic Configuration」の uuid 「0x2902」があり、そのハンドラを見ると「0x004a」だということがわかります
また、「0x0049」というハンドラが notification 受信時に出力されたハンドラと一致することも確認できると思います

表と照らしあわせてみると分かりますが、表のハンドラは「0x6A」であるのに対して調べてみたわかったハンドラは「0x4A」でやはり CC2650 は表と違うことがわかると思います

最後に

BLE の情報は Web で探してもなかなか見つからず、解決するのに時間と根性をかなり費やすとつくづく感じさせられます

2015年10月27日火曜日

bluetoothctl と expect で無線キーボードに定期的に接続するスクリプト

概要

RaspberryPi に無線キーボードの設定をしたあとで無線キーボードからの入力が一定時間ないと bluetooth が切断されてしまう現象が発生しました
切断のたびに bluetoothctl コマンドを実行するのは面倒なので、cron を使って一定間隔で bluetoothctl を実行させるようにしてみました

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 8.0 (Jessie)
  • Kernel Version 4.1.10
  • expect 5.45

スクリプト

とりあえず expect スクリプトの全貌です

#!/usr/bin/expect -f

set timemout 5
set prompt "#"
spawn sudo bluetoothctl -a
expect -re $prompt
send "connect xx:xx:xx:xx:xx:xx\r"
expect -re $prompt
send "quit\r"
expect eof

Mac アドレスの部分は接続する無線キーボードの Mac アドレスを入力してください

デプロイする

pi ユーザで実行しています

  • cd
  • mkdir script
  • cd script
  • touch connect_keyboard.sh
    • 上記のスクリプトを記載
  • chmod 755 connect_keyboard.sh
  • crontab -e
    • */1 * * * * /home/pi/script/connect_keyboard.sh

で1分おきに connect の命令が実行されます
切断されたキーボード側をペアリング状態にしておけば5分以内には再接続されて使えるようになるはずです

Tips

postfix のインストール

postfix がインストールされていない場合 cron のログに以下のようなエラーが出てうまく cron が動かないことがあります

CRON[2369]: (CRON) info (No MTA installed, discarding output)

この場合は素直に postfix をインストールしましょう
途中設定するために config 画面に切り替わりますが、ローカル用で設定すればOKです

  • sudo apt-get -y install postfix

また cron のメールが送られているのが嫌な場合は crontab -e の設定に以下を追記してください

MAILTO=”“

手動でスクリプトを実行する場合

最後の expect eof を interact に書き換えて実行してください
それ用のスクリプトを準備しておくのがいいかもしれません

2015年10月23日金曜日

CentOS に Latex をインストール

概要

Latex で文書を作成できる環境を整備したのでメモしておきます
すごい久しぶりに使った気がします

環境

  • CentOS 6.7 64bit
  • platex 3.141592-p3.1.10
  • dvipdfmx 0.0.31

インストール

  • yum -y install texlive-latex
  • yum -y install texlive-east-asian
  • yum -y install dvipdfmx

texlive-latex で Latex のインストールを実施し
texlive-east-asianplatex というコマンドをインストールしています
platex は Latex 上で日本語を使うために必要なコマンドです
dvipdfmx で platex で作成される dvi ファイルを pdf に変換するコマンドをインストールします

サンプル作成

  • sample.tex
\documentclass[12pt,a4j]{jarticle}

\title{タイトル}
\author{kakakikikeke}
\date{\today}

\begin{document}

\maketitle

\begin{abstract}
概要
\end{abstract}

テスト
\end{document}

\ で始まるものを「コマンド」呼びます
\documentclass は必須コマンドで jarticle というクラスを利用します
他にも jreport や jbook というクラスがあります
jarticle は短めの日本語文書を書くために用意されたクラスです
jrepot はそれよりはちょっと長め、jbook はそれよりも長めで本を書くためのクラスです

\documentclass から\begin{document} までをプリアンブルと呼び、ここでメタ情報の定義や外部スタイルの読み込み ( \usepackage[dvipdfmx]{graphicx} … etc ) などを行います

\begin{document} 内に本文を記載します
\maketitle と記載すると文書冒頭にメタ情報に記載した情報を元にタイトル情報を記載してくれます

\begin{abstract} に概要を記載します

、、、等々いろいろとコマンドがあるので詳細は この辺 を見たり Web で調べてください
「latex + やりたいこと」でググれば大抵は出ると思います

ビルド

tex -> dvi -> pdf という順番でビルドします

  • platex sample.tex

で tex -> dvi が作成され

  • dvipdfmx sample.dvi

で dvi -> pdf が作成されます
あとは pdf を開けばドキュメントを確認することができます
sample_pdf.png

** WARNING ** No character mapping available.

というエラーというか警告が出て日本語が文字化けする場合は .tex ファイルの文字コードを EUC_JP に変更してください

  • nkf -e --overwrite sample.tex

emacsの設定

これはおまけですが、自分は emacs で .tex ファイルを編集するので emacs を使っている方は設定したほうがいいと思うことを紹介します

YaTex (Yet Another TeX mode for Emacs)

という拡張があります
読み方は「やてふ」です
package.el が使えるのであれば「yatex」という拡張をインストールすればOKです

インストールしたら

  • M-x yatex-mode

とすればモードがやてふモードになります
いろいろと機能がありますが自分は補完機能が使いたくてインストールしています

  • Ctrl-c b space で \begin コマンドを補完
  • Ctrl-c space で随時補完

とかとか emacs 上でビルドすることもできます
emacs で Latex を書くなら必須かなと思います

最後に

文書が大規模になればなるほど Latex を使ったほうがいいなと思います
図や表を大量に使う文書で参照が発生する場合は Latex のほうが絶対楽です
図1 と 図2の間に新たに図を入れて、図2以降を全部インクリメントし直して、、、なんて作業が発生したときには発狂しなくてすみます

あとは Latex で作成した文書のほうが体裁が綺麗です
ワードソフトだとどうしても文書の端がずれたり、微妙にフォントが変わったり、文字間隔が変わったりします
ワードマスターとかなら、その辺上手くできるのかもしれませんが、自分はワードの使い方がわからないので、その辺の体裁を気にしなくていいのもメリットかもしれません

デメリットとしては学習コストが高いくらいでしょうか

2015年10月22日木曜日

ニフティクラウドMQTT で WebSocket を使ってみた

概要

ニフティクラウド MQTT には標準で WebSocket が使える機能があるので使ってみました
ブローカを作成しブラウザでメッセージを受信できるところまでやってみました

環境

MQTTブローカ作成

コントロールパネルにログインして作成します

MQTTサーバー作成 -> ダイアログ表示 -> MQTTサーバー名、管理者ユーザー名、管理者パスワードを入力 -> 作成する

で作成完了です

クライアントアプリの作成

WebサーバはなんでもOKです
今回は Apache を想定しています
DocumentRoot に展開しているのでパスは環境に合わせて適宜変更してください

  • cd /var/www/html
  • wget http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.javascript.git/plain/src/mqttws31.js
  • touch index.html
  • emacs index.html
<!DOCTYPE html>
<html>
  <head>
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
  <script src="mqttws31.js" type="text/javascript"></script>
  <script type="text/javascript">
    var wsbroker = "your.mqtt.domain";
    var wsport = xxxxxx // port for above
    var username = "username"
    var password = "password"

    var client = new Paho.MQTT.Client(wsbroker, wsport, "myclientid_" + parseInt(Math.random() * 100, 10));
    client.onConnectionLost = function (responseObject) {
      console.log("connection lost: " + responseObject.errorMessage);
    };
    client.onMessageArrived = function (message) {
      var div_element = document.createElement("div");
      div_element.innerHTML = '<b>' + message.payloadString + '</b>';
      var parent_object = document.getElementById("messages");
      parent_object.appendChild(div_element);
      console.log(message.destinationName, ' -- ', message.payloadString);
    };
    var options = {
      timeout: 3,
      onSuccess: function () {
        console.log("mqtt connected");
        // Connection succeeded; subscribe to our topic, you can add multile lines of these
        client.subscribe('hoge', {qos: 1});

        //use the below if you want to publish to a topic on connect
        message = new Paho.MQTT.Message("Hello");
        message.destinationName = "hoge";
        client.send(message);
      },
      onFailure: function (message) {
        console.log("Connection failed: " + message.errorMessage);
      }
    };
    options.userName = username;
    options.password = password;
    function init() {
        client.connect(options);
    }
    </script>
  </head>
  <body onload="init();">
    <div id="messages"></div>
  </body>
</html>

JavaScript 部分の冒頭の wsbroker, wsport, username, password を作成した MQTTサーバーの情報に書き換えれば基本は動作すると思います

説明

簡単にポイントを説明します

まず書き換える部分の 4 箇所ですがこれはコントールパネルで確認することができます
作成した MQTT サーバーの「基本情報」を確認できるのでそこに記載してある情報を入力してください
一点注意しなければいけないのはポートの部分で、これは「WebSocketポート」に記載のポート番号を入力してください
「MQTTポート」ではないです

var client = new Paho.MQTT.Client(wsbroker, wsport, “myclientid_” + parseInt(Math.random() * 100, 10));

の部分で MQTT ブローカに接続するためのクライアントを生成しています

client.onMessageArrived

でメッセージが受信したときの処理を記載しています
今回は受信したメッセージを<div>タグを使ってそのまま出力しています

onSuccess, onFailure

で MQTT ブローカに接続できたかどうかを判断します
接続できた場合は onSuccess が自動的にコールされ、接続に失敗した場合は onFailure が呼ばれます
onSuccess と同時に client.subscribe('hoge', {qos: 1}); を呼び subscribe を開始しています
また、今回は接続できたと同時に hoge というトピックに対してメッセージを送信しています

message = new Paho.MQTT.Message(“Hello”);
message.destinationName = “hoge”;
client.send(message);

そのためこの HTML ページにアクセスした瞬間「Hello」というメッセージが確認できると思います

動作を確認してみる

WebSocket に publish できるツールがあればそれ使うのが一番です
もしない場合は
http://www.hivemq.com/demos/websocket-client/
なんかを使うといいかもしれません
ドメイン、ポート、ユーザ名、パスワードを入力して connect してメッセージを publish することができます
input_hivemq_connect.png

これらのツールを使ってメッセージを publish してみましょう
publish するトピックは「hoge」を選択してください
「/hoge」とかスラッシュを付けてもダメなので必ず同一名称のトピックを設定してください
publish_message_with_hivemq.png

すると先ほど開いておいたサンプルのページに新たにメッセージが届いていることが確認できると思います
confirm_page.png

最後に

ニフティクラウド MQTT で websocket を試してみました
嵌りそうなポイントは特にありませんでしたが、ユーザ名とパスワードを設定しないとブローカに接続できないので注意してください
また MQTT ポートを使って publish/subscribe しても websocket のポートを使って publish/subscribe したメッセージは受信できないので注意してください

2015年10月21日水曜日

out_exec プラグインを使ってtail したログを MQTT に publish してみた

概要

tail した json ログの情報をそのまま MQTT に publish してみました
publish には out_exec プラグイン を使いました

環境

  • Raspbian 8.0 (Jessie)
  • Kernel Version 4.1.10
  • Ruby 2.1.5p273
  • Gem 2.2.2
  • fluentd 0.12.16

各種インストール

fluentd のインストールに関してはこちらを御覧ください
out_exec プラグイン自体はデフォルトで使える状態なので特にインストール作業は不要です

今回 publish に使ったツールは「mosquitto-clients」でこれを使うことで CLI で MQTT ブローカにメッセージを publish することができます
インストール方法は以下の通りです

  • sudo apt-get -y install mosquitto-clients

これで mosquitto_submosquitto_pub というコマンドが使えるようになります
fluentd で使用するのは mosquitto_pub になります

ちなみに CLI 単体で使用する例は以下の通りです

mosquitto_pub -h your.broker.domain -p 1884 -t topic/test -u username -P password -m “test”

  • ホスト名 (-h)
  • ポート (-p)
  • メッセージを送信するトピック (-t)
  • ユーザ名 (-u)
  • パスワード (-P)
  • メッセージ (-m)

というオプションを付与して実行しています
これを fluentd で実行することでメッセージを publish してみます

設定ファイル編集

in

まず in 側ですが type tail でログファイルを tail して1行ずつ処理することを想定しています

in の設定例として以下のような感じかと思います

<source>
  type tail
  path /path/to/log/hoge_json.log
  pos_file /path/to/log/hoge_json.log.pos
  tag hoge_json.log
  format json
  time_key time
  time_format %Y-%m-%dT%H:%M:%S%z
</source>

out

次に out 側ですがここで exec プラグインを使用します
exec プラグインは任意のコマンドを実行できるプラグインです
また、in から受け取った情報をバッファ用のファイルに一旦出力し、そのファイルを引数として受け取ることができます
その特性と mosquitto_pub を組み合わせることで publish を実現します

設定は以下のようになると思います

<match hoge_json.log>
  type exec
  command /usr/bin/mosquitto_pub -h your.mqtt.host -p 1883 -t topic/test -u username -P password -f 
  format json
  flush_interval 5s
  buffer_path /etc/fluentd/buffer
</match>

ポイントを説明します
まず command パラメータですが、ここに実行するコマンドを記載します
PATHや実行ユーザの関係があるのでコマンドへはフルパスで記載したほうが無難です
必要なオプションを記載していきますが、最後の「-f」オプションがポイントです
先ほどは「-m」オプションでメッセージを publish する方法を紹介しましたが mosquitto_pub コマンドは「-f」オプションを使うことで指定されたファイルに記載されている情報を publish することができます
このオプションがあるために out exec プラグインとの親和性があると思っています
コマンドが成立するために「-f」オプションの後ろに半角スペースが 1 つあることに注意してください

肝心の引数として渡されるファイルですが buffer パラメータで指定されたパス配下に自動で作成されます
ここで作成されたファイルがコマンドの引数として渡されます

試す

あとは試すだけです
すでに json のログがうまく in できているのであれば今回の out を追加するだけで動作するはずです
うまく publish されない場合は、まず mosquitto_pub コマンド単体でちゃんとブローカに publish できるか確認することをおすすめします
subscribe の確認は mosquitto_sub というコマンドが同時に使えるようになっているのでこれを使えばいいと思います
もちろん別の方法でもOKです

最後に

おそらく fluentd 的には out exec プラグインを使ってコマンドを実行するのではなく、プラグインをちゃんと作成して実行するのが正しいんだと思います
今回はたまたま思いついて試したらできたので紹介してみましたが、もしかしたら MQTT に pusblish できるプラグインはすでにあるかもしれません
( subscribe するプラグインはありましたが、publish するプラグインは見つけられませんでした)
まぁそもそもログを MQTT に publish すること自体あまり需要がないのかもしれませんが、、

以上

2015年10月19日月曜日

RaspberryPi に fluentd をインストールしてみた

概要

RaspberryPi 上に fluentd をインストールしてみました
バージョン周りがハマりポイントかと思います

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 8.0 (Jessie)
  • Kernel Version 4.1.10
  • Ruby 2.1.5p273
  • Gem 2.2.2
  • gcc 4.9.2
  • fluentd 0.12.16

インストール

必要なパッケージのインストール

  • sudo apt-get -y install ruby-dev
  • sudo apt-get -y install ruby1.9.1-dev
  • sudo apt-get install --upgrade gcc

ポイントは 2 つ
ruby-dev 系のインストールがちゃんとできていないと以下のエラーになります

'require': cannot load such file -- mkmf (LoadError)

gcc のバージョンが古いと以下のエラーになります

error: unrecognized command line option '-fstack-protector-strong'

とりあえず自分は上記を解決すれば OK でした
他にも足りないパッケージがあれば基本は apt-get でインストールすれば OK だと思います

fluentd のインストール

  • sudo gem install fluentd

これで問題なくインストールできました
他にも lib なんちゃら系が必要になるかもしれません
おそらく自分は他のインストール作業で lib なんちゃら系をインストールしていたのだと思います

一応インストール成功時の Gem のログを記載しておきます

Building native extensions. This could take a while…
Successfully installed msgpack-0.6.0pre1
Fetching: yajl-ruby-1.2.1.gem (100%)
Building native extensions. This could take a while…
Successfully installed yajl-ruby-1.2.1
Fetching: cool.io-1.4.1.gem (100%)
Building native extensions. This could take a while…
Successfully installed cool.io-1.4.1
Fetching: http_parser.rb-0.6.0.gem (100%)
Building native extensions. This could take a while…
Successfully installed http_parser.rb-0.6.0
Fetching: sigdump-0.2.3.gem (100%)
Successfully installed sigdump-0.2.3
Fetching: thread_safe-0.3.5.gem (100%)
Successfully installed thread_safe-0.3.5
Fetching: tzinfo-1.2.2.gem (100%)
Successfully installed tzinfo-1.2.2
Fetching: tzinfo-data-1.2015.7.gem (100%)
Successfully installed tzinfo-data-1.2015.7
Fetching: string-scrub-0.0.5.gem (100%)
Building native extensions. This could take a while…
Successfully installed string-scrub-0.0.5
Fetching: fluentd-0.12.16.gem (100%)
Successfully installed fluentd-0.12.16
Parsing documentation for cool.io-1.4.1
Installing ri documentation for cool.io-1.4.1
Parsing documentation for fluentd-0.12.16
Installing ri documentation for fluentd-0.12.16
Parsing documentation for http_parser.rb-0.6.0
Installing ri documentation for http_parser.rb-0.6.0
Parsing documentation for msgpack-0.6.0pre1
Installing ri documentation for msgpack-0.6.0pre1
Parsing documentation for sigdump-0.2.3
Installing ri documentation for sigdump-0.2.3
Parsing documentation for string-scrub-0.0.5
Installing ri documentation for string-scrub-0.0.5
Parsing documentation for thread_safe-0.3.5
Installing ri documentation for thread_safe-0.3.5
Parsing documentation for tzinfo-1.2.2
Installing ri documentation for tzinfo-1.2.2
Parsing documentation for tzinfo-data-1.2015.7
Installing ri documentation for tzinfo-data-1.2015.7
Parsing documentation for yajl-ruby-1.2.1
Installing ri documentation for yajl-ruby-1.2.1
Done installing documentation for cool.io, fluentd, http_parser.rb, msgpack, sigdump, string-scrub, thread_safe, tzinfo, tz
info-data, yajl-ruby after 416 seconds
10 gems installed

Tips

ldconfig の追記

もしかしたらやらなくても OK かもしれません

  • sudo touch /etc/ld.so.conf.d/userlocal.conf
  • sudo vim /etc/ld.so.conf.d/userlocal.conf

/usr/local/lib

  • sudo ldconfig

td-agent はインストールできなかった

公式サイトを見ると Debian の最新版の Jessie 用のインストールコマンドが載っていました

  • curl -L https://toolbelt.treasuredata.com/sh/install-debian-jessie-td-agent2.sh | sh

しかしこれでインストールしようとしても

W: http://packages.treasuredata.com/2/debian/jessie/dists/jessie/InRelease の取得に失敗しました 期待されるエントリ 'contrib/binary-armhf/Packages' が Release ファイル内に見つかりません (誤った sources.list エントリか、壊れたファイル)

というエラーになりインストールできません
RaspberryPi 上で動作している ARM の CPU アーキテクチャはサポートしていないようでインストールできませんでした

上記でインストールできたほうが、service コマンドで起動できたるので嬉しかったのですが

2015年10月18日日曜日

gatttool で Bluetooth デバイスの情報を取得する方法

概要

RaspberryPi 上に BlueZ をインストールして gatttool でデバイスの情報を取得する方法を紹介します
また今回使用した BLE デバイスは BL600 です

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 8.0 (Jessie)
  • Kernel Version 4.1.10
  • BlueZ 5.23-2+b1

BLEデバイスをスキャンし接続する

  • sudo hcitool -i hci0 lescan

でまずは Mac アドレスを調べます
対象の Mac アドレス (今回は xx:xx:xx:xx:xx:xx) が判明したら gatttool で接続します
これで gatttool のインタラクティブモードになります

  • gatttool -t random -b xx:xx:xx:xx:xx:xx -I

あとは connect コマンドを実行しましょう

[xx:xx:xx:xx:xx:xx][LE]> connect
Attempting to connect to xx:xx:xx:xx:xx:xx
Connection successful
[xx:xx:xx:xx:xx:xx][LE]>

connect に成功するとプロンプトの色が青色に変化すると思います

値を取得する

まず primary というコマンドを実行しましょう

[xx:xx:xx:xx:xx:xx][LE]> primary
attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x0008, end grp handle: 0x0008 uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0009, end grp handle: 0x000e uuid: 0000180d-0000-1000-8000-00805f9b34fb
attr handle: 0x000f, end grp handle: 0x0012 uuid: 0000180f-0000-1000-8000-00805f9b34fb
attr handle: 0x0013, end grp handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb

すると謎の文字列がずらーっと出てくると思います
これがこのデバイスから取得できるサービスの一覧です
サービスとは BLE が定めたもので各種値は必ずどこかのサービスに属しています

着目するのはこの中の uuid という項目でこの uuid を元にどんなデータが取得できるサービスなのか判断します

例えば一番上の uuid 00001800-0000-1000-8000-00805f9b34fb の初めの8桁の下4桁 1800 に着目します
この 1800 を先ほどの URL の中で探すと Generic Access という項目に該当することがわかります
そして Generic Access の中に Device Name という項目がありここの問い合わせることでデバイス名を取得することができます
では具体的に値を取得してみましょう

デバイス名を取得する

1800 のサービスの中でどの項目がデバイス名なのか調べる必要があります
どんな項目があるかは char-desc というコマンドを使用します

[xx:xx:xx:xx:xx:xx][LE]> char-desc 0x0001 0x0007
handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb

するとまたずらーっと謎の文字列が登場します
この中のどれかがデバイス名になります
ここでまた登場するのが uuid です
先ほど紹介した Generic Access の詳細を説明するページに移動します
この中の「Device Name」をクリックすると「 Assigned Number: 0x2A00」というのが記載されていると思います
ble_device_name_number.png

この「2A00」を先ほどの char-desc の uuid 下4桁と照らし合わせると以下が該当することがわかります

handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb

ここにアクセスするとデバイス名を取得できそうです
で、アクセスする方法は以下になります

[xx:xx:xx:xx:xx:xx][LE]> char-read-hnd 0x0003
Characteristic value/descriptor: 46 5f 49 49 49

取得できたと思ったら謎の文字列がまた返ってきました
先ほどの Device Name の説明のページを見ると「Format」という欄がありそこに「utf8s」と記載されているのがわかると思います
つまりこの16進数の数字の羅列を utf8s に変換する必要があるのです(面倒くさい!)
そして utf8s への変換方法は以下の通り

  • echo ” 46 5f 49 49 49” | tr \ = | nkf -WwmQ

ちなみにこの文字列は「F_III」に変換されます
ちょっとわかりづらいですが、echo している文字列の先頭にはスペースが入っています
tr コマンドの変換元の文字列はスペースをエスケープしているため「\」が変換元の文字列になります

こんな感じでデバイス名は取得することができます

バッテリ残量を取得する

バッテリ残量も同様の方法で取得することができます
uuid は「0x180F Battery Service」になります

[xx:xx:xx:xx:xx:xx][LE]> connect
Attempting to connect to xx:xx:xx:xx:xx:xx
Connection successful
[xx:xx:xx:xx:xx:xx][LE]> primary
attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x0008, end grp handle: 0x0008 uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0009, end grp handle: 0x000e uuid: 0000180d-0000-1000-8000-00805f9b34fb
attr handle: 0x000f, end grp handle: 0x0012 uuid: 0000180f-0000-1000-8000-00805f9b34fb
attr handle: 0x0013, end grp handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb
[xx:xx:xx:xx:xx:xx][LE]> char-desc 0x000f 0x0012
handle: 0x000f, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0010, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0011, uuid: 00002a19-0000-1000-8000-00805f9b34fb
handle: 0x0012, uuid: 00002902-0000-1000-8000-00805f9b34fb
[xx:xx:xx:xx:xx:xx][LE]> char-read-hnd 0x0011
Characteristic value/descriptor: 52

Format を見ると uint8 なので符号なし整数です
値はもちろん16進数なのでこれを10進数に変換すると

52(16) = 82(10)

になります
単位はパーセンテージなので電池残量は残り 82 %だとわかります

最後に

紹介は以上です
取得の仕組みがわかるとスイスイ値を取得できますが、わかるまでが大変でした
基本的に英語の文献ばかりなので英語が読めないと辛いです

Tips

  • UUID を直接指定して値を取得する方法
    例えばデバイス名を取得する場合

char-read-uuid 2a00

でも取得することができます

  • インタラクティブモードじゃない方法で取得する方法

gatttool -t random -b xx:xx:xx:xx:xx:xx –char-read –uuid=0x2a00

この場合 connect -> disconnect も勝手に行ってくれます

  • 存在しない UUID もあります
    UUID は決められてはいますがデバイスによってはカスタマイズされており、存在していないものもあります
    なのでサービスの一覧と primary コマンド等で UUID を照らし合わせつつ値の取得を行ってください

2015年10月17日土曜日

RaspberryPi の OS を MicroSD に書き込む方法

概要

RaspberryPi はOSも含め外部記憶にデータを持ちます
今回は公式で公開されている Raspbian というOSを MicroSD に書き込む方法を紹介します

環境

Raspbianのダウンロード

RaspbianとはRaspberryPi用に作成されたOSでDebianをベースにしています
これをSDカードにインストールしてSDカードからRaspberryPiを起動します

https://www.raspberrypi.org/downloads/
にアクセスしましょう
Raspbianのダウンロードボタンがあるのでクリックしてダウンロードします
download_raspbian.png

今回は Wheezy というバージョンの Raspbian をダウンロードしました
TorrentとZipがありますが、今回はZip形式をダウンロードしました
Zipのサイズで990MBでした

SDカードへimgを書き込む

ダウンロードしたzipファイルを解凍すると「2015-05-05-raspbian-wheezy.img」というファイルがあります
※ファイルの解凍は「The Unarchiver」というアプリを使うと楽です、unzip コマンドだとエラーになりました

これをRaspberryPiが読み込んだ時に起動できるようにSDカードに書き込みます
今回環境がMacOSなのでddコマンドを使ってイメージを書き込みます
他の方法として専用のツールを使って書き込むこともできます

dd コマンドを使って書き込む

SDカードをPCに接続してください
Mac Book Air の場合 SD カードを接続できる I/F がデフォルトでついていると思います
MicroSD の場合は SD カードのアダプタを付けて接続してください

解凍したimgファイルがあるディレクトリに移動して以下のコマンドを実行します (以下では ~/Downloads に解凍しています)
MOUNTED_SDCARD_NAME は各自の環境でことなるので df コマンド等で確かめてから実行してください

cd ~/Downloads
sudo diskutil umount /Volumes/[MOUNTED_SDCARD_NAME]
sudo dd bs=1m if="./2015-05-05-raspbian-wheezy.img" of="/dev/rdisk2"

以下のように表示されればイメージの書き込みは完了です

3125+0 records in
3125+0 records out
3276800000 bytes transferred in 228.385373 secs (14347679 bytes/sec)

dd: /dev/rdisk2: Input/output error
みたいなエラーが表示された場合は書き込みに失敗しています
2GBのSDカードでは容量不足になり上記エラーになるようです
最低でも4GBのSDカードを用意してください

書き込みが完了したらSDカードを取り出してください
ちゃんとFinderから「取り出す」とかで外してください

最後に

書き込み自体はダウンロードしてコマンド実行だけと非常に簡単でした
あとは RaspberryPi 本体の裏側に MicroSD ( or SDカード ) を挿入する I/F があるので接続し RaspberryPi に電源を入れましょう
うまく OS が焼けていれば起動し、設定画面に遷移すると思います (参考 : http://kakakikikeke.blogspot.jp/2015/10/raspberrypi-started.html)

2015年10月16日金曜日

RaspberryPi の bluetoothctl で無線キーボードに接続

概要

RaspberryPi のバージョン8 (Jessie) から bluez-utils というパッケージがなくなったようで bluez-simple-agent, bluez-test-device, bluez-test-input 等のコマンドが使えません
その代わりに bluetoothctl というコマンドで制御することができるのでその方法を紹介します

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 8.0 (Jessie)
  • Kernel Version 4.1.10
  • BlueZ 5.23-2+b1
  • Bluetoothキーボード : iBUFFALO Bluetooth3.0対応 コンパクトキーボード 薄型モデル BSKBB24BK
  • Bluetoothレシーバ : ELECOM Bluetooth PC用USBアダプタ 超小型 Ver4.0 Class2 forWin8 ブラック LBT-UAN05C2

接続方法

まず bluetoothctl をエージェントモードで起動します
すると [bluetooth]# というプロンプト表示になるのでここで対話的にコマンドを入力していきます
※念のためレシーバ、キーボードの Mac アドレスは伏せています
※yy: … はレシーバの Mac アドレス、xx: … はキーボードの Mac アドレスです

pi@raspberrypi ~ $ sudo bluetoothctl -a
[NEW] Controller yy:yy:yy:yy:yy:yy BlueZ 5.23 [default]
Agent registered
[bluetooth]#

まず、キーボードをペアリングできる状態にしてキーボードをスキャンします

[bluetooth]# scan on
Discovery started
[NEW] Device xx:xx:xx:xx:xx:xx BSKBB24

検知できると NEW と出て対象の Mac アドレスが出力されます
この Mac アドレスに対して connect します

[bluetooth]# connect xx:xx:xx:xx:xx:xx
Attempting to connect to xx:xx:xx:xx:xx:xx
[CHG] Device xx:xx:xx:xx:xx:xx Connected: yes
Connection successful

successful と出れば接続完了です
この段階で bluetooth キーボードが使えるようになっていると思います

あとは再起動時にも自動で接続するよう trust しておきます

[bluetooth]# trust xx:xx:xx:xx:xx:xx
[CHG] Device xx:xx:xx:xx:xx:xx Trusted: yes
Changing xx:xx:xx:xx:xx:xx trust succeeded

これで再起動しても自動で無線キーボードが接続されるようになりました

Tips

一定時間キーボードからの入力がないと自動でスリープ状態に入ってしまうようです
とりあえずキーボードを適当に叩いてキーボード側のスリープを解除し信号を送ってみて、それでもダメなら再度 bluetoothctl を実行すれば OK だと思います
ただ、その場合は無線キーボードが使えないので有線 or SSH でのログインができる状態である必要があります

参考サイト

2015年10月15日木曜日

RaspberryPi で Error: connect: Connection refused (111)

概要

RaspberryPi で BLE と connect するために gatttool やら hcitool を使っていたのですがタイトルのエラーが解消できずに悩んでいました
ようやく解決できたので紹介します

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 7.8 (Wheezy) -> 8.0 (Jessie)
  • Kernel Version 4.17 -> 4.1.10
  • BlueZ 5.35 -> 5.23-2+b1
  • Bluetoothレシーバ : ELECOM Bluetooth PC用USBアダプタ 超小型 Ver4.0 Class2 forWin8 ブラック LBT-UAN05C2

解決方法

結論から述べると自分のケースでは

OS と kernel をアップグレードし BlueZ を再インストール

することで解決しました

OS アップグレード方法

一旦 Wheezy のパッケージを最新にします

  • sudo apt-get update
  • sudo apt-get upgrade
  • sudo apt-get dist-upgrade

apt の対象リポジトリを Jessie に変更します

  • sudo cp /etc/apt/sources.list{,.wheezy}
  • sudo vim /etc/apt/sources.list

deb http://mirrordirector.raspbian.org/raspbian/ jessie main contrib non-free rpi

再度アップデートコマンドを実行します

  • sudo apt-get update
  • sudo apt-get upgrade
  • sudo apt-get dist-upgrade

すべて完了したら再起動します
OS のバージョンと kernel のバージョンを確かめましょう

  • sudo reboot
  • cat /etc/issue
  • uname -a

BlueZ の再インストール

過去にソースをコンパイルしてインストールしていたものを Jessie にすることで apt でインストールできる BlueZ に入れ替えます

ソースからインストールした hcitool 等は直接 rm で削除しました

  • sudo rm /usr/local/bin/*

あとは apt-get で BlueZ をインストールすれば OK です

  • sudo apt-get install bluetooth bluez blueman

Jessie になると bluez-utils というパッケージがなくなって bluez に統一されているようです
自分は念のためインストール後に再起動も実施しました
また、apt-get でインストールできるものに hcidump がないので、これだけはソースコンパイルしてできた hcidump を適当に配置しました

  • sudo cp ./bluez-5.35/tools/hcidump /usr/bin

P.S 20151029
hcidump は bluez-hcidump というパッケージに含まれているので sudo apt-get install bluez-hcidump でもインストール可能です

BLE デバイスの検知

OS をアップグレードした状態で hcitool と gatttool を使ってBLE デバイス(今回は SensorTag ) を検知してみました
USBドングルを接続はあらかじめ接続しておいてください

Macアドレスのスキャンおよび接続テスト

別ターミナルで詳細を確認するために hcidump を起動しておいてください

  • sudo hcidump -X

まずは BLE デバイスをスキャンします
もちろん BLE デバイスは Advertise できるように電源を入れてください

  • sudo hcitool -i hci0 lescan

検出された Mac アドレスに接続テストします

  • sudo hcitool -i hci0 lecc xx:xx:xx:xx:xx:xx

接続が持続されているか確認します

  • sudo hcitool con

これで接続したはずの BLE デバイスが表示されないとうまく接続できていないことになります
おそらく大丈夫だと思いますがダメな場合は lecc のコマンドに --random のオプションを付けて実行してみてください

安定した接続が確認できたら lecc 時に発行されるハンドル番号をもとに一旦切断します

  • sudo hcitool ledc NN

切断しない状態で gatttool 等を実行すると

Error: connect error: Device or resource busy (16)

というエラーが発生してしまいます

gatttool で接続する

では次に gatttool でも接続してみましょう
先ほど lescan で検知した同一の Mac アドレスに接続してください

  • gatttool -b xx:xx:xx:xx:xx:xx -I

lecc 時に --random をつけていた場合には gatttool 実行時にも random で接続してください

  • gatttool -t random -b xx:xx:xx:xx:xx:xx -I

これでインタラクティブモードに入ります
問題の元凶である Connection refused (111) はここで connect 時に発生していました

[xx:xx:xx:xx:xx:xx][LE]> connect
Attempting to connect to xx:xx:xx:xx:xx:xx
Connection successful

こんな感じになれば OK です
あとは SensorTag を Read/Write してみましょう
終わったら disconnect してください

[xx:xx:xx:xx:xx:xx][LE]> char-read-hnd 0x25
Characteristic value/descriptor: 0a 26 00 00 00 00 00 00 00 00 b0 00 40 51 04 03 aa 00 f0
[xx:xx:xx:xx:xx:xx][LE]> char-write-cmd 0x29 01
[xx:xx:xx:xx:xx:xx][LE]> disconnect

その他試したこと

いろいろと Try&Error したので覚えている限りで事象を記載します
もちろんここに記載していることは全部ダメでした

  • hcitool, gatttool のコマンドオプションをいろいろ変更してテスト
    特にタイプの public や random を変更してやってみました
    関係ないわけではないですが、根本対応が問題で効果はありませんでした

  • 異なる USB ドングルを使ってみる
    RaspberryPi に接続されているドングルが原因なのではと思い ELECOM 製以外の USB ドングルを接続してみましたがダメでした
    また、USB ドングルの再接続も何度か試しました

  • HCIの再起動
    sudo hciconfig hci0 down
    sudo hciconfig hci0 up
    で再起動してみましたがダメでした

  • BlueZ のバージョンアップ
    実は初めは 4.99 で試していました
    それでダメだったのでソースインストールに切り替えたのですがそれでもダメでした

  • 既存の BlueZ の削除
    apt-get でインストールした 4.99 を apt-get –purge remove してからソースインストールしたのですが、ダメでした

  • 別のBLEデバイスを用意してテスト
    BLE デバイス側が悪いのではと原因を切り分けるために別の BLE デバイスを用意してテストしました
    用意したデバイスは BL600 と 自作のペリフェラルiPhoneアプリを作成しました

  • Kernel のバージョンだけあげて BlueZ を再コンパイル&インストール
    rpi-update を使ってカーネルのバージョンをアップデートしました
    結果的にカーネルだけではダメでした

  • OS のバージョンをあげて BlueZ を再コンパイル&インストール
    OS のバージョンをあげた場合はソースインストールせず、apt で配布されている BlueZ を使用するのが正解でした

Tips

  • bluez-simple-agent や bluez-test-device, bluez-test-input 等のコマンドがなくなっています
    bluez-utils のパッケージが Jessie では削除されているため上記のコマンドが使えなくなります
    調べた限りだと bluetoothctl というコマンドで代用するみたいですが、詳細な方法(コマンド)までは調べていません

  • Could not create connection: Connection timed out
    hcitool lecc コマンドで上記のエラーが発生することがあります
    このエラーがでると同じ Mac アドレスに次回以降接続しようとしても Could not create connection: Input/output error となり接続できません
    その場合は hcitool を使って対象の hci を再起動してください

    sudo hciconfig hci0 down
    sudo hciconfig hci0 up

  • Bluetooth: SMP security requested but not available
    lecc 実行時に dmesg のログに発生する
    初めはこれが問題だと思いいろいろとググるが結果的に問題なく lecc できていたときにも発生していた
    とりあえず原因不明のまま無視することにした

  • 接続できない場合の hcidump の特徴

> HCI Event: Command Status (0x0f) plen 4
    LE Create Connection (0x08|0x000d) status 0x00 ncmd 1
> HCI Event: Command Status (0x0f) plen 4
    LE Read Remote Used Features (0x08|0x0016) status 0x00 ncmd 1
> HCI Event: Command Status (0x0f) plen 4
    Disconnect (0x01|0x0006) status 0x00 ncmd 1
> HCI Event: Disconn Complete (0x05) plen 4
    status 0x00 handle 72 reason 0x16
    Reason: Connection Terminated by Local Host

うまく接続できない場合には hcidump にずっと上記のようなログが出力されていました
うまく接続できたと思っても Connection Terminated by Local Host が強制的に発生し BLE デバイスとの接続を勝手に切断sれていました
対処後はこのログも出なくなりました

最後に

対象のエラー文でググるとカーネルがバグっている系と BlueZ のバージョンをあげてくださいという記事が多く見受けられたような気がします
カーネルは確かに怪しかったので rpi-update でアップデートしたのですが、まさか OS まであげないとダメとは思いませんでした
そしてソースインストールした BlueZ も悪いとは思いませんでした
1週間はがんばったと思います
この記事が誰かの助けになれば幸いです

2015年10月14日水曜日

CentOS で Consul 入門

概要

CentOS 上で Consul を触ってみたのでメモ

Consul はいわゆる、サービスディスカバリのためのツールです
あるクラスタにサーバが1台追加されたら、それを検知して何かアクションを実行したりすることができます
今回は2台のサーバを用意して試してみました

環境

  • CentOS 6.6 64bit
  • Consul 0.5.2

インストール

バイナリを1つ配置して終了です

サーバモードで起動

1台はサーバモードで起動します
サーバ側の IP は 192.168.0.10 (server001) とします

  • consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul &

クライアントモードで起動

クライアント側はサーバモードで起動したノードに対して join します
クライアント側の IP は 192.168.0.11 (client001) とします

  • consul agent -data-dir=/tmp/consul -server -join 192.168.0.10 &

クラスタ内のメンバーを確認する

  • consul members
Node           Address            Status  Type    Build  Protocol  DC
server001      192.168.0.10:8301  alive   server  0.5.2  2         dc1
client002      192.168.0.11:8301  alive   client  0.5.2  2         dc1

サーバ、クライアントどちらで実行しても OK です
こんな感じで表示されるはずです
どちらのノードも alive になっていることがわかると思います

終了する(リーブする)

特定のクライアントを終了したい(クラスタから離脱させたい)場合は kill をするのではなく leave コマンドを使います

  • consul leave

これでプロセス自体もいなくなります
consul members で見てみると alive だったのが left になっているのが確認できると思います

consul watch で特定のコマンドを実行してみる

例えば server001 で以下を実行してみましょう

  • consul watch -type=service -service=consul “echo change services >> /var/tmp/consul.log”

クラスタ内に属するどれかのサーバで consul プロセスに何か変化があった場合に最後に指定したコマンドが実行されます
この状態で client001 で consul leave を実行するとコマンドが実行されファイルに文字列が出力されると思います

type はいろいろと指定できます
今回指定した service はサービスプロセスの変化を watch するタイプです
他にも key (key - value ストアの変化を watch する) , event (任意のイベントの発行を watch する) などがあります
詳細はここの Watch Types という項目に記載されています

最後に

簡単ですが、インストールから起動、consul watch までを試してみました
印象は非常にシンプルで便利なツールだと思いました
シンプルが故に応用もかなり効くと思います
今回は紹介しませんでしたが、クラスタ内で KVS を共有できたり、クラスタ内で DNS を立てたりすることもできるようです

たぶん機能の肝になるのは consul watch かなと思います

参考サイト

2015年10月13日火曜日

RaspberryPi 超入門 〜OS起動まで〜

概要

RaspberryPi の OS の準備ができたので実際に起動まで行ってみました
起動用の OS 準備編はこちら

環境

RaspberryPi の購入に関して

実は購入は2013年にしており最新版のRaspberryPiを使っているわけではありません
また、購入自体は本家 RaspberryPi のサイトから購入しました
raspberry_order.png

配線

配線は基本4箇所でOK

  • RaspberryPi <- SDカード
    裏側にSDカードの挿入 I/F があります

  • RaspberryPi <- キーボード
    USBポートに接続します

  • RaspberryPi <- HDMIケーブル -> モニタ
    HDMIポートに接続します

  • RaspberryPi <- 電源ケーブル -> コンセント
    MicroUSBポートに接続します
    電源ケーブルは今回 RaspberryPi と同様に公式サイトで購入したものを使っています

RaspberryPi 的にはこんな感じで接続されていればOKです
raspberry-pi.jpg

電源ON

RaspberryPi に特に電源スイッチはありません
上記配線を完了した上でコンセントに電源プラグを接続してください
電源が共有されると自動で RaspberryPi が起動します
起動する PWR という LED が点灯します
起動中は ACT という LED が点滅し起動処理を実施します

raspi-config

いわゆる BIOS の設定画面です
ここではローケールの設定やタイムゾーン、キーボードのレイアウトなどを設定します
自分は以下の部分だけ設定しました

  • Expand Filesystem (1)
    ストレージとして使用するSDカードの領域を拡張してくれます
    基本は実行したほうがいいと思います
    クリックするだけでOKです

  • Internationlisation Options (4)

    • I1 Change Locale -> リスト表示 -> ja_JP.UTF-8 UTF-8 -> ja_JP.UTF-8
    • I2 Change Timezone -> Asia -> Tokyo
    • I3 Change Keyboard Layout -> リスト表示 -> Generic 105-key (Intl) PC -> Other -> Japanese -> Japanese (OADG 109A) -> The default for the keyboard layout -> No compose key -> Yes
  • Advanced Options

    • A4 SSH -> Enable

あたりを設定しました
Locale を ja_JP に設定すると日本語が化ける問題が発生するので日本語フォントをインストールする必要があります
( 日本語表示が全部豆腐 (■) になってしまいます )
英語キーボードでかつ RaspberryPi で日本語表示されなくてもいい場合は、Internationlisation Options は Timezone だけ設定すればいいと思います

その他の項目の詳細は公式の raspi-config の説明を御覧ください
日本語でも調べればいろいろでますが、Raspbian のバージョンによって設定項目が変わると思いますのでバージョンにご注意ください

ログイン

起動が完了するとログインプロンプトが表示されます

raspberrypi login :

raspi-config で特にユーザのパスワード等は設定していないのでデフォルトの ID/PW でログインできると思います

pi / raspberry

成功するとコマンドプロンプトの表示になりコマンドを入力することができるようになります

pi@raspberrypi ~$ ls

基本的な Linux のコマンド ( ls や cd ) は普通に使えます

最後に

とりあえず起動して OS へログインすることに成功しました
RaspberryPi 自体 Linux みたいなものなので慣れている方はある程度簡単に使えると思います

RaspberryPi 自体は小さくていいのですが、とは言えやはり始めるにはいろいろと周辺機器が必要になってしまうのは仕方ないといったところでしょうか

いざやる気になって RaspberryPi を購入したものの、キーボードやらモニタやら各種ケーブルやらがない、、、という状況になってしまう人は多いのではと思いました

2015年10月12日月曜日

RaspberryPi で WiMAX2 に接続する方法

概要

USB の Wi-Fi ドングルを使って RaspberryPi を無線 LAN に接続してみました

環境

無線LANの設定

RaspberryPi を起動する前に USBドングルは接続しちゃってください
空いている RaspberryPi 上の USB ポートを使ってしまえばOKです

接続した状態で RaspberryPi が起動したら Wi-Fi の設定をしていきます

USBドングルの接続確認

  • lsusb

を実行して USB ドングルを RaspberryPi が認識しているか確認してください
今回の場合だと BUFFALO INC. という文字列を含む行が出力されていれば OK です

Wi-Fi 接続用ファイルの作成

ルータに接続する設定ファイルを作成します
事前に SSID と接続用のパスワードを用意しておいてください

  • sudo cp /etc/wpa_supplicant/wpa_supplicant.conf{,.back}
  • sudo chmod 666 /etc/wpa_supplicant/wpa_supplicant.conf
    バックアップを作成して書き込み権限を付与してあげます

  • sudo wpa_passphrase [ssid] [password] >> /etc/wpa_supplicant/wpa_supplicant.conf

  • sudo vi /etc/wpa_supplicant/wpa_supplicant.conf

wps_passphrase コマンドで接続用の設定を出力してファイルにリダイレクトします
[ssid] と [password] は自分の環境の ID/PW に変更してくだdさい
wps_passphrase コマンドの内容だけでは足りないのでファイルを開いて直接編集します

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
        proto=WPA2
        key_mgmt=WPA-PSK
        pairwise=CCMP
        group=CCMP
        ssid="ssid"
        psk=xxxxxxxxxxxxxx
}

network の部分が追記部分でここに他に必要なパラメータを追記します
自分の場合は

  • proto=WPA2
  • key_mgmt=WPA-PSK
  • pairwise=CCMP
  • group=CCMP

の 4 つのパラメータを追記すれば OK でした
追記したら保存します

  • sudo chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf

権限も戻しておきましょう

DHCP で IP を取得するように設定

ルータからは DHCP で IP を取得するようにします
こちらも念のためバックアップを取得してから実施します

  • sudo cp /etc/network/interfaces{,.back}
  • sudo vi /etc/network/interfaces

iface wlan0 inet dhcp

wlan0 の manual の部分を dhcp に書き換えればOKです

ネットワーク起動

  • sudo /etc/init.d/networking restart

でルータから IP を取得できれば OK です
取得できない場合は設定ファイルに不備がないか確認してください
Wi-Fi の設定によっては設定ファイルの書き方が異なります
例えば暗号化モードに(ないとは思いますが) WEP を採用している場合は書き方が代わります

確認

pi@raspberrypi ~ $ ifconfig wlan0
wlan0 Link encap:イーサネット ハードウェアアドレス aa:bb:cc:dd:ee:ff
inetアドレス:192.168.179.13 ブロードキャスト:192.168.179.255 マスク:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 メトリック:1
RXパケット:623 エラー:0 損失:0 オーバラン:0 フレーム:0
TXパケット:408 エラー:0 損失:0 オーバラン:0 キャリア:0
衝突(Collisions):0 TXキュー長:1000
RXバイト:88191 (86.1 KiB) TXバイト:56337 (55.0 KiB)

あとは apt コマンド等でパッケージのインストールができることも確認するといいと思います

sudo apt-get install emacs

Tips

今回使った子機はかなり熱を持つため RaspberryPi ではちょっとオススメしません
長時間起動していると USB ポートの部分がかなり熱くなってしまいます

P.S 20151130
ステルスモードのアクセスポイントを使っている場合は以下を試してみてください
http://blog.rutoru.com/2014/04/05/raspberry-pi-wifi/

自分の場合は PSK を手動でコピーするのが面倒だったので以下のような流れで作業しました

  • chmod 666 /etc/network/interfaces
  • sudo wpa_passphrase [ssid] [password] | grep psk= | grep -v “#psk” >> /etc/network/interfaces
  • 以下を手動で修正する
    • #wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
    • wpa-driver wext
    • wpa-scan-ssid 1
    • wpa-ssid “ssid”
    • wpa-psk “xxxxxxxxxx”
  • sudo /etc/init.d/networking restart

で参考サイト通り無事取得できました

2015年10月11日日曜日

RaspberryPi で Bluetooth キーボードを接続する方法

概要

RaspberryPi に有線キーボードを接続しているといろいろと邪魔なので Bluetooth の無線キーボードに変更してみました

環境

必要なパッケージのインストール

この作業はまだ有線キーボードで実施する必要があります

  • sudo apt-get -y update
  • sudo apt-get install bluetooth bluez-utils blueman

apt-get でインストールされる BlueZ は 4.99 になるので注意してください
Bluetooth キーボードと接続するだけであれば 4.99 でも問題ないです

Bluetooth レシーバを接続する

この作業も有線キーボードで実施します

空いている USB ポートに Bluetooth レシーバを接続しましょう
RaspberryPi が起動中の状態でもOKです
うまく認識しない場合は停止してからお試しください

  • lsusb
    Cambrige Silicon Radio, Ltd Bluetooth Dongle (HCI mode) が認識されていることを確認しましょう
  • Bluetooth キーボードの Bluetooth を ON にする
    RaspberryPi がレシーバを認識したら Bluetooth キーボードを ON にしましょう
    今回使用した iBuffalo のキーボードであれば左側の側面に ON/OFF のスイッチがあります
    また充電式なので MicroUSB ポートを使って事前に充電しておきましょう
  • Bluetooth キーボードをペアリング待機状態にする
    今回のキーボードであれば、電源を ON にしてランプが青から消灯した段階で fn + delete を押すことでペアリングの待機状態にすることができます
    待機状態になるとランプが青色の点滅状態になります
  • sudo hcitool scan
    RaspberryPi 側から Bluetoothe キーボードを探索します
    おそらく簡単に見つかると思います
    見つかったらそこに表示されている Mac アドレスをメモしておきましょう
    見つからない場合はちゃんとペアリングの待機状態になっているかキーボード側を確認してください

スクリプト修正

bluez-simple-agent というスクリプトを修正しないと、うまくペアリングできなかったので修正します

  • sudo cp /usr/bin/bluez-simple-agent{,.back}
  • sudo vi /usr/bin/bluez-simple-agent

cabability=”DisplayYesNo”

92行目 を上記のように修正しましょう
修正できたらペアリングしていきます

ペアリング

  • sudo bluez-simple-agent hci0 [mac_address]
  • sudo bluez-test-device trusted [mac_address] yes
  • sudo bluez-test-input connect [mac_address]

でエラーがでなければペアリング完了です
実際に Bluetooth キーボードから入力ができるかと思います
入力が確認できたら有線キーボードは外してもらってOKです

英語キーボードとして認識させる

例えば有線の場合は日本語キーボードだったので raspi-config で日本語キーボードの設定をしていたため英語キーボードを接続したらうまく動かなくなったなど (自分はそのパターン)

以下のようにキーボードの設定ファイルを書き換えることで英語キーボードとして認識させることができました

  • sudo cp /etc/default/keyboard{,.back}
  • sudo vi /etc/default/keyboard
# KEYBOARD CONFIGURATION FILE

# Consult the keyboard(5) manual page.

XKBMODEL="pc105"
XKBLAYOUT="us"
XKBVARIANT=""
XKBOPTIONS="ctrl:swapcaps"

BACKSPACE="guess"

上記のように必要な箇所を書き換えましょう
( 自分は XKBLAYOUT, XKBVARIANT, XKBOPTIONS だけ書き換えれば OK でした)
その後

  • sudo reboot

で次回起動時に英語キーボードとして認識します
XKBOPTIONS の設定でついでに capslock と ctrl を入れ替えているので不要な場合は空白を設定してください

トラブルシュート

  • キーボードからの入力ができなくなった

おそらく RaspberryPi がキーボードを認識できなくなったんだと思います

sudo hcitool con

で何も表示されなくなります
USBドングルを RaspberryPi から外して再度接続すると RaspberryPi がリフレッシュし再度認識されると思います
それでもダメな場合は再起動してください
キーボード側の充電がなくなった可能性もあります
Bluetooth キーボードの種類によっては一定時間操作していない場合は休止状態になることがあるので、久しぶりに触る場合は何度かキーをストロークすることで再認識することもあります

  • 再度ペアリングする

上記の再起動方法はちょっと力づくなので、この方法がいいと思います
fn + delete で再度ペアリング状態にして別ターミナルで SSH ログインして

sudo bluez-test-input connect [mac_address]

を実行すると再度ペアリングしてキーボードが使えるようになります
RaspberryPi の bluetooth は一定期間通信していないとペアリングを解除してしまうのでしょうか、それともキーボード側が一定期間使われていないとペアリングを解除してしまうとか
ペアリングを解除しないために RaspberryPi 側から一定間隔で信号を送っておく必要がありそうです

  • RaspberryPi 再起動後の挙動

特に再度ペアリングのコマンドを実施しなくてもキーボードに接続することができました
もちろん再起動時にキーボード側の Bluetooth は ON にしておいてください

2015年10月9日金曜日

RaspberryPi に BlueZ をインストールして BLE を検知してみた

概要

BlueZ は Linux 上で Bluetooth を扱うためのプロジェクトです
RaspberryPi で Bluetooth や Bluetooth Low Energy を扱う場合にも BlueZ が必要になります
今回は BlueZ のインストール方法と BlueZ を使った簡単な Python スクリプトのサンプルを動作させてみました

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 7.8
  • Python 2.7
  • BlueZ 5.32
  • pybluez 0.22
  • Boost 1.49

BlueZ 5.32 のインストール

Rasbian 上で BlueZ をインストールする際に apt-get を使うと 4.99 というバージョンがインストールされてしまうのでソースからコンパイルしてインストールします

  • sudo apt-get install libdbus-1-dev libdbus-glib-1-dev libglib2.0-dev libical-dev libreadline-dev libudev-dev libusb-dev make
  • mkdir -p work/bluetooth
  • cd work/bluetooth
  • wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.32.tar.xz
  • tar xvf bluez-5.32.tar.xz
  • cd bluez-5.32
  • ./configure --disable-systemd --enable-library
  • make
  • sudo make install

make から make install にかけてやや時間がかかります
続けて make でインストールされないものを手動でインストールします

  • sudo cp attrib/gatttool /usr/local/bin/

あと、libbluetooth-dev の各種ヘッダファイルをビルドしたもので置き換えます

  • sudo cp -ipr lib/ /usr/include/bluetooth.5.32
  • cd /usr/include
  • sudo mv bluetooth bluetooth.4.99
  • sudo ln -s bluetooth.5.32/ bluetooth

BLE 検知テスト

hcitool という検知用の簡易ツールがあるのでそれを使ってみます

  • sudo hcitool lescan

とすることで BLE の信号を検知することができます
近くに BLE の端末がある場合は近づけると Mac アドレスとデバイス名を表示してくれます
hcitool のバージョンは hcitool と入力して表示されるヘルプの先頭に表示されています

より詳細な情報 (Advertising パケットの中身など) をみたい場合はあらかじめ sudo hcidump & としてバックグランド実行した状態で lescan をかけましょう

pybluez インストール

Python から操作するためのライブラリをインストールします
pip を使うのでインストールしています

  • sudo apt-get -y install python-pip
  • sudo apt-get install python-dev libbluetooth-dev libboost-all-dev
  • sudo pip install pybluez
  • sudo pip install pybluez[ble]

Python スクリプトから検知してみる

サンプルスクリプトを作成してスクリプトで BLE デバイスが検知できるか確認してみましょう

  • cd work/bluetooth
  • touch scan_ble.py
  • vim scan_ble.py
# bluetooth low energy scan
from bluetooth.ble import DiscoveryService

service = DiscoveryService()
devices = service.discover(2)

for address, name in devices.items():
    print("name: {}, address: {}".format(name, address))
  • sudo python scan_ble.py

でエラーにはならいのですが、BLE をうまく検知してくれず、、、

P.S 20151015
以下を対応してから実施したら上記でもうまく検知できました
http://kakakikikeke.blogspot.com/2015/10/raspberrypi-error-connect-connection.html

別のサンプルスクリプトを試してみる

で 10個 BLE情報を受信すると情報を出力しつづけてくれます
こちらはあっさり動きました
pybluez と一緒にインストールされる bluetooth というライブラリを使っていますがこっちのほうが簡単に扱えるかもしれません

最後に

BlueZ をインストールして BLE デバイスを検知してみました
最後は Python スクリプトから検知してみました
正直 hcitool がよく出来ているので難しいソースコードを見て自分スクリプトを組まなくてもいいかもしれません

また pybluez の BLE サポートライブラリをインストールするのに libbluetooth-dev が 4.101 以上のバージョンでないと gattlib のインストールに失敗するのはハマりました
今回は BlueZ をコンパイルしてできた bluetooth ディレクトリをコピーして最新にすることで対応しましたが、どこを探してもなかったので結構大変でした
2つ目のサンプルは gattlib を使っていないので BLE サポートのライブラリも入れる必要がないので 2 つ目を素直に使うのがいいと思います

参考サイト

2015年10月8日木曜日

消えた 1a0a666f941c99882093d7bd08ced15033bc3f0c の package.el

概要

どこを探してもない
とりあえず emacs23 で動いた package.el をキャッシュしておきます

package.el

たぶんこれのはず
package.el

とりあえず Debian 上で動作する emacs 23.4.1 ではちゃんと動くことを確認しました

2015年10月7日水曜日

RaspberryPi で日本語の文字化けを解消する方法

概要

raspi-config の初回設定時に Locale を ja_JP.UTF-8 にしていると RaspberryPi 上で日本語が文字化けを起こします
RaspberryPi 上でも日本語を使う方法を紹介します

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 7.8

日本語フォントインストール

  • sudo apt-get install ttf-kochi-gothic xfonts-intl-japanese xfonts-intl-japanese-big xfonts-kaname
  • sudo apt-get install jfbterm
  • sudo reboot

apt を使ってインストールするのでインターネットに接続していることが条件になります
フォントをインストールしたら一旦再起動します

jfbterm 起動

  • jfbterm

上記コマンドを実行するとつらつらーとログが流れて再度プロンプトが表示されると思います
この状態で例えば存在しないコマンドなどを入力すると

pi@raspberrypi ~ $ hoge
-bash: hoge: コマンドが見つかりません

とちゃんと日本語表示されると思います
日本語表示したい場合は jfbterm を起動する必要があります
ログイン直後などに実行するといいと思います

Tips

Ctrl + d とかで jfbterm を終了すると普通はもとのプロンプトに戻るのですが戻らない場合がありました
何も入力を受け付けなくなり、元に戻れない現象になってしまいます
RaspberryPi 自体を再起動してもいいですが面倒です
そんな場合もし SSH が使えるのであれば別のマシンから RaspberryPi に SSH ログインして再度 jfbterm を実行すると復活すると思います

Zabbix のアクションで送信するメールに日付を挿入する方法

概要

Zabbix で発泡するアクションメール内に時刻情報を記載する方法を紹介します

環境

  • CentOS 6.6 64bit
  • Zabbix 2.4.5

設定方法

設定 -> アクションを開き設定したいアクションに以下のマクロを追記します

  • Event time: {EVENT.TIME}
  • Event date: {EVENT.DATE}

設定画面のサンプルは以下のような感じです

insert_event_info.png

これで時刻情報がアクションメールの本文内に記載されます

2015年10月6日火曜日

chef-td-agent の cookbooks を chef-client でインストールしてみた

概要

公式では Berkshelf を使用するのが推奨されていますがあえて使わないでインストールしてみました
chef-client を使って実行しています

環境

  • CentOS 6.6 64bit
  • Chef 12.0.3-1 (chef-client)
  • td-agent 0.12.12
  • chef-td-agent (revision : 143057e)

必要なレシピを取得

実行用 json ファイルを作成

  • cd work/td-agent
  • touch td-agent.json
  • vim td-agent.json
{
  "run_list": [
    "td-agent"
  ]
}

実行

  • cd work/td-agent
  • chef-client -z -j td-agent.json -o td-agent

確認

  • which td-agent

    /usr/sbin/td-agent

  • ls -l /etc/td-agent/td-agent.conf

  • td-agent-gem list | grep fluent

2015年10月2日金曜日

AutoLayout 超入門

概要

AutoLayout はサイズの異なるデバイス間でもレイアウトを自動で調整することで綺麗に見せる機能です
Xcode の InterfaceBuilder を使って設定する方法を紹介します
Android で言うところの RelativeLayout 的な機能です

環境

  • Mac OS X 10.10.5
  • Xcode 7.0.1

サンプルプロジェクト作成

Xcode を開いてサンプルプロジェクトを作成します

  • Fire -> New -> Project
  • Single View Application
  • Choose options for your new project は適当に決定してOK
  • プロジェクトの保存先を適当に決定

これでOKです
配布するアプリではないので、AppID とかは気にしないでいいと思います

Main.storyboard を開く

左メニューから Main.storyboard をクリックして開きましょう
とりあえず View Controller が 1 つあると思います
今回はこれをそのまま使っていきましょう
open_xib.png

UIコンポーネントを設置する

View が 1 つあるのでそれに Label の UI コンポーネントを 3 つ配置しましょう
set_3_label.png

とりあえずこんな感じになればOKです
3 つの UI コンポーネントを重ねて設置しないように注意しましょう

あと AutoLayout の効果がわかるように適当に背景色を指定しておきましょう
set_background.png

constraints を設定する

さて、ここからが本題です
この constraints (制約) という機能が AutoLayout の正体といってもいいでしょう

まず一番上の Label から設定していきましょう
Label を選択した状態にし、右下にある 4 つ並んだアイコンの右から 2 番目を選択します
すると吹き出しみたいなやつが出てきて constraints を設定できます
これで何ができるのかというと、他のUIコンポーネントとのマージンや配置場所を設定することができます
マージンを設定する場合は

  • 赤い点線になっている部分をクリック
  • 赤い実線になる
  • プルダウンからマージンの基準となる他のUIコンポーネントを指定
  • 距離を設定

という手順になります(これが非常にわかりづらい、あと点線を実線にしたり、他にフォーカスがあたると指定した数字が戻っちゃったりする、、)

とりあえず一番上のラベルは以下のような感じで設定しました
set_constraints.png

隣接するコンポーネントとはそれぞれ 10 マージンするという設定になります
これで良ければ一番下の Add 4 constraints をクリックします
すると左メニューに constraints が追加されます
added_constraints.png

こんな感じで他の Label も設定しましょう
最終的に以下のような constraints の設定にしました
set_all_constraints.png

急に複雑になった感がハンパないですが、落ち着きましょう
一番初めの Label にした上下左右の 10 のマージンの設定を他の Label にもやっただけです

フレームを更新する

constraints を設定したらその設定を InterfaceBuilder に反映させてどう見えるか確認することができます
4 つ並んでいるアイコンの一番右をクリックし「Update Frames」を選択しましょう
update_frame.png

すると作成した constraints にしたがって UI コンポーネントが整理されます
たぶん今回の設定だと以下のようになると思います
updated_frames.png

最後のラベルが異様な高さになっていますが、今回は各コンポーネント間のマージンだけを設定しました
具体的に高さを決めていません
この場合、先にマージンが決定されそれに応じて各UIコンポーネントの高さが決定します
上に配置したコンポーネントから先に評価され最後のラベルのコンポーネントが最後に評価されたため余った高さ分がコンポーネントの高さに割り当てられたことになります

動作確認

では動作確認してみましょう
適当にシミュレータを選択してビルドしましょう

まず Portrait (縦向き) の場合ですが、これは InterfaceBuilder で確認していた通りの感じだと思います
横まできっちりラベルが伸びており、縦は最後のラベルの高さで画面いっぱいまで伸びていると思います
portrait.png

では、次にシミュレータを Landscape (横向き) にしてみましょう
Hardware -> Lotate Left で横向きにできます
すると横幅と縦幅が変化したにも関わらずピッタリ綺麗に表示されていると思います
landscape.png

これが AutoLayout のちからになります
例えばこれが AutoLayout を使わずに決め打ちで width や height を設定していると Landscape にしたときに横幅が足りなくなる現象に見舞われると思います

最後に

InterfaceBuilder だけで設定できるので、使いこなせると非常に便利な機能だと思いました
ただ、操作や設定がやや困難でマスタするまでには少し時間が必要かなと感じました
また、Xcode のバージョンは頻繁にアップデートし、それに伴い UI が変わるので、今回紹介した操作とは、バージョンが違う場合異なる可能性が高いです

自分的にハマったのは隣接するコンポーネント間のマージンの設定です
マージンを設定するときに XCode が自動で判断して隣接するコンポーネントを決めるのですが、それが全然違うコンポーネントだったケースがあったので、それにハマりました

あとは自分は遭遇したことがないですが、1 つの View 上に非常に大量の UI コンポーネントがある場合にそれに 1 つ 1 つ constraints を設定するのは非常に大変で手間のかかる作業になると思いました
そういった場合にはちょっと使えないレベルになってしまうかもしれません