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
pull/974/head
Connor Rigby 2019-09-13 15:21:54 -07:00
parent b42992c3c8
commit 8a816ba1f4
No known key found for this signature in database
GPG Key ID: 29A88B24B70456E0
7 changed files with 124 additions and 40 deletions

View File

@ -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)

View File

@ -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

View File

@ -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])

View File

@ -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())

View File

@ -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

View File

@ -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

View File

@ -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]})