Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- defmodule Thumbex do
- @moduledoc """
- Thumbex keeps the contexts that define your domain
- and business logic.
- Contexts are also responsible for managing your data, regardless
- if it comes from the database, an external API or others.
- """
- end
- defmodule ElectronicLock do
- use GenStateMachine
- # Client
- def start_link(code),
- do: GenStateMachine.start_link(__MODULE__, code)
- def button(lock, digit),
- do: GenStateMachine.cast(lock, {:button, digit})
- def code_length(lock),
- do: GenStateMachine.call(lock, :code_length)
- def lock(lock),
- do: GenStateMachine.call(lock, :lock)
- def status(lock),
- do: GenStateMachine.call(lock, :status)
- # Server
- def init(code) do
- {:ok, :locked, %{code: code}, [{:next_event, :internal, :enter}]}
- end
- def handle_event(:internal, :enter, :locked, %{code: code} = data),
- do: IO.puts("Locked!") && {:keep_state, Map.put(data, :remaining, code)}
- def handle_event(:cast, {:button, digit}, :locked, data) do
- case data.remaining do
- [^digit] ->
- {:next_state, :open, data, [{:next_event, :internal, :enter}]}
- [^digit | rest] ->
- {:keep_state, %{data | remaining: rest}}
- [_ | _] ->
- {:keep_state, %{data | remaining: data.code}}
- end
- end
- def handle_event(:internal, :enter, :open, data) do
- #timer = :erlang.start_timer(10_000, self(), :lock)
- IO.puts("Unlocked!")
- #{:keep_state, Map.put(data, :timer, timer)}
- {:next_state, :open, data, [
- {:state_timeout,4_000,:lock}
- ]}
- end
- # [:state_timeout, :lock, :open, %{code: [1, 2, 3, 4], remaining: [4]}],
- # [file: 'lib/thumbex.ex', line: 31]},
- def handle_event(
- :state_timeout,
- :lock,
- :open,
- data
- ),
- do: {:next_state, :locked, data, [{:next_event, :internal, :enter}]}
- def handle_event(
- :state_timeout,
- :lock,
- :locked,
- data
- ),
- do: {:next_state, :locked, data, [{:next_event, :internal, :enter}]}
- # def handle_event(
- # :info,
- # {:timeout, timer, :lock},
- # :open,
- # %{timer: timer} = data
- # ),
- # do: {:next_state, :locked, data, [{:next_event, :internal, :enter}]}
- #
- # def handle_event(
- # :info,
- # {:timeout, timer, :lock},
- # :locked,
- # %{timer: timer} = data
- # )
- # do
- # IO.puts("Ignoring timeout event, already locked.")
- # {:next_state, :locked, data, [{:next_event, :internal, :enter}]}
- # end
- def handle_event(:cast, {:button, _digit}, :open, _data),
- do: {:keep_state_and_data, [:postpone]}
- def handle_event({:call, from}, :code_length, _state, %{code: code}),
- do: {:keep_state_and_data, [{:reply, from, length(code)}]}
- def handle_event({:call, from}, :status, state, %{code: code}),
- do: {:keep_state_and_data, [{:reply, from, state}]}
- def handle_event({:call, from}, :lock, :open, data) do
- {
- :next_state,
- :locked,
- data,
- [
- {:next_event, :internal, :enter},
- {:reply, from, :ok}
- ]
- }
- end
- def handle_event({:call, from}, :lock, :locked, data) do
- {
- :next_state,
- :locked,
- data,
- [
- {:next_event, :internal, :enter},
- {:reply, from, :ok}
- ]
- }
- end
- end
Add Comment
Please, Sign In to add comment