From 95852084b65e38a8a859e02457862151534e66f5 Mon Sep 17 00:00:00 2001 From: dawnwinterLiu <1737801684@qq.com> Date: Mon, 19 Feb 2024 17:14:10 +0800 Subject: [PATCH] feat: upgrade plugin --- .../priv/swagger/swagger_system.json | 43 ++++++++++++++++ .../src/handler/dgiot_system_handler.erl | 10 ++++ apps/dgiot_hjt212/.gitignore | 12 +++++ .../dgiot_hjt212/src/dgiot_hjt212_channel.erl | 50 ++++++++++++------- apps/dgiot_hjt212/src/dgiot_hjt212_tcp.erl | 25 ++++------ .../src/protocol/dgiot_hjt212_decoder.erl | 14 +++++- 6 files changed, 118 insertions(+), 36 deletions(-) create mode 100644 apps/dgiot_hjt212/.gitignore diff --git a/apps/dgiot_api/priv/swagger/swagger_system.json b/apps/dgiot_api/priv/swagger/swagger_system.json index 281030b3..c51078d4 100644 --- a/apps/dgiot_api/priv/swagger/swagger_system.json +++ b/apps/dgiot_api/priv/swagger/swagger_system.json @@ -614,6 +614,49 @@ "System" ] } + }, + "/upgrade_plugin": { + "post": { + "summary": "插件升级", + "description": "插件升级", + "consumes": [ + "multipart/form-data" + ], + "parameters": [ + { + "name": "type", + "in": "formData", + "description": "类型", + "type": "string" + }, + { + "name": "file", + "in": "formData", + "description": "数据文件", + "type": "file" + } + ], + "responses": { + "200": { + "description": "Returns operation status" + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + }, + "500": { + "description": "Server Internal error" + } + }, + "tags": [ + "Data" + ] + } } } } diff --git a/apps/dgiot_api/src/handler/dgiot_system_handler.erl b/apps/dgiot_api/src/handler/dgiot_system_handler.erl index 9658fe9f..6839fc02 100644 --- a/apps/dgiot_api/src/handler/dgiot_system_handler.erl +++ b/apps/dgiot_api/src/handler/dgiot_system_handler.erl @@ -182,6 +182,16 @@ do_request(post_plugin_app, #{<<"Action">> := Action, <<"App">> := App}, _Contex {200, #{<<"error">> => <<"license error">>}} end; +%% iot_hub 概要: 升级插件dgiot_system_handler +%% OperationId:post_station_data +%% 请求:POST /iotapi/post_station_data +do_request(post_upgrade_plugin, #{<<"file">> := #{<<"filename">> := Filename, <<"fullpath">> := Fullpath}}, _Context, _Req) -> + Len = size(Filename) - 5, + <> = Filename, + {file, Here} = code:is_loaded(dgiot_utils:to_atom(Mod)), + os:cmd("cp -R " ++ dgiot_utils:to_list(Fullpath) ++ " " ++ Here), + {200, #{<<"status">> => 0, <<"msg">> => <<"success">>, <<"data">> => #{}}}; + %% System 概要: 编译代码 描述:在线编译代码 %% OperationId:post_compile diff --git a/apps/dgiot_hjt212/.gitignore b/apps/dgiot_hjt212/.gitignore new file mode 100644 index 00000000..0d51a6ba --- /dev/null +++ b/apps/dgiot_hjt212/.gitignore @@ -0,0 +1,12 @@ +# ---> Erlang +.eunit +deps +*.o +*.beam +*.plt +erl_crash.dump +ebin +rel/example_project +.concrete/DEV_MODE +.rebar + diff --git a/apps/dgiot_hjt212/src/dgiot_hjt212_channel.erl b/apps/dgiot_hjt212/src/dgiot_hjt212_channel.erl index b8932a7f..5f982c20 100644 --- a/apps/dgiot_hjt212/src/dgiot_hjt212_channel.erl +++ b/apps/dgiot_hjt212/src/dgiot_hjt212_channel.erl @@ -19,7 +19,7 @@ -include_lib("dgiot_bridge/include/dgiot_bridge.hrl"). -include("dgiot_hjt212.hrl"). -include_lib("dgiot/include/logger.hrl"). --define(TYPE, <<"hjt212">>). +-define(TYPE, <<"HJT212">>). -dgiot_data("ets"). -export([init_ets/0]). @@ -91,19 +91,25 @@ start(ChannelId, ChannelArgs) -> %% 通道初始化 init(?TYPE, ChannelId, #{ <<"port">> := Port, - <<"devtype">> := DevType + <<"devtype">> := DevType, + <<"product">> := Products } = _Args) -> + {ProdcutId, App} = + case get_app(Products) of + [{ProdcutId1, App1} | _] -> + {ProdcutId1, App1}; + [] -> + {<<>>, <<>>}; + _ -> + {<<>>, <<>>} + end, State = #state{ id = ChannelId, + app = App, + product = ProdcutId, devtype = DevType }, - case dgiot_parse:get_object(<<"Channel">>, ChannelId) of - {ok, Channel} -> - App = get_app(Channel), - {ok, State, dgiot_hjt212_tcp:start(Port, State#state{app = App})}; - _ -> - {ok, State, []} - end; + {ok, State, dgiot_hjt212_tcp:start(Port, State)}; init(?TYPE, _ChannelId, _Args) -> {ok, #{}, #{}}. @@ -137,14 +143,22 @@ handle_message(_Message, State) -> stop(_ChannelType, _ChannelId, _State) -> ok. -get_app(#{<<"ACL">> := Acl}) -> - Predicate = fun(E) -> - case E of - <<"role:", _/binary>> -> true; - _ -> false - end - end, - [<<"role:", App/binary>> | _] = lists:filter(Predicate, maps:keys(Acl)), - App. +get_app(Products) -> + lists:map(fun({ProdcutId, #{<<"ACL">> := Acl}}) -> + Predicate = fun(E) -> + case E of + <<"role:", _/binary>> -> true; + _ -> false + end + end, + App = + case lists:filter(Predicate, maps:keys(Acl)) of + [<<"role:", Name/binary>> | _] -> + Name; + _ -> + <<"dgiot">> + end, + {ProdcutId, App} + end, Products). diff --git a/apps/dgiot_hjt212/src/dgiot_hjt212_tcp.erl b/apps/dgiot_hjt212/src/dgiot_hjt212_tcp.erl index 25547e19..2373b47b 100644 --- a/apps/dgiot_hjt212/src/dgiot_hjt212_tcp.erl +++ b/apps/dgiot_hjt212/src/dgiot_hjt212_tcp.erl @@ -39,22 +39,15 @@ init(#tcp{state = #state{id = ChannelId}} = TCPState) -> {stop, not_find_channel} end. -handle_info({tcp, Buff}, #tcp{state = #state{id = ChannelId} = State} = TCPState) -> - dgiot_bridge:send_log(ChannelId, "revice from ~p", [Buff]), - case dgiot_hjt212_decoder:parse_frame(Buff, State) of - {ok, [Frame | _]} -> - io:format("~s ~p ~p ~n",[?FILE, ?LINE, Frame]); -%% dgiot_bridge:send_log(ChannelId, "~s ~p ~ts", [?FILE, ?LINE, unicode:characters_to_list(jiffy:encode(Result))]), -%% R = dgiot_hjt212_decoder:to_frame(Frame), -%% case R of -%% Buff -> -%% io:format("success to_frame Buff ~p~n", [Buff]), -%% dgiot_bridge:send_log(ChannelId, "success to_frame Buff ~p", [Buff]); -%% _ -> -%% io:format("error to_frame R ~p~n", [R]), -%% dgiot_bridge:send_log(ChannelId, "error to_frame Buff ~p", [R]) -%% end; - _ -> +handle_info({tcp, Buff}, #tcp{state = #state{id = ChannelId, product = ProductId} = _State} = TCPState) -> + dgiot_bridge:send_log(ChannelId, ProductId, "~s ~p ~p revice from ~p => ProductId ~p ", [?FILE, ?LINE, dgiot_datetime:format("YYYY-MM-DD HH:NN:SS"), Buff, ProductId]), + case dgiot_hjt212_decoder:parse_frame(Buff, []) of + {ok, [#{<<"devaddr">> := Devaddr} = Data | _]} -> + NewData = dgiot_dlink_proctol:parse_payload(ProductId, Data), + dgiot_bridge:send_log(ChannelId, ProductId, Devaddr, "~s ~p ~p revice from ~p~n save td => ProductId ~p DevAddr ~p ~ts ", [?FILE, ?LINE, dgiot_datetime:format("YYYY-MM-DD HH:NN:SS"), Buff, ProductId, Devaddr, unicode:characters_to_list(dgiot_json:encode(NewData))]), + dgiot_task:save_td(ProductId, Devaddr, NewData, #{}); + _O -> + dgiot_bridge:send_log(ChannelId, ProductId, "~s ~p ~p revice from => ~p ", [?FILE, ?LINE, dgiot_datetime:format("YYYY-MM-DD HH:NN:SS"), _O]), pass end, {noreply, TCPState}; diff --git a/apps/dgiot_hjt212/src/protocol/dgiot_hjt212_decoder.erl b/apps/dgiot_hjt212/src/protocol/dgiot_hjt212_decoder.erl index 1344b6a0..e8e389b8 100644 --- a/apps/dgiot_hjt212/src/protocol/dgiot_hjt212_decoder.erl +++ b/apps/dgiot_hjt212/src/protocol/dgiot_hjt212_decoder.erl @@ -115,13 +115,23 @@ parse_frame(<<_:8, Data/binary>> = _Rest, Acc, Opts) -> %| 指令参数 CP | 字符 | 0≤n≤950| CP=&&数据区&&,数据区定义见 6.3.3 章节 | %|----------------------------------------------------------------------------------------------------------------------| %%parse_userzone(<<"QN=",QN:17/binary,";ST=", ST:2/binary, ";CN=", CN:4/binary, ";PW=", PWD:6/binary, ";MN=", MN:24/binary, ";Flag=", Flag:2/binary, PNUM:9/binary, PNO:8/binary, ";CP=", CP/binary>>, _State) -> +%% ##0331QN=20240204193300000;ST=31;CN=2011;PW=123456;MN=60436377;Flag=4;CP=&&DataTime=20240204193300;a34004-Rtd=10,a34004-Flag=N;a34002-Rtd=12,a34002-Flag=N;a34001-Rtd=26,a34001-Flag=N;a01001-Rtd=1.8,a01001-Flag=N;a01002-Rtd=91.0,a01002-Flag=N;a01007-Rtd=3.9,a01007-Flag=N;a01008-Rtd=314.00,a01008-Flag=N;a01006-Rtd=102.36,a01006-Flag=N;&&7F80\r\n parse_userzone(UserZone, _State) -> lists:foldl(fun(X, Acc) -> case X of + <<"MN=", Devaddr/binary>> -> + Acc#{<<"devaddr">> => Devaddr}; <<"CP=&&", CP/binary>> -> Acc#{<<"CP">> => dgiot_hjt212_utils:get_cps(CP)}; _ -> - case re:split(X, <<"=">>) of + NewX = + case re:split(X, <<",">>) of + [First, _] -> + First; + _ -> + X + end, + case re:split(NewX, <<"=">>) of [K, V] -> Acc#{K => V}; _ -> Acc @@ -131,7 +141,7 @@ parse_userzone(UserZone, _State) -> to_frame(#{<<"QN">> := QN, <<"ST">> := ST, <<"CN">> := CN, <<"PW">> := PW, <<"MN">> := MN, <<"Flag">> := Flag, <<"CP">> := CP, <<"PNUM">> := PNUM, <<"PNO">> := PNO}) -> Rdata = <<"QN=", QN/binary, ";ST=", ST/binary, ";CN=", CN/binary, ";PW=", PW/binary, ";MN=", MN/binary, - ";Flag=", Flag/binary, ";PNUM=",PNUM/binary,";PNO=", PNO/binary, ";CP=&&", CP/binary, "&&">>, + ";Flag=", Flag/binary, ";PNUM=", PNUM/binary, ";PNO=", PNO/binary, ";CP=&&", CP/binary, "&&">>, Len = dgiot_hjt212_utils:get_len(Rdata), Crc = dgiot_hjt212_utils:crc16(Rdata), <<"##", Len/binary, Rdata/binary, Crc/binary, "\r\n">>;