お天気時計の作成(その3:お天気表示)

Raspberry pi zero 2Wを入手したので備忘録として書きます。

 

天気予報API

下記のURLで提供している情報を取得してお天気をLCDへ表示したいと思います。

天気予報 API(livedoor 天気互換) (tsukumijima.net)

 

お天気の情報は、JSONデータで取得でき、例えば「神奈川県(横浜)」の場合は、cityコード(地域ID)が「140010」なので下記のURLから取得できます。

https://weather.tsukumijima.net/api/forecast/city/140010

 

お天気情報の取得プログラム

下記は、先ほどのJSONデータから今日のお天気と今の時間の降水確率を取り出すプログラムです。

ファイル名:weather_get.py


#----weather_get-----

def weather_get():
    import requests
    import re
    from datetime import datetime

    #global cor,weather,weather_url
    city_code = "140010" # kanagawa(yokohama) のcityコード
    url = "https://weather.tsukumijima.net/api/forecast/city/" + city_code
    try:
        response = requests.get(url)
        response.raise_for_status()     # ステータスコード200番台以外は例外とする
    except requests.exceptions.RequestException as e:
        print("Error:{}".format(e))

    else:
        weather_json = response.json()
    #    print(weather_json['forecasts'][0]['telop']) # 0:今日 1:明日 2:明後日
        print(weather_json['forecasts'][0]['chanceOfRain']) # 0:今日 1:明日 2:明後日
        weather = weather_json['forecasts'][0]['telop']
        weather_code = weather_json['forecasts'][0]['image']['title']
        weather_url = weather_json['forecasts'][0]['image']['url']

        #file download
        import urllib.request
    #    url2 = "https://www.jma.go.jp/bosai/forecast/img/313.svg"
        url2 = weather_url
        urllib.request.urlretrieve(url2,'./icon/temp.svg')
        urllib.request.urlretrieve(url2,'./icon/'+weather_url[-7:])

     #--------------------------------------------
     #-- ICON change ----
        #svg -> pgn
        
        import sys
        import os
        os.environ['LC_CTYPE'] = "ja_JP.UTF-8"
        import cairosvg
        from PIL import Image

        svg = "./icon/temp.svg"
        png = "./icon/temp.png"
        cairosvg.svg2png(url=svg, write_to=png)
        img = Image.open(png)
    #    img.save('.icon/temp.png')
    #    print('Deleting temporary png file.')
    #    os.unlink(png)

        # 現在の時間の降水確率を取得していく
        now_hour = datetime.now().hour
        if 0 <= now_hour and now_hour < 6:
            cor = weather_json['forecasts'][0]['chanceOfRain']['T00_06']
        elif 6 <= now_hour and now_hour < 12:
            cor = weather_json['forecasts'][0]['chanceOfRain']['T06_12']
        elif 12 <= now_hour and now_hour < 18:
            cor = weather_json['forecasts'][0]['chanceOfRain']['T12_18']
        else:
            cor = weather_json['forecasts'][0]['chanceOfRain']['T18_24']

        print("現在の降水確率 {}".format(cor))
        print("today is  {}".format(weather))
        
    return cor,weather,weather_url
#--------------------------------------------------------------
if __name__ == '__main__':

    # libフォルダのライブラリを参照できるようにする。
    import sys
    sys.path.append('./lib')
    from weather_get import weather_get

    weather_get()

今日のお天気の情報

今日のお天気情報は「0」番目にあります。「1」番目は明日、「2」番目は明後日の情報になります。

「0」番目のみ取り出したのが下記になります。

 

    "forecasts": [
        {
            "date": "2024-03-30",
            "dateLabel": "今日",
            "telop": "晴のち曇",
            "detail": {
                "weather": "晴れ 夜 くもり",
                "wind": "南西の風 海上 では 南西の風 やや強く",
                "wave": "2メートル"
            },
            "temperature": {
                "min": {
                    "celsius": null,
                    "fahrenheit": null
                },
                "max": {
                    "celsius": null,
                    "fahrenheit": null
                }
            },
            "chanceOfRain": {
                "T00_06": "--%",
                "T06_12": "--%",
                "T12_18": "--%",
                "T18_24": "0%"
            },
            "image": {
                "title": "晴のち曇",
                "url": "https://www.jma.go.jp/bosai/forecast/img/110.svg",
                "width": 80,
                "height": 60
            }
        },

お天気

先ほどのプログラムでは、赤文字部分("晴のち曇")を weaterという変数へ格納しています。

降水確率

降水確率は、現在の時間から「T00_06」~「T18_24」を判定して、該当する時間の降水確率をcorという変数へ格納しています。例えば18:30の場合は「0%」(青文字の部分)です。

お天気アイコンの取得

お天気のアイコン(緑文字の部分)は、このプログラムがあるフォルダの下にiconフォルダに格納します。あらかじめiconフォルダを作成しておいてください。

 

お天気アイコンの変換

PythonのライブラリCairoSVGで、SVGファイルからPNGファイルへ変換します。

CairoSVGは、SVGファイルをPDF、EPS、PS、PNGファイルに変換することができます。
CairoSVGを使用するには、pipを使用してインストールする必要があります。

以下のコマンドを使用して、CairoSVGをインストールできます。


    $ pip install CairoSVG

 

プログラムの実行結果


LCDへのお天気の表示

下図のお天気の表示エリア(黄色の部分)に表示したいと思います。


LCD表示プログラム

下記のプログラムを以前作成したLCD_disp.pyへ追加します。


def weather_disp(cor,weather,weather_url):
    from PIL import Image
       
    #weather info
    #cor,weather,weather_url = weather_get()
                
    #天気アイコンの色を決定する
    weather_n = weather_url[-7:]
    weather_n = int(weather_n[0:3])

    icon_color = (0,0,255)
    if weather_n >= 100 and weather_n < 200 : icon_color = COLOR_RED
    if weather_n >= 200 and weather_n < 300 : icon_color = COLOR_GRAY
    if weather_n >= 300 and weather_n < 400 : icon_color = COLOR_LIGTH_BLUE
                
    # テキストを消去
    draw.rectangle((0,104,319,209), fill=COLOR_BLACK)
    draw.text((180,104), weather, font=FONT_NOTO_36, fill=COLOR_WHITE)
    draw.text((180,144), cor,     font=FONT_NOTO_48, fill=COLOR_WHITE)

    # Open image
    png = "./icon/temp.png"
    icon_image = Image.open(png)
    
    # Resize to screen size
    size = (160,120)
    icon_image = icon_image.resize(size, resample=Image.LANCZOS)
    
    # アイコンを表示
    draw.bitmap((0,96), icon_image, fill=icon_color)
    # Display image
    disp.image(image)

アイコン表示の関数「draw.bitmap」は、単色表示だったので、アイコンの種類によって色を指定するようにしました。

(アイコン名が1xx.pngは:赤、2xx.pngはグレー、3xx.pngはブルー)

 

メインプログラム

前回の温度表示のメインプログラムに赤文字部分を追加しました。


if __name__ == '__main__':

    # libフォルダのライブラリを参照できるようにする。
    import sys
    sys.path.append('./lib')
    from LCD_led import LCD_led
    from LCD_disp import LCD_set,setup_disp,time_disp,now_daytime
    from LCD_disp import temp_disp,weather_disp
    from weather_get import weather_get    
    import time
    
    #---DHT22温度センサの初期設定-----
    import Adafruit_DHT
    sensor = Adafruit_DHT.DHT22
    pin = 26
    #------------------
    
    LCD_set()     #LCDの初期設定
    LCD_led(23,1) #LCDのLED点灯
    setup_disp()  #起動中表示
    time.sleep(1) #1秒wait
    
    #今の日時を取得
    today_n,time_n,now_M_S,now_S = now_daytime()
    #時計表示
    time_disp(today_n,time_n)
    #温度取得
    humi, temp = Adafruit_DHT.read_retry(sensor, pin)
    if humi is not None and temp is not None:
        #温度表示
        temp_disp(temp,humi) 
    else:
        print('Failed to get reading. Try again!')    

    #お天気を取得
    cor,weather,weather_url = weather_get()
    #お天気をLCDへ表示
    weather_disp(cor,weather,weather_url)
    
    now_S_old = "--"
    
    while True:   
        #今の日時を取得
        today_n,time_n,now_M_S,now_S = now_daytime()
        
        if now_S != now_S_old: #1秒に1回処理するためにこの処理を追加
            #0秒になったら時計表示
            if now_S == "00" :
                time_disp(today_n,time_n)
                print(today_n,time_n)                
        
            if now_S[1] == "0": #10秒毎に処理
                #温度取得
                humi, temp = Adafruit_DHT.read_retry(sensor, pin)

                if humi is not None and temp is not None:
                    print('Temp={0:0.1f}*C  Humidity={1:0.1f}%'.format(temp, humi))
                    #温度表示
                    temp_disp(temp,humi)
                else:
                    print('Failed to get reading. Try again!')
                
            if now_M_S == "00:00" :
                #お天気を取得
                cor,weather,weather_url = weather_get()
                #お天気をLCDへ表示
                weather_disp(cor,weather,weather_url)
    
        now_S_old = now_S #1秒の切り替わりを判定するために前の秒数を保存

起動時と1時間ごとにお天気を取得してLCDへ表示するようにしました。

 

実行結果