Raspberry Piに現在時刻、天気予報、ニュースを喋らせる(旧ver)

Openwetherではなく気象庁から情報を取得できるようになったため以下のページにて書き直しました。
[Raspberry Piに現在時刻＋時報ボイス、天気予報、ニュースを喋らせる(2)](https://qiita.com/conqueror/items/6ca699b811e604a0f0be)
# 初めに
前回[Raspberry Piに現在時刻、天気予報を喋らせる](https://qiita.com/conqueror/items/f94587785fb2230a97cc)で作ったコードなんですが、引っ越した際なんと喋らなくなってしまいました。
どうやらOpenWeathermapには郵便番号から位置情報が引き出せない地域があるようで404が帰ってきてしまいました。
この問題を直すついでにニュースも読み上げれるよう改良しようかと思います。
# 今回新たに利用する物
#### ・郵便番号より緯度・経度の取得
今回は[HeartRailsGeo API](http://geoapi.heartrails.com/api.html)の[郵便番号による住所検索 API](http://geoapi.heartrails.com/api.html#postal)を利用しようかと思います。
#### ・ニュースの取得
NHKの[RSS](https://www.nhk.or.jp/toppage/rss/index.html)を利用します。
このうち取得日時より二日以内の主要ニュースと政治を読み上げようかと思います。
# 事前準備
・下記の記事を参考にAquasTalkを利用した"atalk"コマンドを使えるようにしてください。
　[raspberry piの音周り](http://nos.hateblo.jp/entry/20150218/1424217597)

・[OpenWeathermap](https://openweathermap.org/)にてアカウント登録(無料)してAPIを取得してください。
# 実装
適当な場所に実行させるプログラムを作ってください。

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

city_name = "100-0005" #郵便番号
API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxx" #APIキー
CMD_SAY = "atalk -b -s 90"
da = datetime.now()

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

def say_datetime():
        if 6<= da.hour <=22:
                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
        else:
                exit()

def say_weather():
        url0 = "http://geoapi.heartrails.com/api/json?method=searchByPostal&postal=%s" % (city_name)
        r0 = urllib.request.urlopen(url=url0)
        obj0 = json.loads(r0.read())
        lat = obj0["response"]["location"][0]["y"]
        lon = obj0["response"]["location"][0]["x"]
        url = "https://api.openweathermap.org/data/2.5/onecall?lat=%s&lon=%s&appid=%s&units=metric&lang=ja&exclude=hourly" % (lat, lon, API_KEY)
        print(url)
        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["response"]["location"][0]["town"]

                #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
                weather_str = weather_str.replace("-", "マイナス")
                text = '''%s '%s' ''' % (CMD_SAY, weather_str)
                print(text)
                proc = subprocess.Popen(shlex.split(text))
                proc.communicate()
        finally:
                r.close()
        return

def say_news():
        l = ["0", "4"]
        for loop in l:
                RSS_URL = 'https://www.nhk.or.jp/rss/news/cat%s.xml' % (loop)
                d = feedparser.parse(RSS_URL)
                for i, entry in enumerate(d.entries):
                        newstime = ",".join(map(str, entry.published_parsed[:5]))
                        newstime = datetime.strptime(newstime, "%Y,%m,%d,%H,%M")
                        if i == 0:
                                text = entry.summary
                        else:
                                text = "次のニュースです。" +  entry.summary
                        text = "atalk " + text
                        if da.timestamp() - newstime.timestamp() <= 172800:
                                print(text)
                                proc = subprocess.Popen(shlex.split(text))
                                proc.communicate()
        return

def say_datetime2():
        da = datetime.now()
        text = "%s時%s分です。" % (da.hour, da.minute)
        text = CMD_SAY + ' ' + text
        print(text)
        proc = subprocess.Popen(shlex.split(text))
        proc.communicate()
        return

### Execute
if __name__ == "__main__":
    main()
```
前回と同様に同じディレクトリ内に以下のものを作ります。

```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)
```

多分これで行けると思います。
# 注意点
・[郵便番号や市区町村データを取り扱うときにはまったこと](https://qiita.com/_takwat/items/3a121656425fac7bb820)
この記事を見ればわかるのですが、場所が全く異なるにもかかわらず郵便番号が同じである場合もあります。
当てはまる場合は各々でコードの修正をお願いいたします。
# 参考文献
[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)
[Raspberry Piに現在時刻、天気予報を喋らせる](https://qiita.com/conqueror/items/f94587785fb2230a97cc)
[OpenWeatherMapで郵便番号が使えないときのアプローチ](https://sho0126hiro.hatenablog.com/entry/2019/08/01/131532)
[郵便番号や市区町村データを取り扱うときにはまったこと](https://qiita.com/_takwat/items/3a121656425fac7bb820)
[PythonでDatetimeからUnixtime変換](https://techtech-sorae.com/python%E3%81%A7datetime%E3%81%8B%E3%82%89unixtime%E5%A4%89%E6%8F%9B/)
[Weather condition codes](https://openweathermap.org/weather-conditions)
[OpenWeatherMapの空模様（概況）の表現対照表](https://wisteriahill.sakura.ne.jp/CMS/WordPress/2018/03/05/openweathermap-term-table/)