Yay. many nodes working again
This commit is contained in:
parent
6782e88792
commit
d6bdfd3433
|
@ -8,9 +8,13 @@ defmodule Farmbot.BotState do
|
|||
@target Mix.Project.config()[:target]
|
||||
@env Mix.env()
|
||||
|
||||
alias Farmbot.CeleryScript.AST
|
||||
|
||||
defstruct mcu_params: %{},
|
||||
jobs: %{},
|
||||
location_data: %{},
|
||||
location_data: %{
|
||||
position: %{x: -1, y: -1, z: -1}
|
||||
},
|
||||
pins: %{},
|
||||
configuration: %{},
|
||||
informational_settings: %{
|
||||
|
@ -27,6 +31,11 @@ defmodule Farmbot.BotState do
|
|||
GenStage.call(__MODULE__, :force_state_push)
|
||||
end
|
||||
|
||||
@doc "Emit an AST."
|
||||
def emit(%AST{} = ast) do
|
||||
GenStage.call(__MODULE__, {:emit, ast})
|
||||
end
|
||||
|
||||
def get_user_env do
|
||||
# GenStage.call(__MODULE__, :get_user_env)
|
||||
%{}
|
||||
|
@ -54,6 +63,10 @@ defmodule Farmbot.BotState do
|
|||
{:reply, state, [state], state}
|
||||
end
|
||||
|
||||
def handle_call({:emit, ast}, _from, state) do
|
||||
{:reply, :ok, [{:emit, ast}], state}
|
||||
end
|
||||
|
||||
defp do_handle([], state), do: state
|
||||
|
||||
defp do_handle([{key, diff} | rest], state) do
|
||||
|
|
|
@ -2,6 +2,7 @@ defmodule Farmbot.BotState.Transport.GenMQTT.Client do
|
|||
@moduledoc "Underlying client for interfacing MQTT."
|
||||
use GenMQTT
|
||||
require Logger
|
||||
alias Farmbot.CeleryScript.AST
|
||||
|
||||
@doc "Start a MQTT Client."
|
||||
def start_link(device, token, server) do
|
||||
|
@ -26,6 +27,11 @@ defmodule Farmbot.BotState.Transport.GenMQTT.Client do
|
|||
GenMQTT.cast(client, {:bot_log, log})
|
||||
end
|
||||
|
||||
@doc "Emit an AST to the frontend."
|
||||
def emit(client, %AST{} = ast) do
|
||||
GenMQTT.cast(client, {:emit, ast})
|
||||
end
|
||||
|
||||
def init({device, _server}) do
|
||||
{:ok, %{connected: false, device: device, cache: nil}}
|
||||
end
|
||||
|
@ -59,10 +65,10 @@ defmodule Farmbot.BotState.Transport.GenMQTT.Client do
|
|||
end
|
||||
|
||||
def on_publish(["bot", _bot, "from_clients"], msg, state) do
|
||||
Logger.warn("not implemented yet: #{inspect Poison.decode!(msg) |> Farmbot.CeleryScript.AST.decode()}")
|
||||
msg
|
||||
|> Poison.decode!()
|
||||
|> Farmbot.CeleryScript.AST.decode()
|
||||
|> elem(1)
|
||||
|> Farmbot.CeleryScript.execute()
|
||||
{:ok, state}
|
||||
end
|
||||
|
@ -79,23 +85,30 @@ defmodule Farmbot.BotState.Transport.GenMQTT.Client do
|
|||
{:ok, state}
|
||||
end
|
||||
|
||||
def handle_cast(_, %{connected: false} = state) do
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_cast({:bot_state, bs}, state) do
|
||||
json = Poison.encode!(bs)
|
||||
GenMQTT.publish(self(), status_topic(state.device), json, 0, false)
|
||||
{:noreply, %{state | cache: json}}
|
||||
end
|
||||
|
||||
def handle_cast(_, %{connected: false} = state) do
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_cast({:bot_log, log}, state) do
|
||||
json = Poison.encode!(log)
|
||||
GenMQTT.publish(self(), log_topic(state.device), json, 0, false)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
# defp frontend_topic(bot), do: "bot/#{bot}/from_device"
|
||||
def handle_cast({:emit, msg}, state) do
|
||||
{:ok, encoded_ast} = AST.encode(msg)
|
||||
json = Poison.encode!(encoded_ast)
|
||||
GenMQTT.publish(self(), frontend_topic(state.device), json, 0, false)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
defp frontend_topic(bot), do: "bot/#{bot}/from_device"
|
||||
defp bot_topic(bot), do: "bot/#{bot}/from_clients"
|
||||
defp sync_topic(bot), do: "bot/#{bot}/sync/#"
|
||||
defp status_topic(bot), do: "bot/#{bot}/status"
|
||||
|
|
|
@ -3,6 +3,7 @@ defmodule Farmbot.BotState.Transport.GenMQTT do
|
|||
use GenStage
|
||||
require Logger
|
||||
alias Farmbot.BotState.Transport.GenMQTT.Client
|
||||
alias Farmbot.CeleryScript.AST
|
||||
|
||||
@doc false
|
||||
def start_link do
|
||||
|
@ -31,12 +32,18 @@ defmodule Farmbot.BotState.Transport.GenMQTT do
|
|||
{:noreply, [], {internal_state, old_bot_state}}
|
||||
end
|
||||
|
||||
def handle_bot_state_events(events, {%{client: client} = internal_state, _old_bot_state}) do
|
||||
new_bot_state = List.last(events)
|
||||
def handle_bot_state_events([event | rest], {%{client: client} = internal_state, old_bot_state}) do
|
||||
case event do
|
||||
{:emit, %AST{} = ast} ->
|
||||
Client.emit(client, ast)
|
||||
handle_bot_state_events(rest, {internal_state, old_bot_state})
|
||||
new_bot_state ->
|
||||
Client.push_bot_state(client, new_bot_state)
|
||||
handle_bot_state_events(rest, {internal_state, new_bot_state})
|
||||
end
|
||||
end
|
||||
|
||||
Client.push_bot_state(client, new_bot_state)
|
||||
# if new_bot_state != old_bot_state do
|
||||
# end
|
||||
{:noreply, [], {internal_state, new_bot_state}}
|
||||
def handle_bot_state_events([], {internal, bot_state}) do
|
||||
{:noreply, [], {internal, bot_state}}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,5 +2,7 @@ defmodule Farmbot.CeleryScript.AST.Arg.Else do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: Farmbot.CeleryScript.AST.decode(val)
|
||||
def decode(val), do: Farmbot.CeleryScript.AST.decode(val)
|
||||
|
||||
def encode(ast), do: Farmbot.CeleryScript.AST.encode(ast)
|
||||
end
|
||||
|
|
|
@ -2,5 +2,7 @@ defmodule Farmbot.CeleryScript.AST.Arg.Then do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: Farmbot.CeleryScript.AST.decode(val)
|
||||
def decode(val), do: Farmbot.CeleryScript.AST.decode(val)
|
||||
|
||||
def encode(ast), do: Farmbot.CeleryScript.AST.encode(ast)
|
||||
end
|
||||
|
|
|
@ -2,8 +2,13 @@ defmodule Farmbot.CeleryScript.AST.Arg.Axis do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify("x"), do: {:ok, :x}
|
||||
def verify("y"), do: {:ok, :y}
|
||||
def verify("z"), do: {:ok, :z}
|
||||
def verify("all"), do: {:ok, :all}
|
||||
def decode("x"), do: {:ok, :x}
|
||||
def decode("y"), do: {:ok, :y}
|
||||
def decode("z"), do: {:ok, :z}
|
||||
def decode("all"), do: {:ok, :all}
|
||||
|
||||
def encode(:x), do: {:ok, "x"}
|
||||
def encode(:y), do: {:ok, "y"}
|
||||
def encode(:z), do: {:ok, "z"}
|
||||
def encode(:all), do: {:ok, "all"}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.ChannelName do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.IsOutdated do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Label do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,11 +2,16 @@ defmodule Farmbot.CeleryScript.AST.Arg.Lhs do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify("x"), do: {:ok, :x}
|
||||
def verify("y"), do: {:ok, :y}
|
||||
def verify("z"), do: {:ok, :z}
|
||||
def decode("x"), do: {:ok, :x}
|
||||
def decode("y"), do: {:ok, :y}
|
||||
def decode("z"), do: {:ok, :z}
|
||||
|
||||
def verify("pin" <> num), do: {:pin, String.to_integer(num)}
|
||||
def decode("pin" <> num), do: {:pin, String.to_integer(num)}
|
||||
|
||||
def verify(other), do: {:error, "unknown left hand side: #{inspect other}"}
|
||||
def decode(other), do: {:error, "unknown left hand side: #{inspect other}"}
|
||||
|
||||
def encode(:x), do: {:ok, "x"}
|
||||
def encode(:y), do: {:ok, "y"}
|
||||
def encode(:z), do: {:ok, "z"}
|
||||
def encode({:pin, num}), do: {:ok, "pin#{num}"}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,7 @@ defmodule Farmbot.CeleryScript.AST.Arg.Location do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: Farmbot.CeleryScript.AST.decode(val)
|
||||
def decode(val), do: Farmbot.CeleryScript.AST.decode(val)
|
||||
|
||||
def encode(ast), do: Farmbot.CeleryScript.AST.encode(ast)
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Message do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.MessageType do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Milliseconds do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,7 @@ defmodule Farmbot.CeleryScript.AST.Arg.Offset do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: Farmbot.CeleryScript.AST.decode(val)
|
||||
def decode(val), do: Farmbot.CeleryScript.AST.decode(val)
|
||||
|
||||
def encode(ast), do: Farmbot.CeleryScript.AST.encode(ast)
|
||||
end
|
||||
|
|
|
@ -2,10 +2,16 @@ defmodule Farmbot.CeleryScript.AST.Arg.Op do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify("is_undefined"), do: {:ok, :is_undefined}
|
||||
def verify("is"), do: {:ok, :==}
|
||||
def verify("not"), do: {:ok, :!=}
|
||||
def verify(">"), do: {:ok, :>}
|
||||
def verify("<"), do: {:ok, :<}
|
||||
def verify(other), do: {:error, "unexpected if operator: #{inspect other}"}
|
||||
def decode("is_undefined"), do: {:ok, :is_undefined}
|
||||
def decode("is"), do: {:ok, :==}
|
||||
def decode("not"), do: {:ok, :!=}
|
||||
def decode(">"), do: {:ok, :>}
|
||||
def decode("<"), do: {:ok, :<}
|
||||
def decode(other), do: {:error, "unexpected if operator: #{inspect other}"}
|
||||
|
||||
def encode(:is_undefined), do: {:ok, "is_undefined"}
|
||||
def encode(:==), do: {:ok, "is"}
|
||||
def encode(:!=), do: {:ok, "not"}
|
||||
def encode(:>), do: {:ok, ">"}
|
||||
def encode(:<), do: {:ok, "<"}
|
||||
end
|
||||
|
|
|
@ -2,7 +2,11 @@ defmodule Farmbot.CeleryScript.AST.Arg.Package do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify("farmbot_os"), do: {:ok, :farmbot_os}
|
||||
def verify("arduino_firmware"), do: {:ok, :arduino_firmware}
|
||||
def verify(other), do: {:ok, {:farmware, other}}
|
||||
def decode("farmbot_os"), do: {:ok, :farmbot_os}
|
||||
def decode("arduino_firmware"), do: {:ok, :arduino_firmware}
|
||||
def decode(other), do: {:ok, {:farmware, other}}
|
||||
|
||||
def encode(:farmbot_os), do: {:ok, "farmbot_os"}
|
||||
def encode(:arduino_firmware), do: {:ok, "arduino_firmware"}
|
||||
def encode({:farmware, package}), do: {:ok, "package"}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.PinMode do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.PinNumber do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.PinValue do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.PointerId do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.PointerType do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Radius do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,6 +2,8 @@ defmodule Farmbot.CeleryScript.AST.Arg.Rhs do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val) when is_number(val), do: {:ok, val}
|
||||
def verify(val), do: {:error, "unexpected right hand side: #{inspect val}"}
|
||||
def decode(val) when is_number(val), do: {:ok, val}
|
||||
def decode(val), do: {:error, "unexpected right hand side: #{inspect val}"}
|
||||
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.SequenceId do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Speed do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.ToolId do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Url do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Value do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Version do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.X do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Y do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -2,5 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Arg.Z do
|
|||
@moduledoc false
|
||||
@behaviour Farmbot.CeleryScript.AST.Arg
|
||||
|
||||
def verify(val), do: {:ok, val}
|
||||
def decode(val), do: {:ok, val}
|
||||
def encode(val), do: {:ok, val}
|
||||
end
|
||||
|
|
|
@ -24,6 +24,31 @@ defmodule Farmbot.CeleryScript.AST do
|
|||
# AST struct.
|
||||
defstruct [:kind, :args, :body, :comment]
|
||||
|
||||
@doc "Encode a AST back to a map."
|
||||
def encode(%__MODULE__{kind: mod, args: args, body: body, comment: comment}) do
|
||||
case mod.encode_args(args) do
|
||||
{:ok, encoded_args} ->
|
||||
case encode_body(body) do
|
||||
{:ok, encoded_body} ->
|
||||
{:ok, %{kind: mod_to_kind(mod), args: encoded_args, body: encoded_body, comment: comment}}
|
||||
{:error, _} = err -> err
|
||||
end
|
||||
{:error, _} = err -> err
|
||||
end
|
||||
end
|
||||
|
||||
@doc "Encode a list of asts."
|
||||
def encode_body(body, acc \\ [])
|
||||
|
||||
def encode_body([ast | rest], acc) do
|
||||
case encode(ast) do
|
||||
{:ok, encoded} -> encode_body(rest, [encoded | acc])
|
||||
{:error, _} = err -> err
|
||||
end
|
||||
end
|
||||
|
||||
def encode_body([], acc), do: {:ok, Enum.reverse(acc)}
|
||||
|
||||
@doc "Try to decode anything into an AST struct."
|
||||
def decode(arg1)
|
||||
|
||||
|
@ -110,4 +135,9 @@ defmodule Farmbot.CeleryScript.AST do
|
|||
module
|
||||
end
|
||||
|
||||
@doc "Change a module back to a kind."
|
||||
def mod_to_kind(module) when is_atom(module) do
|
||||
Module.split(module) |> List.last() |> Macro.underscore()
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@ defmodule Farmbot.CeleryScript.AST.Node do
|
|||
@doc false
|
||||
defmacro __using__(_) do
|
||||
quote do
|
||||
import AST.Node, only: [allow_args: 1]
|
||||
import AST.Node, only: [allow_args: 1, return_self: 0, rebuild_self: 2]
|
||||
@behaviour AST.Node
|
||||
@after_compile AST.Node
|
||||
require Logger
|
||||
|
@ -44,7 +44,7 @@ defmodule Farmbot.CeleryScript.AST.Node do
|
|||
# This requires that the Node module has
|
||||
# `allow_args [<arg_name>]`
|
||||
if {arg_name, 0} in __MODULE__.module_info(:exports) do
|
||||
case apply(__MODULE__, arg_name, []).verify(val) do
|
||||
case apply(__MODULE__, arg_name, []).decode(val) do
|
||||
# if this argument is valid, continue enumeration.
|
||||
{:ok, decoded} -> decode_args(rest, [{arg_name, decoded} | acc])
|
||||
{:error, _} = err -> err
|
||||
|
@ -59,6 +59,46 @@ defmodule Farmbot.CeleryScript.AST.Node do
|
|||
def decode_args([], acc) do
|
||||
{:ok, Map.new(acc)}
|
||||
end
|
||||
|
||||
@doc false
|
||||
def encode_args(args, acc \\ [])
|
||||
|
||||
def encode_args(args, acc) when is_map(args) do
|
||||
encode_args(Map.to_list(args), acc)
|
||||
end
|
||||
|
||||
def encode_args([{arg_name, val} = arg | rest], acc) do
|
||||
if {arg_name, 0} in __MODULE__.module_info(:exports) do
|
||||
case apply(__MODULE__, arg_name, []).encode(val) do
|
||||
# if this argument is valid, continue enumeration.
|
||||
{:ok, encoded} -> encode_args(rest, [{arg_name, encoded} | acc])
|
||||
{:error, _} = err -> err
|
||||
end
|
||||
else
|
||||
{:error, {:unknown_arg, arg_name}}
|
||||
end
|
||||
end
|
||||
|
||||
def encode_args([], acc) do
|
||||
{:ok, Map.new(acc)}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@doc "Used with data manipulation nodes."
|
||||
defmacro return_self do
|
||||
quote do
|
||||
def execute(args, body, env) do
|
||||
{:ok, rebuild_self(args, body), env}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@doc "Rebuild the args and body into an AST struct."
|
||||
defmacro rebuild_self(args, body) do
|
||||
quote bind_quoted: [args: args, body: body] do
|
||||
struct(AST, kind: __MODULE__, args: args, body: body, comment: nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,4 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Node.Explanation do
|
|||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
allow_args [:message]
|
||||
|
||||
return_self()
|
||||
end
|
||||
|
|
|
@ -2,4 +2,9 @@ defmodule Farmbot.CeleryScript.AST.Node.PowerOff do
|
|||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
allow_args []
|
||||
|
||||
def execute(_, _, env) do
|
||||
Farmbot.System.shutdown("CeleryScript request")
|
||||
{:ok, env}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,4 +2,9 @@ defmodule Farmbot.CeleryScript.AST.Node.ReadStatus do
|
|||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
allow_args []
|
||||
|
||||
def execute(_, _, env) do
|
||||
Farmbot.BotState.force_state_push()
|
||||
{:ok, env}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,4 +2,9 @@ defmodule Farmbot.CeleryScript.AST.Node.Reboot do
|
|||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
allow_args []
|
||||
|
||||
def execute(_, _, env) do
|
||||
Farmbot.System.reboot("CeleryScript request.")
|
||||
{:ok, env}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,4 +2,18 @@ defmodule Farmbot.CeleryScript.AST.Node.RemoveFarmware do
|
|||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
allow_args [:package]
|
||||
|
||||
def execute(%{package: {:farmware, name}}, _, env) do
|
||||
case Farmbot.Farmware.lookup(name) do
|
||||
{:ok, fw} -> do_uninstall(fw, env)
|
||||
{:error, _} -> {:ok, env}
|
||||
end
|
||||
end
|
||||
|
||||
def do_uninstall(%Farmbot.Farmware{} = fw, env) do
|
||||
case Farmbot.Farmware.Installer.uninstall(fw) do
|
||||
:ok -> {:ok, env}
|
||||
{:error, reason} -> {:error, reason, env}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,4 +2,12 @@ defmodule Farmbot.CeleryScript.AST.Node.RpcError do
|
|||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
allow_args [:label]
|
||||
|
||||
def execute(%{label: _label} = args, body, env) do
|
||||
ast = rebuild_self(args, body)
|
||||
case Farmbot.BotState.emit(ast) do
|
||||
:ok -> {:ok, env}
|
||||
{:error, reason} -> {:error, reason, env}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,4 +2,12 @@ defmodule Farmbot.CeleryScript.AST.Node.RpcOk do
|
|||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
allow_args [:label]
|
||||
|
||||
def execute(%{label: _label} = args, body, env) do
|
||||
ast = rebuild_self(args, body)
|
||||
case Farmbot.BotState.emit(ast) do
|
||||
:ok -> {:ok, env}
|
||||
{:error, reason} -> {:error, reason, env}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,28 @@
|
|||
defmodule Farmbot.CeleryScript.AST.Node.RpcRequest do
|
||||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
alias Farmbot.CeleryScript.AST.Node
|
||||
allow_args [:label]
|
||||
|
||||
def execute(%{label: label}, body, env) do
|
||||
do_reduce(body, label, env)
|
||||
end
|
||||
|
||||
defp do_reduce([ast | rest], label, env) do
|
||||
case Farmbot.CeleryScript.execute(ast, env) do
|
||||
{:ok, new_env} -> do_reduce(rest, label, new_env)
|
||||
{:error, reason, new_env} -> handle_error(ast, reason, new_env)
|
||||
end
|
||||
end
|
||||
|
||||
defp do_reduce([], label, env) do
|
||||
Node.RpcOk.execute(%{label: label}, [], env)
|
||||
end
|
||||
|
||||
defp handle_error(ast, reason, env) do
|
||||
case Node.Explanation.execute(%{message: "#{inspect ast} failed: #{inspect reason}"}, [], env) do
|
||||
{:ok, expl, new_env} -> Node.RpcError.execute(%{label: ast.args.label}, [expl], new_env)
|
||||
{:error, reason, env} -> {:error, reason, env}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ defmodule Farmbot.CeleryScript.AST.Node.Sequence do
|
|||
end
|
||||
|
||||
defp do_reduce([ast | rest], env) do
|
||||
case Farmbot.CeleryScript.execute(ast) do
|
||||
case Farmbot.CeleryScript.execute(ast, env) do
|
||||
{:ok, new_env} -> do_reduce(rest, new_env)
|
||||
{:error, reason, env} -> {:error, reason, env}
|
||||
end
|
||||
|
|
|
@ -2,4 +2,9 @@ defmodule Farmbot.CeleryScript.AST.Node.SetUserEnv do
|
|||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
allow_args []
|
||||
|
||||
def execute(args, body, env) do
|
||||
Logger.warn "FIXME"
|
||||
{:ok, env}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -100,6 +100,15 @@ defmodule Farmbot.Farmware.Installer do
|
|||
end
|
||||
end
|
||||
|
||||
def uninstall(%Farmware{} = fw) do
|
||||
Logger.info "Uninstalling farmware: #{inspect fw}"
|
||||
install_path = install_path(fw)
|
||||
case File.rm_rf(install_path) do
|
||||
{:ok, _} -> :ok
|
||||
{:error, _} = err -> err
|
||||
end
|
||||
end
|
||||
|
||||
defp preflight_checks(%Farmware{} = fw) do
|
||||
Logger.info "Starting preflight checks for #{inspect fw}"
|
||||
with :ok <- check_version(fw.min_os_version_major),
|
||||
|
|
Loading…
Reference in a new issue