余ったラズパイで時計と天気を表示するデジタルサイネージっぽいものを作った。
使用したもの
- Raspberry Pi 3 ModelB+
- LEDディスプレイ
- HDMI
- マウス
- キーボード
時計と天気を表示するPythonアプリの作成
時計と天気はTkinterで表示する。天気はOpenWetherAPIで特定の場所の天気を取得する。
Tkinterをインストール
pip3 install pytk
下記時計と天気情報を表示するプログラム
import tkinter as tk
from tkinter import font
import time
import requests
import math
# OpenWeatherMap API
api_key = '**************************' # ここにAPIキーを入力してください
city_name = 'Tokyo' # 表示したい都市名
def get_weather():
url = f"http://api.openweathermap.org/data/2.5/weather?q={city_name}&appid={api_key}&units=metric"
response = requests.get(url)
weather_data = response.json()
if weather_data['cod'] == 200:
temp = weather_data['main']['temp']
weather_desc = weather_data['weather'][0]['description']
return f"{city_name}: {temp}°C, {weather_desc.capitalize()}"
else:
return "Weather data not available"
def update_clock():
current_time = time.strftime('%H:%M:%S')
time_label.config(text=current_time)
time_label.after(1000, update_clock) # 1秒ごとに更新
def update_weather():
weather = get_weather()
weather_label.config(text=weather)
weather_label.after(600000, update_weather) # 10分ごとに更新
def draw_hand(canvas, length, angle, width, color, tag):
angle = math.radians(angle)
x = center_x + length * math.sin(angle)
y = center_y - length * math.cos(angle)
canvas.create_line(center_x, center_y, x, y, width=width, fill=color, tags=tag)
def update_analog_clock():
# 既存の針を削除
canvas.delete('hands')
# 現在時刻を取得
now = time.localtime()
hour = now.tm_hour % 12
minute = now.tm_min
second = now.tm_sec
# 角度計算
hour_angle = (hour + minute / 60) * 30 # 1時間=30度
minute_angle = (minute + second / 60) * 6 # 1分=6度
second_angle = second * 6 # 1秒=6度
# 時計の針を描画(タグ付き)
draw_hand(canvas, clock_radius * 0.5, hour_angle, 8, 'white', 'hands') # 時針
draw_hand(canvas, clock_radius * 0.7, minute_angle, 6, 'white', 'hands') # 分針
draw_hand(canvas, clock_radius * 0.9, second_angle, 2, 'red', 'hands') # 秒針
canvas.after(1000, update_analog_clock)
# GUI Setup
root = tk.Tk()
root.title("Digital Signage")
root.attributes("-fullscreen", True) # フルスクリーンモード
root.configure(background='black')
root.attributes('-fullscreen', True)
# フォント設定
time_font = font.Font(family='Helvetica', size=30, weight='bold')
weather_font = font.Font(family='Helvetica', size=20, weight='bold')
# 時計の中心と半径
center_x, center_y = 200, 180
clock_radius = 150
# キャンバス(アナログ時計表示用)
canvas = tk.Canvas(root, width=400, height=400, bg='black', highlightthickness=0)
canvas.pack(anchor='center', pady=0)
# デジタル時計表示ラベル
time_label = tk.Label(root, font=time_font, bg='black', fg='white')
time_label.pack(anchor='n', pady=0)
# 天気表示ラベル
weather_label = tk.Label(root, font=weather_font, bg='black', fg='white')
weather_label.pack(anchor='s', pady=20)
# アナログ時計の盤面を描画
for i in range(12):
angle = math.radians(i * 30)
x = center_x + clock_radius * 0.9 * math.sin(angle)
y = center_y - clock_radius * 0.9 * math.cos(angle)
canvas.create_text(x, y, text=str(i if i > 0 else 12), fill="white", font=("Helvetica", 24))
# 時刻と天気情報の更新
update_clock()
update_weather()
update_analog_clock()
# 終了するにはEscキーを押す
root.bind("<Escape>", lambda e: root.destroy())
root.mainloop()
ラズパイ起動時に自動実行
意外とここに時間がかかった。
サービスデーモンを作成するときに気を付けること
- コマンドはフルパスで記載
- 実行ユーザーを指定する
- 失敗したときの再実行を定義する
sudo emacs /etc/systemd/system/run_uvicorn.service
sudo systemctl daemon-reload
sudo systemctl stop run_uvicorn.service
sudo systemctl start run_uvicorn.service
[Unit]
Description = run uvicorn daemon
After=network.target
[Service]
User=ec2-user
Group=ec2-user
ExecStart = /home/ec2-user/run_uvicorn.sh
WorkingDirectory=/var/www/html/myapp
RemainAfterExit=yes
Restart=always
RestartSec=20
[Install]
WantedBy = multi-user.target
run_uvicorn.sh
#!/bin/sh
PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH
echo `date` >> /home/ec2-user/run_uvicorn.log
# Fast API Server Auto Boot
alias mycommand='/usr/bin/nohup uvicorn main:app --host localhost --port 8000 --workers 1 --timeout-keep-alive 30 &'
mycommand
#find /tmp/ -type f -mtime +7 -exec rm -f {} \;
起動時の自動実行は、systemctl serviceを使用する。
- 上記Pythonコードを実行するシェルスクリプトを作成する。
/home/pi/autoexec.sh
#!/bin/sh
export DISPLAY=:0.0
exec python3 /home/pi/auroexec.py
DISPLAY=:**の数字はecho $DISPLAYで確認してください
- serviceファイルを作成する
vi /etc/systemdl/system/autoexec.service - 下記を記載する
/etc/systemdl/system/autoexec.service
[Unit] Desription=My Tkinter Script After=network-online.target #Wants=graphical.target [Service] User=pi Group=pi Environment=DISPLAY=:0.0 #Environment=XAUTHOITY=/home/pi/.Xauthority ExecStart=/bin/bash /home/pi/autoexec.sh Restart=always RestartSec=5 Type=forking RemainAfterExit=yes RuntimeMaxSec=7d [Install] WantedBy=multi-user.target
- systemctl daemon-reload
- systemctl start autoexec.service
これで正常にPythonプログラムが実行されるか確認する。 - systemctl enable autoexec.service
- sudo reboot
参考リンク