From 77f938e9dfbfa7cb99bb7e0536493eb57bf15ad4 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 11:56:55 +0800 Subject: [PATCH] fix host --- .../src/http_handler/http_host_handler.erl | 123 +++++++++++------- apps/iot/src/iot_mqtt_publisher.erl | 2 +- apps/iot/src/iot_mqtt_subscriber.erl | 9 +- apps/iot/src/iot_util.erl | 10 +- apps/iot/src/model/host_model.erl | 14 +- 5 files changed, 95 insertions(+), 63 deletions(-) diff --git a/apps/iot/src/http_handler/http_host_handler.erl b/apps/iot/src/http_handler/http_host_handler.erl index 7867d1f..79dc9fb 100644 --- a/apps/iot/src/http_handler/http_host_handler.erl +++ b/apps/iot/src/http_handler/http_host_handler.erl @@ -18,60 +18,79 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% 添加主机 -handle_request("POST", "/host/create", _, - PostParams = #{<<"name">> := Name, <<"model">> := Model, <<"cell_id">> := CellId, <<"serial_number">> := SerialNumber}) -> +handle_request("POST", "/host/create", _, HostInfo) -> + lager:debug("[host_handler] create post params: ~p", [HostInfo]), - lager:debug("[host_handler] create post params: ~p", [PostParams]), - HostId = iot_util:uuid(), - Host = #host{ - host_id = HostId, - serial_number = SerialNumber, - name = Name, - model = Model, - cell_id = CellId, - status = 1 - }, - case host_model:add_host(Host) of - ok -> - {ok, 200, iot_util:json_data(HostId)}; - {error, Reason} -> - lager:warning("[host_handler] get a error: ~p", [Reason]), - {ok, 200, iot_util:json_error(404, <<"database error">>)} + case valid_host_info(HostInfo) of + true -> + 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 + 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)} end; %% 批量导入 handle_request("POST", "/host/batch_create", _, HostInfos) -> lager:debug("[host_handler] batch_create post params: ~p", [HostInfos]), - case lists:all(fun valid_host_info/1, HostInfos) of + %% serial_number是必填项 + case lists:any(fun(Info) -> not is_map_key(<<"serial_number">>, Info) orelse maps:get(<<"serial_number">>, Info) == <<"">> end, 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 = 1 - }, - case host_model:add_host(Host) of - ok -> - {SerialNumber, HostId}; - {error, Reason} -> - lager:debug("[host_handler] add_host get error: ~p", [Reason]), - {SerialNumber, <<"failed">>} - end - end, HostInfos), - - {ok, 200, iot_util:json_data(Result)}; + {ok, 200, iot_util:json_error(-1, <<"serial_number missed">>)}; false -> - {ok, 200, iot_util:json_error(-1, <<"invalid arguments">>)} + 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), + + {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; -handle_request(_, "/host/list", Params, PostParams) -> - Page0 = maps:get(<<"page">>, Params, <<"1">>), - Size0 = maps:get(<<"size">>, Params, <<"10">>), +handle_request(_, "/host/list", GetParams, PostParams) -> + Page0 = maps:get(<<"page">>, GetParams, <<"1">>), + Size0 = maps:get(<<"size">>, GetParams, <<"10">>), Page = binary_to_integer(Page0), Size = binary_to_integer(Size0), @@ -149,9 +168,17 @@ handle_request("POST", "/host/update", _, _Params) -> %% 检查是否是合法的主机信息 valid_host_info(#{<<"name">> := Name, <<"model">> := Model, <<"cell_id">> := CellId, <<"serial_number">> := SerialNumber}) -> - Name =/= <<"">> andalso Model =/= <<"">> andalso CellId > 0 and SerialNumber =/= <<"">>. + Name =/= <<"">> andalso Model =/= <<"">> andalso CellId > 0 andalso SerialNumber =/= <<"">>. -host_error(M = #{<<"name">> := <<>>}) when not is_map_key(<<"name">>, M) -> - -host_error(M = #{<<"name">> := <<>>}) when not is_map_key(<<"name">>, M) -> - ok. +%% 获取错误信息 +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 diff --git a/apps/iot/src/iot_mqtt_publisher.erl b/apps/iot/src/iot_mqtt_publisher.erl index a8bfb8f..fd5bde6 100644 --- a/apps/iot/src/iot_mqtt_publisher.erl +++ b/apps/iot/src/iot_mqtt_publisher.erl @@ -66,7 +66,7 @@ init([]) -> case emqtt:start_link(Opts) of {ok, ConnPid} -> lager:debug("[iot_mqtt_publisher] connect success, pid: ~p", [ConnPid]), - {ok, _} = emqtt:connect(ConnPid), + % {ok, _} = emqtt:connect(ConnPid), {ok, #state{conn_pid = ConnPid}}; ignore -> lager:debug("[iot_mqtt_publisher] connect emqx get ignore"), diff --git a/apps/iot/src/iot_mqtt_subscriber.erl b/apps/iot/src/iot_mqtt_subscriber.erl index dd8aebe..968467a 100644 --- a/apps/iot/src/iot_mqtt_subscriber.erl +++ b/apps/iot/src/iot_mqtt_subscriber.erl @@ -75,15 +75,16 @@ init([]) -> Opts = iot_config:emqt_opts(), case emqtt:start_link(Opts) of {ok, ConnPid} -> - lager:debug("[iot_mqtt_subscriber] connect success, pid: ~p", [ConnPid]), + lager:debug("[iot_mqtt_subscriber] start connecting"), %% 监听和host相关的全部事件 - {ok, _} = emqtt:connect(ConnPid), + %{ok, _} = emqtt:connect(ConnPid), + lager:debug("[iot_mqtt_subscriber] connect success, pid: ~p", [ConnPid]), Topics = [ {<<"$share/nodes_group//server/register">>, 1}, {<<"$share/nodes_group//host/+/upstream">>, 1} ], - SubscribeResult = emqtt:subscribe(ConnPid, Topics), - lager:debug("[iot_mqtt_subscriber] subscribe result is: ~p", [SubscribeResult]), + %SubscribeResult = emqtt:subscribe(ConnPid, Topics), + % lager:debug("[iot_mqtt_subscriber] subscribe topics: ~p, result is: ~p", [Topics, SubscribeResult]), {ok, #state{conn_pid = ConnPid}}; ignore -> diff --git a/apps/iot/src/iot_util.erl b/apps/iot/src/iot_util.erl index ecd9b0e..ec01914 100644 --- a/apps/iot/src/iot_util.erl +++ b/apps/iot/src/iot_util.erl @@ -13,7 +13,7 @@ -export([timestamp/0, number_format/2, current_time/0]). -export([step/3, chunks/2, rand_bytes/1, uuid/0]). -export([json_data/1, json_error/2]). --export([queue_limited_in/3, assert_exec/2]). +-export([queue_limited_in/3]). %% 时间,精确到毫秒 timestamp() -> @@ -80,10 +80,4 @@ queue_limited_in(Item, Q, Num) when is_integer(Num) -> queue:in(Item, Q1); false -> queue:in(Item, Q) - end. - --spec assert_exec(boolean(), any()) -> any(). -assert_exec(true, Fun) when is_function(Fun, 0) -> - {ok, Fun()}; -assert_exec(_, _) -> - aborted. \ No newline at end of file + end. \ 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 7619ab4..32ef9af 100644 --- a/apps/iot/src/model/host_model.erl +++ b/apps/iot/src/model/host_model.erl @@ -83,8 +83,18 @@ find_hosts(Pred, Start, Limit) when is_function(Pred, 1), is_integer(Limit), is_ end. -spec add_host(Host :: #host{}) -> ok | {error, Reason :: any()}. -add_host(Host = #host{}) -> - case mnesia:transaction(fun() -> mnesia:write(host, Host, write) end) of +add_host(Host = #host{serial_number = SerialNumber}) -> + Fun = fun() -> + Q = qlc:q([E || E <- mnesia:table(host), E#host.serial_number =:= SerialNumber]), + case qlc:e(Q) of + [_|_] -> + mnesia:abort(<<"serial_number exists">>); + [] -> + mnesia:write(host, Host, write) + end + end, + + case mnesia:transaction(Fun) of {atomic, _} -> ok; {aborted, Error} ->