lib/gas.ex

defmodule GGSV2.GAS do
  alias GGSV2.I2C
  alias GGSV2.Measurement

  # GM102B sensor
  @read_no2_reg [0x01]
  # GM302B sensor
  @read_c2h5ch_reg [0x03]
  # GM502B sensor
  @read_voc_reg [0x05]
  # GM702B sensor
  @read_co_reg [0x07]

  def read_no2(i2c, device_addr), do: read(i2c, device_addr, @read_no2_reg)
  def read_c2h5ch(i2c, device_addr), do: read(i2c, device_addr, @read_c2h5ch_reg)
  def read_voc(i2c, device_addr), do: read(i2c, device_addr, @read_voc_reg)
  def read_co(i2c, device_addr), do: read(i2c, device_addr, @read_co_reg)

  @spec read_all(reference, byte) :: GGSV2.Measurement.t()
  def read_all(i2c, device_addr) do
    %Measurement{
      no2_ppm: read_no2(i2c, device_addr),
      c2h5ch_ppm: read_c2h5ch(i2c, device_addr),
      voc_ppm: read_voc(i2c, device_addr),
      co_ppm: read_voc(i2c, device_addr)
    }
  end

  defp read(i2c, device_addr, reg_addr) do
    case I2C.write_read(i2c, device_addr, reg_addr, 4) do
      {:ok, data} -> data |> decode()
      _ -> :error
    end
  end

  defp decode(<<value_byte1::8, value_byte2::8, value_byte3::8, value_byte4::8>>) do
    <<value::little-unsigned-size(32)>> = <<value_byte1, value_byte2, value_byte3, value_byte4>>

    value
  end
end