Raspberry Piに現在時刻、天気予報を喋らせる

このコードでは一部取得することのできない地域があることが判明したため新たに作る場合は[修正版](https://qiita.com/conqueror/items/12dec5bc9ac99027e381)の方を参考にしてください。
#初めに
もともと[ここ](http://raspi.seesaa.net/article/415530289.html)を参考に使っていたのですが、喋らなくなっていたので調べてみるといつの間にか「[livedoor 天気](https://help.livedoor.com/weather/index.html)」は終了していたみたいです。

というわけで代わりに使えるものがないかと探してみたところ"OpenWeathermap"がよさげだったのでこれを使うことにしました。
#事前準備

・下記の記事を参考にAquasTalkを利用した"atalk"コマンドを使えるようにしてください。
[raspberry piの音周り](http://nos.hateblo.jp/entry/20150218/1424217597)

・[OpenWeathermap](https://openweathermap.org/)にてアカウントを登録してAPIを取得してください。

#必要なモジュールをインストール
```
pi@raspberrypi ~ $sudo pip install romkan
```
#実装
適当な場所に実行させるプログラムを作ってください。

```python:open_talkweather.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import shlex
import subprocess
from datetime import datetime
import urllib.request
import json
import deg_speed
import r_k

city_name = "100-0005,jp" #取得したい地域の郵便番号
API_KEY = "*********************" #APIキー
CMD_SAY = "atalk"
da = datetime.now()

def main():
        say_datetime()
        say_weather()
        return

def say_datetime():
                text = "天気予報です。%s年%s月%s日、%s時をお知らせします。" % (da.year, da.month, da.day, da.hour)
                text = CMD_SAY + ' ' + text
                print(text)
                proc = subprocess.Popen(shlex.split(text))
                proc.communicate()
                return

def say_weather():
        api0 = "https://api.openweathermap.org/data/2.5/weather?zip={0}&appid={1}&units=metric&lang=ja&exclude=hourly,daily"
        url0 = api0.format(city_name,API_KEY)
        r0 = urllib.request.urlopen(url=url0)
        obj0 = json.loads(r0.read())
        lat = obj0["coord"]["lat"]
        lon = obj0["coord"]["lon"]
        api = "https://api.openweathermap.org/data/2.5/onecall?lat={0}&lon={1}&appid={2}&units=metric&lang=ja&exclude=hourly"
        url = api.format(lat,lon,API_KEY)
        title_text = u'%sの天気'
        weather_text = u'%sは%sの風、風力%s、%s。天気は%s。降水確率は%s％です。'
        now_text = u'現在の気温は%s度、湿度%s％で体感温度は%s度です。'
        temperature_text = u'%sの予想最高気温は、%s度。予想最低気温は、%s度、湿度は%s％です。'
        try:
                r = urllib.request.urlopen(url=url)
                obj = json.loads(r.read())
                c = obj["current"]
                d = obj["daily"]
                title = obj0["name"]
                title = r_k.toKanji(title)
                title = title_text % (title)
                #today
                Nt = d[0]["temp"]
                pop = round(d[0]["pop"] * 100)
                wdn = c["wind_deg"]
                wdn = deg_speed.wdeg(wdn)
                wsn = c["wind_speed"]
                (wsn,wsna) = deg_speed.wspeed(wsn)
                today_w = d[0]["weather"][0]["description"]
                today_w_txt = weather_text % (u"今日", wdn, wsn, wsna, today_w, pop)
                today_t_txt = temperature_text % (u"今日", round(Nt["max"], 1), round(Nt["min"], 1), d[0]["humidity"])
                today_n_txt = now_text % (round(c["temp"], 1), c["humidity"], round(c["feels_like"], 1))

                #tommorow
                Nt = d[1]["temp"]
                pop = round(d[1]["pop"] * 100)
                wdt = d[1]["wind_deg"]
                wdt = deg_speed.wdeg(wdt)
                wst = d[1]["wind_speed"]
                (wst,wsna) = deg_speed.wspeed(wst)
                tommorow_w = d[1]["weather"][0]["description"]
                tommorow_w_txt = weather_text % (u"明日", wdt, wst, wsna, tommorow_w, pop)
                tommorow_t_txt = temperature_text % (u"明日", round(Nt["max"], 1), round(Nt["min"], 1), d[1]["humidity"])

                #say
                weather_str = title + ' ' + today_w_txt + ' ' + today_n_txt + ' ' + today_t_txt + ' ' + tommorow_w_txt + ' ' + tommorow_t_txt
                text = '''%s '%s' ''' % (CMD_SAY, weather_str)
                print(text)
                proc = subprocess.Popen(shlex.split(text))
                proc.communicate()
        finally:
                r.close()
        return

### Execute
if __name__ == "__main__":
    main()

```

また、これと同じディレクトリに下記の2つのモジュールを作ります。

```pytho:deg_speed.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-


import math

def wdeg(wd):
        obj = ["北","北北東","北東", "東北東", "東", "東南東", "南東", "南南東", "南", "南南西", "南西", "西南西", "西", "西北西", "北西", "北北西", "北"];
        wd = ((wd + 11.24) / 22.5)
        wd = math.floor(wd)
        return obj[wd]

def wspeed(ws):
        if 0 <= ws <= 0.3:
                return (0, u"静穏")
        elif 0.3 <= ws < 1.6:
                return (1, u"至軽風")
        elif 1.6 <= ws < 3.4:
                return (2, u"軽風")
        elif 3.4 <= ws < 5.5:
                return (3, u"軟風")
        elif 5.5 <= ws < 8.0:
                return (4, u"和風")
        elif 8.0 <= ws < 10.8:
                return (5, u"疾風")
        elif 10.8 <= ws < 13.9:
                return (6, u"雄風")
        elif 13.9 <= ws < 17.2:
                return (7, u"強風")
        elif 17.2 <= ws < 20.8:
                return (8, u"疾強風")
        elif 20.8 <= ws < 24.5:
                return (9, u"大強風")
        elif 24.5 <= ws < 28.5:
                return (10, u"暴風")
        elif 28.5 <= ws < 32.7:
                return (11, u"烈風")
        elif 32.7 <= ws:
                return (12, u"颶風")

if __name__ == '__main__':

        wd = input("風向(度)")
        ws = input("風速(m/s)")
        wd = int(wd)
        d = wdeg(wd)
        ws = int(ws)
        (x, y) = wspeed(ws)
        text = u"%sの風、風力%s,%s" % (d, x, y)
        print(text)
```
```python:r_k.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib.request
import json
import romkan
import urllib.parse
def toKanji(s):
        s = s + ","
        s = romkan.to_hiragana(s)
        s = urllib.parse.quote(s.encode('utf-8'))
        url = 'http://www.google.com/transliterate?langpair=ja-Hira|ja&text={}'.format(s)
        r = urllib.request.urlopen(url=url)
        obj = json.loads(r.read())
        return obj[0][1][0]

### Execute
if __name__ == "__main__":

        print(toKanji('honnjituhaseitennnari'))
```
#実行する
cronで回せば時報として使えると思います。

```
pi@raspberrypi ~ $ python3 open_talkweather.py
atalk 天気予報です。2020年8月15日、22時をお知らせします。
atalk '丸の内（次のビルを除く）の天気 今日は南の風、風力3、軟風。天気は晴天。降水確率は15％です。 現在の気温は32.2度、湿度79％で体感温度は37.9度です。 今日の予想最高気温は、32.2度。予想最低気温は、31.9度、湿度は79％です。 明日は南南東の風 、風力3、軟風。天気は薄い雲。降水確率は26％です。 明日の予想最高気温は、35.3度。予想最低気温は、30.4度、湿度は46％です。'
```
#参考文献
[Raspberry Piに現在時刻と、天気をしゃべらせてみた（Python）](http://raspi.seesaa.net/article/415530289.html)
[raspberry piの音周り](http://nos.hateblo.jp/entry/20150218/1424217597)
[One Call API](https://openweathermap.org/api/one-call-api)
[ビューフォート風力階級](https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%A5%E3%83%BC%E3%83%95%E3%82%A9%E3%83%BC%E3%83%88%E9%A2%A8%E5%8A%9B%E9%9A%8E%E7%B4%9A)