dotfiles/awes2/widget/weather/init.lua

370 lines
8.9 KiB
Lua

local awful = require('awful')
local beautiful = require('beautiful')
local naughty = require('naughty')
local wibox = require('wibox')
local gears = require('gears')
local dpi = beautiful.xresources.apply_dpi
local config_dir = gears.filesystem.get_configuration_dir()
local widget_icon_dir = config_dir .. 'widget/weather/icons/'
local clickable_container = require('widget.clickable-container')
local secrets = require('configuration.secrets')
local key = secrets.weather.key
local city_id = secrets.weather.city_id
local units = secrets.weather.units
local update_interval = 1200
local weather_icon_widget = wibox.widget {
{
id = 'icon',
image = widget_icon_dir .. 'weather-error.svg',
resize = true,
forced_height = dpi(45),
forced_width = dpi(45),
widget = wibox.widget.imagebox,
},
layout = wibox.layout.fixed.horizontal
}
local sunrise_icon_widget = wibox.widget {
{
id = 'sunrise_icon',
image = widget_icon_dir .. 'sunrise.svg',
resize = true,
forced_height = dpi(18),
forced_width = dpi(18),
widget = wibox.widget.imagebox,
},
layout = wibox.layout.fixed.horizontal
}
local sunset_icon_widget = wibox.widget {
{
id = 'sunset_icon',
image = widget_icon_dir .. 'sunset.svg',
resize = true,
forced_height = dpi(18),
forced_width = dpi(18),
widget = wibox.widget.imagebox,
},
layout = wibox.layout.fixed.horizontal
}
local refresh_icon_widget = wibox.widget {
{
id = 'refresh_icon',
image = widget_icon_dir .. 'refresh.svg',
resize = true,
forced_height = dpi(18),
forced_width = dpi(18),
widget = wibox.widget.imagebox,
},
layout = wibox.layout.fixed.horizontal
}
local refresh_button = clickable_container(refresh_icon_widget)
refresh_button:buttons(
gears.table.join(
awful.button(
{},
1,
nil,
function()
awesome.emit_signal('widget::weather_fetch')
end
)
)
)
local refresh_widget = wibox.widget {
refresh_button,
bg = beautiful.transparent,
shape = gears.shape.circle,
widget = wibox.container.background
}
local weather_desc_temp = wibox.widget {
{
id = 'description',
markup = 'dust and clouds, -1000°C',
font = 'SF Pro Text Bold 12',
align = 'left',
valign = 'center',
widget = wibox.widget.textbox
},
id = 'scroll_container',
max_size = 345,
speed = 75,
expand = true,
direction = 'h',
step_function = wibox.container.scroll
.step_functions.waiting_nonlinear_back_and_forth,
fps = 30,
layout = wibox.container.scroll.horizontal,
}
local weather_location = wibox.widget {
{
id = 'location',
markup = 'Earth, Milky Way',
font = 'SF Pro Text Regular 12',
align = 'left',
valign = 'center',
widget = wibox.widget.textbox
},
id = 'scroll_container',
max_size = 345,
speed = 75,
expand = true,
direction = 'h',
step_function = wibox.container.scroll
.step_functions.waiting_nonlinear_back_and_forth,
fps = 30,
layout = wibox.container.scroll.horizontal,
}
local weather_sunrise = wibox.widget {
markup = "00:00",
font = 'SF Pro Text Regular 10',
align = 'center',
valign = 'center',
widget = wibox.widget.textbox
}
local weather_sunset = wibox.widget {
markup = "00:00",
font = 'SF Pro Text Regular 10',
align = 'center',
valign = 'center',
widget = wibox.widget.textbox
}
local weather_data_time = wibox.widget {
markup = "00:00",
font = 'SF Pro Text Regular 10',
align = 'center',
valign = 'center',
widget = wibox.widget.textbox
}
local weather_report = wibox.widget {
{
{
layout = wibox.layout.fixed.horizontal,
spacing = dpi(10),
{
layout = wibox.layout.align.vertical,
expand = 'none',
nil,
weather_icon_widget,
nil
},
{
layout = wibox.layout.align.vertical,
expand = 'none',
nil,
{
layout = wibox.layout.fixed.vertical,
spacing = dpi(3),
weather_location,
weather_desc_temp,
{
layout = wibox.layout.fixed.horizontal,
spacing = dpi(7),
{
layout = wibox.layout.fixed.horizontal,
spacing = dpi(3),
sunrise_icon_widget,
weather_sunrise
},
{
layout = wibox.layout.fixed.horizontal,
spacing = dpi(3),
sunset_icon_widget,
weather_sunset
},
{
layout = wibox.layout.fixed.horizontal,
spacing = dpi(3),
refresh_widget,
weather_data_time
}
}
},
nil
}
},
margins = dpi(10),
widget = wibox.container.margin
},
forced_height = dpi(92),
bg = beautiful.groups_bg,
shape = function(cr, width, height)
gears.shape.partially_rounded_rect(cr, width, height, true, true, true, true, beautiful.groups_radius)
end,
widget = wibox.container.background
}
if units == "metric" then
weather_temperature_symbol = "°C"
elseif units == "imperial" then
weather_temperature_symbol = "°F"
end
-- Weather script using your API KEY
local weather_details_script = [[
KEY="]]..key..[["
CITY="]]..city_id..[["
UNITS="]]..units..[["
weather=$(curl -sf "http://api.openweathermap.org/data/2.5/weather?APPID="${KEY}"&id="${CITY}"&units="${UNITS}"")
if [ ! -z "$weather" ]; then
weather_icon="icon=$(printf "$weather" | jq -r ".weather[].icon" | head -1)"
weather_location="location=$(printf "$weather" | jq -r ".name")"
weather_country="country=$(printf "$weather" | jq -r ".sys.country")"
weather_sunrise="sunrise=$(printf "$weather" | jq -r ".sys.sunrise" | xargs -0 -L1 -I '$' echo '@$' | xargs date +"%H:%M" -d)"
weather_sunset="sunset=$(printf "$weather" | jq -r ".sys.sunset" | xargs -0 -L1 -I '$' echo '@$' | xargs date +"%H:%M" -d)"
weather_data_time="update=$(printf "$weather" | jq -r ".dt" | xargs -0 -L1 -I '$' echo '@$' | xargs date +"%H:%M" -d)"
weather_temp="temperature=$(printf "$weather" | jq ".main.temp" | cut -d "." -f 1)"
weather_description="details=$(printf "$weather" | jq -r ".weather[].description" | head -1)"
DATA="${weather_icon}\n${weather_location}\n${weather_country}\n${weather_sunrise}\n${weather_sunset}\n${weather_data_time}\n${weather_temp}\n${weather_description}\n"
printf "${DATA}"
else
printf "icon=..."
fi
]]
awesome.connect_signal(
'widget::weather_fetch',
function()
awful.spawn.easy_async_with_shell(
weather_details_script,
function(stdout)
local weather_data_tbl = {}
for data in stdout:gmatch("[^\n]+") do
local key = data:match("(.*)=")
local value = data:match("=(.*)")
weather_data_tbl[key] = value
end
local icon_code = weather_data_tbl['icon']
if icon_code == '...' then
awesome.emit_signal("widget::weather_update",
icon_code,
'dust and clouds, -1000°C',
'Earth, Milky Way',
'00:00',
'00:00',
'00:00'
)
else
local location = weather_data_tbl['location']
local country = weather_data_tbl['country']
local sunrise = weather_data_tbl['sunrise']
local sunset = weather_data_tbl['sunset']
local update_time = weather_data_tbl['update']
local temperature = weather_data_tbl['temperature']
local details = weather_data_tbl['details']
local description = details:sub(1, 1):upper() .. details:sub(2)
local weather_description = description .. ', ' .. temperature .. weather_temperature_symbol
local weather_location = location .. ', ' .. country
awesome.emit_signal("widget::weather_update",
icon_code,
weather_description,
weather_location,
sunrise,
sunset,
update_time
)
end
collectgarbage('collect')
end
)
end)
local update_widget_timer = gears.timer {
timeout = update_interval,
autostart = true,
call_now = true,
single_shot = false,
callback = function()
awesome.emit_signal('widget::weather_fetch')
end
}
awesome.connect_signal(
'system::wifi_connected',
function()
gears.timer.start_new(
5,
function()
awesome.emit_signal('widget::weather_fetch')
end
)
end
)
awesome.connect_signal(
"widget::weather_update",
function(code, desc, location, sunrise, sunset, data_receive)
local widget_icon_name = 'weather-error'
local icon_tbl = {
['01d'] = 'sun_icon.svg',
['01n'] = 'moon_icon.svg',
['02d'] = 'dfew_clouds.svg',
['02n'] = 'nfew_clouds.svg',
['03d'] = 'dscattered_clouds.svg',
['03n'] = 'nscattered_clouds.svg',
['04d'] = 'dbroken_clouds.svg',
['04n'] = 'nbroken_clouds.svg',
['09d'] = 'dshower_rain.svg',
['09n'] = 'nshower_rain.svg',
['10d'] = 'd_rain.svg',
['10n'] = 'n_rain.svg',
['11d'] = 'dthunderstorm.svg',
['11n'] = 'nthunderstorm.svg',
['13d'] = 'snow.svg',
['13n'] = 'snow.svg',
['50d'] = 'dmist.svg',
['50n'] = 'nmist.svg',
['...'] = 'weather-error.svg'
}
widget_icon_name = icon_tbl[code]
weather_icon_widget.icon:set_image(widget_icon_dir .. widget_icon_name)
weather_icon_widget.icon:emit_signal('widget::redraw_needed')
weather_desc_temp.description:set_markup(desc)
weather_location.location:set_markup(location)
weather_sunrise:set_markup(sunrise)
weather_sunset:set_markup(sunset)
weather_data_time:set_markup(data_receive)
end
)
return weather_report