This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Active scanning with enabled filter causes sending SCAN_REQ to every advertiser

Hi everybody,

I saw topics with similar naming like mine, but none of them actually describes my issue.

I develop some simple scanner and advertiser solution.

On advertiser side I've implemented ADV_SCAN_IND and SCAN_RSP packets. In ADV_SCAN_IND I've put some custom UUID to easy find my advertisers if there is many BLE devices around. In SCAN_RSP there is my custom data (0xFF - manufacture data).

On scanner side I've turned on active scanning with turned on filtering by UUID (same solution as it is in some sample code).

I've observed some strange behaviors:

1. Scanner side invokes "filter match" callback when ADV_SCAN_IND packet is received with correct UUID...and then "filter no match" callback when SCAN_RSP packet is received which contains my own custom data. To avoid this would I need to put UUID data also in SCAN_RSP packet? Or maybe some scanner configuration should be changed?

2. Even if in ADV_SCAN_IND there is no matching data (no UUID field), my scanner sends SCAN_REQ anyway...I think is pointless to waste time for sending SCAN_REQ for different advertisers.

- Can I configure my scanner in a way that it will send SCAN_REQ only to devices which contain correct data in first ADV_SCAN_IND?

- Can I avoid invoking "no filter match" callback for devices which have correct data only in ADV_SCAN_IND packets?

Best regards,

Adam

Parents
  • Hi Edvin,

    thank you for your fully explainable response! :) I'm quite new in BLE and in Nordic products, so some obvious stuff is still new to me.

    About sending scan response - you're right, I forgot that time between receiving first advertising data and sending SCAN_REQ / CONNECT_IND is quite tight (150us).

    Right now I've implemented something similar as you suggested. I've put simple machine state and "match flags" in "no_match" callback and if data in both received packets is ok, I can determine if it's my peripherals.

    Just to make sure - if my device is connectable, I have to send CONNECT_IND after receiving first packet, Trying to establish connection in callback from receiving second packet is pointless, right? Then advertiser would need to send at least 2 adv packets, right?

    From the advertiser device I have small issue with whitelists.

    I would like to response for SCAN_REQ only to "my" centrals. But central can send in SCAN_REQ only it's own random address. During every scanning "session" scanner will have different (random) address. Let's say I can send private static address of central during "initial phase", but it gives me nothing when scanner will send random address in SCAN_REQ.

    How to properly handle it? I saw some article to make pairing and use IRK keys to resolve random address into private address, but I couldn't find any example for that.

    For any help thanks in advance!

    Adam

  • Kedlov said:
    Just to make sure - if my device is connectable, I have to send CONNECT_IND after receiving first packet, Trying to establish connection in callback from receiving second packet is pointless, right? Then advertiser would need to send at least 2 adv packets, right?

    Typically, the flow is that you receive an advertising packet, with or without a scan response (that doesn't really matter). Then you decide whether you want to connect to it or not. If you want to connect, you will call the API that will connect to the device (which depends on what SDK version you are using. Are you using the nRF5 SDK, or are you using NCS?). When this is called, the scanner will then wait for the next advertising packet from that device, and it will send the connect_ind immediately after receiving the advertisement. 

    This next part is also dependent on what SDK you are using, but the principle will be the same.

    In BLE you have several address types. In private addresses, you can have resolvable or unresolvable addresses. Resolvable addresses means that there is an IRK (Identity Resolving Key), which you can use to figure out whether a seemingly random address actually belongs to a known device or not. I don't know exactly how that works on the mathematical level, but the Bluetooth Low Energy stack supports this. 

    What are you using to scan? Is it another nRF chip, a phone? Or something else?

    And what SDK version are you using?

    Best regards,

    Edvin

  • Thanks for reply!

    I'm using NCS updated to v2.0.0, based on some example projects generated from "Create a new application from sample" and now I explore most common use case scenarios which would also adjust to my projects' requirements.

    Some of this requirements is:

    - use radio as short as possible (connectionless beacon mode)

    - get information is central node really received data or we should repeat it (data will change in some intervals but we shouldn't miss any of that data)

    - from central point of view - sends scan requests only to "my" peripherals

    - from peripheral point of view - sends scan responses only to "my" centrals

    In BLE you have several address types. In private addresses, you can have resolvable or unresolvable addresses. Resolvable addresses means that there is an IRK (Identity Resolving Key), which you can use to figure out whether a seemingly random address actually belongs to a known device or not.

    Exactly this is what i needed to know, thanks! Actually after tests with some example which used bonding, when my peripheral was bonded with scanner, I was able to see its static private address, so I think that bonding and storing IRK keys are essentials which I need in my peripheral to know which scanner is "my" scanner.

    What are you using to scan? Is it another nRF chip, a phone? Or something else?

    I will use nRF chip, for few tests I've used phone but scanning performance was too low for me. With scanner on nRF52840 I think I was able to catch almost very first advertising packet every time. Time from starting advertising to send scan response was around 4-15ms (probably depends of current scanning and adv channel)

    Thanks to your reply, now I know how to figure out if scan request comes from my scanner.

    Now the issue is following:

    Let's say I have few hundreds peripheral nodes. Creating bond (by manually clicking some buttons for pairing mode) only to generate IRK keys would be time consuming. Let's say I could program this keys through wired connection during production or change the roles and central for few seconds would broadcast it's IRK key to all sensors in close proximity. I saw OOB pairing by using NFC and external antenna but we want to cut piece price for every peripheral node.

    After this long "preamble" here comes my question ;)

    Is it possible to manually create/save IRK keys which will be later used to resolve scanner private address?

    For any help, thanks in advance!

    Adam

  • Kedlov said:

    - from central point of view - sends scan requests only to "my" peripherals

    - from peripheral point of view - sends scan responses only to "my" centrals

    No. That is not possible.

    So if you plan to not bond the devices, how do you plan to transfer the IRK? And why do you need to change addresses in the first place? I am not sure whether or not you can set this manually in NCS, but even if you can, you would only be able to change the address every ~15 minutes, or in that order. Not between every advertising packet. If you are not connecting, I don't see what sort of security this adds.

    To put you on track, you can use the configuration CONFIG_BT_PRIVACY=y to enable address switching. You can also try to see if you figure out how the IRK is set using 

    int bt_id_create(bt_addr_le_t *addr, uint8_t *irk) from id.c. I think you can use this, and set the IRK to whatever you like (look at the declaration of bt_id_create() in bluetooth.h. As long as it is not all zeroes (or a null pointer), you just need the scanner to be aware of the same IRK.

    BR,

    Edvin

Reply
  • Kedlov said:

    - from central point of view - sends scan requests only to "my" peripherals

    - from peripheral point of view - sends scan responses only to "my" centrals

    No. That is not possible.

    So if you plan to not bond the devices, how do you plan to transfer the IRK? And why do you need to change addresses in the first place? I am not sure whether or not you can set this manually in NCS, but even if you can, you would only be able to change the address every ~15 minutes, or in that order. Not between every advertising packet. If you are not connecting, I don't see what sort of security this adds.

    To put you on track, you can use the configuration CONFIG_BT_PRIVACY=y to enable address switching. You can also try to see if you figure out how the IRK is set using 

    int bt_id_create(bt_addr_le_t *addr, uint8_t *irk) from id.c. I think you can use this, and set the IRK to whatever you like (look at the declaration of bt_id_create() in bluetooth.h. As long as it is not all zeroes (or a null pointer), you just need the scanner to be aware of the same IRK.

    BR,

    Edvin

Children
  • Hi,

    So if you plan to not bond the devices, how do you plan to transfer the IRK?

    During post production process when I will have all around 32 or 64 peripherals on big PCB "matrix" and program it with UART/SPI through test pads and spring needles. Also bond information would need to be stored in central, but central should handle hundreds of peripherals so CONFIG_BT_KEYS_OVERWRITE_OLDEST would need to be enabled. If I would perform paring+bonding with every peripheral it will be time consuming, it's not only about the time to exchange data and create keys, but also to check every peripheral if the bond has been created. Another option would be to switch roles and advertise IRK key from central to all nodes in close area for few seconds, but there will be no confirmation from every node that it received IRK key.

    And why do you need to change addresses in the first place?

    I think I was misunderstood - I don't need to change address, I've just observed on nRF sniffer that scanner address has changed few times. Maybe at happened only for scanner on mobile phone, but it would be also good for my scanner based on nRF528xx chip to change from time to time.

    To put you on track, you can use the configuration CONFIG_BT_PRIVACY=y to enable address switching.

    I already have it turned on, anyway thanks for that hint Slight smile

    Not between every advertising packet. If you are not connecting, I don't see what sort of security this adds.

    Sure, I don't want to change address of peripherals, I didn't write anything like that :) I only wanted to send scan requests only to my peripherals (based on advertising data in first packet) and from peripherals side I want to send scan response only to my central. It's not about security, I just want to reduce cases when somebody will come with smartphone in range of central and peripherals, will try to act as central/peripheral and will disrupt my data flow. Of course if somebody will come with SDR, then only encrypted connection may help but storing keys for several hundreds of nodes may take a "little" of flash memory ;)

    int bt_id_create(bt_addr_le_t *addr, uint8_t *irk) from id.c. I think you can use this, and set the IRK to whatever you like (look at the declaration of bt_id_create() in bluetooth.h.

    Great! Probably I will use it or something similar for central to get my own IRK key and distribute it to peripherals.

    Anyway I think now everything is clear and I will somehow handle it in the code.

    Thank you for help and I think I can close this case :)

Related