DGIOT插件机制

首页博客, 技术文章, 置顶推荐

插件机制

目录结构

dgiot插件开发
rebar3插件目录结构如下:


dgiot

|——lib

|-dgiot_demoplugin

|- ebin

|- dgiot_demopugin.app

- dgiot_demoplugin.beam

- dgiot_demoplugin_app.beam

- dgiot_demoplugin_sup.beam

- dgiot_demonplugin_channel.beam

- dgiot_demonplugin_handler.beam

-dgiot_otherplugin

|- ebin

|- dgiot_otherplugin.app

- dgiot_otherplugin.beam

- dgiot_otherplugin_app.beam

- dgiot_otherplugin_sup.beam

- dgiot_otherplugin_channel.beam

- dgiot_otherplugin_handler.beam

示例代码


%%%-------------------------------------------------------------------

%%% @author johnliu

%%% @copyright (C) 2021, <COMPANY>

%%% @doc

%%%

%%% @end

%%% Created : 24. 3月 2021 10:17

%%%-------------------------------------------------------------------

-module(dgiot_demonplugin_channel).

-author("johnliu").

-behavior(dgiot_channelx).

-include("dgiot_demonplugin.hrl").

-define(TYPE, <<"demonplugin">>).

-record(state, {id}).

%% API

-export([

start/2

]).

%% Channel callback

-export([init/3, handle_init/1, handle_event/3, handle_message/2, stop/3]).

-channel(?TYPE).

-channel_type(#{

type => 1,

title => #{

zh => <<"demonplugin通道"/utf8>>

},

description => #{

zh => <<"demonplugin通道"/utf8>>

}

}).

%% 注册通道参数

-params(#{

<<"port">> => #{

order => 2,

type => integer,

required => true,

default => 51889,

title => #{

zh => <<"服务器端口"/utf8>>

},

description => #{

zh => <<"服务器端口"/utf8>>

}

}

}).

start(ChannelId, ChannelArgs) ->

dgiot_channelx:add(?TYPE, ChannelId, ?MODULE, ChannelArgs).

%% 通道初始化

init(?TYPE, ChannelId, Args) ->

#{

<<"ip">> := Ip,

<<"port">> := Port,

<<"total">> := Total} = Args,

do_something(<<"hello plugin">>),

State = #state{

id = ChannelId

},

{ok, State, []}.

handle_init(State) ->

{ok, State}.

%% 通道消息处理,注意:进程池调用

handle_event(_EventId, Event, State) ->

lager:info("channel ~p", [Event]),

{ok, State}.

handle_message(_Message, State) ->

{ok, State}.

stop(ChannelType, ChannelId, _State) ->

ok.

do_something(Msg) ->

io:format("Msg ~p",[Msg]).

加载机制

  • 搜索到所有已经加载的插件

application:loaded_applications()

  • 通过App名称搜索ebin下面所有的beam文件

file:list_dir(Dir)

  • 搜素对应beam文件内的attributes是否包含channel

Mod:module_info(attributes)

  • 如果有channele的attributes则启动插件

Mod:start(ChannelId, ChannelArgs)

示例代码如下:


%%%-------------------------------------------------------------------

%%% @author johnliu

%%% @copyright (C) 2019, <COMPANY>

%%% @doc

%%%

%%% @end

%%% Created : 06. 八月 2019 18:00

%%%-------------------------------------------------------------------

-module(dgiot_plugin).

-author("johnliu").

-define(SYS_APP, [

kernel, stdlib, sasl

]).

-export([start/0])

start() ->

check_module(

fun({_App, _Vsn, Mod}, Acc) ->

case code:is_loaded(Mod) =/= false of

true ->

case lists:keyfind(channel, 1, Mod:module_info(attributes)) of

false ->

Acc;

{channel, ChannelTypes} ->

do_somthing()

end;

false ->

Acc

end

end, []).

check_module(Check, Acc0) ->

Fun =

fun({App, _Desc, Vsn}, Acc) ->

Dir = lists:concat(["lib/", App, "-", Vsn, "/ebin"]),

case not lists:member(App, ?SYS_APP) andalso file:list_dir(Dir) of

{ok, FS} ->

lists:foldl(

fun(FileName, Acc1) ->

case filename:extension(FileName) == ".beam" of

true ->

Mod = list_to_atom(filename:basename(FileName, ".beam")),

Check({App, Vsn, Mod}, Acc1);

false ->

Acc1

end

end, Acc, FS);

_ ->

Acc

end

end,

lists:foldl(Fun, Acc0, application:loaded_applications()).

do_somthing() ->

ok

没有了,已经是最后文章
上一篇:

加小迪为好友
即可加入交流群

点击填写表单
获得解决方案专家帮助
点击前往 GitHub
查看源代码