Rework default sequences/pin_bindings
parent
9a26a9c531
commit
1ffa365642
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue