ラズパイと音声認識でmicro:bitに天気表示してみた



今回用意したもの
![](https://ueqareer.net/wp-content/uploads/2017/12/IMG_0166-300x225.jpg)

* RaspberryPi3(普通のパソコンで構いません)
* USBマイク（前回と同じもの）
* micro:bit(実験で使わせてもらってる借り物です笑)
micro:bitは2000円ちょっとで買えちゃうので驚きですね。
小学生向けの直感的プログラミングで組めちゃいます（もちろんコード直書き[python,js]でもOK）

必要な環境
-----

* 下記２つのAPIキー
* Node.jsの実行環境
* Pythonの実行環境
今回は,[OpenWeatherMapAPI](http://openweathermap.org/)と[DarkSkyAPI](https://darksky.net/forecast/35.66,139.5548/si12/en)の２つのAPIを使って天気情報と気温情報を取得します。
コンピュータからmicro:bitへのBLEでの送信はNode.jsを使って行うので、NodeでAPIを叩いて情報をそのままmicro:bitに送るような仕組みにしました。
音声制御部分は前回同様pythonで行い、pythonファイルの中でNodeを実行するという仕組みです。

Nodeの実行環境
---------
今回は[Raspberry Pi への Node.js インストールとnvmでのバージョン管理](https://qiita.com/kimio_kosaka/items/0b2ccb18ed77306e9e41)を参考にnvmを使ってインストールしました。ちなみに自分のmacでは初期で使えました。
sudo nodeが使えればOKです。

pythonの実行環境
-----------
今回はラズパイを使用して初期でpython2系が使えたので割愛します。

api叩いてみる
--------[無料天気予報APIのOpenWeatherMapを使ってみる](https://qiita.com/nownabe/items/aeac1ce0977be963a740)を参考にapiキーを取得します。
apiキーが取得できたら実際にapiを叩いてみます。
今回OpenWeatherAPIからほしい情報は今日の天気の情報なので、今はそれだけとってきます。（DarkSkyAPIで気温情報を取得します)

micro:bitに組み込むプログラム
-------------------
今回はBLEをつかって通信します。
[マイクロビットのコード作成画面](https://makecode.microbit.org/)でbluetoothを使えるようにします。
「高度なブロック」→「パッケージを追加する」を順にクリックしbluetoothを選択します。
![](https://ueqareer.net/wp-content/uploads/2017/12/efc2fda9226cebb7186a12b173b97a8b-176x300.png)
これが

![](https://ueqareer.net/wp-content/uploads/2017/12/b6ef835caff2bc4c3b1ddde35d029740-1-218x300.png)
こうなればOKです。

次にペアリングしていないデバイスとも通信できるように設定を行います。
右上の歯車マークから「プロジェクトの設定」を選択し一番上をONにします。
![](https://ueqareer.net/wp-content/uploads/2017/12/448458fc7bade1eaecedb96258984e84-300x130.png)
こんな感じ。
![](https://ueqareer.net/wp-content/uploads/2017/12/8e72e33f48fde5a83b5de1c2a1e7681b-300x188.png)
このプロジェクトをmicro:bitに入れて準備完了！

micro:bitに送信する
--------------
取得した情報をmicro:bitに送信してみます。今回は天気の情報を絵にしてmicro:bitに送信したいので、16進数で点灯する場所を指定して送ります。
Node.jsのモジュール[node-bbc-microbit](https://github.com/sandeepmistry/node-bbc-microbit)を使用します。

```
$ npm install bbc-microbit --save
```
インストールします。


```js:json_weather.js
var http = require('http');
var BBCMicrobit = require('../../node_modules/bbc-microbit/index');

var id = '1864518'; //chofu
// var id = '2128295'; //sapporo
// var id = '5128581'; //new york
var appid = '自分のapiキー';

var URL = 'http://api.openweathermap.org/data/2.5/weather?id='+ id +'&appid='+ appid;

var R="";

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);
    R = res.weather[0].main;
    weather(R)
  });
}).on('error', function(e) {
  console.log(e.message);
});

var PATTERNS = [
  {  //天気に合わせたLEDパターン
    name: 'Clouds',
    value: new Buffer('000609110E', 'hex')
  },
  {
    name: 'Thunderstorm',
    value: new Buffer('060C060C08', 'hex')
  },
  {
    name: 'Snow',
    value: new Buffer('150E040E15', 'hex')
  },
  {
    name: 'Clear',
    value: new Buffer('0E1F1F1F0E', 'hex')
  },
  {
    name: 'Rain',
    value: new Buffer('040E1F040C', 'hex')
  },
];

// search for a micro:bit, to discover a particular micro:bit use:
//  BBCMicrobit.discoverById(id, callback); or BBCMicrobit.discoverByAddress(id, callback);
function weather(str){

  for(var i=0;i<PATTERNS.length;i++){
    if(str==PATTERNS[i].name){　//jsonの結果からほしいパターンを取ってくる
      var pattern = PATTERNS[i];
    }
  }

  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 pattern: "%s"', pattern.name);
      microbit.writeLedMatrixState(pattern.value, function() {
        console.log('\tpattern sent');

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

このプログラムを実行したらmicro:bitのLEDに天気のマークが表示されます。今回は電通大の所在地である調布の天気を取得しています。

音声で制御する
-------
あとは、音声で制御するためにpythonファイルを作ります。
juliusのインストールや自作辞書の作成については[前回の記事](https://ueqareer.net/2463)を参考にしてください。
以下のコードを作成します。


```python:weather.py
import os

def main():
    os.system('sudo node json_weather.js')

if __name__ == "__main__":
    main()
```


```python:juliustest.py
import socket
import string
import subprocess
import weather
import temp_now as now
import temp_min as min
import temp_max as max
import os

host = 'localhost'   # Raspberry PiのIPアドレス
port = 10500         # juliusの待ち受けポート

# パソコンからTCP/IPで、自分PCのjuliusサーバに接続
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))

data = ""
while True:

    # "/RECOGOUT"を受信するまで、一回分の音声データを全部読み込む。
    while (string.find(data, "\n.") == -1):
        data = data + sock.recv(1024)

    # 音声XMLデータから、<WORD>を抽出して音声テキスト文に連結する。
    strTemp = ""
    for line in data.split('\n'):
        index = line.find('WORD="')

        if index != -1:
            line = line[index + 6:line.find('"', index + 6)]
            if line != "[s]":
                strTemp = strTemp + line
    if strTemp != "":
        print("結果:" + strTemp)
    if strTemp == "きょうのてんき":  # if you say Hikaregoma, led will turn on
        #os.system('sudo python ~/irmcli/irmcli.py -p -f ~/irmcli/light_on.json')
	weather.main()
    if strTemp == "さいこうきおん":
        #os.system('sudo python ~/irmcli/irmcli.py -p -f ~/irmcli/light_off.json')
	max.main()
    if strTemp == "さいていきおん":
        min.main()
    if strTemp == "いまのきおん":
        now.main()
    data = ""
```

temp_now,temp_min,temp_maxはDarkSkyAPIをつかって気温情報を取得するプログラムです。
[自分のgithub](https://github.com/mr04vv/raspi-micro-bit-weather)にあるので参考にしてください。

実際に実行した結果こんな感じになりました！！
[実行動画１](https://ueqareer.net/wp-content/uploads/2017/12/tenki.mp4)

[実行動画２] (https://ueqareer.net/wp-content/uploads/2017/12/kion.mp4)

参考記事
----

* [無料天気予報APIのOpenWeatherMapを使ってみる](https://qiita.com/nownabe/items/aeac1ce0977be963a740)
* [Raspberry Pi への Node.js インストールとnvmでのバージョン管理](https://qiita.com/kimio_kosaka/items/0b2ccb18ed77306e9e41)
* [ラズパイで音声認識つかってLチカしてみる](https://ueqareer.net/2463)