From 8a816ba1f468fb3be3116c5774d59edc769429c8 Mon Sep 17 00:00:00 2001 From: Connor Rigby Date: Fri, 13 Sep 2019 15:21:54 -0700 Subject: [PATCH] Change if and read_pin to function the same as v7 this prevents the possibility of reading a sensor and it changing by the time an if statement is executed --- .../lib/farmbot_celery_script/compiler.ex | 13 +++--- .../lib/farmbot_celery_script/sys_calls.ex | 30 ++++++++++++++ .../farmbot_celery_script/sys_calls/stubs.ex | 12 ++++++ farmbot_os/lib/farmbot_os/sys_calls.ex | 28 +++++++++++++ .../lib/farmbot_os/sys_calls/pin_control.ex | 20 +++++---- .../lib/farmbot_os/sys_calls/send_message.ex | 41 +++++++------------ test/support/celery_script/test_sys_calls.ex | 20 +++++++++ 7 files changed, 124 insertions(+), 40 deletions(-) diff --git a/farmbot_celery_script/lib/farmbot_celery_script/compiler.ex b/farmbot_celery_script/lib/farmbot_celery_script/compiler.ex index a33711e6..cb872b6f 100644 --- a/farmbot_celery_script/lib/farmbot_celery_script/compiler.ex +++ b/farmbot_celery_script/lib/farmbot_celery_script/compiler.ex @@ -267,23 +267,26 @@ defmodule FarmbotCeleryScript.Compiler do lhs = case lhs_ast do "x" -> - quote [location: :keep], do: FarmbotCeleryScript.SysCalls.get_current_x() + quote [location: :keep], + do: FarmbotCeleryScript.SysCalls.get_cached_x() "y" -> - quote [location: :keep], do: FarmbotCeleryScript.SysCalls.get_current_y() + quote [location: :keep], + do: FarmbotCeleryScript.SysCalls.get_cached_y() "z" -> - quote [location: :keep], do: FarmbotCeleryScript.SysCalls.get_current_z() + quote [location: :keep], + do: FarmbotCeleryScript.SysCalls.get_cached_z() "pin" <> pin -> quote [location: :keep], - do: FarmbotCeleryScript.SysCalls.read_pin(unquote(String.to_integer(pin)), nil) + do: FarmbotCeleryScript.SysCalls.read_cached_pin(unquote(String.to_integer(pin))) # Named pin has two intents here # in this case we want to read the named pin. %AST{kind: :named_pin} = ast -> quote [location: :keep], - do: FarmbotCeleryScript.SysCalls.read_pin(unquote(compile_ast(ast)), nil) + do: FarmbotCeleryScript.SysCalls.read_cached_pin(unquote(compile_ast(ast))) %AST{} = ast -> compile_ast(ast) diff --git a/farmbot_celery_script/lib/farmbot_celery_script/sys_calls.ex b/farmbot_celery_script/lib/farmbot_celery_script/sys_calls.ex index ded8b08d..b2fe8ae5 100644 --- a/farmbot_celery_script/lib/farmbot_celery_script/sys_calls.ex +++ b/farmbot_celery_script/lib/farmbot_celery_script/sys_calls.ex @@ -38,6 +38,11 @@ defmodule FarmbotCeleryScript.SysCalls do @callback get_current_x() :: number() | error() @callback get_current_y() :: number() | error() @callback get_current_z() :: number() | error() + + @callback get_cached_x() :: number() | error() + @callback get_cached_y() :: number() | error() + @callback get_cached_z() :: number() | error() + @callback get_sequence(resource_id) :: FarmbotCeleryScript.AST.t() | error() @callback get_toolslot_for_tool(resource_id) :: %{x: number(), y: number(), z: number()} | error() @@ -51,6 +56,7 @@ defmodule FarmbotCeleryScript.SysCalls do @callback point(point_type :: String.t(), resource_id) :: number() | error() @callback power_off() :: ok_or_error @callback read_pin(pin_num :: number(), pin_mode :: number()) :: number | error() + @callback read_cached_pin(pin_num :: number()) :: number | error() @callback toggle_pin(pin_num :: number()) :: ok_or_error @callback read_status() :: ok_or_error @callback reboot() :: ok_or_error @@ -184,6 +190,18 @@ defmodule FarmbotCeleryScript.SysCalls do number_or_error(sys_calls, :get_current_z, []) end + def get_cached_x(sys_calls \\ @sys_calls) do + number_or_nil_or_error(sys_calls, :get_cached_x, []) + end + + def get_cached_y(sys_calls \\ @sys_calls) do + number_or_nil_or_error(sys_calls, :get_cached_y, []) + end + + def get_cached_z(sys_calls \\ @sys_calls) do + number_or_nil_or_error(sys_calls, :get_cached_z, []) + end + def get_sequence(sys_calls \\ @sys_calls, sequence_id) do case sys_calls.get_sequence(sequence_id) do %AST{} = ast -> ast @@ -236,6 +254,10 @@ defmodule FarmbotCeleryScript.SysCalls do number_or_error(sys_calls, :read_pin, [pin_num, pin_mode]) end + def read_cached_pin(sys_calls \\ @sys_calls, pin_num) do + number_or_nil_or_error(sys_calls, :read_cached_pin, [pin_num]) + end + def toggle_pin(sys_calls \\ @sys_calls, pun_num) do ok_or_error(sys_calls, :toggle_pin, [pun_num]) end @@ -298,6 +320,14 @@ defmodule FarmbotCeleryScript.SysCalls do end end + defp number_or_nil_or_error(sys_calls, fun, args) do + case apply(sys_calls, fun, args) do + result when is_number(result) -> result + nil -> nil + error -> or_error(sys_calls, fun, args, error) + end + end + defp coord_or_error(sys_calls, fun, args) do case apply(sys_calls, fun, args) do %{x: x, y: y, z: z} = coord when is_number(x) when is_number(y) when is_number(z) -> coord diff --git a/farmbot_celery_script/lib/farmbot_celery_script/sys_calls/stubs.ex b/farmbot_celery_script/lib/farmbot_celery_script/sys_calls/stubs.ex index a888484a..569d8d0e 100644 --- a/farmbot_celery_script/lib/farmbot_celery_script/sys_calls/stubs.ex +++ b/farmbot_celery_script/lib/farmbot_celery_script/sys_calls/stubs.ex @@ -64,6 +64,15 @@ defmodule FarmbotCeleryScript.SysCalls.Stubs do @impl true def get_current_z(), do: error(:get_current_z, []) + @impl true + def get_cached_x(), do: error(:get_cached_x, []) + + @impl true + def get_cached_y(), do: error(:get_cached_y, []) + + @impl true + def get_cached_z(), do: error(:get_cached_z, []) + @impl true def get_sequence(resource_id), do: error(:get_sequence, [resource_id]) @@ -94,6 +103,9 @@ defmodule FarmbotCeleryScript.SysCalls.Stubs do @impl true def read_pin(pin_num, pin_mode), do: error(:read_pin, [pin_num, pin_mode]) + @impl true + def read_cached_pin(pin_num), do: error(:read_cached_pin, [pin_num]) + @impl true def toggle_pin(pin_num), do: error(:toggle_pin, [pin_num]) diff --git a/farmbot_os/lib/farmbot_os/sys_calls.ex b/farmbot_os/lib/farmbot_os/sys_calls.ex index 8defa374..fe14c6c7 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls.ex @@ -66,6 +66,9 @@ defmodule FarmbotOS.SysCalls do @impl true defdelegate read_pin(number, mode), to: PinControl + @impl true + defdelegate read_cached_pin(number), to: PinControl + @impl true defdelegate write_pin(number, mode, value), to: PinControl @@ -171,6 +174,21 @@ defmodule FarmbotOS.SysCalls do get_position(:z) end + @impl true + def get_cached_x do + get_cached_position(:x) + end + + @impl true + def get_cached_y do + get_cached_position(:y) + end + + @impl true + def get_cached_z do + get_cached_position(:z) + end + @impl true def zero(axis) do axis = assert_axis!(axis) @@ -211,6 +229,16 @@ defmodule FarmbotOS.SysCalls do end end + def get_cached_position() do + %{x: x, y: y, z: z} = FarmbotCore.BotState.fetch().location_data.position + [x: x, y: y, z: z] + end + + def get_cached_position(axis) do + axis = assert_axis!(axis) + Keyword.fetch!(get_cached_position(), axis) + end + @impl true def move_absolute(x, y, z, speed) do do_move_absolute(x, y, z, speed, max_retries()) diff --git a/farmbot_os/lib/farmbot_os/sys_calls/pin_control.ex b/farmbot_os/lib/farmbot_os/sys_calls/pin_control.ex index 6dce79ff..962c40e3 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls/pin_control.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls/pin_control.ex @@ -9,6 +9,14 @@ defmodule FarmbotOS.SysCalls.PinControl do require FarmbotCore.Logger + def read_cached_pin(%_{pin: number}) do + read_cached_pin(number) + end + + def read_cached_pin(pin_number) do + FarmbotCore.BotState.fetch().pins()[pin_number][:value] + end + def toggle_pin(pin_number) when is_number(pin_number) do peripheral = Asset.get_peripheral_by_pin(pin_number) @@ -198,19 +206,16 @@ defmodule FarmbotOS.SysCalls.PinControl do end # Peripheral digital - def write_pin(%Peripheral{pin: pin, label: label}, 0, 1) do - FarmbotCore.Logger.info(2, "Turning the #{label} ON (digital)") + def write_pin(%Peripheral{pin: pin, label: _label}, 0, 1) do do_write_pin(pin, 0, 1) end - def write_pin(%Peripheral{pin: pin, label: label}, 0, 0) do - FarmbotCore.Logger.info(2, "Turning the #{label} OFF (digital)") + def write_pin(%Peripheral{pin: pin, label: _label}, 0, 0) do do_write_pin(pin, 0, 0) end # Peripheral analog - def write_pin(%Peripheral{pin: pin, label: label}, 1, value) do - FarmbotCore.Logger.info(2, "Setting the #{label} to #{value} (analog)") + def write_pin(%Peripheral{pin: pin, label: _label}, 1, _value) do do_write_pin(pin, 0, 0) end @@ -248,17 +253,14 @@ defmodule FarmbotOS.SysCalls.PinControl do # Generic pin digital def write_pin(pin, 0, 1) do - FarmbotCore.Logger.info(2, "Turning pin #{pin} ON (digital)") do_write_pin(pin, 0, 1) end def write_pin(pin, 0, 0) do - FarmbotCore.Logger.info(2, "Turning pin #{pin} OFF (digital)") do_write_pin(pin, 0, 0) end def write_pin(pin, 1, value) do - FarmbotCore.Logger.info(2, "Setting pin #{pin} to #{value} (analog)") do_write_pin(pin, 1, value) end diff --git a/farmbot_os/lib/farmbot_os/sys_calls/send_message.ex b/farmbot_os/lib/farmbot_os/sys_calls/send_message.ex index bf511bda..f617ca6c 100644 --- a/farmbot_os/lib/farmbot_os/sys_calls/send_message.ex +++ b/farmbot_os/lib/farmbot_os/sys_calls/send_message.ex @@ -22,7 +22,7 @@ defmodule FarmbotOS.SysCalls.SendMessage do def render(templ) do with {:ok, pos} <- pos(), - {:ok, pins} <- pins(Enum.to_list(0..69)), + {:ok, pins} <- pins(), env <- Keyword.merge(pos, pins) do env = Map.new(env, fn {k, v} -> {to_string(k), to_string(v)} end) @@ -44,33 +44,22 @@ defmodule FarmbotOS.SysCalls.SendMessage do end def pos do - case FarmbotFirmware.request({:position_read, []}) do - {:ok, {_, {:report_position, [x: x, y: y, z: z]}}} -> - {:ok, - [ - x: FarmbotCeleryScript.FormatUtil.format_float(x), - y: FarmbotCeleryScript.FormatUtil.format_float(y), - z: FarmbotCeleryScript.FormatUtil.format_float(z) - ]} + [x: x, y: y, z: z] = FarmbotOS.SysCalls.get_cached_position() - {:error, reason} -> - {:error, inspect(reason)} - end + {:ok, + [ + x: FarmbotCeleryScript.FormatUtil.format_float(x), + y: FarmbotCeleryScript.FormatUtil.format_float(y), + z: FarmbotCeleryScript.FormatUtil.format_float(z) + ]} end - def pins(nums, acc \\ []) - - def pins([p | rest], acc) do - case FarmbotFirmware.request({:pin_read, [p: p]}) do - {:ok, {_, {:report_pin_value, [p: ^p, v: v]}}} -> - v = FarmbotCeleryScript.FormatUtil.format_float(v) - acc = Keyword.put(acc, :"pin#{p}", v) - pins(rest, acc) - - er -> - er - end + def pins() do + {:ok, + FarmbotCore.BotState.fetch().pins + |> Map.new() + |> Enum.map(fn {p, %{value: v}} -> + {:"pin#{p}", FarmbotCeleryScript.FormatUtil.format_float(v)} + end)} end - - def pins([], acc), do: {:ok, acc} end diff --git a/test/support/celery_script/test_sys_calls.ex b/test/support/celery_script/test_sys_calls.ex index c20fbd88..2e4fc773 100644 --- a/test/support/celery_script/test_sys_calls.ex +++ b/test/support/celery_script/test_sys_calls.ex @@ -106,6 +106,21 @@ defmodule Farmbot.TestSupport.CeleryScript.TestSysCalls do call({:get_current_z, []}) end + @impl true + def get_cached_x do + call({:get_cached_x, []}) + end + + @impl true + def get_cached_y do + call({:get_cached_y, []}) + end + + @impl true + def get_cached_z do + call({:get_cached_z, []}) + end + @impl true def write_pin(pin_number, mode, value) do call({:write_pin, [pin_number, mode, value]}) @@ -121,6 +136,11 @@ defmodule Farmbot.TestSupport.CeleryScript.TestSysCalls do call({:read_pin, [number, mode]}) end + @impl true + def read_cached_pin(number) do + call({:read_cached_pin, [number]}) + end + @impl true def toggle_pin(number) do call({:toggle_pin, [number]})