IOT command (based on sip) client API design for java, iotsip
The Iot Device Control we implement is implemented by extending the sip protocol. Because pjsip is implemented based on pjsip, while pjsip uses C Programming, how to make the business layer (android end, java) easier to use the provided command API is the focus, the original method is to encapsulate (C ---> jni ---> java) from the underlying c, which has obvious defects: 1. difficult third-party development and development, heavy workload, and unreasonable API design; 2. different device control business access codes must be integrated into the main program iot_sip_cli, which is highly coupled and unacceptable (especially for third-party development ). Therefore, the IOC principle (don't call us, we'll call you) enables third-party development to be implemented directly at the java layer, an interface is provided to a third party to register the implementation to the iot_sip_cli_jni layer. The call to the jni layer is driven by iot_sip_cli. For example, to access a device type named test_plugin, there are two methods: test1, test5. 1. third-party development first defines the method Response Processing: public class TestPluginCallBack {// The following two methods are finally called by 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. Third-party development will pass the above object and method to the sdk (the IOTCmdAttachment inside the sdk is responsible ):
IOTCmdAttachment att = IOTCmdAttachment.getSingleton(); TestPluginCallBack cbObj = new TestPluginCallBack(); att.registerCmdHandlers(cbObj);
3. third-party development, Write Device control request sending: att. inputCommand ("test_plugin", "test1", reqJson, toUri); // The response result retJson is uploaded to the business layer through the first step. In this way, third-party development can complete the control of access devices through the above three steps. Shows the process principle (the sdk provided to a third party is composed of the pai_api_4java jar package and iot_rj_jni so). The main step is to use IOTCmdAttachment method registerCmdHandlers: CmdCBAnnotation using custom java annotations, identify the function to be called and pass it to jni_reg_cmdcb (it calls reg_handler internally ),
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 (response, TAGSTR, "reg_handler"); JNIEnv * env = handler (); std:: string str_devtype = jstring2str (env, dev_type); std: string str_methname = jstring2str (env, method_name); // generate the DeviceCmdHandler object and name the storage device type, device method name (that is, the value of @ CmdCBAnnotation dev_type, method_name), // TestPluginCallBack Image, and the annotated java method DeviceCmdHandler * pt_dchdl = new DeviceCmdHandler (str_devtype, str_methname, jobj, jmeth); // metadata: methodCallBack4c uses pt_dchdl as the parameter, and it will be called by iot_sip_cli as the callback function int ret = pai_cb_reg4cpp (str_devtype.c_str (), callback (), & DeviceCmdHandler: methodCallBack4c, pt_dchdl); if (0! = Ret) {_ android_log_print (ANDROID_LOG_ERROR, TAGSTR, "reg_handler fail ret % d: % s", ret, str_devtype.c_str (), str_methname.c_str ());} else {_ android_log_print (ANDROID_LOG_INFO, TAGSTR, "reg_handler succ: % s", str_devtype.c_str (), str_methname.c_str ();} return ret ;}
Struct class: int DeviceCmdHandler: methodCallBack4c (int ret_ I, const char * ret_json, void * pt_obj) {return (DeviceCmdHandler *) pt_obj)-> methodCallBack (ret_ I, ret_json);} And DeviceCmdHandler: methodCallBack (int ret_ I, const char * ret_json) method, finally calling CallObjectMethod (env, this-> mJmethod, mid, jo, (jobjectArray) texts), that is, the method that calls the two annotations TestPluginCallBack at the java layer. Obtain the mid, using 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 ;")