This commit is contained in:
anlicheng 2025-07-02 15:16:53 +08:00
parent ec392e1795
commit 5de6731d7f

View File

@ -42,13 +42,8 @@
%% %%
mode :: #rtu_mode{} | #tcp_mode{} | undefined, mode :: #rtu_mode{} | #tcp_mode{} | undefined,
is_pending = true :: boolean(),
socket :: gen_tcp:socket() | undefined,
%% #{slaveId => DevicePid} %% #{slaveId => DevicePid}
devices_map = #{}, devices_map = #{},
%% %%
processor_pids = [], processor_pids = [],
%% alarms %% alarms
@ -100,11 +95,11 @@ init([AST = #ast{modbus = Modbus = #modbus{transport = Transport, error_log = Er
{rtu, Port, DelayMs} -> {rtu, Port, DelayMs} ->
{ok, ?CONNECTED, #state{ast = AST, access_log_pid = create_log_file(AccessLog), error_log_pid = create_log_file(ErrorLog), {ok, ?CONNECTED, #state{ast = AST, access_log_pid = create_log_file(AccessLog), error_log_pid = create_log_file(ErrorLog),
mode = #rtu_mode{port = Port, delay_ms = DelayMs}, is_pending = false, mode = #rtu_mode{port = Port, delay_ms = DelayMs},
queue = queue:new(), packet_id = 1, devices_map = DevicesMap, alarm_pids = []}}; queue = queue:new(), packet_id = 1, devices_map = DevicesMap, alarm_pids = []}};
Socket -> Socket ->
{ok, ?CONNECTED, #state{ast = AST, access_log_pid = create_log_file(AccessLog), error_log_pid = create_log_file(ErrorLog), {ok, ?CONNECTED, #state{ast = AST, access_log_pid = create_log_file(AccessLog), error_log_pid = create_log_file(ErrorLog),
mode = #tcp_mode{socket = Socket}, is_pending = false, mode = #tcp_mode{socket = Socket},
queue = queue:new(), packet_id = 1, devices_map = DevicesMap, alarm_pids = []}} queue = queue:new(), packet_id = 1, devices_map = DevicesMap, alarm_pids = []}}
end; end;
{error, Reason} -> {error, Reason} ->
@ -127,18 +122,12 @@ callback_mode() ->
%% process message, this function is called. %% process message, this function is called.
%% modbus需要控制请求的频率 %% modbus需要控制请求的频率
handle_event(info, {request, ReceiverPid, Ref, SlaveId, Address}, StateName, State = #state{mode = rtu, is_pending = IsPending, packet_id = PacketId, queue = Q}) -> handle_event(info, {request, ReceiverPid, Ref, SlaveId, Address}, StateName, State = #state{mode = #rtu_mode{}, packet_id = PacketId, queue = Q}) ->
case StateName of case StateName of
?CONNECTED -> ?CONNECTED ->
Actions = case IsPending of
true ->
[{next_event, info, read_next}];
false ->
[]
end,
%% , modbus不是全双工的模式 %% , modbus不是全双工的模式
NQ = queue:in({PacketId, ReceiverPid, Ref, SlaveId, Address}, Q), NQ = queue:in({PacketId, ReceiverPid, Ref, SlaveId, Address}, Q),
{keep_state, State#state{queue = NQ, packet_id = PacketId + 1}, Actions}; {keep_state, State#state{queue = NQ, packet_id = PacketId + 1}, [{next_event, info, read_next}]};
_ -> _ ->
{keep_state, State} {keep_state, State}
end; end;
@ -153,9 +142,9 @@ handle_event(info, read_next, ?CONNECTED, State = #state{mode = #rtu_mode{port =
Port ! {self(), {command, ReadCmd}}, Port ! {self(), {command, ReadCmd}},
{keep_state, State#state{queue = Q2, inflight = maps:put(PacketId, {ReceiverPid, Ref}, Inflight)}}; {keep_state, State#state{queue = Q2, inflight = maps:put(PacketId, {ReceiverPid, Ref}, Inflight)}};
{empty, Q1} -> {empty, Q1} ->
{keep_state, State#state{queue = Q1, is_pending = true}} {keep_state, State#state{queue = Q1}}
end; end;
handle_event(info, read_next, ?DISCONNECTED, State = #state{mode = rtu}) -> handle_event(info, read_next, ?DISCONNECTED, State = #state{mode = #rtu_mode{}}) ->
{keep_state, State}; {keep_state, State};
%% port读取数据, todo 32 %% port读取数据, todo 32
@ -184,25 +173,25 @@ handle_event(info, {broadcast, Key, Val}, ?CONNECTED, State = #state{alarm_pids
handle_event(info, {Port, {exit_status, Code}}, ?CONNECTED, State = #state{mode = #rtu_mode{port = Port}}) -> handle_event(info, {Port, {exit_status, Code}}, ?CONNECTED, State = #state{mode = #rtu_mode{port = Port}}) ->
lager:debug("[modbus_service] port: ~p, exit with code: ~p", [Port, Code]), lager:debug("[modbus_service] port: ~p, exit with code: ~p", [Port, Code]),
retry_connect(), retry_connect(),
{next_state, ?DISCONNECTED, State#state{mode = undefined, is_pending = true}}; {next_state, ?DISCONNECTED, State#state{mode = undefined}};
%% port的退出消息 %% port的退出消息
handle_event(info, {'EXIT', Port, Reason}, ?CONNECTED, State = #state{mode = #rtu_mode{port = Port}}) -> handle_event(info, {'EXIT', Port, Reason}, ?CONNECTED, State = #state{mode = #rtu_mode{port = Port}}) ->
lager:debug("[modbus_service] port: ~p, exit with code: ~p", [Port, Reason]), lager:debug("[modbus_service] port: ~p, exit with code: ~p", [Port, Reason]),
retry_connect(), retry_connect(),
{next_state, ?DISCONNECTED, State#state{mode = undefined, is_pending = true}}; {next_state, ?DISCONNECTED, State#state{mode = undefined}};
%% tcp退出 %% tcp退出
handle_event(info, {tcp_closed, Socket}, ?CONNECTED, State = #state{mode = tcp, socket = Socket}) -> handle_event(info, {tcp_closed, Socket}, ?CONNECTED, State = #state{mode = #tcp_mode{socket = Socket}}) ->
lager:debug("[modbus_service] socket: ~p, exit with tcp_closed", [Socket]), lager:debug("[modbus_service] socket: ~p, exit with tcp_closed", [Socket]),
retry_connect(), retry_connect(),
{next_state, ?DISCONNECTED, State#state{socket = undefined}}; {next_state, ?DISCONNECTED, State#state{mode = undefined}};
%% tcp的退出消息 %% tcp的退出消息
handle_event(info, {tcp_error, Socket, Reason}, ?CONNECTED, State = #state{mode = tcp, socket = Socket}) -> handle_event(info, {tcp_error, Socket, Reason}, ?CONNECTED, State = #state{mode = #tcp_mode{socket = Socket}}) ->
lager:debug("[modbus_service] socket: ~p, exit with code: ~p", [Socket, Reason]), lager:debug("[modbus_service] socket: ~p, exit with code: ~p", [Socket, Reason]),
retry_connect(), retry_connect(),
{next_state, ?DISCONNECTED, State#state{socket = undefined}}; {next_state, ?DISCONNECTED, State#state{mode = undefined}};
%% , todo is_pending的状态要形成闭环 %% , todo is_pending的状态要形成闭环
handle_event(info, {timeout, _Ref, modbus_connect}, ?DISCONNECTED, State = #state{ast = #ast{modbus = #modbus{transport = Transport}}, queue = Q}) -> handle_event(info, {timeout, _Ref, modbus_connect}, ?DISCONNECTED, State = #state{ast = #ast{modbus = #modbus{transport = Transport}}, queue = Q}) ->
@ -216,7 +205,7 @@ handle_event(info, {timeout, _Ref, modbus_connect}, ?DISCONNECTED, State = #stat
end, end,
case ConnectResult of case ConnectResult of
{rtu, Port, DelayMs} -> {rtu, Port, DelayMs} ->
{next_state, ?CONNECTED, State#state{mode = #rtu_mode{port = Port, delay_ms = DelayMs}, is_pending = false}, Actions}; {next_state, ?CONNECTED, State#state{mode = #rtu_mode{port = Port, delay_ms = DelayMs}}, Actions};
Socket -> Socket ->
{next_state, ?CONNECTED, State#state{mode = #tcp_mode{socket = Socket}}, Actions} {next_state, ?CONNECTED, State#state{mode = #tcp_mode{socket = Socket}}, Actions}
end; end;