From b4a07fe27308f15f217a262dd21fd367859f28cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E7=A4=BC=E6=88=90?= Date: Wed, 1 Mar 2023 17:06:32 +0800 Subject: [PATCH] add rule --- apps/iot/include/iot.hrl | 7 ++ apps/iot/src/http_router_handler.erl | 74 ++++++++++++++ apps/iot/src/iot_mnesia.erl | 8 ++ apps/iot/src/model/id_generator_model.erl | 22 ++++ apps/iot/src/model/router_model.erl | 117 ++++++++++++++++++++++ 5 files changed, 228 insertions(+) create mode 100644 apps/iot/src/http_router_handler.erl create mode 100644 apps/iot/src/model/id_generator_model.erl create mode 100644 apps/iot/src/model/router_model.erl diff --git a/apps/iot/include/iot.hrl b/apps/iot/include/iot.hrl index 5995dda..75c4f80 100644 --- a/apps/iot/include/iot.hrl +++ b/apps/iot/include/iot.hrl @@ -84,6 +84,12 @@ interfaces = [] }). +%% id生成器 +-record(id_generator, { + name :: string(), + seq = 0 :: integer() +}). + %% 主机定义 -record(host, { %% ID @@ -164,6 +170,7 @@ %% 数据转换规则表 -record(router, { + router_id :: integer(), %% 名称 name = <<>>, %% 数据过滤规则 diff --git a/apps/iot/src/http_router_handler.erl b/apps/iot/src/http_router_handler.erl new file mode 100644 index 0000000..2eece01 --- /dev/null +++ b/apps/iot/src/http_router_handler.erl @@ -0,0 +1,74 @@ +%%%------------------------------------------------------------------- +%%% @author licheng5 +%%% @copyright (C) 2020, +%%% @doc +%%% +%%% @end +%%% Created : 26. 4月 2020 3:36 下午 +%%%------------------------------------------------------------------- +-module(http_router_handler). +-author("licheng5"). +-include("iot.hrl"). + +%% API +-export([handle_request/4]). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% helper methods +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +handle_request(_, "/router/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 = #router{name = '$1', _ = '_'}, + Guard = [], + Guard1 = case Name =/= <<"">> of + true -> + [{'=:=', '$1', Name}|Guard]; + false -> + Guard + end, + + Result = ['$_'], + + case router_model:get_routers({MatchHead, Guard1, Result}, Start, Size) of + {ok, Routers, TotalNum} -> + Response = #{ + <<"routers">> => lists:map(fun(R) -> router_model:to_map(R) end, Routers), + <<"total_num">> => TotalNum + }, + + {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", "/router/detail", #{<<"router_id">> := RouterId}, _) -> + case router_model:get_router(RouterId) of + undefined -> + {ok, 200, iot_util:json_error(404, <<"router not found">>)}; + {ok, Router} -> + RouterInfo = router_model:to_map(Router), + + {ok, 200, iot_util:json_data(RouterInfo)} + end; + +handle_request("POST", "/router/changer_status", _, #{<<"router_id">> := RouterId, <<"status">> := NStatus}) -> + lager:debug("[router_handler] post params is: ~p", [_Params]), + + case router_model:change_status(RouterId, NStatus) of + ok -> + {ok, 200, iot_util:json_data(<<"success">>)}; + {error, _} -> + {ok, 200, iot_util:json_error(404, <<"error">>)} + end. \ No newline at end of file diff --git a/apps/iot/src/iot_mnesia.erl b/apps/iot/src/iot_mnesia.erl index 408a981..5e88006 100644 --- a/apps/iot/src/iot_mnesia.erl +++ b/apps/iot/src/iot_mnesia.erl @@ -24,6 +24,14 @@ init_database() -> ok = mnesia:start(), %% 创建数据库表 + %% id生成表 + mnesia:create_table(id_generator, [ + {attributes, record_info(fields, id_generator)}, + {record_name, id_generator}, + {disc_copies, [node()]}, + {type, ordered_set} + ]), + %% 主机表 mnesia:create_table(host, [ {attributes, record_info(fields, host)}, diff --git a/apps/iot/src/model/id_generator_model.erl b/apps/iot/src/model/id_generator_model.erl new file mode 100644 index 0000000..2590ec2 --- /dev/null +++ b/apps/iot/src/model/id_generator_model.erl @@ -0,0 +1,22 @@ +%%%------------------------------------------------------------------- +%%% @author licheng5 +%%% @copyright (C) 2021, +%%% @doc +%%% +%%% @end +%%% Created : 27. 4月 2021 下午4:38 +%%%------------------------------------------------------------------- +-module(id_generator_model). +-author("licheng5"). +-include("iot.hrl"). + +%% API +-export([generate/1]). + +generate(Name) when is_list(Name) -> + case mnesia:transaction(fun() -> mnesia:dirty_update_counter(id_generator, Name, 1) end) of + {atomic, Id} -> + {ok, Id}; + {aborted, Reason} -> + {error, Reason} + end. \ No newline at end of file diff --git a/apps/iot/src/model/router_model.erl b/apps/iot/src/model/router_model.erl new file mode 100644 index 0000000..59b3bcc --- /dev/null +++ b/apps/iot/src/model/router_model.erl @@ -0,0 +1,117 @@ +%%%------------------------------------------------------------------- +%%% @author licheng5 +%%% @copyright (C) 2021, +%%% @doc +%%% +%%% @end +%%% Created : 27. 4月 2021 下午4:38 +%%%------------------------------------------------------------------- +-module(router_model). +-author("licheng5"). +-include("iot.hrl"). +-include_lib("stdlib/include/qlc.hrl"). + +%% API +-export([get_router/1, get_routers/3, add_router/1, change_status/2, delete/1, table_size/0]). +-export([to_map/1]). + +get_router(RouterId) when is_integer(RouterId) -> + case mnesia:dirty_read(router, RouterId) of + [Router = #router{}] -> + {ok, Router}; + _ -> + undefined + end. + +%% 获取app信息 +-spec get_routers(Filter :: any(), Start :: integer(), Limit :: integer()) -> + {ok, Items :: list(), TotalNum :: integer()} | + {error, Reason :: any()}. +get_routers(Spec, Start, Limit) when is_integer(Limit), is_integer(Start), Start >= 0, Limit > 0 -> + Items0 = mnesia:dirty_select(router, [Spec]), + Items = lists:reverse(Items0), + NItems = lists:sublist(Items, Start + 1, Limit), + {ok, NItems, length(Items)}. + +-spec add_router(Router :: #router{}) -> ok | {error, Reason :: any()}. +add_router(Router = #router{}) -> + case mnesia:transaction(fun() -> mnesia:write(router, Router, write) end) of + {atomic, ok} -> + ok; + {aborted, Error} -> + {error, Error} + end. + +-spec change_status(RouterId :: integer(), Status :: integer()) -> ok | {error, Reason :: any()}. +change_status(RouterId, Status) when is_integer(RouterId), is_integer(Status) -> + Fun = fun() -> + case mnesia:read(router, RouterId) of + [] -> + mnesia:abort(<<"router not found">>); + [Router] -> + mnesia:write(host, Router#router{status = Status}, write) + end + end, + case mnesia:transaction(Fun) of + {atomic, ok} -> + ok; + {aborted, Reason} -> + {error, Reason} + end. + +-spec delete(HostId :: integer()) -> ok | {error, Reason :: any()}. +delete(RouterId) when is_integer(RouterId) -> + case mnesia:transaction(fun() -> mnesia:delete(router, RouterId, write) end) of + {atomic, ok} -> + ok; + {aborted, Reason} -> + {error, Reason} + end. + +%% 获取app表的数据大小 +table_size() -> + mnesia:table_info(router, size). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% helper methods +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +to_map(#host{host_id = HostId, name = Name, model = Model, cell_id = CellId, activated_ts = ActivatedTs, update_ts = UpdateTs, status = Status, + metric = #host_metric{ + cpus = Cpus, + cpu_temperature = CpuTemperature, + memory = #memory_metric{used = MemoryUsed, total = MemoryTotal}, + disk = #disk_metric{used = DiskUsed, total = DiskTotal}, + interfaces = Interfaces}}) -> + #{ + <<"host_id">> => HostId, + <<"name">> => Name, + <<"model">> => Model, + <<"cell_id">> => CellId, + <<"activated_ts">> => ActivatedTs, + <<"update_ts">> => UpdateTs, + <<"status">> => Status, + <<"metric">> => #{ + <<"cpus">> => lists:map(fun(#cpu_metric{num = Num, load = Load}) -> + #{<<"num">> => Num, <<"load">> => Load } + end, + Cpus), + <<"cpu_temperature">> => CpuTemperature, + <<"memory">> => #{ + <<"used">> => MemoryUsed, + <<"total">> => MemoryTotal + }, + <<"disk">> => #{ + <<"used">> => DiskUsed, + <<"total">> => DiskTotal + }, + <<"interfaces">> => lists:map(fun(#interface_metric{name = IName, desc = IDesc, status = IStatus, detail = IDetail}) -> + #{ + <<"name">> => IName, + <<"desc">> => IDesc, + <<"status">> => IStatus, + <<"detatil">> => IDetail + } + end, Interfaces) + } + }. \ No newline at end of file