cordova-plugin-ble-central icon indicating copy to clipboard operation
cordova-plugin-ble-central copied to clipboard

Native hook system proposition for third party plugins

Open zabojad opened this issue 8 years ago • 1 comments

Hi !

Following our discussion about it, here is a first proposition for a native hook system allowing third party plugins to share BT connections with the ble central plugin for features like peripheral firmware update or regular peripheral status update (peripheral that requires to sync state with master app every xx ms).

I'm fully aware that the present proposition is far from being perfect but I've sent it just to start concrete technical discussions about how to do it right. I'm aware it won't be merged as is...

Now this PR just contains the ble central plugin part. I've used it successfully on a firmware update plugin I've developed for one of my current projects. Here is how it looks on the third party plugin side:

iOS:

// ...

- (void)initBlePluginRef {

    NSLog(@"initBlePluginRef");

    blePlugin = [self.commandDelegate getCommandInstance:@"BLE"];
}

- (void)removeHooks {

    NSLog(@"removeHooks");

    [blePlugin removeHook:bleHk];
}

- (void)registerHooks {

    NSLog(@"registerHooks");

    bleHk = [[BLECentralPluginHook alloc] init];

    bleHk.uuid = uuid;

    bleHk.didWriteValueForCharacteristic = ^(CDVPluginResult* pr)
        {
            CDVPluginResult* r = nil;

            NSLog(@"successfully shortcut write cb");

            // whatever I want to do with the write cb...

            return r;
        };

    bleHk.didUpdateValueForCharacteristic = ^(CDVPluginResult *pr)
        {
            CDVPluginResult* r = nil;

            NSLog(@"successfully shortcut notif cb");

            // my notification cb hook implementation
            NSData * d = [[NSData alloc] initWithBase64EncodedString:[pr.message objectForKey:@"data"] options:0];
            [self onNotificationCb:d];

            return r;
        };

    [blePlugin registerHook:bleHk forPeripheral:uuid];
}

// ...

Android:

    // ...

    private void getBlePlugin() {

        Class webViewClass = webView.getClass();
        PluginManager pm = null;
        
        try {

            Method gpm = webViewClass.getMethod("getPluginManager");
            pm = (PluginManager) gpm.invoke(webView);

        }
        catch (NoSuchMethodException e) { }
        catch (IllegalAccessException e) { }
        catch (InvocationTargetException e) { }

        if (pm == null) {

            try {
                Field pmf = webViewClass.getField("pluginManager");
                pm = (PluginManager)pmf.get(webView);
            }
            catch (NoSuchFieldException e) { }
            catch (IllegalAccessException e) { }
        }

        blePlugin = (BLECentralPlugin) pm.getPlugin("BLE");
    }

    // ...

    private PluginResult removeHook() {

        PluginResult result = null;

        if (blePlugin != null) {

            LOG.d(TAG, "remove BLE hook");

            boolean r = blePlugin.removeHook("MyThirdPartyPlugin", macAddress);

            if (!r) {
                // should not happen...
                LOG.e(TAG, "BLE plugin doesn't know peripheral "+macAddress);
                result = new PluginResult(PluginResult.Status.ERROR, "BLE plugin doesn't know peripheral "+macAddress);
            }
        }
        else {
            // should not happen...
            LOG.e(TAG, "BLE plugin not found");
            result = new PluginResult(PluginResult.Status.ERROR, "BLE plugin not found");
        }
        return result;
    }

    private PluginResult registerBleHook() {

        PluginResult result = null;
        
        if (blePlugin != null) {

            LOG.d(TAG, "register BLE hook");

            boolean r = blePlugin.registerHook(new BLECentralPluginHook() {
                public PluginResult onCharacteristicChanged(PluginResult pr) {
                    return MyThirdPartyPlugin.this.onCharacteristicChanged(pr);
                }
                public PluginResult onCharacteristicRead(PluginResult pr) {
                    return pr;
                }
                public PluginResult onCharacteristicWrite(PluginResult pr) {
                    if (pr.getStatus() == PluginResult.Status.ERROR.ordinal()) {
                        updateCallback.sendPluginResult(pr);
                    }
                    return null;
                }
            }, "MyThirdPartyPlugin", macAddress);

            if (!r) {

                LOG.e(TAG, "BLE plugin doesn't know peripheral "+macAddress);
                result = new PluginResult(PluginResult.Status.ERROR, "BLE plugin doesn't know peripheral "+macAddress);
            }
        }
        else {

            LOG.e(TAG, "BLE plugin not found; cannot start firmware update");
            result = new PluginResult(PluginResult.Status.ERROR, "BLE plugin not found; cannot start firmware update");
        }
        return result;
    }

And that's pretty much it. I just needed to hook the write and notification commands but we could easily apply it to the read command of course.

Now what I think about all this is: a better design would not require the hook to use PluginResult and cordova command callbacks. However, I did not see how to avoid this with the current cle central plugin implementation. So designing a better hook feature would probably require re-organize the ble central plugin code and separate better the core functions from the cordova callback instructions.

What do you think about all this?

Do you see any chance we can find some common ground to implement a good hook feature?

zabojad avatar Sep 11 '17 16:09 zabojad

@don Did you have a chance to have a look at this?

zabojad avatar Sep 21 '17 08:09 zabojad

I'm closing this as it's not clear to me whether the plugin and requirement are still a current demand. If there is a lot of interest in such a feature, I'd be happy to reconsider however.

peitschie avatar Mar 16 '23 10:03 peitschie

No problem @peitschie this PR is just 6 years old :D ! I do not use Cordova anymore now :p...

zabojad avatar Mar 16 '23 16:03 zabojad