fix host status

This commit is contained in:
anlicheng 2026-05-09 23:35:28 +08:00
parent fe46aff527
commit b8d3d4b524

View File

@ -215,11 +215,12 @@ handle_event({call, From}, get_metric, _, State = #state{metrics = Metrics}) ->
{keep_state, State, [{reply, From, {ok, Metrics}}]};
%%
handle_event({call, From}, get_status, _, State = #state{channel_pid = ChannelPid, heartbeat_counter = HeartbeatCounter, metrics = Metrics, has_session = HasSession}) ->
handle_event({call, From}, get_status, _, State = #state{channel_pid = ChannelPid, heartbeat_counter = HeartbeatCounter, metrics = Metrics, has_session = HasSession, host_status = HostStatus}) ->
HasChannel = (ChannelPid /= undefined),
Reply = #{
<<"has_channel">> => HasChannel,
<<"has_session">> => HasSession,
<<"host_status">> => HostStatus,
<<"heartbeat_counter">> => HeartbeatCounter,
<<"metrics">> => Metrics
},
@ -271,23 +272,21 @@ handle_event({call, From}, {activate, Auth}, _, State = #state{uuid = UUID}) ->
{next_state, NStateName, State, [{reply, From, ok}]};
%% channel
handle_event({call, From}, {attach_channel, ChannelPid}, StateName, State = #state{uuid = UUID, channel_pid = OldChannelPid}) ->
handle_event({call, From}, {attach_channel, ChannelPid}, StateName, State = #state{uuid = UUID, channel_pid = OldChannelPid, host_status = HostStatus}) ->
case OldChannelPid == undefined orelse OldChannelPid =:= ChannelPid of
true ->
case StateName of
?STATE_ACTIVATED ->
erlang:monitor(process, ChannelPid),
%% 线
ChangeResult = iot_api_client:change_host_status(UUID, ?HOST_ONLINE),
logger:debug("[iot_host] host_id(attach_channel) uuid: ~p, will change status, result: ~p", [UUID, ChangeResult]),
{keep_state, State#state{channel_pid = ChannelPid, has_session = true}, [{reply, From, ok}]};
NState = mark_host_online(UUID, HostStatus, State#state{channel_pid = ChannelPid, has_session = true}),
{keep_state, NState, [{reply, From, ok}]};
%%
?STATE_DENIED ->
logger:notice("[iot_host] attach_channel host_id uuid: ~p, channel: ~p, host denied locally", [UUID, ChannelPid]),
erlang:monitor(process, ChannelPid),
ChangeResult = iot_api_client:change_host_status(UUID, ?HOST_ONLINE),
logger:debug("[iot_host] host_id(attach_channel) uuid: ~p, denied but online, change status result: ~p", [UUID, ChangeResult]),
{keep_state, State#state{channel_pid = ChannelPid, has_session = true}, [{reply, From, ok}]}
NState = mark_host_online(UUID, HostStatus, State#state{channel_pid = ChannelPid, has_session = true}),
{keep_state, NState, [{reply, From, ok}]}
end;
false ->
logger:notice("[iot_host] attach_channel host_id uuid: ~p, old channel exists: ~p", [UUID, OldChannelPid]),
@ -313,12 +312,8 @@ handle_event(cast, {handle, {ping, Metrics}}, ?STATE_ACTIVATED, State = #state{u
%%
handle_event(cast, heartbeat, _, State = #state{uuid = UUID, heartbeat_counter = HeartbeatCounter, host_status = HostStatus}) ->
case maybe_mark_host_online(UUID, HostStatus) of
keep_status ->
{keep_state, State#state{heartbeat_counter = HeartbeatCounter + 1}};
{next_status, NStatus} ->
{keep_state, State#state{heartbeat_counter = HeartbeatCounter + 1, host_status = NStatus}}
end;
NState = mark_host_online(UUID, HostStatus, State#state{heartbeat_counter = HeartbeatCounter + 1}),
{keep_state, NState};
%% UDP SSL channel host 线
handle_event(info, {timeout, _, heartbeat_ticker}, _,
@ -326,24 +321,15 @@ handle_event(info, {timeout, _, heartbeat_ticker}, _,
erlang:start_timer(?HEARTBEAT_INTERVAL, self(), heartbeat_ticker),
logger:warning("[iot_host] uuid: ~p, udp heartbeat lost but ssl channel is alive: ~p", [UUID, ChannelPid]),
case maybe_mark_host_online(UUID, HostStatus) of
keep_status ->
{keep_state, State#state{heartbeat_counter = 0}};
{next_status, NStatus} ->
{keep_state, State#state{heartbeat_counter = 0, host_status = NStatus}}
end;
NState = mark_host_online(UUID, HostStatus, State#state{heartbeat_counter = 0}),
{keep_state, NState};
%% UDP SSL channel线,
handle_event(info, {timeout, _, heartbeat_ticker}, _, State = #state{uuid = UUID, heartbeat_counter = 0, host_status = HostStatus}) ->
logger:warning("[iot_host] uuid: ~p, heartbeat lost, devices will unknown", [UUID]),
erlang:start_timer(?HEARTBEAT_INTERVAL, self(), heartbeat_ticker),
case maybe_mark_host_offline(UUID, HostStatus) of
keep_status ->
{keep_state, State#state{channel_pid = undefined, has_session = false, heartbeat_counter = 0}};
{next_status, NStatus} ->
{keep_state, State#state{channel_pid = undefined, host_status = NStatus, has_session = false, heartbeat_counter = 0}};
end;
NState = mark_host_offline(UUID, HostStatus, State#state{channel_pid = undefined, has_session = false, heartbeat_counter = 0}),
{keep_state, NState};
%%
handle_event(info, {timeout, _, heartbeat_ticker}, _, State = #state{}) ->
@ -393,10 +379,11 @@ get_route_key(RouteKey) when is_binary(RouteKey) ->
RouteKey.
%% state转换成map
state_map(#state{host_id = HostId, uuid = UUID, has_session = HasSession, heartbeat_counter = HeartbeatCounter, channel_pid = ChannelPid, metrics = Metrics}) ->
state_map(#state{host_id = HostId, uuid = UUID, host_status = HostStatus, has_session = HasSession, heartbeat_counter = HeartbeatCounter, channel_pid = ChannelPid, metrics = Metrics}) ->
#{
host_id => HostId,
uuid => UUID,
host_status => HostStatus,
has_session => HasSession,
heartbeat_counter => HeartbeatCounter,
channel_pid => ChannelPid,
@ -415,12 +402,36 @@ flush_reply(Ref) ->
request_ref() ->
crypto:strong_rand_bytes(16).
-spec mark_host_online(binary(), integer(), #state{}) -> #state{}.
mark_host_online(UUID, HostStatus, State) ->
case maybe_mark_host_online(UUID, HostStatus) of
keep_status ->
State;
{next_status, NStatus} ->
State#state{host_status = NStatus}
end.
-spec mark_host_offline(binary(), integer(), #state{}) -> #state{}.
mark_host_offline(UUID, HostStatus, State) ->
case maybe_mark_host_offline(UUID, HostStatus) of
keep_status ->
State;
{next_status, NStatus} ->
State#state{host_status = NStatus}
end.
-spec maybe_mark_host_online(binary(), integer()) -> {next_status, NStatus :: integer()} | keep_status.
maybe_mark_host_online(UUID, HostStatus) ->
case HostStatus of
?HOST_OFFLINE ->
_ = iot_api_client:change_host_status(UUID, ?HOST_ONLINE),
{next_status, ?HOST_ONLINE};
case iot_api_client:change_host_status(UUID, ?HOST_ONLINE) of
{ok, Result} ->
logger:debug("[iot_host] uuid: ~p, change host status online success: ~p", [UUID, Result]),
{next_status, ?HOST_ONLINE};
{error, Reason} ->
logger:warning("[iot_host] uuid: ~p, change host status online failed: ~p", [UUID, Reason]),
keep_status
end;
_ ->
keep_status
end.
@ -429,8 +440,14 @@ maybe_mark_host_online(UUID, HostStatus) ->
maybe_mark_host_offline(UUID, HostStatus) ->
case HostStatus of
?HOST_ONLINE ->
_ = iot_api_client:change_host_status(UUID, ?HOST_OFFLINE),
{next_status, ?HOST_OFFLINE};
case iot_api_client:change_host_status(UUID, ?HOST_OFFLINE) of
{ok, Result} ->
logger:debug("[iot_host] uuid: ~p, change host status offline success: ~p", [UUID, Result]),
{next_status, ?HOST_OFFLINE};
{error, Reason} ->
logger:warning("[iot_host] uuid: ~p, change host status offline failed: ~p", [UUID, Reason]),
keep_status
end;
_ ->
keep_status
end.