fix tranport crashes causing app crash

pull/363/head
connor rigby 2017-11-08 11:10:28 -08:00
parent 4e207092e8
commit a86e986a1d
12 changed files with 73 additions and 26 deletions

View File

@ -6,8 +6,10 @@ env = Mix.env()
config :logger,
utc_log: true,
# handle_otp_reports: true,
# handle_sasl_reports: true,
backends: []
config :elixir, ansi_enabled: true
config :iex, :colors, enabled: true

View File

@ -35,6 +35,7 @@ end
config :farmbot, Farmbot.System.ConfigStorage,
adapter: Sqlite.Ecto2,
loggers: [],
database: "tmp/#{Farmbot.System.ConfigStorage}_dev.sqlite3"
# Configure Farmbot Behaviours.
@ -42,7 +43,7 @@ config :farmbot, Farmbot.System.ConfigStorage,
# SystemTasks for host mode.
config :farmbot, :behaviour,
authorization: Farmbot.Bootstrap.Authorization,
system_tasks: Farmbot.Host.SystemTasks
# firmware_handler: Farmbot.Firmware.UartHandler
system_tasks: Farmbot.Host.SystemTasks,
firmware_handler: Farmbot.Firmware.UartHandler
config :farmbot, :uart_handler, tty: "/dev/ttyACM0"

View File

@ -122,13 +122,15 @@ defmodule Farmbot.Bootstrap.Supervisor do
children = [
worker(Farmbot.Bootstrap.AuthTask, []),
supervisor(Farmbot.Firmware.Supervisor, []),
supervisor(Farmbot.BotState.Supervisor, []),
supervisor(Farmbot.BotState.Transport.Supervisor, []),
supervisor(Farmbot.HTTP.Supervisor, []),
supervisor(Farmbot.Repo.Supervisor, []),
supervisor(Farmbot.Farmware.Supervisor, [])
]
opts = [strategy: :one_for_all]
opts = [strategy: :one_for_one]
supervise(children, opts)
# I don't actually _have_ to factory reset here. It would get detected ad

View File

@ -55,7 +55,8 @@ defmodule Farmbot.BotState do
{
:producer_consumer,
struct(__MODULE__, configuration: Farmbot.System.ConfigStorage.get_config_as_map()["settings"]),
subscribe_to: [Farmbot.Firmware, Farmbot.System.ConfigStorage.Dispatcher], dispatcher: GenStage.BroadcastDispatcher
subscribe_to: [Farmbot.Firmware, Farmbot.System.ConfigStorage.Dispatcher],
dispatcher: GenStage.BroadcastDispatcher
}
end

View File

@ -9,9 +9,7 @@ defmodule Farmbot.BotState.Supervisor do
def init([]) do
children = [
supervisor(Farmbot.Firmware.Supervisor, []),
worker(Farmbot.BotState, []),
supervisor(Farmbot.BotState.Transport.Supervisor, [])
]
supervise(children, strategy: :one_for_one)

View File

@ -14,9 +14,19 @@ defmodule Farmbot.BotState.Transport.GenMQTT do
token = Farmbot.System.ConfigStorage.get_config_value(:string, "authorization", "token")
{:ok, %{bot: device, mqtt: mqtt_server}} = Farmbot.Jwt.decode(token)
{:ok, client} = Client.start_link(device, token, mqtt_server)
Process.flag(:trap_exit, true)
{:consumer, {%{client: client}, nil}, subscribe_to: [Farmbot.BotState, Farmbot.Logger]}
end
def handle_info({:EXIT, _, error}, {state, bot_state}) do
Logger.error 1, "MQTT Client died: #{inspect error}"
token = Farmbot.System.ConfigStorage.get_config_value(:string, "authorization", "token")
{:ok, %{bot: device, mqtt: mqtt_server}} = Farmbot.Jwt.decode(token)
{:ok, client} = Client.start_link(device, token, mqtt_server)
new_state = %{state | client: client}
{:noreply, [], {new_state, bot_state}}
end
def handle_events(events, {pid, _}, state) do
case Process.info(pid)[:registered_name] do
Farmbot.Logger -> handle_log_events(events, state)

View File

@ -43,10 +43,18 @@ defmodule Farmbot.BotState.Transport.HTTP do
s = Farmbot.System.ConfigStorage.get_config_value(:string, "authorization", "server")
{:ok, {_, _, body}} = :httpc.request(:get, {'#{s}/api/public_key', []}, [], [body_format: :binary])
public_key = body |> JOSE.JWK.from_pem
state = %{bot_state: nil, sockets: [], public_key: public_key}
{:ok, web} = Plug.Adapters.Cowboy.http Router, [], [port: @port, dispatch: [cowboy_dispatch()]]
Process.link(web)
{:consumer, state, [subscribe_to: [Farmbot.BotState, Farmbot.Logger]]}
# FIXME(Connor) The router should probably be put in an externally supervised module..
case Plug.Adapters.Cowboy.http Router, [], [port: @port, dispatch: [cowboy_dispatch()]] do
{:ok, web} ->
state = %{web: web, bot_state: nil, sockets: [], public_key: public_key}
Process.link(state.web)
{:consumer, state, [subscribe_to: [Farmbot.BotState, Farmbot.Logger]]}
{:error, {:already_started, web}} ->
state = %{web: web, bot_state: nil, sockets: [], public_key: public_key}
Process.link(state.web)
{:consumer, state, [subscribe_to: [Farmbot.BotState, Farmbot.Logger]]}
err -> err
end
end
def handle_events(events, {pid, _}, state) do

View File

@ -8,9 +8,9 @@ defmodule Farmbot.BotState.Transport.Supervisor do
end
def init([]) do
:farmbot
|> Application.get_env(:transport)
|> Enum.map(&worker(&1, []))
|> supervise(strategy: :one_for_one)
children = Application.get_env(:farmbot, :transport) |> Enum.map(&worker(&1, []))
supervise(children, strategy: :one_for_one)
end
end

View File

@ -81,7 +81,7 @@ defmodule Farmbot.Firmware do
Application.get_env(:farmbot, :behaviour)[:firmware_handler] || raise("No fw handler.")
{:ok, handler} = handler_mod.start_link()
Process.link(handler)
Process.flag(:trap_exit, true)
{
:producer_consumer,
@ -98,6 +98,7 @@ defmodule Farmbot.Firmware do
{:error, _} = res -> res
end
{:reply, res, [], state}
end
@ -106,6 +107,13 @@ defmodule Farmbot.Firmware do
{:noreply, diffs, state}
end
def handle_info({:EXIT, _, reason}, state) do
Logger.error 1, "Firmware handler: #{state.handler_mod} died: #{inspect reason}"
{:ok, handler} = state.handler_mod.start_link()
new_state = %{state | handler: handler}
{:noreply, [], new_state}
end
defp handle_gcodes(codes, state, acc \\ [])
defp handle_gcodes([], state, acc), do: {Enum.reverse(acc), state}

View File

@ -59,9 +59,16 @@ defmodule Farmbot.Firmware.Gcode.Parser do
["P" <> parm, "V" <> val, "Q" <> tag] = String.split(params, " ")
if parm in ["141", "142", "143"] do
uh = :report_axis_calibration
msg = {uh, parse_param(parm), String.to_integer(val)}
{tag, msg}
parm_name = :report_axis_calibration
result = parse_param(parm)
case Float.parse(val) do
{float, _} ->
msg = {parm_name, result, float}
{tag, msg}
:error ->
msg = {parm_name, result, String.to_integer(val)}
{tag, msg}
end
else
{tag, :noop}
end

View File

@ -3,8 +3,8 @@ defmodule Farmbot.Firmware.Supervisor do
use Supervisor
@doc false
def start_link(opts \\ []) do
Supervisor.start_link(__MODULE__, [], opts)
def start_link() do
Supervisor.start_link(__MODULE__, [], [name: __MODULE__])
end
def init([]) do

View File

@ -6,20 +6,21 @@ defmodule Farmbot.Firmware.UartHandler do
use GenStage
alias Nerves.UART
use Farmbot.Logger
@behaviour Farmbot.Firmware.Handler
def start_link do
GenStage.start_link(__MODULE__, [])
end
def move_absolute(handler, pos, axis, speed) do
GenStage.call(handler, {:move_absolute, pos, axis, speed})
def move_absolute(handler, pos, speed) do
GenStage.call(handler, {:move_absolute, pos, speed})
end
def calibrate(handler, axis, axis, speed) do
def calibrate(handler, axis, speed) do
GenStage.call(handler, {:calibrate, axis, speed})
end
def find_home(handler, axis, axis, speed) do
def find_home(handler, axis, speed) do
GenStage.call(handler, {:find_home, axis, speed})
end
@ -27,7 +28,7 @@ defmodule Farmbot.Firmware.UartHandler do
GenStage.call(handler, {:home, axis, speed})
end
def zero(handler, axis, axis, speed) do
def zero(handler, axis, speed) do
GenStage.call(handler, {:zero, axis, speed})
end
@ -123,6 +124,15 @@ defmodule Farmbot.Firmware.UartHandler do
{:noreply, [], state}
end
def handle_call({:move_absolute, pos, speed}, _from, state) do
UART.write(state.nerves, "G00 X#{pos.x} Y#{pos.y} Z#{pos.z} A#{speed} B#{speed} C#{speed}")
{:noreply, [], state}
end
def handle_call(_call, _from, state) do
{:reply, {:error, :bad_call}, [], state}
end
def handle_demand(_amnt, state) do
do_dispatch(state.codes, state)
end