This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to read RSSI from an specific UUID?

Hello,

I'm implementing an observer/peripheral device that would read the RSSI value from a device with an specific UUID.

I'm aware I can create a rssiCallback function and put it into this function array like this:

static gapRolesCBs_t simpleBLEPeripheral_PeripheralCBs =
{
  peripheralStateNotificationCB,  // Profile State Change Callbacks
  rssiCallback,                           // When a valid RSSI is read from controller (not used by application)
  observerEventCB
};

but of course I think this would detect any RSSI from any advertising device, right?
So, where is the relevant function and file in which I could read the RSSI with precondition checking?

Thanks for your help

Best regards,
Ernesto


  

  • Hey Ernesto,

    If you are wanting to filter based on advertising alone you can do this within the GAP_DEVICE_INFO_EVENT in your APPeventCB().

    For example in the simpleBLEObserver project, if you look at SimpleBLEObserverEventCB() in simpleBLEObserver.c you will see a case for the GAP_DEVICE_INFO_EVENT. When you receive this event pEvent will be of type gapDeviceInfoEvent_t (gapObserverRoleEvent_t is a union of many types). If you look into this gapDeviceInfoEvent_t (in gap.h) type there is an rssi field. There are also fields in that struct (pEvtData, addr, etc) that give you access to the adv data among other info that you can filter on. You can do similar operations from other peripheral based projects as well.

    I think rssi callback function you have already set up is for reading the RSSI of packets rx'ed while in a connection. Since peripheral devices are spec'd to only handle one connection at a time then you will know exactly which device you are getting RSSI data for and won't need any real filtering.

    -Matt

  • At the moment, I have that callback and the following code in that function:

    case GAP_DEVICE_INFO_EVENT:
          {
            if ( DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
            {
                
              if ( simpleBLEFindSvcUuid( MY_UUID,
                                        pEvent->deviceInfo.pEvtData,
                                        pEvent->deviceInfo.dataLen ) )
              {
                simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType );
                int8 rssi = pEvent->deviceInfo.rssi;
                //turn on or off a bit (a field with notify property in a service)if the RSSI is within a certain range        
              }
            }

    Are both of them necessary in order to keep the filtering and RSSI read, or can I take out the rssi callback I showed in my first post?

  • If you only want to filter on UUID in adv data then you only need the GAP_DEVICE_INFO_EVENT code.

    If you need to read RSSI values once you're in a connection (which it doesn't look like you doing this) then you can use the call back function to get RSSI values from packets rx'ed from connected devices.

    They each handle different link layer states (scanning or connected).

    -Matt

  • Ok, after some effort. I have finally managed to have my observer not miss any of the advertisements packets of the peripheral/broadcaster (i.e. I receive several GAP_DEVICE_INFO_EVENT). Inside this case, I have the following code:

            if ( DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
            {
              
              if ( simpleBLEFindSvcUuid( MY_UUID,
                                        pEvent->deviceInfo.pEvtData,
                                        pEvent->deviceInfo.dataLen ) )
              {
                simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType );
                int8 currentRSSIThreshold = -40;
           

            // then I'm getting a threshold value from a field my GATTprofile. Then I compare the current RSSI with this threshold


               if (currentRSSIThreshold <= pEvent->deviceInfo.rssi ){  // if broadcaster/peripheral is in range
                
                 uint8 inRange = 1;
                 uint8 outRange = !inRange;        
                    observerProfile_SetParameter( OBSERVER_IN_RANGE, sizeof( uint8 ), &inRange );
                    observerProfile_SetParameter( OBSERVER_OUT_RANGE, sizeof( uint8 ), &outRange );               
               } else { //do the opposite... }

    However, even though I made sure that my program is going inside the if statement by setting breakpoints there. When using the LightBlue app and go to this In_Range field (which has the notify property, so it should notify whenever it has been changed), no value is set hence I receive no notifications.
    Whereas, when I do this inside the rssiCallback (that function that only takes the rssi as the parameter), then this actually modifies the In_Range field and it notifies me all the time.


    Assuming that I correctly created my GATT profile, where would the error lie?