-
-
Save meskarune/e415748a104f0479f54dd642d66011e8 to your computer and use it in GitHub Desktop.
#!/usr/bin/env lua | |
conky_color = "${color1}%2d${color}" | |
t = os.date('*t', os.time()) | |
year, month, currentday = t.year, t.month, t.day | |
daystart = os.date("*t",os.time{year=year,month=month,day=01}).wday | |
month_name = os.date("%B") | |
days_in_month = { | |
31, 28, 31, 30, 31, 30, | |
31, 31, 30, 31, 30, 31 | |
} | |
-- check for leap year | |
-- Any year that is evenly divisible by 4 is a leap year | |
-- Any year that is evenly divisible by 100 is a leap year if | |
-- it is also evenly divisible by 400. | |
LeapYear = function (year) | |
return year % 4 == 0 and (year % 100 ~= 0 or year % 400 == 0) | |
end | |
if LeapYear(year) then | |
days_in_month[2] = 29 | |
end | |
title_start = (20 - (string.len(month_name) + 5)) / 2 | |
title = string.rep(" ", math.floor(title_start+0.5)) .. -- add padding to center the title | |
(" %s %s\n Su Mo Tu We Th Fr Sa\n"):format(month_name, year) | |
io.write(title) | |
function seq(a,b) | |
if a > b then | |
return | |
else | |
return a, seq(a+1,b) | |
end | |
end | |
days = days_in_month[month] | |
io.write( | |
string.format( | |
string.rep(" ", daystart-1) .. | |
string.rep(" %2d", days), seq(1,days) | |
):gsub(string.rep(".",21),"%0\n") | |
:gsub(("%2d"):format(currentday), | |
(conky_color):format(currentday), | |
1 | |
) .. "\n" | |
) |
-- vim: ts=4 sw=4 noet ai cindent syntax=lua | |
conky.config = { | |
alignment = 'top_right', | |
background = false, | |
border_width = 0, | |
cpu_avg_samples = 2, | |
default_color = 'cccccc', | |
color1 = '86b5ea', | |
default_outline_color = 'cccccc', | |
default_shade_color = '7a999c', | |
double_buffer = true, | |
draw_borders = false, | |
draw_graph_borders = false, | |
draw_outline = false, | |
draw_shades = false, | |
use_xft = true, | |
font = 'Fira Sans:normal:size=14', | |
gap_x = 10, | |
gap_y = 41, | |
minimum_height = 5, | |
minimum_width = 231, | |
maximum_width = 231, | |
net_avg_samples = 2, | |
no_buffers = true, | |
out_to_console = false, | |
out_to_stderr = false, | |
extra_newline = false, | |
own_window = true, | |
own_window_class = 'Conky', | |
own_window_transparent = true, | |
own_window_type = 'desktop', | |
stippled_borders = 0, | |
update_interval = 1.0, | |
uppercase = false, | |
use_spacer = 'none', | |
show_graph_scale = false, | |
show_graph_range = false, | |
} | |
conky.text = [[ | |
${alignc}${font :size=28} ${time %k:%M %p}${font} | |
${font Fira Mono:size=14}${execpi 3600 ~/.config/conky/cal.lua}${font} | |
${alignc}${execpi 1800 ~/.config/conky/weather.lua} | |
]] |
#!/usr/bin/lua | |
https = require("ssl.https") | |
json = require("json") | |
-- To use edit variables below for your timezone and location then add the next line to your conky config, uncommented | |
-- ${alignc}${execpi 3600 ~/.config/conky/moonphase.lua} | |
-- Change to your timezone offset | |
tz = "-0" | |
-- Change to the lattitude and longitude you want to use | |
lat = "51.5" | |
long = "-0.116667" | |
curdate = os.date("!%Y%m%d") | |
curtime = os.date("!%Y%m%d%H%M%S") | |
api_url = ("https://api.solunar.org/solunar/%s,%s,%s,%s"):format(lat,long,curdate,tz) | |
moon = { | |
["New Moon"] = "🌑", | |
["Waxing Crescent"] = "🌒", | |
["First Quarter"] = "🌓", | |
["Waxing Gibbous"] = "🌔", | |
["Full moon"] = "🌕", | |
["Waning Gibbous"] = "🌖", | |
["Third Quarter"] = "🌗", | |
["Waning Crescent"] = "🌘" | |
} | |
file_exists = function (name) | |
f=io.open(name,"r") | |
if f~=nil then | |
f:close() | |
return true | |
else | |
return false | |
end | |
end | |
if file_exists("moonphase.json") then | |
cache = io.open("moonphase.json","r") | |
data = json.decode(cache:read()) | |
cache:close() | |
timepassed = os.difftime(curtime, data.timestamp) | |
else | |
timepassed = 6000 | |
end | |
makecache = function (s) | |
cache = io.open("moonphase.json", "w+") | |
s.timestamp = curtime | |
save = json.encode(s) | |
cache:write(save) | |
cache:close() | |
end | |
if timepassed < 3600 then | |
response = data | |
else | |
mooninfo = https.request(api_url) | |
if mooninfo then | |
response = json.decode(mooninfo) | |
makecache(response) | |
else | |
response = data | |
end | |
end | |
phase = response.moonPhase | |
conky_text = [[${font Symbola:size=20}%s${font} %s]] | |
io.write((conky_text):format(moon[phase], phase)) |
#!/usr/bin/env lua | |
-- load the http socket module | |
http = require("socket.http") | |
-- load the json module | |
json = require("json") | |
api_url = "https://api.openweathermap.org/data/2.5/onecall?" | |
-- Your lattitude and longitude | |
LAT = 51.509865 | |
LON = -0.118092 | |
-- metric or imperial | |
cf = "metric" | |
-- get an open weather map api key: http://openweathermap.org/appid | |
apikey = "api-key" | |
-- measure is °C if metric and °F if imperial | |
measure = '°' .. (cf == 'metric' and 'C' or 'F') | |
wind_units = (cf == 'metric' and 'km/h' or 'mph') | |
-- Unicode weather symbols to use | |
icons = { | |
["01"] = "☀", | |
["02"] = "🌤", | |
["03"] = "🌥", | |
["04"] = "☁", | |
["09"] = "🌧", | |
["10"] = "🌦", | |
["11"] = "🌩", | |
["13"] = "🌨", | |
["50"] = "🌫", | |
} | |
currenttime = os.date("!%Y%m%d%H%M%S") | |
file_exists = function (name) | |
f=io.open(name,"r") | |
if f~=nil then | |
f:close() | |
return true | |
else | |
return false | |
end | |
end | |
if file_exists("weather.json") then | |
cache = io.open("weather.json","r") | |
data = json.decode(cache:read()) | |
cache:close() | |
timepassed = os.difftime(currenttime, data.timestamp) | |
else | |
timepassed = 6000 | |
end | |
makecache = function (s) | |
cache = io.open("weather.json", "w+") | |
s.timestamp = currenttime | |
save = json.encode(s) | |
cache:write(save) | |
cache:close() | |
end | |
if timepassed < 3600 then | |
response = data | |
else | |
weather = http.request(("%slat=%s&lon=%s&exclude=minutely,hourly&units=%s&APPID=%s"):format(api_url, LAT, LON, cf, apikey)) | |
if weather then | |
response = json.decode(weather) | |
makecache(response) | |
else | |
response = data | |
end | |
end | |
math.round = function (n) | |
return math.floor(n + 0.5) | |
end | |
degrees_to_direction = function (d) | |
val = math.round(d/22.5) | |
directions = { [0] = "N", [1] = "NNE", [2] = "NE", [3] = "ENE", | |
[4] = "E", [5] = "ESE", [6] = "SE", [7] = "SSE", | |
[8] = "S", [9] = "SSW", [10] = "SW", [11] = "WSW", | |
[12] = "W", [13] = "WNW", [14] = "NW", [15] = "NNW" | |
} | |
return directions[val % 16] | |
end | |
temp = response.current.temp | |
min = response.daily[1].temp.min | |
max = response.daily[1].temp.max | |
conditions = response.current.weather[1].description | |
icon2 = response.current.weather[1].id | |
icon = response.current.weather[1].icon:sub(1, 2) | |
humidity = response.current.humidity | |
wind = response.current.wind_speed | |
deg = degrees_to_direction(response.current.wind_deg) | |
sunrise = os.date("%H:%M", response.current.sunrise) | |
sunset = os.date("%H:%M", response.current.sunset) | |
forcast_icon = response.daily[2].weather[1].icon:sub(1, 2) | |
forcast_temp = response.daily[2].temp.day | |
forcast_conditions = response.daily[2].weather[1].main | |
conky_text = [[ | |
${font Symbola:size=48}%s ${voffset -10}${font :size=20}${color1}%s${font}${voffset -5}%s${color} | |
${alignc}${voffset 28} %s | |
${alignc}High: ${color1}%s%s ${color}Low: ${color1}%s%s${color} | |
${alignc}Humidity: ${color1}%s%%${color} | |
${alignc}Wind: ${color1}%s%s %s${color} | |
${alignc}Tomorrow: | |
${alignc}${color1}${font Symbola:size=20}%s${font} %s%s %s${color} | |
${alignc}${font Symbola:size=20}─☀─${font} | |
${alignc}${color1}%s${color} | ${color1}%s${color} | |
]] | |
io.write((conky_text):format(icons[icon], | |
math.round(temp), | |
measure, | |
conditions, | |
math.round(max), | |
measure, | |
math.round(min), | |
measure, | |
humidity, | |
math.round(wind), | |
wind_units, | |
deg, | |
icons[forcast_icon], | |
math.round(forcast_temp), | |
measure, | |
forcast_conditions, | |
sunrise, | |
sunset) | |
) |
I'm having this following error message:
/usr/bin/lua5.2: /home/arafat/.config/conky/weather/weather.lua:60: attempt to index global 'cache' (a nil value) stack traceback: /home/arafat/.config/conky/weather/weather.lua:60: in function 'makecache' /home/arafat/.config/conky/weather/weather.lua:70: in main chunk [C]: in ?
Can you help me please?
Wind direction in weather.lua:80 is decoded wrong. Right solution
`
degrees_to_direction = function (d)
val = math.floor(d/22.5 + 0.5)
directions = {
[0] = "N", [1] = "NNE", [2] = "NE", [3] = "ENE",
[4] = "E", [5] = "ESE", [6] = "SE", [7] = "SSE",
[8] = "S", [9] = "SSW", [10] = "SW", [11] = "WSW",
[12] = "W", [13] = "WNW", [14] = "NW", [15] = "NNW"
}
return directions[val % 16]
end
`
@alo0oz - the problem is the path. You can either CD to the path where the script is located or you can edit weather.lua and add:
wdir = os.getenv("HOME").."/path/to/directory/"
Near the top of the script where /path/to/directory/ is your directory.
Then concatenate that variable in the 3 places in the script:
so...
if file_exists(wdir.."weather.json") then
cache = io.open(wdir.."weather.json","r")
and..
cache = io.open(wdir.."weather.json", "w+")
I used your code as a starting point for my own script. I just refactored some of it to lose the global variables. If anyone needs it, here it is.
#!/usr/bin/env lua
local json = require("json")
local function file_exists(name)
local f = io.open(name, "r")
if f ~= nil then
f:close()
return true
else
return false
end
end
local function write_cache(s)
local cache = io.open("weather.json", "w+")
s.timestamp = os.date("!%Y%m%d%H%M%S")
local save = json.encode(s)
cache:write(save)
cache:close()
end
local function read_cache()
local data
if file_exists("weather.json") then
local cache = io.open("weather.json","r")
data = json.decode(cache:read())
cache:close()
end
return data
end
local function fetch_weather(cf)
local http = require("socket.http")
local api_url = "http://api.openweathermap.org/data/2.5/weather?"
local cityid = "<city_id>"
local apikey = "<api_key>"
return http.request(("%sid=%s&units=%s&APPID=%s"):format(api_url, cityid, cf, apikey))
end
local function time_passed(data)
if data == nil then
return 6000
else
return os.difftime(os.date("!%Y%m%d%H%M%S"), data.timestamp)
end
end
local function get_response(cf)
local data = read_cache()
local timepassed = time_passed(data)
if timepassed < 3600 then
return data
else
local weather = fetch_weather(cf)
if weather ~= nil then
local response = json.decode(weather)
write_cache(response)
return response
else
return data
end
end
end
function conky_main()
-- metric or imperial
local cf = "metric"
local measure = '°' .. (cf == 'metric' and 'C' or 'F')
local wind_units = (cf == 'metric' and 'kph' or 'mph')
local response = get_response(cf)
return "..."
end
I've updated the script to latest working version. The api stopped giving wind direction so that is removed and min/max temp were added in. I need to clean it up a bit more. Maybe in the future I can also add in 3 day forecast.
@FSchliephacke thanks so much for sharing your script! :D
fixed some issue in weather.lua
#!/usr/bin/env lua
-- load the http socket module
http = require("socket.http")
-- load the json module
json = require("json")
api_url = "http://api.openweathermap.org/data/2.5/weather?"
-- http://openweathermap.org/help/city_list.txt , http://openweathermap.org/find
cityid = "6542124"
-- metric or imperial
cf = "metric"
-- get an open weather map api key: http://openweathermap.org/appid
apikey = "api key"
-- measure is °C if metric and °F if imperial
measure = "°" .. (cf == "metric" and "C" or "F")
wind_units = (cf == "metric" and "kph" or "mph")
-- Unicode weather symbols to use
icons = {
["01"] = "☀️",
["02"] = "🌤",
["03"] = "🌥",
["04"] = "☁",
["09"] = "🌧",
["10"] = "🌦",
["11"] = "🌩",
["13"] = "🌨",
["50"] = "🌫"
}
currenttime = os.date("!%Y%m%d%H%M%S")
file_exists = function(name)
f = io.open(name, "r")
if f ~= nil then
f:close()
return true
else
return false
end
end
if file_exists("weather.json") then
cache = io.open("weather.json", "r")
data = json.decode(cache:read())
cache:close()
timepassed = os.difftime(currenttime, data.timestamp)
else
timepassed = 6000
end
makecache = function(s)
cache = io.open("weather.json", "w+")
s.timestamp = currenttime
save = json.encode(s)
cache:write(save)
cache:close()
end
if timepassed < 3600 then
response = data
else
weather = http.request(("%sid=%s&units=%s&APPID=%s"):format(api_url, cityid, cf, apikey))
if weather then
response = json.decode(weather)
makecache(response)
else
response = data
end
end
math.round = function(n)
return math.floor(n + 0.5)
end
degrees_to_direction = function(d)
val = math.floor(d / 22.5 + 0.5)
directions = {
[00] = "N",
[01] = "NNE",
[02] = "NE",
[03] = "ENE",
[04] = "E",
[05] = "ESE",
[06] = "SE",
[07] = "SSE",
[08] = "S",
[09] = "SSW",
[10] = "SW",
[11] = "WSW",
[12] = "W",
[13] = "WNW",
[14] = "NW",
[15] = "NNW"
}
return directions[val % 16]
end
temp = response.main.temp
min = response.main.temp_min
max = response.main.temp_max
conditions = response.weather[1].description
icon2 = response.weather[1].id
icon = response.weather[1].icon:sub(1, 2)
humidity = response.main.humidity
wind = response.wind.speed
deg = degrees_to_direction(response.wind.deg)
sunrise = os.date("%H:%M %p", response.sys.sunrise)
sunset = os.date("%H:%M %p", response.sys.sunset)
conky_text =
[[
${font Symbola:size=36}%s ${voffset -10}${font :size=10}${color1}%s${font}${voffset 0}%s${color}
${alignc}${voffset 28} %s
${alignc}High: ${color1}%s%s ${color}Low: ${color1}%s%s${color}
${alignc}Humidity: ${color1}%s%%${color}
${alignc}${font Symbola:size=20}─⯊─${font}
${alignc}${color1}%s${color} | ${color1}%s${color}
]]
io.write(
(conky_text):format(
icons[icon],
math.round(temp),
measure,
conditions,
math.round(max),
measure,
math.round(min),
measure,
humidity,
math.round(wind),
deg,
sunrise,
sunset
)
)
I modified you code slightly to use a JSON cache file in a consistent location:
$HOME/.config/conky
This makes my home directory maintenance much easier. I also cleaned up the output to suite my personal conky configuration.
Here is the updated moonphase.lua:
#!/usr/bin/lua
https = require("ssl.https")
json = require("json")
-- To use edit variables below for your timezone and location then add the next line to your conky config, uncommented
-- ${alignc}${execpi 3600 ~/.config/conky/moonphase.lua}
-- Change to your timezone offset
--- EST -5, EDT -4
tz = "-4"
-- Change to the lattitude and longitude you want to use
lat = "XX.43"
long = "-XX.48"
curdate = os.date("!%Y%m%d")
curtime = os.date("!%Y%m%d%H%M%S")
api_url = ("https://api.solunar.org/solunar/%s,%s,%s,%s"):format(lat,long,curdate,tz)
moon = {
["New Moon"] = "🌑",
["Waxing Crescent"] = "🌒",
["First Quarter"] = "🌓",
["Waxing Gibbous"] = "🌔",
["Full moon"] = "🌕",
["Waning Gibbous"] = "🌖",
["Third Quarter"] = "🌗",
["Waning Crescent"] = "🌘"
}
cachefile = os.getenv("HOME")..("/.config/conky/moonphase.json")
file_exists = function (name)
f=io.open(name,"r")
if f~=nil then
f:close()
return true
else
return false
end
end
if file_exists(cachefile) then
cache = io.open(cachefile,"r")
data = json.decode(cache:read())
cache:close()
timepassed = os.difftime(curtime, data.timestamp)
else
timepassed = 6000
end
makecache = function (s)
cache = io.open(cachefile, "w+")
s.timestamp = curtime
save = json.encode(s)
cache:write(save)
cache:close()
end
if timepassed < 3600 then
response = data
else
mooninfo = https.request(api_url)
if mooninfo then
response = json.decode(mooninfo)
makecache(response)
else
response = data
end
end
phase = response.moonPhase
transit = response.moonTransit
rise = response.moonRise
set = response.moonSet
conky_text = [[${font Symbola:size=20}${alignc}${color2}%s${font} %s
${color}Rise: ${color9}%5s
${color}Transit: ${color9}%5s
${color}Set: ${color9}%5s]]
io.write((conky_text):format(moon[phase], phase, rise, transit, set))
And, I made a similar update to weather.lua to use a consistent cache file in $HOME/.config/conky and a few other cosmetic changes to suite my personal conky configuration.
#!/usr/bin/env lua
-- load the http socket module
http = require("socket.http")
-- load the json module
json = require("json")
api_url = "http://api.openweathermap.org/data/2.5/weather?"
-- http://openweathermap.org/help/city_list.txt , http://openweathermap.org/find
---cityid = "6542124"
-- metric or imperial
cf = "imperial"
-- get an open weather map api key: http://openweathermap.org/appid
apikey = "XXX"
-- measure is °C if metric and °F if imperial
measure = "°" .. (cf == "metric" and "C" or "F")
wind_units = (cf == "metric" and "kph" or "mph")
-- Unicode weather symbols to use
icons = {
["01"] = "☀️",
["02"] = "🌤",
["03"] = "🌥",
["04"] = "☁",
["09"] = "🌧",
["10"] = "🌦",
["11"] = "🌩",
["13"] = "🌨",
["50"] = "🌫"
}
currenttime = os.date("!%Y%m%d%H%M%S")
cachefile = os.getenv("HOME")..("/.config/conky/weather.json")
---print (cachefile)
file_exists = function(name)
f = io.open(name, "r")
if f ~= nil then
f:close()
return true
else
return false
end
end
if file_exists(cachefile) then
cache = io.open(cachefile, "r")
data = json.decode(cache:read())
cache:close()
timepassed = os.difftime(currenttime, data.timestamp)
else
timepassed = 6000
end
makecache = function(s)
cache = io.open(cachefile, "w+")
s.timestamp = currenttime
save = json.encode(s)
cache:write(save)
cache:close()
end
if timepassed < 3600 then
response = data
else
weather = http.request(("%sid=%s&units=%s&APPID=%s"):format(api_url, cityid, cf, apikey))
if weather then
response = json.decode(weather)
makecache(response)
else
response = data
end
end
math.round = function(n)
return math.floor(n + 0.5)
end
degrees_to_direction = function(d)
val = math.floor(d / 22.5 + 0.5)
directions = {
[00] = "N",
[01] = "NNE",
[02] = "NE",
[03] = "ENE",
[04] = "E",
[05] = "ESE",
[06] = "SE",
[07] = "SSE",
[08] = "S",
[09] = "SSW",
[10] = "SW",
[11] = "WSW",
[12] = "W",
[13] = "WNW",
[14] = "NW",
[15] = "NNW"
}
return directions[val % 16]
end
temp = response.main.temp
min = response.main.temp_min
max = response.main.temp_max
conditions = response.weather[1].description
icon2 = response.weather[1].id
icon = response.weather[1].icon:sub(1, 2)
humidity = response.main.humidity
wind = response.wind.speed
deg = degrees_to_direction(response.wind.deg)
sunrise = os.date("%H:%M %p", response.sys.sunrise)
sunset = os.date("%H:%M %p", response.sys.sunset)
conky_text =
[[
${font Symbola:size=36}${alignc}${color2}%s ${voffset -10}${font :size=10}${color9}%s${font}${voffset 0}%s
${alignc}${color2}${voffset 28}%s
${alignc}${color}High: ${color9}%s%s ${color}Low: ${color9}%s%s${color}
${alignc}Humidity: ${color9}%s%%${color}
${alignc}Wind: ${color9}%smph${color} @ ${color9}%s${color}
${alignc}${font Symbola:size=20}─⯊─${font}
${alignc}${color9}%s${color} | ${color9}%s${color}
]]
io.write(
(conky_text):format(
icons[icon],
math.round(temp),
measure,
conditions,
math.round(max),
measure,
math.round(min),
measure,
humidity,
math.round(wind),
deg,
sunrise,
sunset
)
)
Wind direction in weather.lua:80 is decoded wrong. Right solution
`
degrees_to_direction = function (d)
val = math.floor(d/22.5 + 0.5)
directions = {
[0] = "N", [1] = "NNE", [2] = "NE", [3] = "ENE",
[4] = "E", [5] = "ESE", [6] = "SE", [7] = "SSE",
[8] = "S", [9] = "SSW", [10] = "SW", [11] = "WSW",
[12] = "W", [13] = "WNW", [14] = "NW", [15] = "NNW"
}
return directions[val % 16]
end`
Thanks, I added to the script. I can try to update to use local vars as well. Sorry I am a bit slow. Maybe I should move all this to it's own repository at some point.
You can just add the ${alignc} conky directive in your conky.conf:
${font Fira Mono:size=14}${alignc}${execpi 3600 ~/.config/conky/cal.lua}${font}
Bumping ~5 months old post, cause these days I spent lot of useless, but very very interesting hours - top fun time, to fit these scripts to my taste and positioning of calendar was one of challenges (don't take me wrong: I like to have candy desktop and this kind of modding is very interesting for me - I enjoy it, but I have to say it is useless cause it is :) 👯 👯 :) ).
1st thing: Thanks to @meskarune for scripts and concept!!!
2nd thing: @jnyilas: unfortunately, this couldn't be accomplished with Conky alignment, cause putting any ${offset xx}
, ${alignc}
, ${alignr}
, etc. in front or middle of ${font Fira Mono:size=14}${execpi 3600 ~/.config/conky/cal.lua}${font}
will move/align only first line, i.e. December 2020, like this:
I am not developer. Usually I am able to edit finished code and fit it to my needs, but this was my first time with Lua and hadn't success to figure out could this be aligned inside cal.lua file. So i used workaround/cheat/hack whatever and piped conky exec line for cal.lua to sed, adding spaces in front to every line:
${font Ubuntu Mono:size=14:style=bold}${execpi 3600 ~/.config/conky/cal.lua | sed 's/^/ /'}${font}
(there are lot of SPACEs between two slashes above / / , but it seems that github code tag is displaying all of them as one SPACE)
Anyway, this is my final desktop and I am happy:
I would paste my edit of weather.lua here, cause I made 7 days forecast and will be glad to give my contribution here - @meskarune: please be free to implement it in your script if you want. @ALL: Please note that you will need either to revert back icons to unicode icons in weather.lua or you will need icon font I made for this, where I used someone else icons (or you will need to make that font). Reason why I'm not providing everything right now is because I'm lazy :) . I used lot of someone else work for this and if I want to publish my work, I need to credit all these people properly. It will require some more work and hours and I cannot know will this be interesting for even one person at all. I can promise, if someone wish all resources, I will immediately publish this somewhere with all proper credits and share link here - please just let me know (I subscribed to this topic :) ).
At the end, once again, I am not developer and I believe that this probably can be done better and more elegant, but it doing the job for me and I am ok with that.
weather.lua:
#!/usr/bin/env lua
-- load the http socket module
http = require("socket.http")
-- load the json module
json = require("json")
api_url = "https://api.openweathermap.org/data/2.5/onecall?"
-- Your lattitude and longitude
LAT = <put your latitude here>
LON = <put your longitude here>
-- metric or imperial
cf = "metric"
-- get an open weather map api key: http://openweathermap.org/appid
apikey = "<put your API key here>"
-- measure is °C if metric and °F if imperial
measure = '°' .. (cf == 'metric' and 'C' or 'F')
wind_units = (cf == 'metric' and 'm/s' or 'mph')
-- Font icon to use
icons = {
["01d"] = "a",
["02d"] = "c",
["03d"] = "e",
["04d"] = "g",
["09d"] = "i",
["10d"] = "k",
["11d"] = "m",
["13d"] = "o",
["50d"] = "q",
["01n"] = "b",
["02n"] = "d",
["03n"] = "f",
["04n"] = "h",
["09n"] = "j",
["10n"] = "l",
["11n"] = "n",
["13n"] = "p",
["50n"] = "r",
}
currenttime = os.date("!%Y%m%d%H%M%S")
file_exists = function (name)
f=io.open(name,"r")
if f~=nil then
f:close()
return true
else
return false
end
end
if file_exists("weather.json") then
cache = io.open("weather.json","r")
data = json.decode(cache:read())
cache:close()
timepassed = os.difftime(currenttime, data.timestamp)
else
timepassed = 6000
end
makecache = function (s)
cache = io.open("weather.json", "w+")
s.timestamp = currenttime
save = json.encode(s)
cache:write(save)
cache:close()
end
if timepassed < 3600 then
response = data
else
weather = http.request(("%slat=%s&lon=%s&exclude=minutely,hourly&units=%s&APPID=%s"):format(api_url, LAT, LON, cf, apikey))
if weather then
response = json.decode(weather)
makecache(response)
else
response = data
end
end
math.round = function (n)
return math.floor(n + 0.5)
end
degrees_to_direction = function (d)
val = math.round(d/22.5)
directions = { [0] = "N", [1] = "NNE", [2] = "NE", [3] = "ENE",
[4] = "E", [5] = "ESE", [6] = "SE", [7] = "SSE",
[8] = "S", [9] = "SSW", [10] = "SW", [11] = "WSW",
[12] = "W", [13] = "WNW", [14] = "NW", [15] = "NNW"
}
return directions[val % 16]
end
daysoftheweek = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}
day = daysoftheweek[os.date("*t").wday]
day1 = daysoftheweek[os.date("*t", (os.time() + 86400)).wday]
day2 = daysoftheweek[os.date("*t", (os.time() + 172800)).wday]
day3 = daysoftheweek[os.date("*t", (os.time() + 259200)).wday]
day4 = daysoftheweek[os.date("*t", (os.time() + 345600)).wday]
day5 = daysoftheweek[os.date("*t", (os.time() + 432000)).wday]
day6 = daysoftheweek[os.date("*t", (os.time() + 518400)).wday]
day7 = daysoftheweek[os.date("*t", (os.time() + 604800)).wday]
temp = response.current.temp
min = response.daily[1].temp.min
max = response.daily[1].temp.max
conditions = response.current.weather[1].description
icon2 = response.current.weather[1].id
icon = response.current.weather[1].icon
humidity = response.current.humidity
wind = response.current.wind_speed
deg = degrees_to_direction(response.current.wind_deg)
sunrise = os.date("%H:%M", response.current.sunrise)
sunset = os.date("%H:%M", response.current.sunset)
forecast1_icon = response.daily[2].weather[1].icon
forecast2_icon = response.daily[3].weather[1].icon
forecast3_icon = response.daily[4].weather[1].icon
forecast4_icon = response.daily[5].weather[1].icon
forecast5_icon = response.daily[6].weather[1].icon
forecast6_icon = response.daily[7].weather[1].icon
forecast7_icon = response.daily[8].weather[1].icon
forecast1_temp = response.daily[2].temp.day
forecast2_temp = response.daily[3].temp.day
forecast3_temp = response.daily[4].temp.day
forecast4_temp = response.daily[5].temp.day
forecast5_temp = response.daily[6].temp.day
forecast6_temp = response.daily[7].temp.day
forecast7_temp = response.daily[8].temp.day
forecast1_conditions = response.daily[2].weather[1].main
forecast2_conditions = response.daily[3].weather[1].main
forecast3_conditions = response.daily[4].weather[1].main
forecast4_conditions = response.daily[5].weather[1].main
forecast5_conditions = response.daily[6].weather[1].main
forecast6_conditions = response.daily[7].weather[1].main
forecast7_conditions = response.daily[8].weather[1].main
forecast1_min = response.daily[2].temp.min
forecast2_min = response.daily[3].temp.min
forecast3_min = response.daily[4].temp.min
forecast4_min = response.daily[5].temp.min
forecast5_min = response.daily[6].temp.min
forecast6_min = response.daily[7].temp.min
forecast7_min = response.daily[8].temp.min
forecast1_max = response.daily[2].temp.max
forecast2_max = response.daily[3].temp.max
forecast3_max = response.daily[4].temp.max
forecast4_max = response.daily[5].temp.max
forecast5_max = response.daily[6].temp.max
forecast6_max = response.daily[7].temp.max
forecast7_max = response.daily[8].temp.max
conky_text = [[
${alignc}${offset -50}${color9}${font Weather_icons_tatosxl_stiw47:size=47}%s${color} ${voffset -5}${font Alpaca Scarlett Demo:size=27}${color1}%s${font}${voffset -13}${font Alpaca Scarlett Demo:size=15}%s${font}${color}
${alignc}${offset 115}${voffset 8}${color1} %s${color}
${alignc}${offset 172}${voffset 3}${font Alpaca Scarlett Demo:size=12}${color5}High:${color} ${color1}%s${color}${font}${font Alpaca Scarlett Demo:size=7}${color1}${voffset -15}%s${voffset}${color}${font} ${font Alpaca Scarlett Demo:size=12}${color7}${voffset -6}Low:${color} ${color1}${offset 0}%s${color}${font}${font Alpaca Scarlett Demo:size=7}${color1}${voffset -15}%s${voffset}${color}${font}
${alignc}${offset 130}${voffset -10}${font Alpaca Scarlett Demo:size=12}${color3}Humidity:${color} ${color1}%s%%${color}
${alignc}${offset 115}${voffset 5}${color4}Wind:${color} ${color1}%s%s %s${color}${font}
${alignc}${offset 115}${voffset -10}${color FF945E}${font Weather_icons_tatosxl_stiw47:size=70}s${font}${color}
${alignc}${offset 143}${voffset -27}${font Alpaca Scarlett Demo:size=12}${color1}%s${color}${color2} |${color} ${color1}%s${color}${font}
${alignc}${offset -202}${voffset 35}${font Alpaca Scarlett Demo:size=12}${color3}%s
${alignc}${offset -129}${voffset -20}${font Alpaca Scarlett Demo:size=12}${color3}%s
${alignc}${offset -55}${voffset -20}${font Alpaca Scarlett Demo:size=12}${color3}%s
${alignc}${offset 18}${voffset -20}${font Alpaca Scarlett Demo:size=12}${color3}%s
${alignc}${offset 90}${voffset -20}${font Alpaca Scarlett Demo:size=12}${color3}%s
${alignc}${offset 164}${voffset -20}${font Alpaca Scarlett Demo:size=12}${color3}%s
${alignc}${offset 237}${voffset -20}${font Alpaca Scarlett Demo:size=12}${color3}%s
${alignc}${offset -155}${voffset 4}${font Weather_icons_tatosxl_stiw47:size=30}${color9}%s${color}${font}${offset 4}${voffset -7}${color1}${font Alpaca Scarlett Demo:size=11}%s${font}${color}${color1}${font Alpaca Scarlett Demo:size=8}${voffset -14}%s${font}${color}
${alignc}${offset -85}${voffset -34}${font Weather_icons_tatosxl_stiw47:size=30}${color9}%s${color}${font}${offset 4}${voffset -7}${color1}${font Alpaca Scarlett Demo:size=11}%s${font}${color}${color1}${font Alpaca Scarlett Demo:size=8}${voffset -14}%s${font}${color}
${alignc}${offset -11}${voffset -34}${font Weather_icons_tatosxl_stiw47:size=30}${color9}%s${color}${font}${offset 4}${voffset -7}${color1}${font Alpaca Scarlett Demo:size=11}%s${font}${color}${color1}${font Alpaca Scarlett Demo:size=8}${voffset -14}%s${font}${color}
${alignc}${offset 64}${voffset -34}${font Weather_icons_tatosxl_stiw47:size=30}${color9}%s${color}${font}${offset 4}${voffset -7}${color1}${font Alpaca Scarlett Demo:size=11}%s${font}${color}${color1}${font Alpaca Scarlett Demo:size=8}${voffset -14}%s${font}${color}
${alignc}${offset 135}${voffset -34}${font Weather_icons_tatosxl_stiw47:size=30}${color9}%s${color}${font}${offset 4}${voffset -7}${color1}${font Alpaca Scarlett Demo:size=11}%s${font}${color}${color1}${font Alpaca Scarlett Demo:size=8}${voffset -14}%s${font}${color}
${alignc}${offset 206}${voffset -35}${font Weather_icons_tatosxl_stiw47:size=30}${color9}%s${color}${font}${offset 4}${voffset -7}${color1}${font Alpaca Scarlett Demo:size=11}%s${font}${color}${color1}${font Alpaca Scarlett Demo:size=8}${voffset -14}%s${font}${color}
${alignc}${offset 282}${voffset -34}${font Weather_icons_tatosxl_stiw47:size=30}${color9}%s${color}${font}${offset 4}${voffset -7}${color1}${font Alpaca Scarlett Demo:size=11}%s${font}${color}${color1}${font Alpaca Scarlett Demo:size=8}${voffset -14}%s${font}${color}
${alignc}${offset -185}${voffset -10}${font Alpaca Scarlett Demo:size=8}${color7}%s${color}${color1}%s${color} ${color5}%s${color}${color1}%s${color}
${alignc}${offset -120}${voffset -14}${font Alpaca Scarlett Demo:size=8}${color7}%s${color}${color1}%s${color} ${color5}%s${color}${color1}%s${color}
${alignc}${offset -47}${voffset -13}${font Alpaca Scarlett Demo:size=8}${color7}%s${color}${color1}%s${color} ${color5}%s${color}${color1}%s${color}
${alignc}${offset 26}${voffset -14}${font Alpaca Scarlett Demo:size=8}${color7}%s${color}${color1}%s${color} ${color5}%s${color}${color1}%s${color}
${alignc}${offset 101}${voffset -14}${font Alpaca Scarlett Demo:size=8}${color7}%s${color}${color1}%s${color} ${color5}%s${color}${color1}%s${color}
${alignc}${offset 172}${voffset -13}${font Alpaca Scarlett Demo:size=8}${color7}%s${color}${color1}%s${color} ${color5}%s${color}${color1}%s${color}
${alignc}${offset 246}${voffset -13}${font Alpaca Scarlett Demo:size=8}${color7}%s${color}${color1}%s${color} ${color5}%s${color}${color1}%s${color}
${alignc}${offset -202}${voffset 10}${font Alpaca Scarlett Demo:size=8}${color1}%s
${alignc}${offset -128}${voffset -13}${font Alpaca Scarlett Demo:size=8}${color1}%s
${alignc}${offset -54}${voffset -14}${font Alpaca Scarlett Demo:size=8}${color1}%s
${alignc}${offset 18}${voffset -13}${font Alpaca Scarlett Demo:size=8}${color1}%s
${alignc}${offset 93}${voffset -14}${font Alpaca Scarlett Demo:size=8}${color1}%s
${alignc}${offset 164}${voffset -13}${font Alpaca Scarlett Demo:size=8}${color1}%s
${alignc}${offset 237}${voffset -13}${font Alpaca Scarlett Demo:size=8}${color1}%s
]]
io.write((conky_text):format(icons[icon],
math.round(temp),
measure,
conditions,
math.round(max),
measure,
math.round(min),
measure,
humidity,
wind,
wind_units,
deg,
sunrise,
sunset,
day1,
day2,
day3,
day4,
day5,
day6,
day7,
icons[forecast1_icon],
math.round(forecast1_temp),
measure,
icons[forecast2_icon],
math.round(forecast2_temp),
measure,
icons[forecast3_icon],
math.round(forecast3_temp),
measure,
icons[forecast4_icon],
math.round(forecast4_temp),
measure,
icons[forecast5_icon],
math.round(forecast5_temp),
measure,
icons[forecast6_icon],
math.round(forecast6_temp),
measure,
icons[forecast7_icon],
math.round(forecast7_temp),
measure,
math.round(forecast1_min),
measure,
math.round(forecast1_max),
measure,
math.round(forecast2_min),
measure,
math.round(forecast2_max),
measure,
math.round(forecast3_min),
measure,
math.round(forecast3_max),
measure,
math.round(forecast4_min),
measure,
math.round(forecast4_max),
measure,
math.round(forecast5_min),
measure,
math.round(forecast5_max),
measure,
math.round(forecast6_min),
measure,
math.round(forecast6_max),
measure,
math.round(forecast7_min),
measure,
math.round(forecast7_max),
measure,
forecast1_conditions,
forecast2_conditions,
forecast3_conditions,
forecast4_conditions,
forecast5_conditions,
forecast6_conditions,
forecast7_conditions
)
)
Hello.
I had a hard time at first to show something, but after a boot it worked.
My suggestion is to create a step-by-step for beginning users. It was not so intuitive for me to have to create an account and a API KEY at api.openweathermap.org and replace it in the wheater.lua
file, as well as inform my lat/long values. In any case, this solution has enormous potential. Congratulations!
In my case, for Ubuntu 20.04, as I never developed on the moon (I thought it was pretty cool) I had to run the commands:
sudo apt install lua5.3
sudo apt install lua-socket
sudo apt-install lua-json
chmod 755 ~/.config /conky /*.lua
This is the best conky weather script though it's not working on my end because it's unmaintained
screenshot: