lib/led_strip_driver/logger_driver.ex

defmodule Fledex.LedStripDriver.LoggerDriver do
  @behaviour Fledex.LedStripDriver.Driver
  use Fledex.Color.Types

  alias Fledex.Color.Utils

  @default_update_freq 10
  @divisor 255/5
  @block <<"\u2588">>

  @moduledoc """
    This is a dummy implementation of the LedStripDriver that dumps
    the binaries to IO. This can be useful if you want to run
    some tests without real hardware.
    The real implementatin probably opens a channel (if not already open)
    to the bus (like SPI) sends the data to the bus.

    Note: this module is allowed to store information in the state
    (like the channel it has oppened), so that we don't have open/close it
    all the time. Cleanup should happen in the terminate function
  """
  @impl true
  @spec init(map) :: map
  def init(init_module_args) do
    %{
      update_freq: init_module_args[:update_freq] || @default_update_freq,
      log_color_code: init_module_args[:log_color_code] || false
    }
  end

  @impl true
  @spec transfer(list(colorint), pos_integer, map) :: map
  def transfer(leds, counter, config) do
    if (rem(counter, config.update_freq) == 0 and length(leds) > 0) do
      log_color_code = config.log_color_code
      output = Enum.reduce(leds, <<>>, fn value, acc ->
        if log_color_code do
          acc <> <<value>>
        else
          acc <> to_ansi_color(value) <> @block
        end
      end)
      IO.puts(output <> "\r")
    end
    config
  end

  @spec to_ansi_color(colorint) :: String.t
  defp to_ansi_color(value) do
    {r,g,b} = Utils.split_into_subpixels(value)
    IO.ANSI.color(trunc(r/@divisor), trunc(g/@divisor), trunc(b/@divisor))
  end

  @impl true
  @spec terminate(reason, map) :: :ok when reason: :normal | :shutdown | {:shutdown, term()} | term()
  def terminate(_reason, _state) do
    # nothing needs to be done here
    :ok
  end
end