defmodule GGSV2 do
use GenServer
require Logger
alias GGSV2.Comm
@default_polling_interval_ms 10_000
def start_link(init_arg \\ []) do
options = Keyword.take(init_arg, [:name])
GenServer.start_link(__MODULE__, init_arg, options)
end
def measure(pid) do
GenServer.call(pid, :measure)
end
@impl true
def init(options \\ []) do
# Sample options keyword list :
# [polling_interval: 10_000]
polling_interval = Keyword.get(options, :polling_interval, @default_polling_interval_ms)
:timer.send_interval(polling_interval, :measure)
Logger.info("Starting GGSV2 : Polling interval : #{polling_interval}")
state = %{
init_done: false,
options: options,
i2c: nil,
device_addr: nil,
last_reading: nil
}
{:ok, state}
end
defp deferred_init(%{init_done: false, options: options} = state) do
# Having a deferred init can help main application using this sensor
# to start event if the sensor has been removed.
{bus_name, device_addr} = Keyword.get(options, :transport, Comm.discover())
Logger.info("Starting (defered) GGSV2 on bus: #{bus_name}, address: #{device_addr} : ")
i2c = Comm.open(bus_name)
GGSV2.PREHEAT.activate(i2c, device_addr)
%{
state
| init_done: true,
i2c: i2c,
device_addr: device_addr
}
end
defp deferred_init(state) do
state
end
@impl true
def handle_info(
:measure,
state
) do
state = deferred_init(state)
%{i2c: i2c, device_addr: device_addr} = state
{:noreply,
%{
state
| last_reading: GGSV2.GAS.read_all(i2c, device_addr)
}}
end
@impl true
def handle_call(:measure, _from, state) do
{:reply, {:ok, state.last_reading}, state}
end
end