Does espruino support bonding with a pin?

Posted on
Page
of 2
Prev
/ 2
  • Connection Failed


    1 Attachment

    • 1549274550137999.jpg
  • No Device Connected


    1 Attachment

    • 1549274549756142.jpg
  • I have attached some (blurry!) pictures of the camera during this process.

    Hmm... If only you had an expensive imaging device somewhere that you could use :)

    What happens if you try to connect from the Android phone but enter the wrong PIN? Does it behave in exactly the same way that Espruino does?

    If so it's possible that the PIN is getting corrupted somehow - it might give me a better idea where to look.

  • Ok, just some more thoughts:

    • Maybe try setting NRF.setSecurity({keyboard:1, mitm:1});
    • You mention the PIN screen only shows when you try to write to a characteristic? How about removing the startBonding line and instead just trying to access the characteristic (but while listening for the passkeyRequest event)? It's possible that would be more successful at kicking off the bonding properly?
  • Hmm... If only you had an expensive imaging device somewhere that you
    could use :)

    Yes, all the gear, no idea ;)

    Connecting in nRF and sending the wrong PIN results in the same behaviour, so there is a connection failed message on the camera which then is replaced by the no device connected screen as per the sequence when doing it from the Pixl.

    This is an nRF session where I connect and put in the wrong PIN and then re-connect and put in the correct PIN

    nRF Connect, 2019-02-04
    Pocket Cinema Camera 4K A:1C2 (90:FD:9F:B8:CA:37)
    D    18:46:51.954    gatt.close()
    D    18:46:51.957    wait(200)
    V    18:46:52.158    Connecting to 90:FD:9F:B8:CA:37...
    D    18:46:52.158    gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE)
    D    18:46:52.406    [Server callback] Connection state changed with status: 0 and new state: CONNECTED (2)
    I    18:46:52.406    [Server] Device with address 90:FD:9F:B8:CA:37 connected
    I    18:46:52.406    [Server] MTU changed to 64
    D    18:46:52.453    [Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
    I    18:46:52.453    Connected to 90:FD:9F:B8:CA:37
    D    18:46:52.457    wait(1600ms)
    D    18:46:52.484    [Broadcast] Action received: android.bluetooth.device.action.ACL_CONN­ECTED
    V    18:46:54.072    Discovering services...
    D    18:46:54.072    gatt.discoverServices()
    D    18:46:54.087    [Callback] Services discovered with status: 0
    I    18:46:54.087    Services discovered
    V    18:46:54.115    Generic Access (0x1800)
    - Device Name [R] (0x2A00)
    - Appearance [R] (0x2A01)
    Device Information (0x180A)
    - Manufacturer Name String [R] (0x2A29)
    - Model Number String [R] (0x2A24)
    Unknown Service (291d567a-6d75-11e6-8b77-86f30ca893d3)
    - Unknown Characteristic [W] (5dd3465f-1aee-4299-8493-d2eca2f8e1bb)
    - Unknown Characteristic [I] (b864e140-76a0-416a-bf30-5876504537d9)
     Client Characteristic Configuration (0x2902)
    - Unknown Characteristic [N] (6d8f2110-86f1-41bf-9afb-451d87e976c8)
     Client Characteristic Configuration (0x2902)
    - Unknown Characteristic [N R W] (7fe8691d-95dc-4fc5-8abd-ca74339b51b9)
     Client Characteristic Configuration (0x2902)
    - Unknown Characteristic [W] (ffac0c52-c9fb-41a0-b063-cc76282eb89c)
    - Unknown Characteristic [R] (8f1fd018-b508-456f-8f82-3d392bee2706)
    D    18:46:54.116    gatt.setCharacteristicNotification(b864e­140-76a0-416a-bf30-5876504537d9, true)
    D    18:46:54.119    gatt.setCharacteristicNotification(6d8f2­110-86f1-41bf-9afb-451d87e976c8, true)
    D    18:46:54.122    gatt.setCharacteristicNotification(7fe86­91d-95dc-4fc5-8abd-ca74339b51b9, true)
    V    18:47:09.481    Writing request to characteristic 5dd3465f-1aee-4299-8493-d2eca2f8e1bb
    D    18:47:09.481    gatt.writeCharacteristic(5dd3465f-1aee-4­299-8493-d2eca2f8e1bb, value=0xFF04000000010000)
    D    18:47:09.904    [Broadcast] Action received: android.bluetooth.device.action.BOND_STA­TE_CHANGED, bond state changed to: BOND_BONDING (11)
    D    18:47:09.920    [Broadcast] Action received: android.bluetooth.device.action.PAIRING_­REQUEST, pairing variant: PAIRING_VARIANT_PIN (0)
    D    18:47:18.238    [Broadcast] Action received: android.bluetooth.device.action.BOND_STA­TE_CHANGED, bond state changed to: BOND_NONE (10)
    I    18:47:18.238    Bonding failed
    D    18:47:21.182    [Server callback] Connection state changed with status: 0 and new state: DISCONNECTED (0)
    I    18:47:21.182    [Server] Device disconnected
    D    18:47:21.196    [Callback] Connection state changed with status: 22 and new state: DISCONNECTED (0)
    E    18:47:21.197    Error 22 (0x16): GATT CONN TERMINATE LOCAL HOST
    I    18:47:21.197    Disconnected
    D    18:47:21.290    [Broadcast] Action received: android.bluetooth.device.action.ACL_DISC­ONNECTED
    D    18:47:48.789    gatt.close()
    D    18:47:48.791    wait(200)
    V    18:47:48.992    Connecting to 90:FD:9F:B8:CA:37...
    D    18:47:48.992    gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE)
    D    18:47:49.292    [Server callback] Connection state changed with status: 0 and new state: CONNECTED (2)
    I    18:47:49.292    [Server] Device with address 90:FD:9F:B8:CA:37 connected
    I    18:47:49.292    [Server] MTU changed to 64
    D    18:47:49.400    [Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
    D    18:47:49.400    [Broadcast] Action received: android.bluetooth.device.action.ACL_CONN­ECTED
    I    18:47:49.400    Connected to 90:FD:9F:B8:CA:37
    V    18:47:49.422    Discovering services...
    D    18:47:49.422    gatt.discoverServices()
    D    18:47:50.038    [Callback] Services discovered with status: 0
    I    18:47:50.039    Services discovered
    V    18:47:50.062    Generic Access (0x1800)
    - Device Name [R] (0x2A00)
    - Appearance [R] (0x2A01)
    Device Information (0x180A)
    - Manufacturer Name String [R] (0x2A29)
    - Model Number String [R] (0x2A24)
    Unknown Service (291d567a-6d75-11e6-8b77-86f30ca893d3)
    - Unknown Characteristic [W] (5dd3465f-1aee-4299-8493-d2eca2f8e1bb)
    - Unknown Characteristic [I] (b864e140-76a0-416a-bf30-5876504537d9)
     Client Characteristic Configuration (0x2902)
    - Unknown Characteristic [N] (6d8f2110-86f1-41bf-9afb-451d87e976c8)
     Client Characteristic Configuration (0x2902)
    - Unknown Characteristic [N R W] (7fe8691d-95dc-4fc5-8abd-ca74339b51b9)
     Client Characteristic Configuration (0x2902)
    - Unknown Characteristic [W] (ffac0c52-c9fb-41a0-b063-cc76282eb89c)
    - Unknown Characteristic [R] (8f1fd018-b508-456f-8f82-3d392bee2706)
    D    18:47:50.062    gatt.setCharacteristicNotification(b864e­140-76a0-416a-bf30-5876504537d9, true)
    D    18:47:50.065    gatt.setCharacteristicNotification(6d8f2­110-86f1-41bf-9afb-451d87e976c8, true)
    D    18:47:50.068    gatt.setCharacteristicNotification(7fe86­91d-95dc-4fc5-8abd-ca74339b51b9, true)
    V    18:48:01.291    Writing request to characteristic 5dd3465f-1aee-4299-8493-d2eca2f8e1bb
    D    18:48:01.291    gatt.writeCharacteristic(5dd3465f-1aee-4­299-8493-d2eca2f8e1bb, value=0xFF04000000010000)
    D    18:48:01.778    [Broadcast] Action received: android.bluetooth.device.action.BOND_STA­TE_CHANGED, bond state changed to: BOND_BONDING (11)
    D    18:48:01.778    [Broadcast] Action received: android.bluetooth.device.action.PAIRING_­REQUEST, pairing variant: PAIRING_VARIANT_PIN (0)
    D    18:48:12.993    [Broadcast] Action received: android.bluetooth.device.action.BOND_STA­TE_CHANGED, bond state changed to: BOND_BONDED (12)
    I    18:48:12.994    Device bonded
    I    18:48:13.021    Data written to 5dd3465f-1aee-4299-8493-d2eca2f8e1bb, value: (0x) FF-04-00-00-00-01-00-00
    A    18:48:13.021    "(0x) FF-04-00-00-00-01-00-00" sent
    V    18:48:19.171    [Server] Cancelling server connection...
    D    18:48:19.171    server.cancelConnection(device)
    V    18:48:19.179    Disconnecting...
    D    18:48:19.179    gatt.disconnect()
    D    18:48:19.191    [Callback] Connection state changed with status: 0 and new state: DISCONNECTED (0)
    I    18:48:19.191    Disconnected
    D    18:48:20.229    [Server callback] Connection state changed with status: 0 and new state: DISCONNECTED (0)
    I    18:48:20.229    [Server] Device disconnected
    D    18:48:20.259    [Broadcast] Action received: android.bluetooth.device.action.ACL_DISC­ONNECTED
    

    Changing the NRF.setSecurity doesn't change the behaviour and the PIN prompt will only be invoked on the camera and the passkeyRequest triggered if startBonding is included.

    I changed the Write function so that it retains the startBonding but doesn't disconnect after writing to the characteristic. This leaves the PIN prompt up on the camera in the waiting state so gives me a chance to then pass the PIN to it but again it invokes the connection failure on the camera.

    With the behaviour being identical by passing the wrong PIN when connected through nRF it does appear to point to the the problem being the PIN being mangled on its way from the Pixl.

  • Perfect - thanks! I just found the problem. sendPasskey wasn't sending the supplied key at all (I'd got the arguments to it wrong).

    If you try an automatic build from http://www.espruino.com/binaries/travis/­master/ you should hopefully have a lot more success with it now!

    Thanks for sticking with me on this and trying out the suggestions!

  • Thanks for sticking with me on this and trying out the suggestions!>

    No, thanks to you for sorting it out!

    Which it now is with regard to the PIN.

    Using the startBonding(true) invokes the PIN prompt every time and startBonding() connects without once it has been done once so everything is working as it should there as well.

    I'm away for a couple of days from this evening so can look at it more when I get back but my challenge now is to send commands while maintaining the connection.

    When I'm connected to the camera, its stops advertising so functions with NRF.requestDevice can't find it and a composite function that bonds and then sends does connect but the camera isn't actioning the write to the characteristic that I'm sending.

    Apologies for my ignorance over this but is there a way to stay connected and just use BluetoothRemoteGATTCharacteristic.writeV­alue(data) as a single command ?

  • Great! That sounds really promising!

    Yes! Just delete:

    gatt.disconnect();
    

    writeValue by itself shouldn't cause a disconnect, so you should be able to stay connected and just keep writing to it - you just have to have saved characteristic to a variable that you can access once you've left that last part of the promise.

    If you can't see advertisements then it'll be because you're connected - so you should just be able to keep writing to the characteristic and you're sorted.

    I guess it's possible that the camera wants you to have subscribed to indications on the other characteristic before it'll perform the command?

  • I had already removed the gatt.disconnect and wrote another function to write to it whilst it was still connected but couldn't get any joy in terms of the camera actioning the command.

    I then thought to myself, "surely you haven't been stupid enough to be sending an invalid array to it have you?"

    Turns out I had been exactly that stupid and been sending nine bytes instead of eight so we now - insert fanfare here - have a camera that bonds correctly and can be operated from the Pixl.

    I won't have time now until the weekend to look at the notifications aspect but I'll be back to let you know how that worked out as soon as I've done so.

    Many, many thanks for your help and patience with this.

  • That's fantastic news - thanks for letting me know!

    Is this something you'd be willing to share the code for when you have it to a state you'd be happy with? As @user63214 brought this up reasonably recently you're obviously not the only person wanting to play around and do stuff with these cameras :)

  • No probelm, I'll pop up the basic connect/bond/PIN entry and single command code as a foundation and then people can use the Camera Control Protocol document that I linked to to build out the rest of it from there.

    I'll sort it out over the weekend when I'm back at base.

  • OK, so here we go with a basic template for connecting and sending commands.

    There is a bit of an issue regarding the bonding timing out when the flag isn't set to True to force it to pair. Basically, if you haven't sent the pin to it within about 7 seconds it times out which isn't long enough to set it through the terminal and send it.

    As I want to have the Pixl auto-connect to the camera as soon as it is switched on and stay connected, it would be a bit of a pain to have to go through the PIN entry process every time its switched on.

    Because the camera stores the bonding and it literally only needs to be sent the PIN once, I have not set it the flag to True but instead made a separate function with it being to True to initially set it. That way as soon as the Pixl powers on every time after the PIN has been set then it connects immediately and we are ready to send real commands to it.

    The process for initial bonding only then is
    1) Switch the Pixl on
    2) Wait for the PIN entry screen on the camera to timeout
    3) Press Button 4 on the Pixl which will start a new bonding process with no timeout
    4) Enter the PIN value from the console with pin="xxxxxx"
    5) Press Button 3 on the Pixl which will then send the PIN and complete the bonding.

    All subsequent restarts of the Pixl will connect the camera automatically with it being ready to receive commands.

    I have included an example byte array for a command (it triggers the Auto Focus on the camera) and this is then sent using Button 1 on the Pixl.

    The full camera control protocol for the camera can be downloaded here

    https://documents.blackmagicdesign.com/D­eveloperManuals/BlackmagicCameraControl/­20181019-740d71/BlackmagicCameraControl.­pdf

    var characteristicWrite;
    var characteristicRead;
    var dev;
    var gatt;
    var pin="";
    var ServUUId="291d567a-6d75-11e6-8b77-86f30c­a893d3";
    var CharUUID="5dd3465f-1aee-4299-8493-d2eca2­f8e1bb";
    
    function Connect(){
    // Insert own camera MAC address in id //
    NRF.requestDevice({ filters: [{ id: "90:fd:9f:b8:ca:37 public"  }] }).then(function(device) {
    dev=device;
    NRF.setSecurity({keyboard:1, mitm:1});
    console.log("Connecting");
    device.on('passkeyRequest', function() {
    console.log("passkey requested");
    });
    return device.gatt.connect();
    }).then(function(g) {
    gatt = g;
    console.log("Connected");
    return gatt.startBonding(); //< If the camera has been previously bonded the PIN pop-up will not be invoked //
    }).then(function() {
    console.log("bonded", gatt.getSecurityStatus());
    return gatt.getPrimaryService("291d567a-6d75-11­e6-8b77-86f30ca893d3");
    }).then(function(service) {
    return service.getCharacteristic("5dd3465f-1aee­-4299-8493-d2eca2f8e1bb");
    }).then(function(characteristic) {
        console.log("Writing To Characteristic");
        characteristicWrite=characteristic;
        return characteristic.writeValue([0xFF, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00] );
    }).then(function() {
      console.log("Done!");
    });
    }
    
    function Bond(){
    // Insert own camera MAC address in id //
    NRF.requestDevice({ filters: [{ id: "90:fd:9f:b8:ca:37 public" }] }).then(function(device) {
    dev=device;
    NRF.setSecurity({keyboard:1, mitm:1});
    console.log("Connecting");
    device.on('passkeyRequest', function() {
    console.log("passkey requested");
    });
    return device.gatt.connect();
    }).then(function(g) {
    gatt = g;
    console.log("Connected");
    return gatt.startBonding(true);//< This will force the PIN pop-up to be invoked irrespective of previous bond//
    }).then(function() {
    console.log("bonded", gatt.getSecurityStatus());
    return gatt.getPrimaryService("291d567a-6d75-11­e6-8b77-86f30ca893d3");
    }).then(function(service) {
    return service.getCharacteristic("5dd3465f-1aee­-4299-8493-d2eca2f8e1bb");
    }).then(function(characteristic) {
        console.log("Writing To Characteristic");
        characteristicWrite=characteristic;
        return characteristic.writeValue([0xFF, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00] );
    }).then(function() {
      console.log("Done!");
    });
    }
    
    function SendPin(){
    //Enter required PIN in console using pin="xxxxxx"//
    dev.sendPasskey(pin);
    }
    
    function WriteValNoConnect(){
    //Writes Auto-Focus command to the connected camera without re-connection//
    characteristicWrite.writeValue([0xFF, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00] );
    }
    
    function onInit(){
    //Automatically connects the camera and establishes Characteristic to be written to//
    // If camera has been bonded the PIN pop-up will not be invoked//
    Connect();
    }
    
    
    setWatch(function() {
      console.log("WRITING AUTO FOCUS COMMAND TO CAMERA");
      WriteValNoConnect();
    }, BTN, {edge:"rising", debounce:50, repeat:true});
    
    setWatch(function() {
      console.log("NO FUNCTION ASSIGNED");
    }, BTN2, {edge:"rising", debounce:50, repeat:true});
    
    setWatch(function() {
      console.log("SENDING PIN : "+pin);
      SendPin(); 
    }, BTN3, {edge:"rising", debounce:50, repeat:true});
    
    setWatch(function() {
      console.log("BONDING");
      Bond();
    }, BTN4, {edge:"rising", debounce:50, repeat:true});
    
    
  • Nice - thanks!

  • Done a quick mod job pressing a Puck into service as a Record Start/Stop control.


    1 Attachment

    • 20190211_132727-01.jpeg
  • Is there any Api documentation for NRF.setSecurity options (e.g. keyboard:1)? I want to use a Pixl as a peripheral (no keyboard attached) but force bonding and whitelisting. The central is an IOS app.

  • BTW, I've tried the NRF.setSecurity({passkey:"123456", mitm:1, display:1}); to no avail using 2v01.35 of the firmware.

  • The proper documentation for it is generated when I next do a release, so apart from http://www.espruino.com/Puck.js+Security­ you have to look at the source (which is used to generate the documentation).

    For example setSecurity is here: https://github.com/espruino/Espruino/blo­b/master/libs/bluetooth/jswrap_bluetooth­.c#L2493

    Then you have the passkey event, passkeyRequest event and sendPasskey (just do a work search for them in quotes in the above file).

    I'm not sure how you'd go about actually forcing bonding though - I believe you can do so from the iOS app though?

  • Sorry about the delay in replying and thanks for the pointer to GitHub. I'll work a bit more on it next week when hopefully I'll have a bluetooth dongle to sniff the packets with WireShark.
    iOS takes the approach that it's up to the peripheral to decide if it wants to implement any security - there's no way to force it from that side.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Does espruino support bonding with a pin?

Posted by Avatar for user63214 @user63214

Actions