复杂的状态管理
This commit is contained in:
parent
5de6731d7f
commit
c7cfc8eff5
@ -100,7 +100,7 @@ handle_info({timeout, _, {poll_ticker, Name}}, State = #state{parent_pid = Paren
|
||||
%% 读取采集项目
|
||||
ReceiverPid = self(),
|
||||
Ref = make_ref(),
|
||||
ParentPid ! {request, ReceiverPid, Ref, SlaveId, Address},
|
||||
ParentPid ! {request, ReceiverPid, Ref, SlaveId, Address, 1},
|
||||
|
||||
{noreply, State#state{inflight = maps:put(Ref, Name, Inflight)}};
|
||||
|
||||
|
||||
@ -20,8 +20,7 @@
|
||||
-export([init/1, handle_event/4, terminate/3, code_change/4, callback_mode/0]).
|
||||
|
||||
%% rtu指令
|
||||
-define(MODBUS_CONNECT, 16#01).
|
||||
-define(MODBUS_READ, 16#02).
|
||||
-define(MODBUS_READ, 16#01).
|
||||
|
||||
%% 当前的状态
|
||||
-define(DISCONNECTED, disconnected).
|
||||
@ -33,7 +32,9 @@
|
||||
|
||||
-record(rtu_mode, {
|
||||
port :: erlang:port(),
|
||||
delay_ms = 0 :: integer()
|
||||
delay_ms = 0 :: integer(),
|
||||
%% 信道是否在忙
|
||||
is_busy = false
|
||||
}).
|
||||
|
||||
-record(state, {
|
||||
@ -122,25 +123,27 @@ callback_mode() ->
|
||||
%% process message, this function is called.
|
||||
|
||||
%% 请求的时候必须先加入队列,modbus需要控制请求的频率
|
||||
handle_event(info, {request, ReceiverPid, Ref, SlaveId, Address}, StateName, State = #state{mode = #rtu_mode{}, packet_id = PacketId, queue = Q}) ->
|
||||
handle_event(info, {request, ReceiverPid, Ref, SlaveId, Address, Cnt}, StateName, State = #state{mode = #rtu_mode{}, packet_id = PacketId, queue = Q}) ->
|
||||
case StateName of
|
||||
?CONNECTED ->
|
||||
%% 基于队列处理, modbus不是全双工的模式
|
||||
NQ = queue:in({PacketId, ReceiverPid, Ref, SlaveId, Address}, Q),
|
||||
NQ = queue:in({PacketId, ReceiverPid, Ref, SlaveId, Address, Cnt}, Q),
|
||||
{keep_state, State#state{queue = NQ, packet_id = PacketId + 1}, [{next_event, info, read_next}]};
|
||||
_ ->
|
||||
{keep_state, State}
|
||||
end;
|
||||
|
||||
%% rtu 模式下读取下一个任务
|
||||
handle_event(info, read_next, ?CONNECTED, State = #state{mode = #rtu_mode{port = Port}, queue = Q, inflight = Inflight}) ->
|
||||
handle_event(info, read_next, ?CONNECTED, State = #state{mode = #rtu_mode{is_busy = true}}) ->
|
||||
{keep_state, State};
|
||||
handle_event(info, read_next, ?CONNECTED, State = #state{mode = Mode = #rtu_mode{port = Port}, queue = Q, inflight = Inflight}) ->
|
||||
lager:debug("[modbus_service] read next, q: ~p, port is: ~p", [queue:to_list(Q), Port]),
|
||||
|
||||
case queue:out(Q) of
|
||||
{{value, {PacketId, ReceiverPid, Ref, SlaveId, Address}}, Q2} ->
|
||||
ReadCmd = <<?MODBUS_READ:8, PacketId:32, SlaveId:8, Address:16>>,
|
||||
{{value, {PacketId, ReceiverPid, Ref, SlaveId, Address, Cnt}}, Q2} ->
|
||||
ReadCmd = <<?MODBUS_READ:8, PacketId:32, SlaveId:8, Address:16, Cnt:16>>,
|
||||
Port ! {self(), {command, ReadCmd}},
|
||||
{keep_state, State#state{queue = Q2, inflight = maps:put(PacketId, {ReceiverPid, Ref}, Inflight)}};
|
||||
{keep_state, State#state{queue = Q2, mode = Mode#rtu_mode{is_busy = true}, inflight = maps:put(PacketId, {ReceiverPid, Ref}, Inflight)}};
|
||||
{empty, Q1} ->
|
||||
{keep_state, State#state{queue = Q1}}
|
||||
end;
|
||||
@ -148,7 +151,8 @@ handle_event(info, read_next, ?DISCONNECTED, State = #state{mode = #rtu_mode{}})
|
||||
{keep_state, State};
|
||||
|
||||
%% 从port读取数据, todo 获取到的数据表示为32位整数
|
||||
handle_event(info, {Port, {data, <<?MODBUS_READ:8, PacketId:32, Val:32>>}}, ?CONNECTED, State = #state{mode = #rtu_mode{port = Port, delay_ms = DelayMs}, inflight = Inflight}) ->
|
||||
handle_event(info, {Port, {data, <<?MODBUS_READ:8, PacketId:32, Val/binary>>}}, ?CONNECTED, State = #state{mode = Mode = #rtu_mode{port = Port, delay_ms = DelayMs}, inflight = Inflight}) ->
|
||||
lager:debug("[device_service] read port data packet_id: ~p, val: ~p", [PacketId, Val]),
|
||||
NInflight = case maps:take(PacketId, Inflight) of
|
||||
error ->
|
||||
Inflight;
|
||||
@ -157,11 +161,16 @@ handle_event(info, {Port, {data, <<?MODBUS_READ:8, PacketId:32, Val:32>>}}, ?CON
|
||||
Inflight0
|
||||
end,
|
||||
lager:debug("[modbus_service] port data is: ~p", [{PacketId, Val}]),
|
||||
%% 读取下一条
|
||||
erlang:start_timer(DelayMs, self(), read_next),
|
||||
|
||||
%% 通讯的过程需要一个空闲时间
|
||||
erlang:start_timer(DelayMs, self(), delay_locking),
|
||||
|
||||
{keep_state, State#state{inflight = NInflight}};
|
||||
|
||||
%% 锁定一个空闲时间, 把状态标记为空闲
|
||||
handle_event(info, {timeout, _, delay_locking}, ?CONNECTED, State = #state{mode = Mode = #rtu_mode{}}) ->
|
||||
{keep_state, State#state{mode = Mode#rtu_mode{is_busy = false}}, [{next_event, info, read_next}]};
|
||||
|
||||
%% 广播消息
|
||||
handle_event(info, {broadcast, Key, Val}, ?CONNECTED, State = #state{alarm_pids = AlarmPids}) ->
|
||||
%% 推送告警信息
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user