插件化开发Yate【2】 - 简单插件Demo

插件开发是Yate开发的主要内容,本文将以一个简单的插件为例,说明Yate插件开发的基础方式。

插件的源码地址为:https://gitee.com/iseelgy/demo00

插件源码

#include "Aux_cmd_define.h"
#include "Aux_yate_hal.h"


//=====================================================================================================================
//=====================================================================================================================
//=====================================================================================================================
//=====================================================================================================================

using namespace TelEngine;

// 注意: 插件名称和动态库名称需要保持一致,否则会导致部分插件管理功能缺失

#define MY_PLUGIN_NAME "demo00"

namespace {	 // 使用匿名空间


	//===============================
	// 类定义

	class MyPlugin : public Plugin
	{
	public:


		MyPlugin() : Plugin(MY_PLUGIN_NAME)
			, _debug_hdl(0), m_initialized(false)
		{
			
		}


		~MyPlugin() {

		}

		// 模块初始化函数,会被多次调用
		void initialize(void) override;

		// 引擎启动处理
		void onEngineStart();
		
		// 引擎退出处理
		void onEngineStop();

		// debug消息
		bool onYateDebug(Message& msg);

		// 消息处理函数
		bool onYateMessage(Message& msg);


	private:

		// 插件对象初始化标记
		bool m_initialized;

		YateMsgHandler* _debug_hdl;


	};

	//===============================
	// 变量定义


	// 实现模块对象
	INIT_PLUGIN(MyPlugin);

	// 配置文件
	static Configuration s_cfg;


	//===============================
	// 功能实现

	void MyPlugin::initialize()
	{
		Output( "Initializing module " MY_PLUGIN_NAME);


		// 配置文件,配置文件名可任意指定,
		s_cfg = Engine::configFile(MY_PLUGIN_NAME);
		s_cfg.load();

		int level = s_cfg.getIntValue("debug", "level", TelEngine::debugLevel());
		withDebugEnabler()->debugLevel(level);

		if (!m_initialized) {

			// 设置初始化标记,避免多次调用情况下出现问题
			m_initialized = true;

			// 订阅消息处理
			YateMsgHandler* handler;

			// 引擎启动消息
			handler = new YateMsgHandler(MSG_ENGINE_START);
			handler->_handler = [this](Message& msg) {
				this->onEngineStart();
				return false;
			};
			Engine::install(handler);

			// 引擎退出消息
			handler = new YateMsgHandler(MSG_ENGINE_STOP);
			handler->_handler = [this](Message& msg) {
				this->onEngineStop();
				return false;
			};
			Engine::install(handler);

			int priority = s_cfg.getIntValue("general", "priority", 100);
			handler = new YateMsgHandler(MSG_YATE, priority);
			handler->_handler = [this](Message& msg) {
				return this->onYateMessage(msg);
			};
			Engine::install(handler);

		}

		// 调试消息处理
		int on = s_cfg.getBoolValue("debug", "on", false);
		if (on) {
			if (!_debug_hdl) {
				int priority = s_cfg.getIntValue("debug", "priority", 100);
				_debug_hdl = new YateMsgHandler("Yateshop.debug", priority);
				_debug_hdl->_handler = [this](Message & msg) {
					return this->onYateDebug(msg);
				};
				Engine::install(_debug_hdl);
			}
		}
		else {
			if (_debug_hdl) {
				Engine::uninstall(_debug_hdl);
				delete _debug_hdl;
				_debug_hdl = nullptr;
			}
		}

		//String demo = s_cfg.getValue("general", "demo", "default");
		//S_INFO("config -> " << demo.safe());

	}


	void MyPlugin::onEngineStart()
	{

		//S_INFO("onEngineStart, ***************************");
		//Y_WARN("onEngineStart, ***************************");

		//const String& shared = Engine::sharedPath();

		// 用户信息配置路径, 与操作系统的登录用户关联
		//const String& user = Engine::configPath(true);

		// Yate全局配置路径, 与yate的安装路径相关
		//const String& config = Engine::configPath(false);

	}

	void MyPlugin::onEngineStop()
	{
		
		//S_INFO( "onEngineStop ")  ;

	}


	bool MyPlugin::onYateMessage(Message& msg)
	{
		//String Op = msg.getParam("Op");

		return false;
	}

	bool MyPlugin::onYateDebug(Message& msg)
	{

		return false;
	}

}

/*
* 支持模块内日志宏
*/

TelEngine::DebugEnabler * withDebugEnabler()
{
	return &__plugin;
}

TE::Configuration * get_configuration()
{
	return &s_cfg;
}

const char* get_app_name()
{
	return s_cfg.getValue("general", "app.name", __plugin.name());
}

类定义

插件可以通过Plugin派生实现MyPlugin,插件初始化的时候,需要确定插件的名称。Yate引擎通过插件名称对插件进行管理。相同名称的插件,在系统中只能注册成功一个,如果有多个同名插件,后续的插件将注册失败。

initialize函数

插件MyPlugin必须实现纯虚函数initialize(),该函数实现插件的初始化处理。系统启动后,Yate引擎在初始化过程中,在加载完插件后,会调用该函数。通常在该函数中,读取插件的配置文件,并完成插件的初始化处理等操作的。 需要注意的是,该函数在系统初始化的时候会被调用,在后续的处理中,如果系统动态加载了插件,也会调用该函数; 同时也可使用系统提供的API函数,static bool Engine::init(const String& name); 单独对某个插件进行初始化,并触发调用该插件的initialize函数。

消息订阅

插件通过API函数bool Engine::install(MessageHandler* handler); 订阅消息;也可以通过接口 bool Engine::uninstall(MessageHandler* handler);取消消息订阅。

订阅消息的处理流程如下:

           YateMsgHandler* handler;

            // 引擎启动消息
            handler = new YateMsgHandler( “消息名称” );
            handler->_handler = [this](Message& msg) {                        

                  // ..........

                  // 实现消息处理逻辑 

                  //  返回true 或者 false,控制后续处理流程

                return true; //  返回true,将结束非广播消息的处理流程

                return false;  //  返回false,消息继续处理
            };
            Engine::install(handler);

或者实现一个消息处理类,XXXHandler 的类,并从MessageHandler 基类继承。

1.      class XXXHandler : public MessageHandler  

2.      {  

3.      public:  

4.          XXXHandler(int prio)  

5.              : MessageHandler("call.route",prio) { }  

6.          virtual bool received(Message &msg);  

7.      };  

在 received 方法中实现消息处理逻辑。

插件对象实例

插件对象实例化通过定义一个静态对象即可实现,可通过宏NIT_PLUGIN即可完成。

INIT_PLUGIN(MyPlugin);

配置

Yate提供了配置管理类Configuration,可以提供配置管理功能,在插件开发中,通常在initialize函数中实现配置的读取,完成配置逻辑。

日志:

全局控制日志

S_TRACE(message) 
S_DEBUG(message)
S_INFO(message)
S_WARN(message)
S_ERROR(message) 
S_FATAL(message) 

插件控制日志

Y_TRACE(message) 
Y_DEBUG(message)
Y_INFO(message)
Y_WARN(message)
Y_ERROR(message) 
Y_FATAL(message) 
 

其中全局控制日志,其显示级别与Yate系统的显示级别是一致的,而插件控制日志,是在每个的插件中,独立控制日志显示级别;插件控制日志可以通过配置文件,控制当前模块的日志显示。

为了支持插件控制日志,当前插件需要实现接口函数,TelEngine::DebugEnabler * withDebugEnabler()

该文档用于实现一个最基础的Yate插件,在后续的文档中,将介绍Yate插件开发的更多方面的内容。

【上一篇】插件化开发Yate【1】 - 框架介绍-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值