EdisonをiBeacon化してみた。

2015.01.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Edisonには、Bluetoothもはじめから付いているため、 ライブラリを追加し簡単なプログラムを書くだけでiBeaconとして扱うことができます。

iBeaconでやってみたいネタもあったので、それも含めてやってみたいと思います。

EdisonのiBeacon化

今回検証を行ったEdisonのファームは以下になります。

$ cat /etc/version
edison-rel1-maint-weekly_build_16_2014-10-14_14-56-19

Edisonはopkgコマンドでパッケージのインストールが行える状態とします。

opkgの導入等については下記記事を参照してください。

10: Edison上のYocto Linuxで採用されたパッケージマネージャ opkg をいじる | Developers.IO

EdisonのBluetoothを有効にし起動します。 また、EdisonでBluetoothを扱うにはライブラリが足りないため、ライブラリの導入を行います。

$ rfkill unblock bluetooth
$ hciconfig hci0 up
$ opkg install bluez5-dev

iBeacon化のコードは以下になります。

package.json

{
  "name": "edison_iBeacon",
  "version": "1.0.0",
  "description": "edison_iBeacon ===============",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "http://localhost:8080/git/yutaka/edison_iBeacon.git"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "bleacon": "^0.2.0",
    "cylon": "^0.21.2",
    "cylon-firmata": "^0.18.0",
    "cylon-intel-iot": "^0.4.0"
  }
}

main.js

var Cylon = require('cylon');
var Bleacon = require('bleacon');
var bleaconStatus = false;
var uuid = 'AD2E48C690224BB3AAE7CCBFE17DDE4E'
var major = 0; // 0 - 65535
var minor = 0; // 0 - 65535
var measuredPower = -59; // -128 - 127 (measured RSSI at 1 meter)

var writeScreen = function(screen,message){
    screen.setCursor(0, 0);
    screen.write(message);
};
Cylon
    .robot()
    .connection('edison', {
        adaptor: 'intel-iot'
    })
    .device('touch', {
        driver: 'button',
        pin: 2,
        connection: 'edison'
    })
    .device('screen', {
        driver: 'upm-jhd1313m1',
        connection: 'edison'
    })
    .on('ready', function(my) {
        my.screen.clear();
        my.touch.on('push', function() {
            my.screen.clear();
            bleaconStatus = !bleaconStatus; 
            if (bleaconStatus) {
                Bleacon.startAdvertising(uuid, major, minor, measuredPower);
                writeScreen(my.screen,'start adv.');
            } else {
                Bleacon.stopAdvertising();
                writeScreen(my.screen,'stop adv.');
            }
        });
    });
Cylon.start();

Intel Edison Kit for ArduinoのD2にスイッチを、I2CにLCDを指すことでiBeaconの状態を変更・確認できるようにしてあります。

起動方法

$ npm install (初回のみ)
node main.js

上記のコマンドを実行後、D2につないだスイッチを押下することでiBeaconとして有効になります。 また、押下した際にLCDに'start adv.'と表示されます

この段階でもう一度スイッチを押下するとLCDには'stop adv.’と表示され、iBeaconとしては無効となります。

補足:xdk-deamonの止め方

今回上記のサンプルアプリはIntel XDK IoT Edisonは全く使わず実装を進めました。

そのためか、以前Intel XDK IoT Edisonから作成したプログラムと同時起動したりするのか、 LCDに全く関係ない文字列が出る等一部おかしな挙動をしてしまうことがありました。

そういったケースにおいてxdk-deamonは不要なケースが有ります。

xdk-deamonは下記のコマンドで停止することができます。

systemctl stop xdk-daemon

iBeaconの確認用アプリの作成

せっかくiBeacon化しても確認をする方法が必要です。

使っているMacBook ProにはBluetoothがあるので、それらを用いて確認することとします。

package.json

{
  "name": "PC_iBeacon",
  "version": "1.0.0",
  "description": "PC_iBeacon ===============",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "http://localhost:8080/git/yutaka/PC_iBeacon.git"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "bleacon": "^0.2.0"
  }
}

main.js

'use strict';
var bleacon = require('bleacon');
var uuid = 'AD2E48C690224BB3AAE7CCBFE17DDE4E';
bleacon.startScanning(uuid.toLowerCase());
bleacon.on('discover',function(bleacon){
    var date = Date.now();
    console.log(date);
    console.log(bleacon);
});

uuidはEdison側で書いたものと同一のものになります。 また、uuidは小文字である必要があるので、15行目でtoLowerCaseで小文字にしています。

起動方法

npm install (初回のみ)
node main.js

起動後、Edison側のスイッチを押下すると以下の様な情報が表示されます。

1420537939980
{ uuid: 'ad2e48c690224bb3aae7ccbfe17dde4e',
  major: 0,
  minor: 0,
  measuredPower: -59,
  rssi: -46,
  accuracy: 0.4398670722282996,
  proximity: 'immediate' }
1420537940605
{ uuid: 'ad2e48c690224bb3aae7ccbfe17dde4e',
  major: 0,
  minor: 0,
  measuredPower: -59,
  rssi: -45,
  accuracy: 0.41293780149195125,
  proximity: 'immediate' }
  ・・・

小ネタ編

iBeaconが受信できましただけでは面白く無いので、少し改良をしてみました。

main.js

'use strict';
var bleacon = require('bleacon');
var uuid = 'AD2E48C690224BB3AAE7CCBFE17DDE4E';
var exec = require('child_process').exec;
var screenLock = function(callback) {
    var command = '"/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/CGSession" -suspend';
    exec(command,function(err){
        var message;
        if(!err){
            message = 'suspent';
        }
        callback(err,message);
    });
};
bleacon.startScanning(uuid.toLowerCase());
bleacon.on('discover',function(bleacon){
    var date = Date.now();
    console.log(date);
    console.log(bleacon);
    if(bleacon.proximity === 'far'){
       screenLock(function(err,message){
           console.log(err,message);
           process.exit();
       });
    }
});

iBeaconを初めて知った時に、これでPCから離席するときに自動でスクリーンロックとか実現できるのではと思い、 いつの日か試してやろうと考えていました。

そんな思いを実現したのが上記のプログラムとなります。

挙動としてはiBeaconとPCがある程度離れるとスクリーンロックされます。 また、スクリーンロックが複数実行を行わせないようにするため、 スクリーンロックが実行された際にはプログラムは終了します。

参考サイト

Intel EdisonをiBeacon化する. - 椎茸糞日記