/ PyPortal_Titano_Weather_Station / openweather_graphics.py
openweather_graphics.py
  1  # SPDX-FileCopyrightText: 2019 Limor Fried for Adafruit Industries
  2  # SPDX-FileCopyrightText: 2020 Liz Clark for Adafruit Industries
  3  #
  4  # SPDX-License-Identifier: MIT
  5  
  6  import time
  7  import json
  8  from calendar import holidays
  9  import displayio
 10  from adafruit_display_text.label import Label
 11  from adafruit_bitmap_font import bitmap_font
 12  
 13  cwd = ("/"+__file__).rsplit('/', 1)[0] # the current working directory (where this file is)
 14  
 15  small_font = cwd+"/fonts/EffectsEighty-24.bdf"
 16  medium_font = cwd+"/fonts/EffectsEighty-32.bdf"
 17  weather_font = cwd+"/fonts/EffectsEighty-48.bdf"
 18  large_font = cwd+"/fonts/EffectsEightyBold-68.bdf"
 19  
 20  month_name = ["Jan.", "Feb.", "Mar.", "Apr.", "May", "June", "July", "Aug.",
 21                "Sept.", "Oct.", "Nov.", "Dec."]
 22  weekday = ["Mon.", "Tues.", "Wed.", "Thurs.", "Fri.", "Sat.", "Sun."]
 23  holiday_checks = [holidays['new years'][0],holidays['valentines'][0],
 24                    holidays['halloween'][0],holidays['xmas'][0]]
 25  holiday_greetings = [holidays['new years'][1],holidays['valentines'][1],
 26                       holidays['halloween'][1],holidays['xmas'][1]]
 27  
 28  class OpenWeather_Graphics(displayio.Group):
 29  
 30      def __init__(self, root_group, *, am_pm=True, celsius=True):
 31          super().__init__()
 32          self.am_pm = am_pm
 33          self.celsius = celsius
 34  
 35          root_group.append(self)
 36          self._icon_group = displayio.Group()
 37          self.append(self._icon_group)
 38          self._text_group = displayio.Group()
 39          self.append(self._text_group)
 40  
 41          self._icon_sprite = None
 42          self._icon_file = None
 43          self.set_icon(cwd+"/weather_background.bmp")
 44  
 45          self.small_font = bitmap_font.load_font(small_font)
 46          self.medium_font = bitmap_font.load_font(medium_font)
 47          self.weather_font = bitmap_font.load_font(weather_font)
 48          self.large_font = bitmap_font.load_font(large_font)
 49          glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.: '
 50          self.small_font.load_glyphs(glyphs)
 51          self.medium_font.load_glyphs(glyphs)
 52          self.weather_font.load_glyphs(glyphs)
 53          self.large_font.load_glyphs(glyphs)
 54          self.large_font.load_glyphs(('°',))  # a non-ascii character we need for sure
 55          self.city_text = None
 56          self.holiday_text = None
 57  
 58          self.time_text = Label(self.medium_font)
 59          self.time_text.x = 365
 60          self.time_text.y = 15
 61          self.time_text.color = 0x5AF78E
 62          self._text_group.append(self.time_text)
 63  
 64          self.date_text = Label(self.medium_font)
 65          self.date_text.x = 10
 66          self.date_text.y = 15
 67          self.date_text.color = 0x57C6FE
 68          self._text_group.append(self.date_text)
 69  
 70          self.temp_text = Label(self.large_font)
 71          self.temp_text.x = 316
 72          self.temp_text.y = 165
 73          self.temp_text.color = 0xFF6AC1
 74          self._text_group.append(self.temp_text)
 75  
 76          self.main_text = Label(self.weather_font)
 77          self.main_text.x = 10
 78          self.main_text.y = 258
 79          self.main_text.color = 0x99ECFD
 80          self._text_group.append(self.main_text)
 81  
 82          self.description_text = Label(self.small_font)
 83          self.description_text.x = 10
 84          self.description_text.y = 296
 85          self.description_text.color = 0x9FA0A2
 86          self._text_group.append(self.description_text)
 87  
 88      def display_weather(self, weather):
 89          weather = json.loads(weather)
 90  
 91          # set the icon/background
 92          weather_icon = weather['weather'][0]['icon']
 93          self.set_icon("/sd/icons/"+weather_icon+".bmp")
 94  
 95          city_name =  weather['name'] + ", " + weather['sys']['country']
 96          print(city_name)
 97          if not self.city_text:
 98              self.city_text = Label(self.medium_font, text=city_name)
 99              self.city_text.x = 300
100              self.city_text.y = 296
101              self.city_text.color = 0xCF5349
102              self._text_group.append(self.city_text)
103  
104          self.update_time()
105  
106          main_text = weather['weather'][0]['main']
107          print(main_text)
108          self.main_text.text = main_text
109  
110          temperature = weather['main']['temp'] - 273.15 # its...in kelvin
111          print(temperature)
112          if self.celsius:
113              self.temp_text.text = "%d °C" % temperature
114          else:
115              self.temp_text.text = "%d °F" % ((temperature * 9 / 5) + 32)
116  
117          description = weather['weather'][0]['description']
118          description = description[0].upper() + description[1:]
119          print(description)
120          self.description_text.text = description
121          # "thunderstorm with heavy drizzle"
122  
123      def update_time(self):
124          """Fetch the time.localtime(), parse it out and update the display text"""
125          now = time.localtime()
126          hour = now[3]
127          minute = now[4]
128          format_str = "%d:%02d"
129          if self.am_pm:
130              if hour >= 12:
131                  hour -= 12
132                  format_str = format_str+" PM"
133              else:
134                  format_str = format_str+" AM"
135              if hour == 0:
136                  hour = 12
137          time_str = format_str % (hour, minute)
138          print(time_str)
139          self.time_text.text = time_str
140  
141      def update_date(self):
142          date_now = time.localtime()
143          year = date_now[0]
144          mon = date_now[1]
145          date = date_now[2]
146          day = date_now[6]
147          today = weekday[day]
148          month = month_name[mon - 1]
149          date_format_str = " %d, %d"
150          shortened_date_format_str = " %d"
151          date_str = today+", "+month+date_format_str % (date, year)
152          holiday_date_str = month+shortened_date_format_str % (date)
153          print(date_str)
154          self.date_text.text = date_str
155          for i in holiday_checks:
156              h = holiday_checks.index(i)
157              if holiday_date_str == holiday_checks[h]:
158                  if not self.holiday_text:
159                      self.holiday_text = Label(self.medium_font)
160                      self.holiday_text.x = 10
161                      self.holiday_text.y = 45
162                      self.holiday_text.color = 0xf2f89d
163                      self._text_group.append(self.holiday_text)
164                  self.holiday_text.text = holiday_greetings[h]
165  
166      def set_icon(self, filename):
167          """The background image to a bitmap file.
168  
169          :param filename: The filename of the chosen icon
170  
171          """
172          print("Set icon to ", filename)
173          if self._icon_group:
174              self._icon_group.pop()
175  
176          if not filename:
177              return  # we're done, no icon desired
178          if self._icon_file:
179              self._icon_file.close()
180  
181          # CircuitPython 6 & 7 compatible
182          self._icon_file = open(filename, "rb")
183          icon = displayio.OnDiskBitmap(self._icon_file)
184          self._icon_sprite = displayio.TileGrid(icon,
185                                                 pixel_shader=getattr(icon, 'pixel_shader', displayio.ColorConverter()))
186  
187          # # CircuitPython 7+ compatible
188          # icon = displayio.OnDiskBitmap(filename)
189          # self._icon_sprite = displayio.TileGrid(icon, pixel_shader=icon.pixel_shader)
190  
191          self._icon_group.append(self._icon_sprite)