LoginSignup
1
1

More than 5 years have passed since last update.

「ラズパイ天気予報 〜for AIT〜」作った!

Posted at

システムの概要

どんなものを作ったか

 大学にいる時に雨が降ってきそうな天候の場合、さっさと家に帰るべきなのか、まだ大学にいてもいいのかわからないですよね。
 今回作ったシステムは、そんな問題を手軽に解決するためのものです。三時間後の天気予報をツイートするBotアカウントを作ることで、ユーザがまだ大学にいていいのか、判断を補助するためのシステムを目指しました。

システム構成

 ラズベリーパイで自校である愛知工業大学周辺地域の天気を取得し、作った専用アカウントでその情報をわかりやすい形にフォーマットして呟きます。
 システムの構成は以下の通りです。

  • Rasberry Pi model B+
  • 専用のTwitterアカウント
  • ThingTwiite
  • OpenWeatherMap

スクリーンショット 2019-05-31 21.32.57.png

 Rasberry PiがOpenWeatherMapにリクエストを送信し、受け取ったレスポンス(天気情報)を整形して、その情報をThingTweetAPIに投げます。ThingTweetAPIはAPIキーデータを元にして、紐づけられた天気予報用の専用アカウントでその情報をツイートします。
 この流れで天気予報を呟きます。

APIについてはこちらの記事、書籍にお世話になりました。
書籍:Raspberry Pi クックブック 369p「ThingSpeakを使ってツイートする」
記事:【WebAPI】OpenWeatherMapで3時間ごとの天気を取りたい【json】

システム詳細

ソースコード

 ソースコードの全貌はGithubに載せてあります。

 ラズパイ天気予報! 〜for AIT〜

 APIキーは残ったままになっていますが、削除&再生成しているので問題ありません。

 ここでは、こだわったポイントについて載せようと思います!

Main文中のbeSureToDoメソッド

Main.py
def beSureToDo(city):
    while(True):
        try:
            data = weatherApi.getDataLatLon(city[0],city[1],1)
            weatherData = extractor.DataSetting(data)
            twitter.twitte( twitext.Build(weatherData) )
        except apie.APIgetDataException:
            sleep(60)
            continue
        break

 やっていることとしてはまず、設定した市の緯度経度を元にJson形式の天気データを取得し、そこから抽出した天気情報をまとめてweatherDataに入れます。そして、ツイートするテキストを組み立てる役割を持ったクラスのインスタンスであるtwitextに天気情報を渡して組み立てたツイート文章をTwitterクラスに投げてツイートさせています。
 注目してほしいのは、天気情報の取得に失敗することで発生するAPIgetDataExceptionをキャッチして一分後にもう一度天気情報を取得できないかトライしているところです。こうすることで、APIにリクエストが集中して情報が取れなかった場合にも処理を継続して確実に天気情報をツイートすることができます!

WeatherApiUiクラス

WeatherApiUi.py
# coding: utf-8

import json
import requests
import APIgetDataException as apide

class WeatherApiUi:
    def __init__(self):
        self.api_key = '***************api - key************'
        self.baseUrl = 'http://api.openweathermap.org/data/2.5/forecast?&APPID={0}'

    def getDataLatLon(self, lat, lon, cnt=0):
        api_page = self.baseUrl + '&lat={1}&lon={2}'
        if 0 < cnt and cnt <= 30:
            api_page = api_page + '&cnt=' + str( cnt )
        url = api_page.format(self.api_key, lat, lon)
        req_response = requests.get( url )
        res = json.loads(req_response.text)
        if "message" in res and 'Internal error: 500001' == res["message"]:
            raise apide.APIgetDataException("APIサービスが混んでいるようです")
        return res

    def getDataZip(self, zip, cnt=0):
        api_page = self.baseUrl + '&zip={1}'
        if 0 < cnt and cnt <= 30:
            api_page = api_page + '&cnt=' + str( cnt )
        url = api_page.format(self.api_key,zip)
        req_response = requests.get( url )
        res = json.loads(req_response.text)
        if "message" in res and 'Internal error: 500001' == res["message"]:
            raise apide.APIgetDataException("APIサービスが混んでいるようです")
        return res

 getDataLatLonは緯度経度の情報に従って、その地点の天気情報をAPIから取得するためのメソッドで、getDataZipは郵便番号を元に天気情報を取得するメソッドです。取得件数も指定できるようになっています。
 OpenWeatherMapからの情報取得方法には都市名を指定してデータを取得するものや都市IDを指定してデータを取得するものもありますが、それらも当クラスに同様にように実装すれば、OpenWeatherMapからデータを取得するクラスとしてかなり充実したものとなると思います。

 作成段階では、当クラスに必要な天気情報だけを抽出するメソッドも実装するという案ありましたが、メソッド数が多くなりすぎてしまうのでそれは断念しました。しかも、よくよく考えると、このクラスの役割が「APIからデータを取得すること」だけでなく、「必要な情報を抜き出すこと」も持ってしまうところでした。あぶなかったです。

教訓としてはメソッド数が多くなりすぎるときはそのクラスが責務を負い過ぎている可能性が高いというところでしょうか。

 オブジェクト指向でいうところの
- 単一責務の法則
 を実践できた瞬間でした。

システムの運用方法

 OpenWeatherMapでは、天気情報の更新が0,3,6,9,12,15,18,21時に行われるので、3時間毎の定期処理実行が必要になってきます。これにはcronコマンドを利用しました。

cronとは?

 cron(クーロン)とは、Linux標準の定期処理実行を行う常駐プログラムです。crontabと呼ばれる設定ファイルに定期で実行するコマンドを書き足すことによって利用することができます。
 常駐プログラムという特性上、crontabに実行するコマンドを記述するだけで、処理が定期実行されるようになります。

 cronコマンドについてはRasberry Piを触るまで知らなかったので、色々参考にしました。

クーロン(cron)をさわってみるお
cronでスクリプトを定期実行させるときに注意したい4つのこと
Cron が走っているかどうか確認する
cronの停止コマンド
RaspberryPi cronが効かない → /etc/crontab のパーミッションと所有者を見直して解決

 調査の結果、以下のコマンドをcrontabに記述しておけば良いことがわかりました。

LANG=jp_JP.UTF-8
0 0,3,6,9,12,15,18,21 * * * python3 /etc/pi/hoge/fugafuga/Main.py

 一行目では、スクリプト中に登場する日本語を文字化けさせないための環境変数設定です。cronは実行時にユーザの環境変数を引き継がないので、スクリプト中に日本語を使っている場合は文字化けを防ぐために書いた方が良いとのことです。

cronについて学んだこと一覧

  • cronは、設定した定期処理を実行してくれる常駐プログラムである
  • 設定の変更はcrontab -eで行える(ユーザ権限の設定ファイル)
  • crontab -rで設定が吹き飛ぶ(消去される)ので、注意する。
  • 管理者用のcrontab/home/pi階層から../../etc/crontabの位置にある。
  • なおこのファイルを変更する場合はテキストエディタで設定する。例としてはsudo nano crontabである。
  • cronが実行されているかはservice cron statusで調べられる。
  • cronを起動するコマンドは、service cron start
  • cronを再起動するコマンドはservice cron restart
  • cronを停止するコマンドはservice cron stop
  • cronに設定されているコマンドを確認するためのコマンドはcrontab -l
  • ネットの情報を見ているとcrondcronの二種類が散見されるが、Rasberry Piの場合はcronである。
  • 権限を付与しないとコマンドを実行できない場合がある。
  • cronの時間指定は分 時 日 月 曜日の順
  • コマンドは絶対パスで記述した方が良い。

できあがったもの

 こんな感じになりました!

 ラズパイ天気予報! ~for AIT~のTwitterアカウント
 スクリーンショット 2019-06-02 13.44.43.png

 Rasberry PiがAITの周辺の市の天気予報を三時間おきにつぶやいています。
 これで早く帰らないといけないかがわかりますね(予報だから当たるとは言ってない)

参考文献

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1