Skip to content

Commit

Permalink
Rework default sequences/pin_bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
connor rigby committed Jul 13, 2018
1 parent 9a26a9c commit 1ffa365
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 74 deletions.
7 changes: 0 additions & 7 deletions config/config.exs
Expand Up @@ -52,13 +52,6 @@ config :farmbot, :farmware,
first_part_farmware_manifest_url: "https://raw.githubusercontent.com/FarmBot-Labs/farmware_manifests/master/manifest.json" first_part_farmware_manifest_url: "https://raw.githubusercontent.com/FarmBot-Labs/farmware_manifests/master/manifest.json"


config :farmbot, :builtins, config :farmbot, :builtins,
sequence: [
emergency_lock: -1,
emergency_unlock: -2,
sync: -3,
reboot: -4,
power_off: -5
],
pin_binding: [ pin_binding: [
emergency_lock: -1, emergency_lock: -1,
emergency_unlock: -2, emergency_unlock: -2,
Expand Down
1 change: 0 additions & 1 deletion formatted_files
Expand Up @@ -5,7 +5,6 @@ lib/farmbot/farmware/runtime.ex
lib/farmbot/farmware/runtime_error.ex lib/farmbot/farmware/runtime_error.ex
lib/farmbot/farmware/supervisor.ex lib/farmbot/farmware/supervisor.ex
lib/farmbot/repo/worker.ex lib/farmbot/repo/worker.ex
lib/farmbot/pin_binding/handler.ex
lib/farmbot/pin_binding/pin_binding.ex lib/farmbot/pin_binding/pin_binding.ex
lib/farmbot/pin_binding/stub_handler.ex lib/farmbot/pin_binding/stub_handler.ex
lib/farmbot/asset/farm_event.ex lib/farmbot/asset/farm_event.ex
Expand Down
3 changes: 2 additions & 1 deletion lib/farmbot/asset/pin_binding.ex
Expand Up @@ -9,9 +9,10 @@ defmodule Farmbot.Asset.PinBinding do
schema "pin_bindings" do schema "pin_bindings" do
field(:pin_num, :integer) field(:pin_num, :integer)
field(:sequence_id, :integer) field(:sequence_id, :integer)
field(:special_action, :string)
end end


@required_fields [:id, :pin_num, :sequence_id] @required_fields [:id, :pin_num]


def changeset(pin_binding, params \\ %{}) do def changeset(pin_binding, params \\ %{}) do
pin_binding pin_binding
Expand Down
90 changes: 47 additions & 43 deletions lib/farmbot/pin_binding/manager.ex
Expand Up @@ -8,13 +8,13 @@ defmodule Farmbot.PinBinding.Manager do
@handler || Mix.raise("No pin binding handler.") @handler || Mix.raise("No pin binding handler.")


@doc "Register a pin number to execute sequence." @doc "Register a pin number to execute sequence."
def register_pin(pin_num, sequence_id) do def register_pin(%PinBinding{} = binding) do
GenStage.call(__MODULE__, {:register_pin, pin_num, sequence_id}) GenStage.call(__MODULE__, {:register_pin, binding})
end end


@doc "Unregister a sequence." @doc "Unregister a sequence."
def unregister_pin(pin_num) do def unregister_pin(%PinBinding{} = binding) do
GenStage.call(__MODULE__, {:unregister_pin, pin_num}) GenStage.call(__MODULE__, {:unregister_pin, binding})
end end


def confirm_asset_storage_up do def confirm_asset_storage_up do
Expand All @@ -38,8 +38,6 @@ defmodule Farmbot.PinBinding.Manager do
case @handler.start_link() do case @handler.start_link() do
{:ok, handler} -> {:ok, handler} ->
state = initial_state([], struct(State, handler: handler)) state = initial_state([], struct(State, handler: handler))
Process.send_after(self(), :update_fb_state_tree, 10)

{:producer_consumer, state, {:producer_consumer, state,
subscribe_to: [handler], dispatcher: GenStage.BroadcastDispatcher} subscribe_to: [handler], dispatcher: GenStage.BroadcastDispatcher}


Expand All @@ -50,22 +48,24 @@ defmodule Farmbot.PinBinding.Manager do


defp initial_state([], state), do: state defp initial_state([], state), do: state


defp initial_state( defp initial_state([%PinBinding{pin_num: pin} = binding | rest], state) do
[%PinBinding{pin_num: pin, sequence_id: sequence_id} | rest],
state
) do
case @handler.register_pin(pin) do case @handler.register_pin(pin) do
:ok -> :ok ->
initial_state(rest, %{ new_state = do_register(state, binding)
state initial_state(rest, new_state)
| registered: Map.put(state.registered, pin, sequence_id)
})

_ -> _ ->
initial_state(rest, state) initial_state(rest, state)
end end
end end


defp do_register(state, %PinBinding{pin_num: pin} = binding) do
%{state | registered: Map.put(state.registered, pin, binding)}
end

defp do_unregister(state, %PinBinding{pin_num: pin_num}) do
%{state | registered: Map.delete(state.registered, pin_num)}
end

def handle_events(_, _, %{repo_up: false} = state) do def handle_events(_, _, %{repo_up: false} = state) do
Logger.warn(3, "Not handling gpio events until Asset storage is up.") Logger.warn(3, "Not handling gpio events until Asset storage is up.")
{:noreply, [], state} {:noreply, [], state}
Expand All @@ -76,11 +76,11 @@ defmodule Farmbot.PinBinding.Manager do


new_env = new_env =
Enum.reduce(t, state.env, fn {:pin_trigger, pin}, env -> Enum.reduce(t, state.env, fn {:pin_trigger, pin}, env ->
sequence_id = state.registered[pin] binding = state.registered[pin]


if sequence_id do if binding do
Logger.busy(1, "Starting Sequence: #{sequence_id} from pin: #{pin}") Logger.busy(1, "PinBinding #{pin} triggered.")
do_execute(sequence_id, env) %Macro.Env{} = do_execute(binding, env)
else else
Logger.warn(3, "No sequence assosiated with: #{pin}") Logger.warn(3, "No sequence assosiated with: #{pin}")
env env
Expand All @@ -90,22 +90,14 @@ defmodule Farmbot.PinBinding.Manager do
{:noreply, [], %{state | env: new_env}} {:noreply, [], %{state | env: new_env}}
end end


def handle_info(:update_fb_state_tree, state) do def handle_call({:register_pin, %PinBinding{pin_num: pin_num} = binding}, _from, state) do
{:noreply, [{:gpio_registry, state.registered}], state} Logger.info 1, "Registering PinBinding #{pin_num}"
end

def handle_call({:register_pin, pin_num, sequence_id}, _from, state) do
Logger.info 1, "Registering #{pin_num} to sequence by id: #{sequence_id}"
case state.registered[pin_num] do case state.registered[pin_num] do
nil -> nil ->
case @handler.register_pin(pin_num) do case @handler.register_pin(pin_num) do
:ok -> :ok ->
new_state = %{ new_state = do_register(state, binding)
state {:reply, :ok, [{:gpio_registry, %{}}], new_state}
| registered: Map.put(state.registered, pin_num, sequence_id)
}

{:reply, :ok, [{:gpio_registry, new_state.registered}], new_state}


{:error, _} = err -> {:error, _} = err ->
{:reply, err, [], state} {:reply, err, [], state}
Expand All @@ -116,23 +108,17 @@ defmodule Farmbot.PinBinding.Manager do
end end
end end


def handle_call({:unregister_pin, pin_num}, _from, state) do def handle_call({:unregister_pin, %PinBinding{pin_num: pin_num}}, _from, state) do

case state.registered[pin_num] do case state.registered[pin_num] do
nil -> nil ->
{:reply, {:error, :unregistered}, [], state} {:reply, {:error, :unregistered}, [], state}


sequence_id -> %PinBinding{} = old ->
Logger.info 1, "Unregistering #{pin_num} from sequence by id: #{sequence_id}" Logger.info 1, "Unregistering PinBinding #{pin_num}"
case @handler.unregister_pin(pin_num) do case @handler.unregister_pin(pin_num) do
:ok -> :ok ->

new_state = do_unregister(state, old)
new_state = %{ {:reply, :ok, [{:gpio_registry, %{}}], new_state}
state
| registered: Map.delete(state.registered, pin_num)
}

{:reply, :ok, [{:gpio_registry, new_state.registered}], new_state}


err -> err ->
{:reply, err, [], state} {:reply, err, [], state}
Expand All @@ -154,7 +140,24 @@ defmodule Farmbot.PinBinding.Manager do
end end
end end


defp do_execute(sequence_id, env) do defp do_execute(%PinBinding{pin_num: num, special_action: kind}, env) when is_binary(kind) do
celery = %{kind: kind, args: %{}, body: []}
{:ok, seq} = Farmbot.CeleryScript.AST.decode(celery)
try do
case Farmbot.CeleryScript.execute(seq, env) do
{:ok, env} -> env
{:error, _, env} -> env
end
rescue
err ->
message = Exception.message(err)
Logger.warn(2, "Failed to execute sequence PinBinding #{num}: " <> message)
IO.warn "", System.stacktrace()
env
end
end

defp do_execute(%PinBinding{sequence_id: sequence_id}, env) when is_integer(sequence_id) do
import Farmbot.CeleryScript.AST.Node.Execute, only: [execute: 3] import Farmbot.CeleryScript.AST.Node.Execute, only: [execute: 3]


try do try do
Expand All @@ -166,6 +169,7 @@ defmodule Farmbot.PinBinding.Manager do
err -> err ->
message = Exception.message(err) message = Exception.message(err)
Logger.warn(2, "Failed to execute sequence #{sequence_id} " <> message) Logger.warn(2, "Failed to execute sequence #{sequence_id} " <> message)
IO.warn "", System.stacktrace()
env env
end end
end end
Expand Down
14 changes: 7 additions & 7 deletions lib/farmbot/repo/after_sync_worker.ex
Expand Up @@ -26,19 +26,19 @@ defmodule Farmbot.Repo.AfterSyncWorker do
{:noreply, state} {:noreply, state}
end end


def handle_info({Farmbot.Repo.Registry, :addition, Farmbot.Asset.PinBinding, %{pin_num: pin, sequence_id: sequence_id}}, state) do def handle_info({Farmbot.Repo.Registry, :addition, Farmbot.Asset.PinBinding, binding}, state) do
Farmbot.PinBinding.Manager.register_pin(pin, sequence_id) Farmbot.PinBinding.Manager.register_pin(binding)
{:noreply, state} {:noreply, state}
end end


def handle_info({Farmbot.Repo.Registry, :updated, Farmbot.Asset.PinBinding, %{pin_num: pin, sequence_id: sequence_id}}, state) do def handle_info({Farmbot.Repo.Registry, :updated, Farmbot.Asset.PinBinding, binding}, state) do
Farmbot.PinBinding.Manager.unregister_pin(pin) Farmbot.PinBinding.Manager.unregister_pin(binding)
Farmbot.PinBinding.Manager.register_pin(pin, sequence_id) Farmbot.PinBinding.Manager.register_pin(binding)
{:noreply, state} {:noreply, state}
end end


def handle_info({Farmbot.Repo.Registry, :deletion, Farmbot.Asset.PinBinding, %{pin_num: pin, sequence_id: _sequence_id}}, state) do def handle_info({Farmbot.Repo.Registry, :deletion, Farmbot.Asset.PinBinding, binding}, state) do
Farmbot.PinBinding.Manager.unregister_pin(pin) Farmbot.PinBinding.Manager.unregister_pin(binding)
{:noreply, state} {:noreply, state}
end end


Expand Down
25 changes: 10 additions & 15 deletions lib/farmbot/repo/seed_db.ex
Expand Up @@ -9,25 +9,20 @@ defmodule Farmbot.Repo.SeedDB do
end end


def init([]) do def init([]) do
sequence(builtin(:sequence, :emergency_lock), "emergency_lock") pin_binding(builtin(:pin_binding, :emergency_lock), "emergency_lock", 17)
sequence(builtin(:sequence, :emergency_unlock), "emergency_unlock") pin_binding(builtin(:pin_binding, :emergency_unlock), "emergency_unlock", 23)
sequence(builtin(:sequence, :sync), "sync")
sequence(builtin(:sequence, :reboot), "reboot")
sequence(builtin(:sequence, :power_off), "power_off")

pin_binding(builtin(:pin_binding, :emergency_lock), builtin(:sequence, :emergency_lock), 17)
pin_binding(builtin(:pin_binding, :emergency_unlock), builtin(:sequence, :emergency_unlock), 23)


:ignore :ignore
end end


def sequence(id, kind, args \\ %{}, body \\ []) do def pin_binding(id, special_action, pin_num) do
ConfigStorage.register_sync_cmd(id, "Sequence", %{id: id, name: "__#{kind}", kind: kind, args: args, body: body}) body = %{
|> Farmbot.Repo.apply_sync_cmd() id: id,
end sequence_id: nil,

special_action: special_action,
def pin_binding(id, sequence_id, pin_num) do pin_num: pin_num
ConfigStorage.register_sync_cmd(id, "PinBinding", %{id: id, sequence_id: sequence_id, pin_num: pin_num}) }
ConfigStorage.register_sync_cmd(id, "PinBinding", body)
|> Farmbot.Repo.apply_sync_cmd() |> Farmbot.Repo.apply_sync_cmd()
end end


Expand Down
@@ -0,0 +1,9 @@
defmodule Farmbot.Repo.Migrations.PinBindingsSpecialAction do
use Ecto.Migration

def change do
alter table("pin_bindings") do
add(:special_action, :string)
end
end
end

0 comments on commit 1ffa365

Please sign in to comment.