feat: show hourly forecast
This took me quite some trial and error to figure out. Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
This commit is contained in:
parent
4d05c96f65
commit
9604aef6ba
|
@ -18,7 +18,8 @@ following config parameters:
|
|||
| 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 |
|
||||
| icons_extension | `.png` | File extension of icons in the pack |
|
||||
| show_forecast | false | Show forecast for next three days |
|
||||
| show_daily_forecast | false | Show forecast for next three days |
|
||||
| show_hourly_forecast | false | Show hourly forecast section |
|
||||
| timeout | 120 | How often in seconds the widget refreshes |
|
||||
|
||||
### Icons:
|
||||
|
|
|
@ -171,14 +171,16 @@ local function worker(user_args)
|
|||
local api_key = args.api_key
|
||||
local font_name = args.font_name or beautiful.font:gsub("%s%d+$", "")
|
||||
local units = args.units or 'metric'
|
||||
local time_format_12h = args.time_format_12h
|
||||
local both_units_widget = args.both_units_widget or false
|
||||
local icon_pack_name = args.icons or 'weather-underground-icons'
|
||||
local icons_extension = args.icons_extension or '.png'
|
||||
local show_forecast = args.show_forecast or false
|
||||
local show_daily_forecast = args.show_daily_forecast or false
|
||||
local show_hourly_forecast = args.show_hourly_forecast or false
|
||||
local timeout = args.timeout or 120
|
||||
|
||||
local ICONS_DIR = WIDGET_DIR .. '/icons/' .. icon_pack_name .. '/'
|
||||
-- Forecast endpoint includes current. I could map show_forecast to days here.
|
||||
-- Forecast endpoint includes current. I could map show_daily_forecast to days here.
|
||||
-- Currently overfetching but only showing when opting in.
|
||||
local weather_api =
|
||||
('https://api.weatherapi.com/v1/forecast.json' ..
|
||||
|
@ -304,7 +306,7 @@ local function worker(user_args)
|
|||
end
|
||||
}
|
||||
|
||||
local forecast_widget = {
|
||||
local daily_forecast_widget = {
|
||||
forced_width = 300,
|
||||
layout = wibox.layout.flex.horizontal,
|
||||
update = function(self, forecast)
|
||||
|
@ -364,6 +366,181 @@ local function worker(user_args)
|
|||
end
|
||||
}
|
||||
|
||||
local hourly_forecast_graph = wibox.widget {
|
||||
step_width = 12,
|
||||
color = '#EBCB8B',
|
||||
background_color = beautiful.bg_normal,
|
||||
forced_height = 100,
|
||||
forced_width = 300,
|
||||
widget = wibox.widget.graph,
|
||||
set_max_value = function(self, new_max_value)
|
||||
self.max_value = new_max_value
|
||||
end,
|
||||
set_min_value = function(self, new_min_value)
|
||||
self.min_value = new_min_value
|
||||
end,
|
||||
}
|
||||
|
||||
local hourly_forecast_negative_graph = wibox.widget {
|
||||
step_width = 12,
|
||||
color = '#5E81AC',
|
||||
background_color = beautiful.bg_normal,
|
||||
forced_height = 100,
|
||||
forced_width = 300,
|
||||
widget = wibox.widget.graph,
|
||||
set_max_value = function(self, new_max_value)
|
||||
self.max_value = new_max_value
|
||||
end,
|
||||
set_min_value = function(self, new_min_value)
|
||||
self.min_value = new_min_value
|
||||
end,
|
||||
}
|
||||
|
||||
local hourly_forecast_widget = {
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
update = function(self, hourly)
|
||||
local hours_below = {
|
||||
id = 'hours',
|
||||
forced_width = 300,
|
||||
layout = wibox.layout.flex.horizontal
|
||||
}
|
||||
local temp_below = {
|
||||
id = 'temp',
|
||||
forced_width = 300,
|
||||
layout = wibox.layout.flex.horizontal
|
||||
}
|
||||
|
||||
local max_temp = -1000
|
||||
local min_temp = 1000
|
||||
local values= {}
|
||||
|
||||
-- Yeah, this looks weird. I would expect to have to use ipairs
|
||||
for i, hour in pairs(hourly) do
|
||||
if i > 25 then
|
||||
break
|
||||
end
|
||||
|
||||
values[i] = hour.temp_c
|
||||
|
||||
if max_temp < hour.temp_c then
|
||||
max_temp = hour.temp_c
|
||||
end
|
||||
|
||||
if min_temp > hour.temp_c then
|
||||
min_temp = hour.temp_c
|
||||
end
|
||||
|
||||
if (i - 1) % 5 == 0 then
|
||||
table.insert(hours_below, wibox.widget {
|
||||
text = os.date(time_format_12h and '%I%p' or '%H:00', tonumber(hour.time_epoch)),
|
||||
align = 'center',
|
||||
font = font_name .. ' 9',
|
||||
widget = wibox.widget.textbox
|
||||
})
|
||||
|
||||
table.insert(temp_below, wibox.widget {
|
||||
markup = '<span foreground=""'
|
||||
.. (tonumber(hour.temp_c) > 0 and '#2E3440' or '#ECEFF4') .. '">'
|
||||
.. string.format('%.0f', hour.temp_c) .. '°' .. '</span>',
|
||||
align = 'center',
|
||||
font = font_name .. ' 9',
|
||||
widget = wibox.widget.textbox
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
hourly_forecast_graph:set_max_value(math.max(max_temp, math.abs(min_temp)))
|
||||
hourly_forecast_graph:set_min_value(min_temp > 0 and min_temp * 0.7 or 0) -- move graph a bit up
|
||||
|
||||
hourly_forecast_negative_graph:set_max_value(math.abs(min_temp))
|
||||
hourly_forecast_negative_graph:set_min_value(max_temp < 0 and math.abs(max_temp) * 0.7 or 0)
|
||||
|
||||
for _, value in ipairs(values) do
|
||||
if value >= 0 then
|
||||
hourly_forecast_graph:add_value(value)
|
||||
hourly_forecast_negative_graph:add_value(0)
|
||||
else
|
||||
hourly_forecast_graph:add_value(0)
|
||||
hourly_forecast_negative_graph:add_value(math.abs(value))
|
||||
end
|
||||
end
|
||||
|
||||
local count = #self
|
||||
for i = 0, count do
|
||||
self[i] = nil
|
||||
end
|
||||
|
||||
-- all temperatures are positive
|
||||
if min_temp > 0 then
|
||||
table.insert(self, wibox.widget {
|
||||
{
|
||||
hourly_forecast_graph,
|
||||
reflection = { horizontal = true },
|
||||
widget = wibox.container.mirror
|
||||
},
|
||||
{
|
||||
temp_below,
|
||||
valign = 'bottom',
|
||||
widget = wibox.container.place
|
||||
},
|
||||
id = 'graph',
|
||||
layout = wibox.layout.stack
|
||||
})
|
||||
table.insert(self, hours_below)
|
||||
|
||||
-- all temperatures are negative
|
||||
elseif max_temp < 0 then
|
||||
table.insert(self, hours_below)
|
||||
table.insert(self, wibox.widget {
|
||||
{
|
||||
hourly_forecast_negative_graph,
|
||||
reflection = { horizontal = true, vertical = true },
|
||||
widget = wibox.container.mirror
|
||||
},
|
||||
{
|
||||
temp_below,
|
||||
valign = 'top',
|
||||
widget = wibox.container.place
|
||||
},
|
||||
id = 'graph',
|
||||
layout = wibox.layout.stack
|
||||
})
|
||||
|
||||
-- mixed temperatures
|
||||
else
|
||||
table.insert(self, wibox.widget {
|
||||
{
|
||||
hourly_forecast_graph,
|
||||
reflection = { horizontal = true },
|
||||
widget = wibox.container.mirror
|
||||
},
|
||||
{
|
||||
temp_below,
|
||||
valign = 'bottom',
|
||||
widget = wibox.container.place
|
||||
},
|
||||
id = 'graph',
|
||||
layout = wibox.layout.stack
|
||||
})
|
||||
|
||||
table.insert(self, wibox.widget {
|
||||
{
|
||||
hourly_forecast_negative_graph,
|
||||
reflection = { horizontal = true, vertical = true },
|
||||
widget = wibox.container.mirror
|
||||
},
|
||||
{
|
||||
temp_below,
|
||||
valign = 'top',
|
||||
widget = wibox.container.place
|
||||
},
|
||||
id = 'graph',
|
||||
layout = wibox.layout.stack
|
||||
})
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
local function update_widget(widget, stdout, stderr)
|
||||
if stderr ~= '' then
|
||||
if not warning_shown then
|
||||
|
@ -411,9 +588,14 @@ local function worker(user_args)
|
|||
}
|
||||
|
||||
|
||||
if show_forecast then
|
||||
forecast_widget:update(result.forecast.forecastday)
|
||||
table.insert(final_widget, forecast_widget)
|
||||
if show_hourly_forecast then
|
||||
hourly_forecast_widget:update(result.forecast.forecastday[1].hour)
|
||||
table.insert(final_widget, hourly_forecast_widget)
|
||||
end
|
||||
|
||||
if show_daily_forecast then
|
||||
daily_forecast_widget:update(result.forecast.forecastday)
|
||||
table.insert(final_widget, daily_forecast_widget)
|
||||
end
|
||||
|
||||
weather_popup:setup({
|
||||
|
|
Loading…
Reference in New Issue