IOT command (based on sip)client API設計 for java,iotsip

來源:互聯網
上載者:User

IOT command (based on sip)client API設計 for java,iotsip
我們實現的物聯網裝置控制是通過擴充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;")

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.