B4A Class [IoT] BeaconParser - Discover iBeacons and Eddystone beacons

The BeaconParser class parses the advertising data that is sent by BLE beacons.
It supports iBeacons, Eddystone UID and Eddystone URL formats.

Note that this class is also compatible with B4i. However it will not detect iBeacons due to the way those beacons are handled in iOS.

You do not need to connect to the beacon. All the important information is delivered in the advertising data.
Call BleManager2.Scan2(Null, True) to start scanning. The second parameter (AllowDuplicates) means that it will "find" the same devices again and again.

B4A example:

upload_2015-12-7_13-4-49.png


B4i example:

upload_2015-12-7_13-5-13.png


The distance is not accurate enough to be useful.

The main method of BeaconParser is Parse. You should call it from the DeviceFound sub:
B4X:
Sub Manager_DeviceFound (Name As String, Id As String, AdvertisingData As Map, RSSI As Double)
   Dim beacon1 As Beacon = Parser.Parse(AdvertisingData, RSSI)
   If beacon1 <> Null Then
    'a beacon was discovered.
    'find the beacon type based on the BeaconType field.
  Select beacon1.BeaconType
     Case Parser.TypeiBeacon
       Dim ib As iBeacon = beacon1.SpecificData
       Log($"iBeacon: ${ib.uuid} (${ib.major}/${ib.minor})"$)
     Case Parser.TypeEddystoneUID
       Dim euid As EddystoneUID = beacon1.SpecificData
       lLog($"Eddystone UID: ${euid.Namespace}:${euid.Instance}"$)
     Case Parser.TypeEddystoneURL
       Dim eurl As EddystoneURL = beacon1.SpecificData
      Log($"Eddystone URL: ${eurl.url}"$)
   End Select
   End If
End Sub

New version of BeaconParser was uploaded. It requires BLE v1.20+: https://www.b4x.com/android/forum/threads/ble-2-bluetooth-low-energy.59937/#post-377705

It fixes an issue when there are multiple records with the same type.
 

Attachments

  • BeaconParser_B4i.zip
    7.2 KB · Views: 339
  • BeaconParser_B4A.zip
    7.3 KB · Views: 448
Last edited:

luke2012

Well-Known Member
Licensed User
I'm not familiar with this devices but I did a test:

- Tested device name: "Skybeacon"

- Tested with 2 Android phones:
On the left of the attached pic: "Nexus 4" with BLE Scanner App (light blue)
On the right of the attached pic: "Motorola Moto G (2° gen) with the B4A BeaconParser

Result (see attached pic):
BLE Scanner find the beacon in few seconds and keep the beacon info on the screen.
B4A BeaconParser display the beacon info later than BLE scanner and keep the info only for few seconds: after this short interval the beacon info disappears (blank screen).

Note: I'm trying to understand if it only a display bug or a manager bug...

P.S.
thanks in advance for any help or reply :)
 

Attachments

  • IMG_20161020_091623.jpg
    IMG_20161020_091623.jpg
    110.7 KB · Views: 143
Last edited:

luke2012

Well-Known Member
Licensed User
Hi @freedom2000 .
Your App (iTag Alarm) have the same behaviour of BeaconParser. The Skybeacon is displayed (only one time) for few seconds and than disappear (empty screen).
Note that the Skybeacon is near the phone (<1mt).

So it seem that the only app the constantly keep the skybeacon info on the screen is BLE Scanner:

https://play.google.com/store/apps/details?id=com.macdom.ble.blescanner&hl=it

But my target is to implement an app that (always) keep the beacon (skybeacon) info on the screen.
To be onest, actually I don't known why BeaconParser doesn't keep the beacon (Skybeacon) info on the screen. Is related to my beacon settings ? My beacon hardware ? Or others things ?

P.S.
@Erel says: "The second parameter (AllowDuplicates) means that it will "find" the same devices again and again."

My doubt is that this parameter isn't set to AllowDuplicates by default within the attached demo (I have to verify).
 
Last edited:

freedom2000

Well-Known Member
Licensed User
Hi @freedom2000 .
Your App (iTag Alarm) have the same behaviour of BeaconParser. The Skybeacon is displayed (only one time) for few seconds and than disappear (empty screen).
Note that the Skybeacon is near the phone (<1mt).

So it seem that the only app the constantly keep the skybeacon info on the screen is BLE Scanner:

https://play.google.com/store/apps/details?id=com.macdom.ble.blescanner&hl=it

But my target is to implement an app that (always) keep the beacon (skybeacon) info on the screen.
To be onest, actually I don't known why BeaconParser doesn't keep the beacon (Skybeacon) info on the screen. Is related to my beacon settings ? My beacon hardware ? Or others things ?

P.S.
@Erel says: "The second parameter (AllowDuplicates) means that it will "find" the same devices again and again."

My doubt is that this parameter isn't set to AllowDuplicates by default within the attached demo (I have to verify).

I do believe that allow duplicate is set to true in my app...

Another very good App is nRFConnect. It's a little complex but extremely powerful to help you discover the bowels of our device !
 

luke2012

Well-Known Member
Licensed User
I do believe that allow duplicate is set to true in my app...

Another very good App is nRFConnect. It's a little complex but extremely powerful to help you discover the bowels of our device !

If allow duplicate is set to true, the beacon parser should keep the beacon info on the screen ?
 

luke2012

Well-Known Member
Licensed User
How to monitor the distance dinamically ?
I'm monitoring the distance within the SetDistance Sub (called by StateChanged Sub when the Timer1_Tick is raised) but the distance that I can see is always the same (beacon.distance) also when the device / beacon is moving away.

B4X:
Private Sub SetDistance(lbl As Label, beacon As Beacon)
    lbl.Text = $"Distance: $1.1{beacon.distance} meters"$
    ToastMessageShow($"Distance: $1.1{beacon.distance} meters"$, True)
End Sub
 

luke2012

Well-Known Member
Licensed User
This is the known distance. It will be difficult to see accurate results.
Thanks for your reply Erel. I known that it's difficult to see accurare results.

If is possible, I wish to known:

1) Is it correct that the known distance doesn't change (the known distance is always the same of the first detected distance) also if I move the device away ? In this case the known distance should grow.

2) Is there a possibility to improve the detected distance accuracy? For example improving the code / class or improving the beacon hw / sw side ?

3) My target is to track (in real time and with a good accuracy) the distance between two devices (a Smartphone and a smaller hw device). Is Beacon the right solution for this target ?

4) If the answer to the question 3 is "yes", there are beacons that provide more accuracy and more reliability compared to the beacon that I'm testing: "skybeacon" Shenzhen Sky Electronics Manufactory (model number 20150427)

Thanks in advance for your reply.
 

Erel

Administrator
Staff member
Licensed User
This is the code that calculates the distance:
B4X:
'based on this answer: http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing
Private Sub CalculateDistance(tx As Int, rssi As Double) As Double
   If rssi = 0 Then Return -1
   Dim ratio As Double = rssi / tx
   If ratio < 1 Then
     Return Power(ratio, 10)
   Else
     Return 0.89976 * Power(ratio, 7.7095) + 0.111
   End If
End Sub
The distance should change when the rssi change.
You can improve it by calibrating the three constants.

http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing
 

luke2012

Well-Known Member
Licensed User
This is the code that calculates the distance:
B4X:
'based on this answer: http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing
Private Sub CalculateDistance(tx As Int, rssi As Double) As Double
   If rssi = 0 Then Return -1
   Dim ratio As Double = rssi / tx
   If ratio < 1 Then
     Return Power(ratio, 10)
   Else
     Return 0.89976 * Power(ratio, 7.7095) + 0.111
   End If
End Sub
The distance should change when the rssi change.
You can improve it by calibrating the three constants.

http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing

Thanks for your suggestion Erel! Very useful for me.
 

luke2012

Well-Known Member
Licensed User
Starting from this sample (Class) I need to monitor the distance also if the App isn't in foreground.
Which is the simpler solution to implement this ?

Thanks in advance for your reply.
 

luke2012

Well-Known Member
Licensed User
Add another Service to the project and call Service.StartForeground. You will also need to acquire a partial lock with PhoneWakeState.

Please start a new thread for further discussion.

Thanks Erel. So I have to move all the Beacon related code from the Starter service to the new (Foregroud) service ?
 

luke2012

Well-Known Member
Licensed User
Only devices with Android 4.3+ and Bluetooth 4.0 works with this BLE Manager object right?

If this is true, is there a way to exclude the devices that doesn't have the above requirements directly on the Play Store putting a manifest code?

Thanks in advance for any help.
 

dataware

Member
Licensed User
hi, am trying to make some another functions on the example, but, when i put a condition, the program is run really slowly, i dont know if is the "If" condition on the SetDistance function what i put it, cause i must identify some especific beacon and his especific range, like this example:

B4X:
Private Sub SetDistance(lbl As Label, beacon As Beacon)
    lbl.Text = $"Distance: $1.1{beacon.distance} meters"$
    If beacon.Distance < 0.05 Then
        If beacon.uniqueid.CompareTo("Some Id")==0 True Then
            ToastMessageShow("Blue", False)
        Else
            If beacon.uniqueid.CompareTo("Some Other Id")==0 True Then
                 ToastMessageShow("Red", False)
            End If
        End If
    End If
End Sub

i hope someone can help me with an optimization, thanks.
 
Top