Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
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

NUS Central and Peripheral MAC Filter and Whitelist

Hello everyone,

I developed an application that makes it possible to scan devices and retransmit your advertisements. In addition to enabling the connection with peripheral devices, it also allows the connection to a central device, retransmitting data via the NUS service from the central to the peripherals.

Currently, I filter the devices that I want to retransmit the advertising through the following code in the scan_evt_handler() function.

case NRF_BLE_SCAN_EVT_NOT_FOUND:
            if(memcmp("\xac\x31\x38",&p_scan_evt->params.p_not_found->peer_addr.addr[3],3) == 0){
            ...
            }

As I understand it, I'm actually receiving all the advertising but I only perform the retransmission if the condition of the device starting with MAC 38:31:AC is satisfied, correct? For performance reasons would it be better to use a MAC filter so that this filtering is done in Softdevice or would there be no difference? If there is a difference, I want to carry out this implementation, but I haven't seen any example that the implementation is carried out from a MAC range.

In the filter implementations I found, I see that the filter is applied to a specific MAC, but what I want is to listen to all devices that start with MAC 38:31:AC, is it possible to do this? If yes, could you provide me with an example?

My other doubt would be in relation to retransmission through NUS. Is it possible when retransmitting data from the peripheral or central, choose the device I'm going to connect to and send the data through the MAC of this device? I saw some examples doing this by the connection identifier, but I would like to know who to direct the data to according to the MAC, as I will not maintain a connection with peripherals, I just connect to send data. In short, I would like to establish a connection and send data only if the device has a specific MAC. 

How to do this, can you give me an example?

I'm open to suggestions, I'd like to do this with the best possible performance, either with a whitelist or filters. Thank you very much.

I'm using nRF 52840, Softdevice S140, nRF5 SDK 17.0.2 and my application has a  nus central + nus + beacon.

Parents
  • Hi,

    In the filter implementations I found, I see that the filter is applied to a specific MAC, but what I want is to listen to all devices that start with MAC 38:31:AC, is it possible to do this? If yes, could you provide me with an example?

    That is not possible with the SoftDevice whitelisting, and also whitelisting is about controlling connections, so it does not do what you want in any case. So you need to continue to parse the Bluetooth address on your own, as you are doing.

    In short, I would like to establish a connection and send data only if the device has a specific MAC. 

    Here it sounds like you only want to establish connections with devices with a specific address? If so, that is precisely what whitelisting is for. If you just want to filter a specific address, then I suggest you look at this post. Whitelisting is similar both in central and peripheral roles.

  • Einar, as I said the filter was working, but the filter applied previously was related to the UUID, I tried to add a filter referring to the address, and I'm not successful! I've checked it several times, I've also tried using examples and I can't get the address filter to work!

    Could you take a look at my code to see what's going on? I don't get any error, I find the mac searched for filter through the scan but I never get a match. I've tried running examples and I can never get connection using the address filter, I found several cases with the same problem... is this a bug in sdk 17.0.2?

  • Hello, i have updates!

    As I had suggested, this is a bug from SDK 17.0.2. I switched my application to SDK 17.1.0 without changing anything in my code, and the address filter started working.

  • The only question that remained for me was to understand the difference between a connection coming from the central to the peripheral and a connection coming from the peripheral to the central.

    Because when I connect through nRF Connect on my central, everything works fine, but when I connect from the central to the peripheral corresponding to the filter, I get an error when I try for stop the scan module to change the MAC.

    Why does this happen when the connection comes from the central to the peripheral, and not when a peripheral (smartphone) is connected to the central?

    As I understand it, when I make a connection with a peripheral through the central, the scan module is automatically paused, but when I make the connection through nRF Connect with the central, the scan is not paused, why does this occur? Can I prevent the scan from being paused when requesting a connection through the central?

  • The central and peripheral plays completely different roles when it comes to establishing a connection in BLE.

    Thabet said:
    but when I connect from the central to the peripheral corresponding to the filter, I get an error when I try for stop the scan module to change the MAC.

    I assume this is the remaining issue you are referring to. Can you explain where you get this error? Which function returns an error, and what is the error code? Perhaps it is related to "NRF_ERROR_INVALID_STATE, when calling the stop scan function inside the beacon function." which you wrote some posts back? That does not really say much though (both as beacon is a advertiser activity and not scan related), and I have no knowledge of the code or where you got this. In sum, please elaborate with detailed references to your code.

    Thabet said:
    As I understand it, when I make a connection with a peripheral through the central, the scan module is automatically paused, but when I make the connection through nRF Connect with the central, the scan is not paused, why does this occur?

    There should not be any dependency on the scan module here. It could be that your application behaves differently depending on which peripheral it has connected to perhaps? That is only speculation.

    In general you need to show your source code and relate the questions and observations to the code as there is not much I can say without such a link.

    Thabet said:
    Can I prevent the scan from being paused when requesting a connection through the central?

    The SoftDevice always stops scanning after providing a scan report to the application, and sd_ble_gap_scan_start() needs to be called again. The scan module does this in most cases, see the last lines in the implementation of nrf_ble_scan_on_adv_report(). However, scanning is stopped when connecting to a peripheral (see implementation of nrf_ble_scan_connect_with_target()). In this case scanning is never automatically started unless the application do that (typically by calling nrf_ble_scan_start()).

  • I assume this is the remaining issue you are referring to. Can you explain where you get this error? Which function returns an error, and what is the error code? Perhaps it is related to "NRF_ERROR_INVALID_STATE, when calling the stop scan function inside the beacon function." which you wrote some posts back? That does not really say much though (both as beacon is a advertiser activity and not scan related), and I have no knowledge of the code or where you got this. In sum, please elaborate with detailed references to your code.

    You're right, the error is this and it occurs where you mentioned, I know the classic beacon has nothing to do with scanning, but my "beacon" repeats the device advertisement, assuming MAC devices, so I need to stop scanning and change the device mac. So I get or error when I stop scan because the scan was already paused inside nrf_ble_scan_connect_with_target(). By the way, thanks for the information, it was very important to know that.

    The SoftDevice always stops scanning after providing a scan report to the application, and sd_ble_gap_scan_start() needs to be called again. The scan module does this in most cases, see the last lines in the implementation of nrf_ble_scan_on_adv_report(). However, scanning is stopped when connecting to a peripheral (see implementation of nrf_ble_scan_connect_with_target()). In this case scanning is never automatically started unless the application do that (typically by calling nrf_ble_scan_start()).

    I actually fixed the problem by calling sd_ble_gap_scan_start(). Is there any flag or variable that I can check to know the status of the scan module? Something to check if scan == start or scan == stop?

  • Hi,

    That makes sense.

    The scan module does not have any state information about if it is scanning or not. You could add this if you like. If so it should be part of nrf_ble_scan_t, and you need to update it whenever it changes. It is normally predictable when this changes though, so it should not be needed. Also, if you get NRF_ERROR_INVALID_STATE when you try to stop scanning you know why, so you could simply ignore that error.

    If you want to ignore specific errors because you know this does not represent an actual error, you typically do something like this:

        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }

Reply
  • Hi,

    That makes sense.

    The scan module does not have any state information about if it is scanning or not. You could add this if you like. If so it should be part of nrf_ble_scan_t, and you need to update it whenever it changes. It is normally predictable when this changes though, so it should not be needed. Also, if you get NRF_ERROR_INVALID_STATE when you try to stop scanning you know why, so you could simply ignore that error.

    If you want to ignore specific errors because you know this does not represent an actual error, you typically do something like this:

        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }

Children
  • Thanks for the suggestion Einar, I'll do it! I think we can close this topic, because my doubts will now be more related to the exchange of data between devices after establishing the connection, I know you don't like it and it's not organized for users if we change the subject a lot over the tickets.

    So if necessary, I'll open another ticket. Thanks again, you really brought me important information!

Related