Open Richard238 opened 1 year ago
We've been enjoying using the OpenMeteo API for weather stuff!
I recently updated the Inky pHAT weather example to use OpenMeteo as its data source instead of DarkSky - looks like the weather example in this repo is quite similar if you wanted to modify this one in the same way?
I'm probably out of my depth with that kind of thing TBH. I'll give it a try when I get time...
NameError: name 'sh1106' is not defined
#!/usr/bin/env python3
## -*- coding: utf-8 -*-
import os
import time
import datetime
import glob
import logging
import json
from demo_opts import get_device
from font_fredoka_one import FredokaOne
from PIL import Image, ImageDraw, ImageFont
try:
from smbus2 import SMBus
except ImportError:
from smbus import SMBus
from bme280 import BME280
from sys import exit
try:
import requests
except ImportError:
exit("This script requires the requests module\nInstall with: sudo pip install requests")
try:
import geocoder
except ImportError:
exit("This script requires the geocoder module\nInstall with: sudo pip install geocoder")
print("""Test""")
CITY = "Sheffield"
COUNTRYCODE = "GB"
WARNING_TEMP = 25.0
# Used to calibrate the sensor
TEMP_OFFSET = 0.0
logging.basicConfig(level=os.environ.get("LOGLEVEL", "WARNING"))
### using BME280 not 680 ###
print("""This Pimoroni Breakout Garden example requires a
BME680 Environmental Sensor Breakout and a 1.12" OLED Breakout.
This example turns your Breakout Garden into a mini weather display
combining indoor temperature and pressure data with a weather icon
indicating the current local weather conditions.
Press Ctrl+C a couple times to exit.
""")
# Convert a city name and country code to latitude and longitude
def get_coords(address):
g = geocoder.arcgis(address)
coords = g.latlng
return coords
# Query OpenMeteo (https://open-meteo.com) to get current weather data
def get_weather(address):
coords = get_coords(address)
weather = {}
res = requests.get("https://api.open-meteo.com/v1/forecast?latitude=" + str(coords[0]) + "&longitude=" + str(coords[1]) + "¤t_weather=true")
if res.status_code == 200:
j = json.loads(res.text)
current = j["current_weather"]
weather["temperature"] = current["temperature"]
weather["windspeed"] = current["windspeed"]
weather["weathercode"] = current["weathercode"]
return weather
else:
return weather
icon_map = {
"snow": [71, 73, 75, 77, 85, 86],
"rain": [51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82],
"cloud": [1, 2, 3, 45, 48],
"sun": [0],
"storm": [95, 96, 99],
"wind": []
}
# Pre-load icons into a dictionary with PIL
icons = {}
for icon in glob.glob("icons/*.png"):
icon_name = icon.split("/")[1].replace(".png", "")
icon_image = Image.open(icon)
icons[icon_name] = icon_image
location_string = "{city}, {countrycode}".format(city=CITY,
countrycode=COUNTRYCODE)
coords = get_coords(location_string)
def get_weather_icon(weather):
if weather:
summary = weather["summary"]
for icon in icon_map:
if summary in icon_map[icon]:
logging.info("Weather icon: %s", icon)
return icons[icon]
logging.error("Could not determine icon for weather")
return None
else:
logging.error("No weather information provided to get icon")
return None
# Get initial weather data for the given location
#weather_icon = get_weather_icon(get_weather(coords))
# Get the weather data for the given location
location_string = "{city}, {countrycode}".format(city=CITY, countrycode=COUNTRYCODE)
weather = get_weather(location_string)
# Set up OLED
# Launching from terminal, so don't seem to need this?
oled = sh1106(spi(port=0, device=1, gpio_DC=9), rotate=2, height=128, width=128)
# Initialise the BME280
bus = SMBus(1)
bme280 = BME280(i2c_dev=bus)
temperature = bme280.get_temperature()
pressure = bme280.get_pressure()
humidity = bme280.get_humidity()
print('{:05.2f}*C {:05.2f}hPa {:05.2f}%'.format(temperature, pressure, humidity))
last_checked = time.time()
# device = get_device()
device = oled.display
# Main loop
while True:
# Limit calls to Dark Sky to 1 per minute
if time.time() - last_checked > 60:
weather_icon = get_weather_icon(get_weather(coords))
last_checked = time.time()
#device = get_device()
# Load in the background image
# Use random image until it works
background = Image.open("images/runner.png").convert(device)
# Place the weather icon and draw the background
if weather_icon:
background.paste(weather_icon, (10, 46))
draw = ImageDraw.ImageDraw(background)
# Gets temp. and press. and keeps track of daily min and max temp
if sensor.get_sensor_data():
temp = sensor.data.temperature
press = sensor.data.pressure
if datetime.datetime.today().day == curr_date:
if temp < low_temp:
low_temp = temp
elif temp > high_temp:
high_temp = temp
else:
curr_date = datetime.datetime.today().day
low_temp = temp
high_temp = temp
# Write temp. and press. to image
draw.text((8, 22), "{0:4.0f}".format(press),
fill="white", font=rb_20)
draw.text((86, 12), u"{0:2.0f}°".format(temp),
fill="white", font=rb_20)
# Write min and max temp. to image
draw.text((80, 0), u"max: {0:2.0f}°".format(high_temp),
fill="white", font=rr_12)
draw.text((80, 110), u"min: {0:2.0f}°".format(low_temp),
fill="white", font=rr_12)
# Write the 24h time and blink the separator every second
if int(time.time()) % 2 == 0:
draw.text((4, 98), datetime.datetime.now().strftime("%H:%M"),
fill="white", font=rr_24)
else:
draw.text((4, 98), datetime.datetime.now().strftime("%H %M"),
fill="white", font=rr_24)
# These lines display the temp. on the thermometer image
draw.rectangle([(97, 43), (100, 86)], fill="black")
temp_offset = 86 - ((86 - 43) * ((temp - 20) / (32 - 20)))
draw.rectangle([(97, temp_offset), (100, 86)], fill="white")
# Display the completed image on the OLED
oled.display(background)
time.sleep(TEMPERATURE_UPDATE_INTERVAL)
Looks like you're missing the imports for the OLED display?
from luma.core.interface.serial import spi
from luma.core.error import DeviceNotFoundError
from luma.oled.device import sh1106
For the weather.py example, what's the new suggested, recommended source API?
I ask as it appears the Dark Sky API is no longer available.
Thank you.