gen_statem example
-module(code_lock).
-behaviour(gen_statem).
-define(NAME, code_lock).
-export([start_link/1]).
-export([button/1]).
-export([init/1,callback_mode/0,terminate/3,code_change/4]).
-export([locked/3,open/3]).
start_link(Code) ->
gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).
button(Digit) ->
gen_statem:cast(?NAME, {button,Digit}).
init(Code) ->
do_lock(),
Data = #{code => Code, remaining => Code},
{ok, locked, Data}.
callback_mode() ->
state_functions.
locked(
cast, {button,Digit},
#{code := Code, remaining := Remaining} = Data) ->
case Remaining of
[Digit] ->
do_unlock(),
{next_state, open, Data#{remaining := Code},
[{state_timeout,10000,lock}]};
[Digit|Rest] -> % Incomplete
{next_state, locked, Data#{remaining := Rest}};
_Wrong ->
{next_state, locked, Data#{remaining := Code}}
end.
open(state_timeout, lock, Data) ->
do_lock(),
{next_state, locked, Data};
open(cast, {button,_}, Data) ->
{next_state, open, Data}.
do_lock() ->
io:format("Lock~n", []).
do_unlock() ->
io:format("Unlock~n", []).
terminate(_Reason, State, _Data) ->
State =/= locked andalso do_lock(),
ok.
code_change(_Vsn, State, Data, _Extra) ->
{ok, State, Data}.