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,
is_pending = true :: boolean(),
socket :: gen_tcp:socket() | undefined,
%% #{slaveId => DevicePid}
devices_map = #{},
%%
processor_pids = [],
%% alarms
@ -100,11 +95,11 @@ init([AST = #ast{modbus = Modbus = #modbus{transport = Transport, error_log = Er
{rtu, Port, DelayMs} ->
{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 = []}};
Socket ->
{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 = []}}
end;
{error, Reason} ->
@ -127,18 +122,12 @@ callback_mode() ->
%% process message, this function is called.
%% 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
?CONNECTED ->
Actions = case IsPending of
true ->
[{next_event, info, read_next}];
false ->
[]
end,
%% , modbus不是全双工的模式
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}
end;
@ -153,9 +142,9 @@ handle_event(info, read_next, ?CONNECTED, State = #state{mode = #rtu_mode{port =
Port ! {self(), {command, ReadCmd}},
{keep_state, State#state{queue = Q2, inflight = maps:put(PacketId, {ReceiverPid, Ref}, Inflight)}};
{empty, Q1} ->
{keep_state, State#state{queue = Q1, is_pending = true}}
{keep_state, State#state{queue = Q1}}
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};
%% 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}}) ->
lager:debug("[modbus_service] port: ~p, exit with code: ~p", [Port, Code]),
retry_connect(),
{next_state, ?DISCONNECTED, State#state{mode = undefined, is_pending = true}};
{next_state, ?DISCONNECTED, State#state{mode = undefined}};
%% 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]),
retry_connect(),
{next_state, ?DISCONNECTED, State#state{mode = undefined, is_pending = true}};
{next_state, ?DISCONNECTED, State#state{mode = undefined}};
%% 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]),
retry_connect(),
{next_state, ?DISCONNECTED, State#state{socket = undefined}};
{next_state, ?DISCONNECTED, State#state{mode = undefined}};
%% 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]),
retry_connect(),
{next_state, ?DISCONNECTED, State#state{socket = undefined}};
{next_state, ?DISCONNECTED, State#state{mode = undefined}};
%% , todo is_pending的状态要形成闭环
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,
case ConnectResult of
{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 ->
{next_state, ?CONNECTED, State#state{mode = #tcp_mode{socket = Socket}}, Actions}
end;