diff --git a/apps/iot/include/iot.hrl b/apps/iot/include/iot.hrl index f9c1b4d..d607d14 100644 --- a/apps/iot/include/iot.hrl +++ b/apps/iot/include/iot.hrl @@ -166,6 +166,38 @@ status = 0 }). +%% scenario 应用场景 +-record(scenario, { + %% 场景id,自增id + scenario_id :: integer(), + %% 名称 + name :: binary(), + %% 场景描述 + desc :: binary(), + %% 场景规则数据 + rule :: binary(), + %% 最后更新时间 + update_ts = 0 :: integer(), + %% 状态 + status :: integer() +}). + +%% 场景部署关系表 +-record(scenario_deploy, { + %% id,自增id + deploy_id :: integer(), + %% 场景id + scenario_id :: integer(), + %% 主机id + host_id :: binary(), + %% 创建时间 + create_ts = 0 :: integer(), + %% 更新时间 + update_ts = 0 :: integer(), + %% 状态 + status = 0:: integer() +}). + -record(http_endpoint, { url = <<>> }). diff --git a/apps/iot/src/http_handler/http_host_handler.erl b/apps/iot/src/http_handler/http_host_handler.erl index 75bdeaf..dcbe936 100644 --- a/apps/iot/src/http_handler/http_host_handler.erl +++ b/apps/iot/src/http_handler/http_host_handler.erl @@ -72,7 +72,6 @@ handle_request(_, "/host/list", Params, PostParams) -> handle_request("GET", "/host/detail", #{<<"id">> := HostId}, _) -> lager:debug("[host_handler] detail id is: ~p", [HostId]), - timer:tc(), case host_model:get_host(HostId) of undefined -> {ok, 200, iot_util:json_error(404, <<"host not found">>)}; diff --git a/apps/iot/src/http_handler/http_scenario_handler.erl b/apps/iot/src/http_handler/http_scenario_handler.erl new file mode 100644 index 0000000..ab7b741 --- /dev/null +++ b/apps/iot/src/http_handler/http_scenario_handler.erl @@ -0,0 +1,88 @@ +%%%------------------------------------------------------------------- +%%% @author licheng5 +%%% @copyright (C) 2020, +%%% @doc +%%% +%%% @end +%%% Created : 26. 4月 2020 3:36 下午 +%%%------------------------------------------------------------------- +-module(http_scenario_handler). +-author("licheng5"). +-include("iot.hrl"). + +%% API +-export([handle_request/4]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% helper methods +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +handle_request(_, "/scenario/list", Params, PostParams) -> + Page0 = maps:get(<<"page">>, Params, <<"1">>), + Size0 = maps:get(<<"size">>, Params, <<"10">>), + Page = binary_to_integer(Page0), + Size = binary_to_integer(Size0), + + true = Page > 0 andalso Size > 0, + Start = (Page - 1) * Size, + + %% 处理查询条件 + Name = maps:get(<<"name">>, PostParams, <<"">>), + + MatchHead = #scenario{name = '$1', _ = '_'}, + Guard = [], + Guard1 = case Model =/= <<"">> of + true -> + [{'=:=', '$1', Model}|Guard]; + false -> + Guard + end, + + Guard2 = case CellId1 > 0 of + true -> + [{'=:=', '$2', CellId1}|Guard1]; + false -> + Guard1 + end, + + Result = ['$_'], + + case host_model:get_hosts({MatchHead, Guard2, Result}, Start, Size) of + {ok, Hosts, TotalNum} -> + Response = #{ + <<"hosts">> => lists:map(fun(Host) -> host_model:to_map(Host) end, Hosts), + <<"stat">> => host_model:get_stat(), + <<"total_num">> => TotalNum + }, + + lager:debug("resp is: ~p", [Response]), + + {ok, 200, iot_util:json_data(Response)}; + {error, Reason} -> + lager:warning("[host_handler] get a error: ~p", [Reason]), + {ok, 200, iot_util:json_error(404, <<"database error">>)} + end; + +handle_request("GET", "/host/detail", #{<<"id">> := HostId}, _) -> + lager:debug("[host_handler] detail id is: ~p", [HostId]), + case host_model:get_host(HostId) of + undefined -> + {ok, 200, iot_util:json_error(404, <<"host not found">>)}; + {ok, Host} -> + HostInfo = host_model:to_map(Host), + %% 获取终端信息 + {ok, Terminals0} = terminal_model:get_host_terminals(HostId), + Terminals = lists:map(fun(E) -> terminal_model:to_map(E) end, Terminals0), + HostInfo1 = maps:put(<<"terminals">>, Terminals, HostInfo), + %% 获取微服务信息 + {ok, Services0} = service_model:get_host_services(HostId), + Services = lists:map(fun(S) -> service_model:to_map(S) end, Services0), + HostInfo2 = maps:put(<<"services">>, Services, HostInfo1), + + {ok, 200, iot_util:json_data(HostInfo2)} + end; + +handle_request("POST", "/host/update", _, _Params) -> + lager:debug("[host_handler] post params is: ~p", [_Params]), + + {ok, 200, iot_util:json_data(<<"success">>)}. \ No newline at end of file diff --git a/apps/iot/src/model/scenario_deploy_model.erl b/apps/iot/src/model/scenario_deploy_model.erl new file mode 100644 index 0000000..f99ea3f --- /dev/null +++ b/apps/iot/src/model/scenario_deploy_model.erl @@ -0,0 +1,97 @@ +%%%------------------------------------------------------------------- +%%% @author licheng5 +%%% @copyright (C) 2021, +%%% @doc +%%% +%%% @end +%%% Created : 27. 4月 2021 下午4:38 +%%%------------------------------------------------------------------- +-module(scenario_deploy_model). +-author("licheng5"). +-include("iot.hrl"). +-include_lib("stdlib/include/qlc.hrl"). + +-define(TAB_NAME, scenario_deploy). + +%% API +-export([get_host_deploy_list/1, get_scenario_deploy_list/1, add_deploy/1, change_status/2, delete/1, table_size/0]). +-export([to_map/1]). + +-spec get_host_deploy_list(HostId :: binary()) -> {ok, List :: [#scenario_deploy{}]} | error. +get_host_deploy_list(HostId) when is_binary(HostId) -> + Fun = fun() -> + Q = qlc:q([E || E <- mnesia:table(?TAB_NAME), E#scenario_deploy.host_id =:= HostId]), + qlc:e(Q) + end, + case mnesia:transaction(Fun) of + {atomic, Items} -> + {ok, Items}; + {aborted, _} -> + error + end. + +-spec get_scenario_deploy_list(ScenarioId :: integer()) -> {ok, List :: [#scenario_deploy{}]} | error. +get_scenario_deploy_list(ScenarioId) when is_integer(ScenarioId) -> + Fun = fun() -> + Q = qlc:q([E || E <- mnesia:table(?TAB_NAME), E#scenario_deploy.scenario_id =:= ScenarioId]), + qlc:e(Q) + end, + case mnesia:transaction(Fun) of + {atomic, Items} -> + {ok, Items}; + {aborted, _} -> + error + end. + +-spec add_deploy(Deploy :: #scenario_deploy{}) -> ok | {error, Reason :: any()}. +add_deploy(Deploy = #scenario_deploy{}) -> + case mnesia:transaction(fun() -> mnesia:write(?TAB_NAME, Deploy, write) end) of + {atomic, _} -> + ok; + {aborted, Error} -> + {error, Error} + end. + +-spec change_status(DeployId :: integer(), Status :: integer()) -> ok | {error, Reason :: any()}. +change_status(DeployId, Status) when is_integer(DeployId), is_integer(Status) -> + Fun = fun() -> + case mnesia:read(?TAB_NAME, DeployId) of + [] -> + mnesia:abort(<<"deploy not found">>); + [Deploy] -> + mnesia:write(?TAB_NAME, Deploy#scenario_deploy{status = Status}, write) + end + end, + case mnesia:transaction(Fun) of + {atomic, ok} -> + ok; + {aborted, Reason} -> + {error, Reason} + end. + +-spec delete(DeployId :: binary()) -> ok | {error, Reason :: any()}. +delete(DeployId) when is_integer(DeployId) -> + case mnesia:transaction(fun() -> mnesia:delete(?TAB_NAME, DeployId, write) end) of + {atomic, ok} -> + ok; + {aborted, Reason} -> + {error, Reason} + end. + +%% 获取app表的数据大小 +table_size() -> + mnesia:table_info(?TAB_NAME, size). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% helper methods +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +to_map(#scenario_deploy{deploy_id = DeployId, scenario_id = ScenarioId, host_id = HostId, create_ts = CreateTs, update_ts = UpdateTs, status = Status}) -> + #{ + <<"deploy_id">> => DeployId, + <<"scenario_id">> => ScenarioId, + <<"host_id">> => HostId, + <<"create_ts">> => CreateTs, + <<"update_ts">> => UpdateTs, + <<"status">> => Status + }. \ No newline at end of file diff --git a/apps/iot/src/model/scenario_model.erl b/apps/iot/src/model/scenario_model.erl new file mode 100644 index 0000000..d573465 --- /dev/null +++ b/apps/iot/src/model/scenario_model.erl @@ -0,0 +1,87 @@ +%%%------------------------------------------------------------------- +%%% @author licheng5 +%%% @copyright (C) 2021, +%%% @doc +%%% +%%% @end +%%% Created : 27. 4月 2021 下午4:38 +%%%------------------------------------------------------------------- +-module(scenario_model). +-author("licheng5"). +-include("iot.hrl"). +-include_lib("stdlib/include/qlc.hrl"). + +%% API +-export([get_scenario/1, get_scenario_list/3, add_scenario/1, change_status/2, delete/1, table_size/0]). +-export([to_map/1]). + +get_scenario(ScenarioId) when is_integer(ScenarioId) -> + case mnesia:dirty_read(scenario, ScenarioId) of + [Scenario = #scenario{}] -> + {ok, Scenario}; + _ -> + undefined + end. + +%% 获取app信息 +-spec get_scenario_list(Filter :: any(), Start :: integer(), Limit :: integer()) -> + {ok, Items :: list(), TotalNum :: integer()} | + {error, Reason :: any()}. +get_scenario_list(Spec, Start, Limit) when is_integer(Limit), is_integer(Start), Start >= 0, Limit > 0 -> + Items0 = mnesia:dirty_select(scenario, [Spec]), + Items = lists:reverse(Items0), + NItems = lists:sublist(Items, Start + 1, Limit), + {ok, NItems, length(Items)}. + +-spec add_scenario(Scenario :: #scenario{}) -> ok | {error, Reason :: any()}. +add_scenario(Scenario = #scenario{}) -> + case mnesia:transaction(fun() -> mnesia:write(scenario, Scenario, write) end) of + {atomic, _} -> + ok; + {aborted, Error} -> + {error, Error} + end. + +-spec change_status(ScenarioId :: integer(), Status :: integer()) -> ok | {error, Reason :: any()}. +change_status(ScenarioId, Status) when is_integer(ScenarioId), is_integer(Status) -> + Fun = fun() -> + case mnesia:read(scenario, ScenarioId) of + [] -> + mnesia:abort(<<"host not found">>); + [Scenario] -> + mnesia:write(scenario, Scenario#scenario{status = Status}, write) + end + end, + case mnesia:transaction(Fun) of + {atomic, ok} -> + ok; + {aborted, Reason} -> + {error, Reason} + end. + +-spec delete(ScenarioId :: binary()) -> ok | {error, Reason :: any()}. +delete(ScenarioId) when is_integer(ScenarioId) -> + case mnesia:transaction(fun() -> mnesia:delete(scenario, ScenarioId, write) end) of + {atomic, ok} -> + ok; + {aborted, Reason} -> + {error, Reason} + end. + +%% 获取app表的数据大小 +table_size() -> + mnesia:table_info(scenario, size). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% helper methods +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +to_map(#scenario{scenario_id = ScenarioId, name = Name, desc = Desc, rule = Rule, update_ts = UpdateTs, status = Status}) -> + #{ + <<"scenario_id">> => ScenarioId, + <<"name">> => Name, + <<"desc">> => Desc, + <<"rule">> => Rule, + <<"update_ts">> => UpdateTs, + <<"status">> => Status + }. \ No newline at end of file