From c5e69e0c3de88ff51075252cbae89f55653ecbbc Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Fri, 10 Apr 2020 10:13:13 -0500 Subject: [PATCH 01/27] v9.2.2-rc8, plus dev doc updates --- .../releasing_target_firmware.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/docs/target_development/releasing_target_firmware.md b/docs/target_development/releasing_target_firmware.md index 380c88ac..567ac7e7 100644 --- a/docs/target_development/releasing_target_firmware.md +++ b/docs/target_development/releasing_target_firmware.md @@ -20,15 +20,22 @@ string. ```bash cd $FARMBOT_OS_ROOT_DIRECTORY git checkout staging -git fetch --all && git reset --hard origin/staging + +# Ensure you don't accidentally publish local changes +# that have not gone through CI: +git fetch --all +git reset --hard origin/staging + # update the CHANGELOG, but DO NOT put the `rc` # on the semver string. $EDITOR CHANGELOG.md -echo 10.5.6-rc30 > VERSION -git add CHANGELOG.md VERSION -git commit -m "Release v10.5.6-rc30" -git tag v$(cat VERSION) -git push origin staging v$(cat VERSION) + +echo 1.2.3-rc4 > VERSION + +git add -A +git commit -am "Release v10.5.6-rc30" +git tag v1.2.3-rc4 +git push origin v1.2.3-rc4 ``` or call the helper script: From ebb9ff41e720c9a02403d4d984c41033c6cefcc7 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Fri, 10 Apr 2020 16:16:18 -0500 Subject: [PATCH 02/27] Better AVR Error handling --- .../lib/farmbot_os/sys_calls/flash_firmware.ex | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex index 6df8287d..6329080b 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex @@ -29,9 +29,7 @@ defmodule FarmbotOS.SysCalls.FlashFirmware do ), :ok <- FarmbotFirmware.close_transport(), _ <- FarmbotCore.Logger.debug(3, "starting firmware flash"), - {_, 0} <- Avrdude.flash(hex_file, tty, fun) do - FarmbotCore.Logger.success(2, "Firmware flashed successfully!") - + _ <- finish_flashing(Avrdude.flash(hex_file, tty, fun)) do %{firmware_path: tty} |> Asset.update_fbos_config!() |> Private.mark_dirty!(%{}) @@ -42,10 +40,18 @@ defmodule FarmbotOS.SysCalls.FlashFirmware do {:error, reason} error -> - {:error, "flash_firmware misc error: #{inspect(error)}"} + {:error, "flash_firmware returned #{inspect(error)}"} end end + def finish_flashing({_result, 0}) do + FarmbotCore.Logger.success(2, "Firmware flashed successfully!") + end + + def finish_flashing(result) do + FarmbotCore.Logger.debug(2, "AVR Unexpected return code #{inspect(result)}") + end + defp find_tty() do case FirmwareTTYDetector.tty() do nil -> From 0fc39b1500b5728684a0bcfebea7b90536f69627 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Fri, 10 Apr 2020 19:15:12 -0500 Subject: [PATCH 03/27] Remove guard clause from config.exs --- farmbot_core/lib/farmbot_core.ex | 4 ++-- farmbot_os/config/config.exs | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/farmbot_core/lib/farmbot_core.ex b/farmbot_core/lib/farmbot_core.ex index d001bb51..10a0067b 100644 --- a/farmbot_core/lib/farmbot_core.ex +++ b/farmbot_core/lib/farmbot_core.ex @@ -30,7 +30,7 @@ defmodule FarmbotCore do {FarmbotFirmware, transport: FarmbotFirmware.StubTransport, side_effects: FarmbotCore.FirmwareSideEffects}, FarmbotCeleryScript.Scheduler ] - config = Application.get_env(:farmbot_ext, __MODULE__) || [] -Keyword.get(config, :children, default) + config = (Application.get_env(:farmbot_ext, __MODULE__) || []) + Keyword.get(config, :children, default) end end diff --git a/farmbot_os/config/config.exs b/farmbot_os/config/config.exs index 4abc7c32..99b374f4 100644 --- a/farmbot_os/config/config.exs +++ b/farmbot_os/config/config.exs @@ -100,9 +100,7 @@ if Mix.target() == :host do else import_config("target/#{Mix.env()}.exs") - if File.exists?("config/target/#{Mix.target()}.exs") do - import_config("target/#{Mix.target()}.exs") - end + import_config("target/#{Mix.target()}.exs") end if Mix.env() == :test do From a69decb1399e8ee377bb0b8738dc0465753bb03a Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Fri, 10 Apr 2020 19:19:23 -0500 Subject: [PATCH 04/27] v9.2.2-rc9 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9c0e1ab9..0e7c6532 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc8 +9.2.2-rc9 From e5a0c403899e84888bfec710859c0d71ec3aebc1 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Fri, 10 Apr 2020 20:21:41 -0500 Subject: [PATCH 05/27] v9.2.2-rc10 --- VERSION | 2 +- farmbot_os/config/target/rpi.exs | 4 ++ farmbot_os/config/target/rpi0.exs | 4 ++ .../farmbot_os/sys_calls/flash_firmware.ex | 49 +++++++++++++++---- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/VERSION b/VERSION index 0e7c6532..3f70cebb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc9 +9.2.2-rc10 diff --git a/farmbot_os/config/target/rpi.exs b/farmbot_os/config/target/rpi.exs index da5ba893..0d15369c 100644 --- a/farmbot_os/config/target/rpi.exs +++ b/farmbot_os/config/target/rpi.exs @@ -10,3 +10,7 @@ config :farmbot, FarmbotOS.Init.Supervisor, init_children: [ FarmbotOS.Platform.Target.RTCWorker ] + +# :farmbot_firmware, FarmbotFirmware changes too much. +# Needed one that would stay stable, so I duplicated it here: +config :farmbot, FarmbotOS.SysCalls.FlashFirmware, gpio: Circuits.GPIO diff --git a/farmbot_os/config/target/rpi0.exs b/farmbot_os/config/target/rpi0.exs index ffc236c9..7bc696aa 100644 --- a/farmbot_os/config/target/rpi0.exs +++ b/farmbot_os/config/target/rpi0.exs @@ -8,6 +8,10 @@ config :farmbot_core, FarmbotCore.FirmwareOpenTask, attempt_threshold: 50 config :farmbot_firmware, FarmbotFirmware, reset: FarmbotOS.Platform.Target.FirmwareReset.GPIO +# :farmbot_firmware, FarmbotFirmware changes too much. +# Needed one that would stay stable, so I duplicated it here: +config :farmbot, FarmbotOS.SysCalls.FlashFirmware, gpio: Circuits.GPIO + config :farmbot, FarmbotOS.Init.Supervisor, init_children: [ FarmbotOS.Platform.Target.RTCWorker diff --git a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex index 6329080b..07fa8fd6 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex @@ -5,6 +5,23 @@ defmodule FarmbotOS.SysCalls.FlashFirmware do alias FarmbotFirmware alias FarmbotCore.FirmwareTTYDetector + defmodule Stub do + require FarmbotCore.Logger + + def fail do + m = "No express function found. Please notify support." + FarmbotCore.Logger.error(3, m) + {:error, m} + end + + def open(_, _), do: fail() + def write(_, _), do: fail() + end + + # This only matter for express. + # When it's an express, use Circuits.GPIO. + @gpio Application.get_env(:farmbot, __MODULE__, [])[:gpio] || Stub + import FarmbotFirmware.PackageUtils, only: [find_hex_file: 1, package_to_string: 1] @@ -66,18 +83,32 @@ defmodule FarmbotOS.SysCalls.FlashFirmware do end defp find_reset_fun("express_k10") do - FarmbotCore.Logger.debug(3, "Using special reset function for express") - # "magic" workaround to avoid compiler warnings. - # We used to inject this via App config, but it was - # error prone. - mod = :"Elixir.FarmbotOS.Platform.Target.FirmwareReset.GPIO" - fun = &mod.reset/0 - {:ok, fun} + FarmbotCore.Logger.debug(3, "Using special express reset function") + {:ok, fn -> express_reset_fun() end} end defp find_reset_fun(_) do FarmbotCore.Logger.debug(3, "Using default reset function") - fun = &FarmbotFirmware.NullReset.reset/0 - {:ok, fun} + {:ok, &FarmbotFirmware.NullReset.reset/0} + end + + defp express_reset_fun() do + try do + FarmbotCore.Logger.debug(3, "Express reset step (1/4)") + {:ok, gpio} = @gpio.open(19, :output) + + FarmbotCore.Logger.debug(3, "Express reset step (2/4)") + :ok = @gpio.write(gpio, 1) + + FarmbotCore.Logger.debug(3, "Express reset step (3/4)") + :ok = @gpio.write(gpio, 0) + + FarmbotCore.Logger.debug(3, "Express reset step (4/4)") + rescue + ex -> + message = Exception.message(ex) + Logger.error("Could not flash express firmware: #{message}") + :express_reset_error + end end end From 24d02d6a6ce238783a64ab48238bb4981c65c220 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Fri, 10 Apr 2020 20:56:47 -0500 Subject: [PATCH 06/27] Add better logs --- farmbot_os/lib/avrdude.ex | 2 +- farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/farmbot_os/lib/avrdude.ex b/farmbot_os/lib/avrdude.ex index dd907eae..319b7090 100644 --- a/farmbot_os/lib/avrdude.ex +++ b/farmbot_os/lib/avrdude.ex @@ -30,7 +30,7 @@ defmodule Avrdude do # call the function for resetting the line before executing avrdude. call_reset_fun(reset_fun) - + FarmbotCore.Logger.info(3, "Writing firmware to MCU...") MuonTrap.cmd("avrdude", args, into: IO.stream(:stdio, :line), stderr_to_stdout: true diff --git a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex index 07fa8fd6..0229078c 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex @@ -94,16 +94,17 @@ defmodule FarmbotOS.SysCalls.FlashFirmware do defp express_reset_fun() do try do - FarmbotCore.Logger.debug(3, "Express reset step (1/4)") + FarmbotCore.Logger.debug(3, "Reseting MCU (1/4)") {:ok, gpio} = @gpio.open(19, :output) - FarmbotCore.Logger.debug(3, "Express reset step (2/4)") + FarmbotCore.Logger.debug(3, "Reseting MCU (2/4)") :ok = @gpio.write(gpio, 1) - - FarmbotCore.Logger.debug(3, "Express reset step (3/4)") + Process.sleep(250) + FarmbotCore.Logger.debug(3, "Reseting MCU (3/4)") :ok = @gpio.write(gpio, 0) + Process.sleep(250) - FarmbotCore.Logger.debug(3, "Express reset step (4/4)") + FarmbotCore.Logger.debug(3, "Reseting MCU (4/4)") rescue ex -> message = Exception.message(ex) From 609150d96e9348e189c4e82d10c255114bed7f9a Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Fri, 10 Apr 2020 21:01:23 -0500 Subject: [PATCH 07/27] v9.2.2-rc11 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 3f70cebb..525ff454 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc10 +9.2.2-rc11 From 5eeec86db4a63cfcc888e9c96828ebe34b6074a2 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sat, 11 Apr 2020 10:43:50 -0500 Subject: [PATCH 08/27] Remove VCR for clarity while debugging. --- farmbot_firmware/lib/farmbot_firmware.ex | 99 ------------------------ 1 file changed, 99 deletions(-) diff --git a/farmbot_firmware/lib/farmbot_firmware.ex b/farmbot_firmware/lib/farmbot_firmware.ex index f33cc397..cb091acf 100644 --- a/farmbot_firmware/lib/farmbot_firmware.ex +++ b/farmbot_firmware/lib/farmbot_firmware.ex @@ -78,28 +78,6 @@ defmodule FarmbotFirmware do and reply with `:ok | {:error, term()}` - # VCR - - This server can save all the input and output gcodes to a text file for - further external analysis or playback later. - - ## Using VCR mode - - The server can be started in VCR mode by doing: - - FarmbotFirmware.start_link([transport: FarmbotFirmware.StubTransport, vcr_path: "/tmp/vcr.txt"], []) - - or can be started at runtime: - - FarmbotFirmware.enter_vcr_mode(firmware_server, "/tmp/vcr.txt") - - in either case the VCR recording needs to be stopped: - - FarmbotFirmware.exit_vcr_mode(firmware_server) - - VCRs can later be played back: - - FarmbotFirmware.VCR.playback!("/tmp/vcr.txt") """ use GenServer require Logger @@ -129,7 +107,6 @@ defmodule FarmbotFirmware do :command_queue, :caller_pid, :current, - :vcr_fd, :reset, :reset_pid ] @@ -146,7 +123,6 @@ defmodule FarmbotFirmware do command_queue: [{pid(), GCODE.t()}], caller_pid: nil | pid, current: nil | GCODE.t(), - vcr_fd: nil | File.io_device(), reset: module(), reset_pid: nil | pid() } @@ -209,22 +185,6 @@ defmodule FarmbotFirmware do GenServer.call(server, :reset) end - @doc """ - Sets the Firmware server to record input and output GCODES - to a pair of text files. - """ - def enter_vcr_mode(server \\ __MODULE__, tape_path) do - GenServer.call(server, {:enter_vcr_mode, tape_path}) - end - - @doc """ - Sets the Firmware server to stop recording input and output - GCODES. - """ - def exit_vcr_mode(server \\ __MODULE__) do - GenServer.cast(server, :exit_vcr_mode) - end - @doc """ Starting the Firmware server requires at least: * `:transport` - a module implementing the Transport GenServer behaviour. @@ -252,18 +212,6 @@ defmodule FarmbotFirmware do # probably? reset = Keyword.get(args, :reset) || FarmbotFirmware.NullReset - vcr_fd = - case Keyword.get(args, :vcr_path) do - nil -> - nil - - tape_path -> - {:ok, vcr_fd} = - File.open(tape_path, [:binary, :append, :exclusive, :write]) - - vcr_fd - end - # Add an anon function that transport implementations should call. fw = self() fun = fn {_, _} = code -> GenServer.cast(fw, code) end @@ -280,7 +228,6 @@ defmodule FarmbotFirmware do reset_pid: nil, command_queue: [], configuration_queue: [], - vcr_fd: vcr_fd } send(self(), :timeout) @@ -358,7 +305,6 @@ defmodule FarmbotFirmware do } _ = side_effects(new_state, :handle_output_gcode, [{state.tag, code}]) - _ = vcr_write(state, :out, {state.tag, code}) {:noreply, new_state} @@ -374,7 +320,6 @@ defmodule FarmbotFirmware do :ok -> new_state = %{state | current: code, configuration_queue: rest} _ = side_effects(new_state, :handle_output_gcode, [{state.tag, code}]) - _ = vcr_write(state, :out, {state.tag, code}) {:noreply, new_state} error -> @@ -411,7 +356,6 @@ defmodule FarmbotFirmware do } _ = side_effects(new_state, :handle_output_gcode, [{state.tag, code}]) - _ = vcr_write(state, :out, {state.tag, code}) for {pid, _code} <- rest, do: send(pid, {state.tag, {:report_busy, []}}) {:noreply, new_state} @@ -485,16 +429,6 @@ defmodule FarmbotFirmware do {:reply, {:error, s}, state} end - def handle_call({:enter_vcr_mode, tape_path}, _from, state) do - with {:ok, vcr_fd} <- - File.open(tape_path, [:binary, :append, :exclusive, :write]) do - {:reply, :ok, %{state | vcr_fd: vcr_fd}} - else - error -> - {:reply, error, state} - end - end - def handle_call({tag, {kind, args}}, from, state) do handle_command({tag, {kind, args}}, from, state) end @@ -565,15 +499,9 @@ defmodule FarmbotFirmware do end end - def handle_cast(:exit_vcr_mode, state) do - state.vcr_fd && File.close(state.vcr_fd) - {:noreply, %{state | vcr_fd: nil}} - end - # Extracts tag def handle_cast({tag, {_, _} = code}, state) do _ = side_effects(state, :handle_input_gcode, [{tag, code}]) - _ = vcr_write(state, :in, {tag, code}) handle_report(code, %{state | tag: tag}) end @@ -995,31 +923,4 @@ defmodule FarmbotFirmware do defp side_effects(%{side_effects: m}, function, args), do: apply(m, function, args) - - @spec vcr_write(state, :in | :out, GCODE.t()) :: :ok - defp vcr_write(%{vcr_fd: nil}, _direction, _code), do: :ok - - defp vcr_write(state, :in, code), do: vcr_write(state, "<", code) - - defp vcr_write(state, :out, code), do: vcr_write(state, "\n>", code) - - defp vcr_write(state, direction, code) do - data = GCODE.encode(code) - time = :os.system_time(:second) - - current_data = - if state.current do - GCODE.encode({state.tag, state.current}) - else - "nil" - end - - state_data = - "#{state.status} | #{current_data} | #{inspect(state.caller_pid)}" - - IO.write( - state.vcr_fd, - direction <> " #{time} " <> data <> " state=" <> state_data <> "\n" - ) - end end From 96867553e42a3cdeadd61171c0be85d821406961 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sat, 11 Apr 2020 11:17:19 -0500 Subject: [PATCH 09/27] Add debug helpers --- farmbot_firmware/lib/farmbot_firmware.ex | 39 ++++++++++++++---------- farmbot_os/lib/avrdude.ex | 5 +++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/farmbot_firmware/lib/farmbot_firmware.ex b/farmbot_firmware/lib/farmbot_firmware.ex index cb091acf..8c5a32aa 100644 --- a/farmbot_firmware/lib/farmbot_firmware.ex +++ b/farmbot_firmware/lib/farmbot_firmware.ex @@ -230,7 +230,7 @@ defmodule FarmbotFirmware do configuration_queue: [], } - send(self(), :timeout) + send_timeout_self() {:ok, state} end @@ -334,7 +334,6 @@ defmodule FarmbotFirmware do for {pid, _code} <- state.command_queue, do: send(pid, {state.tag, {:report_busy, []}}) - # Logger.debug "Got checkup message when current command still executing" {:noreply, state} end @@ -382,8 +381,12 @@ defmodule FarmbotFirmware do true = Process.demonitor(state.transport_ref) end - :ok = GenServer.stop(state.transport_pid, :normal) - + if is_pid(state.transport_pid) do + Logger.debug("closing transport") + :ok = GenServer.stop(state.transport_pid, :normal) + else + Logger.debug("No tranport pid found.") + end next_state = goto( %{ @@ -417,7 +420,7 @@ defmodule FarmbotFirmware do next_state = %{state | transport: module, transport_args: transport_args} - send(self(), :timeout) + send_timeout_self() {:reply, :ok, next_state} end @@ -455,7 +458,7 @@ defmodule FarmbotFirmware do for {pid, _code} <- state.command_queue, do: send(pid, {state.tag, {:report_emergency_lock, []}}) - send(self(), :timeout) + send_timeout_self() {:reply, {:ok, tag}, %{state | command_queue: [{pid, code}], configuration_queue: []}} @@ -467,7 +470,7 @@ defmodule FarmbotFirmware do {pid, _ref}, state ) do - send(self(), :timeout) + send_timeout_self() {:reply, {:ok, tag}, %{state | command_queue: [{pid, code}], configuration_queue: []}} @@ -484,14 +487,14 @@ defmodule FarmbotFirmware do case {new_state.status, state.current} do {:idle, nil} -> - send(self(), :timeout) + send_timeout_self() {:reply, {:ok, tag}, new_state} # Don't do any flow control if state is emergency_lock. # This allows a transport to decide # if a command should be blocked or not. {:emergency_lock, _} -> - send(self(), :timeout) + send_timeout_self() {:reply, {:ok, tag}, new_state} _unknown -> @@ -513,7 +516,7 @@ defmodule FarmbotFirmware do if state.caller_pid, do: send(state.caller_pid, {state.tag, code}) for {pid, _code} <- state.command_queue, do: send(pid, code) - send(self(), :timeout) + send_timeout_self() {:noreply, goto(%{state | current: nil, caller_pid: nil}, :emergency_lock)} end @@ -576,7 +579,7 @@ defmodule FarmbotFirmware do do: to_process ++ [{:command_movement_find_home, [:x]}], else: to_process - send(self(), :timeout) + send_timeout_self() {:noreply, goto(%{state | tag: tag, configuration_queue: to_process}, :configuration)} @@ -612,7 +615,7 @@ defmodule FarmbotFirmware do side_effects(state, :handle_busy, [false]) side_effects(state, :handle_idle, [true]) - send(self(), :timeout) + send_timeout_self() {:noreply, goto(%{state | caller_pid: nil, current: nil}, :idle)} end @@ -633,7 +636,7 @@ defmodule FarmbotFirmware do new_state = %{state | current: nil, caller_pid: nil} side_effects(state, :handle_busy, [false]) - send(self(), :timeout) + send_timeout_self() {:noreply, goto(new_state, :idle)} end @@ -667,7 +670,7 @@ defmodule FarmbotFirmware do do: send(pid, {state.tag, {:report_busy, []}}) side_effects(state, :handle_busy, [false]) - send(self(), :timeout) + send_timeout_self() {:noreply, %{state | caller_pid: nil, current: nil}} end @@ -689,7 +692,7 @@ defmodule FarmbotFirmware do for {pid, _code} <- state.command_queue, do: send(pid, {state.tag, {:report_busy, []}}) - send(self(), :timeout) + send_timeout_self() {:noreply, %{state | caller_pid: nil, current: nil}} end @@ -724,7 +727,7 @@ defmodule FarmbotFirmware do to_process = [{:parameter_write, param}] side_effects(state, :handle_parameter_value, [param]) side_effects(state, :handle_parameter_calibration_value, [param]) - send(self(), :timeout) + send_timeout_self() {:noreply, goto( @@ -923,4 +926,8 @@ defmodule FarmbotFirmware do defp side_effects(%{side_effects: m}, function, args), do: apply(m, function, args) + + defp send_timeout_self do + send(self(), :timeout) + end end diff --git a/farmbot_os/lib/avrdude.ex b/farmbot_os/lib/avrdude.ex index 319b7090..8933ba6e 100644 --- a/farmbot_os/lib/avrdude.ex +++ b/farmbot_os/lib/avrdude.ex @@ -31,6 +31,11 @@ defmodule Avrdude do # call the function for resetting the line before executing avrdude. call_reset_fun(reset_fun) FarmbotCore.Logger.info(3, "Writing firmware to MCU...") + IO.inspect(%{ + args: args, + into: IO.stream(:stdio, :line), + stderr_to_stdout: true + }) MuonTrap.cmd("avrdude", args, into: IO.stream(:stdio, :line), stderr_to_stdout: true From c9174cf1d24339e72609bf6bc837cb8ba2eca049 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sat, 11 Apr 2020 11:39:47 -0500 Subject: [PATCH 10/27] v9.2.2-rc12 --- VERSION | 2 +- farmbot_firmware/lib/farmbot_firmware.ex | 29 ++++++++++++++++++++---- farmbot_os/lib/avrdude.ex | 2 ++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index 525ff454..4a65ee10 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc11 +9.2.2-rc12 diff --git a/farmbot_firmware/lib/farmbot_firmware.ex b/farmbot_firmware/lib/farmbot_firmware.ex index 8c5a32aa..4a94e9fe 100644 --- a/farmbot_firmware/lib/farmbot_firmware.ex +++ b/farmbot_firmware/lib/farmbot_firmware.ex @@ -227,7 +227,7 @@ defmodule FarmbotFirmware do reset: reset, reset_pid: nil, command_queue: [], - configuration_queue: [], + configuration_queue: [] } send_timeout_self() @@ -294,7 +294,7 @@ defmodule FarmbotFirmware do ] } = state ) do - case GenServer.call(state.transport_pid, {tag, code}) do + case call_transport(state.transport_pid, {tag, code}, 297) do :ok -> new_state = %{ state @@ -316,7 +316,7 @@ defmodule FarmbotFirmware do def handle_info(:timeout, %{configuration_queue: [code | rest]} = state) do # Logger.debug("Starting next configuration code: #{inspect(code)}") - case GenServer.call(state.transport_pid, {state.tag, code}) do + case call_transport(state.transport_pid, {state.tag, code}, 319) do :ok -> new_state = %{state | current: code, configuration_queue: rest} _ = side_effects(new_state, :handle_output_gcode, [{state.tag, code}]) @@ -344,7 +344,8 @@ defmodule FarmbotFirmware do for {pid, _code} <- state.command_queue, do: send(pid, {state.tag, {:report_busy, []}}) - case GenServer.call(state.transport_pid, {tag, code}) do + + case call_transport(state.transport_pid, {tag, code}, 348) do :ok -> new_state = %{ state @@ -385,8 +386,9 @@ defmodule FarmbotFirmware do Logger.debug("closing transport") :ok = GenServer.stop(state.transport_pid, :normal) else - Logger.debug("No tranport pid found.") + Logger.debug("No tranport pid found. Nothing to close") end + next_state = goto( %{ @@ -930,4 +932,21 @@ defmodule FarmbotFirmware do defp send_timeout_self do send(self(), :timeout) end + + defp call_transport(nil, args, where) do + msg = "#{inspect(where)} Firmware restart required (#{inspect(args)})" + Logger.debug(msg) + {:error, msg} + end + + defp call_transport(transport_pid, args, where) do + # Returns :ok + response = GenServer.call(transport_pid, args) + + unless response == :ok do + Logger.debug("#{inspect(where)}: returned #{inspect(response)}") + end + + response + end end diff --git a/farmbot_os/lib/avrdude.ex b/farmbot_os/lib/avrdude.ex index 8933ba6e..ff91923c 100644 --- a/farmbot_os/lib/avrdude.ex +++ b/farmbot_os/lib/avrdude.ex @@ -31,11 +31,13 @@ defmodule Avrdude do # call the function for resetting the line before executing avrdude. call_reset_fun(reset_fun) FarmbotCore.Logger.info(3, "Writing firmware to MCU...") + IO.inspect(%{ args: args, into: IO.stream(:stdio, :line), stderr_to_stdout: true }) + MuonTrap.cmd("avrdude", args, into: IO.stream(:stdio, :line), stderr_to_stdout: true From c82cd1f165e0748b31f1818863848b4ea761ea7a Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sat, 11 Apr 2020 12:16:39 -0500 Subject: [PATCH 11/27] v9.2.2-rc13 --- VERSION | 2 +- farmbot_firmware/lib/farmbot_firmware.ex | 7 +++-- farmbot_os/lib/avrdude.ex | 28 +++++++++++++------ .../test/farmbot_os/avrdude/avrdude_test.exs | 22 ++++++++------- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/VERSION b/VERSION index 4a65ee10..66ec03ac 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc12 +9.2.2-rc13 diff --git a/farmbot_firmware/lib/farmbot_firmware.ex b/farmbot_firmware/lib/farmbot_firmware.ex index 4a94e9fe..3c0ed544 100644 --- a/farmbot_firmware/lib/farmbot_firmware.ex +++ b/farmbot_firmware/lib/farmbot_firmware.ex @@ -344,7 +344,6 @@ defmodule FarmbotFirmware do for {pid, _code} <- state.command_queue, do: send(pid, {state.tag, {:report_busy, []}}) - case call_transport(state.transport_pid, {tag, code}, 348) do :ok -> new_state = %{ @@ -934,7 +933,11 @@ defmodule FarmbotFirmware do end defp call_transport(nil, args, where) do - msg = "#{inspect(where)} Firmware restart required (#{inspect(args)})" + msg = + "#{inspect(where)} Firmware not ready. A restart may be required if not already started (#{ + inspect(args) + })" + Logger.debug(msg) {:error, msg} end diff --git a/farmbot_os/lib/avrdude.ex b/farmbot_os/lib/avrdude.ex index ff91923c..29f1f06a 100644 --- a/farmbot_os/lib/avrdude.ex +++ b/farmbot_os/lib/avrdude.ex @@ -25,6 +25,7 @@ defmodule Avrdude do "-b#{@uart_speed}", "-D", "-V", + "-v", "-Uflash:w:#{hex_path}:i" ] @@ -32,16 +33,25 @@ defmodule Avrdude do call_reset_fun(reset_fun) FarmbotCore.Logger.info(3, "Writing firmware to MCU...") - IO.inspect(%{ - args: args, - into: IO.stream(:stdio, :line), - stderr_to_stdout: true - }) - - MuonTrap.cmd("avrdude", args, - into: IO.stream(:stdio, :line), - stderr_to_stdout: true + FarmbotCore.Logger.debug( + 1, + inspect(%{ + args: args, + into: IO.stream(:stdio, :line), + stderr_to_stdout: true + }) ) + + FarmbotCore.Logger.info(3, "Writing firmware to MCU...") + + result = MuonTrap.cmd("avrdude", args, stderr_to_stdout: true) + + if is_tuple(result) do + {a, _b} = result + FarmbotCore.Logger.info(3, "Done. #{inspect(a)}") + end + + result end def call_reset_fun(reset_fun) do diff --git a/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs b/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs index 4a2bde4d..ec795a63 100644 --- a/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs +++ b/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs @@ -31,15 +31,16 @@ defmodule FarmbotOs.AvrdudeTest do "-b115200", "-D", "-V", + "-v", "-Uflash:w:/tmp/wow:i" ] assert opts == [ - into: %IO.Stream{ - device: :standard_io, - line_or_bytes: :line, - raw: false - }, + # into: %IO.Stream{ + # device: :standard_io, + # line_or_bytes: :line, + # raw: false + # }, stderr_to_stdout: true ] end) @@ -62,15 +63,16 @@ defmodule FarmbotOs.AvrdudeTest do "-b115200", "-D", "-V", + "-v", "-Uflash:w:/tmp/wow:i" ] assert opts == [ - into: %IO.Stream{ - device: :standard_io, - line_or_bytes: :line, - raw: false - }, + # into: %IO.Stream{ + # device: :standard_io, + # line_or_bytes: :line, + # raw: false + # }, stderr_to_stdout: true ] end) From c9dc517df685b9c36d11586a2cac287cf0283a4d Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sat, 11 Apr 2020 15:42:09 -0500 Subject: [PATCH 12/27] v9.2.2-rc14, manual override of errors. --- VERSION | 2 +- farmbot_os/lib/avrdude.ex | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index 66ec03ac..6f9e7586 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc13 +9.2.2-rc14 diff --git a/farmbot_os/lib/avrdude.ex b/farmbot_os/lib/avrdude.ex index 29f1f06a..6296ce2a 100644 --- a/farmbot_os/lib/avrdude.ex +++ b/farmbot_os/lib/avrdude.ex @@ -47,11 +47,15 @@ defmodule Avrdude do result = MuonTrap.cmd("avrdude", args, stderr_to_stdout: true) if is_tuple(result) do - {a, _b} = result - FarmbotCore.Logger.info(3, "Done. #{inspect(a)}") + {a, exit_code} = result + FarmbotCore.Logger.info(3, inspect(a)) + FarmbotCore.Logger.info(3, "Exit code #{exit_code}") + # Manually override errors while debugging. + {a, 0} + else + result end - result end def call_reset_fun(reset_fun) do From 87fcc9f5a91fb30511875f68e8346dc991088b0e Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sun, 12 Apr 2020 11:37:39 -0500 Subject: [PATCH 13/27] [UNSTABLE] Add new test cases to criteria retriever --- .../test/asset/criteria_retriever_test.exs | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/farmbot_core/test/asset/criteria_retriever_test.exs b/farmbot_core/test/asset/criteria_retriever_test.exs index 404c8d2e..a2fc6a64 100644 --- a/farmbot_core/test/asset/criteria_retriever_test.exs +++ b/farmbot_core/test/asset/criteria_retriever_test.exs @@ -494,4 +494,70 @@ defmodule FarmbotCore.Asset.CriteriaRetrieverTest do assert Enum.count(whitelist) == Enum.count(results) Enum.map(whitelist, fn id -> assert Enum.member?(results, id) end) end + + test "edge case: Filter by slot direction" do + Repo.delete_all(PointGroup) + Repo.delete_all(Point) + ok = point!(%{id: 1, pointer_type: "Plant", openfarm_slug: "spinach"}) + point!(%{id: 2, pointer_type: "Plant", openfarm_slug: "beetroot"}) + point!(%{id: 3, pointer_type: "Weed", openfarm_slug: "thistle"}) + point!(%{id: 4, pointer_type: "Weed", openfarm_slug: "spinach"}) + + pg = %PointGroup{ + :id => 241, + :point_ids => [], + :criteria => %{ + "day" => %{ + "op" => "<", + "days_ago" => 0 + }, + "string_eq" => %{ + "pointer_type" => ["Plant"], + "openfarm_slug" => ["spinach"] + }, + "number_eq" => %{}, + "number_lt" => %{}, + "number_gt" => %{} + } + } + + ids = CriteriaRetriever.run(pg) |> Enum.map(fn p -> p.id end) + assert Enum.member?(ids, ok.id) + assert Enum.count(ids) == 1 + end + + test "edge case: Filter by crop type" do + Repo.delete_all(PointGroup) + Repo.delete_all(Point) + + ok = point!(%{id: 1, pointer_type: "ToolSlot", pullout_direction: 3}) + point!(%{id: 2, pointer_type: "Weed", pullout_direction: 3}) + point!(%{id: 3, pointer_type: "ToolSlot", pullout_direction: 4}) + point!(%{id: 4, pointer_type: "GenericPointer", pullout_direction: 2}) + + pg = %PointGroup{ + :id => 242, + :name => "Filter by slot direction", + :point_ids => [], + :sort_type => "xy_ascending", + :criteria => %{ + "day" => %{ + "op" => "<", + "days_ago" => 0 + }, + "string_eq" => %{ + "pointer_type" => ["ToolSlot"] + }, + "number_eq" => %{ + "pullout_direction" => [3] + }, + "number_lt" => %{}, + "number_gt" => %{} + } + } + + ids = CriteriaRetriever.run(pg) |> Enum.map(fn p -> p.id end) + assert Enum.member?(ids, ok.id) + assert Enum.count(ids) == 1 + end end From 446aeb007de98d58ef6682e64766910908454f46 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sun, 12 Apr 2020 12:32:40 -0500 Subject: [PATCH 14/27] Add `pullout_direction` to points table --- .../lib/farmbot_core/asset/criteria_retriever.ex | 9 +++++++-- ...20200411204400_add_pullout_direction_to_point.exs | 12 ++++++++++++ farmbot_core/test/asset/criteria_retriever_test.exs | 4 ++-- 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 farmbot_core/priv/asset/migrations/20200411204400_add_pullout_direction_to_point.exs diff --git a/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex b/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex index 2afc6348..8f681d40 100644 --- a/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex +++ b/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex @@ -22,7 +22,7 @@ defmodule FarmbotCore.Asset.CriteriaRetriever do # We will not query any string/numeric fields other than these. # Updating the PointGroup / Point models may require an update # to these fields. - @numberic_fields ["radius", "x", "y", "z"] + @numberic_fields ["radius", "x", "y", "z", "pullout_direction"] @string_fields ["name", "openfarm_slug", "plant_stage", "pointer_type"] @doc """ @@ -114,8 +114,13 @@ defmodule FarmbotCore.Asset.CriteriaRetriever do def finalize({fragments, criteria}) do x = Enum.join(fragments, " AND ") sql = "SELECT id FROM points WHERE #{x}" - {:ok, query} = Repo.query(sql, List.flatten(criteria)) + query_params = List.flatten(criteria) + IO.inspect(sql) + IO.inspect(query_params) + {:ok, query} = Repo.query(sql, query_params) %Sqlite.DbConnection.Result{ rows: rows } = query + IO.puts("Results:") + IO.inspect(rows) List.flatten(rows) end diff --git a/farmbot_core/priv/asset/migrations/20200411204400_add_pullout_direction_to_point.exs b/farmbot_core/priv/asset/migrations/20200411204400_add_pullout_direction_to_point.exs new file mode 100644 index 00000000..a357e5ad --- /dev/null +++ b/farmbot_core/priv/asset/migrations/20200411204400_add_pullout_direction_to_point.exs @@ -0,0 +1,12 @@ +defmodule FarmbotCore.Asset.Repo.Migrations.AddPulloutDirectionToPoint do + use Ecto.Migration + + def change do + alter table("points") do + # 0 means "NONE" + add(:pullout_direction, :integer, default: 0) + end + + execute("UPDATE points SET updated_at = \"1970-11-07 16:52:31.618000\"") + end +end diff --git a/farmbot_core/test/asset/criteria_retriever_test.exs b/farmbot_core/test/asset/criteria_retriever_test.exs index a2fc6a64..d4559cb9 100644 --- a/farmbot_core/test/asset/criteria_retriever_test.exs +++ b/farmbot_core/test/asset/criteria_retriever_test.exs @@ -495,7 +495,7 @@ defmodule FarmbotCore.Asset.CriteriaRetrieverTest do Enum.map(whitelist, fn id -> assert Enum.member?(results, id) end) end - test "edge case: Filter by slot direction" do + test "edge case: Filter by crop type" do Repo.delete_all(PointGroup) Repo.delete_all(Point) ok = point!(%{id: 1, pointer_type: "Plant", openfarm_slug: "spinach"}) @@ -526,7 +526,7 @@ defmodule FarmbotCore.Asset.CriteriaRetrieverTest do assert Enum.count(ids) == 1 end - test "edge case: Filter by crop type" do + test "edge case: Filter by slot direction" do Repo.delete_all(PointGroup) Repo.delete_all(Point) From f463c698e00ee021c911558799f3a52e6f0ad133 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sun, 12 Apr 2020 12:47:10 -0500 Subject: [PATCH 15/27] Fix pullout_direction query issues --- VERSION | 2 +- .../lib/farmbot_core/asset/criteria_retriever.ex | 4 ---- farmbot_core/lib/farmbot_core/asset/point.ex | 10 ++++++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/VERSION b/VERSION index 6f9e7586..3b2c983b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc14 +9.2.2-rc15 diff --git a/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex b/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex index 8f681d40..db77e21a 100644 --- a/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex +++ b/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex @@ -115,12 +115,8 @@ defmodule FarmbotCore.Asset.CriteriaRetriever do x = Enum.join(fragments, " AND ") sql = "SELECT id FROM points WHERE #{x}" query_params = List.flatten(criteria) - IO.inspect(sql) - IO.inspect(query_params) {:ok, query} = Repo.query(sql, query_params) %Sqlite.DbConnection.Result{ rows: rows } = query - IO.puts("Results:") - IO.inspect(rows) List.flatten(rows) end diff --git a/farmbot_core/lib/farmbot_core/asset/point.ex b/farmbot_core/lib/farmbot_core/asset/point.ex index 5af3c4d3..c5e980a9 100644 --- a/farmbot_core/lib/farmbot_core/asset/point.ex +++ b/farmbot_core/lib/farmbot_core/asset/point.ex @@ -13,20 +13,21 @@ defmodule FarmbotCore.Asset.Point do foreign_key: :asset_local_id ) + field(:discarded_at, :utc_datetime) + field(:gantry_mounted, :boolean) field(:meta, :map) + field(:monitor, :boolean, default: true) field(:name, :string) field(:openfarm_slug, :string) field(:plant_stage, :string) field(:planted_at, :utc_datetime) field(:pointer_type, :string) + field(:pullout_direction, :integer) field(:radius, :float) + field(:tool_id, :integer) field(:x, :float) field(:y, :float) field(:z, :float) - field(:tool_id, :integer) - field(:discarded_at, :utc_datetime) - field(:gantry_mounted, :boolean) - field(:monitor, :boolean, default: true) timestamps() end @@ -42,6 +43,7 @@ defmodule FarmbotCore.Asset.Point do tool_id: point.tool_id, discarded_at: point.discarded_at, gantry_mounted: point.gantry_mounted, + pullout_direction: point.pullout_direction, x: point.x, y: point.y, z: point.z From 626fb4e5a4989a6ad73c4ba0e40738db497c67ac Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sun, 12 Apr 2020 16:07:13 -0500 Subject: [PATCH 16/27] Perform reset AFTER flash, not before. --- VERSION | 2 +- farmbot_core/lib/farmbot_core/asset.ex | 4 +++- farmbot_os/lib/avrdude.ex | 9 +++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/VERSION b/VERSION index 3b2c983b..442e0c68 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc15 +9.2.2-rc16 diff --git a/farmbot_core/lib/farmbot_core/asset.ex b/farmbot_core/lib/farmbot_core/asset.ex index cfdb7cb2..457d4d9f 100644 --- a/farmbot_core/lib/farmbot_core/asset.ex +++ b/farmbot_core/lib/farmbot_core/asset.ex @@ -323,8 +323,10 @@ defmodule FarmbotCore.Asset do # the DB / API. sorted = CriteriaRetriever.run(point_group) |> sort_points(sort_by || "xy_ascending") - |> Enum.map(&Map.fetch!(&1, :id)) + |> Enum.map(fn point -> point.id end) + count = Enum.count(sorted) + Logger.debug("There are #{count} points. #{inspect(sorted)}") %{ point_group | point_ids: sorted } other -> # Swallow all other errors diff --git a/farmbot_os/lib/avrdude.ex b/farmbot_os/lib/avrdude.ex index 6296ce2a..10393c98 100644 --- a/farmbot_os/lib/avrdude.ex +++ b/farmbot_os/lib/avrdude.ex @@ -29,8 +29,6 @@ defmodule Avrdude do "-Uflash:w:#{hex_path}:i" ] - # call the function for resetting the line before executing avrdude. - call_reset_fun(reset_fun) FarmbotCore.Logger.info(3, "Writing firmware to MCU...") FarmbotCore.Logger.debug( @@ -50,12 +48,11 @@ defmodule Avrdude do {a, exit_code} = result FarmbotCore.Logger.info(3, inspect(a)) FarmbotCore.Logger.info(3, "Exit code #{exit_code}") - # Manually override errors while debugging. - {a, 0} - else - result end + call_reset_fun(reset_fun) + + result end def call_reset_fun(reset_fun) do From 88da7a298cf698881778617a652cac32c1188e25 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sun, 12 Apr 2020 17:39:34 -0500 Subject: [PATCH 17/27] Formatting updates. --- .../lib/farmbot_core/firmware_open_task.ex | 6 +++--- farmbot_firmware/lib/farmbot_firmware.ex | 5 +---- farmbot_os/lib/avrdude.ex | 4 ++-- .../lib/farmbot_os/sys_calls/flash_firmware.ex | 13 ++++--------- .../test/farmbot_os/avrdude/avrdude_test.exs | 18 ++---------------- 5 files changed, 12 insertions(+), 34 deletions(-) diff --git a/farmbot_core/lib/farmbot_core/firmware_open_task.ex b/farmbot_core/lib/farmbot_core/firmware_open_task.ex index 844c8c2a..2e326216 100644 --- a/farmbot_core/lib/farmbot_core/firmware_open_task.ex +++ b/farmbot_core/lib/farmbot_core/firmware_open_task.ex @@ -77,21 +77,21 @@ defmodule FarmbotCore.FirmwareOpenTask do {:noreply, increment_attempts(%{state | timer: timer})} firmware_hardware == "none" && needs_open? -> - FarmbotCore.Logger.debug 3, "Firmware needs to be closed" + FarmbotCore.Logger.debug 3, "Closing firmware..." unswap_transport() Config.update_config_value(:bool, "settings", "firmware_needs_open", false) timer = Process.send_after(self(), :open, 5000) {:noreply, %{state | timer: timer, attempts: 0}} needs_open? -> - FarmbotCore.Logger.debug 3, "Firmware needs to be opened" + FarmbotCore.Logger.debug 3, "Opening firmware..." case swap_transport(firmware_path) do :ok -> Config.update_config_value(:bool, "settings", "firmware_needs_open", false) timer = Process.send_after(self(), :open, 5000) {:noreply, %{state | timer: timer, attempts: 0}} other -> - FarmbotCore.Logger.debug 3, "Firmware failed to open: #{inspect(other)}" + FarmbotCore.Logger.debug 3, "Not ready to open yet, will retry in 5s (#{inspect(other)})" timer = Process.send_after(self(), :open, 5000) {:noreply, %{state | timer: timer, attempts: 0}} end diff --git a/farmbot_firmware/lib/farmbot_firmware.ex b/farmbot_firmware/lib/farmbot_firmware.ex index 3c0ed544..9f1bb2da 100644 --- a/farmbot_firmware/lib/farmbot_firmware.ex +++ b/farmbot_firmware/lib/farmbot_firmware.ex @@ -530,10 +530,7 @@ defmodule FarmbotFirmware do handle_report({:report_no_config, []}, state) end - def handle_report( - {:report_idle, []}, - %{status: :boot} = state - ) do + def handle_report({:report_idle, []}, %{status: :boot} = state) do Logger.info("ARDUINO STARTUP COMPLETE (idle) transport=#{state.transport}") handle_report({:report_no_config, []}, state) end diff --git a/farmbot_os/lib/avrdude.ex b/farmbot_os/lib/avrdude.ex index 10393c98..c8254c52 100644 --- a/farmbot_os/lib/avrdude.ex +++ b/farmbot_os/lib/avrdude.ex @@ -44,14 +44,14 @@ defmodule Avrdude do result = MuonTrap.cmd("avrdude", args, stderr_to_stdout: true) + call_reset_fun(reset_fun) + if is_tuple(result) do {a, exit_code} = result FarmbotCore.Logger.info(3, inspect(a)) FarmbotCore.Logger.info(3, "Exit code #{exit_code}") end - call_reset_fun(reset_fun) - result end diff --git a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex index 0229078c..dcdfb380 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex @@ -66,7 +66,7 @@ defmodule FarmbotOS.SysCalls.FlashFirmware do end def finish_flashing(result) do - FarmbotCore.Logger.debug(2, "AVR Unexpected return code #{inspect(result)}") + FarmbotCore.Logger.debug(2, "AVR flash returned #{inspect(result)}") end defp find_tty() do @@ -94,17 +94,12 @@ defmodule FarmbotOS.SysCalls.FlashFirmware do defp express_reset_fun() do try do - FarmbotCore.Logger.debug(3, "Reseting MCU (1/4)") + FarmbotCore.Logger.debug(3, "Resetting MCU") {:ok, gpio} = @gpio.open(19, :output) - - FarmbotCore.Logger.debug(3, "Reseting MCU (2/4)") :ok = @gpio.write(gpio, 1) - Process.sleep(250) - FarmbotCore.Logger.debug(3, "Reseting MCU (3/4)") :ok = @gpio.write(gpio, 0) - Process.sleep(250) - - FarmbotCore.Logger.debug(3, "Reseting MCU (4/4)") + FarmbotCore.Logger.debug(3, "MCU Reset done") + :ok rescue ex -> message = Exception.message(ex) diff --git a/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs b/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs index ec795a63..c6366113 100644 --- a/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs +++ b/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs @@ -35,14 +35,7 @@ defmodule FarmbotOs.AvrdudeTest do "-Uflash:w:/tmp/wow:i" ] - assert opts == [ - # into: %IO.Stream{ - # device: :standard_io, - # line_or_bytes: :line, - # raw: false - # }, - stderr_to_stdout: true - ] + assert opts == [ stderr_to_stdout: true ] end) Avrdude.flash("/tmp/wow", "null", fn -> @@ -67,14 +60,7 @@ defmodule FarmbotOs.AvrdudeTest do "-Uflash:w:/tmp/wow:i" ] - assert opts == [ - # into: %IO.Stream{ - # device: :standard_io, - # line_or_bytes: :line, - # raw: false - # }, - stderr_to_stdout: true - ] + assert opts == [ stderr_to_stdout: true ] end) Avrdude.flash("/tmp/wow", "/dev/null", fn -> From 92121b49558f1e15bfa4e15cfb030b386c8e4b7a Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sun, 12 Apr 2020 19:42:57 -0500 Subject: [PATCH 18/27] v9.2.2-rc17 --- VERSION | 2 +- farmbot_core/lib/farmbot_core/asset/point.ex | 15 +++++++++------ .../test/asset/criteria_retriever_test.exs | 1 - 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/VERSION b/VERSION index 442e0c68..124b2284 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc16 +9.2.2-rc17 diff --git a/farmbot_core/lib/farmbot_core/asset/point.ex b/farmbot_core/lib/farmbot_core/asset/point.ex index c5e980a9..28984dc3 100644 --- a/farmbot_core/lib/farmbot_core/asset/point.ex +++ b/farmbot_core/lib/farmbot_core/asset/point.ex @@ -43,6 +43,7 @@ defmodule FarmbotCore.Asset.Point do tool_id: point.tool_id, discarded_at: point.discarded_at, gantry_mounted: point.gantry_mounted, + openfarm_slug: point.openfarm_slug, pullout_direction: point.pullout_direction, x: point.x, y: point.y, @@ -53,22 +54,24 @@ defmodule FarmbotCore.Asset.Point do def changeset(point, params \\ %{}) do point |> cast(params, [ + :created_at, + :discarded_at, + :gantry_mounted, :id, :meta, + :monitor, :name, :plant_stage, :planted_at, :pointer_type, + :pullout_direction, + :openfarm_slug, :radius, + :tool_id, + :updated_at, :x, :y, :z, - :tool_id, - :gantry_mounted, - :discarded_at, - :monitor, - :created_at, - :updated_at ]) |> validate_required([]) end diff --git a/farmbot_core/test/asset/criteria_retriever_test.exs b/farmbot_core/test/asset/criteria_retriever_test.exs index d4559cb9..8d08c9e9 100644 --- a/farmbot_core/test/asset/criteria_retriever_test.exs +++ b/farmbot_core/test/asset/criteria_retriever_test.exs @@ -482,7 +482,6 @@ defmodule FarmbotCore.Asset.CriteriaRetrieverTest do "string_eq" => %{} }, id: 201, - local_id: "30856f5e-1f97-4e18-b5e0-84dc7cd9bbf0", name: "Test (Broke?)", point_ids: whitelist, sort_type: "xy_ascending", From b149504ca2550591dfb676d036fffbabcf163b7f Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Mon, 13 Apr 2020 10:17:18 -0500 Subject: [PATCH 19/27] v9.2.2-rc18 --- VERSION | 2 +- farmbot_os/lib/farmbot_os/sys_calls/farmware.ex | 6 +++--- farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex | 8 +++++--- farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs | 4 ++-- farmbot_os/test/farmbot_os/syscalls/farmware_test.exs | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/VERSION b/VERSION index 124b2284..482d1799 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc17 +9.2.2-rc18 diff --git a/farmbot_os/lib/farmbot_os/sys_calls/farmware.ex b/farmbot_os/lib/farmbot_os/sys_calls/farmware.ex index bce83065..72f37a3a 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls/farmware.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls/farmware.ex @@ -4,7 +4,7 @@ defmodule FarmbotOS.SysCalls.Farmware do require FarmbotCore.Logger alias FarmbotCore.{Asset, AssetSupervisor, FarmwareRuntime} alias FarmbotExt.API.ImageUploader - @farmware_timeout 60_000 + @farmware_timeout 1_200_000 def update_farmware(farmware_name) do with {:ok, installation} <- lookup_installation(farmware_name) do @@ -56,9 +56,9 @@ defmodule FarmbotOS.SysCalls.Farmware do end def farmware_timeout(farmware_runtime) do - time = @farmware_timeout / 1_000 + time = @farmware_timeout / 1_000 / 60 runtime = inspect(farmware_runtime) - msg = "Farmware did not exit after #{time} seconds. Terminating #{runtime}" + msg = "Farmware did not exit after #{time} minutes. Terminating #{runtime}" FarmbotCore.Logger.info(2, msg) FarmwareRuntime.stop(farmware_runtime) diff --git a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex index dcdfb380..c379d5dc 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex @@ -94,11 +94,13 @@ defmodule FarmbotOS.SysCalls.FlashFirmware do defp express_reset_fun() do try do - FarmbotCore.Logger.debug(3, "Resetting MCU") + FarmbotCore.Logger.debug(3, "Begin MCU reset") {:ok, gpio} = @gpio.open(19, :output) - :ok = @gpio.write(gpio, 1) :ok = @gpio.write(gpio, 0) - FarmbotCore.Logger.debug(3, "MCU Reset done") + :ok = @gpio.write(gpio, 1) + Process.sleep(1000) + :ok = @gpio.write(gpio, 0) + FarmbotCore.Logger.debug(3, "Finish MCU Reset") :ok rescue ex -> diff --git a/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs b/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs index c6366113..292b12ee 100644 --- a/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs +++ b/farmbot_os/test/farmbot_os/avrdude/avrdude_test.exs @@ -35,7 +35,7 @@ defmodule FarmbotOs.AvrdudeTest do "-Uflash:w:/tmp/wow:i" ] - assert opts == [ stderr_to_stdout: true ] + assert opts == [stderr_to_stdout: true] end) Avrdude.flash("/tmp/wow", "null", fn -> @@ -60,7 +60,7 @@ defmodule FarmbotOs.AvrdudeTest do "-Uflash:w:/tmp/wow:i" ] - assert opts == [ stderr_to_stdout: true ] + assert opts == [stderr_to_stdout: true] end) Avrdude.flash("/tmp/wow", "/dev/null", fn -> diff --git a/farmbot_os/test/farmbot_os/syscalls/farmware_test.exs b/farmbot_os/test/farmbot_os/syscalls/farmware_test.exs index 3bec795a..2a475965 100644 --- a/farmbot_os/test/farmbot_os/syscalls/farmware_test.exs +++ b/farmbot_os/test/farmbot_os/syscalls/farmware_test.exs @@ -9,7 +9,7 @@ defmodule FarmbotOS.SysCalls.FarmwareTest do expect(FarmbotCore.LogExecutor, :execute, fn log -> expected = - "Farmware did not exit after 60.0 seconds. Terminating :FAKE_PID" + "Farmware did not exit after 20.0 minutes. Terminating :FAKE_PID" assert log.message == expected :ok From 7407119942eceed2b8d6fc9b18b09ac89f80498d Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Mon, 13 Apr 2020 10:40:17 -0500 Subject: [PATCH 20/27] v9.2.2-rc19 --- VERSION | 2 +- farmbot_os/lib/avrdude.ex | 4 ++-- farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index 482d1799..a22826d8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc18 +9.2.2-rc19 diff --git a/farmbot_os/lib/avrdude.ex b/farmbot_os/lib/avrdude.ex index c8254c52..f43af1fd 100644 --- a/farmbot_os/lib/avrdude.ex +++ b/farmbot_os/lib/avrdude.ex @@ -42,10 +42,10 @@ defmodule Avrdude do FarmbotCore.Logger.info(3, "Writing firmware to MCU...") - result = MuonTrap.cmd("avrdude", args, stderr_to_stdout: true) - call_reset_fun(reset_fun) + result = MuonTrap.cmd("avrdude", args, stderr_to_stdout: true) + if is_tuple(result) do {a, exit_code} = result FarmbotCore.Logger.info(3, inspect(a)) diff --git a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex index c379d5dc..f1874783 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls/flash_firmware.ex @@ -1,3 +1,5 @@ +Application.get_env(:farmbot, FarmbotOS.SysCalls.FlashFirmware, [])[:gpio] + defmodule FarmbotOS.SysCalls.FlashFirmware do @moduledoc false @@ -92,7 +94,7 @@ defmodule FarmbotOS.SysCalls.FlashFirmware do {:ok, &FarmbotFirmware.NullReset.reset/0} end - defp express_reset_fun() do + def express_reset_fun() do try do FarmbotCore.Logger.debug(3, "Begin MCU reset") {:ok, gpio} = @gpio.open(19, :output) From bfb4f21f5450178149c14dff2ca587fa9cd97aec Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Mon, 13 Apr 2020 11:47:49 -0500 Subject: [PATCH 21/27] v9.2.2-rc20 --- CHANGELOG.md | 3 +++ VERSION | 2 +- farmbot_core/lib/farmbot_core/asset.ex | 3 --- farmbot_os/lib/avrdude.ex | 12 ------------ 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f409175..032c1dab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ * Unit test additions (+2.7% coverage :tada:) * Updates to build instructions for third party developers * Bug fix for criteria-based groups that have only one filter criteria. + * Bug fix for express bots involving timeout during remote firmware flash + * Remove VCR again (for now) + * Increase farmware timeout to 20 minutes (use at own risk) # 9.2.1 diff --git a/VERSION b/VERSION index a22826d8..82aec3ad 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc19 +9.2.2-rc20 diff --git a/farmbot_core/lib/farmbot_core/asset.ex b/farmbot_core/lib/farmbot_core/asset.ex index 457d4d9f..574cbdfc 100644 --- a/farmbot_core/lib/farmbot_core/asset.ex +++ b/farmbot_core/lib/farmbot_core/asset.ex @@ -324,9 +324,6 @@ defmodule FarmbotCore.Asset do sorted = CriteriaRetriever.run(point_group) |> sort_points(sort_by || "xy_ascending") |> Enum.map(fn point -> point.id end) - - count = Enum.count(sorted) - Logger.debug("There are #{count} points. #{inspect(sorted)}") %{ point_group | point_ids: sorted } other -> # Swallow all other errors diff --git a/farmbot_os/lib/avrdude.ex b/farmbot_os/lib/avrdude.ex index f43af1fd..5c87e4c2 100644 --- a/farmbot_os/lib/avrdude.ex +++ b/farmbot_os/lib/avrdude.ex @@ -17,7 +17,6 @@ defmodule Avrdude do _ = File.stat!(hex_path) - # STEP 1: Is the UART in use? args = [ "-patmega2560", "-cwiring", @@ -31,17 +30,6 @@ defmodule Avrdude do FarmbotCore.Logger.info(3, "Writing firmware to MCU...") - FarmbotCore.Logger.debug( - 1, - inspect(%{ - args: args, - into: IO.stream(:stdio, :line), - stderr_to_stdout: true - }) - ) - - FarmbotCore.Logger.info(3, "Writing firmware to MCU...") - call_reset_fun(reset_fun) result = MuonTrap.cmd("avrdude", args, stderr_to_stdout: true) From 7ca2725540cc0c7477137524c2d66437976a3b7d Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Mon, 13 Apr 2020 12:21:19 -0500 Subject: [PATCH 22/27] v9.2.2-rc20 - Possible fix for time-based criteria. --- VERSION | 2 +- farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex | 8 +++++--- farmbot_core/test/asset/criteria_retriever_test.exs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/VERSION b/VERSION index 82aec3ad..38ac43e1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc20 +9.2.2-rc21 diff --git a/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex b/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex index db77e21a..ebb927ea 100644 --- a/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex +++ b/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex @@ -138,10 +138,12 @@ defmodule FarmbotCore.Asset.CriteriaRetriever do { pg, accum } else - op = day_criteria["op"] || "<" - time = Timex.shift(Timex.now(), days: -1 * days) + op = day_criteria["op"] || ">" + time = Timex.shift(Timex.now(), days: days) - { pg, accum ++ [{"created_at", op, time}] } + inverted_op = if op == ">" do "<" else ">" end + + { pg, accum ++ [{"created_at", inverted_op, time}] } end end diff --git a/farmbot_core/test/asset/criteria_retriever_test.exs b/farmbot_core/test/asset/criteria_retriever_test.exs index 8d08c9e9..c316b60d 100644 --- a/farmbot_core/test/asset/criteria_retriever_test.exs +++ b/farmbot_core/test/asset/criteria_retriever_test.exs @@ -13,7 +13,7 @@ defmodule FarmbotCore.Asset.CriteriaRetrieverTest do @fake_point_group %PointGroup{ criteria: %{ - "day" => %{"op" => "<", "days_ago" => 4}, + "day" => %{"op" => ">", "days_ago" => 4}, "string_eq" => %{ "openfarm_slug" => ["five", "nine"], "meta.created_by" => ["plant-detection"] From 5eeebba6cfc97c39e2ca4e56af2a2073410fe5a9 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Mon, 13 Apr 2020 12:26:52 -0500 Subject: [PATCH 23/27] v9.2.2-rc22 - Possible fix for time-based criteria. --- VERSION | 2 +- farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 38ac43e1..858f2f84 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc21 +9.2.2-rc22 diff --git a/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex b/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex index ebb927ea..ee1708e1 100644 --- a/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex +++ b/farmbot_core/lib/farmbot_core/asset/criteria_retriever.ex @@ -138,8 +138,8 @@ defmodule FarmbotCore.Asset.CriteriaRetriever do { pg, accum } else - op = day_criteria["op"] || ">" - time = Timex.shift(Timex.now(), days: days) + op = day_criteria["op"] || "<" + time = Timex.shift(Timex.now(), days: -1 * days) inverted_op = if op == ">" do "<" else ">" end From 8c4ee03193fadbd1d7f50690fb53608f868dd3a5 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Mon, 13 Apr 2020 13:51:42 -0500 Subject: [PATCH 24/27] v9.2.2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 858f2f84..21a050b4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.2.2-rc22 +9.2.2 From a55295f596404e0abc45ff091f6e01c7b4770c98 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Mon, 13 Apr 2020 13:58:06 -0500 Subject: [PATCH 25/27] Force rebuild --- farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs b/farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs index bd96a596..c112227e 100644 --- a/farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs +++ b/farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs @@ -78,7 +78,7 @@ defmodule AutoSyncChannelTest do # Helpers.expect_log("Failed to connect to AutoSync channel: :whatever") # Helpers.expect_log("Disconnected from AutoSync channel: :normal") pid = generate_pid() - IO.puts(" = = = ==RICK: This test blinks and you should fix it.") + IO.puts(" =====RICK: This test blinks and you should fix it.") assert %{chan: nil, conn: nil, preloaded: true} == AutoSyncChannel.network_status(pid) GenServer.stop(pid, :normal) end From 37222d09d63e37112f655292a7f9c40f8d6dfa45 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Mon, 13 Apr 2020 14:03:45 -0500 Subject: [PATCH 26/27] CI debug: Possible race condition, again? --- farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs | 1 + farmbot_ext/test/test_helper.exs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs b/farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs index c112227e..f520c748 100644 --- a/farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs +++ b/farmbot_ext/test/farmbot_ext/amqp/auto_sync_channel_test.exs @@ -155,5 +155,6 @@ defmodule AutoSyncChannelTest do end) Helpers.wait_for(pid) + Process.sleep(1000) end end diff --git a/farmbot_ext/test/test_helper.exs b/farmbot_ext/test/test_helper.exs index 40f2c1b8..f25435b9 100644 --- a/farmbot_ext/test/test_helper.exs +++ b/farmbot_ext/test/test_helper.exs @@ -27,7 +27,7 @@ defmodule Helpers do # Maybe I could use `start_supervised`? # https://hexdocs.pm/ex_unit/ExUnit.Callbacks.html#start_supervised/2 - @wait_time 60 + @wait_time 180 # Base case: We have a pid def wait_for(pid) when is_pid(pid), do: check_on_mbox(pid) # Failure case: We failed to find a pid for a module. From 1bb175a387ebebc6340bb13b721561864998f2a2 Mon Sep 17 00:00:00 2001 From: Gabriel Burnworth Date: Mon, 13 Apr 2020 15:54:51 -0700 Subject: [PATCH 27/27] Update FEATURE_MIN_VERSIONS.json [skip ci] --- FEATURE_MIN_VERSIONS.json | 1 + 1 file changed, 1 insertion(+) diff --git a/FEATURE_MIN_VERSIONS.json b/FEATURE_MIN_VERSIONS.json index 057eb51d..68a5bf07 100644 --- a/FEATURE_MIN_VERSIONS.json +++ b/FEATURE_MIN_VERSIONS.json @@ -5,6 +5,7 @@ "assertion_block": "8.0.0", "backscheduled_regimens": "6.4.0", "change_ownership": "6.3.0", + "criteria_groups": "9.2.2", "diagnostic_dumps": "6.4.4", "endstop_invert": "6.4.1", "express_k10": "8.0.0",