feat: dlink

This commit is contained in:
dawnwinterLiu 2024-07-11 14:42:25 +08:00
parent 600cb4bac5
commit f249e78806
11 changed files with 217 additions and 33 deletions

1
apps/dgiot_atomgit Submodule

@ -0,0 +1 @@
Subproject commit 6b224f6f77eab84e2dc7d0d912780b6d132f4f0b

View File

@ -240,6 +240,7 @@ handle_message({sync_parse, _Pid, 'after', put, _Token, <<"Product">>, QueryData
ProductId = maps:get(<<"objectId">>, QueryData),
dgiot_product_channel:do_td_message(ProductId),
dgiot_product_knova:save_Product_konva(ProductId),
dgiot_product:hook_topic(QueryData),
{ok, State};
handle_message({sync_parse, _Pid, 'after', delete, _Token, <<"Product">>, ObjectId}, State) ->

View File

@ -25,7 +25,7 @@
-export([get_prop/1, get_props/1, get_props/2, get_unit/1, update_properties/2, update_properties/0]).
-export([update_topics/0, update_product_filed/1]).
-export([save_devicetype/1, get_devicetype/1, get_device_thing/2, get_productSecret/1]).
-export([save_/1, get_keys/1, get_control/1, save_control/1, get_interval/1, save_device_thingtype/1, get_product_identifier/2]).
-export([save_/1, get_keys/1, get_control/1, save_control/1, get_interval/1, save_device_thingtype/1, get_product_identifier/2, hook_topic/1]).
init_ets() ->
dgiot_data:init(?DGIOT_PRODUCT, [public, named_table, set, {write_concurrency, true}, {read_concurrency, true}]),
@ -81,6 +81,7 @@ save(Product) ->
dgiot_product_channel:save_channel(ProductId),
dgiot_product_channel:save_tdchannel(ProductId),
dgiot_product_channel:save_taskchannel(ProductId),
hook_topic(Product),
%% dgiot_product_enum:save_product_enum(ProductId),
{ok, Product1}.
@ -537,3 +538,14 @@ get_props(ProductId, Keys) ->
Acc
end
end, [], List).
hook_topic(#{<<"objectId">> := ProductId, <<"topics">> := Topics}) ->
maps:fold(
fun(K, Topic, _) ->
dgiot_data:insert({ProductId, Topic}, K),
dgiot_hook:add(one_for_one, {ProductId, Topic}, fun dgiot_mqtt_message:redirect_topic/1)
end, {}, Topics);
hook_topic(_) ->
pass.

View File

@ -677,6 +677,47 @@
"id": "milliliter",
"type": "capacity"
},
{
"symbol": "L",
"typeText": "其他",
"name": "升",
"description": "容积单位:升(L)",
"id": "litre",
"type": "capacity"
},
{
"symbol": "Lux",
"typeText": "其他",
"name": "光照强度",
"description": "光照单位:光照强度(Lux)",
"id": "lightintensity",
"type": "capacity"
},
{
"symbol": "%RH",
"typeText": "其他",
"name": "相对湿度",
"description": "湿度单位:相对湿度(%RH)",
"id": "relativehumidity",
"type": "capacity"
},
{
"symbol": "μmol/㎡·s",
"typeText": "其他",
"name": "光合辐射",
"description": "光合辐射:微爱因/(米²秒)(μmol/㎡·s)",
"id": "microeine",
"type": "capacity"
},
{
"symbol": "mm/h",
"typeText": "其他",
"name": "降雨强度",
"description": "降雨强度(mm/h)",
"id": "rainfallintensity",
"type": "capacity"
},
{
"symbol": "L",
"typeText": "其他",

View File

@ -56,10 +56,6 @@
"Symbol": "只",
"Name": "只"
},
{
"Symbol": "%RH",
"Name": "相对湿度"
},
{
"Symbol": "m³/s",
"Name": "立方米每秒"
@ -136,10 +132,6 @@
"Symbol": "pixel",
"Name": "像素"
},
{
"Symbol": "Lux",
"Name": "照度"
},
{
"Symbol": "grav",
"Name": "重力加速度"
@ -368,6 +360,22 @@
"Symbol": "Pa",
"Name": "帕斯卡"
},
{
"Symbol": "Lux",
"Name": "光照强度"
},
{
"Symbol": "%RH",
"Name": "相对湿度"
},
{
"Symbol": "μmol/㎡·s",
"Name": "微爱因/(米²秒)"
},
{
"Symbol": "mm/h",
"Name": "降雨强度"
},
{
"Symbol": "mg",
"Name": "毫克"

View File

@ -289,6 +289,43 @@
"Dlink"
]
}
},
"/third_party_push": {
"post": {
"security": [],
"summary": "third_party_push",
"description": "第三方推送",
"parameters": [
{
"in": "body",
"name": "data",
"required": true,
"schema": {
"type": "object"
}
}
],
"responses": {
"201": {
"description": "Returns operation status"
},
"400": {
"description": "Bad Request"
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"500": {
"description": "Server Internal error"
}
},
"tags": [
"Dlink"
]
}
}
}
}

View File

@ -129,13 +129,13 @@ do_request(get_protocol, Body, _Context, _Req) ->
#{<<"type">> := undefined} ->
{200, Protocols};
#{<<"type">> := Type1} ->
Amis = lists:foldl(
Amis = lists:foldl(
fun
(#{cType := Type, mod := Mod} = _X, _Acc) when Type1 == Type ->
io:format("Type ~p Mod ~p ~n",[Type, Mod]),
dgiot_utils:get_JsonFile(Mod, <<Type/binary, ".json">>);
io:format("Type ~p Mod ~p ~n", [Type, Mod]),
dgiot_utils:get_JsonFile(Mod, <<Type/binary, ".json">>);
(#{cType := Type} = _X, Acc) ->
io:format("Type ~p ~n",[Type]),
io:format("Type ~p ~n", [Type]),
Acc
end, <<"{}">>, Protocols),
{200, Amis};
@ -215,5 +215,16 @@ do_request(post_cookie, #{<<"UserSession">> := UserSession, <<"cookie">> := Cook
{500, #{<<"result">> => <<"save_cookie_failed">>}}
end;
%% api
%% wget -qoP /data/dgiot/go_fastdfs/files/dgiot_file/device/861551058865106 https://bigdata-image.oss-cn-hangzhou.aliyuncs.com/Basics/cbd/861551058865106/2023/8/29/861551058865106-20230829234037.jpg
do_request(post_third_party_push, #{<<"imei">> := Imei} = Args, _Context, _Req) ->
Image = maps:get(<<"Image">>, Args, <<>>),
Result_image = maps:get(<<"Result_image">>, Args, Image),
os:cmd(<<"wget -qoP /data/dgiot/go_fastdfs/files/dgiot_file/device/", Imei/binary, " ", Image/binary>>),
os:cmd(<<"wget -qoP /data/dgiot/go_fastdfs/files/dgiot_file/device/", Imei/binary, " ", Result_image/binary>>),
io:format("~s ~p Args = ~p.~n", [?FILE, ?LINE, Args]),
{ok, #{<<"status">> => 0, <<"msg">> => <<"success">>}};
do_request(_OperationId, _Args, _Context, _Req) ->
{error, <<"Not Allowed.">>}.

View File

@ -25,6 +25,7 @@
properties_report/3
, firmware_report/3
, parse_payload/2
, nested_map/2
]).
-define(TYPE, <<"DLINK">>).
@ -90,7 +91,7 @@
%% json格式报文
properties_report(ProductId, DevAddr, Payload) when is_map(Payload) ->
%% io:format("~s ~p ProductId ~p, DevAddr ~p, Payload: ~p ~n", [?FILE, ?LINE, ProductId, DevAddr, Payload]),
%% io:format("~s ~p ProductId ~p, DevAddr ~p, Payload = ~p.~n", [?FILE, ?LINE, ProductId, DevAddr, Payload]),
OldPayload =
case dgiot_hook:run_hook({dlink_properties_report, ProductId}, {DevAddr, Payload}) of
{ok, [Payload1]} ->
@ -143,26 +144,74 @@ parse_payload(ProductId, Payload) ->
case X of
#{<<"identifier">> := Identifier,
<<"dataSource">> := DtaSource} ->
Dis =
lists:foldl(
fun
(#{<<"key">> := Key}, Acc1) ->
Acc1 ++ [Key];
(_, Acc1) ->
Acc1
end, [], maps:get(<<"dis">>, DtaSource, [])),
maps:fold(fun(PK, PV, Acc1) ->
case lists:member(PK, Dis) of
true ->
Acc1#{Identifier => PV};
_ ->
Acc1#{PK => PV}
end
end, Acc, Payload);
lists:foldl(
fun
(#{<<"key">> := Key}, Acc1) ->
case dgiot_dlink_proctol:nested_map(Key, Payload) of
{ok, V} ->
Acc1#{Identifier => V};
_ ->
Acc1
end;
(_, Acc1) ->
Acc1
end, Acc, maps:get(<<"dis">>, DtaSource, []));
_ ->
Acc
end
end, #{}, Props);
end, Payload, Props);
_Error ->
Payload
end.
nested_map(Key, Map) ->
case maps:find(Key, Map) of
{ok, V} ->
{ok, V};
_ ->
nested_map(Key, maps:keys(Map), Map)
end.
nested_map(_, [], _) ->
undefined;
nested_map(Key, [H | T], Map) ->
case maps:get(H, Map) of
HMap when is_map(HMap) ->
case nested_map(Key, HMap) of
undefined ->
nested_map(Key, T, Map);
Value ->
Value
end;
HList when is_list(HList) ->
nested_list(Key, HList);
_ ->
nested_map(Key, T, Map)
end.
nested_list(Key, List) ->
nested_list(Key, List, undefined).
nested_list(_, [], Value) ->
Value;
nested_list(Key, [H | T], Value) when is_map(H) ->
NewValue =
case Value of
undefined ->
nested_map(Key, H);
_ ->
Value
end,
nested_list(Key, T, NewValue);
nested_list(Key, [_ | T], Value) ->
nested_list(Key, T, Value).

View File

@ -23,7 +23,8 @@
%% ACL Callbacks
-export([
on_message_publish/2,
init_ets/0
init_ets/0,
redirect_topic/1
]).
-define(EMPTY_USERNAME, <<"">>).
@ -76,9 +77,32 @@ on_message_publish(Message = #message{topic = <<"$dg/thing/", Topic/binary>>, pa
end,
{ok, Message};
on_message_publish(Message = #message{from = DeviceAddr, headers = #{username := ProductId}, topic = Topic}, State) ->
Topic1 = re:replace(Topic, DeviceAddr, <<"${deviceAddr}">>, [global, {return, binary}]),
NewTopic = re:replace(Topic1, ProductId, <<"${productId}">>, [global, {return, binary}]),
dgiot_hook:run_hook({ProductId, NewTopic}, {NewTopic, Message, State}),
{ok, Message};
on_message_publish(Message = #message{topic = _Topic, payload = _Payload}, _State) ->
{ok, Message}.
%% topic
redirect_topic({HookTopic, Message = #message{from = DeviceAddr, headers = #{username := ProductId}}, State}) ->
case dgiot_data:get({ProductId, HookTopic}) of
not_find ->
pass;
Type ->
Topic = get_topic(Type, ProductId, DeviceAddr),
on_message_publish(Message#message{topic = Topic}, State)
end.
get_topic(<<"device_property_report">>, ProductId, DeviceAddr) ->
<<"$dg/thing/", ProductId/binary, "/", DeviceAddr/binary, "/properties/report">>;
get_topic(_, ProductId, DeviceAddr) ->
<<"$dg/thing/", ProductId/binary, "/", DeviceAddr/binary, "/properties/report">>.
get_payload(Payload) ->
%% io:format("~s ~p Payload: ~p~n", [?FILE, ?LINE, Payload]),
case jsx:is_json(Payload) of

View File

@ -42,6 +42,7 @@ init(#tcp{state = #state{id = ChannelId}} = TCPState) ->
%%40400000010214200E0C07160000000000006400000000000A000218010101220D0E0C07165F2323
handle_info({tcp, Buff}, #tcp{state = #state{id = ChannelId} = State} = TCPState) ->
dgiot_bridge:send_log(ChannelId, "revice from ~p", [dgiot_utils:binary_to_hex(Buff)]),
io:format("~s ~p Data = ~p.~n", [?FILE, ?LINE, dgiot_utils:binary_to_hex(Buff)]),
case dgiot_gb26875_decoder:parse_frame(Buff, State) of
{ok, #{<<"ack">> := Ack}} ->
dgiot_tcp_server:send(TCPState, Ack),

@ -1 +0,0 @@
Subproject commit 60df64205d30744bb4be81b9a1a3a7883de7553b