obnizをLineSimpleBeacon化する


obnizはLineBeaconになれるのか？と質問があったので，試してみました．

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">LINE BOOT AWARDSに関連してひとつ質問させて頂きたいのですが、obnizでLINE Beaconを動作させることは可能でしょうか？<br>ESP32で動作させることは可能なようなのですが…<a href="https://t.co/5JEzoMsYFo">https://t.co/5JEzoMsYFo</a></p>&mdash; 田中みそ (@miso_develop) <a href="https://twitter.com/miso_develop/status/1032435838741692416?ref_src=twsrc%5Etfw">August 23, 2018</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 


# LINE Beaconの概要

特定のadvertisementを出しているBeaconをLineが発見するとbotのwebhookに，beaconが見つかったよと通知を出します．
サーバー側で，そのbeacon情報をもとにどういう処理をするか決めて，対応します．

例だと，商品に付いてるボタンを押したらその商品の情報がbotから送られてくる　などがありました．

# LINE の設定

[Line Developer](https://developers.line.me/ja/services/messaging-api/)のサイトで，messaging apiを使ったbotを作成します

通知がきたときの処理をするために，LINE Developersのbot設定画面でWebhookを設定します


![スクリーンショット 2018-08-26 14.44.06.png](https://qiita-image-store.s3.amazonaws.com/0/227015/aa69d4f0-73b1-e139-770a-a27473e8f260.png)

HTTPSサーバーが必要なので，[runkit](https://runkit.com)を使いました
  ※runkitはnode.jsの無料ホスティングサービスです．httpsのリクエストが受け付けられるので重宝しています



作ったbotとは友だちになっておきます．
そうしないと通知が来ないです

# LINE Beaconの設定

[LINE@ Managerのビーコン登録画面](https://admin-official.line.me/beacon/register/#/)から，LINE Simple BeaconのハードウェアIDの払い出しをします，

![スクリーンショット 2018-08-26 14.57.20.png](https://qiita-image-store.s3.amazonaws.com/0/227015/f76886f5-0624-8f93-c278-9dcaf3f68d93.png)


# obnizのコード

advertisementを作るだけなのでobnizの知識というよりは，bleの知識になります．
deviceMessageとhardwareId以外は固定なので，とりあえずはそこをいじれば使えます．

```javascript

var obniz = new Obniz("XXXXXXXX");
obniz.onconnect = async function () {
  
  var adv = [];
  var UUID_FOR_LINECORP = [0x6F, 0xFE];
  var deviceMessage = [01,02,10];  //サーバーに送るメッセージ　1~13byte
  var hardwareId = [0x01, 0x16, 0xcb, 0xf3, 0x79 ]; //払い出されたID（元：0116cbf379）

  
  // flag
  adv = adv.concat([0x02, 0x01, 0x06]);  //LE General Discoverable Mode & BR/EDR Not Supported
  
  //16bit uuid
  adv = adv.concat([0x03, 0x03]);
  adv = adv.concat(UUID_FOR_LINECORP);
  
  //simple beacon
  adv = adv.concat([1+9+deviceMessage.length, 0x16]);
  adv = adv.concat(UUID_FOR_LINECORP);
  adv = adv.concat([0x02]);
  adv = adv.concat(hardwareId);
  adv = adv.concat([0x7F]);
  adv = adv.concat(deviceMessage);
  
  
  obniz.ble.advertisement.setAdvDataRaw(adv);
  obniz.ble.advertisement.start();
}

```


`adv = adv.concat([ ... ]);`でadvertisementを作り，` obniz.ble.advertisement.setAdvDataRaw(adv);`でそれをobnizにセットし，` obniz.ble.advertisement.start();`で開始しています．

# サーバー上のコード

runkitで書きました．そのため，生のnode.jsとは少しだけ違いますが，ほとんど同じです．
(expressのlistenをしてなかったり，requireするものが違ったりする程度です．)

```javascript
const express = require("@runkit/runkit/express-endpoint/1.0.0");
const app = express(exports);
const line = require('@line/bot-sdk');

// create LINE SDK config from env variables
const config = {
  channelAccessToken: "",
  channelSecret: "",
};

// create LINE SDK client
const client = new line.Client(config);

// register a webhook handler with middleware
// about the middleware, please refer to doc
app.post('/',  line.middleware(config), (req, res) => {
  Promise
    .all(req.body.events.map(handleEvent))
    .then((result) => res.json(result))
    .catch((err) => {
      console.error("ERROR");
      console.error(err.message);
      res.status(500).end();
    });
});

// event handler
function handleEvent(event) {
  console.log(event);
  if (event.type === 'message' && event.message.type === 'text') {
    const echo = { type: 'text',  text: event.message.text };
    console.log(echo)
    return client.replyMessage(event.replyToken, echo);
    
  }else if(event.type === 'beacon' && event.beacon){
    const message = { type: 'text', text: `beacon device(${event.beacon.hwid})から${event.beacon.dm}が届いたよ` };
    console.log(message)
    return client.replyMessage(event.replyToken, message);

  }
    return Promise.resolve(null);
}


```


重要なのは`handleEvent(event)`の中身です．
`event.type`が`beacon`だったらbeacon情報なので，返信のメッセージを変えています．
通常はエコーにしています

これに，channelAccessTokenとchannelSecretをつければ動きます．

## 動かした

<img width="375" alt="IMG_8546.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/227015/80ac649d-4a68-7063-cc68-be2565418cdc.png">

## さいごに

obnizには[スイッチを押したらプログラムを走らせる機能](https://qiita.com/yukisato1987/items/f04bebef7c89897cc51e)もあるので，スイッチを押す→beaconを出す→LINE beaconで検知→LINEになにか出す　ということもできそうです

動的にdeviceMessageの中身を変えることもできるので，今までの独立型beaconではできなかったことがいろいろできるかもしれませんね


# 参考

[LINE Beacon Document](https://github.com/line/line-simple-beacon/blob/master/README.ja.md)
[ESP32でLINE Simple Beaconを2000円弱で作ってみた](https://qiita.com/stachibana/items/758e68372088413fcd8d)