Raspberry Piでダッシュボードを作る(4) -天気予報-
Raspberry Piとミニディスプレイ,各種センサを使ってダッシュボードを作ります.
- Raspberry Piでダッシュボードを作る(1) -準備-
- Raspberry Piでダッシュボードを作る(2) -真っ白ダッシュボード-
- Raspberry Piでダッシュボードを作る(3) -デザイン-
- Raspberry Piでダッシュボードを作る(4) -天気予報- ←イマココ
今回のゴール
- 天気予報を表示させる.
体調を崩して少し間が空いてしまいました.デザインが出来たところで天気予報を表示させていきます.
livedoor Weather Hacks
livedoorが,Weather Hacksと題して天気予報などのデータを提供しています.商用利用はできませんが,事例のところで九州の方言が楽しめるばい(方言).
ここでは,そのうちのお天気Webサービスを使います.レスポンスがJSON形式で返却されるため,取り扱いが非常に簡単です.
URLやパラメタの確認
URLやパラメタの地域(city)IDについては,お天気Webサービスのページに記述がありますのでよく読みましょう.例えば東京のidは130010です.
http://weather.livedoor.com/forecast/webservice/json/v1?city=130010
PCのブラウザで開くと,JSONと呼ばれる形式でデータが確認できます.
※スマートフォンのブラウザ等ではJSONハイジャック防止のため表示できない場合があります.
irb(Interactive Ruby)でデータを解析
では,ダッシュボードへ表示する準備です.
いきなりダッシュボードに載せる前に,rubyを対話型実行できるirb
を使って,データを解析してみましょう.
$ irb irb(main):001:0>
irb
を起動すると,入力待ちの状態になります.1行ごとに入力した内容が実行され,結果が分かるという優れものです(exitで終了します).
irb(main):001:0> require 'uri' => true
require 'uri'
と入力して実行すると,true
という結果が返却されました.
このままじゃんじゃん入力します.
irb(main):002:0> require 'net/http' => true irb(main):003:0> require 'yaml' => true irb(main):004:0> data = Net::HTTP.get(URI.parse("http://weather.livedoor.com/forecast/webservice/json/v1?city=130010")) => "{\"pinpointLocations\":[{\"link\":\"http://weather.livedoor.com/area/forecast/1310100\",\"name\":\"\\u5343\\u4ee3\\u7530\\u533a\"}, (省略) irb(main):005:0> json = YAML.load(data) => {"pinpointLocations"=>[{"link"=>"http://weather.livedoor.com/area/forecast/1310100", "name"=>"千代田区"}, (省略)
お天気WebサービスのJSONを解釈するところまで進めました.なんだか読めるモノが出てきたと思います.
引き続きお天気Webサービスの仕様を見ていると,forecasts
というプロパティに天気予報が入っていることが分かります.ちょっと見てみます.
irb(main):006:0> json["forecasts"] => [{"dateLabel"=>"今日", "telop"=>"曇時々晴", "date"=>"2017-10-31", "temperature"=>{"min"=>nil, "max"=>nil}, "image"=>{"width"=>50, "url"=>"http://weather.livedoor.com/img/icon/9.gif", "title"=>"曇時々晴", "height"=>31}}, (省略)
おっ,天気予報です.date
が日付,telop
が予報,temperature
が予想気温(夜に取得したのでその日の予想情報は無い)のようです.
だいたい取得方法がわかったので,ダッシュボードに載せていきましょう.
いざダッシュボードへ
ダッシュボードアプリの views/index.erb
を編集します.前回のデザインでカードを4個置いたので,そのうち1個を使いましょう.
<div class="card"> <h4 class="card-header">天気予報</h4> <div class="card-body"> <% # 天気予報取得処理 require 'uri' require 'net/http' require 'yaml' data = Net::HTTP.get(URI.parse("http://weather.livedoor.com/forecast/webservice/json/v1?city=130010")) json = YAML.load(data) # 今日と明日の天気 today = json["forecasts"][0]["telop"] tomorrow = json["forecasts"][1]["telop"] %> <p class="card-text"> <strong>今日</strong>: <%= today %><br> <strong>明日</strong>: <%= tomorrow %> </p> </div> </div>
補足 erb(embedded Ruby)テンプレートでは,<% ~ %>
の間にRubyスクリプトを記述したり,<%= ~ %>
の間にページに出力したい変数や式を記述することで,出力内容を柔軟に変えることができます.それ以外の部分は,そのまま出力されます.
すかさず http://localhost:4567/ にアクセスします.天気予報が表示されました.
もうちょっと,ダッシュボードへ
物足りないのでちょっと表示を良くしましょう.スクリプトの細かい説明は省きます.
<div class="card"> <h4 class="card-header">天気予報</h4> <div class="card-body"> <% # 天気予報取得処理 require 'uri' require 'net/http' require 'yaml' data = Net::HTTP.get(URI.parse("http://weather.livedoor.com/forecast/webservice/json/v1?city=130010")) json = YAML.load(data) # 今日と明日の天気 today = json["forecasts"][0]["telop"] tomorrow = json["forecasts"][1]["telop"] %> <p class="card-text"> <% json["forecasts"].each { |forecast| %> <strong><%= forecast["dateLabel"] %></strong>: <%= forecast["telop"] %> <% if forecast["temperature"]["min"] %> <span class="text-info">最低<%= forecast["temperature"]["min"]["celsius"] %>℃</span> <% end %> <% if forecast["temperature"]["max"] %> <span class="text-danger">最高<%= forecast["temperature"]["max"]["celsius"] %>℃</span> <% end %> <br> <% } %> </p> </div> </div>
気温も表示されるようになったと思います.
ページを表示するたびにお天気Webサービスへアクセスするので,更新しすぎに注意しましょう.
今回はここまで.