fix host_status
This commit is contained in:
parent
0dd6f9715a
commit
fe46aff527
@ -36,6 +36,9 @@
|
|||||||
host_id :: integer(),
|
host_id :: integer(),
|
||||||
%% 从数据库里面读取到的数据
|
%% 从数据库里面读取到的数据
|
||||||
uuid :: binary(),
|
uuid :: binary(),
|
||||||
|
%% 主机状态
|
||||||
|
host_status :: integer(),
|
||||||
|
|
||||||
has_session = false :: boolean(),
|
has_session = false :: boolean(),
|
||||||
%% 心跳计数器
|
%% 心跳计数器
|
||||||
heartbeat_counter = 0 :: integer(),
|
heartbeat_counter = 0 :: integer(),
|
||||||
@ -179,7 +182,7 @@ start_link(Name, UUID) when is_binary(UUID) ->
|
|||||||
init([UUID]) ->
|
init([UUID]) ->
|
||||||
ok = iot_log:set_metadata(),
|
ok = iot_log:set_metadata(),
|
||||||
case iot_api_client:get_host_by_uuid(UUID) of
|
case iot_api_client:get_host_by_uuid(UUID) of
|
||||||
{ok, #host_info{id = HostId, authorize_status = AuthorizeStatus}} ->
|
{ok, #host_info{id = HostId, authorize_status = AuthorizeStatus, status = HostStatus}} ->
|
||||||
%% 通过host_id注册别名, 可以避免通过查询数据库获取HostPid
|
%% 通过host_id注册别名, 可以避免通过查询数据库获取HostPid
|
||||||
AliasName = get_alias_name(HostId),
|
AliasName = get_alias_name(HostId),
|
||||||
global:register_name(AliasName, self()),
|
global:register_name(AliasName, self()),
|
||||||
@ -191,7 +194,7 @@ init([UUID]) ->
|
|||||||
true -> ?STATE_ACTIVATED;
|
true -> ?STATE_ACTIVATED;
|
||||||
false -> ?STATE_DENIED
|
false -> ?STATE_DENIED
|
||||||
end,
|
end,
|
||||||
{ok, StateName, #state{host_id = HostId, uuid = UUID, has_session = false}};
|
{ok, StateName, #state{host_id = HostId, uuid = UUID, host_status = HostStatus, has_session = false}};
|
||||||
undefined ->
|
undefined ->
|
||||||
logger:warning("[iot_host] host uuid: ~p, load host info failed", [UUID]),
|
logger:warning("[iot_host] host uuid: ~p, load host info failed", [UUID]),
|
||||||
ignore
|
ignore
|
||||||
@ -309,24 +312,38 @@ handle_event(cast, {handle, {ping, Metrics}}, ?STATE_ACTIVATED, State = #state{u
|
|||||||
{keep_state, State#state{metrics = Metrics}};
|
{keep_state, State#state{metrics = Metrics}};
|
||||||
|
|
||||||
%% 心跳机制
|
%% 心跳机制
|
||||||
handle_event(cast, heartbeat, _, State = #state{uuid = UUID, heartbeat_counter = HeartbeatCounter}) ->
|
handle_event(cast, heartbeat, _, State = #state{uuid = UUID, heartbeat_counter = HeartbeatCounter, host_status = HostStatus}) ->
|
||||||
maybe_mark_host_online(UUID),
|
case maybe_mark_host_online(UUID, HostStatus) of
|
||||||
|
keep_status ->
|
||||||
{keep_state, State#state{heartbeat_counter = HeartbeatCounter + 1}};
|
{keep_state, State#state{heartbeat_counter = HeartbeatCounter + 1}};
|
||||||
|
{next_status, NStatus} ->
|
||||||
|
{keep_state, State#state{heartbeat_counter = HeartbeatCounter + 1, host_status = NStatus}}
|
||||||
|
end;
|
||||||
|
|
||||||
%% UDP 心跳丢失但 SSL channel 仍在时,不能把 host 标记为离线。
|
%% UDP 心跳丢失但 SSL channel 仍在时,不能把 host 标记为离线。
|
||||||
handle_event(info, {timeout, _, heartbeat_ticker}, _, State = #state{uuid = UUID, heartbeat_counter = 0, channel_pid = ChannelPid}) when is_pid(ChannelPid) ->
|
handle_event(info, {timeout, _, heartbeat_ticker}, _,
|
||||||
logger:warning("[iot_host] uuid: ~p, udp heartbeat lost but ssl channel is alive: ~p", [UUID, ChannelPid]),
|
State = #state{uuid = UUID, heartbeat_counter = 0, host_status = HostStatus, channel_pid = ChannelPid}) when is_pid(ChannelPid) ->
|
||||||
maybe_mark_host_online(UUID),
|
|
||||||
erlang:start_timer(?HEARTBEAT_INTERVAL, self(), 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}};
|
{keep_state, State#state{heartbeat_counter = 0}};
|
||||||
|
{next_status, NStatus} ->
|
||||||
|
{keep_state, State#state{heartbeat_counter = 0, host_status = NStatus}}
|
||||||
|
end;
|
||||||
|
|
||||||
%% 没有收到 UDP 心跳且没有 SSL channel,主机下线, 设备状态不变
|
%% 没有收到 UDP 心跳且没有 SSL channel,主机下线, 设备状态不变
|
||||||
handle_event(info, {timeout, _, heartbeat_ticker}, _, State = #state{uuid = UUID, heartbeat_counter = 0}) ->
|
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]),
|
logger:warning("[iot_host] uuid: ~p, heartbeat lost, devices will unknown", [UUID]),
|
||||||
maybe_mark_host_offline(UUID),
|
|
||||||
erlang:start_timer(?HEARTBEAT_INTERVAL, self(), heartbeat_ticker),
|
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}};
|
{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;
|
||||||
|
|
||||||
%% 其他情况下需要重置系统计数器
|
%% 其他情况下需要重置系统计数器
|
||||||
handle_event(info, {timeout, _, heartbeat_ticker}, _, State = #state{}) ->
|
handle_event(info, {timeout, _, heartbeat_ticker}, _, State = #state{}) ->
|
||||||
@ -398,34 +415,22 @@ flush_reply(Ref) ->
|
|||||||
request_ref() ->
|
request_ref() ->
|
||||||
crypto:strong_rand_bytes(16).
|
crypto:strong_rand_bytes(16).
|
||||||
|
|
||||||
-spec maybe_mark_host_offline(binary()) -> ok.
|
-spec maybe_mark_host_online(binary(), integer()) -> {next_status, NStatus :: integer()} | keep_status.
|
||||||
maybe_mark_host_offline(UUID) ->
|
maybe_mark_host_online(UUID, HostStatus) ->
|
||||||
case iot_api_client:get_host_by_uuid(UUID) of
|
case HostStatus of
|
||||||
{ok, #host_info{status = ?HOST_NOT_JOINED}} ->
|
?HOST_OFFLINE ->
|
||||||
logger:debug("[iot_host] host: ~p, host_maybe_offline, host not joined, can not change to offline", [UUID]),
|
_ = iot_api_client:change_host_status(UUID, ?HOST_ONLINE),
|
||||||
ok;
|
{next_status, ?HOST_ONLINE};
|
||||||
{ok, #host_info{status = ?HOST_OFFLINE}} ->
|
_ ->
|
||||||
logger:debug("[iot_host] host: ~p, host_maybe_offline, host now is offline, do nothing", [UUID]),
|
keep_status
|
||||||
ok;
|
|
||||||
{ok, #host_info{status = ?HOST_ONLINE}} ->
|
|
||||||
_ = iot_api_client:change_host_status(UUID, ?HOST_OFFLINE),
|
|
||||||
ok;
|
|
||||||
Other ->
|
|
||||||
logger:warning("[iot_host] host: ~p, load status failed while marking offline: ~p", [UUID, Other]),
|
|
||||||
ok
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec maybe_mark_host_online(binary()) -> ok.
|
-spec maybe_mark_host_offline(binary(), integer()) -> {next_status, NStatus :: integer()} | keep_status.
|
||||||
maybe_mark_host_online(UUID) ->
|
maybe_mark_host_offline(UUID, HostStatus) ->
|
||||||
case iot_api_client:get_host_by_uuid(UUID) of
|
case HostStatus of
|
||||||
{ok, #host_info{status = ?HOST_OFFLINE}} ->
|
?HOST_ONLINE ->
|
||||||
_ = iot_api_client:change_host_status(UUID, ?HOST_ONLINE),
|
_ = iot_api_client:change_host_status(UUID, ?HOST_OFFLINE),
|
||||||
ok;
|
{next_status, ?HOST_OFFLINE};
|
||||||
{ok, #host_info{status = ?HOST_ONLINE}} ->
|
_ ->
|
||||||
ok;
|
keep_status
|
||||||
{ok, #host_info{status = ?HOST_NOT_JOINED}} ->
|
|
||||||
ok;
|
|
||||||
Other ->
|
|
||||||
logger:warning("[iot_host] host: ~p, load status failed while marking online: ~p", [UUID, Other]),
|
|
||||||
ok
|
|
||||||
end.
|
end.
|
||||||
Loading…
x
Reference in New Issue
Block a user