|
| 1 | +from datetime import datetime |
| 2 | +import json |
| 3 | +from PIL import Image, ImageDraw, ImageFont |
| 4 | +from adafruit_epd.epd import Adafruit_EPD |
| 5 | + |
| 6 | +small_font = ImageFont.truetype( |
| 7 | + "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 16 |
| 8 | +) |
| 9 | +medium_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20) |
| 10 | +large_font = ImageFont.truetype( |
| 11 | + "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 24 |
| 12 | +) |
| 13 | +icon_font = ImageFont.truetype("./meteocons.ttf", 48) |
| 14 | + |
| 15 | +# Map the OpenWeatherMap icon code to the appropriate font character |
| 16 | +# See http://www.alessioatzeni.com/meteocons/ for icons |
| 17 | +ICON_MAP = { |
| 18 | + "01d": "B", |
| 19 | + "01n": "C", |
| 20 | + "02d": "H", |
| 21 | + "02n": "I", |
| 22 | + "03d": "N", |
| 23 | + "03n": "N", |
| 24 | + "04d": "Y", |
| 25 | + "04n": "Y", |
| 26 | + "09d": "Q", |
| 27 | + "09n": "Q", |
| 28 | + "10d": "R", |
| 29 | + "10n": "R", |
| 30 | + "11d": "Z", |
| 31 | + "11n": "Z", |
| 32 | + "13d": "W", |
| 33 | + "13n": "W", |
| 34 | + "50d": "J", |
| 35 | + "50n": "K", |
| 36 | +} |
| 37 | + |
| 38 | +# RGB Colors |
| 39 | +WHITE = (255, 255, 255) |
| 40 | +BLACK = (0, 0, 0) |
| 41 | + |
| 42 | + |
| 43 | +class Weather_Graphics: |
| 44 | + def __init__(self, display, *, am_pm=True, celsius=True): |
| 45 | + self.am_pm = am_pm |
| 46 | + self.celsius = celsius |
| 47 | + |
| 48 | + self.small_font = small_font |
| 49 | + self.medium_font = medium_font |
| 50 | + self.large_font = large_font |
| 51 | + |
| 52 | + self.display = display |
| 53 | + |
| 54 | + self._weather_icon = None |
| 55 | + self._city_name = None |
| 56 | + self._main_text = None |
| 57 | + self._temperature = None |
| 58 | + self._description = None |
| 59 | + self._time_text = None |
| 60 | + |
| 61 | + def display_weather(self, weather): |
| 62 | + weather = json.loads(weather) |
| 63 | + |
| 64 | + # set the icon/background |
| 65 | + self._weather_icon = ICON_MAP[weather["weather"][0]["icon"]] |
| 66 | + |
| 67 | + city_name = weather["name"] + ", " + weather["sys"]["country"] |
| 68 | + print(city_name) |
| 69 | + self._city_name = city_name |
| 70 | + |
| 71 | + main = weather["weather"][0]["main"] |
| 72 | + print(main) |
| 73 | + self._main_text = main |
| 74 | + |
| 75 | + temperature = weather["main"]["temp"] - 273.15 # its...in kelvin |
| 76 | + print(temperature) |
| 77 | + if self.celsius: |
| 78 | + self._temperature = "%d °C" % temperature |
| 79 | + else: |
| 80 | + self._temperature = "%d °F" % ((temperature * 9 / 5) + 32) |
| 81 | + |
| 82 | + description = weather["weather"][0]["description"] |
| 83 | + description = description[0].upper() + description[1:] |
| 84 | + print(description) |
| 85 | + self._description = description |
| 86 | + # "thunderstorm with heavy drizzle" |
| 87 | + |
| 88 | + self.update_time() |
| 89 | + |
| 90 | + def update_time(self): |
| 91 | + now = datetime.now() |
| 92 | + self._time_text = now.strftime("%I:%M %p").lstrip("0").replace(" 0", " ") |
| 93 | + self.update_display() |
| 94 | + |
| 95 | + def update_display(self): |
| 96 | + self.display.fill(Adafruit_EPD.WHITE) |
| 97 | + image = Image.new("RGB", (self.display.width, self.display.height), color=WHITE) |
| 98 | + draw = ImageDraw.Draw(image) |
| 99 | + |
| 100 | + # Draw the Icon |
| 101 | + (font_width, font_height) = icon_font.getsize(self._weather_icon) |
| 102 | + draw.text( |
| 103 | + ( |
| 104 | + self.display.width // 2 - font_width // 2, |
| 105 | + self.display.height // 2 - font_height // 2 - 5, |
| 106 | + ), |
| 107 | + self._weather_icon, |
| 108 | + font=icon_font, |
| 109 | + fill=BLACK, |
| 110 | + ) |
| 111 | + |
| 112 | + # Draw the city |
| 113 | + draw.text( |
| 114 | + (5, 5), self._city_name, font=self.medium_font, fill=BLACK, |
| 115 | + ) |
| 116 | + |
| 117 | + # Draw the time |
| 118 | + (font_width, font_height) = medium_font.getsize(self._time_text) |
| 119 | + draw.text( |
| 120 | + (5, font_height * 2 - 5), |
| 121 | + self._time_text, |
| 122 | + font=self.medium_font, |
| 123 | + fill=BLACK, |
| 124 | + ) |
| 125 | + |
| 126 | + # Draw the main text |
| 127 | + (font_width, font_height) = large_font.getsize(self._main_text) |
| 128 | + draw.text( |
| 129 | + (5, self.display.height - font_height * 2), |
| 130 | + self._main_text, |
| 131 | + font=self.large_font, |
| 132 | + fill=BLACK, |
| 133 | + ) |
| 134 | + |
| 135 | + # Draw the description |
| 136 | + (font_width, font_height) = small_font.getsize(self._description) |
| 137 | + draw.text( |
| 138 | + (5, self.display.height - font_height - 5), |
| 139 | + self._description, |
| 140 | + font=self.small_font, |
| 141 | + fill=BLACK, |
| 142 | + ) |
| 143 | + |
| 144 | + # Draw the temperature |
| 145 | + (font_width, font_height) = large_font.getsize(self._temperature) |
| 146 | + draw.text( |
| 147 | + ( |
| 148 | + self.display.width - font_width - 5, |
| 149 | + self.display.height - font_height * 2, |
| 150 | + ), |
| 151 | + self._temperature, |
| 152 | + font=self.large_font, |
| 153 | + fill=BLACK, |
| 154 | + ) |
| 155 | + |
| 156 | + self.display.image(image) |
| 157 | + self.display.display() |
0 commit comments