Moddable-OpenSource / moddable

Tools for developers to create truly open IoT products using standard JavaScript on low cost microcontrollers.
http://www.moddable.com
1.35k stars 238 forks source link

BLE completeName #1402

Open mauroForlimpopoli opened 2 months ago

mauroForlimpopoli commented 2 months ago

I'm running the example https://github.com/Moddable-OpenSource/moddable/blob/24e3e54fd3b66379c1f91ad92969c99f941ff4cf/examples/network/ble/scanner/main.js on Moddable Six. I used this example in Moddable Two with old compiler. Now when a BLE device is discoverd, only some of them answer to device.scanResponse.completeName To be clear I have many Bluetooth sensors and printers and only one of them work right. In the previus version all these devices answer to device.scanResponse.completeName No error only "undefined" like answer Is something changed? Regards

phoddie commented 2 months ago

Is something changed?

Yes. As explained in multiple release notes, the Modable SDK have migrated to ESP-IDF v5. There are significant differences in many areas of the IDF, including BLE and Wi-Fi.

It seems possible that this BLE behavior you observe is a result of the changes in ESP-IDF v5. We can investigate. Is there a common device (iPhone, HP printer, etc) that provides a completeName that you would recommend for reproducing this problem?

mauroForlimpopoli commented 2 months ago

the Bluetooth test is done on 7 differente devices. There are thermal printers and temperature sensors , but they aren't common devices. Just one works. So I suppose that the problem can be reproducted from a simple bluetooth device you test.

phoddie commented 2 months ago

The JavaScript APIs simply report the advertising packets provided by the ESP-IDF BLE stack (which uses the NimBLE API). Since I cannot see your devices, it is not possible to diagnose what is going on. I put together an extended version of the ble/scanner example The modified source code for that is below. For each device it outputs a hex dump of the advertising packet, a text dump of all the ASCII characters in the advertising packet, and the name of each field parsed out of the advertising packet. Please give that a try and post the results. Thank you.

import BLEClient from "bleclient";
import GAP from "gap";

class Scanner extends BLEClient {
    addresses = new Set;

    onReady() {
        this.startScanning({});
    }
    onDiscovered(device) {
        const address = device.address.toString();
        if (this.addresses.has(address))
            return;
        this.addresses.add(address);

        trace(`Device: ${address} ${device.scanResponse.completeName ?? device.scanResponse.shortName ?? ""}\n`);

        const data = Array.from(new Uint8Array(device.scanResponse.buffer));

        trace("  ", data.map(value => value.toString(16).padStart(2, "0")).join(" "), "\n")
        trace("  ", data.map(value => ((32 <= value) && (value < 127)) ? String.fromCharCode(value) : ".").join(""), "\n");

        let index = 0;
        while (index < data.length) {
            const length = data[index++];
            let type = data[index++];
            for (let name in GAP.ADType) {
                if (GAP.ADType[name] === type) {
                    type = name;
                    break;
                }
            }
            trace(`  type ${type}, length ${length}\n`);
            index += length - 1;
        }
    }
}

let scanner = new Scanner;
mauroForlimpopoli commented 2 months ago

This is the report :

No Wi-Fi SSID
Device: 86:67:7A:5A:BF:9E 
  02 01 0a 03 02 f0 18 11 06 f2 c3 f0 ae a9 fa 15 8c 9d 49 ae 73 71 0a 81 e7
  ..................I.sq...
  type FLAGS, length 2
  type INCOMPLETE_UUID16_LIST, length 3
  type INCOMPLETE_UUID128_LIST, length 17
Device: 86:67:7A:88:1D:62 
  02 01 0a 03 02 f0 18 11 06 f2 c3 f0 ae a9 fa 15 8c 9d 49 ae 73 71 0a 81 e7
  ..................I.sq...
  type FLAGS, length 2
  type INCOMPLETE_UUID16_LIST, length 3
  type INCOMPLETE_UUID128_LIST, length 17
Device: 57:4C:54:01:E3:A5 
  02 01 0a 03 02 f0 18 11 06 f2 c3 f0 ae a9 fa 15 8c 9d 49 ae 73 71 0a 81 e7
  ..................I.sq...
  type FLAGS, length 2
  type INCOMPLETE_UUID16_LIST, length 3
  type INCOMPLETE_UUID128_LIST, length 17
Device: 70:B8:F6:21:DD:A2 One-DDA0
  02 01 06 09 09 4f 6e 65 2d 44 44 41 30 11 07 9e ca dc 24 0e e5 a9 e0 93 f3 a3 b5 01 00 40 6e
  .....One-DDA0.....$..........@n
  type FLAGS, length 2
  type COMPLETE_LOCAL_NAME, length 9
  type COMPLETE_UUID128_LIST, length 17
Device: 60:6E:41:62:C8:AD 
  02 01 06 11 07 f2 c3 f0 ae a9 fa 15 8c 9d 49 ae 73 71 0a 81 e7 03 03 e7 fe 03 03 f0 18
  ..............I.sq...........
  type FLAGS, length 2
  type COMPLETE_UUID128_LIST, length 17
  type COMPLETE_UUID16_LIST, length 3
  type COMPLETE_UUID16_LIST, length 3
Device: FF:B4:73:E5:48:80 ela50506543
  02 01 06 05 16 6e 2a d0 0a 0c 09 65 6c 61 35 30 35 30 36 35 34 33
  .....n*....ela50506543
  type FLAGS, length 2
  type SERVICE_DATA_UUID16, length 5
  type COMPLETE_LOCAL_NAME, length 12
Device: 60:1E:1F:1E:09:BA 
  02 01 1a 02 0a 0b 0a ff 4c 00 10 05 72 1c bb cf 40
  ........L...r...@
  type FLAGS, length 2
  type TX_POWER_LEVEL, length 2
  type MANUFACTURER_SPECIFIC_DATA, length 10
Device: 7C:D9:F4:10:3E:61 
  02 01 06 03 03 aa fe 17 16 aa fe 00 e8 24 14 40 b7 85 8a 55 aa cf be ea 61 30 35 00 55 00 00
  .............$.@...U....a05.U..
  type FLAGS, length 2
  type COMPLETE_UUID16_LIST, length 3
  type SERVICE_DATA_UUID16, length 23
Device: 7C:D9:F4:11:7C:6A 
  02 01 06 03 03 aa fe 17 16 aa fe 00 e8 e4 53 ef 10 48 b9 55 aa 8f fe 99 bb f3 63 00 55 00 00
  ..............S..H.U......c.U..
  type FLAGS, length 2
  type COMPLETE_UUID16_LIST, length 3
  type SERVICE_DATA_UUID16, length 23
Device: 58:3B:95:7D:40:02 
  02 01 1a 0d ff 4c 00 16 08 00 54 2f 5d 1a 6e 24 b0
  .....L....T/].n$.
  type FLAGS, length 2
  type MANUFACTURER_SPECIFIC_DATA, length 13
Device: 7C:D9:F4:15:AB:C7 
  02 01 06 03 03 aa fe 17 16 aa fe 00 e2 f0 27 70 b2 2b c9 55 aa 9b d2 1a 5d d6 73 00 55 00 00
  ..............'p.+.U....].s.U..
  type FLAGS, length 2
  type COMPLETE_UUID16_LIST, length 3
  type SERVICE_DATA_UUID16, length 23
Device: 7C:D9:F4:14:00:F8 
  02 01 06 03 03 aa fe 17 16 aa fe 00 e8 13 7c 8f b2 2b c9 55 aa be 26 3a 5d d6 73 00 55 00 00
  ..............|..+.U..&:].s.U..
  type FLAGS, length 2
  type COMPLETE_UUID16_LIST, length 3
  type SERVICE_DATA_UUID16, length 23
Device: 7C:D9:F4:10:F5:70 
  02 01 06 03 03 aa fe 17 16 aa fe 00 e8 04 98 70 b2 2b c9 55 aa af 42 1b 5d d6 73 00 55 00 00
  ...............p.+.U..B.].s.U..
  type FLAGS, length 2
  type COMPLETE_UUID16_LIST, length 3
  type SERVICE_DATA_UUID16, length 23

MAC 70:B8:F6:21:DD:A2 is a Moddable Two MAC FF:B4:73:E5:48:80 is a temperature sensor

phoddie commented 2 months ago

Thanks for the trace. That all looks reasonable. The Moddable Two and temperature sensor contain the COMPLETE_LOCAL_NAME in their advertising packet. Those names (One-DDA0 and ela50506543) are logged as the device name.

mauroForlimpopoli commented 2 months ago

That is true, but the other devices don't contain the COMPLETE_LOCAL_NAME. The other devices are printers and sensors and by using simples App BLE scanner the complete name is showed.

phoddie commented 2 months ago

The JavaScript API can only provide the information that the ESP-IDF provides. The test above shows that it is doing that.

There are two kinds of scans: passive and active. The advertising packets seen above are the result of a passive scan. In an active scan, the scanning device requests each device to send an additional "advertising response packet." No advertising response packets are provided by the ESP-IDF.

The JavaScript BLE client requests an active scan by setting the passive field to 0. The code in the Moddable SDK that configures the scan is here. I've recently compared that to the BLE scan example in the ESP-IDF and found them to be consistent.

The Moddable SDK uses the NimBLE API in the ESP-IDF. This is the recommended API for projects using only BLE (and not classic Bluetooth). Perhaps the lack of response packets is a limitation of the ESP-IDF integration of the NimBLE API. In reviewing the ESP-IDF repository and forums, it seems others have encountered this same behavior. I also ran idp.py menuconfigto look for options that might enable active scanning but didn't find that.

Perhaps someone else has an idea?