micro:bit を Scratch 2 + Bluetooth で使う（ビルド編1：noble-uwp）

# micro:bit を Scratch 2 + Bluetooth で使う（ビルド編1）

以下のような話題についてまとめます。

1. ネイティブアドオンを使う Electron アプリケーションのビルドと配布可能なパッケージ化の方法
1. Scratch2（オフライン版）から Bluetooth Low Energy 経由で BBC micro:bit を使うためのヘルパーアプリケーション作成方法

前半は node-gyp の環境準備とネイティブアドオンのビルドの話、後半は electron-builder を用いたビルドと配布用パッケージの作り方です。長いので2つに分け、ここでは前半をビルド編1としてまとめておきます。[後半のビルド編2はこちら](https://qiita.com/memakura/items/dc5cf2ff39d24ceb53ff)。 

## 動機

Scratch 2 のヘルパーアプリケーションを https://github.com/memakura/s2microbit-ble で公開していますが、この[コンソール版](https://github.com/memakura/s2microbit-ble-console)のビルド方法が前半（ビルド編1）、Electron版のビルド・パッケージ化の方法が後半（ビルド編2）に対応します。Scratch 2 で子供にビジュアルプログラミングをしてもらうときに、Node や Python などの環境を準備してもらうのは大変なので、ビルド編2のまとめにあるような実行形式で配布したいのです。Github 上の s2microbit-ble(-console) を clone して使うだけなら、前半、後半いずれも「まとめ: ... 」と書かれたセクションを確認してください。

あと、なぜ Node + Electron でパッケージ化することにしたかは、[micro:bit を Scratch 2 + Bluetooth で使う（調査編）](https://qiita.com/memakura/items/6b74e01fba310ebf6381) にまとめています。また、s2microbit-ble の中身の話は[まとめ編](https://qiita.com/memakura/items/1acab55a37651e9081b4)でまとめる予定です。

# noble-uwp モジュールのインストール

## noble-uwp と bbc-microbit

Node で Bluetooth を扱うには noble というモジュールがよく使われます。Windows 10 でも、以前は特定のBluetooth USBドングルやドライバを用意する必要がありましたが、2017年春ごろの[バージョン1703・ビルド15063（いわゆるCreators Update）](https://en.wikipedia.org/wiki/Windows_10_version_history#Version_1703_(Creators_Update)_2)からは、多くのUSBもしくはPC内臓のBluetoothアダプタでも動くようになりました。ただし、これには noble を入れた後にその一部を [noble-uwp (Windows 10 UWP binding)](https://github.com/jasongin/noble-uwp) にアップデートする必要があります。なお、UWP は異種デバイスの動作プラットフォームを共通化するために Windows 10 から導入されたもので、 Universal Windows Platform の略です。

Bluetooth + JavaScript というと、Web Bluetooth API とどっちにするかという話もありますが、Windows で動作実績があるので noble API にしています（Web Bluetooth API も wrapping されると期待）。

以下ではこの noble-uwp のインストールと注意点をまとめます。具体的には、noble から Bluetooth Low Energy 経由で BBC micro:bit を使うための [bbc-microbit](https://github.com/sandeepmistry/node-bbc-microbit) というモジュールのインストールを行い、これに依存してインストールされた noble を差し替えることで noble-uwp を使えるようにします。

## node-gyp には実行環境が必要

ここでは以下のバージョンを使います。

```
> node -v
v8.10.0
> npm -v
5.6.0
```

まずは bbc-microbit をインストールします。

```
> npm init（適当に答えて package.json を作成する）
> npm install --save bbc-microbit
```

こうすると `node-pre-gyp install --fallback-to-build` が実行され、必要なバインディング（ネイティブモジュール）をビルドしようとします。node-gyp や node-pre-gyp は Node でネイティブアドオンモジュールをビルドするための、クロスプラットフォームのコマンドラインツールで、GYP (Generate Your Project) とは、Google Chrome の元になった [Chromium の開発チームで使われていた（メタ）ビルドシステム](https://gyp.gsrc.io/)らしいです。

しかし、いくつかのモジュール（usb モジュールなど）はビルドされず、以下のようにリモートからダウンロードされます。

```
[usb] Success: "<現在のフォルダ>\node_modules\usb\src\binding\usb_bindings.node" is installed via remote
```

リモートにビルド済みバインディングがすでにあり、Node用については**ローカルではビルドしなくてよい** ということです。（[ビルド編2](https://qiita.com/memakura/items/dc5cf2ff39d24ceb53ff)で述べるように、Electron用にはビルドは必要になります。）


一方、bluetooth-hci-socket は `node-gyp rebuid` で怒られます。リモートからダウンロードできないときは、**ローカルでビルドが必要**ですが、node-gyp でのビルドに必要な Python 2.7 もしくは VC++ 2015 の環境がないためです。詳しくは [node-gyp のページ](https://github.com/nodejs/node-gyp) の Installations > On Windows あたりを見ながら設定しておきます。（後々 Electron を使うときには、noble-uwp もビルドが必要です。）

## node-gyp の実行環境の準備

[node-gyp のページ](https://github.com/nodejs/node-gyp) の Option 1: [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools) を、管理者権限のコンソール(Cmd)から入れてしまうのが楽です。VC++ Build Tools 2015 と Python が自動でダウンロード、インストールされます。

- Python は `c:\Users\.windows-build-tools` の下に入ります。
- Pythonへのパスはデフォルトでは npm の globalconfig に追加されるだけのようです。自分は Python (Anaconda) や Visual Studio 2017 は入っていましたが、これならコンフリクトはしなさそう。
- 通常はこの作業は不要かもしれないですが、自分は Python 環境をいくつも入れたくないため、windows-build-tools で入った Python は `c:\Users\.windows-build-tools\python-2.7.14.amd64.msi` を実行してアンインストールし、`npm config -g delete python` で npm のパスからも消してしまいました。

以下では、Python 2.7 は Anaconda の仮想環境で [py27という名前で設定してある](https://qiita.com/supersaiakujin/items/50def6f33b79f9a61b18)とします。つまり、

```
> conda info -e
# conda environments:
#
py27                  *  C:\Program Files\Anaconda3\envs\py27
root                     C:\Program Files\Anaconda3
```

のような環境です。

```
> activate py27
(py27)> npm install --save bbc-microbit
```

これで bluetooth-hci-socket のビルドが成功します。（windows-build-tools で入れた Python をそのまま使うなら activate 不要です。）

## noble-uwp のビルド

まずはインストールしてみます。

```
(py27)> npm install --save noble-uwp
```

すると、

```
Installing NodeRT UWP adapter for Windows.Foundation
[windows.foundation] Success: "<現在のパス>\node_modules\noble-uwp\uwp\windows.foundation\binding\node-v57-win32-x64\binding.node" is installed via remote
```

のようなメッセージがいくつも出てきます。usb と同様、node-uwp のバインディングもリモートからダウンロードされるため、ローカルでビルドしなくてよいようです。[ビルド編2](https://qiita.com/memakura/items/dc5cf2ff39d24ceb53ff)で説明する Electron のときには変わってきます。

## noble の代わりに noble-uwp を使うように設定

[noble-uwpのリポジトリのREADME](https://github.com/jasongin/noble-uwp)にあるように、noble-uwp を使うには、モジュールインストール後に、`node_modules/noble-device/lib/util.js` の `require('noble')` を `require('noble-uwp')` に差し替えるようです。
これは忘れそうです。[このページ](https://github.com/jaafreitas/scratch-microbit-extension)を参考に、以下のように postinstall のスクリプトを設定しておきます。

```json:package.json（該当部）
  "scripts": {
    "postinstall": "node noble-uwp-replace.js"
  },
```

```js:noble-uwp-replace.js
const os = require('os');

if (os.platform() === 'win32') {
  // https://github.com/jasongin/noble-uwp
  console.log("### noble is replaced by noble-uwp");
  var fs = require('fs');
  var f = 'node_modules/noble-device/lib/util.js';
  fs.writeFileSync(f, fs.readFileSync(f).toString().replace('require(\'noble\')', 'require(\'noble-uwp\')'));
}
```
これで `npm install` とした際にスクリプトが走るようになります。


# まとめ: s2microbit-ble-console の使用方法

## 要件

Windows 10 バージョン1703・ビルド15063 以降

## インストール方法

noble-uwp + bbc-microbit を使ったアプリケーションのインストール方法を、[こちらで公開している s2microbit-ble-console](https://github.com/memakura/s2microbit-ble-console) （BLE 経由で BBC microbit を使う Scratch 2 のヘルパー（コンソール版））を例にまとめておきます。

1. インストールに先立って、上で述べたような node-gyp のビルド環境（VC++ Build Tools 2015 と Python 2.7）を用意しておきます。
1. 以下のように `npm install` します。

```
> git clone https://github.com/memakura/s2microbit-ble-console.git
> cd s2microbit-ble-console
> activate py27 (npm config のpython にパスがあればこれは不要)
(py27)> npm install
```
`py27` はAnacondaの環境名ですが、あくまで例です。windows-build-tools でインストールした場合など、すでに Python 2.7 にパスが通っていれば `activate` の部分は不要です。

`### noble is replaced by noble-uwp` というメッセージが最後の方に出て、noble-uwp のバインディングが使えるようになれば成功です。

## 使用方法

1. [s2microbit-ble-console](https://github.com/memakura/s2microbit-ble-console.git) のリポジトリにある hex ファイルを micro:bit に書き込んでおきます。
1. 同じくリポジトリにある Scratch 2 のプロジェクト (.sb2) をダウンロードして開いておきます。（Scratch 2 を開き、シフトを押しながらファイルを押して「実験的なHTTP拡張を読み込み」から拡張ブロックの定義ファイル (.s2e) ファイルを開いても使えます。
1. `npm start` とすると node で s2microbit.js を実行します。
1. micro:bit 側はLEDマトリクスが「ハート」を経て「チェックマーク」に変わり、Scratch 2 側は「その他」のs2microbit-ble の横にある赤丸が緑色になれば接続完了で使用できます。

## 補足

### bbc-microbit のパッチ

bbc-microbit のモジュールはそのままだと scanning に失敗するとすぐにエラーで終了してしまうため、見つかるまで scanning し続けるように、postinstall で node_modules\bbc-microbit\lib\bbc-microbit.js を一部書き換えています。

### Scratch 2 ヘルパーの作成方法

Scratch 2 オフライン版のヘルパーアプリケーションは、Scratch 2 側のGETリクエストに答えるようなHTTPサーバです（[詳細はこちらの記事](https://qiita.com/memakura/items/ca1fff4d7dd33164bb7e)）。s2microbit-ble では、LED の点灯やセンサー情報の取得（GETポーリング）を Express サーバで受け、noble を使って micro:bit 側と通信します。詳しくは[まとめ編](https://qiita.com/memakura/items/1acab55a37651e9081b4)で説明します。

## Electron版へ

以上から分かるように、この s2microbit-ble のコンソール版を使うには環境構築が大変です・・
次回は Electron版のビルド方法を述べて、実行形式をインストーラで配布できるようにします。

つづく：[ビルド編2](https://qiita.com/memakura/items/dc5cf2ff39d24ceb53ff)