[3分クッキング♪] 余っていたM5StickCでLINE Beacon化してみた！

この投稿は [IoTLT Advent Calendar 2019](https://qiita.com/advent-calendar/2019/iotlt_neo)の11日目の投稿です。

こんにちは！もちゃんと申します！
LINE ThingsやLINE Beaconが好きです。

この夏、**[LINE Thingsのアワード](https://engineering.linecorp.com/ja/blog/line-things-mini-award-2019/)**が開催され、私もたくさんの作品を応募し大盛況のうちに幕を閉じました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/0b23de68-c06d-c7fb-4d29-c1709fbf8e77.png)

作品を応募するにあたり、多くのセンサーやデバイスを購入していたのですが**M5StickC**に関しては安かった(1,000円ぐらい)のもあり気が付いたら**余るレベルの数を購入**しておりました...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/89bcf1ed-9e02-2764-b0c1-8543b4728e92.png)

下記は**[LINE対応ビーコン](https://beacon.theshop.jp/items/6617930)**ですが何か**M5StickC**と形似てませんか？もうM5StickCがビーコンにしか見えなくなりました。少なくとも私はそう思います。(余ってるし)こいつをビーコン化してやろうと...(2019年秋)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/b75fe83a-d8fa-7ab8-958d-710919b2cc9f.png)


## はじめに

前置きが長くなりました。。
今回はオープンなLINE Beaconデバイスの仕様である、「[LINE Simple Beacon](https://engineering.linecorp.com/ja/blog/detail/117/)」の仕組みを使ってLINE Beacon化していきます。

### LINE Simple Beaconとは

>LINE Simple Beaconとは、LINE Bot開発者向けのビーコンデバイス仕様です。 LINE Simple BeaconはBluetooth Low Energy (以下、「BLE」という)の仕様にもとづいており、 汎用のデバイスでLINE Beaconのサービスを利用することを可能とします。

https://github.com/line/line-simple-beacon/blob/master/README.ja.md

## さっそくBeacon化してみる

### 必要なもの

* 余ったM5StickC
* LINE Bot
* LINE Beacon化したいと思うお気持ち

### 事前準備

事前にLINE Botが必要になります。
ここでは簡単にですが、下記にLINE Botの準備手順を記載します。


#### ◆ まずMessaging APIのチャネルを作成します。

下記URLからチャネルを作成します。
https://developers.line.me/ja/services/messaging-api/
作成後、Messaging API設定タブに移動し、QRコードでBotと友だちになっておきましょう。
![スクリーンショット 2019-12-12 0.49.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/cfc5114c-e2e8-d899-b1ea-9f7fc140a391.png)


#### ◆ そしてwebhookの設定

webhook URLを入力し、webhookの利用をONにします。
![スクリーンショット 2019-12-12 0.07.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/f322f0aa-f7ec-964a-a06c-c3d807ec6db6.png)

#### ◆ 応答メッセージの無効

応答メッセージを利用しないので編集ボタンからLINE公式アカウント画面で無効にしましょう。
![スクリーンショット 2019-12-12 1.01.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/a66186ee-17eb-d726-d400-bef47aaa4cca.png)

#### ◆ LINE Bot のコードは下記のような感じです

```javascript

'use strict';

const line = require('@line/bot-sdk');

const config = {
    channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
    channelSecret: process.env.CHANNEL_SECRET
};

const client = new line.Client(config);

module.exports = async( req, res ) => {
  Promise
    .all(req.body.events.map(await handleEvent))
    .then((result) => res.json(result))
    .catch((err) => {
      console.error(err);
      res.status(200).end();
    });
};

// event handler
async function handleEvent(event, session) {
  console.log(event);
  let echo = [];
  // 参考：https://developers.line.biz/ja/reference/messaging-api/#beacon-event
  if (event.type === 'beacon') {
    if (event.beacon.type === 'enter') {
      // LINE Botと友だちになっている方がLINE Beaconの近くにきたら、その人の情報を送る
      await client.pushMessage(process.env.USER_ID, [
        { 'type': 'text', 'text': event.source.userId + 'さんが来店しました。' }
      ]);
    }
    return;
  } else if (event.type === 'follow') {
    return;
  } else {
    echo = { 'type': 'text', 'text': '申し訳ありませんが、お返事できません。' }; 
  }

  // use reply API
  return client.replyMessage(event.replyToken, echo);
}
```

※ 上記では[プッシュメッセージ](https://developers.line.biz/ja/reference/messaging-api/)機能を使ってLINE Botにメッセージを送信しています。1か月あたり1,000通までの制限はありますが無料でも利用できます。
https://engineering.linecorp.com/ja/blog/line-developer-trial-migration/

### LINE Beacon化の作業

ここからがLINE Beacon化の作業です。
下記の手順に従えば3分ぐらいでいけると思います！

#### ◆ 環境構築

[Arduino IDE](https://www.arduino.cc/en/main/software)はお手持ちのPCに入っている前提で

ESP32のボード開発用のライブラリをインストールしていきます。
メニューバーの「Arduino」->「Preference（環境設定）」を開きましょう。
![スクリーンショット 2019-12-12 8.46.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/1fedce10-7c7d-e09f-c128-ae363ac2622b.png)

https://dl.espressif.com/dl/package_esp32_index.json
上記をコピーして、赤枠に入力して、「OK」ボタンを押しましょう。
![スクリーンショット 2019-12-12 8.49.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/b677f3a8-310a-3551-8ee0-03af76b56389.png)

次にメニューバーの「ツール」->「ボード」->「ボードマネージャー」を開きましょう。
![スクリーンショット 2019-12-12 8.49.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/e0bd308c-70d2-cdb4-5bd0-1a3e6a2fbe53.png)

上の入力欄にESP32を検索して表示されたたものをインストールしていきます。
![スクリーンショット 2019-12-12 8.52.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/32389194-c059-ee96-8af6-32fa98d918cc.png)

次にM5StickCのライブラリをインストールします。「ツール」->「ライブラリを管理」を開きましょう。
![スクリーンショット 2019-12-12 8.54.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/b3e94400-9ac5-dbb3-beb1-46b0f5e74591.png)

同様に入力欄にM5StickCで検索し赤枠をインストールしましょう。
![スクリーンショット 2019-12-12 8.55.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/90f556de-9a07-63c5-f6c3-fb9eda8f7e4f.png)

M5StickCをPCと接続して、メニューバーの「ツール」から下記のように設定をします。他はデフォルトのままでOKです。
![スクリーンショット 2019-12-12 8.57.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/7b2da0cb-3783-42ca-126d-7ee8e79234a3.png)

上記のインストールを進めながら、下記のLINE Simple BeaconのハードウェアIDの設定も実施します。

#### ◆ LINE Simple BeaconのハードウェアID

下記URLから [LINE Simple BeaconのハードウェアIDを発行]ボタンを押します。
https://manager.line.biz/beacon/register
![スクリーンショット 2019-12-12 1.25.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/675d656d-b9fd-c2cc-a5a0-484423676b6b.png)


アカウントリストから、上記で作成したチャネルの選択ボタンを押して、ハードウェアIDを発行します。
![スクリーンショット 2019-12-12 0.56.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/9f0aedde-5f69-9ca8-aba2-636adedafc43.png)

![スクリーンショット 2019-12-12 1.03.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/0ce159bc-9108-0662-1d28-ec70906218a0.png)

発行したハードウェアIDをM5StickCのコードの「YOUR_HWID」に書き換えます。
![スクリーンショット 2019-12-12 0.56.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/da752543-4e48-ec0b-1dc7-0f14eb9a75a2.png)


#### ◆ M5StickCのコードは下記のような感じです

下記がM5StickCをLINE Simple Beaconとして動作させるコードになります。Arduino IDEを使って書き込みます。

```c

#include <M5StickC.h>
#include <string>
#include "BLEDevice.h"
#include "BLEAdvertising.h"

/**
 * Bluetooth TX power level(index), it's just a index corresponding to power(dbm).
 * * ESP_PWR_LVL_N12 (-12 dbm)
 * * ESP_PWR_LVL_N9  (-9 dbm)
 * * ESP_PWR_LVL_N6  (-6 dbm)
 * * ESP_PWR_LVL_N3  (-3 dbm)
 * * ESP_PWR_LVL_N0  ( 0 dbm)
 * * ESP_PWR_LVL_P3  (+3 dbm)
 * * ESP_PWR_LVL_P6  (+6 dbm)
 * * ESP_PWR_LVL_P9  (+9 dbm)
 */
#define POWER_LEVEL ESP_PWR_LVL_P9

// 発行したハードウェアIDを書き換える
#define HWID "YOUR_HWID"
bool beaconFlg = false;

BLEAdvertising *pAdvertising;

std::string hexEncode(std::string raw) {
  const char *hexMap = "0123456789abcdef";
  std::string hex = "";
  for(int i=0; i<raw.size(); i++) {
    hex += hexMap[(raw[i] >> 4) & 0x0F];
    hex += hexMap[raw[i] & 0x0F];
  }
  return hex;
}

int htoi (unsigned char c)
{
  if ('0' <= c && c <= '9') return c - '0';
  if ('A' <= c && c <= 'F') return c - 'A' + 10;
  if ('a' <= c && c <= 'f') return c - 'a' + 10;
  return 0;
}

std::string hexDecode(std::string hex) {
  if (hex.size() % 2) return "";
  std::string raw = "";
  for(int i=0; i<hex.size(); i+=2) {
    raw += (char) ( htoi(hex[i]) * 16 + htoi(hex[i+1]) );
  }
  return raw;
}

bool setLINEBeacon (std::string hwid, std::string msg) {
  // check hwid
  if (hwid.size() != 5 || msg.size() > 13) return false;

  BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
  BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
  BLEUUID line_uuid("FE6F");

  // flag
  // LE General Discoverable Mode (2)
  // BR/EDR Not Supported (4)
  oAdvertisementData.setFlags(0x06);

  // LINE Corp UUID
  oAdvertisementData.setCompleteServices(line_uuid);

  // Service Data
  std::string payload = "";
  payload += (char) 0x02; // Frame Type of the LINE Simple Beacon Frame
  payload += hwid; // HWID of LINE Simple Beacon
  payload += 0x7F; // Measured TxPower of the LINE Simple Beacon Frame
  payload += msg; // Device message of LINE Simple Beacon Frame
  oAdvertisementData.setServiceData(line_uuid, payload);

  pAdvertising->setAdvertisementData(oAdvertisementData);
  pAdvertising->setScanResponseData(oScanResponseData);
  return true;
}

void setup() {
  M5.begin();
  BLEDevice::init("");
  esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, POWER_LEVEL);
  pAdvertising = BLEDevice::getAdvertising();

  M5.Lcd.setCursor(0, 30);
  M5.Lcd.print("Ready");
}

void loop()
{
  // The underlying framework will advertise periodically.
  // we simply wait here.
  if (digitalRead(M5_BUTTON_HOME) == LOW) {
    if (!beaconFlg) {
      // LINE BeaconをONにする
      setLINEBeacon(hexDecode(HWID), hexEncode(std::string((const char*) BLEDevice::getAddress().getNative(), 6)));
      pAdvertising->start();
      M5.Lcd.fillScreen(BLACK);
      M5.Lcd.setCursor(0, 30);
      M5.Lcd.print("line beacon! ON");
      beaconFlg = true;
    } else {
      // LINE BeaconをOFFにする
      //// LINE Beaconをストップする機能は現在動作しないようです。下記URLを参考にしてください。
      //// https://github.com/nkolban/esp32-snippets/issues/797
      pAdvertising = BLEDevice::getAdvertising();
      pAdvertising->stop();
      M5.Lcd.fillScreen(BLACK);
      M5.Lcd.setCursor(0, 30);
      M5.Lcd.print("line beacon! OFF");
      beaconFlg = false;
    }
    while(digitalRead(M5_BUTTON_HOME) == LOW);
  }
}
```

これでLINE Beacon化完了です！


## 活用アイディア
ジャストアイディアですが、お得意さんが来店された時に名前思い出せないッ!...みたいな時にもLINE BeaconとLINE Botで来店時にお客様のuserIdからお名前をそっと教えてくれる仕組みとか色々できそうではないでしょうか！(LINEのuserIdと顧客情報を紐づける仕組みは別途必要)


## その他、LINE Beacon活用事例など

* LINE DEVELOPER DAY 2019でもLINE Beaconを活用した可視化の取り組みがあったようです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/00f5f7ee-7228-c4cb-9ce8-59fcec3e4936.png)

[https://speakerdeck.com/line_devday2019/the-iot-technology-inside-line-developer-day-2019?slide=11](https://speakerdeck.com/line_devday2019/the-iot-technology-inside-line-developer-day-2019?slide=11)

* 出退勤をLINE Beaconで自動化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/7bc18c13-48f1-e0f8-37d7-4185e9066567.png)

[https://www.slideshare.net/linecorp/line-beacon-assists-employees-who-forget-to-clockin-and-out-124004111](https://www.slideshare.net/linecorp/line-beacon-assists-employees-who-forget-to-clockin-and-out-124004111)


他にも様々な場面でLINE Beaconは活用されています。


## お・ま・け

ちなみに、Micro:bit ならもっと簡単にLINE Beacon化できるやり方がありますので下記のハンズオン資料を参考にしていただけれ幸いです。

* LINE Simple Beacon × Micro:bit ハンズオン
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121860/084a71dc-8d57-8cd0-336b-34ce6f4912fa.png)](https://speakerdeck.com/mochan_tk/line-simple-beacon-microbit-hands-on)
https://speakerdeck.com/mochan_tk/line-simple-beacon-microbit-hands-on


## まとめ

LINE Botと友達になるだけでLINE Beaconと連携できる手軽さが良いですよね。
既存のBotにも活用できると思いますので、新しい展望が出てくる可能性もあるのではないでしょうか。
年末年始でお時間ある方も是非試してみてください。

## 参考情報
* https://developers.line.biz/ja/docs/messaging-api/using-beacons/