-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME.Rmd
199 lines (139 loc) · 7.1 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
---
output: github_document
---
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```
# netatmo.weather
The goal of netatmo.weather is to provide access to Netatmo measurements and station metadata making use of the Netatmo Weather API.
## Installation
You can install the development version of netatmo.weather with:
``` r
# install.packages("devtools")
devtools::install_github("dimfalk/netatmo.weather")
```
and load the package via
```{r}
library(netatmo.weather)
```
## Getting Started
### Authentication
In order to be able to access data, please follow the subsequent steps:
1) Register a user account at [auth.netatmo.com](https://auth.netatmo.com/access/signup) and login at [dev.netatmo.com](https://auth.netatmo.com/de-de/access/login?next_url=https%3A%2F%2Fdev.netatmo.com%2F).
2) Click on your username in the upper right corner and create a new application. Provide mandatory information (*) and save.
3) Credentials will be stored making use of `{keyring}`. In order to securely encrypt your secrets stored, it is necessary to define a vault password in your user-level `.Renviron`, which can be edited via `file.edit("~/.Renviron")` or by running `usethis::edit_r_environ()`. Create a new environment variable called `KEYRING_PASSWORD`.
The new line added now looks something like `KEYRING_PASSWORD = "<insert_your_strong_password_here_123!>"`. You can also create a password using e.g. `{sodium}` with `keygen() |> bin2hex()`. Restart R to see changes. Eventually inspect the key (privately) via `Sys.getenv("KEYRING_PASSWORD")`.
4) Run `set_credentials()` and copy & paste the information necessary (id/secret), as supplied in 2) .
``` r
set_credentials()
#> Note: Keyring 'netatmo' successfully created.
```
5) Run `fetch_token()` to cache Oauth 2.0 access credentials based on the specifications provided in 4). When asked, whether you want to use a local file to cache OAuth access credentials between R sessions, choose "1: Yes". You'll be redirected to your browser to grant access to your application. Accept and close the browser tab.
```{r, message = FALSE}
fetch_token()
#> Note: OAuth 2.0 access credentials successfully cached in file `.httr-oauth`.
```
Successful authentication is confirmed in the browser. Your token is now stored to disk as `.httr-oauth` in your working directory.
In case you wanted to execute **/getpublicdata** and **/getmeasure** API calls from your browser (for debugging reasons or whatever), you'll need to append your access token to your URL: `"&access_token=xxx"`. You'll also be notified if you try to execute requests with your access token missing.
You can access your tokens consisting of a key and secret making use of little helpers provided:
``` r
print_at()
#> "&access_token=62361e03ca18e13802546z20|5dt2091f1693dbff35f0428f2386b492"
print_rt()
#> "&refresh_token=62361e03ca18e13802546z20|6ce2fb2490a615d58b16e874fz4eb579"
```
Tokens expire after 3 hours and have to be refreshed again in order to be used. `{netatmo.weather}` does so in the background automatically without the user noticing. But if you're using your access token in a browser session temporarily, make use of these little helpers provided:
``` r
is_expired()
#> TRUE
refresh_at()
#> <Token>
#> <oauth_endpoint>
#> authorize: https://api.netatmo.net/oauth2/authorize
#> access: https://api.netatmo.net/oauth2/token
#> <oauth_app> netatmo.weather
#> key: 62361e03ca18e13802546z20
#> secret: <hidden>
#> <credentials> scope, access_token, expires_in, expire_in, refresh_token
is_expired()
#> FALSE
```
### /getpublicdata
Queries via `get_publicdata()` to obtain station locations and metadata require a user-defined bounding box as the main function argument. In order to facilitate this, `get_extent()` was implemented to help you out:
```{r}
# using coordinates (xmin, ymin, xmax, ymax)
e1 <- get_extent(c(6.89, 51.34, 7.13, 51.53), crs = "epsg:4326")
e1
# using municipality names
e2 <- get_extent("Essen")
e2
# using postal codes
e3 <- get_extent("45145")
e3
```
This information can now be used to list stations located in this area (at the time of the query):
```{r}
stations <- get_publicdata(ext = e1)
stations
```
However, since the number of stations returned by **/getpublicdata** seems to be influenced by the size of the area queried, the logical argument `tiles` was implemented, slicing your area of interest in tiles à 0.05 degrees per default to be queried separately in order to ensure the maximum number of available stations.
```{r, message = FALSE}
stations_tiles <- get_publicdata(ext = e1, tiles = TRUE)
#> /getpublicdata: Fetching stations from the following area: 6.89, 51.34, 7.13, 51.53 ...
stations_tiles
```
### /getmeasure
Queries via `get_measure()` to obtain station observations basically require a base station MAC address to be queried (included in `stations` returned by `get_publicdata()`), the parameter to be queried (e.g. `temperature`, `humudity`, `sum_rain`, `...`), the measurement interval in minutes (e.g. `5`, `30`, `60`) and a period encompassing the timestamp of the first and last observation to retrieve in form of UNIX time (seconds since 1970-01-01 00:00 UTC).
To assist you with the latter going backwards from `lubridate::now("UTC")`, `get_period()` exists:
```{r}
# per default (with x = NULL) returning the maximum number of observations (1024) as a function of `res` chosen
# 5-minutely data
p1 <- get_period(res = 5)
as.POSIXct(p1, tz = "UTC")
# hourly data
p2 <- get_period(res = 60)
as.POSIXct(p2, tz = "UTC")
# querying the last 24 hours, maybe convenient for scheduled jobs
p3 <- get_period("recent")
as.POSIXct(p3, tz = "UTC")
# self-defined periods
p4 <- get_period("2024-03-01/2024-04-01")
as.POSIXct(p4, tz = "UTC")
p5 <- get_period("2024-03-01 18:00/2024-03-15 18:00")
as.POSIXct(p5, tz = "UTC")
```
Just to ensure you do not run into HTTP 429 because of API guideline violations, you can use another little helper in advance to make sure the number of your requests fired does not exceed 500 at one time.
```{r}
# 10 stations, hourly data
get_n_queries(d = 10, res = 60, p = p4)
# 20 stations, 5-minutely data
get_n_queries(d = 20, res = 5, p = p5)
```
This last piece of information can now be used to finally acquire observations (iterating over previously identified stations) in form of listed `xts` objects. This might take some time to finish.
```{r, message = FALSE}
# get subset of data for demonstration purposes
obs <- get_measure(devices = stations_tiles[1:10, ],
period = p2,
par = "temperature",
res = 60)
#> /getmeasure: Fetching temperature measurements (60 min) from 2024-02-26 07:00 UTC to 2024-04-08 23:00 UTC for 10 station(s) ...
class(obs)
length(obs)
names(obs)
# subset to individual xts object
xts <- obs[[1]]
class(xts)
# inspect index range
zoo::index(xts) |> range()
# inspect index/coredata
head(xts)
# inspect attribute names appended
attributes(xts) |> names() |> tail(-4)
plot(xts, main = "hourly air temperatures", col = "red")
```