From 996540fa210032a776254729261c4d64c1cd9626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E7=A4=BC=E6=88=90?= Date: Wed, 19 Apr 2023 18:06:09 +0800 Subject: [PATCH] simple code --- .../src/http_handler/http_host_handler.erl | 136 +++++++++--------- .../http_handler/http_terminal_handler.erl | 4 +- apps/iot/src/model/host_model.erl | 55 +++++-- apps/iot/src/model/terminal_model.erl | 2 +- 4 files changed, 115 insertions(+), 82 deletions(-) diff --git a/apps/iot/src/http_handler/http_host_handler.erl b/apps/iot/src/http_handler/http_host_handler.erl index 20f27c7..f38ac8a 100644 --- a/apps/iot/src/http_handler/http_host_handler.erl +++ b/apps/iot/src/http_handler/http_host_handler.erl @@ -21,72 +21,48 @@ handle_request("POST", "/host/create", _, HostInfo) -> lager:debug("[host_handler] create post params: ~p", [HostInfo]), - case valid_host_info(HostInfo) of - true -> + case convert_host_info(HostInfo) of + {ok, Host} -> HostId = iot_util:uuid(), - #{<<"name">> := Name, <<"model">> := Model, <<"cell_id">> := CellId, <<"serial_number">> := SerialNumber} = HostInfo, - Host = #host{ - host_id = HostId, - serial_number = SerialNumber, - name = Name, - model = Model, - cell_id = CellId, - status = ?HOST_STATUS_INACTIVE - }, - case host_model:add_host(Host) of + case host_model:add_host(Host#host{host_id = HostId}) of ok -> {ok, 200, iot_util:json_data(HostId)}; {error, Reason} when is_binary(Reason) -> - lager:warning("[host_handler] get a error: ~p", [Reason]), {ok, 200, iot_util:json_error(-1, Reason)}; {error, Reason} when is_binary(Reason) -> {ok, 200, iot_util:json_error(-1, <<"database error">>)} end; - false -> - Error = host_error(HostInfo), - {ok, 200, iot_util:json_error(-1, Error)} + {error, Reason} -> + {ok, 200, iot_util:json_error(-1, Reason)} end; %% 批量导入 handle_request("POST", "/host/batch_import", _, HostInfos) -> lager:debug("[host_handler] batch_create post params: ~p", [HostInfos]), - %% serial_number是必填项 - case lists:any(fun(Info) -> not is_map_key(<<"serial_number">>, Info) orelse maps:get(<<"serial_number">>, Info) == <<"">> end, HostInfos) of - true -> - {ok, 200, iot_util:json_error(-1, <<"serial_number missed">>)}; - false -> - case lists:all(fun valid_host_info/1, HostInfos) of - true -> - Result = lists:map(fun(#{<<"name">> := Name, <<"model">> := Model, <<"cell_id">> := CellId, <<"serial_number">> := SerialNumber}) -> - HostId = iot_util:uuid(), - Host = #host{ - host_id = HostId, - serial_number = SerialNumber, - name = Name, - model = Model, - cell_id = CellId, - status = ?HOST_STATUS_INACTIVE - }, - case host_model:add_host(Host) of - ok -> - {SerialNumber, HostId}; - {error, Reason} when is_binary(Reason) -> - lager:debug("[host_handler] add_host get error: ~p", [Reason]), - {SerialNumber, Reason}; - {error, Reason} -> - {SerialNumber, <<"failed">>} - end - end, HostInfos), + {SuccessList, FailedList} = lists:foldl(fun(HostInfo, {SuccessList0, FailedList0}) -> + case convert_host_info(HostInfo) of + {ok, Host = #host{serial_number = SerialNumber}} -> + HostId = iot_util:uuid(), + case host_model:add_host(Host#host{host_id = HostId}) of + ok -> + SuccessItem = #{<<"serial_number">> => SerialNumber, <<"host_id">> => HostId}, + {[SuccessItem|SuccessList0], FailedList0}; + {error, Reason} when is_binary(Reason) -> + ErrorItem = maps:put(<<"error_message">>, Reason, HostInfo), + {SuccessList0, [ErrorItem|FailedList0]} + end; + {error, Reason} -> + ErrorItem = maps:put(<<"error_message">>, Reason, HostInfo), + {SuccessList0, [ErrorItem|FailedList0]} + end + end, {[], []}, HostInfos), + ImportResult = #{ + <<"success_list">> => lists:reverse(SuccessList), + <<"failed_list">> => lists:reverse(FailedList) + }, - {ok, 200, iot_util:json_data(Result)}; - false -> - %% 反馈错误信息 - InvalidHostInfos = lists:filter(fun(Info) -> not valid_host_info(Info) end, HostInfos), - ErrorInfos = lists:map(fun(Info = #{<<"serial_number">> := SerialNumber}) -> {SerialNumber, host_error(Info)} end, InvalidHostInfos), - {ok, 200, iot_util:json_error(-1, maps:from_list(ErrorInfos))} - end - end; + {ok, 200, iot_util:json_data(ImportResult)}; handle_request(_, "/host/list", GetParams, PostParams) -> Page0 = maps:get(<<"page">>, GetParams, <<"1">>), @@ -157,28 +133,50 @@ handle_request("GET", "/host/detail", #{<<"id">> := HostId}, _) -> {ok, 200, iot_util:json_data(HostInfo3)} end; -handle_request("POST", "/host/update", _, _Params) -> - lager:debug("[host_handler] post params is: ~p", [_Params]), +handle_request("POST", "/host/update", _, Fields0 = #{<<"host_id">> := HostId}) when is_binary(HostId) -> + lager:debug("[host_handler] post params is: ~p", [Fields0]), - {ok, 200, iot_util:json_data(<<"success">>)}. + Fields = maps:remove(<<"host_id">>, Fields0), + case host_model:update_host(HostId, Fields) of + ok -> + {ok, 200, iot_util:json_data(<<"success">>)}; + {error, Reason} when is_binary(Reason) -> + {ok, 200, iot_util:json_error(-1, Reason)} + end; + +handle_request(_, Path, _, _) -> + Path1 = list_to_binary(Path), + {ok, 200, iot_util:json_error(-1, <<"url: ", Path1/binary, " not found">>)}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% helper methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% 检查是否是合法的主机信息 -valid_host_info(#{<<"name">> := Name, <<"model">> := Model, <<"cell_id">> := CellId, <<"serial_number">> := SerialNumber}) -> - Name =/= <<"">> andalso Model =/= <<"">> andalso CellId > 0 andalso SerialNumber =/= <<"">>. +convert_host_info(#{<<"name">> := Name, <<"model">> := Model, <<"cell_id">> := CellId, <<"serial_number">> := SerialNumber}) -> + CheckResult = if + Name == <<>> -> + {error, <<"name is empty">>}; + Model == <<>> -> + {error, <<"model is empty">>}; + SerialNumber == <<>> -> + {error, <<"serial_number is empty">>}; + not is_integer(CellId) orelse CellId < 0 -> + {ok, <<"cell_id is error">>}; + true -> + ok + end, -%% 获取错误信息 -host_error(M) when is_map(M) -> - if - not is_map_key(<<"name">>, M) orelse map_get(<<"name">>, M) == <<>> -> - <<"name is empty">>; - not is_map_key(<<"model">>, M) orelse map_get(<<"model">>, M) == <<>> -> - <<"model is empty">>; - not is_map_key(<<"serial_number">>, M) orelse map_get(<<"serial_number">>, M) == <<>> -> - <<"serial_number is empty">>; - true -> - <<"unknown error">> - end. \ No newline at end of file + case CheckResult of + ok -> + {ok, #host{ + serial_number = SerialNumber, + name = Name, + model = Model, + cell_id = CellId, + status = ?HOST_STATUS_INACTIVE + }}; + {error, Reason} -> + {error, Reason} + end; +convert_host_info(_) -> + {error, <<"miss required param">>}. \ No newline at end of file diff --git a/apps/iot/src/http_handler/http_terminal_handler.erl b/apps/iot/src/http_handler/http_terminal_handler.erl index f5b4f19..61cdbb7 100644 --- a/apps/iot/src/http_handler/http_terminal_handler.erl +++ b/apps/iot/src/http_handler/http_terminal_handler.erl @@ -206,4 +206,6 @@ convert_terminal_info(#{<<"host_id">> := HostId, <<"serial_number">> := SerialNu }}; {error, Reason} -> {error, Reason} - end. \ No newline at end of file + end; +convert_terminal_info(_) -> + {error, <<"miss required param">>}. \ No newline at end of file diff --git a/apps/iot/src/model/host_model.erl b/apps/iot/src/model/host_model.erl index 74c3213..c10355d 100644 --- a/apps/iot/src/model/host_model.erl +++ b/apps/iot/src/model/host_model.erl @@ -11,12 +11,14 @@ -include("iot.hrl"). -include_lib("stdlib/include/qlc.hrl"). +-define(TAB_NAME, host). + %% API --export([get_host/1, get_hosts/3, get_all_hosts/0, get_stat/0, add_host/1, change_status/2, delete/1, table_size/0, find_hosts/3, activate/1]). +-export([get_host/1, get_hosts/3, get_all_hosts/0, get_stat/0, add_host/1, change_status/2, delete/1, table_size/0, find_hosts/3, activate/1, update_host/2]). -export([to_map/1, match_spec/1]). get_host(HostId) when is_binary(HostId) -> - case mnesia:dirty_read(host, HostId) of + case mnesia:dirty_read(?TAB_NAME, HostId) of [Host = #host{}] -> {ok, Host}; _ -> @@ -25,7 +27,7 @@ get_host(HostId) when is_binary(HostId) -> get_all_hosts() -> Fun = fun() -> - Q = qlc:q([E || E <- mnesia:table(host), E#host.status == 1]), + Q = qlc:q([E || E <- mnesia:table(?TAB_NAME), E#host.status == ?HOST_STATUS_ONLINE]), qlc:e(Q) end, case mnesia:transaction(Fun) of @@ -40,8 +42,7 @@ get_all_hosts() -> {ok, Items :: list(), TotalNum :: integer()} | {error, Reason :: any()}. get_hosts(Spec, Start, Limit) when is_integer(Limit), is_integer(Start), Start >= 0, Limit > 0 -> - Hosts0 = mnesia:dirty_select(host, [Spec]), - %% TODO 处理host的排序方式 + Hosts0 = mnesia:dirty_select(?TAB_NAME, [Spec]), SortedHosts = sort(Hosts0), Len = length(SortedHosts), case Len >= Start + 1 of @@ -57,7 +58,7 @@ get_stat() -> mnesia:foldl(fun(#host{status = Status}, Acc) -> Num = maps:get(Status, Acc, 0), Acc#{Status => Num + 1} - end, #{}, host) + end, #{}, ?TAB_NAME) end, case mnesia:transaction(Fun) of {atomic, Stat} when is_map(Stat) -> @@ -71,7 +72,7 @@ get_stat() -> {error, Reason :: any()}. find_hosts(Pred, Start, Limit) when is_function(Pred, 1), is_integer(Limit), is_integer(Start), Start >= 0, Limit > 0 -> Fun = fun() -> - Q = qlc:q([E || E <- mnesia:table(host)]), + Q = qlc:q([E || E <- mnesia:table(?TAB_NAME)]), qlc:fold(fun(Host, Acc) -> case Pred(Host) of true -> [Host|Acc]; @@ -97,12 +98,12 @@ find_hosts(Pred, Start, Limit) when is_function(Pred, 1), is_integer(Limit), is_ -spec add_host(Host :: #host{}) -> ok | {error, Reason :: binary()}. add_host(Host = #host{serial_number = SerialNumber}) -> Fun = fun() -> - Q = qlc:q([E || E <- mnesia:table(host), E#host.serial_number =:= SerialNumber]), + Q = qlc:q([E || E <- mnesia:table(?TAB_NAME), E#host.serial_number =:= SerialNumber]), case qlc:e(Q) of [_SomeHost|_] -> mnesia:abort(<<"serial_number exists">>); [] -> - mnesia:write(host, Host, write) + mnesia:write(?TAB_NAME, Host, write) end end, @@ -116,11 +117,43 @@ add_host(Host = #host{serial_number = SerialNumber}) -> -spec change_status(HostId :: binary(), Status :: integer()) -> ok | {error, Reason :: any()}. change_status(HostId, Status) when is_binary(HostId), is_integer(Status) -> Fun = fun() -> - case mnesia:read(host, HostId) of + case mnesia:read(?TAB_NAME, HostId) of [] -> mnesia:abort(<<"host not found">>); [Host] -> - mnesia:write(host, Host#host{status = Status}, write) + mnesia:write(?TAB_NAME, Host#host{status = Status}, write) + end + end, + case mnesia:transaction(Fun) of + {atomic, ok} -> + ok; + {aborted, Reason} -> + {error, Reason} + end. + +-spec update_host(HostId :: binary(), Fields :: #{}) -> ok | {error, Reason :: any()}. +update_host(HostId, Fields) when is_binary(HostId), is_map(Fields) -> + Fun = fun() -> + case mnesia:read(?TAB_NAME, HostId) of + [] -> + mnesia:abort(<<"host not found">>); + [Host] -> + NHost = lists:foldl(fun(E, Host0) -> + case E of + {<<"name">>, Name} when is_binary(Name) -> + Host0#host{name = Name}; + {<<"serial_number">>, SerialNumber} when is_binary(SerialNumber) -> + Host0#host{serial_number = SerialNumber}; + {<<"model">>, Model} when is_binary(Model) -> + Host0#host{model = Model}; + {<<"cell_id">>, CellId} when is_integer(CellId) -> + Host0#host{cell_id = CellId}; + {Name, _} -> + mnesia:abort(<<"invalid: ", Name/binary>>) + end + end, Host, maps:to_list(Fields)), + + mnesia:write(?TAB_NAME, NHost, write) end end, case mnesia:transaction(Fun) of diff --git a/apps/iot/src/model/terminal_model.erl b/apps/iot/src/model/terminal_model.erl index 9352c5d..85c5d26 100644 --- a/apps/iot/src/model/terminal_model.erl +++ b/apps/iot/src/model/terminal_model.erl @@ -101,7 +101,7 @@ add_terminal(Terminal = #terminal{}) -> {error, Error} end. --spec change_status(TerminalId :: integer(), Fields :: #{}) -> ok | {error, Reason :: any()}. +-spec update_terminal(TerminalId :: integer(), Fields :: #{}) -> ok | {error, Reason :: any()}. update_terminal(TerminalId, Fields) when is_integer(TerminalId), is_map(Fields) -> Fun = fun() -> case mnesia:read(?TAB_NAME, TerminalId) of