feat: show daily forecast

Each day is also including hourly forecast, but this PR lays the
groundwork by talking to the right endpoint.

Instead of day and night values (like in the old weather-widget) I'm
showing min and max temperature as forecasted here.

Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
This commit is contained in:
André Jaenisch 2024-09-27 19:20:37 +02:00
parent 68ddbd9812
commit 27727f0ccc
No known key found for this signature in database
GPG Key ID: 5A668E771F1ED854
2 changed files with 73 additions and 3 deletions

View File

@ -18,6 +18,7 @@ following config parameters:
| units | `metric` | `metric` for celsius, `imperial` for fahrenheit | | units | `metric` | `metric` for celsius, `imperial` for fahrenheit |
| icon_pack_name | `weather-underground-icons` | Name of the icon pack, could be `weather-underground-icon` or `VitalyGorbachev` or create your own, more details below | | icon_pack_name | `weather-underground-icons` | Name of the icon pack, could be `weather-underground-icon` or `VitalyGorbachev` or create your own, more details below |
| icons_extension | `.png` | File extension of icons in the pack | | icons_extension | `.png` | File extension of icons in the pack |
| show_forecast | false | Show forecast for next three days |
| timeout | 120 | How often in seconds the widget refreshes | | timeout | 120 | How often in seconds the widget refreshes |
### Icons: ### Icons:

View File

@ -174,13 +174,16 @@ local function worker(user_args)
local both_units_widget = args.both_units_widget or false local both_units_widget = args.both_units_widget or false
local icon_pack_name = args.icons or 'weather-underground-icons' local icon_pack_name = args.icons or 'weather-underground-icons'
local icons_extension = args.icons_extension or '.png' local icons_extension = args.icons_extension or '.png'
local show_forecast = args.show_forecast or false
local timeout = args.timeout or 120 local timeout = args.timeout or 120
local ICONS_DIR = WIDGET_DIR .. '/icons/' .. icon_pack_name .. '/' local ICONS_DIR = WIDGET_DIR .. '/icons/' .. icon_pack_name .. '/'
local weather_api = -- Forecast endpoint includes current. I could map show_forecast to days here.
('https://api.weatherapi.com/v1/current.json' .. -- Currently overfetching but only showing when opting in.
local weather_api =
('https://api.weatherapi.com/v1/forecast.json' ..
'?q=' .. coordinates[1] .. ',' .. coordinates[2] .. '&key=' .. api_key .. '?q=' .. coordinates[1] .. ',' .. coordinates[2] .. '&key=' .. api_key ..
'&units=' .. units .. '&lang=' .. LANG) '&units=' .. units .. '&lang=' .. LANG .. '&days=3')
weather_widget = wibox.widget { weather_widget = wibox.widget {
{ {
@ -301,6 +304,66 @@ local function worker(user_args)
end end
} }
local forecast_widget = {
forced_width = 300,
layout = wibox.layout.flex.horizontal,
update = function(self, forecast)
local count = #self
for i = 0, count do self[i] = nil end
for i, day in ipairs(forecast) do
-- Free plan allows forecast for up to three days, each with hours
if i > 3 then break end
local day_forecast = wibox.widget {
{
text = os.date('%a', tonumber(day.date_epoch)),
align = 'center',
font = font_name .. ' 9',
widget = wibox.widget.textbox
},
{
{
{
image = ICONS_DIR .. icon_map[day.day.condition.code] .. icons_extension,
resize = true,
forced_width = 48,
forced_height = 48,
widget = wibox.widget.imagebox
},
align = 'center',
layout = wibox.container.place
},
{
text = day.day.condition.text,
font = font_name .. ' 8',
align = 'center',
forced_height = 50,
widget = wibox.widget.textbox
},
layout = wibox.layout.fixed.vertical
},
{
{
text = gen_temperature_str(day.day.mintemp_c, '%.0f', false, units),
align = 'center',
font = font_name .. ' 9',
widget = wibox.widget.textbox
},
{
text = gen_temperature_str(day.day.maxtemp_c, '%.0f', false, units),
align = 'center',
font = font_name .. ' 9',
widget = wibox.widget.textbox
},
layout = wibox.layout.fixed.vertical
},
spacing = 8,
layout = wibox.layout.fixed.vertical
}
table.insert(self, day_forecast)
end
end
}
local function update_widget(widget, stdout, stderr) local function update_widget(widget, stdout, stderr)
if stderr ~= '' then if stderr ~= '' then
if not warning_shown then if not warning_shown then
@ -347,6 +410,12 @@ local function worker(user_args)
layout = wibox.layout.fixed.vertical layout = wibox.layout.fixed.vertical
} }
if show_forecast then
forecast_widget:update(result.forecast.forecastday)
table.insert(final_widget, forecast_widget)
end
weather_popup:setup({ weather_popup:setup({
{ {
final_widget, final_widget,