定時にラズパイを使って時刻と横浜の天気予報をしゃべらせてみる
openjtalkでraspberrypiにおしゃべりをさせる準備は整いました。
何をしゃべらせるかが問題だったのですが、丁度良いプログラムを見つけたので、それを実行してみます。
それが、「raspberrypiに時刻と天気をしゃべらせる」ことです。参考資料は以下です。
Raspberry Piに現在時刻と、天気をしゃべらせてみた(Python)
内容を全く変えずにしゃべらせても良かったのですが、地域を変えられるので、横須賀から地理的に近い「横浜」でやってみることにしました。
さて、どうなることやら、60爺が実行すると必ず何かが起こりますが、エラー対応を含めて、実施内容をご覧いただければと思います。
備忘録にもなるので。
横浜の天気を喋らせる
上記のページで、『地域IDは全国の地点定義表(RSS) の「cityタグ」のidを参照して下さい。』と出ていますが、このページに行っても、「cityタグ」を見つけることができません。
60爺は、いろいろと指定ページからめぐってみましたが、さっぱりわかりません。結局、たどり着いたのが、以下のページです。
ここには、主だった都市が一覧で載っているので簡単です。
livedoor Weather Hacks APIで、お天気データのJSONを取得するための1次細分区(cityタグ)の地域id一覧まとめ
横浜「140010」を指定して動かしてみます。
pi@raspberrypi:~/python_pg/open_jtalk $ python talk_weather.py
jsay 7月13日、13時13分32秒
jsay '神奈川県 横浜 の天気 今日の天気は曇時々晴です。 明日の天気は晴時々曇です。 明日の予想最高気温、31度、予想最低気温、25度です。'
おーー。見事に動きましたね。ちゃんと、スピーカから声が流れます。
当然ですが、printされてから声が出るまでに時差はあります。
python3で動かす
さて、ここまでは上述の記事の焼き直しです。
それだけではつまらないので、ここで、60爺は、少しですがオリジナルな部分を追加してみます。
Python3で実行してみます。
PythonとPython3では、コードに大きく変わった部分がありますので手直ししながら進めてみたいと思います。
print文でエラー発生
さっそく、エラーが発生です。
pi@raspberrypi:~/python_pg/open_jtalk $ python3 talk_weather.py
File "talk_weather.py", line 23 print text ^ SyntaxError: Missing parentheses in call to 'print'
python3では、print文が大きく変わっていて「()」でくくらなくてはいけません。print文が2箇所あるので、両方とも「()」でくくります。
urlib2が存在しない
修正後、再実行します。すると新たなエラーが発生しました。
Traceback (most recent call last):
File "talk_weather.py", line 9, in <module>
import urllib2 ImportError: No module named 'urllib2'
Python では「urllib2」を使えばよいですが、Python3では「urllib.request」を使用するそうです。
(Pythonでurllib2を使ってインターネット上のリソースを取得する方法)
早々、「urllib2」を「urllib.request」に修正しました。
python3はunicode使用不可能
実行してみると、おー、日付と時間が print されました。よーし、あれ、時間がかかってるぞ・・・。あ、またまたエラーが発生ですね。
pi@raspberrypi:~/python_pg/open_jtalk $ python3 talk_weather.py
jsay 7月13日、11時16分14秒
Traceback (most recent call last):
File "talk_weather.py", line 68, in <module>
main()
File "talk_weather.py", line 16, in main
say_weather()
File "talk_weather.py", line 37, in say_weather
obj = json.loads( unicode(r.read()) )
NameError: name 'unicode' is not defined
python3はunicodeの使用が不可能なんです。
unicode を str に変更して再実行します。またまた、変なエラーが出ましたねエ。
pi@raspberrypi:~/python_pg/open_jtalk $ python3 talk_weather.py
jsay 7月13日、11時32分42秒 Traceback (most recent call last):
File "talk_weather.py", line 68, in <module>
main()
File "talk_weather.py", line 16, in main
say_weather()
File "talk_weather.py", line 37, in say_weather
obj = json.loads( str(r.read()) )
File "/usr/lib/python3.4/json/__init__.py", line 318, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.4/json/decoder.py", line 343, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.4/json/decoder.py", line 361, in raw_decode
raise ValueError(errmsg("Expecting value", s, err.value)) from None
ValueError: Expecting value: line 1 column 1 (char 0)
根本的に unicode を str に変更したのがミスの原因でした。そこで、いろいろ調べてみました。
見つけたのが下記のページです。
このプログラムでは、最後に decode してますので、 json.loads の所でやってみるとよさそうです。
⇒ PythonでJSON 読み込み
ようやくエラー収束
さて、say_weather の部分を切り出して、テストしてみました。
jsay '神奈川県 横浜 の天気 今日の天気は曇時々晴です。 明日の天気は晴時々曇です。 明日の予想最高気温、31度、予想最低気温、25度です。'
ちゃんと出力されました。
それでは、ここで修正した内容を本体ににも施します。修正したソースで再実行します。
pi@raspberrypi:~/python_pg/open_jtalk $ python3 talk_weather_3.py
jsay 7月14日、22時11分56秒
jsay '神奈川県 横浜 の天気 今日の天気は晴れです。 明日の天気は晴のち曇です。 明 日の予想最高気温、33度、予想最低気温、24度です。'
やったね!ちゃんと、声も出ています。
ソースコード
訂正した python3 のソースコードを載せておきます。
2020年7月31日livedoor が天気予報サービスの配信を停止しました。yahoo!天気にリプレースしたプログラムを以下の記事に掲載しています!
天気予報配信サービス停止による天気予報データ読上げプログラムリプレース実施
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import shlex
import subprocess
from datetime import datetime
import urllib.request
import json
CMD_SAY = 'jsay'
def main():
say_datetime()
say_weather()
return
def say_datetime():
d = datetime.now()
text = '%s月%s日、%s時%s分%s秒' % (d.month, d.day, d.hour, d.minute, d.second)
text = CMD_SAY + ' ' + text
print (text)
text = '/usr/local/bin/' + text
print (text)
proc = subprocess.Popen(shlex.split(text))
proc.communicate()
return
def say_weather():
city = '140010'; # Yokohama
json_url = 'https://weather.livedoor.com/forecast/webservice/json/v1' #API URL
weather_text = u'%sの天気は%sです。'
temperature_text = u'%sの予想最高気温、%s度、予想最低気温、%s度です。'
try:
r = urllib.request.urlopen('%s?city=%s' % (json_url, city) )
obj = json.loads( r.read().decode('utf-8') )
title = obj['title']
forecasts = obj['forecasts']
# TODAY
cast = forecasts[0]
today_w_txt = weather_text % (cast['dateLabel'], cast['telop'])
# TOMMOROW
cast = forecasts[1]
temperature = cast['temperature']
tommorow_w_txt = weather_text % (cast['dateLabel'], cast['telop'])
tommorow_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
# SAY
weather_str = title + ' ' + today_w_txt + ' ' + tommorow_w_txt + ' ' + tommorow_t_txt
#weather_str = weather_str.encode('utf-8')
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()
お決まりの時間に喋らせる
最後に、crontabを使用して決まった時間にお天気予報を喋ってもらうようにしました。
0 8,12,15,20 * * * python3 /home/pi/python_pg/open_jtalk/talk_weather_3.py
最後に
openjtalkでraspberrypiにおしゃべりさせる環境は整えました。
今回は、そのraspberrypiを使って、時刻と横浜の天気をしゃべらせてみました。
単純なプログラムのコピーではつまらないのでpython3を使用するよう、ちょこっとオリジナル性を持たせました。
print文やライブラリ名の違いなどが見られましたが、ひとつずつ対応して何とか実行することが出来ました。
■思えば、「openjtalk」の記事も増えてきました
ディスカッション
コメント一覧
まだ、コメントがありません