Skip to content

Instantly share code, notes, and snippets.

@Staars
Created October 7, 2025 19:55
Show Gist options
  • Select an option

  • Save Staars/a617f8bc0dcf4487efe137e08fb646cd to your computer and use it in GitHub Desktop.

Select an option

Save Staars/a617f8bc0dcf4487efe137e08fb646cd to your computer and use it in GitHub Desktop.
variant 1
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&current=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