In this post, I outline an approach for retrieving weather conditions from the command line. There are websites and widgets that provide weather details but I like using the command line because I find that it's more efficient than pointing and clicking on stuff. In addition, this approach enables us to program specific tasks. For example, we can set up a task to check the weather every 30 minutes and if weather conditions are getting bad (or going to get bad as forecasted), send us a message or an email. We can program any alert that we need!
We will be using an API provided by Meteomatics to retrieve weather conditions and you need to register an account before you can use the API; you can register for a Free Basic API Package at their API page. The other requirements are R, the lubridate R package, and wget (or if you prefer, you can use curl). We don't really need R and could use some scripting language (like Bash) instead but the lubridate package makes it easy to work with dates.
After registering an account you should receive an email with your username and password, which you need to make an API request. The request URI (uniform resource identifier) follows this format:
https://api.meteomatics.com/validdatetime/parameters/locations/format?optionals
I will go through each section of the URI.
Valid datetime
The API accepts the date and time in the format specified by ISO 8601 and in UTC. We can get the current time in R using Sys.time(); R will automatically detect your time zone but we can also explicitly state it.
To find your time zone use the function OlsonNames(), which outputs all supported time zones in R, together with grep(). It's called Olson because that's the surname of the founding contributor.
grep("Tokyo", OlsonNames(), value=TRUE)
# [1] "Asia/Tokyo"
The with_tz() function from the lubridate package allows us to output datetimes at different time zones.
with_tz(Sys.time(), "Australia/Perth") # [1] "2022-03-17 21:10:15 AWST" with_tz(Sys.time(), "Asia/Tokyo") # [1] "2022-03-17 22:10:15 JST"
To generate the current time in UTC according to ISO 8601, we can use the following code; the Z is the time zone designator for UTC time.
paste0(
format_ISO8601(
with_tz(Sys.time(), "UTC")
),
"Z"
)
# [1] "2022-03-17T13:11:01Z"
Now that we have a valid datetime, we can move on to setting up the parameters.
Parameters
The Free Basic API Package allows you to retrieve the following weather conditions:
| API parameter | Description |
|---|---|
| wind_speed_10m | Instantaneous wind speed at 10m above ground |
| wind_dir_10m:d | Instantaneous wind direction at 10m above ground in degrees |
| wind_gusts_10m_1h | Wind gusts in 10 m in the previous 1h |
| wind_gusts_10m_24h | Wind gusts in 10 m in the previous 24h |
| t_2m | Instantaneous temperature at 2m above ground |
| t_max_2m_24h | Maximum temperature at 2m height in the previous 24h |
| t_min_2m_24h | Minimum temperature at 2m height in the previous 24h |
| msl_pressure | Mean sea level pressure |
| precip_1h | Precipitation accumulated over the past hour |
| precip_24h:mm | Precipitation accumulated over the past 24 hours |
| weather_symbol_1h | Weather symbol giving an overall impression of the weather state of the past hour |
| weather_symbol_24h | Weather symbol giving an overall impression of the weather state of the past 24 hours |
| uv | UV index |
| sunrise | Sunrise |
| sunset | Sunset |
Wind direction is in the direction from which the wind is blowing; a southerly wind blows from the south to the north. The direction is given in degrees clockwise from due north, so a southerly wind has a wind direction of 180 degrees. This is very useful to know if you cycle!
The API parameter is followed by a colon (":") and the desired unit, for example Celsius for temperature. The basic package only allows up to ten parameters per query and I have gone ahead and prepared the parameter part of the URI. The trailing forward slash ("/") at the end of the string is used to delimit each part of the URI, when I join each part back up.
my_param <- 't_2m:C,weather_symbol_1h:idx,weather_symbol_24h:idx,wind_speed_10m:ms,wind_dir_10m:d,uv:idx,msl_pressure:Pa,precip_24h:mm,sunrise:sql,sunset:sql/'
Note that there are units called idx and sql, which I don't think are actual units but perhaps specify how the data is stored (in an index and SQL database).
Locations
The free package only allows one location per query and the location is specified by GPS coordinates. The easiest way to get GPS coordinates for a location of interest is to load up Google Maps, right click on the wanted location, and then copy the coordinates to the clipboard.
my_coord <- '35.550041057153614,139.78659223114846/'
Format
For the format, we simply want CSV.
my_format <- 'csv'
Optionals
In this section we can specify the forecasting model to be used and I will use the mixed model, which is recommended.
my_optional <- '?model=mix'
API call
We can now construct the API call by putting it all together and make the request using wget by using a system call in R. Please substitute my_user and my_password with your username and password. Also note that I am adding 10 hours to my_wanted_Time to get a forecast 10 hours from now and I have set my_tz to Asia/Tokyo; please change these values as you wish.
my_add_hour <- 10
my_wanted_time <- Sys.time()+60*60*my_add_hour
my_tz <- "Asia/Tokyo"
my_user <- 'not_me'
my_password <- 'not_my_password'
my_url <- 'https://api.meteomatics.com/'
my_datetime <- paste0(
format_ISO8601(
with_tz(my_wanted_time, "UTC")
),
"Z/"
)
my_param <- 't_2m:C,weather_symbol_1h:idx,weather_symbol_24h:idx,wind_speed_10m:ms,wind_dir_10m:d,uv:idx,msl_pressure:Pa,precip_24h:mm,sunrise:sql,sunset:sql/'
my_coord <- '35.550041057153614,139.78659223114846/'
my_format <- 'csv'
my_optional <- '?model=mix'
paste0(
'wget --quiet -O - --user ',
my_user,
' --password ',
my_password,
' ',
my_url,
my_datetime,
my_param,
my_coord,
my_format,
my_optional
) -> my_call
my_return <- system(my_call, intern = TRUE)
The return values are saved in my_return but they are a bit hard to read.
my_return # [1] "validdate;t_2m:C;weather_symbol_1h:idx;weather_symbol_24h:idx;wind_speed_10m:ms;wind_dir_10m:d;uv:idx;msl_pressure:Pa;precip_24h:mm;sunrise:sql;sunset:sql" # [2] "2022-03-17T23:34:49Z;7.0;4;8;8.7;34.8;0;101957;7.01;2022-03-16T20:49:00Z;2022-03-17T08:48:00Z"
In order to create a better output, let's first create a vector of the parameters and the units. The code below splits the long return string by their delimiters.
my_cols <- unlist(strsplit(my_return[1],';')) my_cols <- my_cols[-1] my_units <- sapply(my_cols, function(x) strsplit(x, ':')[[1]][2]) my_cols <- sapply(my_cols, function(x) strsplit(x, ':')[[1]][1]) my_cols # t_2m:C weather_symbol_1h:idx weather_symbol_24h:idx wind_speed_10m:ms # "t_2m" "weather_symbol_1h" "weather_symbol_24h" "wind_speed_10m" # wind_dir_10m:d uv:idx msl_pressure:Pa precip_24h:mm # "wind_dir_10m" "uv" "msl_pressure" "precip_24h" # sunrise:sql sunset:sql # "sunrise" "sunset"
We'll create a vector of the returned values joined with their respective unit (and getting rid of the sql and idx units).
my_values <- unlist(strsplit(my_return[2],';'))
my_values <- my_values[-1]
my_values <- paste0(my_values, my_units)
my_values <- sub("sql|idx", "", my_values)
my_values
# [1] "7.0C" "4" "8"
# [4] "8.7ms" "34.8d" "0"
# [7] "101957Pa" "7.01mm" "2022-03-16T20:49:00Z"
# [10] "2022-03-17T08:48:00Z"
We'll create a lookup for the weather codes, instead of displaying an uninformative number, and convert the numbers into their descriptions.
my_code <- c(
"Could not be determined",
"Clear sky",
"Light clouds",
"Partly cloudy",
"Cloudy",
"Rain",
"Rain and snow / sleet",
"Snow",
"Rain shower",
"Snow shower",
"Sleet shower",
"Light Fog",
"Dense fog",
"Freezing rain",
"Thunderstorms",
"Drizzle",
"Sandstorm"
)
names(my_code) <- as.character(0:16)
my_index <- grep("weather_symbol", my_cols)
convert_weather_symbol <- function(x){
x <- as.numeric(x)
if(x >= 100){
x <- x - 100
}
my_code[as.character(x)]
}
my_values[my_index] <- sapply(my_values[my_index], convert_weather_symbol)
my_values
# [1] "7.0C" "Cloudy" "Rain shower"
# [4] "8.7ms" "34.8d" "0"
# [7] "101957Pa" "7.01mm" "2022-03-16T20:49:00Z"
# [10] "2022-03-17T08:48:00Z"
We'll also convert the sunrise and sunset times back into our timezone instead of using UTC time.
my_index <- grep("^sun", my_cols)
convert_datetime <- function(x, tz = my_tz){
x <- sub("T", " ", x)
x <- sub("Z", "", x)
x <- ymd_hms(x, tz = "UTC")
format_ISO8601(with_tz(x, tz), usetz = TRUE)
}
my_values[my_index] <- sapply(my_values[my_index], convert_datetime)
my_values
# [1] "7.0C" "Cloudy" "Rain shower"
# [4] "8.7ms" "34.8d" "0"
# [7] "101957Pa" "7.01mm" "2022-03-17T05:49:00+0900"
# [10] "2022-03-17T17:48:00+0900"
Finally, instead of displaying the short parameter IDs, we'll create a lookup so that we display their full description.
my_param_lookup <- c(
"Instantaneous wind speed at 10m above ground",
"Instantaneous wind direction at 10m above ground in degrees",
"Wind gusts in 10 m in the previous 1h",
"Wind gusts in 10 m in the previous 24h",
"Instantaneous temperature at 2m above ground",
"Maximum temperature at 2m height in the previous 24h",
"Minimum temperature at 2m height in the previous 24h",
"Mean sea level pressure",
"Precipitation accumulated over the past hour",
"Precipitation accumulated over the past 24 hours",
"Weather symbol of the weather state of the past hour",
"Weather symbol of the weather state of the past 24 hours",
"UV index",
"Sunrise",
"Sunset"
)
names(my_param_lookup) <- c(
"wind_speed_10m",
"wind_dir_10m",
"wind_gusts_10m_1h",
"wind_gusts_10m_24h",
"t_2m",
"t_max_2m_24h",
"t_min_2m_24h",
"msl_pressure",
"precip_1h",
"precip_24h",
"weather_symbol_1h",
"weather_symbol_24h",
"uv",
"sunrise",
"sunset"
)
rbind(
c("Time", format_ISO8601(with_tz(my_wanted_time, tzone = my_tz), usetz = TRUE)),
data.frame(variable = my_param_lookup[my_cols], value = my_values, row.names = NULL)
)
# variable value
# 1 Time 2022-03-18T08:34:49+0900
# 2 Instantaneous temperature at 2m above ground 7.0C
# 3 Weather symbol of the weather state of the past hour Cloudy
# 4 Weather symbol of the weather state of the past 24 hours Rain shower
# 5 Instantaneous wind speed at 10m above ground 8.7ms
# 6 Instantaneous wind direction at 10m above ground in degrees 34.8d
# 7 UV index 0
# 8 Mean sea level pressure 101957Pa
# 9 Precipitation accumulated over the past 24 hours 7.01mm
# 10 Sunrise 2022-03-17T05:49:00+0900
# 11 Sunset 2022-03-17T17:48:00+0900
Weather info from the command line
We can save all the code above into a R script and call it from the command line to retrieve the weather conditions.
#!/usr/bin/env Rscript
suppressPackageStartupMessages(library(lubridate))
args <- commandArgs(trailingOnly=TRUE)
my_add_hour <- 0
if (length(args) > 0){
my_add_hour <- as.numeric(args[1])
if (is.na(my_add_hour)){
message("Please enter the number of hours to forecast")
quit(status = 1)
}
}
my_wanted_time <- Sys.time()+60*60*my_add_hour
my_tz <- "Asia/Tokyo"
my_user <- 'not_me'
my_password <- 'not_my_password'
my_url <- 'https://api.meteomatics.com/'
my_datetime <- paste0(
format_ISO8601(
with_tz(my_wanted_time, "UTC")
),
"Z/"
)
my_param <- 't_2m:C,weather_symbol_1h:idx,weather_symbol_24h:idx,wind_speed_10m:ms,wind_dir_10m:d,uv:idx,msl_pressure:Pa,precip_24h:mm,sunrise:sql,sunset:sql/'
my_coord <- '35.550041057153614,139.78659223114846/'
my_format <- 'csv'
my_optional <- '?model=mix'
paste0(
'wget --quiet -O - --user ',
my_user,
' --password ',
my_password,
' ',
my_url,
my_datetime,
my_param,
my_coord,
my_format,
my_optional
) -> my_call
my_return <- system(my_call, intern = TRUE)
my_param_lookup <- c("Wind speed at 10m above ground",
"wind direction at 10m above ground",
"Wind gusts in 10 m in the previous 1h",
"Wind gusts in 10 m in the previous 24h",
"Temperature at 2m above ground",
"Maximum temperature at 2m in the previous 24h",
"Minimum temperature at 2m in the previous 24h",
"Mean sea level pressure",
"Precipitation over the past hour",
"Precipitation over the past 24 hours",
"Weather symbol of the past hour",
"Weather symbol of the past 24 hours",
"UV index",
"Sunrise",
"Sunset"
)
names(my_param_lookup) <- c(
"wind_speed_10m",
"wind_dir_10m",
"wind_gusts_10m_1h",
"wind_gusts_10m_24h",
"t_2m",
"t_max_2m_24h",
"t_min_2m_24h",
"msl_pressure",
"precip_1h",
"precip_24h",
"weather_symbol_1h",
"weather_symbol_24h",
"uv",
"sunrise",
"sunset"
)
my_code <- c(
"Could not be determined",
"Clear sky",
"Light clouds",
"Partly cloudy",
"Cloudy",
"Rain",
"Rain and snow / sleet",
"Snow",
"Rain shower",
"Snow shower",
"Sleet shower",
"Light Fog",
"Dense fog",
"Freezing rain",
"Thunderstorms",
"Drizzle",
"Sandstorm"
)
names(my_code) <- as.character(0:16)
my_cols <- unlist(strsplit(my_return[1],';'))
my_cols <- my_cols[-1]
my_units <- sapply(my_cols, function(x) strsplit(x, ':')[[1]][2])
my_cols <- sapply(my_cols, function(x) strsplit(x, ':')[[1]][1])
my_values <- unlist(strsplit(my_return[2],';'))
my_values <- my_values[-1]
my_values <- paste0(my_values, my_units)
my_values <- sub("sql|idx", "", my_values)
my_index <- grep("weather_symbol", my_cols)
convert_weather_symbol <- function(x){
x <- as.numeric(x)
if(x >= 100){
x <- x - 100
}
my_code[as.character(x)]
}
my_values[my_index] <- sapply(my_values[my_index], convert_weather_symbol)
my_index <- grep("^sun", my_cols)
convert_datetime <- function(x, tz = my_tz){
x <- sub("T", " ", x)
x <- sub("Z", "", x)
x <- ymd_hms(x, tz = "UTC")
format_ISO8601(with_tz(x, tz), usetz = TRUE)
}
my_values[my_index] <- sapply(my_values[my_index], convert_datetime)
rbind(
c("Current time", format_ISO8601(with_tz(my_wanted_time, tzone = my_tz), usetz = TRUE)),
data.frame(variable = my_param_lookup[my_cols], value = my_values, row.names = NULL)
)
I have named the script get_weather.R, which you execute to get the weather info.
Current weather.
./get_weather.R
variable value
1 Current time 2022-03-17T22:55:57+0900
2 Temperature at 2m above ground 12.2C
3 Weather symbol of the past hour Rain
4 Weather symbol of the past 24 hours Rain shower
5 Wind speed at 10m above ground 6.7ms
6 wind direction at 10m above ground 63.3d
7 UV index 0
8 Mean sea level pressure 101909Pa
9 Precipitation over the past 24 hours 2.44mm
10 Sunrise 2022-03-17T05:49:00+0900
11 Sunset 2022-03-17T17:48:00+0900
Weather seven hours from now.
./get_weather.R 7
variable value
1 Current time 2022-03-18T05:56:43+0900
2 Temperature at 2m above ground 7.6C
3 Weather symbol of the past hour Cloudy
4 Weather symbol of the past 24 hours Rain shower
5 Wind speed at 10m above ground 8.6ms
6 wind direction at 10m above ground 43.4d
7 UV index 0
8 Mean sea level pressure 101982Pa
9 Precipitation over the past 24 hours 7.42mm
10 Sunrise 2022-03-17T05:49:00+0900
11 Sunset 2022-03-17T17:48:00+0900
And there you have it, finding out weather conditions from the command line!

This work is licensed under a Creative Commons
Attribution 4.0 International License.