node.jsを使って天気をchibi:bitに表示する


[International Nodebot Day 2017 in Tokyo](https://nodebots.connpass.com/event/61190/) のイベントに参加してきました。Node.jsでハードウェアを動かそうというイベントです。自分は、chibi:bitを動かしてみました。


### この記事のアウトライン
* chibi:bitについて
* chibi:bitにBLE連携用ファームウェアを書き込む
* node.jsのライブラリ bbc-microbit をインストール
* openWeatherMap APIにアカウント登録し、APIキーを取得
* 気象情報をchibi:bitのLEDに表示

### アウトプット
東京の現在の気温を表示します。

![ファイル 2017-07-29 17 17 12.gif](https://qiita-image-store.s3.amazonaws.com/0/64560/3bbf2ee4-a669-5e17-011a-7d114848fd61.gif "ファイル 2017-07-29 17 17 12.gif")


## 動作環境

* macOS Sierra 10.12.6
* node.js v7.2.1
* chibi:bit基板 (下記)

### chibi:bitについて
イギリスの子供向け学習用ボードであるBBS micro:bitの互換機です。web上でブロックを組み合わせてプログラミングできます。micro:bitは日本の電波法に適合していないため、スイッチサイエンスさんがchibi:bitという名前の互換機を製造、販売されてます。
https://www.switch-science.com/catalog/2900/
![スクリーンショット 2017-07-30 8.42.16.png](https://qiita-image-store.s3.amazonaws.com/0/64560/c6ac2d77-1c4d-806c-85fd-9796855397fb.png "スクリーンショット 2017-07-30 8.42.16.png")


## node.jsでchibi:bitのLEDにテキストを表示

### chibi:bitにBLE連携用ファームウェアを書き込む
chibi:bit側にはBLEを受信してLEDを表示するファームウェアを書き込みます。LEDの表示内容については、node.jsで制御します。chibi:bitは受信したデータを表示するだけです。

こちらの記事がとてもわかりやすいので
https://www.indetail.co.jp/blog/170619/
こちらを参考に進めます。

![chibibit.png](https://qiita-image-store.s3.amazonaws.com/0/64560/ec995f72-2501-4619-72fa-65f18734af52.png "chibibit.png")

「最初だけ」のブロックに「Bluetooth LEDサービス」を入れておくのがポイントです。


### node.jsのライブラリbbc-microbitをインストール
LEDの表示内容を制御するために、node.jsのライブラリである bbc-microbit をインストールします。
ターミナル上で一発でインストールできます。適当な作業用フォルダを作成し、そのフォルダ内で下記コマンドを実行してください。

```Terminal
npm install bbc-microbit
```

ライブラリにサンプルコードがたくさん入っています。LEDにテキストを表示するには以下のようにしてみてください。

```Terminal
node node_modules/bbc-microbit/examples/led-text.js
```

参考：Githubにソースコードが上がっています
https://github.com/sandeepmistry/node-bbc-microbit


##気象情報APIとしてopenWeatherMapを利用
Yahooとかもあるが、日本語になってしまうので、chibi:bitでの表示が面倒になりそうでした。そのため、openWeatherMapを使うことにしました。
https://openweathermap.org/api
![スクリーンショット 2017-07-29 15.28.09.png](https://qiita-image-store.s3.amazonaws.com/0/64560/4903bc55-f2e0-2a30-e584-837fca06c87f.png "スクリーンショット 2017-07-29 15.28.09.png")

### APIキーを取得
サイト上部の「Sign Up」からユーザー登録をして、APIキーを取得します。
無料のFree PlanではAPIを1分間に60回まで呼び出すことができます。
キーを作成してから10分くらい待たないと動かないので注意してください。

### APIの利用
こちらのサイト
https://yoheikoga.github.io/2016/08/14/open-weather-map-by-nodejs/
に掲載されているサンプルコードを使うことにします。

東京の気象情報がJSON形式で取得できます。

```openWeatherMap.js
var http = require('http');
var location = "Tokyo, JP";
var units = 'metric';
var APIKEY = "取得したAPIキーをこちらに入力";
var URL = 'http://api.openweathermap.org/data/2.5/weather?q='+ location +'&units='+ units +'&appid='+ APIKEY;
http.get(URL, function(res) {
  var body = '';
  res.setEncoding('utf8');
  res.on('data', function(chunk) {
    body += chunk;
  });
  res.on('data', function(chunk) {
    res = JSON.parse(body);
    console.log(res);
  });
}).on('error', function(e) {
  console.log(e.message);
});
```

上記を openWeatherMap.js として保存し、ターミナルでコマンド入力しましょう。

```Terminal
node openWeatherMap.js
```

ターミナル上の出力結果は下記のようになります。

```Terminal
{ coord: { lon: 139.69, lat: 35.69 },
  weather:
   [ { id: 521, main: 'Rain', description: 'shower rain', icon: '09d' },
     { id: 300,
       main: 'Drizzle',
       description: 'light intensity drizzle',
       icon: '09d' } ],
  base: 'stations',
  main:
   { temp: 28.59,
     pressure: 1006,
     humidity: 74,
     temp_min: 27,
     temp_max: 30 },
  visibility: 10000,
  wind: { speed: 6.2, deg: 70 },
  clouds: { all: 75 },
  dt: 1501308660,
  sys:
   { type: 1,
     id: 7612,
     message: 0.009,
     country: 'JP',
     sunrise: 1501271213,
     sunset: 1501321684 },
  id: 1850147,
  name: 'Tokyo',
  cod: 200 }
```

### JSONをパース
必要なところを使うためにJSONをパースします。たとえば気温データを使いたい場合は、openWeatherMap.jsの console.log の部分を書きえましょう。

```openWeatherMap.js
// console.log(res); //openWeatherMap.jsのこの部分を変更。下記のようにすればよい
console.log("temp: " + res.main.temp + "C");
```

すると、ターミナル上の出力結果はこのようになります。

```Terminal
temp: 28.59C
```


## 気象情報をchibi:bitに表示
上記方法で取得したテキストデータを、chibi:bitへ表示すれば完了です。さきほどの作業用フォルダに下記ファイルを保存して実行してみてください。

```led-weather.jp
var BBCMicrobit = require('bbc-microbit');
var msg = "";

// openWeatherMap API から情報を取得
var http = require('http');
var ledDisplayName = "TOKYO"
var location = "Tokyo, JP";
var units = 'metric';
var APIKEY = "APIキーをここに入力";
var URL = 'http://api.openweathermap.org/data/2.5/weather?q='+ location +'&units='+ units +'&appid='+ APIKEY;

http.get(URL, function(res) {
  var body = '';
  res.setEncoding('utf8');
  res.on('data', function(chunk) {
    body += chunk;
  });
  res.on('end', function(chunk) {
    res = JSON.parse(body);
    msg = res.main.temp; // 温度を表示したい場合
    // msg = res.weather[0].main; // 天気を表示したい場合
    console.log("openWeatherMap respose: location " + location + " is " + msg );
  });
}).on('error', function(e) {
  console.log(e.message);
});

// chibi:bitに表示
console.log('Scanning for microbit');
BBCMicrobit.discover(function(microbit) {
  console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address);

  microbit.on('disconnect', function() {
    console.log('\tmicrobit disconnected!');
    process.exit(0);
  });

  console.log('connecting to microbit');
  microbit.connectAndSetUp(function() {
    console.log('\tconnected to microbit');

    console.log('sending text: "%s"', msg);
    microbit.writeLedText(ledDisplayName + ":" + msg, function() {
      console.log('\ttext sent');

      console.log('disconnecting');
      microbit.disconnect();
    });
  });
});
```

出力結果は、本記事の最初の画像のようになります。
後は、天気に合わせたLEDの表示パターンを考えれば、もっとオシャレになりそうですね。