Has the format of ble_gap_evt_adv_report_t changed recently?

I have modified code for the Dongle to allow reporting multiple advertising devices, and select one device to connect to the USB/serial port. I can display the 64-bit unit ID and can connect and transfer data in both directions. My device inserts the name of the software in the advertising packet per some Nordic examples, and it shows up on the Android nRF Connect app. That app also shows "Raw Data" where I can clearly see the same field. When I attempt to make use of the name field in the Dongle code, sometimes it shows up, sometimes it's shifted a few bytes, and sometimes I get complete gibberish. From what I read, there is a ble_data_t field named data, with elements p_data that should point to the string, and len that gives the number of bytes. How should I use these to extract the text sent from my device?

Parents
  • Hi,

    There has not been a nRF5 SDK nor SoftDevice release for quite a few years, so there has not been any recent changes. If you can elaborate more on what you do (and also what you have changed if it worked before), I can attempt to understand what the problem is.

    Based on what you write where the data is seemingly sometimes corrupted, two things come to mind. One is some sort of parser error as I do not know how you parse the data, but another possibility is if you restart scanning before the data has been parsed. If that is doen with the same scan buffer it could be that the buffer is updated while or before being parsed.

  • I have these declarations in my code, most of which came from Nordic-provided code:

    static struct
       {
       ble_gap_evt_adv_report_t Adv;
       ble_gap_scan_params_t Scan;
       ble_gap_conn_params_t Conn;
       uint8_t ConnCfgTag;
       uint8_t Name [32];
       }
    Seen [50];
    int NumSeen = 0;

    Within the scan evt handler is this code, with my added code highlighted:

       case NRF_BLE_SCAN_EVT_FILTER_MATCH:
          {
          int i;
          nrf_ble_scan_evt_filter_match_t const * p_filter_match = &(p_scan_evt -> params.filter_match);
          if (NumSeen >= 50) NumSeen = 0;
          if (NumSeen < 50)
             {
             Seen [NumSeen].Adv = *(p_filter_match -> p_adv_report);
             for (int j = 0; j < sizeof Seen [NumSeen].Name - 1; ++j)
                Seen [NumSeen].Name [j] = ((uint8_t *) &Seen [NumSeen].Adv.data.p_data) [j];
             Seen [NumSeen].Name [31] = 0;
             Seen [NumSeen].Scan.extended = 0;
             Seen [NumSeen].Scan.report_incomplete_evts = 0;
             Seen [NumSeen].Scan.active = 1;
             Seen [NumSeen].Scan.filter_policy = 0;
             Seen [NumSeen].Scan.scan_phys = 1;
             Seen [NumSeen].Scan.interval = 160;
             Seen [NumSeen].Scan.window = 80;
             Seen [NumSeen].Scan.timeout = 0;
             Seen [NumSeen].Conn.min_conn_interval = 6; // Minimum Connection Interval in 1.25 ms units
             Seen [NumSeen].Conn.max_conn_interval = 24; // Maximum Connection Interval in 1.25 ms units
             Seen [NumSeen].Conn.slave_latency = 0; // Slave Latency in number of connection events
             Seen [NumSeen].Conn.conn_sup_timeout = 400; // Connection Supervision Timeout in 10 ms units
             Seen [NumSeen].ConnCfgTag = MyConfigTag;
             for (i = 0; i < NumSeen; ++i)
                if (!memcmp (&Seen [NumSeen].Adv.peer_addr, &Seen [i].Adv.peer_addr, sizeof Seen [NumSeen].Adv.peer_addr))
                   break;
             if (i == NumSeen)
                {
                ++NumSeen;
                if (!ShowPeripheralsFlag) ShowPeripherals (1);
                }
             }
          }
          break;

    The Name field is my own addition to the struct (named Seen[] in my code) that records all the info found in the scanning for advertisements. I added the copy here (boldface code above) because it appeared that the .Adv.data was getting corrupted later. Are you suggesting that I might be copying too early, before it's all filled in? I'm just trying to capture the name of the device, as it is set via the sd_ble_gap_device_name_set call within the device's application code. Is there a better way to get that field? The Android nRF Connect app gets it flawlessly, so I know it's there to be harvested.

  • Hi,

    I have several problems with this. Most importantly, you have not fixed th eproblem where your check for "if (name_len == 0)" can never be true as I explained in this post. That must be fixed. But I have general problems with this code and have seen and commented on several issues (and that is without having the full picture). I strongly recommend that you simply use and copy-past from the project I provided in my previosu post, which I have veriified works as expected, extracting both short and full name from addvertising and scan response packets.

  • Now back to this after a couple days' interruption by "life"....

    I had removed the if (name_len == 0) line already, just hadn't updated the copy in the note above. Still, there's surely a clue in that ble_advdata_search returns 0, which would be perfectly reasonable as a flag that the pointer returned is not usable.

    I copy-pasted your code in place of mine, and it behaves exactly the same, which would be expected since it's syntactically identical except for formatting. I started from the same example code you did, apparently.

    Now what? I'm guessing that you're several hours ahead of me and thus about to leave for the weekend.

  • Since you're offline for the weekend, I did a bit more research. I found an example that extracts the name from the same struct, but uses the one passed to nrf_ble_scan_on_ble_evt() rather than the one passed to scan_evt_handler(). Works a treat! Now, how best to synchronize the two. Is it fair game to match up the peer_addr field of the ble_gap_evt_adv_report_t struct, to guarantee the name belongs to that unit?

  • The sample I shared works, but I wonder if ther could be an issue with lifetime fo the moemory you are using (perhaps you re-start scanning before having parced the received advertising packet?). Can you share your whole project so that I get a better picture of the application?

    Edit: I forgot to answer this specfic question:

    SteveHx said:
    nrf_ble_scan_on_ble_evt() rather than the one passed to scan_evt_handler(). Works a treat! Now, how best to synchronize the two. Is it fair game to match up the peer_addr field of the ble_gap_evt_adv_report_t struct, to guarantee the name belongs to that unit?

    Note that you get the same struct on both. But of corse, when using the scan module you filter out some packets (which is the main point of the module), so if you filter out the packets you want for some reason, it would not show up. Also, you have the problem that information can be split across scan response and regular advertising packets. To match that up, you should use the address as you write, yes. That is not handled in the scan module, so it would be up to you.

  • This seems really clumsy and not as designed, but it'll do for now. I still don't understand why the p_adv_report returned in scan_evt_handler() appears to be complete gibberish, but I'll run with this solution for now.

Reply Children
No Data
Related