Current section
Files
Jump to
Current section
Files
lib/firmware_simulator.ex
defmodule FirmwareSimulator do
@moduledoc """
Simulates farmbot-arduino-firmware
"""
use GenServer
require Logger
alias Nerves.UART
@tty "/dev/tnt0"
def start_link do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
def init([]) do
Logger.info "Starting Firmware Simulator"
{:ok, nerves} = UART.start_link()
{:ok, param_handler} = Firmware.ParamaterHandler.start_link()
{:ok, pos_handler} = Firmware.PositionHandler.start_link()
{:ok, pin_handler} = Firmware.PinHandler.start_link()
:ok = UART.open(nerves, @tty,
[active: true, speed: 115200,
framing: {Nerves.UART.Framing.Line, separator: "\r\n"}
])
{:ok, %{
nerves: nerves,
param_handler: param_handler,
position_handler: pos_handler,
pin_handler: pin_handler
}}
end
def handle_info({:nerves_uart, @tty, str}, state) do
cmd = String.split(str, " ")
qcode = find_qcode(cmd)
do_write(state.nerves, "R01 #{qcode}")
reply = Firmware.CodeHandler.handle_code(cmd)
case reply do
# if we just have one binary, write it.
blerp when is_binary(blerp) ->
:ok = do_write(state.nerves, blerp)
# if we have a list of binaries, write them sequentially
flerp when is_list(flerp) ->
do_write_multi(state.nerves, flerp)
# not doing anything is fine too.
:noreply -> :ok
# if no handler for this code, warn.
nil ->
Logger.warn("unhandled command: #{str}")
end
do_write(state.nerves, "R02 #{qcode}")
{:noreply, state}
end
def handle_info(info, state) do
Logger.info("Got unhandled info: #{inspect info}")
{:noreply, state}
end
def handle_call({:write, str}, _, state) do
:ok = do_write(state.nerves, str)
{:reply, :ok, state}
end
def terminate(_reason, state) do
UART.stop(state.nerves)
end
@spec do_write(pid, binary) :: :ok | {:error, term}
defp do_write(nerves, str), do: UART.write(nerves, str)
@spec do_write_multi(pid, [binary]) :: :ok | no_return
defp do_write_multi(_, []), do: :ok
defp do_write_multi(nerves, [str | rest]) do
:ok = do_write(nerves, str)
Process.sleep(100)
do_write_multi(nerves, rest)
end
defp find_qcode([]), do: "Q69"
defp find_qcode([head | tail]) do
case head do
"Q" <> _code -> head
_ -> find_qcode(tail)
end
end
def write(str) do
GenServer.call(__MODULE__, {:write, str})
end
def stop(reason \\ :normal) do
GenServer.stop(__MODULE__, reason)
end
end