Skip to content
Permalink
Browse files

Add Lua helpers for updating and getting resources

  • Loading branch information...
ConnorRigby committed Aug 23, 2019
1 parent c9be1e3 commit 22a3cc908da3218b8ead5836578256d7f36b296c
@@ -11,12 +11,6 @@ standard library](https://www.lua.org/manual/5.2/).
```lua
-- Comments are ignored by the interpreter
-- help(function_name)
-- Returns docs for a function
print(help("send_message"));
print(help("get_position"));
-- get_position()
-- Returns a table containing the current position data
@@ -28,6 +22,8 @@ else
return false;
end
return get_position("y") <= 20;
-- get_pins()
-- Returns a table containing current pin data
@@ -36,10 +32,106 @@ if pins[9] == 1.0 then
return true;
end
return get_pin(10) == 0;
-- send_message(type, message, channels)
-- Sends a message to farmbot's logger
send_message("info", "hello, world", ["toast"])
send_message("info", "hello, world", ["toast"]);
-- calibrate(axis)
-- calibrate an axis
calibrate("x");
calibrate("y");
calibrate("z");
-- emergency_lock()
-- emergency_unlock()
-- lock and unlock farmbot's firmware.
send_message("error", "locking the firmware!");
emergancy_lock();
emergency_unlock();
-- find_home(axis)
-- Find home on an axis.
find_home("x");
find_home("y");
find_home("z");
-- home(axis)
-- Go to home on an axis.
home("x");
home("y");
home("z");
-- coordinate(x, y, z)
-- create a vec3
move_to = coordinate(1.0, 0, 0);
-- move_absolute(x, y, z)
-- Move in a line to a position
move_absolute(1.0, 0, 0);
move_absolute(coordinate(1.0, 20, 30));
-- check_position(vec3, tolerance)
-- Check a position against Farmbot's current
-- position within a error threshold
move_absolute(1.0, 0, 0);
return check_position({x = 1.0, y = 0; z = 0}, 0.50);
move_absolute(20, 100, 100);
return check_position(coordinate(20, 100, 100), 1);
-- read_status(arg0)
-- Get a field on farmbot's current state
status = read_status();
return status.informational_settings.wifi_level >= 5;
return read_status("location_data", "raw_encoders") >= 1900;
-- version()
-- return Farmbot's current version
return version() == "8.1.2";
-- get_device(field)
-- return the device settings
return get_device().timezone == "America/los_angeles";
return get_device("name") == "Test Farmbot";
-- update_device(table)
-- update device settings
update_device({name = "Test Farmbot"});
-- get_fbos_config(field)
-- return the current fbos_config
return get_fbos_config("auto_sync");
return get_fbos_config().os_auto_update;
-- update_fbos_config(table)
-- update the current fbos_config
update_fbos_config({auto_sync = true, os_auto_update = false});
-- get_firmware_config(field)
-- return current firmware_config data
return get_firmware_config().encoder_enabled_x == 1.0;
return get_firmware_config("encoder_enabled_z");
-- update_firmware_config(table)
-- update current firmware_config data
update_firmware_config({encoder_enabled_z = 1.0});
```

## Expression contract
@@ -187,11 +187,16 @@ defmodule FarmbotCeleryScript.Compiler do

quote location: :keep do
comment_header = unquote(comment_header)
assertion_type = unquote(assertion_type)

case FarmbotCeleryScript.SysCalls.eval_assertion(unquote(compile_ast(expression))) do
case FarmbotCeleryScript.SysCalls.eval_assertion(
unquote(comment),
unquote(compile_ast(expression))
) do
{:error, reason} ->
FarmbotCeleryScript.SysCalls.log_assertion(
false,
assertion_type,
"#{comment_header}failed to evaluate, aborting"
)

@@ -200,34 +205,43 @@ defmodule FarmbotCeleryScript.Compiler do
true ->
FarmbotCeleryScript.SysCalls.log_assertion(
true,
assertion_type,
"#{comment_header}passed, continuing execution"
)

:ok

false when unquote(assertion_type) == "continue" ->
false when assertion_type == "continue" ->
FarmbotCeleryScript.SysCalls.log_assertion(
false,
assertion_type,
"#{comment_header}failed, continuing execution"
)

:ok

false when unquote(assertion_type) == "abort" ->
FarmbotCeleryScript.SysCalls.log_assertion(false, "#{comment_header}failed, aborting")
false when assertion_type == "abort" ->
FarmbotCeleryScript.SysCalls.log_assertion(
false,
assertion_type,
"#{comment_header}failed, aborting"
)

{:error, "Assertion failed (aborting)"}

false when unquote(assertion_type) == "recover" ->
false when assertion_type == "recover" ->
FarmbotCeleryScript.SysCalls.log_assertion(
false,
assertion_type,
"#{comment_header}failed, recovering and continuing"
)

unquote(compile_block(then_ast))

false when unquote(assertion_type) == "abort_recover" ->
false when assertion_type == "abort_recover" ->
FarmbotCeleryScript.SysCalls.log_assertion(
false,
assertion_type,
"#{comment_header}failed, recovering and aborting"
)

@@ -67,24 +67,25 @@ defmodule FarmbotCeleryScript.SysCalls do
@callback log(message :: String.t()) :: any()
@callback sequence_init_log(message :: String.t()) :: any()
@callback sequence_complete_log(message :: String.t()) :: any()
@callback eval_assertion(expression :: String.t()) :: true | false | error()
@callback eval_assertion(comment :: String.t(), expression :: String.t()) ::
true | false | error()

def eval_assertion(sys_calls \\ @sys_calls, expression) when is_binary(expression) do
case sys_calls.eval_assertion(expression) do
def eval_assertion(sys_calls \\ @sys_calls, comment, expression) when is_binary(expression) do
case sys_calls.eval_assertion(comment, expression) do
true ->
true

false ->
false

{:error, reason} when is_binary(reason) ->
or_error(sys_calls, :eval_assertion, [expression], reason)
{:error, reason} = error when is_binary(reason) ->
or_error(sys_calls, :eval_assertion, [comment, expression], error)
end
end

def log_assertion(sys_calls \\ @sys_calls, passed?, message) do
if function_exported?(sys_calls, :log_assertion, 2) do
apply(sys_calls, :log_assertion, [passed?, message])
def log_assertion(sys_calls \\ @sys_calls, passed?, type, message) do
if function_exported?(sys_calls, :log_assertion, 3) do
apply(sys_calls, :log_assertion, [passed?, type, message])
end
end

@@ -130,7 +130,7 @@ defmodule FarmbotCeleryScript.SysCalls.Stubs do
def zero(axis), do: error(:zero, [axis])

@impl true
def eval_assertion(expression), do: error(:eval_assertion, [expression])
def eval_assertion(comment, expression), do: error(:eval_assertion, [comment, expression])

defp error(fun, _args) do
msg = """
@@ -96,7 +96,10 @@ defmodule FarmbotExt.AMQP.LogChannel do
# ANSWER(Connor) - because the FE needed it.
created_at: DateTime.from_naive!(log.inserted_at, "Etc/UTC") |> DateTime.to_unix(),
channels: log.meta[:channels] || log.meta["channels"] || [],
assertion_passed: log.meta[:assertion_passed],
meta: %{
assertion_passed: log.meta[:assertion_passed],
assertion_type: log.meta[:assertion_type]
},
message: log.message
}

@@ -1,21 +1,24 @@
defmodule FarmbotOS.Lua do
@type t() :: tuple()
@type table() :: [{any, any}]
require FarmbotCore.Logger

alias FarmbotOS.Lua.Ext.{
Data,
Firmware,
Info
}

def log_assertion(passed?, message) do
# FarmbotCore.Logger.dispatch_log(__ENV__, :assertion, 2, message, [assertion_passed: passed?])
FarmbotCore.Logger.dispatch_log(__ENV__, :info, 2, message, assertion_passed: passed?)
def log_assertion(passed?, type, message) do
meta = [assertion_passed: passed?, assertion_type: type]
FarmbotCore.Logger.dispatch_log(__ENV__, :assertion, 2, message, meta)
end

@doc """
Evaluates some Lua code. The code should
return a boolean value.
"""
def eval_assertion(str) when is_binary(str) do
def eval_assertion(comment, str) when is_binary(str) do
init()
|> eval(str)
|> case do
@@ -35,6 +38,17 @@ defmodule FarmbotOS.Lua do
{:error, "lua runtime error evaluating expression"}

{:error, {:badmatch, {:error, [{line, :luerl_parse, parse_error}], _}}} ->
FarmbotCore.Logger.error(
1,
"""
Failed to parse expression:
`#{comment}.lua:#{line}`
#{IO.iodata_to_binary(parse_error)}
""",
channels: [:toast]
)

{:error, "failed to parse expression (line:#{line}): #{IO.iodata_to_binary(parse_error)}"}

error ->
@@ -59,6 +73,14 @@ defmodule FarmbotOS.Lua do
|> set_table([:read_status], &Info.read_status/2)
|> set_table([:send_message], &Info.send_message/2)
|> set_table([:version], &Info.version/2)
|> set_table([:update_device], &Data.update_device/2)
|> set_table([:get_device], &Data.get_device/2)
|> set_table([:update_fbos_config], &Data.update_fbos_config/2)
|> set_table([:get_fbos_config], &Data.get_fbos_config/2)
|> set_table([:update_firmware_config], &Data.update_firmware_config/2)
|> set_table([:get_firmware_config], &Data.get_firmware_config/2)
|> set_table([:new_farmware_env], &Data.new_farmware_env/2)
|> set_table([:new_sensor_reading], &Data.new_sensor_reading/2)
end

@spec set_table(t(), Path.t(), any()) :: t()
@@ -0,0 +1,73 @@
defmodule FarmbotOS.Lua.Ext.Data do
@moduledoc """
Extensions for manipulating data from Lua
"""
import FarmbotOS.Lua.Util

alias FarmbotCore.{
Asset,
Asset.Device,
Asset.FbosConfig,
Asset.FirmwareConfig
}

def update_device([table], lua) do
params = Map.new(table)
_ = Asset.update_device!(params)
{[true], lua}
end

def get_device([field], lua) do
device = Asset.device() |> Device.render()
{[device[String.to_atom(field)]], lua}
end

def get_device(_, lua) do
device = Asset.device() |> Device.render()
{[map_to_table(device)], lua}
end

def update_fbos_config([table], lua) do
params = Map.new(table)
_ = Asset.update_fbos_config!(params)
{[true], lua}
end

def get_fbos_config([field], lua) do
fbos_config = Asset.fbos_config() |> FbosConfig.render()
{[fbos_config[String.to_atom(field)]], lua}
end

def get_fbos_config(_, lua) do
fbos_config = Asset.fbos_config() |> FbosConfig.render()
{[map_to_table(fbos_config)], lua}
end

def update_firmware_config([table], lua) do
params = Map.new(table)
_ = Asset.update_firmware_config!(params)
{[true], lua}
end

def get_firmware_config([field], lua) do
firmware_config = Asset.firmware_config() |> FirmwareConfig.render()
{[firmware_config[String.to_atom(field)]], lua}
end

def get_firmware_config(_, lua) do
firmware_config = Asset.firmware_config() |> FirmwareConfig.render()
{[map_to_table(firmware_config)], lua}
end

def new_farmware_env([table], lua) do
params = Map.new(table)
_ = Asset.new_farmware_env(params)
{[true], lua}
end

def new_sensor_reading([table], lua) do
params = Map.new(table)
_ = Asset.new_sensor_reading!(params)
{[true], lua}
end
end

0 comments on commit 22a3cc9

Please sign in to comment.
You can’t perform that action at this time.