気の向くままに辿るIT/ICT/IoT
webzoit.net
IoT・電子工作

自作ラズパイスマートスピーカーで天気予報を読み上げ

ウェブ造ホーム前へ次へ
サイト内検索
カスタム検索
Raspberry Piって?

自作ラズパイスマートスピーカーで天気予報を読み上げ

自作ラズパイスマートスピーカーで天気予報を読み上げ

2019/02/06

 以前、作ったRaspberry Pi 3 Model B+とJuliusOpen JTalkベースのスマートスピーカーを自作した時点で搭載済みの機能ですが、改めてページとして起こしておくことに。

 主な機能は、

 尚、ラズパイ用ACアダプタを挿したスイッチ付きコンセントでのON/OFFとは別にラズパイ用boot/reboot/shutdown物理ボタン付き。

 ちなみに便利なのでラズパイだけでなく、PC/Debianにも自作スマートスピーカー機能を搭載しています。

天気予報APIから天気情報取得

 天気APIから情報を得るスクリプトについては、livedoorの天気予報API『Weather Hacks』を使ったというPythonで書かれたtalk_weather.pyをhttp://raspi.seesaa.net/article/415530289.htmlから拝借。

 入力に応じた分岐条件を追記・編集してもよかったのかもしれませんが、Python初心者の自身は、用途ごとにスクリプトファイルを分割し、ベースと成る音声操作応答用Perlスクリプトから、それらPythonスクリプトを直接呼び出す方法をとりました。

 このpythonスクリプト内では、奇しくも発話用にjsayという同じ名前のスクリプトを指定していますが、登録済み実行パスに存在するコマンドとして書いてあるようなので、そうでない場合は、環境に応じてjsayスクリプトのパスを合わせておく必要があります。

 jsayスクリプトは、Open JTalkから成るスクリプト、詳細は、冒頭リンク「スマートスピーカーを自作」参照。

 自身は、ローカルで対応したが、このWeather Hacks、日付や時刻情報も取得できます。

天気予報API取得情報読み上げスクリプト

$ chmod +x ~/script/today_weather.py
$ cat ~/script/today_weather.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import shlex
import subprocess
 
from datetime import datetime
 
import urllib2
import json
 
#CMD_SAY = 'jsay'
#CMD_SAY = './jsay'
CMD_SAY = '/home/xxx/tmp/sound/jsay'
 
def main():
  say_weather()
  return
 
def say_weather():
  city = '130010'; # Tokyo
  json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL
 
  weather_text = u'%sの天気は%sです。'
 
  try:
    r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
    obj = json.loads( unicode(r.read()) )
 
    title = obj['title']
    forecasts = obj['forecasts']
 
    # TODAY
    cast = forecasts[0]
    today_w_txt = weather_text % (cast['dateLabel'], cast['telop'])
 
    # SAY
    weather_str = title + ' ' + today_w_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()
$

 今日の天気、最高気温・最低気温を読み上げてくれるpythonスクリプト。

 と思いましたが、お天気Webサービス仕様のサンプルを見ると当日の最低気温はnullで取得できない仕様、最高気温は取得できそうに見えるもダメな模様。

 ただ、後述の通り、今日の最高気温だけなら取得できます。

 よって当日は、天気のみとしました。

$ chmod +x ~/script/tomorrow_weather.py
$ cat ~/script/tomorrow_weather.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import shlex
import subprocess
 
from datetime import datetime
 
import urllib2
import json
 
#CMD_SAY = 'jsay'
#CMD_SAY = './jsay'
CMD_SAY = '/home/xxx/tmp/sound/jsay'
 
def main():
  say_weather()
  return
 
def say_weather():
  city = '130010'; # Tokyo
  json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL
 
  weather_text = u'%sの天気は%sです。'
  temperature_text = u'%sの予想最高気温、%s度、予想最低気温、%s度です。'
 
  try:
    r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
    obj = json.loads( unicode(r.read()) )
 
    title = obj['title']
    forecasts = obj['forecasts']
 
    # TOMORROW
    cast = forecasts[1]
    temperature = cast['temperature']
    tomorrow_w_txt = weather_text % (cast['dateLabel'], cast['telop'])
    tomorrow_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
 
    # SAY
    weather_str = title + ' ' + 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()
$

 明日の天気及び最高気温、最低気温を読み上げてくれるpythonスクリプト。

$ chmod +x ~/script/day_after_tomorrow_weather.py
$ cat ~/script/day_after_tomorrow_weather.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import shlex
import subprocess
 
from datetime import datetime
 
import urllib2
import json
 
#CMD_SAY = 'jsay'
#CMD_SAY = './jsay'
CMD_SAY = '/home/xxx/tmp/sound/jsay'
 
def main():
  say_weather()
  return
 
def say_weather():
  city = '130010'; # Tokyo
  json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL
 
  weather_text = u'%sの天気は%sです。'
 
  try:
    r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
    obj = json.loads( unicode(r.read()) )
 
    title = obj['title']
    forecasts = obj['forecasts']
 
    # THE DAY AFTER TOMORROW
    cast = forecasts[2]
    day_after_tommorow_w_txt = weather_text % (cast['dateLabel'], cast['telop'])
 
    # SAY
    weather_str = title + ' ' + day_after_tommorow_w_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()
$

 明後日の天気を読み上げてくれるpythonスクリプト。

 Weather Hacksでは、明後日の気温情報はnullであり、ないので天気のみ。

$ chmod +x ~/script/today_temperature.py
$ cat ~/script/today_temperature.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import shlex
import subprocess
 
from datetime import datetime
 
import urllib2
import json
 
#CMD_SAY = 'jsay'
#CMD_SAY = './jsay'
CMD_SAY = '/home/xxx/tmp/sound/jsay'
 
def main():
  say_weather()
  return
 
def say_weather():
  city = '130010'; # Tokyo
  json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL
 
  temperature_text = u'%sの予想最高気温、%s度、予想最低気温は、今更聞かないで下さい。'
 
  try:
    r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
    obj = json.loads( unicode(r.read()) )
 
    title = obj['title']
    forecasts = obj['forecasts']
 
    # TODAY
    cast = forecasts[0]
    temperature = cast['temperature']
    today_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'])
 
    # SAY
    weather_str = title + ' ' + today_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()
$

 今日の最高気温、最低気温を読み上げてくれるpythonスクリプト。

 ただし、前述の通り、当日の最低気温は、nullで取得できない為、「今更聞かないで」と返すようにしてみました。

$ chmod +x ~/script/tomorrow_temperature.py
$ cat ~/script/tomorrow_temperature.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import shlex
import subprocess
 
from datetime import datetime
 
import urllib2
import json
 
#CMD_SAY = 'jsay'
#CMD_SAY = './jsay'
CMD_SAY = '/home/xxx/tmp/sound/jsay'
 
def main():
  say_weather()
  return
 
def say_weather():
  city = '130010'; # Tokyo
  json_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' #API URL
 
  temperature_text = u'%sの予想最高気温、%s度、予想最低気温、%s度です。'
 
  try:
    r = urllib2.urlopen('%s?city=%s' % (json_url, city) )
    obj = json.loads( unicode(r.read()) )
 
    title = obj['title']
    forecasts = obj['forecasts']
 
    # TOMORROW
    cast = forecasts[1]
    tommorow_t_txt = temperature_text % (cast['dateLabel'], temperature['max']['celsius'], temperature['min']['celsius'])
 
    # SAY
    weather_str = title + ' ' + 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()
$

 明日の最高気温、最低気温を読み上げてくれるpythonスクリプト。

ラズパイスマートスピーカーへの反映

 ラズパイスマートスピーカーへの反映についても詳細は、「スマートスピーカーを自作」他、リンク先参照。

ウェブ造ホーム前へ次へ