Yay. many nodes working again

This commit is contained in:
Connor Rigby 2017-11-05 14:13:11 -08:00
parent 6782e88792
commit d6bdfd3433
46 changed files with 299 additions and 61 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,4 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Node.Explanation do
@moduledoc false
use Farmbot.CeleryScript.AST.Node
allow_args [:message]
return_self()
end

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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