228 lines
8.9 KiB
Python
228 lines
8.9 KiB
Python
import time
|
|
|
|
|
|
class WeatherDisplay:
|
|
def __init__(self, display):
|
|
self.display = display
|
|
self.text_padding = 4
|
|
self.last_displayed_data = None
|
|
self.time_update_running = False
|
|
self.time_thread = None
|
|
|
|
def weathercode_to_text(self, weathercode):
|
|
if weathercode == 0:
|
|
return 'Clear Sky'
|
|
elif weathercode == 1:
|
|
return 'Mainly Clear'
|
|
elif weathercode == 2:
|
|
return 'Partly Cloudy'
|
|
elif weathercode == 3:
|
|
return 'Overcast'
|
|
elif weathercode in [45, 48]:
|
|
return 'Foggy'
|
|
elif weathercode in [51, 53, 55]:
|
|
return 'Light Rain'
|
|
elif weathercode in [56, 57]:
|
|
return 'Freezing Rain'
|
|
elif weathercode in [61, 63, 65]:
|
|
return 'Moderate Rain'
|
|
elif weathercode in [66, 67]:
|
|
return 'Heavy Rain'
|
|
elif weathercode in [71, 73, 75]:
|
|
return 'Snow Fall'
|
|
elif weathercode == 77:
|
|
return 'Snow Grains'
|
|
elif weathercode in [80, 81, 82]:
|
|
return 'Rain Showers'
|
|
elif weathercode in [85, 86]:
|
|
return 'Snow Showers'
|
|
elif weathercode == 95:
|
|
return 'Thunderstorm'
|
|
elif weathercode in [96, 99]:
|
|
return 'Thunderstorm with Hail'
|
|
else:
|
|
return 'Unknown Weather'
|
|
|
|
|
|
if force_full_update:
|
|
self.display.clear()
|
|
else:
|
|
# Create a clean buffer but don't send to display yet
|
|
self.display.fill(self.display.black)
|
|
|
|
text_x = self.text_padding
|
|
text_y = 8
|
|
|
|
update_regions = []
|
|
|
|
temp_text = f"Temp: {weather_data.get('max_temp', 0):.0f}/{weather_data.get('min_temp', 0):.0f}C"
|
|
if force_full_update or not self.last_displayed_data or \
|
|
self.last_displayed_data.get('max_temp') != weather_data.get('max_temp') or \
|
|
self.last_displayed_data.get('miget_wen_temp') != weather_data.get('min_temp'):
|
|
self.display.text(temp_text, text_x, text_y)
|
|
update_regions.append((0, text_y, 16, text_y + 8))
|
|
|
|
weathercode = weather_data.get('weathercode', 0)
|
|
weather_text = self.weathercode_to_text(weathercode)
|
|
if force_full_update or not self.last_displayed_data or \
|
|
self.last_displayed_data.get('weathercode') != weathercode:
|
|
self.display.text(f"{weather_text}", text_x, text_y + 12)
|
|
update_regions.append((0, text_y + 12, 16, text_y + 20))
|
|
|
|
precip_text = f"Precip: {weather_data.get('precip_mm', 0):.1f}mm"
|
|
if force_full_update or not self.last_displayed_data or \
|
|
self.last_displayed_data.get('precip_mm') != weather_data.get('precip_mm'):
|
|
self.display.text(precip_text, text_x, text_y + 24)
|
|
update_regions.append((0, text_y + 24, 16, text_y + 32))
|
|
|
|
date_text = weather_data.get('date', '')
|
|
if date_text and len(date_text) >= 10:
|
|
year = date_text[0:4]
|
|
month = date_text[5:7]
|
|
day = date_text[8:10]
|
|
date_text = f"{day}-{month}-{year}"
|
|
if force_full_update or not self.last_displayed_data or \
|
|
self.last_displayed_data.get('date') != weather_data.get('date'):
|
|
self.display.text(f"Date: {date_text}", text_x, text_y + 36)
|
|
update_regions.append((0, text_y + 36, 16, text_y + 44))
|
|
|
|
self.last_displayed_data = dict(weather_data)
|
|
self.last_displayed_data['view_type'] = 'detailed'
|
|
|
|
if force_full_update:
|
|
self.display.show()
|
|
else:
|
|
if update_regions:
|
|
min_y = min(region[1] for region in update_regions)
|
|
max_y = max(region[3] for region in update_regions)
|
|
self.display.show(0, min_y, 16, max_y)
|
|
else:
|
|
pass
|
|
|
|
|
|
def display_weather(self, weather_data):
|
|
"""Detailed view with max/min temps, description, precip, date."""
|
|
if 'daily' in weather_data:
|
|
d = weather_data['daily']
|
|
weather_data = {
|
|
'max_temp': d['temperature_2m_max'][0],
|
|
'min_temp': d['temperature_2m_min'][0],
|
|
'weathercode':d['weathercode'][0],
|
|
'precip_mm': d['precipitation_sum'][0],
|
|
'date': d['time'][0],
|
|
}
|
|
|
|
force_full_update = (
|
|
self.last_displayed_data is None or
|
|
self.last_displayed_data.get('view_type') != 'detailed'
|
|
)
|
|
|
|
if force_full_update:
|
|
self.display.clear()
|
|
else:
|
|
self.display.fill(self.display.black)
|
|
|
|
text_x = self.text_padding
|
|
text_y = 8
|
|
update_regions = []
|
|
|
|
temp_text = f"Temp: {weather_data.get('max_temp', 0):.0f}/" \
|
|
f"{weather_data.get('min_temp', 0):.0f}C"
|
|
if (force_full_update
|
|
or self.last_displayed_data.get('max_temp') != weather_data.get('max_temp')
|
|
or self.last_displayed_data.get('min_temp') != weather_data.get('min_temp')
|
|
):
|
|
self.display.text(temp_text, text_x, text_y)
|
|
update_regions.append((text_y, text_y + 8))
|
|
|
|
code = weather_data.get('weathercode', 0)
|
|
desc = self.weathercode_to_text(code)
|
|
if (force_full_update
|
|
or self.last_displayed_data.get('weathercode') != code
|
|
):
|
|
self.display.text(desc, text_x, text_y + 12)
|
|
update_regions.append((text_y + 12, text_y + 20))
|
|
|
|
precip = f"Precip: {weather_data.get('precip_mm', 0):.1f}mm"
|
|
if (force_full_update
|
|
or self.last_displayed_data.get('precip_mm') != weather_data.get('precip_mm')
|
|
):
|
|
self.display.text(precip, text_x, text_y + 24)
|
|
update_regions.append((text_y + 24, text_y + 32))
|
|
|
|
raw_date = weather_data.get('date', '')
|
|
if raw_date and len(raw_date) >= 10:
|
|
dd = raw_date[8:10]; mm = raw_date[5:7]; yyyy = raw_date[0:4]
|
|
formatted = f"Date: {dd}-{mm}-{yyyy}"
|
|
if (force_full_update
|
|
or self.last_displayed_data.get('date') != raw_date
|
|
):
|
|
self.display.text(formatted, text_x, text_y + 36)
|
|
update_regions.append((text_y + 36, text_y + 44))
|
|
|
|
self.last_displayed_data = dict(weather_data)
|
|
self.last_displayed_data['view_type'] = 'detailed'
|
|
|
|
if force_full_update:
|
|
self.display.show()
|
|
return
|
|
|
|
if update_regions:
|
|
min_y = min(r[0] for r in update_regions)
|
|
max_y = max(r[1] for r in update_regions)
|
|
page_count = self.display.height // 8
|
|
self.display.show(1, min_y, page_count, max_y)
|
|
|
|
|
|
|
|
def display_simple_weather(self, weather_data):
|
|
force_full_update = self.last_displayed_data is None or self.last_displayed_data.get('view_type') != 'simple'
|
|
|
|
if force_full_update:
|
|
self.display.clear()
|
|
else:
|
|
self.display.fill(self.display.black)
|
|
|
|
text_x = self.text_padding
|
|
center_y = self.display.height // 2
|
|
|
|
update_regions = []
|
|
|
|
temp_text = f"{weather_data.get('current_temp', 0):.0f}C"
|
|
if force_full_update or not self.last_displayed_data or \
|
|
self.last_displayed_data.get('current_temp') != weather_data.get('current_temp'):
|
|
self.display.text(temp_text, text_x, center_y - 8, scale=2)
|
|
update_regions.append((0, center_y - 8, 16, center_y + 8)) # Scaled text is 16px high
|
|
|
|
weather_desc = self.weathercode_to_text(weather_data.get('weathercode', 0))
|
|
if force_full_update or not self.last_displayed_data or \
|
|
self.last_displayed_data.get('weathercode') != weather_data.get('weathercode'):
|
|
self.display.text(weather_desc, text_x, center_y + 12)
|
|
update_regions.append((0, center_y + 12, 16, center_y + 20))
|
|
|
|
|
|
current_time_tuple = time.localtime(time.time())
|
|
current_time = f"{current_time_tuple[3]:02d}:{current_time_tuple[4]:02d}:{current_time_tuple[5]:02d}"
|
|
if current_time and (force_full_update or not self.last_displayed_data or \
|
|
self.last_displayed_data.get('current_time') != current_time):
|
|
self.display.text(current_time, text_x, center_y + 24)
|
|
update_regions.append((0, center_y + 24, 16, center_y + 32))
|
|
|
|
self.last_displayed_data = dict(weather_data)
|
|
self.last_displayed_data['view_type'] = 'simple'
|
|
|
|
if force_full_update:
|
|
self.display.show()
|
|
else:
|
|
if update_regions:
|
|
min_y = min(region[1] for region in update_regions)
|
|
max_y = max(region[3] for region in update_regions)
|
|
self.display.show(0, min_y, 16, max_y)
|
|
else:
|
|
pass
|
|
|
|
def reset_display(self):
|
|
"""Clear display and reset last displayed data."""
|
|
self.display.clear()
|
|
self.display.show()
|
|
self.last_displayed_data = None |