复杂的状态管理

This commit is contained in:
anlicheng 2025-07-02 17:03:07 +08:00
parent 5de6731d7f
commit c7cfc8eff5
2 changed files with 22 additions and 13 deletions

View File

@ -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)}};

View File

@ -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}) ->
%%