Created
October 7, 2025 19:55
-
-
Save Staars/a617f8bc0dcf4487efe137e08fb646cd to your computer and use it in GitHub Desktop.
variant 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class WEATHER_DASHBOARD : Driver | |
| var weather_data | |
| var forecast_data | |
| var widget_rotation | |
| var last_update | |
| var widget_content # Global class var to hold widget string | |
| def init() | |
| self.weather_data = nil | |
| self.forecast_data = nil | |
| self.widget_rotation = 0 | |
| self.last_update = 0 | |
| self.widget_content = "" | |
| tasmota.add_driver(self) | |
| # Initial fetch | |
| self.fetch_weather() | |
| end | |
| def fetch_weather() | |
| import json | |
| var cl = webclient() | |
| var lat = tasmota.cmd("latitude")["Latitude"] | |
| var long = tasmota.cmd("longitude")["Longitude"] | |
| # Fetch current + hourly forecast for next 24h + daily for 7 days | |
| var url = format("https://api.open-meteo.com/v1/forecast?latitude=%s&longitude=%s¤t=temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,rain,weather_code,wind_speed_10m,wind_direction_10m&hourly=temperature_2m,precipitation_probability,precipitation&daily=temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max&timezone=auto", | |
| lat, long) | |
| cl.begin(url) | |
| cl.GET() | |
| var response = cl.get_string() | |
| if response | |
| self.weather_data = json.load(response) | |
| self.last_update = tasmota.rtc()['local'] | |
| print("Weather data fetched successfully") | |
| else | |
| print("Failed to fetch weather data") | |
| end | |
| end | |
| def every_second() | |
| # Fetch weather every 10 minutes | |
| var now = tasmota.rtc()['local'] | |
| if now - self.last_update > 600 | |
| self.fetch_weather() | |
| end | |
| end | |
| def every_250ms() | |
| if self.weather_data == nil return end | |
| self.update_widget() | |
| end | |
| def update_widget() | |
| import MI32 | |
| if MI32.widget() == false | |
| return | |
| end | |
| var current = self.weather_data['current'] | |
| var hourly = self.weather_data['hourly'] | |
| var daily = self.weather_data['daily'] | |
| # Rotate through 3 different widgets | |
| if self.widget_rotation == 0 | |
| # Widget 1: Current conditions + next 24h temperature | |
| self.show_current_and_temp_forecast(current, hourly) | |
| elif self.widget_rotation == 1 | |
| # Widget 2: Precipitation forecast (24h) | |
| self.show_precipitation_forecast(hourly) | |
| else | |
| # Widget 3: 7-day forecast | |
| self.show_weekly_forecast(daily) | |
| end | |
| self.widget_rotation = (self.widget_rotation + 1) % 3 | |
| end | |
| def show_current_and_temp_forecast(current, hourly) | |
| import MI32 | |
| var temp = current['temperature_2m'] | |
| var humidity = current['relative_humidity_2m'] | |
| var feels_like = current['apparent_temperature'] | |
| var wind = current['wind_speed_10m'] | |
| var weather_icon = self.get_weather_icon(current['weather_code']) | |
| # Extract next 24 hours of temperature (shift to positive range: add 50 to handle negative temps) | |
| var temp_values = [] | |
| for i: 0..23 | |
| var t = hourly['temperature_2m'][i] | |
| temp_values.push(str(int(t + 50))) # Shift to positive | |
| end | |
| var temp_csv = temp_values.concat(",") | |
| var graph = format('{l,560,120,(250,50,50):%s}', temp_csv) | |
| self.widget_content = format('<div class="box w2 h2" id="weather_now"><p><strong>%s Weather</strong></p><div style="font-size:48px;margin:10px 0;">%.1f°C</div><div>Feels like: %.1f°C | Humidity: %d%% | Wind: %.1f km/h</div><div style="margin-top:10px;"></div><div>%s</div><br><small>24h Temperature</small></div>', | |
| weather_icon, temp, feels_like, humidity, wind, graph) | |
| MI32.widget(self.widget_content) | |
| end | |
| def show_precipitation_forecast(hourly) | |
| import MI32 | |
| # Precipitation probability for next 24 hours | |
| var precip_prob = [] | |
| var precip_amount = [] | |
| for i: 0..23 | |
| var prob = hourly['precipitation_probability'][i] | |
| var amount = hourly['precipitation'][i] | |
| precip_prob.push(str(int(prob * 2.55))) # 0-100% to 0-255 | |
| precip_amount.push(str(int(amount * 25.5))) # 0-10mm to 0-255 | |
| end | |
| var prob_csv = precip_prob.concat(",") | |
| var amount_csv = precip_amount.concat(",") | |
| var graph = format('{h,660,180,(100,150,255):%s|(50,200,255):%s}', prob_csv, amount_csv) | |
| self.widget_content = format('<div class="box w2 h1" id="weather_precip"><p><strong>☔ Precipitation Forecast (24h)</strong></p><div style="margin:10px 0;"><div style="color:#6496ff;">■ Probability (scaled)</div><div style="color:#32c8ff;">■ Amount (scaled)</div></div><div>%s</div></div>', | |
| graph) | |
| MI32.widget(self.widget_content) | |
| end | |
| def show_weekly_forecast(daily) | |
| import MI32 | |
| # 7-day min/max temps (shift to positive) | |
| var temp_max = [] | |
| var temp_min = [] | |
| var precip = [] | |
| for i: 0..6 | |
| temp_max.push(str(int(daily['temperature_2m_max'][i] + 50))) | |
| temp_min.push(str(int(daily['temperature_2m_min'][i] + 50))) | |
| var p = daily['precipitation_sum'][i] | |
| precip.push(str(int(p * 10))) # Scale precipitation | |
| end | |
| var max_csv = temp_max.concat(",") | |
| var min_csv = temp_min.concat(",") | |
| var precip_csv = precip.concat(",") | |
| var graph = format('{l,660,180,(255,100,100):%s|(100,150,255):%s|(50,200,255):%s}', | |
| max_csv, min_csv, precip_csv) | |
| self.widget_content = format('<div class="box w2 h1" id="weather_week"><p><strong>📅 7-Day Forecast</strong></p><div style="margin:10px 0;"><div style="color:#ff6464;">■ Max Temp </div><div style="color:#6496ff;">■ Min Temp</div><div style="color:#32c8ff;">■ Precipitation (scaled)</div></div><div>%s</div></div>', | |
| graph) | |
| MI32.widget(self.widget_content) | |
| end | |
| def get_weather_icon(code) | |
| # WMO Weather codes | |
| if code == 0 return "☀️" end | |
| if code >= 1 && code <= 3 return "⛅" end | |
| if code >= 45 && code <= 48 return "🌫️" end | |
| if code >= 51 && code <= 67 return "🌧️" end | |
| if code >= 71 && code <= 77 return "❄️" end | |
| if code >= 80 && code <= 82 return "🌦️" end | |
| if code >= 85 && code <= 86 return "🌨️" end | |
| if code >= 95 && code <= 99 return "⛈️" end | |
| return "🌡️" | |
| end | |
| end | |
| var weather_dash = WEATHER_DASHBOARD() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment