chore(swagger): lwm2m2 http api to hocon (#6153)
This commit is contained in:
parent
9cf8dfcb55
commit
01f29ab052
|
@ -17,101 +17,112 @@
|
||||||
-module(emqx_lwm2m_api).
|
-module(emqx_lwm2m_api).
|
||||||
|
|
||||||
-behaviour(minirest_api).
|
-behaviour(minirest_api).
|
||||||
|
-include_lib("typerefl/include/types.hrl").
|
||||||
|
|
||||||
-export([api_spec/0]).
|
-export([api_spec/0, paths/0, schema/1, fields/1, namespace/0]).
|
||||||
|
|
||||||
-export([lookup_cmd/2, observe/2, read/2, write/2]).
|
-export([lookup_cmd/2, observe/2, read/2, write/2]).
|
||||||
|
|
||||||
-define(PREFIX, "/gateway/lwm2m/:clientid").
|
-define(PATH(Suffix), "/gateway/lwm2m/:clientid"Suffix).
|
||||||
|
-define(DATA_TYPE, ['Integer', 'Float', 'Time', 'String', 'Boolean', 'Opaque', 'Objlnk']).
|
||||||
|
|
||||||
-import(emqx_mgmt_util, [ object_schema/1
|
-import(hoconsc, [mk/2, ref/1, ref/2]).
|
||||||
, error_schema/2
|
-import(emqx_dashboard_swagger, [error_codes/2]).
|
||||||
, properties/1
|
|
||||||
, schema/1
|
namespace() -> "lwm2m".
|
||||||
]).
|
|
||||||
|
|
||||||
api_spec() ->
|
api_spec() ->
|
||||||
{[ lookup_cmd_api(), observe_api(), read_api()
|
emqx_dashboard_swagger:spec(?MODULE).
|
||||||
, write_api()
|
|
||||||
], []}.
|
|
||||||
|
|
||||||
base_paramters() ->
|
paths() ->
|
||||||
[ make_paramter(clientid, path, true, "string")
|
[?PATH("/lookup_cmd"), ?PATH("/observe"), ?PATH("/read"), ?PATH("/write")].
|
||||||
, make_paramter(path, query, true, "string")
|
|
||||||
].
|
|
||||||
|
|
||||||
lookup_cmd_paramters() ->
|
schema(?PATH("/lookup_cmd")) ->
|
||||||
base_paramters() ++ [make_paramter(action, query, true, "string")].
|
#{
|
||||||
|
'operationId' => lookup_cmd,
|
||||||
lookup_cmd_properties() ->
|
get => #{
|
||||||
properties([ {clientid, string}
|
tags => [<<"lwm2m">>],
|
||||||
, {path, string}
|
description => <<"Look up resource">>,
|
||||||
, {action, string}
|
parameters => [
|
||||||
, {code, string}
|
{clientid, mk(binary(), #{in => path, example => "urn:oma:lwm2m:oma:2"})},
|
||||||
, {codeMsg, string}
|
{path, mk(binary(), #{in => query, required => true, example => "/3/0/7"})},
|
||||||
, {content, {array, object}, lookup_cmd_content_props()}]).
|
{action, mk(binary(), #{in => query, required => true, example => "discover"})}
|
||||||
|
|
||||||
lookup_cmd_content_props() ->
|
|
||||||
[ {operations, string, <<"Resource Operations">>}
|
|
||||||
, {dataType, string, <<"Resource Type">>}
|
|
||||||
, {path, string, <<"Resource Path">>}
|
|
||||||
, {name, string, <<"Resource Name">>}].
|
|
||||||
|
|
||||||
lookup_cmd_api() ->
|
|
||||||
Metadata = #{get =>
|
|
||||||
#{description => <<"look up resource">>,
|
|
||||||
parameters => lookup_cmd_paramters(),
|
|
||||||
responses =>
|
|
||||||
#{<<"200">> => object_schema(lookup_cmd_properties()),
|
|
||||||
<<"404">> => error_schema("client not found error", ['CLIENT_NOT_FOUND'])
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{?PREFIX ++ "/lookup_cmd", Metadata, lookup_cmd}.
|
|
||||||
|
|
||||||
|
|
||||||
observe_api() ->
|
|
||||||
Metadata = #{post =>
|
|
||||||
#{description => <<"(cancel)observe resource">>,
|
|
||||||
parameters => base_paramters() ++
|
|
||||||
[make_paramter(enable, query, true, "boolean")],
|
|
||||||
responses =>
|
|
||||||
#{<<"200">> => schema(<<"Successed">>),
|
|
||||||
<<"404">> => error_schema("client not found error", ['CLIENT_NOT_FOUND'])
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{?PREFIX ++ "/observe", Metadata, observe}.
|
|
||||||
|
|
||||||
read_api() ->
|
|
||||||
Metadata = #{post =>
|
|
||||||
#{description => <<"read resource">>,
|
|
||||||
parameters => base_paramters(),
|
|
||||||
responses =>
|
|
||||||
#{<<"200">> => schema(<<"Successed">>),
|
|
||||||
<<"404">> => error_schema("client not found error", ['CLIENT_NOT_FOUND'])
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{?PREFIX ++ "/read", Metadata, read}.
|
|
||||||
|
|
||||||
write_api() ->
|
|
||||||
Metadata = #{post =>
|
|
||||||
#{description => <<"write to resource">>,
|
|
||||||
parameters => base_paramters() ++
|
|
||||||
[ make_paramter(type, query, true, "string",
|
|
||||||
[<<"Integer">>,
|
|
||||||
<<"Float">>,
|
|
||||||
<<"Time">>,
|
|
||||||
<<"String">>,
|
|
||||||
<<"Boolean">>,
|
|
||||||
<<"Opaque">>,
|
|
||||||
<<"Objlnk">>])
|
|
||||||
, make_paramter(value, query, true, "string")
|
|
||||||
],
|
],
|
||||||
responses =>
|
'requestBody' => [],
|
||||||
#{<<"200">> => schema(<<"Successed">>),
|
responses => #{
|
||||||
<<"404">> => error_schema("client not found error", ['CLIENT_NOT_FOUND'])
|
200 => [
|
||||||
|
{clientid, mk(binary(), #{example => "urn:oma:lwm2m:oma:2"})},
|
||||||
|
{path, mk(binary(), #{example => "/3/0/7"})},
|
||||||
|
{action, mk(binary(), #{example => "discover"})},
|
||||||
|
{'codeMsg', mk(binary(), #{example => "reply_not_received"})},
|
||||||
|
{content, mk(hoconsc:array(ref(resource)), #{})}
|
||||||
|
],
|
||||||
|
404 => error_codes(['CLIENT_NOT_FOUND'], <<"Client not found">>)
|
||||||
}
|
}
|
||||||
}},
|
}
|
||||||
{?PREFIX ++ "/write", Metadata, write}.
|
};
|
||||||
|
schema(?PATH("/observe")) ->
|
||||||
|
#{
|
||||||
|
'operationId' => observe,
|
||||||
|
post => #{
|
||||||
|
tags => [<<"lwm2m">>],
|
||||||
|
description => <<"(cancel) observe resource">>,
|
||||||
|
parameters => [
|
||||||
|
{clientid, mk(binary(), #{in => path, example => "urn:oma:lwm2m:oma:2"})},
|
||||||
|
{path, mk(binary(), #{in => query, required => true, example => "/3/0/7"})},
|
||||||
|
{enable, mk(boolean(), #{in => query, required => true, example => true})}
|
||||||
|
],
|
||||||
|
'requestBody' => [],
|
||||||
|
responses => #{
|
||||||
|
200 => <<"No Content">>,
|
||||||
|
404 => error_codes(['CLIENT_NOT_FOUND'], <<"Clientid not found">>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
schema(?PATH("/read")) ->
|
||||||
|
#{
|
||||||
|
'operationId' => read,
|
||||||
|
post => #{
|
||||||
|
tags => [<<"lwm2m">>],
|
||||||
|
description => <<"Send a read command to resource">>,
|
||||||
|
parameters => [
|
||||||
|
{clientid, mk(binary(), #{in => path, example => "urn:oma:lwm2m:oma:2"})},
|
||||||
|
{path, mk(binary(), #{in => query, required => true, example => "/3/0/7"})}
|
||||||
|
],
|
||||||
|
responses => #{
|
||||||
|
200 => <<"No Content">>,
|
||||||
|
404 => error_codes(['CLIENT_NOT_FOUND'], <<"clientid not found">>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
schema(?PATH("/write")) ->
|
||||||
|
#{
|
||||||
|
'operationId' => write,
|
||||||
|
post => #{
|
||||||
|
description => <<"Send a write command to resource">>,
|
||||||
|
tags => [<<"lwm2m">>],
|
||||||
|
parameters => [
|
||||||
|
{clientid, mk(binary(), #{in => path, example => "urn:oma:lwm2m:oma:2"})},
|
||||||
|
{path, mk(binary(), #{in => query, required => true, example => "/3/0/7"})},
|
||||||
|
{type, mk(hoconsc:enum(?DATA_TYPE),
|
||||||
|
#{in => query, required => true, example => 'Integer'})},
|
||||||
|
{value, mk(binary(), #{in => query, required => true, example => 123})}
|
||||||
|
],
|
||||||
|
responses => #{
|
||||||
|
200 => <<"No Content">>,
|
||||||
|
404 => error_codes(['CLIENT_NOT_FOUND'], <<"Clientid not found">>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.
|
||||||
|
|
||||||
|
fields(resource) ->
|
||||||
|
[
|
||||||
|
{operations, mk(binary(), #{desc => <<"Resource Operations">>, example => "E"})},
|
||||||
|
{'dataType', mk(hoconsc:enum(?DATA_TYPE), #{desc => <<"Data Type">>,
|
||||||
|
example => 'Integer'})},
|
||||||
|
{path, mk(binary(), #{desc => <<"Resource Path">>, example => "urn:oma:lwm2m:oma:2"})},
|
||||||
|
{name, mk(binary(), #{desc => <<"Resource Name">>, example => "lwm2m-test"})}
|
||||||
|
].
|
||||||
|
|
||||||
lookup_cmd(get, #{bindings := Bindings, query_string := QS}) ->
|
lookup_cmd(get, #{bindings := Bindings, query_string := QS}) ->
|
||||||
ClientId = maps:get(clientid, Bindings),
|
ClientId = maps:get(clientid, Bindings),
|
||||||
|
@ -150,7 +161,8 @@ format_cmd_content(Content, <<"discover">>, Result) ->
|
||||||
[H | Content1] = Content,
|
[H | Content1] = Content,
|
||||||
{_, [HObjId]} = emqx_lwm2m_session:parse_object_list(H),
|
{_, [HObjId]} = emqx_lwm2m_session:parse_object_list(H),
|
||||||
[ObjId | _]= path_list(HObjId),
|
[ObjId | _]= path_list(HObjId),
|
||||||
ObjectList = case Content1 of
|
ObjectList =
|
||||||
|
case Content1 of
|
||||||
[Content2 | _] ->
|
[Content2 | _] ->
|
||||||
{_, ObjL} = emqx_lwm2m_session:parse_object_list(Content2),
|
{_, ObjL} = emqx_lwm2m_session:parse_object_list(Content2),
|
||||||
ObjL;
|
ObjL;
|
||||||
|
@ -161,26 +173,28 @@ format_cmd_content(Content, <<"discover">>, Result) ->
|
||||||
{error, _} ->
|
{error, _} ->
|
||||||
lists:map(fun(Object) -> #{Object => Object} end, ObjectList);
|
lists:map(fun(Object) -> #{Object => Object} end, ObjectList);
|
||||||
ObjDefinition ->
|
ObjDefinition ->
|
||||||
lists:map(
|
lists:map(fun(Obj) -> to_operations(Obj, ObjDefinition) end, ObjectList)
|
||||||
fun(Object) ->
|
|
||||||
[_, _, RawResId| _] = path_list(Object),
|
|
||||||
ResId = binary_to_integer(RawResId),
|
|
||||||
Operations = case emqx_lwm2m_xml_object:get_resource_operations(ResId, ObjDefinition) of
|
|
||||||
"E" ->
|
|
||||||
#{operations => list_to_binary("E")};
|
|
||||||
Oper ->
|
|
||||||
#{'dataType' => list_to_binary(emqx_lwm2m_xml_object:get_resource_type(ResId, ObjDefinition)),
|
|
||||||
operations => list_to_binary(Oper)}
|
|
||||||
end,
|
|
||||||
Operations#{path => Object,
|
|
||||||
name => list_to_binary(emqx_lwm2m_xml_object:get_resource_name(ResId, ObjDefinition))}
|
|
||||||
end, ObjectList)
|
|
||||||
end,
|
end,
|
||||||
Result#{content => R};
|
Result#{content => R};
|
||||||
|
|
||||||
format_cmd_content(Content, _, Result) ->
|
format_cmd_content(Content, _, Result) ->
|
||||||
Result#{content => Content}.
|
Result#{content => Content}.
|
||||||
|
|
||||||
|
to_operations(Obj, ObjDefinition) ->
|
||||||
|
[_, _, RawResId| _] = path_list(Obj),
|
||||||
|
ResId = binary_to_integer(RawResId),
|
||||||
|
Operations =
|
||||||
|
case emqx_lwm2m_xml_object:get_resource_operations(ResId, ObjDefinition) of
|
||||||
|
"E" -> #{operations => <<"E">>};
|
||||||
|
Oper ->
|
||||||
|
#{'dataType' =>
|
||||||
|
list_to_binary(emqx_lwm2m_xml_object:get_resource_type(ResId, ObjDefinition)),
|
||||||
|
operations => list_to_binary(Oper)
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
Operations#{path => Obj,
|
||||||
|
name => list_to_binary(emqx_lwm2m_xml_object:get_resource_name(ResId, ObjDefinition))}.
|
||||||
|
|
||||||
path_list(Path) ->
|
path_list(Path) ->
|
||||||
case binary:split(binary_util:trim(Path, $/), [<<$/>>], [global]) of
|
case binary:split(binary_util:trim(Path, $/), [<<$/>>], [global]) of
|
||||||
[ObjId, ObjInsId, ResId, ResInstId] -> [ObjId, ObjInsId, ResId, ResInstId];
|
[ObjId, ObjInsId, ResId, ResInstId] -> [ObjId, ObjInsId, ResId, ResInstId];
|
||||||
|
@ -189,19 +203,6 @@ path_list(Path) ->
|
||||||
[ObjId] -> [ObjId]
|
[ObjId] -> [ObjId]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
make_paramter(Name, In, IsRequired, Type) ->
|
|
||||||
#{name => Name,
|
|
||||||
in => In,
|
|
||||||
required => IsRequired,
|
|
||||||
schema => #{type => Type}}.
|
|
||||||
|
|
||||||
make_paramter(Name, In, IsRequired, Type, Enum) ->
|
|
||||||
#{name => Name,
|
|
||||||
in => In,
|
|
||||||
required => IsRequired,
|
|
||||||
schema => #{type => Type,
|
|
||||||
enum => Enum}}.
|
|
||||||
|
|
||||||
observe(post, #{bindings := #{clientid := ClientId},
|
observe(post, #{bindings := #{clientid := ClientId},
|
||||||
query_string := #{<<"path">> := Path, <<"enable">> := Enable}}) ->
|
query_string := #{<<"path">> := Path, <<"enable">> := Enable}}) ->
|
||||||
MsgType = case Enable of
|
MsgType = case Enable of
|
||||||
|
|
Loading…
Reference in New Issue