Module netatmo

Netatmo API library to access the REST api.

This library implements the session management and makes it easy to access individual endpoints of the API.

To create a valid session, access and refresh tokens are required. This requires the user to login to the NetAtmo site and authorize the application. The library doesn't provide a full flow, but does provide the necessary functions to obtain the required tokens.

The get_authorization_url method will return the url to navigate to to start the OAuth2 flow. Once authorized on the NetAtmo site, it will redirect the users webbrowser to the callback_url provided when creating the session. This url should be handled by a webserver, and the authorize method should be called with the results from the callback url.

To manually obtain the tokens, without a webserver, use a callback_url that is certain to fail (the default will probably do). Then get the url using get_authorization_url and instruct the user to visit that url and authorize the application. Once authorized, the user will be redirected to the callback_url provided when creating the session. Since it is a bad URL the redirect will fail with an error in the browser. Instruct the user to collect the required informatiuon ("state" and "code" parameters) from the url-bar in the browser and use them to call the authorize method.

If you manually retrieved a refresh token, then it can be set by calling set_refresh_token.

The session can be kept alive using the keepalive method. At the time of writing access tokens have a validity of 10800 seconds (3 hours). Internally a clock-skew of 5 minutes is used, so the library considers the token to be expired 5 minutes before the actual expiration time.

Info:

  • Copyright: 2017-2023 Thijs Schreijer
  • Release: Version 0.2.0, Library to acces the Netatmo API
  • License: netatmo.lua is free software under the MIT/X11 license.
  • Author: Thijs Schreijer, https://www.thijsschreijer.nl

Tables

netatmo The module table containing some global settings and constants.

Generic functions

new (options) Creates a new Netatmo session instance.
request (path, method[, headers[, query[, body]]]) Performs a HTTP request on the Netatmo API.
rewrite_error ([expected=nil], ...) Rewrite errors to Lua format (nil+error).

Session management functions

authorize (state[, code]) Authorizes the session.
authorized () Check if the session has been authorized.
get_authorization_url () Gets the authorization url for the user to navigate to to start the OAuth2 flow.
keepalive ([delay_on_error=60]) Keeps the session alive.
logout () Logs out of the current session.
set_refresh_token (refresh_token) Sets the refresh token to use for the session.

API specific functions

get_modules_data ([device_id[, get_favorites=false[, no_warnings=false]]]) Gets device data, but returns by (sub)module instead of station.
get_stations_data ([device_id[, get_favorites=false[, no_warnings=false]]]) Gets device data.


Tables

netatmo
The module table containing some global settings and constants.

Fields:

  • https This is a function set on the module table, such that it can be overridden by another implementation (eg. Copas). The default implementation uses the LuaSec one (module ssl.htps).
  • log Logger is set on the module table, to be able to override it. Default is the LuaLogging default logger.
  • DEVICE_TYPES A lookup table to convert the type ID to a description. Eg. "NAModule4" -> "Additional indoor module".
  • ERR_MUST_AUTHORIZE Error message returned when a call is made without a valid session. This indicates the user must login (again) to authorize the application. See also authorized.
  • ERR_REFRESH_IN_PROGRESS Error message returned when a refresh is (possibly implict) attempted, but another refresh is already in progress. This is to prevent multiple refreshes from happening simultaneously. When this happens retry shortly after.

Generic functions

Functions for session management and instantiation
new (options)
Creates a new Netatmo session instance. Only OAuth2 grant_type supported is "authorization_code", for which the refresh-token is required. The refresh_token can be specified in the options table, or set later using the set_refresh_token method. The token can also be retreived by getting the callback url from get_authorization_url and after calling it, pass on the results to the authorize method.

Parameters:

  • options options table with the following options
    • client_id string the client_id to use for accessing the API
    • client_secret string the client_secret to use for accessing the API
    • refresh_token string the user provided refresh-token to use for accessing the API (optional)
    • scope array the scope(s) to use for accessing the API. Defaults to all read permissions. (optional)
    • persist function callback function called as function(session, refresh_token) whenever the refresh token is updated. This can be used to store the refresh token across restarts. NOTE: the refresh_token can be nil, in case of a logout. (optional)
    • callback_url string the OAuth2 callback url (default "https://localhost:54321")

Returns:

    netatmo session object

Usage:

    local netatmo = require "netatmo"
    
    local must_login = false
    local nasession = netatmo.new {
       client_id = "abcdef",
       client_secret = "xyz",
       scope = { "read_station", "read_thermostat" },
       callback_url = "https://localhost:54321/",  --> callback called with 'state' and 'code' parameters
    }
    user_url = nasession:get_authorization_url()   --> have user navigate to this url and authorize
    -- now authorize using the 'state' and 'code' parameters
    assert(nasession:authorize(state, code))
    
    local data, err = nasession:get_modules_data()
    if not data
      if err == netatmo.ERR_MUST_AUTHORIZE then
        -- tell user to login again, tokens expired for some reason
      end
      -- handle error
    end
request (path, method[, headers[, query[, body]]])
Performs a HTTP request on the Netatmo API. It will automatically inject authentication/session data. If the session has expired it will be renewed.

NOTE: if the response_body is json, then it will be decoded and returned as a Lua table.

Parameters:

  • path string the relative path within the API base path
  • method string HTTP method to use
  • headers table header table (optional)
  • query table query parameters (will be escaped) (optional)
  • body table or string if set the "Content-Length" will be added to the headers. If a table, it will be send as JSON, and the "Content-Type" header will be set to "application/json". (optional)

Returns:

    ok, response_body, response_code, response_headers, response_status_line or nil + err

Usage:

    local netatmo = require "netatmo"
    local nasession = netatmo.new {
       client_id = "abcdef",
       client_secret = "xyz",
       refresh_token = "123",
       scope = { "read_station", "read_thermostat" },
       callback_url = "https://localhost:54321/",
    }
    
    local headers = { ["My-Header"] = "myvalue" }
    local query = { ["param1"] = "value1" }
    
    local ok, response_body, status, headers, statusline = nasession:request("/api/attributes", "GET", headers, query, nil)
    if not ok then
      if response_body == netatmo.ERR_MUST_AUTHORIZE then
        -- tell user to login again, tokens expired for some reason
      end
      -- handle error
    end
rewrite_error ([expected=nil], ...)
Rewrite errors to Lua format (nil+error). Takes the output of the request function and validates it for errors;

  • nil+err
  • body with "error" field (json object)
  • mismatch in expected status code (a 200 expected, but a 404 received)

This reduces the error handling to standard Lua errors, instead of having to validate each of the situations above individually.

If the status code is a 401 or 403, then the access token will be cleared.

Parameters:

  • expected number expected status code, if nil, it will be ignored (default nil)
  • ... same parameters as the request method

Returns:

    nil+err or the input arguments

Usage:

    local netatmo = require "netatmo"
    local nasession = netatmo.new {
       client_id = "abcdef",
       client_secret = "xyz",
       refresh_token = "123",
       scope = { "read_station", "read_thermostat" },
       callback_url = "https://localhost:54321/",
    }
    
    -- Make a request where we expect a 200 result
    local ok, response_body, status, headers, statusline = nasession:rewrite_error(200, nasession:request("/some/thing", "GET"))
    if not ok then
      if response_body == netatmo.ERR_MUST_AUTHORIZE then
        -- tell user to login again, tokens expired for some reason
      end
      -- handle error
      -- a 404 will also follow this path now, since we only want 200's
    end

Session management functions

Functions for OAuth2 session management.
authorize (state[, code])
Authorizes the session. This method is called from the callback url, and should be provided with the state and code values from the callback url. It will fetch the initial tokens, resulting in an access and refresh token if successful. It can also be called with a single argument which is then the request(line) from the callback url. It will then extract the state and code values from the url.

Parameters:

  • state string the state value from the callback url, or the callback request, request-url including query args, or the first request line.
  • code string the code value from the callback url (required if state is not request-data) (optional)

Returns:

    true or nil + err (this function will never return the netatmo.ERR_MUST_AUTHORIZE error)
authorized ()
Check if the session has been authorized.

Returns:

    boolean true if authorized, false + netatmo.ERR_MUST_AUTHORIZE otherwise
get_authorization_url ()
Gets the authorization url for the user to navigate to to start the OAuth2 flow. The resulting "code" and "state" values from the callback url can be used to call the authorize method.

Returns:

    string the url to navigate to
keepalive ([delay_on_error=60])
Keeps the session alive. Keeps the session alive by refreshing the access token. If frequent calls are made, then the refresh should be automatic. If for long periods no calls are made, then this function can be used to keep the session alive.

Call this function in a loop, delaying each time by the returned number of seconds. It will only refresh the token if required (other calls can also refresh the token making an explicit refresh unnecessary).

Parameters:

  • delay_on_error number the number of seconds to delay when an error occurs (to prevent a busy loop). (default 60)

Returns:

    number of seconds to delay until the next call, or delay_on_error+err

Usage:

    local keepalive_thread = create_thread(function()
      while true do
        local delay, err = nasession:keepalive()
        sleep(delay)
      end
    end)
logout ()
Logs out of the current session. There is no real logout option with this API. Hence this only deletes the locally stored tokens. This will make any new calls fail, until the user logs in again.

Returns:

    true
set_refresh_token (refresh_token)
Sets the refresh token to use for the session.

Parameters:

  • refresh_token string the refresh token to use

API specific functions

This section contains functions that directly interact with the Netatmo API.
get_modules_data ([device_id[, get_favorites=false[, no_warnings=false]]])
Gets device data, but returns by (sub)module instead of station. The returned table is both an array of all modules, as well as a hash-table in which the same modules are indexed by their ID's for easy lookup.

Parameters:

  • device_id string the id (mac-address) of the station (optional)
  • get_favorites bool set to true to get the favorites (default false)
  • no_warnings bool set to true to skip generating warnings in the logs (default false)

Returns:

    module list, or nil+err

Usage:

    local netatmo = require "netatmo"
    local nasession = netatmo.new("abcdef", "xyz", "myself@nothere.com", "secret_password")
    local modules = nasession:get_modules_data()
    local module = modules["03:00:00:04:89:50"]
get_stations_data ([device_id[, get_favorites=false[, no_warnings=false]]])
Gets device data.

Parameters:

  • device_id string the id (mac-address) of the station (optional)
  • get_favorites bool set to true to get the favorites (default false)
  • no_warnings bool set to true to skip generating warnings in the logs (default false)

Returns:

    device list + full response, or nil+err

Usage:

    local netatmo = require "netatmo"
    local nasession = netatmo.new("abcdef", "xyz", "myself@nothere.com", "secret_password")
    local stations, full_response = nasession:get_stations_data()
generated by LDoc 1.4.6 Last updated 2023-10-12 21:28:41