LINE Things dev board使用ハンズオン

# LINE Things dev board ハンズオン

![image.png](https://qiita-image-store.s3.amazonaws.com/0/354978/b3ab0103-d8b6-ddda-1713-dae5bdef8057.png)


こちらの記事は[LINE Things dev board](https://github.com/line/line-things-dev-board)を使用したLIFFベースのLINE Thingsハンズオンマニュアルです。ESP32を使用したハンズオンはこちらを、
https://qiita.com/hktechno/items/bb83cc898c75819b2664

Dev boardの自動通信のハンズオンマニュアルはこちらを参考にしてください。
https://qiita.com/hktechno/items/12781e38b09e10c20da2


# 講師紹介
伊藤剛浩

* LINE 株式会社 Search&Clovaセンター Clova開発室 (2019年5月現在)
* 2015年 セキュリティ・キャンプ全国大会 講師
* [Open Design Computer Project](http://open-arch.org/)
    * FPGA 上でオリジナルの 32bit アウトオブオーダー実行 CPU を作るプロジェクト
    * 2011年度 未踏IT人材発掘・育成事業 採択・スーパークリエイター
    * [独自CPU開発で学ぶコンピュータのしくみ](https://www.shuwasystem.co.jp/book/9784798045368.html) 作者 1/2

# 今日の流れ
このハンズオンでは実際にLIFFやファームウェアの変更をせずに、dev boardを使って最低限の操作でLINE Thingsを開始する方法と、デバイスとLIFFがどのように連携をしているかを学んでいただきます。

 - LINE Things と Bluetooth LE について
 - LINE Things で開発のために作ったデバイスの説明
 - LINE Things Developer Trial で開発を行うための準備
 - LINE Things dev board の紹介
 - LINE Things dev board を利用して、LINE Things を体験する
 - 時間が余った人
 - LINE Things を利用したちょっとしたガジェットの作例紹介
 - 懇親・質問タイムなど


# 目標
デバイスにご自身で取得したService UUIDを設定して、LINE App上から、dev boardに乗っているデバイスの情報を取得したり、LEDのコントロールをできるようにします。

# 必要なもの

* USB が使える PC (Windows / Mac)
* LINE の最新版 (>= 8.16) をインストール済の Android か iPhone
    * iPhone 4S 以下では iOS および LINE アプリ最新版が対応しておらず、利用不可能です
    * iPad の LINE appはLINE Thingsに対応していないため利用不可能です
* [LINE Things dev board](https://github.com/line/line-things-dev-board)
* Micro-USB to USB ケーブル
* Atom, Visual Studio Codeなどの適当なエディタ

# 準備
ハンズオンをスムーズに進めるために、参加前にこれらを準備しておいてください。

* 重要なこと
    * 必ずLINE Appを最新版にアップデートしてください
    * LINE Developersで開発者登録をしておいてください
    * Windowsの方は予めcurlコマンドが使えるか確認しておいてください
* 応用編まで行いたい場合
    * Arduino IDEとAdafruit nRF52 by Adafruit 環境のインストール
    * CP2102N ドライパのインストール


# 心得
わからないことがあったら積極的にスタッフを呼んで聞いてください。

限られたハンズオンの時間なので、自分で悩んで考えるより手を動かすことに時間を使ってください！

# ハッシュタグ

`#linethings`

デバイスの写真や本日の内容は、自由に Twitter などへ投稿してもらって構いません。
困ったこと、ご意見等も待ちしております！


# LINE Things と Bluetooth LE について

まずは LINE Things の概要について説明します。それと合わせて、 Bluetooth LE についても多少の知識が必要なのでまずはこれらを説明します。

こちらのページを開いてください。

https://qiita.com/hktechno/items/bb83cc898c75819b2664#line-things-%E3%81%A8%E3%81%AF


# LINE Things dev boardの紹介

![motherboard (4).jpg](https://qiita-image-store.s3.amazonaws.com/0/354978/565bd500-55ba-ba4e-c8c2-ac1ad37ad836.jpeg)


今日これから使用するLINE Things dev boardを紹介します。dev boardにはこのようなデバイスが乗っています。

* 入力デバイス
    * スイッチ
    * 3軸加速度センサ
    * 温度センサ
* 出力デバイス
    * LED
    * OLEDディスプレイ
    * ブザー
    * モーターコントローラ(初期状態未実装)

いくつかの部品は未実装です。今回のハンズオンでは使いませんが、家に持ち帰ってからつくってみてください。

このような入出力デバイスを、LINE AppのLIFFから制御することができます。今回使用していただくLINE Things dev boardは、予めファームウェアが書き込まれていて、今回はそのファームウェアをそのまま使用してLINE Thingsの機能を試してみます。

ピンアサインやファームウェア等、より詳しい情報はこちら。

 * [LINE Things dev board](https://github.com/line/line-things-dev-board) 

## デフォルトファームウェアで Service UUID書き換え機能について

デフォルトファームウェアにはAdvertising packet の Service UUID を書き換える機能が搭載されています。

LINE Things対応デバイスとするには、Advertising Packet に LINE Things プラットフォームに登録された、プロダクト独自の Service UUID (サービス探索用 Service UUID) を含める必要があります。

このAdvertising packetのService UUIDでLINE Thingsへの対応の有無や、登録された情報と紐づけてどんなプロダクトかどうかという情報をLINE App側が知ることができます。

そのため、このService UUIDは、ご自身で取得したUUIDを書き込む必要があります。今回皆さんにはこの作業を行っていただきます。


# LINE Developers にてプロダクトの登録とService UUIDの取得

まずはService UUIDを取得します。これから行う手順は次のとおりです。

 * 新規 Messaging API チャンネル (LINE Bot) の作成
 * 新規 LIFF アプリの作成 + Bluetooth LE 機能の付与
 * 新規 LINE Things dev board プロダクトの作成と GATT Service UUID の発行
 * dev boardのUUIDを書き換え
 
基本的には、LIFF も LINE Things も LINE Bot 機能の延長線 として開発されているので、Bot やメッセージングと連携するデバイスの実現を目的としています。

なので、デバイスが LINE Things を利用するためにはチャンネル (Bot) が必要で、そのチャンネルに結びついた LIFF アプリの作成が必要となっています。
(もちろん、LINE Things をただ Bluetooth LE デバイスのフロントエンドとして利用することも可能です)

この準備が終わると、LIFF やデバイスのファームウェア開発をすぐに開始することが出来ます。

まずは GATT Service UUID を発行するために、開発者登録とプロバイダー作成をしましょう。

## LINE Developers の開発者情報登録とプロバイダーの作成

![image.png](https://qiita-image-store.s3.amazonaws.com/0/354978/359bf0a2-0e9c-ce1f-b38f-47e52c8ffdbe.png)


以下の手順を参考に、LINE Developers コンソールにログインして開発者情報を登録してください。
(すでにされている方は不要です)

 * [LINE Developers コンソールにログインする](https://developers.line.biz/ja/docs/line-things/login-console/)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/354978/70185395-dfcf-f531-ad3e-ce95c419dff8.png)




次に、LINE の Bot を作るためのプロバイダーを作成してください。
(すでに作成してあるプロバイダーを利用する方は不要です)

 * [プロバイダーを作成する](https://developers.line.biz/ja/docs/line-things/create-provider/)

###Messaging API のチャネル (LINE Bot) の作成

![image.png](https://qiita-image-store.s3.amazonaws.com/0/354978/96af577d-1804-1375-c977-4ca188a024ac.png)



以下の手順を参考に、Messaging API のチャネルを作成してください。このチャネル (Bot) をもとに、LIFF や LINE Things プロダクトの情報が結びつきます。

[Messaging APIのチャネルを作成する](https://developers.line.biz/ja/docs/line-things/create-channel/)

⚠注意 チャネルの名前に "LINE" を含めることが出来ません。原因不明のエラーになるので、LINE という文字列を指定しないでください。

ここで、 **必ず自分の LINE アカウントで、作成した LINE Bot と友だち** になっておきましょう。 LINE Things Developer Trial では、 **プロダクトが結び付けられているチャネルの Bot と友達のユーザーにのみ、そのプロダクトが連携画面に表示** されるようになります。 **チャンネル基本設定** タブの下の方にある **QRコードを使って友達登録** してください。

### LIFF アプリの準備と作成
次に、LIFF (LINE Front-end Framework) アプリの準備を行います。

通常、LIFF アプリを作成するには、そのエンドポイントを提供する Web サーバーが必要になります。今回使用しているデモの　LIFF は、静的な HTML と JS を提供するだけでよいので、 GitHub Pages を利用します。


#### GitHub Pages のデプロイ
<img width="775" alt="0760b7ec886f16877173b98a12ba7db2.png" src="https://qiita-image-store.s3.amazonaws.com/0/354978/4eec5948-d396-57bd-c9ef-d3012193db5e.png">


自分の GitHub アカウントで [LINE Things dev board](https://github.com/line/line-things-dev-board) を Fork して、GitHub Pages にデプロイします。

LINE Things dev board のリポジトリ を GitHub で Fork した後、Settingsタブを開き、GitHub Pages の Source を master branch に変更してください。

その後、"Your site is published at {URL}" と表示されるはずなので、この URL に `liff-app/linethings-dev-default/` を末尾につけたものが LIFF のエンドポイント URL になります。

```
注意！
必ずURLの一番最後に "/" をつけてください。
OK : liff-app/linethings-dev-default/
NG : liff-app/linethings-dev-default
```

#### LIFF アプリの作成と BLE feature の付与


<img width="1431" alt="e0e95baf8668729908ed721e438f404c.png" src="https://qiita-image-store.s3.amazonaws.com/0/354978/7b83f7bf-5f32-bc1e-3497-0a19658bfe70.png">



その後、デプロイされた URL をエンドポイント URL として LIFF を作成します。
LINE Things 向けの LIFF を作成する際には、 **BLE feature を ON** に設定する必要があります。
この設定がないと、LIFF の Bluetooth LE プラグインが有効にならず、その LIFF 上では LINE Things の機能を動作させることが出来ません。

公式ドキュメント内の [チャネルにLIFFアプリを追加する](https://developers.line.biz/ja/docs/line-things/regist-liff-app/) では、curl を利用したコマンドラインからの LIFF の作成手順を紹介していますが、現在は LINE Developers コンソールから LIFF の作成が行えるようになりました。

まず、LIFF を作成したいチャンネルを選択して、"LIFF" のタブを開いてください。
上記のような画面が表示されるので、⊕追加 ボタンを押します。

<img width="1091" alt="fde95d08c74cba73f5978362f9bf1df9.png" src="https://qiita-image-store.s3.amazonaws.com/0/354978/b2f3e018-26e5-3914-7a8d-5cc03bc53cb0.png">


LIFF の追加ポップアップが現れます。
まずは、BLE feature を ON にしましょう。こうすることで、LIFF 内で LINE Things 向けの BLE 通信機能が使えるようになります。

LIFF の名前は、何でも良いので適当に入力してください。
サイズは、Full を押すと全画面で LIFF が表示されるので、まずはこれをおすすめします。
エンドポイント URL には、先ほど作成した GitHub Pages の URL を入力してください。
最後に保存するを押してください。

<img width="563" alt="365cb0b88231a90018371a73b82c7643.png" src="https://qiita-image-store.s3.amazonaws.com/0/354978/dd508fee-5a63-d027-bccd-701f2aa0ea89.png">



作成が完了すると、上のように LIFF URL という項目が表示されます。
この URL をメモしておきましょう。プロダクトの作成のために利用します。

### LINE Things プロダクトの作成
LIFF の作成が完了したら、この情報をもとに LINE Things の新しいプロダクトを作成します。
LINE Things Developer Trial 専用の API を利用して、新しい LINE Things プロダクトを作成します。

その前に、まずお使いの PC に curl コマンドが入っているかどうか確認してほしいです。
(残念ながら、現在こちらは Web UI は提供されていませんので、REST API のみとなります...)

 * Windows をお使いの方: PowerShell を開いて `curl.exe --help` と入力して、ヘルプが表示されれば問題ありません。最近の Windows 10 では標準でインストールされていることが多いです。curl (.exe なし) は、ここで扱う curl と違うコマンドにエイリアスされているので使用しないでください。
    * 無事 curl.exe の存在が確認された方: PowerShell では、改行に使っているバックスラッシュ \ を認識できません。削除して1行につなげてコマンドを入力してください。また、JSON の " を \ でエスケープする必要があります。
    * `curl.exe` が見つからない方: 公式ドキュメントの REST APIを利用する を参考に、Invoke-WebRequest を使って API を実行してください。
 * Mac/Linux をお使いの方: おそらく、最初からインストールされています。`curl --help` と入力して、ヘルプが表示されていれば問題ありません。

curl が使えることがわかった方は、以下の公式ドキュメントを参考に　LINE Things Developer Trial 専用 API を利用してプロダクトを作成します。

 * [トライアルプロダクト情報を作成する](https://developers.line.biz/ja/docs/line-things/regist-product/)

以下がプロダクト作成 API を curl コマンドを利用して実行してみた例です。

```
curl -X POST https://api.line.me/things/v1/trial/products \
-H 'Authorization: Bearer <channel access token>' \
-H 'Content-Type:application/json' \
-d '{
  "name": "<trial product name>",
  "liffId": "<LIFF APP ID>"
}'
```

Windowsの方はこちら

```
curl.exe -X POST https://api.line.me/things/v1/trial/products -H 'Authorization: Bearer <channel access token>' -H 'Content-Type:application/json' -d '{\"name\": \"<trial product name>\", \"liffId\": \"<LIFF APP ID>\"}'
```

`name` には、好きなプロダクト名を登録することが出来ます。自分の Product だと分かる名前を設定しましょう。"LINE Things dev board" などありきたりな名前を入れると、同じようなプロダクトを何種類か登録したりしたときに、どのプロダクトと連携したのかがわかりにくくなってしまいます。
`liffId` には、上記で作成した LIFF アプリの ID (LIFF URL の line://app/ 以降の文字列) を指定してください。

`channel access token` は、LINE の Channel API を叩くためのトークンで、LINE Developers コンソールの作成したチャンネルの、チャンネル基本設定タブから取得することができます(表示されてない場合は再発行ボタンを押してください)。チャンネル (Bot) ごとに違う値となっています。

 * [アクセストークン（ロングターム）を発行する](https://developers.line.biz/ja/docs/line-things/create-channel/#preparing-channel-access-token)

上記のプロダクト作成 API を叩くと、以下のような結果が帰ってきます。
LINE Things の Developer Trial 向けプロダクトでは、プロダクトを作成すると専用の Bluetooth LE の GATT Service UUID が発行されます。上記の結果に含まれる serviceUuid が、発行された UUID となります。


```
{
  "id": {productId},
  "name": "{trial product name}",
  "actionUri": "{LIFF APP URL}",
  "channelId": {channelId},
  "type": "BLE",
  "serviceUuid": "{serviceUuid}",
  "psdiServiceUuid": "{psdiServiceUuid}",
  "psdiCharacteristicUuid": "{psdiCharacteristicUuid}"
}
```

ここで発行されたUUIDは後でスマートフォンで使用します。スマートフォン側にコピーして、クリップボードにコピーしておいてください。

メールとか共有ノートなどで送っても良いですが、パソコンのLINEクライアントがインストールされている場合は、さきほど友達登録したbotにパソコンクライアント側から書き込み、スマートフォンのLINE Appのbotのメッセージからコピーすると便利です。

### プロダクト作成 API の Response について
--- ここから詳しい話 (理解していなくても無問題, 要 Bluetooth LE の知識) ---

デバイスは、 serviceUuid を Advertising Packet に含めることで、LINE アプリがデバイスを認識できるようになり、LINE Things に連携できるようになります。
つまり、LINE アプリは Advertising Packet に含まれる Service UUID の値を見て、プロダクトの種類を判別しています。なので、実際に実装されているサービスに関わらず、この値を Advertising する必要があります。
しかし、この UUID の GATT Service に何かしらの Characteristic を実装することは必須ではありませんし、LINE Things プラットフォーム上で操作できる GATT Service がこの UUID だけに制限されるわけでもありません。

psdiServiceUuid, psdiCharacteristicUuid は、デバイスを特定する ID (PSDI) を格納した Characteristic とそれを提供する GATT Service の UUID です。Developer Trial プロダクトでは固定の値です。LINE Things 対応プロダクトでは、この Characteristic を Read した時に、デバイスごとに変わる一意な値を返す必要があります。
詳しい仕様は、 [LINE Things対応デバイスを作成する](https://developers.line.biz/ja/docs/line-things/create-product/) をご覧ください。
LINE Things dev board では、デバイスがハードウェアで持っているIDを返しています。

--- 詳しい話終わり ---


## LINE から LINE Things デバイスを接続してみよう
おまたせしました。やっとLINE Things dev board と LINE App を触る時間がやってきました。

まずはデフォルトファームウェアのまま、初期状態のService UUIDを使用して LINE App から LINE Things dev board に接続してみようと思います。


LINE Things を利用するために、まずお使いの LINE をインストールしたスマートフォン上で、以下の QR コードを読み取って規約に同意していただき、LINE Things の機能を有効化してください。なお、すでにLINE Thingsを利用したことがある方はこの作業は不要です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/354978/cc42d152-c717-74f9-0cef-851597c46dfa.png)

その後、以下のようなデバイス連携画面が見えるはずです。一度有効化したら、次回からは `設定` → `LINE Things` からデバイス連携画面を開くことが出来ます。

![10.jpg](https://qiita-image-store.s3.amazonaws.com/0/354978/9e8ac0ec-2682-0082-94b3-debbbbe81555.jpeg)



LINE Things dev board にUSBケーブルを差し、ディスプレイに表示がされていることを確認します。 **デバイスとLINEがインストールされたスマートフォンを近づけて** `連携可能なデバイス` に `LINE Things dev board` が表示されていることを確認して、タップして LIFF を開きます。

もしデバイスがいくつか出ている場合は、とりあえず一番上のデバイスを選択して接続してみます。

- USBケーブルを差したけど動かない方
    - 左上にあるジャンパーピン(Power Select)で、上と真ん中が接続されていることを確認してください。

![S__5169157.jpg](https://qiita-image-store.s3.amazonaws.com/0/354978/68727d80-9037-94b0-5bde-19ef87efeea3.jpeg)

- LEDは光っているけどデバイスが動かない方
    - スタッフに言ってください。


`連携しました！今すぐ利用してみましょう` の画面が出たら `今すぐ利用` ボタンを押して、LIFFを開きます。

デフォルトのLIFFでは、一度に複数デバイスと接続できるように作られているため、この画面では近くにある全てのLINE Things dev boardが表示されているかと思います。

デフォルトファームウェアでは、すべてのLINE Things dev boardが同じ Service UUID でアドバタイズしているため、 **電波の届く限り、すべてのLINE Things dev boardに接続可能** になっています。

この状態では、デバイスとスマホを近づけ、 **一番電界強度が高いデバイス** と接続します。
よくわかりにくかったら、スマホをデバイスから近づけたり離したりすることで、 **電界強度の強弱から自分のデバイスを見つける** ことができます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/354978/53d0efcd-6c76-6b32-1b3f-6848372393cf.png" width=40%>

上の写真の例では一番上のデバイスが最も強い電波を発しています。

## Dev board に取得した Service UUID を設定
少し前のステップで自分独自のUUIDを取得していました。ここではその取得したUUIDを自分のデバイスに設定してみましょう。自分独自のUUIDをデバイスに設定することで、Advertiseのときに自分のデバイスのみが表示され、接続できるようになります。
本当はデバイスのファームウェアを書き換えて行う必要があるのですが、このボードのデフォルトサンプルファームウェアはUUIDをLIFF上から書き換えることができます。


行う手順は次のとおりです。

1. Write advertising packet書き換えタブを開く
2. 取得したService UUIDをテキストボックスに入れて書き換えボタンを押す


これでdev boardのディスプレイに「BLE advertising uuid changed from LIFF....」 と表示されていれば成功です。

**LINE AppのLINE Thingsを閉じて** 、 **dev boardのリセットボタンを押して** ください。

![IMG_2682.JPG](https://qiita-image-store.s3.amazonaws.com/0/354978/a6be5e29-4048-6c1c-5d1b-1571a33ee9c5.jpeg)

フォーマットの正しくないUUIDを書き込んでしまった場合はエラーメッセージが出るので正しいUUIDを再度書き込みましょう。

書き込んだAdvatising UUIDを初期状態に戻したい場合は、マザーボードのSW1を押しながらリセットボタンを押すと、初期状態に戻ります。



## 取得した Service UUID を用いて LINE からデバイスに接続してみよう
ここまで来た方、おめでとうございます。これで自分独自のデバイスをLINE Thingsとして利用できる準備が整いました。

まずは、先程、デフォルトのUUIDでLINE Thingsから接続してしまったので、そのデバイス情報を消しましょう。
スマートフォンの OS の Bluetooth デバイス連携画面からデバイス登録を解除し、その後 LINE App上の LINE Things のデバイス連携画面からも解除を行います。 

これで自分で設定したUUIDのDev boardに接続できる準備ができました。デバイス選択して開いてください。

NotifyタブのNotifyボタンを押してみましょう。LINE Things dev boardには加速度センサ、温度センサ、スイッチが搭載されています。
ボードを傾けるとX, Y, Zの値が変化し、温度センサを触ると取得される温度が変化することを確認します。同様に、スイッチの状態も取れていることを確認してください。

次に、Writeタブを開きます。LED2 ~ 5のチェックボックスにを ON/OFFしてdev board上のLEDが変化することと、Buzzerが反応することを確認してください。
GPIOはこのボード上以外のデバイスを操作するときに使いますが、その説明は応用編で。

皆さんお疲れ様でした。これでLINE上からデバイスを操作できるLINE Thingsを自由に使ってみることができます。


# 応用編
早く終わった方はデフォルトファームウェアとLIFFを改良して、追加機能を実装してみましょう。

## デバイスファームウェアを改変してみる
デバイスのファームウェア改良をするには、ファームウェア開発環境を構築する必要があります。このボードの開発にはArduino IDEを使用するので、まずはここからダウンロードしてインストールしてください。

[Arduino](https://www.arduino.cc/)

### Arduinoの環境構築

Arduino をインストールした後、ボードを接続せずに、以下の手順を実行してください。

1. Arduino IDE を開きます
2. Preferences を開いてください
3. 'Additional Board Manager URL' に `https://www.adafruit.com/package_adafruit_index.json` を追加します
4. Tools -> Board menu　から Boards Manager を開いてください
5. "nRF52" と検索して、Adafruit nRF52 by Adafruit をインストールしてください 

### CP2102Nドライバのインストール
Arduino のセットアップが終わったら、開発ボードの上の USB - UART シリアル変換チップ (ファームウェア書き込みに必要) のドライバをインストールします。

[CP210x USB to UART Bridge VCP Drivers](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers)


⚠ 注意 [Mac をお使いの方] ドライバをインストールしたあとセキュリティ保護のため、ドライバの実行が拒否される場合があります。
正しくデバイスが検出されませんので、以下の手順をインストール後に確認してください。

1. "システム環境設定" → "セキュリティとプライバシー" を開く
2. "ダウンロードしたアプリケーションの実行許可" より "許可" を行う
3. LINE Things dev board をつなげてみて、ls /dev/tty.SLAB_USBtoUART と実行して "No such file or directory" とならなければ、正しく認識されています


### LINE Things dev boardへ書き込み

まずはArduino IDEの`Tools` -> `Board` のリストから `Adafruit Bluefruit nRF52 Feather` を選択して、dev boardをUSBケーブルでPCに接続してください。


デフォルトファームウェアの書き込みをしてみることにします。

* [LINE Things dev board デフォルトファームウェア](https://github.com/line/line-things-dev-board/blob/master/arduino/linethings-dev-default/linethings-dev-default.ino)


このコードをコピーしてArduino IDEにペーストして `スケッチ` → `マイコンボードに書き込み` を実行してみてください。エラーなく書き込みが行われれば成功です。

### ファームウェアを少しだけ改造してみる

デフォルトのファームウェアでは起動後からずっと表示内容が変わりません。

```
LINE Things
X : 
Y : 
Z : 
...
```

起動時だけ起動メッセージみたいなものを表示するようにしてみましょう。

setup()関数の一番下に以下のプログラムを追加して書き込んでみましょう。起動時に5秒間起動メッセージが表示されれば成功です。

```C++
  // 起動メッセージを表示
  display.clearDisplay();       // ディスプレイのバッファを初期化
  display.setTextSize(1);       // テキストサイズ 1
  display.setTextColor(WHITE);  // Color White
  display.setCursor(0, 10);     // X=0, Y=10
  display.println("LINE Things");
  display.println("Hello world!");
  display.display();            // ディスプレイを更新
  delay(5000);
```

## OLEDにLINEから文字を書く
LINE AppのLIFFから文字を入力して、送信ボタンを押したらdev boardのOLED液晶にその文字が表示されるようにしてみます。表示できる文字は英数字のみで、最大16文字とします。

User Serviceに新しく文字を書き込むため専用のCharacteristicを追加します。
UUIDの生成は Online UUID Generator や `uuidgen` コマンドを利用して生成するのが良いと思います。

* [Online UUID Generator Tool](https://www.uuidgenerator.net/)

### LIFFの改造
まずは`index.html`を編集します。`Write advertising packet`タブの表示名を `Write Text / Service UUID`に変更します。

```html
          <nav class="row">
            <div class="nav nav-tabs col" role="tablist">
              <a class="nav-item nav-link small active" id="nav-notify-tab" data-toggle="tab" href="#nav-notify" role="tab" aria-controls="nav-notify" aria-selected="true">Notify</a>
              <a class="nav-item nav-link small" id="nav-write-tab" data-toggle="tab" href="#nav-write" role="tab" aria-controls="nav-write" aria-selected="true">Write</a>
              <a class="nav-item nav-link small" id="nav-advert-tab" data-toggle="tab" href="#nav-advert" role="tab" aria-controls="nav-advert" aria-selected="true">Write Text / Service UUID</a>
            </div>
          </nav>
```

Write Text / Service UUIDタブのコンテンツにWrite Textを追加します。

```html
            <div class="tab-pane fade col" id="nav-advert" role="tabpanel" aria-labelledby="nav-advert-tab">
              <div class="row justify-content-center">
                <div class="col text-center">
                  <p>
                    <label for="uuid">Write Text</label>
                    <input type="" class="form-control write_text" id="writetext" maxlength='16' placeholder="TEXT">
                    <small class="text-muted">16文字までの半角英数字を入力してください。</small>
                  </p>
                  <p>
                    <button type="button" class="settext btn btn-secondary"><i class="fas fa-sync-alt"></i> Write Text</button>
                  </p>
                  <hr />
                  <p>
                    <label for="uuid">Advertising UUID</label>
                    <input type="" class="form-control uuid_text" id="uuidtext" placeholder="UUID">
                    <small class="text-muted">Advertisingで使うUUIDを変更します。間違ったUUIDを書き込んでしまうとLINE Appから見れなくなってしまうことがあるので注意してください。
                    書き込みしたあとにデバイスのリセットボタンを押して再起動することで反映されます。LIFFアプリも一度閉じてから再度開いてください。初期化したい場合はSW1を押しながらリセットスイッチを押すことでデフォルトのUUIDに戻ります。</small>
                  </p>
                  <p>
                    <button type="button" class="setuuid btn btn-secondary"><i class="fas fa-sync-alt"></i> Write UUID</button>
                  </p>
                </div>
              </div>
            </div>
```


次に、`liff-starter.js`を編集します。まずは新しく追加するキャラクタリスティックのUUIDを定義しましょう。

```javascript
const USER_CHARACTERISTIC_NOTIFY_UUID = "e90b4b4e-f18a-44f0-8691-b041c7fe57f2";
const USER_CHARACTERISTIC_WRITE_UUID = "4f2596d7-b3d6-4102-85a2-947b80ab4c6f";
const USER_CHARACTERISTIC_WRITE_TEXT_UUID = "ここに取得したUUIDを書く"         //←これを追加!
```

テキスト送信ボタンが押されたときの挙動を`initializeCardForDevice(device)`に書きます。

```javascript
    template.querySelector('.setuuid').addEventListener('click', () => {
        writeAdvertuuid(device, template.querySelector('.uuid_text').value).catch(e => onScreenLog(`ERROR on writeAdvertuuid(): ${e}\n${e.stack}`));
    });

    //----追加分ここから----
    template.querySelector('.settext').addEventListener('click', () => {
        writeText(device, template.querySelector('.write_text').value).catch(e => onScreenLog(`ERROR on writeText(): ${e}\n${e.stack}`));
    });
    //----ここまで----
```

次は、ボタンが押されたときのコールバックを書きます。下記関数を適当な位置(`getCharacteristic(device, serviceId, characteristicId)`の上など)に追加します。

```javascript
async function writeText(device, text) {
  let ch_array = text.split("");
  for(let i = 0; i < 16; i = i + 1){
    ch_array[i] = (new TextEncoder('ascii')).encode(ch_array[i]);
  }

  onScreenLog('Write text to device  : ' + new Uint8Array(ch_array));

  const characteristic = await getCharacteristic(
        device, USER_SERVICE_UUID, USER_CHARACTERISTIC_WRITE_TEXT_UUID);
  await characteristic.writeValue(new Uint8Array(ch_array)).catch(e => {
      onScreenLog(`Error writing ${characteristic.uuid}: ${e}`);
      throw e;
  });
}
```

ここまでできたらgithubにpushしましょう。

LIFFはgithub pagesにデプロイしてもすぐには反映されません。htmlは良いのですが、Javascriptの方はその時まちまちですが10分くらい更新されないときがあります。気長に待ちましょう。

その間にファームウェアの改造と書き込みを行っておいてください。

### ファームウェアの改造

まずは新しくCharacteristicを定義して、先程JacaScriptで追加したUUIDを設定します。

```C++
#define USER_CHARACTERISTIC_READ_UUID "e90b4b4e-f18a-44f0-8691-b041c7fe57f2"
#define USER_CHARACTERISTIC_WRITE_UUID "4f2596d7-b3d6-4102-85a2-947b80ab4c6f"
#define USER_CHARACTERISTIC_TEXT_UUID "ここに取得したUUIDを書く"         //←これを追加!
```

次に、新しく追加したキャラクタリスティックのUUIDを格納する配列を宣言します。

```C++

uint8_t blesv_devboard_io_notify_temp_uuid[16];
uint8_t blesv_devboard_text_uuid[16];     //←これを追加!
BLEService blesv_devboard = BLEService(blesv_devboard_uuid);
BLECharacteristic blesv_devboard_notify = BLECharacteristic(blesv_devboard_notify_uuid);
BLECharacteristic blesv_devboard_write = BLECharacteristic(blesv_devboard_write_uuid);
BLECharacteristic blesv_devboard_version = BLECharacteristic(blesv_devboard_version_uuid);
BLECharacteristic blesv_devboard_io_write = BLECharacteristic(blesv_devboard_io_write_uuid);
BLECharacteristic blesv_devboard_io_read = BLECharacteristic(blesv_devboard_io_read_uuid);
BLECharacteristic blesv_devboard_io_notify_sw = BLECharacteristic(blesv_devboard_io_notify_sw_uuid);
BLECharacteristic blesv_devboard_io_notify_temp = BLECharacteristic(blesv_devboard_io_notify_temp_uuid);
BLECharacteristic blesv_devboard_text = BLECharacteristic(blesv_devboard_text_uuid);     //←これを追加!
```

BLEの初期化をする関数(` void bleConfigure(int power) `)に文字列のUUIDを配列に変換するように記述します。

```C++
  strUUID2Bytes(USER_CHARACTERISTIC_READ_UUID, blesv_devboard_notify_uuid);
  strUUID2Bytes(USER_CHARACTERISTIC_WRITE_UUID, blesv_devboard_write_uuid);
  strUUID2Bytes(USER_CHARACTERISTIC_TEXT_UUID, blesv_devboard_text_uuid);      //←これを追加!
```

キャラクタリスティックの有効化と、Writeされたときのcallbackを定義します。`bleSetupServiceDevice()`の一番下にこれをすべて追加します。

```C++
  blesv_devboard_text.setProperties(CHR_PROPS_WRITE);
  blesv_devboard_text.setPermission(SECMODE_ENC_NO_MITM, SECMODE_ENC_NO_MITM);
  blesv_devboard_text.setWriteCallback(bleTextEvent);
  blesv_devboard_text.setFixedLen(16);
  blesv_devboard_text.begin();
```

文字列を格納する配列と、コールバック先を追加します。これは `bleDisconnectEvent(uint16_t conn_handle, uint8_t reason)`関数の下辺りに追加しておくと良いでしょう。

```C++
volatile char g_data_user_text[16] = {
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
};

void bleTextEvent(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset) {
  for (int i = 0; i < 16; i++) {
    g_data_user_text[i] = data[i];
  }
}
```

最後に、loop()関数の中で実際に文字をディスプレイに出力する部分を定義します。オリジナルのファームウェアではSW1とSW2のON/OFFが表示されますが、表示エリアを確保するために、この表示はコメントアウトします。

```C++
      /*
      if (g_data_sw1) {
        display.print("SW1:ON / ");
      } else {
        display.print("SW1:OFF / ");
      }
      if (g_data_sw2) {
        display.println("SW2:ON");
      } else {
        display.println("SW2:OFF");
      }
      */

      for (int i = 0; i < 16; i++){
        display.print(g_data_user_text[i]);
      }
```

### 実行してみる

LIFFを開いて、Write Text / Service UUIDタブを開きます。テキストを送信してみてdev boardのディスプレイ一番下に送信した文字が表示されていれば成功です。

![IMG_2763.JPG](https://qiita-image-store.s3.amazonaws.com/0/354978/74c9bf56-06a5-421b-897c-dae31a160d02.jpeg)

お疲れ様でした!


# 開発のコツとトラブルシューティング

LINE Things の開発を進める上で、なにか問題が起きたときには、以下の情報を参考にしてください。
特に、UUIDの書き換えを行って接続できなくなったなどの問題が起きた場合は試してみましょう。

[重要] デバイスファームウェア書き換え時は必ずペアリング解除 + 連携解除 + Bluetooth OFF
デバイスのファームウェアを書き換えた時、特に iOS において GATT Service や Characteristic の構成に変更を加えた場合、何もせずにすでにペアリング・デバイス連携済みの端末へ接続すると、正しく動作しないことがあります。(デバイス側の OS レベルのキャッシュによる)

デバイス側のファームウェアを書き換えた場合には、Bluetooth 設定画面からペアリングを解除し、LINE Things の連携画面からも連携を解除し、Bluetooth を OFF にしたあと、もう一度 ON にすることで、デバイス側のキャッシュがクリアされる場合があります。

詳細な手順は以下の通りです。

 * iOS
    * iOS の設定より Bluetooth の設定画面を開きます
    * LINE Things dev board と表示されたデバイスの ℹ️ マークを押して、"このデバイスの登録を解除" します
    * LINE Things のデバイス連携画面で、対象のデバイスを左にスワイプして連携を解除します
    * LINE アプリを kill します
    * Bluetooth を OFF にします
    * Bluetooth を ON にします
    * LINE Things のデバイス連携画面を開きます
 * Android
    * Android の設定より Bluetooth の設定画面を開きます
    * LINE Things dev board と表示されたデバイスの設定ボタンを押して、"削除" します
    * LINE Things のデバイス連携画面で、対象のデバイスを長押しして連携を解除します
    * LINE アプリを kill します
    * Bluetooth を OFF にします
    * Bluetooth を ON にします
    * LINE Things のデバイス連携画面を開きます
   
**これでもだめな場合、おとなしく再起動しましょう**

常時、Service の変更や Characteristic の追加を行うようなデバイスや、開発中には Service Changed Characteristic を実装することをおすすめします。

[Bluetooth 公式サイトの Service Changed Characteristic の説明](https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gatt.service_changed.xml)


Android より iOS の方が BLE 自体の機能が安定している (と思う) 一般的に、BLE の機能は iOS のほうが安定していると思います。

実際に、LINE Things を開発する上でも、Android は何度か致命的な問題により突然動かなくなったり、下記で説明する突然何も反応しなくなる問題があったり、不安定なイメージです。特に、端末にいる機種依存の問題がとても多いです。

だからといって、iOS が信頼できるかと言われると、そうでもないイメージです。

Android は稀に BLE がなにも反応しなくなる
Android 端末では、稀に Bluetooth LE の機能が LINE に限らず、何も使えなくなることがあります。
おとなしく、端末を再起動してください！

## nRF Connect for Mobile を活用する
うまく動作しない場合には、正しくファームウェアの Service UUID が書き換えられているか、書き換えた正しく LIFF に反映できているかを確認してみてください。Bluetooth LE のデバッグには、BLE 関連のチップメーカーである Nordic が提供している "nRF Connect for Mobile" というアプリを使うと便利です。

https://itunes.apple.com/jp/app/nrf-connect/id1054362403
https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp
ファームウェアが正しく動作しているか、バグがあるのは LIFF アプリかデバイスなのかといった、問題の切り分けに役立ちます。

## LIFF のキャッシュがクリアされない
Android の場合は、LINE 自体のアプリのキャッシュをクリアすれば、LIFF のキャッシュもクリアされます。

参考: https://www.au.com/support/faq/view.k1205140002/
iOS の場合は、OS のバージョンによってまちまちで、これと言ってしっかり消せる方法がないです...
(僕が知らないだけかも、すいません...)

GitHub Pages であれば、10分でキャッシュが消えるような設定になっています。

## LIFF アプリ内のデバッグ
LIFF アプリは、デバッグコンソールなどは存在しないため、デバッグがやりにくいこともあります。
そこで、以下の vConsole というプラグインを組み込むと、LIFF アプリ内で簡単なデバッグが行えるようになります。
お困りの方は是非試してみてください。

https://github.com/Tencent/vConsole


# Dev board 以外の開発ボードのオススメは？
手軽に開発できる Bluetooth LE 対応の開発ボード紹介

https://qiita.com/hktechno/items/45ce4678e45c4e8331df

Raspberry Pi は？
LINE Things Starter を Raspberry Pi 上で移植された方がいます。
https://qiita.com/pierusan2010/items/10f6ec2e0724f42190ba

しかし、私達の検証では、Raspberry Pi の BLE ライブラリの問題で、iOS と Android 両方で正しく動作させる事ができておらず、Starter のリポジトリには含めておりません。