Merge branch 'error_codes' of github.com:FarmBot/farmbot_os into firmware_fix

pull/1154/head
Rick Carlino 2020-02-17 18:03:02 -06:00
commit 23f668a321
7 changed files with 131 additions and 22 deletions

View File

@ -31,6 +31,36 @@ defmodule FarmbotCore.FirmwareSideEffects do
:noop :noop
end end
@impl FarmbotFirmware.SideEffects
def handle_stall_detected() do
FarmbotCore.Logger.error(1, "Movement failed: stall detected")
:noop
end
@impl FarmbotFirmware.SideEffects
def handle_calibration_error() do
FarmbotCore.Logger.error(1, "Calibration failed")
:noop
end
@impl FarmbotFirmware.SideEffects
def handle_invalid_command() do
FarmbotCore.Logger.error(1, "Invalid command")
:noop
end
@impl FarmbotFirmware.SideEffects
def handle_no_configuration() do
FarmbotCore.Logger.error(1, "No configuration")
:noop
end
@impl FarmbotFirmware.SideEffects
def handle_unknown_error(err) do
FarmbotCore.Logger.error(1, "Unknown error: #{inspect(err)}")
:noop
end
@impl FarmbotFirmware.SideEffects @impl FarmbotFirmware.SideEffects
def handle_home_complete(_) do def handle_home_complete(_) do
:noop :noop

View File

@ -729,6 +729,51 @@ defmodule FarmbotFirmware do
{:noreply, goto(state, :busy)} {:noreply, goto(state, :busy)}
end end
def handle_report({:report_error, [:no_error]}, state) do
Logger.error("Error: no error")
handle_report({:report_error, []}, state)
end
def handle_report({:report_error, [:emergency_lock]}, state) do
Logger.error("Error: emergency lock")
handle_report({:report_error, []}, state)
end
def handle_report({:report_error, [:timeout]}, state) do
Logger.error("Error: timeout")
handle_report({:report_error, []}, state)
end
def handle_report({:report_error, [:stall_detected]}, state) do
Logger.error("Error: stall detected")
side_effects(state, :handle_stall_detected, [])
handle_report({:report_error, []}, state)
end
def handle_report({:report_error, [:calibration_error]}, state) do
Logger.error("Error: calibration error")
side_effects(state, :handle_calibration_error, [])
handle_report({:report_error, []}, state)
end
def handle_report({:report_error, [:invalid_command]}, state) do
Logger.error("Error: invalid command")
side_effects(state, :handle_invalid_command, [])
handle_report({:report_error, []}, state)
end
def handle_report({:report_error, [:no_config]}, state) do
Logger.error("Error: no configuration")
side_effects(state, :handle_no_configuration, [])
handle_report({:report_error, []}, state)
end
def handle_report({:report_error, [unk]}, state) do
Logger.error("Error: #{inspect(unk)}")
side_effects(state, :handle_unknown_error, [unk])
handle_report({:report_error, []}, state)
end
def handle_report( def handle_report(
{:report_error, _} = code, {:report_error, _} = code,
%{status: :configuration} = state %{status: :configuration} = state

View File

@ -49,9 +49,14 @@ defmodule FarmbotFirmware.Command do
debug_log("#{GCODE.encode(code)} position change") debug_log("#{GCODE.encode(code)} position change")
wait_for_command_result(tag, code, retries, error) wait_for_command_result(tag, code, retries, error)
{_, {:report_error, _}} -> {_, {:report_error, [error_code]}} ->
debug_log("#{GCODE.encode(code)} firmware error") if err do
if err, do: {:error, err}, else: {:error, :firmware_error} debug_log("#{GCODE.encode(code)} error: #{inspect(err)}")
{:error, err}
else
debug_log("#{GCODE.encode(code)} #{inspect(error_code)}")
{:error, "firmware error: #{inspect(error_code)}"}
end
{_, {:report_invalid, []}} -> {_, {:report_invalid, []}} ->
debug_log("#{GCODE.encode(code)} invalid command") debug_log("#{GCODE.encode(code)} invalid command")

View File

@ -9,7 +9,7 @@ defmodule FarmbotFirmware.GCODE.Decoder do
def do_decode("R01", []), do: {:report_begin, []} def do_decode("R01", []), do: {:report_begin, []}
def do_decode("R02", []), do: {:report_success, []} def do_decode("R02", []), do: {:report_success, []}
def do_decode("R03", []), do: {:report_error, [:no_error]} def do_decode("R03", []), do: {:report_error, [:no_error]}
def do_decode("R03", error), do: {:report_error, decode_error(error)} def do_decode("R03", v), do: {:report_error, decode_v(v)}
def do_decode("R04", []), do: {:report_busy, []} def do_decode("R04", []), do: {:report_busy, []}
def do_decode("R05", xyz), do: {:report_axis_state, decode_axis_state(xyz)} def do_decode("R05", xyz), do: {:report_axis_state, decode_axis_state(xyz)}
@ -99,17 +99,20 @@ defmodule FarmbotFirmware.GCODE.Decoder do
{:unknown, [kind | args]} {:unknown, [kind | args]}
end end
def decode_error(["V0"]), do: [:no_error] def decode_v(["V" <> value]) do
def decode_error(["V1"]), do: [:emergency_lock] {value, ""} = Float.parse(value)
def decode_error(["V2"]), do: [:timeout]
def decode_error(["V3"]), do: [:stall_detected] case value do
def decode_error(["V14"]), do: [:invalid_command] 0.0 -> [:no_error]
def decode_error(["V15"]), do: [:no_config] 1.0 -> [:emergency_lock]
def decode_error([unk]), do: [unknown_error: unk] 2.0 -> [:timeout]
# TODO(Rick): This is a guess. Can be removed if 3.0 -> [:stall_detected]
# better solution is found. 4.0 -> [:calibration_error]
# FarmBot/farmbot_os/issues/1105#issuecomment-572381069 14.0 -> [:invalid_command]
def decode_error(unk), do: [unknown_error: [unk]] 15.0 -> [:no_config]
unk -> [unknown_error: unk]
end
end
defp decode_floats(list, acc \\ []) defp decode_floats(list, acc \\ [])

View File

@ -8,10 +8,8 @@ defmodule FarmbotFirmware.GCODE.Encoder do
def do_encode(:report_idle, []), do: "R00" def do_encode(:report_idle, []), do: "R00"
def do_encode(:report_begin, []), do: "R01" def do_encode(:report_begin, []), do: "R01"
def do_encode(:report_success, []), do: "R02" def do_encode(:report_success, []), do: "R02"
# TODO(Rick): Why are some `:report_error`s sending def do_encode(:report_error, []), do: "R03"
# tuples instead of lists?? def do_encode(:report_error, error), do: "R03 " <> encode_error(error)
# https://github.com/FarmBot/farmbot_os/issues/1105#issuecomment-572381069
def do_encode(:report_error, _), do: "R03"
def do_encode(:report_busy, []), do: "R04" def do_encode(:report_busy, []), do: "R04"
def do_encode(:report_axis_state, xyz), do: "R05 " <> encode_axis_state(xyz) def do_encode(:report_axis_state, xyz), do: "R05 " <> encode_axis_state(xyz)
@ -158,6 +156,19 @@ defmodule FarmbotFirmware.GCODE.Encoder do
"P#{param_id} V#{binary_float}" "P#{param_id} V#{binary_float}"
end end
defp encode_error(error) do
case error do
:no_error -> "V0"
:emergency_lock -> "V1"
:timeout -> "V2"
:stall_detected -> "V3"
:calibration_error -> "V4"
:invalid_command -> "V14"
:no_config -> "V15"
_ -> ""
end
end
defp encode_ints(args) do defp encode_ints(args) do
Enum.map(args, fn {key, val} -> Enum.map(args, fn {key, val} ->
String.upcase(to_string(key)) <> to_string(val) String.upcase(to_string(key)) <> to_string(val)

View File

@ -74,8 +74,10 @@ defmodule FarmbotFirmware.Request do
do: {:ok, {tag, result}}, do: {:ok, {tag, result}},
else: wait_for_request_result(tag, code, result) else: wait_for_request_result(tag, code, result)
{_, {:report_error, _}} -> {_, {:report_error, error_code}} ->
{:error, :firmware_error} if error_code,
do: {:error, error_code},
else: {:error, :firmware_error}
{_, {:report_invalid, []}} -> {_, {:report_invalid, []}} ->
{:error, :invalid_command} {:error, :invalid_command}

View File

@ -40,11 +40,17 @@ defmodule FarmbotFirmware.GCODETest do
test "error" do test "error" do
assert {nil, {:report_error, [:no_error]}} = GCODE.decode("R03") assert {nil, {:report_error, [:no_error]}} = GCODE.decode("R03")
assert {nil, {:report_error, [:no_error]}} = GCODE.decode("R03 V0") assert {"1", {:report_error, [:no_error]}} = GCODE.decode("R03 V0 Q1")
assert {nil, {:report_error, [:emergency_lock]}} = GCODE.decode("R03 V1") assert {nil, {:report_error, [:emergency_lock]}} = GCODE.decode("R03 V1")
assert {nil, {:report_error, [:timeout]}} = GCODE.decode("R03 V2") assert {nil, {:report_error, [:timeout]}} = GCODE.decode("R03 V2")
assert {nil, {:report_error, [:stall_detected]}} = GCODE.decode("R03 V3") assert {nil, {:report_error, [:stall_detected]}} = GCODE.decode("R03 V3")
assert {nil, {:report_error, [unknown_error: 987.0]}} =
GCODE.decode("R03 V987")
assert {nil, {:report_error, [:calibration_error]}} =
GCODE.decode("R03 V4")
assert {nil, {:report_error, [:invalid_command]}} = assert {nil, {:report_error, [:invalid_command]}} =
GCODE.decode("R03 V14") GCODE.decode("R03 V14")
@ -52,6 +58,13 @@ defmodule FarmbotFirmware.GCODETest do
assert {"100", {:report_error, [:no_error]}} = GCODE.decode("R03 Q100") assert {"100", {:report_error, [:no_error]}} = GCODE.decode("R03 Q100")
assert "R03" = GCODE.encode({nil, {:report_error, []}}) assert "R03" = GCODE.encode({nil, {:report_error, []}})
assert "R03 V0" = GCODE.encode({nil, {:report_error, :no_error}})
assert "R03 V1" = GCODE.encode({nil, {:report_error, :emergency_lock}})
assert "R03 V2" = GCODE.encode({nil, {:report_error, :timeout}})
assert "R03 V3" = GCODE.encode({nil, {:report_error, :stall_detected}})
assert "R03 V4" = GCODE.encode({nil, {:report_error, :calibration_error}})
assert "R03 V14" = GCODE.encode({nil, {:report_error, :invalid_command}})
assert "R03 V15" = GCODE.encode({nil, {:report_error, :no_config}})
assert "R03 Q100" = GCODE.encode({"100", {:report_error, []}}) assert "R03 Q100" = GCODE.encode({"100", {:report_error, []}})
end end