IOT command (based on sip)client API设计 for java – europelee

我们实现的物联网设备控制是通过扩展sip协议来实现的。
由于是基于pjsip来实现的,而pjsip是使用C编程,如何使得业务层(android端,使用java)更容易使用提供的command API
是重点,原始的方法就是从底层C开始往上层层封装(c—>jni—>java),这样存在明显的缺陷:
1. 对于第三方开发开发难度大,工作量多,API设计不合理;
2. 不同的设备控制业务接入代码都需要集成到主程序iot_sip_cli,高耦合,这是不能接受的(特别对于第三方开发)。
 
所以倒过来考虑,利用IOC原则(don’t call us, we’ll call you),让第三方开发直接在java层来实现,提供接口给第三方让其将实现注册到iot_sip_cli_jni层,最后jni层的调用被iot_sip_cli驱动。
 
举例: 接入一个叫test_plugin的设备类型, 它有两个方法test1, test5.
 
1. 第三方开发首先定义方法的响应处理
public class TestPluginCallBack {
           //以下两个方法最终被iot_sip_cli调用
@CmdCBAnnotation(dev_type = “test_plugin”, method_name = “test1”)
 public void setId(int ret, String retJson) {
}
 
 @CmdCBAnnotation(dev_type = “test_plugin”, method_name = “test5”)
 public void setId2(int ret, String retJson) {
}
 
};
 
2.第三方开发将上面的对象,方法传递给 sdk(由sdk内部的IOTCmdAttachment负责):
     
 IOTCmdAttachment att = IOTCmdAttachment.getSingleton();
 TestPluginCallBack cbObj = new TestPluginCallBack();
 att.registerCmdHandlers(cbObj);
 
3. 第三方开发,写设备控制的请求发送
        att.inputCommand(“test_plugin”, “test1”, reqJson, toUri); //响应结果retJson通过第一步的方法传到业务层。
 
这样,第三方开发只要通过上面3个步骤,就能完成对接入设备控制的实现。
 
过程原理如下图所示(提供给第三方的sdk由CMD_API_4JAVA jar包,和IOT_CMD_JNI so构成):
 
主要步骤在于IOTCmdAttachment方法registerCmdHandlers的使用:
利用自定义的java注解CmdCBAnnotation, 识别出需要调用的函数,将其传给 jni_reg_cmdcb(它内部调用reg_handler), 
public int registerCmdHandlers(Object obj) {
int status = 0;
for (Method m : obj.getClass().getMethods()) {
CmdCBAnnotation a
= m.getAnnotation(CmdCBAnnotation.class);
if (a != null) {
Log.d(LOG_TAG,
“” + a.dev_type() + : + a.method_name());
status
= jni_reg_cmdcb(a.dev_type(), a.method_name(), obj, m);
if (0 != status)
return status;
}
}

return status;
}

 

static int reg_handler(jstring dev_type, jstring method_name, jobject jobj,
jobject jmeth)
{
__android_log_print(ANDROID_LOG_INFO, TAGSTR,
reg_handler);

JNIEnv *env = get_jni_env();
std::
string str_devtype = jstring2str(env, dev_type);
std::
string str_methname = jstring2str(env, method_name);

//生成DeviceCmdHandler对象,存储设备类型名,设备方法名(即上面注解@CmdCBAnnotation dev_type, method_name值),
//TestPluginCallBack对象,和被注解的java方法
DeviceCmdHandler * pt_dchdl = new DeviceCmdHandler(str_devtype,
str_methname, jobj, jmeth);

//DeviceCmdHandler::methodCallBack4c会使用pt_dchdl作为参数,并且它作为回调函数将被iot_sip_cli调用
int ret = cmd_cb_reg4cpp(str_devtype.c_str(), str_methname.c_str(),
&DeviceCmdHandler::methodCallBack4c, pt_dchdl);
if (0 != ret)
{
__android_log_print(ANDROID_LOG_ERROR, TAGSTR,
reg_handler fail ret %d:%s %s, ret, str_devtype.c_str(),
str_methname.c_str());
}
else
{
__android_log_print(ANDROID_LOG_INFO, TAGSTR,
reg_handler succ:%s %s, str_devtype.c_str(), str_methname.c_str());
}
return ret;
}

 

  

 
DeviceCmdHandler类如下:
 
int DeviceCmdHandler::methodCallBack4c(int ret_i, const char * ret_json,
  void * pt_obj) {
     return ((DeviceCmdHandler *) pt_obj)->methodCallBack(ret_i, ret_json);
}
而 DeviceCmdHandler::methodCallBack(int ret_i, const char * ret_json)方法,最终调用
CallObjectMethod(env, this->mJmethod, mid, jo, (jobjectArray) texts); 即调用java层的TestPluginCallBack两个注解的方法。
 
mid获取, 使用java.lang.reflect.Method:
 JLocalRef<jclass> clazz = env->GetObjectClass(this->mJmethod);
 jmethodID mid = env->GetMethodID(clazz, “invoke”,   “(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;”)

 

本文链接:IOT command (based on sip)client API设计 for java,转载请注明。



You must enable javascript to see captcha here!

Copyright © All Rights Reserved · Green Hope Theme by Sivan & schiy · Proudly powered by WordPress

无觅相关文章插件,快速提升流量