Просмотр исходного кода

Merge pull request #7114 from lafirest/refactor/coap_api

refactor(emqx_coap): refactor CoAP API
JianBo He 3 лет назад
Родитель
Сommit
48cc641ec0
1 измененных файлов с 65 добавлено и 61 удалено
  1. 65 61
      apps/emqx_gateway/src/coap/emqx_coap_api.erl

+ 65 - 61
apps/emqx_gateway/src/coap/emqx_coap_api.erl

@@ -18,93 +18,89 @@
 
 
 -behaviour(minirest_api).
 -behaviour(minirest_api).
 
 
+-include_lib("typerefl/include/types.hrl").
+-include_lib("emqx/include/logger.hrl").
 -include("src/coap/include/emqx_coap.hrl").
 -include("src/coap/include/emqx_coap.hrl").
 
 
 %% API
 %% API
--export([api_spec/0]).
+-export([api_spec/0, paths/0, schema/1, namespace/0]).
 
 
 -export([request/2]).
 -export([request/2]).
 
 
 -define(PREFIX, "/gateway/coap/clients/:clientid").
 -define(PREFIX, "/gateway/coap/clients/:clientid").
--define(DEF_WAIT_TIME, 10).
 
 
--import(emqx_mgmt_util, [ schema/1
-                        , schema/2
-                        , object_schema/1
-                        , object_schema/2
-                        , error_schema/2
-                        , properties/1]).
+-import(hoconsc, [mk/2, enum/1]).
+-import(emqx_dashboard_swagger, [error_codes/2]).
 
 
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------
 %%  API
 %%  API
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------
+namespace() -> "gateway_coap".
+
 api_spec() ->
 api_spec() ->
-    {[request_api()], []}.
+    emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true, translate_body => true}).
+
+paths() ->
+    [?PREFIX ++ "/request"].
+
+schema(?PREFIX ++ "/request") ->
+    #{operationId => request,
+      post => #{ tags => [<<"gateway|coap">>]
+               , description => <<"Send a CoAP request message to the client">>
+               , parameters => request_parameters()
+               , requestBody => request_body()
+               , responses => #{200 => coap_message(),
+                                404 => error_codes(['CLIENT_NOT_FOUND'], <<"Client not found error">>),
+                                504 => error_codes(['CLIENT_NOT_RESPONSE'], <<"Waiting for client response timeout">>)}
+               }
+     }.
 
 
-request_api() ->
-    Metadata = #{post => request_method_meta()},
-    {?PREFIX ++ "/request", Metadata, request}.
 
 
 request(post, #{body := Body, bindings := Bindings}) ->
 request(post, #{body := Body, bindings := Bindings}) ->
     ClientId = maps:get(clientid, Bindings, undefined),
     ClientId = maps:get(clientid, Bindings, undefined),
-
-    Method = maps:get(<<"method">>, Body, <<"get">>),
-    CT = maps:get(<<"content_type">>, Body, <<"text/plain">>),
+    Method = maps:get(<<"method">>, Body, get),
+    AtomCT = maps:get(<<"content_type">>, Body),
     Token = maps:get(<<"token">>, Body, <<>>),
     Token = maps:get(<<"token">>, Body, <<>>),
     Payload = maps:get(<<"payload">>, Body, <<>>),
     Payload = maps:get(<<"payload">>, Body, <<>>),
-    BinWaitTime = maps:get(<<"timeout">>, Body, <<"10s">>),
-    {ok, WaitTime} = emqx_schema:to_duration_ms(BinWaitTime),
+    WaitTime = maps:get(<<"timeout">>, Body),
+    CT = erlang:atom_to_binary(AtomCT),
     Payload2 = parse_payload(CT, Payload),
     Payload2 = parse_payload(CT, Payload),
-    ReqType = erlang:binary_to_atom(Method),
 
 
     Msg = emqx_coap_message:request(con,
     Msg = emqx_coap_message:request(con,
-                                    ReqType, Payload2, #{content_format => CT}),
+                                    Method, Payload2, #{content_format => CT}),
 
 
     Msg2 = Msg#coap_message{token = Token},
     Msg2 = Msg#coap_message{token = Token},
 
 
-    case call_client(ClientId, Msg2, timer:seconds(WaitTime)) of
+    case call_client(ClientId, Msg2, WaitTime) of
         timeout ->
         timeout ->
             {504, #{code => 'CLIENT_NOT_RESPONSE'}};
             {504, #{code => 'CLIENT_NOT_RESPONSE'}};
         not_found ->
         not_found ->
             {404, #{code => 'CLIENT_NOT_FOUND'}};
             {404, #{code => 'CLIENT_NOT_FOUND'}};
         Response ->
         Response ->
             {200, format_to_response(CT, Response)}
             {200, format_to_response(CT, Response)}
-    end.
+           end.
 
 
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------
 %%  Internal functions
 %%  Internal functions
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------
 request_parameters() ->
 request_parameters() ->
-    [#{name => clientid,
-       in => path,
-       schema => #{type => string},
-       required => true}].
-
-request_properties() ->
-    properties([ {token, string, "message token, can be empty"}
-               , {method, string, "request method type", ["get", "put", "post", "delete"]}
-               , {timeout, string, "timespan for response"}
-               , {content_type, string, "payload type",
-                  [<<"text/plain">>, <<"application/json">>, <<"application/octet-stream">>]}
-               , {payload, string, "payload"}]).
-
-coap_message_properties() ->
-    properties([ {id, integer, "message id"}
-               , {token, string, "message token, can be empty"}
-               , {method, string, "response code"}
-               , {payload, string, "payload"}]).
-
-request_method_meta() ->
-    #{description => <<"lookup matching messages">>,
-      parameters => request_parameters(),
-      'requestBody' =>  object_schema(request_properties(),
-                                      <<"request payload, binary must encode by base64">>),
-      responses => #{
-                     <<"200">> => object_schema(coap_message_properties()),
-                     <<"404">> => error_schema("client not found error", ['CLIENT_NOT_FOUND']),
-                     <<"504">> => error_schema("timeout", ['CLIENT_NOT_RESPONSE'])
-                    }}.
-
+    [{clientid, mk(binary(), #{in => path, required => true})}].
+
+request_body() ->
+    [ {token, mk(binary(), #{desc => "message token, can be empty"})}
+    , {method, mk(enum([get, put, post, delete]), #{desc => "request method type"})}
+    , {timeout, mk(emqx_schema:duration_ms(), #{desc => "timespan for response"})}
+    , {content_type, mk(enum(['text/plain', 'application/json', 'application/octet-stream']),
+                        #{desc => "payload type"})}
+    , {payload, mk(binary(), #{desc => "the content of the payload"})}
+    ].
+
+coap_message() ->
+    [ {id, mk(integer(), #{desc => "message id"})}
+    , {token, mk(string(), #{desc => "message token, can be empty"})}
+    , {method, mk(string(), #{desc => "response code"})}
+    , {payload, mk(string(), #{desc => "payload"})}
+    ].
 
 
 format_to_response(ContentType, #coap_message{id = Id,
 format_to_response(ContentType, #coap_message{id = Id,
                                               token = Token,
                                               token = Token,
@@ -131,15 +127,23 @@ parse_payload(_, Body) ->
     Body.
     Body.
 
 
 call_client(ClientId, Msg, Timeout) ->
 call_client(ClientId, Msg, Timeout) ->
-    case emqx_gateway_cm_registry:lookup_channels(coap, ClientId) of
-        [Channel | _] ->
-            RequestId = emqx_coap_channel:send_request(Channel, Msg),
-            case gen_server:wait_response(RequestId, Timeout) of
-             {reply, Reply} ->
-                 Reply;
-             _ ->
-                 timeout
-            end;
-        _ ->
+    try
+        case emqx_gateway_cm_registry:lookup_channels(coap, ClientId) of
+            [Channel | _] ->
+                RequestId = emqx_coap_channel:send_request(Channel, Msg),
+                case gen_server:wait_response(RequestId, Timeout) of
+                    {reply, Reply} ->
+                        Reply;
+                    _ ->
+                        timeout
+                end;
+            _ ->
+                not_found
+        end
+    catch _:Error:Trace ->
+            ?SLOG(warning, #{msg => "coap_client_call_exception",
+                             clientid => ClientId,
+                             error => Error,
+                             stacktrace => Trace}),
             not_found
             not_found
     end.
     end.