defmodule SHT4X do
@moduledoc """
Use Sensirion SHT4X humidity and temperature sensors in Elixir
"""
use GenServer
require Logger
@type options() :: [GenServer.option() | {:bus_name, bus_name}]
@typedoc """
Which I2C bus to use (defaults to `"i2c-1"`)
"""
@type bus_name :: binary
@default_bus_name "i2c-1"
@bus_address 0x44
@spec start_link(options()) :: GenServer.on_start()
def start_link(init_arg \\ []) do
gen_server_opts =
Keyword.take(init_arg, [:name, :debug, :timeout, :spawn_opt, :hibernate_after])
GenServer.start_link(__MODULE__, init_arg, gen_server_opts)
end
@spec measure(GenServer.server(), Keyword.t()) :: {:ok, SHT4X.Measurement.t()} | {:error, any}
def measure(server, opts \\ []) do
GenServer.call(server, {:measure, opts})
end
@impl GenServer
def init(init_arg) do
bus_name = init_arg[:bus_name] || @default_bus_name
bus_address = @bus_address
Logger.info(
"[SHT4X] Starting on bus #{bus_name} at address #{inspect(bus_address, base: :hex)}"
)
transport = SHT4X.Transport.new(bus_name, bus_address)
case SHT4X.Comm.serial_number(transport) do
{:ok, serial_number} ->
Logger.info("[SHT4X] Initializing sensor #{serial_number}")
state = %{
serial_number: serial_number,
transport: transport
}
{:ok, state}
_error ->
{:stop, "Error connecting to the sensor"}
end
end
@impl GenServer
def handle_call({:measure, opts}, _from, state) do
{:ok, data} = SHT4X.Comm.measure(state.transport, opts)
{:reply, {:ok, SHT4X.Measurement.from_raw(data)}, state}
end
end