lib/tehama_client.ex

defmodule TehamaClient do
  @moduledoc """
  Documentation for `TehamaClient`.
  """

  @typedoc """
  A response which may be {:ok, results} or {:error, error}
  """
  @type response(t) :: {:ok, t} | {:error, any()}

  @doc """
  Create an auth for the client.

  ## Examples

      iex> TehamaClient.client("username", "password")
      {:ok, %TehamaClient.Auth{token: "testtoken"}}

  """
  @spec client(String.t(), String.t()) :: response(TehamaClient.Auth.t())
  def client(username, password) do
    TehamaClientApi.auth(username, password)
  end

  @doc """
  Create an auth for the client or fail.

  ## Examples

      iex> TehamaClient.client!("username", "password")
      %TehamaClient.Auth{token: "testtoken"}

  """
  @spec client!(String.t(), String.t()) :: TehamaClient.Auth.t()
  def client!(username, password) do
    case client(username, password) do
      {:ok, %TehamaClient.Auth{} = auth} -> auth
      error -> raise "error: #{inspect(error)}"
    end
  end

  @doc """
  Get Site List from API

  ## Examples

      iex> auth = TehamaClient.client!("username", "password")
      ...> {:ok, sites} = auth |> TehamaClient.site_list()
      ...> sites
      [%TehamaClient.Site{
        access_code: "88471391331",
        property_id: "4706362",
        name: "Elan Flower Mound #12294 (28667)",
        node_type: "DCAP"
      }] = sites
  """
  @spec site_list(%TehamaClient.Auth{token: String.t()}) :: response(list(TehamaClient.Site.t()))
  defdelegate site_list(auth), to: TehamaClientApi

  @doc """
  Create a temporary Site object to be used to get data

  ## Examples

      iex> TehamaClient.site("88471391331")
      %TehamaClient.Site{access_code: "88471391331"}

  """
  @spec site(String.t()) :: %TehamaClient.Site{access_code: String.t()}
  defdelegate site(access_code), to: TehamaClientApi

  @doc """
  Gets a list of units for a site.

  ## Examples

      iex> auth = %TehamaClient.Auth{token: "testtoken"}
      ...> site = %TehamaClient.Site{access_code: "88471391331"}
      ...> data = TehamaClient.units(auth, site)
      {:ok, [%TehamaClient.Unit{
        id: "5532",
        apt: "68",
        addr: "",
        building: "4706362",
        meters: []
      }]} = data
  """
  @spec units(
          %TehamaClient.Auth{token: String.t()},
          %TehamaClient.Site{access_code: String.t()}
        ) :: response(list(TehamaClient.Unit.t()))
  defdelegate units(auth, site), to: TehamaClientApi

  @doc """
  Get most recent read data.

  ## Examples

      iex> auth = %TehamaClient.Auth{token: "testtoken"}
      ...> site = %TehamaClient.Site{access_code: "88471391331"}
      ...> {:ok, data} = TehamaClient.report_data(auth, site)
      ...> data
      [%TehamaClient.Device{
        addr: "",
        apt: "68 ",
        battery_v: 3020,
        building: "1",
        latest_link_status_data_read_time: "2022-03-02 04:51:12",
        link_partner: "e3000a78",
        link_quality: 98,
        location_note: "Vacant",
        node_id: "5532",
        radio_dec_id: 2175922659,
        radio_hex_id: "81B1F1E3",
        readings: [
          %TehamaClient.Reading{
            alerts: [],
            display_type: "Encoded_Meter_1",
            factor: 10.0,
            initial_meter_read: 0,
            initial_meter_time: nil,
            mon_pt: nil,
            note: nil,
            raw: 47190,
            read_time: "2022-03-02 04:29:41",
            reading: 491900,
            sensor_type: "53",
            serial_number: "0000203389",
            style: "A",
            type: "W",
            units: nil
          }
        ]
      }]

  """
  @spec report_data(
          %TehamaClient.Auth{token: String.t()},
          %TehamaClient.Site{access_code: String.t()}
        ) :: response(list(TehamaClient.Device.t()))
  defdelegate report_data(auth, site), to: TehamaClientApi

  @doc """
  Get all read data between two dates.

  ## Examples

      iex> auth = %TehamaClient.Auth{token: "testtoken"}
      ...> site = %TehamaClient.Site{access_code: "88471391331"}
      ...> {:ok, data} = TehamaClient.report_data(auth, site, ~D[2022-05-01], ~D[2022-05-02])
      ...> data
      [%TehamaClient.Device{
        addr: "",
        apt: "68 ",
        battery_v: 3020,
        building: "1",
        latest_link_status_data_read_time: "2022-03-02 04:51:12",
        link_partner: "e3000a78",
        link_quality: 98,
        location_note: "Vacant",
        node_id: "5532",
        radio_dec_id: 2175922659,
        radio_hex_id: "81B1F1E3",
        readings: [
          %TehamaClient.Reading{
            alerts: [],
            display_type: "Encoded_Meter_1",
            factor: 10.0,
            initial_meter_read: 0,
            initial_meter_time: nil,
            mon_pt: nil,
            note: nil,
            raw: 47190,
            read_time: "2022-03-02 04:29:41",
            reading: 491900,
            sensor_type: "53",
            serial_number: "0000203389",
            style: "A",
            type: "W",
            units: nil
          }
        ]
      }]

  """
  @spec report_data(
          %TehamaClient.Auth{token: String.t()},
          %TehamaClient.Site{access_code: String.t()},
          Date.t(),
          Date.t()
        ) :: response(list(TehamaClient.Device.t()))
  defdelegate report_data(auth, site, start_time, end_time), to: TehamaClientApi
end