Rework default sequences/pin_bindings

pull/578/head
connor rigby 2018-07-13 11:58:25 -07:00
parent 9a26a9c531
commit 1ffa365642
No known key found for this signature in database
GPG Key ID: 24DC438382965C3B
7 changed files with 75 additions and 74 deletions

View File

@ -52,13 +52,6 @@ config :farmbot, :farmware,
first_part_farmware_manifest_url: "https://raw.githubusercontent.com/FarmBot-Labs/farmware_manifests/master/manifest.json"
config :farmbot, :builtins,
sequence: [
emergency_lock: -1,
emergency_unlock: -2,
sync: -3,
reboot: -4,
power_off: -5
],
pin_binding: [
emergency_lock: -1,
emergency_unlock: -2,

View File

@ -5,7 +5,6 @@ lib/farmbot/farmware/runtime.ex
lib/farmbot/farmware/runtime_error.ex
lib/farmbot/farmware/supervisor.ex
lib/farmbot/repo/worker.ex
lib/farmbot/pin_binding/handler.ex
lib/farmbot/pin_binding/pin_binding.ex
lib/farmbot/pin_binding/stub_handler.ex
lib/farmbot/asset/farm_event.ex

View File

@ -9,9 +9,10 @@ defmodule Farmbot.Asset.PinBinding do
schema "pin_bindings" do
field(:pin_num, :integer)
field(:sequence_id, :integer)
field(:special_action, :string)
end
@required_fields [:id, :pin_num, :sequence_id]
@required_fields [:id, :pin_num]
def changeset(pin_binding, params \\ %{}) do
pin_binding

View File

@ -8,13 +8,13 @@ defmodule Farmbot.PinBinding.Manager do
@handler || Mix.raise("No pin binding handler.")
@doc "Register a pin number to execute sequence."
def register_pin(pin_num, sequence_id) do
GenStage.call(__MODULE__, {:register_pin, pin_num, sequence_id})
def register_pin(%PinBinding{} = binding) do
GenStage.call(__MODULE__, {:register_pin, binding})
end
@doc "Unregister a sequence."
def unregister_pin(pin_num) do
GenStage.call(__MODULE__, {:unregister_pin, pin_num})
def unregister_pin(%PinBinding{} = binding) do
GenStage.call(__MODULE__, {:unregister_pin, binding})
end
def confirm_asset_storage_up do
@ -38,8 +38,6 @@ defmodule Farmbot.PinBinding.Manager do
case @handler.start_link() do
{:ok, handler} ->
state = initial_state([], struct(State, handler: handler))
Process.send_after(self(), :update_fb_state_tree, 10)
{:producer_consumer, state,
subscribe_to: [handler], dispatcher: GenStage.BroadcastDispatcher}
@ -50,22 +48,24 @@ defmodule Farmbot.PinBinding.Manager do
defp initial_state([], state), do: state
defp initial_state(
[%PinBinding{pin_num: pin, sequence_id: sequence_id} | rest],
state
) do
defp initial_state([%PinBinding{pin_num: pin} = binding | rest], state) do
case @handler.register_pin(pin) do
:ok ->
initial_state(rest, %{
state
| registered: Map.put(state.registered, pin, sequence_id)
})
new_state = do_register(state, binding)
initial_state(rest, new_state)
_ ->
initial_state(rest, state)
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
Logger.warn(3, "Not handling gpio events until Asset storage is up.")
{:noreply, [], state}
@ -76,11 +76,11 @@ defmodule Farmbot.PinBinding.Manager do
new_env =
Enum.reduce(t, state.env, fn {:pin_trigger, pin}, env ->
sequence_id = state.registered[pin]
binding = state.registered[pin]
if sequence_id do
Logger.busy(1, "Starting Sequence: #{sequence_id} from pin: #{pin}")
do_execute(sequence_id, env)
if binding do
Logger.busy(1, "PinBinding #{pin} triggered.")
%Macro.Env{} = do_execute(binding, env)
else
Logger.warn(3, "No sequence assosiated with: #{pin}")
env
@ -90,22 +90,14 @@ defmodule Farmbot.PinBinding.Manager do
{:noreply, [], %{state | env: new_env}}
end
def handle_info(:update_fb_state_tree, state) do
{:noreply, [{:gpio_registry, state.registered}], state}
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}"
def handle_call({:register_pin, %PinBinding{pin_num: pin_num} = binding}, _from, state) do
Logger.info 1, "Registering PinBinding #{pin_num}"
case state.registered[pin_num] do
nil ->
case @handler.register_pin(pin_num) do
:ok ->
new_state = %{
state
| registered: Map.put(state.registered, pin_num, sequence_id)
}
{:reply, :ok, [{:gpio_registry, new_state.registered}], new_state}
new_state = do_register(state, binding)
{:reply, :ok, [{:gpio_registry, %{}}], new_state}
{:error, _} = err ->
{:reply, err, [], state}
@ -116,23 +108,17 @@ defmodule Farmbot.PinBinding.Manager do
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
nil ->
{:reply, {:error, :unregistered}, [], state}
sequence_id ->
Logger.info 1, "Unregistering #{pin_num} from sequence by id: #{sequence_id}"
%PinBinding{} = old ->
Logger.info 1, "Unregistering PinBinding #{pin_num}"
case @handler.unregister_pin(pin_num) do
:ok ->
new_state = %{
state
| registered: Map.delete(state.registered, pin_num)
}
{:reply, :ok, [{:gpio_registry, new_state.registered}], new_state}
new_state = do_unregister(state, old)
{:reply, :ok, [{:gpio_registry, %{}}], new_state}
err ->
{:reply, err, [], state}
@ -154,7 +140,24 @@ defmodule Farmbot.PinBinding.Manager do
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]
try do
@ -166,6 +169,7 @@ defmodule Farmbot.PinBinding.Manager do
err ->
message = Exception.message(err)
Logger.warn(2, "Failed to execute sequence #{sequence_id} " <> message)
IO.warn "", System.stacktrace()
env
end
end

View File

@ -26,19 +26,19 @@ defmodule Farmbot.Repo.AfterSyncWorker do
{:noreply, state}
end
def handle_info({Farmbot.Repo.Registry, :addition, Farmbot.Asset.PinBinding, %{pin_num: pin, sequence_id: sequence_id}}, state) do
Farmbot.PinBinding.Manager.register_pin(pin, sequence_id)
def handle_info({Farmbot.Repo.Registry, :addition, Farmbot.Asset.PinBinding, binding}, state) do
Farmbot.PinBinding.Manager.register_pin(binding)
{:noreply, state}
end
def handle_info({Farmbot.Repo.Registry, :updated, Farmbot.Asset.PinBinding, %{pin_num: pin, sequence_id: sequence_id}}, state) do
Farmbot.PinBinding.Manager.unregister_pin(pin)
Farmbot.PinBinding.Manager.register_pin(pin, sequence_id)
def handle_info({Farmbot.Repo.Registry, :updated, Farmbot.Asset.PinBinding, binding}, state) do
Farmbot.PinBinding.Manager.unregister_pin(binding)
Farmbot.PinBinding.Manager.register_pin(binding)
{:noreply, state}
end
def handle_info({Farmbot.Repo.Registry, :deletion, Farmbot.Asset.PinBinding, %{pin_num: pin, sequence_id: _sequence_id}}, state) do
Farmbot.PinBinding.Manager.unregister_pin(pin)
def handle_info({Farmbot.Repo.Registry, :deletion, Farmbot.Asset.PinBinding, binding}, state) do
Farmbot.PinBinding.Manager.unregister_pin(binding)
{:noreply, state}
end

View File

@ -9,25 +9,20 @@ defmodule Farmbot.Repo.SeedDB do
end
def init([]) do
sequence(builtin(:sequence, :emergency_lock), "emergency_lock")
sequence(builtin(:sequence, :emergency_unlock), "emergency_unlock")
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)
pin_binding(builtin(:pin_binding, :emergency_lock), "emergency_lock", 17)
pin_binding(builtin(:pin_binding, :emergency_unlock), "emergency_unlock", 23)
:ignore
end
def sequence(id, kind, args \\ %{}, body \\ []) do
ConfigStorage.register_sync_cmd(id, "Sequence", %{id: id, name: "__#{kind}", kind: kind, args: args, body: body})
|> Farmbot.Repo.apply_sync_cmd()
end
def pin_binding(id, sequence_id, pin_num) do
ConfigStorage.register_sync_cmd(id, "PinBinding", %{id: id, sequence_id: sequence_id, pin_num: pin_num})
def pin_binding(id, special_action, pin_num) do
body = %{
id: id,
sequence_id: nil,
special_action: special_action,
pin_num: pin_num
}
ConfigStorage.register_sync_cmd(id, "PinBinding", body)
|> Farmbot.Repo.apply_sync_cmd()
end

View File

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