erlang OTP中的四大behaviour fsm的例子

 

下面是一个fsm的例子,代码如下:

 

 1 -module(code_lock2).
 2 
 3 -behaviour(gen_fsm).
 4 -export([start_link/1]).
 5 -export([button/1]).
 6 -export([init/1, locked/2, open/2]).
 7 -export([code_change/4, handle_event/3, handle_info/3, handle_sync_event/4, terminate/3]).
 8 
 9 -spec(start_link(Code::string()) -> {ok,pid()} | ignore | {error,term()}).
10 start_link(Code) ->
11     gen_fsm:start_link({local, code_lock2}, code_lock2, Code, []).
12 
13 -spec(button(Digit::string()) -> ok).
14 button(Digit) ->
15     gen_fsm:send_event(code_lock2, {button, Digit}).
16 
17 init(LockCode) ->
18     io:format("init: ~p~n", [LockCode]),
19     {ok, locked, {[], LockCode}}.
20 
21 locked({button, Digit}, {SoFar, Code}) ->
22     io:format("buttion: ~p, So far: ~p, Code: ~p~n", [Digit, [SoFar|Digit], Code]),
23     InputDigits = lists:append(SoFar, Digit),
24     io:format("Right now the password is ~p~n", [InputDigits]),
25     case InputDigits of
26         Code ->
27             do_unlock(),
28             {next_state, open, {[], Code}, 10000};
29         Incomplete when length(Incomplete)<length(Code) ->
30             {next_state, locked, {Incomplete, Code}, 5000};
31         Wrong ->
32             io:format("wrong passwd: ~p~n", [Wrong]),
33             {next_state, locked, {[], Code}}
34     end;
35 locked(timeout, {_SoFar, Code}) ->
36     io:format("timout when waiting button inputting, clean the input, button again plz~n"),
37     {next_state, locked, {[], Code}}.
38 
39 open(timeout, State) ->
40     do_lock(),
41     {next_state, locked, State}.
42 
43 code_change(_OldVsn, StateName, Data, _Extra) ->
44     {ok, StateName, Data}.
45 
46 terminate(normal, _StateName, _Data) ->
47     ok.
48 
49 handle_event(Event, StateName, Data) ->
50     io:format("handle_event... ~n"),
51     unexpected(Event, StateName),
52     {next_state, StateName, Data}.
53 
54 handle_sync_event(Event, From, StateName, Data) ->
55     io:format("handle_sync_event, for process: ~p... ~n", [From]),
56     unexpected(Event, StateName),
57     {next_state, StateName, Data}.
58 
59 handle_info(Info, StateName, Data) ->
60     io:format("handle_info...~n"),
61     unexpected(Info, StateName),
62     {next_state, StateName, Data}.
63 
64 %% Unexpected allows to log unexpected messages
65 unexpected(Msg, State) ->
66     io:format("~p RECEIVED UNKNOWN EVENT: ~p, while FSM process in state: ~p~n",
67               [self(), Msg, State]).
68 %%
69 %% actions
70 do_unlock() ->
71     io:format("passwd is right, open the DOOR.~n").
72 
73 do_lock() ->
74     io:format("over, close the DOOR.~n").

 

开锁过程如下:

 1 3> code_lock2:button([1]).
 2 buttion: [1], So far: [], Code: [1,3,5,3,1,7]
 3 Right now the password is [1]
 4 ok
 5 4> code_lock2:button([3]).
 6 buttion: [3], So far: [1], Code: [1,3,5,3,1,7]
 7 Right now the password is [1,3]
 8 ok
 9 5> code_lock2:button([5]).
10 buttion: [5], So far: [1,3], Code: [1,3,5,3,1,7]
11 Right now the password is [1,3,5]
12 ok
13 timout when waiting button inputting, clean the input, button again plz
14 6> code_lock2:button([3]).
15 buttion: [3], So far: [], Code: [1,3,5,3,1,7]
16 Right now the password is [3]
17 ok
18 timout when waiting button inputting, clean the input, button again plz
19 7> code_lock2:button([1]).
20 buttion: [1], So far: [], Code: [1,3,5,3,1,7]
21 Right now the password is [1]
22 ok
23 8> code_lock2:button([3]).
24 buttion: [3], So far: [[1],3], Code: [1,3,5,3,1,7]
25 Right now the password is [1,3]
26 ok
27 9> code_lock2:button([5]).
28 buttion: [5], So far: [[1,3],5], Code: [1,3,5,3,1,7]
29 Right now the password is [1,3,5]
30 ok
31 10> code_lock2:button([3]).
32 buttion: [3], So far: [1,3,5], Code: [1,3,5,3,1,7]
33 Right now the password is [1,3,5,3]
34 ok
35 11> code_lock2:button([1]).
36 buttion: [1], So far: [1,3,5,3], Code: [1,3,5,3,1,7]
37 Right now the password is [1,3,5,3,1]
38 ok
39 12> code_lock2:button([7]).
40 buttion: [7], So far: [1,3,5,3,1], Code: [1,3,5,3,1,7]
41 Right now the password is [1,3,5,3,1,7]
42 ok
43 passwd is right, open the DOOR.
44 over, close the DOOR.
45 13>

 

有一个地方解释一下,使用fsm:send_event(code_lock2, {button, Digit})相当于发送了一个消息,这个消息怎么处理呢?

如果没有fsm,这样的一个问题几乎没法回答!

 

这个消息先交给fsm,由fsm判断该交给谁去处理?众所周知,fsm是有限状态机的那种behaviour,当然有多个不同状态,按照fsm的约定这个消息会交给“当前的状态”。

因为start_link启动fsm,然后init执行后的状态是locked,所以,上面的消息就交道locked函数!

 

其他的代码,看起来就很明白,不说了。

 

抄代码,执行一下,纯玩。

 

posted @ 2015-09-14 16:26  FranklinYang  阅读(382)  评论(0编辑  收藏  举报