FritzApi
Fritz!Box Home Automation API Client for Elixir (documentation).
Usage
iex> {:ok, client} = FritzApi.Client.new()
...> |> FritzApi.Client.login("admin", "changeme")
iex> FritzApi.get_device_list_infos(client)
{:ok, [%FritzApi.Actor{
ain: "687690315761",
fwversion: "03.87",
id: 21,
manufacturer: "AVM",
name: "FRITZ!DECT #1",
powermeter: %{energy: 0.475, power: 0.0},
present: true,
productname: "FRITZ!DECT 200",
switch: %{
devicelock: false,
lock: false,
mode: :manual,
state: false
},
temperature: %{
celsius: 23.5,
offset: 0.0
}
}]}
iex> FritzApi.set_switch_off(client, "687690315761")
:ok
iex> FritzApi.get_temperature(client, "687690315761")
{:ok, 23.5}Example: Automatic Session Refresh
defmodule Switch do
use GenServer
defmodule State do
@derive {Inspect, except: [:password]}
defstruct [:username, :password, :ain, :client]
end
def start_link(opts) do
GenServer.start_link(__MODULE__, opts)
end
def turn_on, do: GenServer.call(__MODULE__, :turn_on)
def turn_off, do: GenServer.call(__MODULE__, :turn_off)
@impl true
def init(opts) do
client =
FritzApi.Client.new(
base_url: opts[:host],
receive_timeout: :timer.seconds(30)
)
state = %State{
username: Keyword.fetch!(opts, :username),
password: Keyword.fetch!(opts, :password),
ain: Keyword.fetch!(opts, :ain),
client: client
}
{:ok, state, {:continue, :login}}
end
@impl true
def handle_continue(:login, %State{} = state) do
{:ok, client} = FritzApi.Client.login(state.client, state.username, state.password)
{:noreply, %State{state | client: client}}
end
@impl true
def handle_call(:turn_on, _from, %State{} = state) do
{result, state} = refresh_session(&FritzApi.set_switch_on(&1, state.ain), state)
{:reply, result, state}
end
def handle_call(:turn_off, _from, %State{} = state) do
{result, state} = refresh_session(&FritzApi.set_switch_off(&1, state.ain), state)
{:reply, result, state}
end
defp refresh_session(fun, %State{} = state) do
with {:error, %FritzApi.Error{reason: :session_expired}} <- fun.(state.client),
{:ok, client} <- FritzApi.Client.login(state.client, state.username, state.password) do
{fun.(client), %State{state | client: client}}
else
result -> {result, state}
end
end
endiex> {:ok, pid} = Switch.start_link(username: "admin", password: "admin", ain: "000111222333")
iex> Switch.turn_on(pid)
:okInstallation
Add fritz_api to your list of dependencies in mix.exs:
def deps do
[
{:fritz_api, "~> 2.0"},
{:hackney, "~> 1.17"}
]
end
By default, fritz_api uses hackney (via Tesla.Adapter.Hackney). Add hackney to the list of dependencies too if you don't want to use another HTTP adapter (see Tesla Adapters to find all available adapters and FritzApi.Client.new/1 on how to configure another adapter).
The docs can be found at hexdocs.pm/fritz_api.