0

AndroidScala用iBeaconライブラリに領域判定機能つけた

だいぶ書き忘れてたけど3週間ぐらい前に作った気がする

https://github.com/shokai/iBeacon-AndroidScala


前:AndroidでiBeaconを読む(Scalaで)


onRegionでRSSIの範囲を指定してevent登録できる
-70から-50、端末にもよるけどだいたい15メートル以上20メートルぐらいに入った時にcallbackされる。

// UUID, major, minor, RSSI range, callback
iBeacon.onRegion("805D6740-F575-492A-8668-45E553EB9DF2", "0001", "0001", Range(-70,-50), (beacon:Beacon) => {
Log.v("iBeacon", s"region(-70~-50) UUID=${beacon.uuid} RSSI=${beacon.rssi}")
})

UUID, major, minorはそれぞれnullを与えると何にでも反応するようになる

onRegionのラッパーでonFar, onNear, onImmediateというのがあって、それぞれ電波とどかなくなるギリギリ30メートルぐらい、割と近い数メートル、すごく近い数十センチでcallbackする。
iBeacon.onFar("805D6740-F575-492A-8668-45E553EB9DF2", "0001", "0001", (beacon:Beacon) => {
Log.v("iBeacon", s"far: ${beacon.uuid}")
})

iBeacon.onNear("805D6740-F575-492A-8668-45E553EB9DF2", "0001", "0001", (beacon:Beacon) => {
Log.v("iBeacon", s"near: ${beacon.uuid}")
})

iBeacon.onImmediate("805D6740-F575-492A-8668-45E553EB9DF2", "0001", "0001", (beacon:Beacon) => {
Log.v("iBeacon", s"immediate: ${beacon.uuid}")
})

これらを使って研究室のドアに近づいたらカギが開くようにしたりしてる。

0

Node.jsでiBeacon

bleaconを使うとMacをiBeacon発信機にできた。もう一台Macを用意すれば受信もできた。

https://gist.github.com/shokai/0354aaf8a72873f4412b


nodeの発信側は、プロセス終了してすぐ再起動するとうまく動かない。最低でも2,3秒まってから再起動する。

% npm i bleacon
% uuidgen

発信
Bleacon = require 'bleacon'

uuid = process.argv[2] || "805D6740-F575-492A-8668-45E553EB9DF2"
major = 1
minor = 1

console.log uuid

Bleacon.startAdvertising uuid, major, minor, -50


受信
Bleacon = require 'bleacon'

Bleacon.startScanning()

Bleacon.on 'discover', (beacon) ->
console.log beacon


昨日作ったAndroidでiBeaconを読むやつでも受信できた。

0

AndroidでiBeaconを読む(Scalaで)

前:ScalaでAndroidアプリを作る


iBeaconをAndroidで読んで、ビーコンが現れたらNotificationを出すとかできるライブラリを作った。
advertiseパケットを自前でparseしてiOSのSDKで使われてるのと同じフォーマットの16進コードに変換してるけど、scalaなので15行ぐらいで書けた。

https://github.com/shokai/iBeacon-AndroidScala

先週研究会でspammerっていう人がiBeaconの仕組みとかをまとめて発表してくれた。
へぇーと思ったのでMyBeacon買って土日にAndroid用のライブラリを作った。

Javaは冗長でつらいのでScalaで書いたけど、Scalaもライブラリの配信方法が.classをjarに固めてmaven使うとか冗長でつらい。どうすればいいんだ。なんでコンパイル前のscalaスクリプトのまま流通させないのか理解できない。


使い方


詳しくはGitHubのREADMEに書いた。

Activityから起動する例
import org.shokai.ibeacon.{IBeacon, Beacon};

class MainActivity extends Activity{

lazy val iBeacon:IBeacon = new IBeacon(this)

override def onCreate(savedInstanceState:Bundle){

// ビーコンを発見した時にcallbackされる
iBeacon.onDiscover((beacon:Beacon) =>
Log.v("iBeacon", s"UUID=${beacon.uuid} Major=${beacon.major} Minor=${beacon.minor} RSSI=${beacon.rssi}")
)

}

}


AndroidManifest.xml
<manifest>
<application> ~~ (略) ~~ </application>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
</manifest>

とても簡単でよい。
onBeaconというコールバックもあって、これは全てのビーコンパケットをコールバックしてくる。
ビーコンは常に電波を発信しまくっているので、onBeaconイベントはものすごい勢いで呼ばれる。
コールバックされるBeaconオブジェクトのrssiプロパティで受信信号強度が取れるので、距離もなんとなく計れる。
だいたい見通し25メートルぐらいで-90、接触するぐらい近いと-20〜-10とかになる。

なお1度呼ばれた同じビーコンのonDiscoverが再び呼ばれるのは、そのビーコンの信号が5秒間無くなって再び現れた時。


サンプルアプリ


信号を読むやつapk


ビーコンを見つけたら通知を出すサービス(電源ONしたら自動起動する)

これ改造すると、猫にビーコンつけて近寄ってきたらエサくれ通知を出すとか、自分が家に近づいたらカギが開くとか簡単に作れる。


iBeaconとは

Appleが考えたBluetoothデバイスの存在通知手法で、ずっと電波出し続けているデバイス(ビーコン)をいろいろな場所に設置しておいて、その電波をスマホが検知すると「〜〜というデバイスがあるのでアプリを起動しますか?」のような通知を出す。
最近のiOSアプリ持ってないので実物を見たことがないんだけどそんな感じのはず。

実装としてはBluetooth LE (ローエナジー) のadvertiseパケットの末尾にビーコンのUUIDやmajor,minorといった識別子を突っ込んでいるもので、そんなに凄い事をしているわけではない。
なのでAndroidでもadvertiseパケットを見て、バイナリをparseしたらUUIDとか取り出せた。

インスタントメッセンジャーアプリの名前欄で会話してる人とかいるけど、そういうのに近い。


1800円のMyBeaconを3個買って、研究室に設置した。


参考

iOS – AndroidでiBeacon信号を受信してみよう – Qiita