Thonthon : mon PI compagnon – Part two
Petit bricolage d’une station météo. L’idée est d’affichier sur le pHat une alternance heure / météo. Pour se faire je me suis basé sur l’exemple “clock.py” auquel j’ai rajouté une connexion à l’API pyowm. Voici le principe :
Le code est assez simple. En gros :
1. On check s’il existe une connexion internet
2. Si oui, on met à jour la ville courrante basée sur l’adresse IP publique (si indisponible, prendre la ville par défaut)
3. On lance de façon alternée l’heure (5 secondes) et la météo (~11 secondes)
4. La météo lancée affiche la température, la vitesse du vent et le pourcentage d’humidité dans l’air.
#!/usr/bin/env python
import time
import json
import pyowm
import requests
import scrollphathd
from datetime import datetime
from scrollphathd.fonts import font5x5, font5x7
print("""
Scroll pHAT HD: Clock
Displays weather, hours and minutes in text,
plus a seconds progress bar.
Press Ctrl+C to exit!
""")
# Display a progress bar for seconds
# Displays a dot if False
DISPLAY_BAR = True
# Brightness of the seconds bar and text
BRIGHTNESS = 0.2
# API Key for Weather forecast and minutes allowed between requests
API_KEY = "XXX"
WEATHER_INTERVAL = 65*60
# Weather location
weather_loc = "Paris,fr"
# Uncomment the below if your display is upside down
# (e.g. if you're using it in a Pimoroni Scroll Bot)
scrollphathd.rotate(degrees=180)
scrollphathd.set_brightness(BRIGHTNESS)
def check_net():
try:
response = requests.get("http://www.google.com")
print("Internet OK")
except requests.ConnectionError:
print("Could not connect to Internet")
return False
return True
def show_clock(duration: int=5) -> None:
print("Running show_clock for", duration, "seconds")
scrollphathd.set_font(font5x5)
sec = abs(datetime.timestamp(datetime.now()))
while abs(datetime.timestamp(datetime.now())) - sec < duration:
scrollphathd.clear()
# Grab the "seconds" component of the current time
# and convert it to a range from 0.0 to 1.0
float_sec = (time.time() % 60) / 59.0
# Multiply our range by 15 to spread the current
# number of seconds over 15 pixels.
#
# 60 is evenly divisible by 15, so that
# each fully lit pixel represents 4 seconds.
#
# For example this is 28 seconds:
# [x][x][x][x][x][x][x][ ][ ][ ][ ][ ][ ][ ][ ]
# ^ - 0 seconds 59 seconds - ^
seconds_progress = float_sec * 15
if DISPLAY_BAR:
# Step through 15 pixels to draw the seconds bar
for y in range(15):
# For each pixel, we figure out its brightness by
# seeing how much of "seconds_progress" is left to draw
# If it's greater than 1 (full brightness) then we just display 1.
current_pixel = min(seconds_progress, 1)
# Multiply the pixel brightness (0.0 to 1.0) by our global brightness value
scrollphathd.set_pixel(y + 1, 6, current_pixel)
# Subtract 1 now we've drawn that pixel
seconds_progress -= 1
# If we reach or pass 0, there are no more pixels left to draw
if seconds_progress <= 0:
break
else:
# Just display a simple dot
scrollphathd.set_pixel(int(seconds_progress), 6, 1)
# Display the time (HH:MM) in a 5x5 pixel font
scrollphathd.write_string(time.strftime("%H:%M"), 0, 0)
# int(time.time()) % 2 will tick between 0 and 1 every second.
# We can use this fact to clear the ":" and cause it to blink on/off
# every other second, like a digital clock.
# To do this we clear a rectangle 8 pixels along, 0 down,
# that's 1 pixel wide and 5 pixels tall.
if int(time.time()) % 2 == 0:
scrollphathd.clear_rect(8, 0, 1, 5)
# Display our time and sleep a bit. Using 1 second in time.sleep
# is not recommended, since you might get quite far out of phase
# with the passing of real wall-time seconds and it'll look weird!
#
# 1/10th of a second is accurate enough for a simple clock though :D
scrollphathd.show()
time.sleep(0.1)
def show_weather(weather, duration: int=5) -> None:
print("Running show_weather for", duration, "seconds")
print("Location: " + weather_loc)
scrollphathd.clear()
scrollphathd.set_font(font5x7)
# Set scrolling speed
speed=0.05
# Get weather data
t_metric = "°C"
w_metric = "km/h"
h_metric = "%"
temp = "0"
humidity = "0"
wind = "0"
if weather:
temp = str(weather.get_temperature('celsius')['temp'])
wind = str(round(weather.get_wind(unit='meters_sec')['speed']*3.6))
humidity = str(weather.get_humidity())
weather_info = (
" "
+ temp + t_metric + " "
+ wind + w_metric + " "
+ humidity + h_metric
)
# Display the weather in a 5x5 pixel font
scrollphathd.write_string(weather_info)
timer = 0
while timer < (duration / (2*speed)):
scrollphathd.show()
scrollphathd.scroll(1)
time.sleep(speed)
timer += 1
def update_location() -> None:
# Update geo location
data_content = requests.get("http://ipinfo.io/json")
loc_data = json.loads(data_content.content.decode())
country = loc_data['country'].lower()
city = loc_data['city']
weather_loc = city + "," + country
while True:
try:
print("Rolling Barrel")
# Fetch time to check for weather every 65 minutes
weather = None
if check_net():
update_location()
owm = pyowm.OWM(API_KEY)
observation = owm.weather_at_place(weather_loc)
weather = observation.get_weather()
sec_timer = abs(datetime.timestamp(datetime.now()))
while abs(datetime.timestamp(datetime.now())) - sec_timer < WEATHER_INTERVAL:
# Alternate betweek clock and weather
show_clock(5)
show_weather(weather, 11)
time.sleep(0.1)
except (KeyboardInterrupt, SystemExit):
print("Exiting...")
exit()
Laisser un commentaire