This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to read URI hash on Un-provisioned Device Beacon with Android app

Hi,

I am trying to modify the Android nRF Mesh app to filter un-provisioned devices with URI hash contained on un-provisioned device beacon.

My question is how I can read the URI hash (4 bytes) in Android app.

I tried to check URI hash in onScanResult callback of ScannerRepository in ScannerRepository.java.

But, I can't find where the URI hash is stored.
I investigated the ScanResult passed as "result", but could not find anything related to URI hash.

It would be great if someone could advise me on how to get the URI hash on Android, using Android-nRF-Mesh-Library.



The mesh node I use is a nRF52840DK with Light Switch Client sample in nRF5 SDK for Mesh ver5.0.0. 
And, the phone which runs nRF Mesh app is Google Pixel 3a with Android ver.11.
I cloned nRF Mesh app from the repo below, and build it on Android Studio 4.2.1.

Also, I am sure that the URI hash does exist on un-provisioned device beacon from the node.
I checked the content of the un-provisioned device beacon with nRF Sniffer for Bluetooth.

I am not an expert of Bluetooth mesh and Android.
This is my first time to post something here.
I would really appreciate any advice.
Parents
  • Hi, check here line number 168 will return a beacon if it's advertised and returns an UnprovisionedBeacon. However is there a reason for not using the Mesh Provisioning Service to filter unprovisioned devices?

  • Hi Roshan-san,
    Thank you so much for the reply!

    I have already checked updateScannerLiveData(), but I could not get the URI hash because the beaconData is null.
    I added the Log.d output to the method like below:
        private void updateScannerLiveData(final ScanResult result) {
            Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- start!");
            Log.d("glamo-log", "result is " + result.toString());
            final ScanRecord scanRecord = result.getScanRecord();
            if (scanRecord != null) {
                Log.d("glamo-log", "scanRecord is " + scanRecord.toString());
                if (scanRecord.getBytes() != null) {
                    Log.d("glamo-log", "scanRecord.getBytes() is " + scanRecord.getBytes().toString());
                    final byte[] beaconData = mMeshManagerApi.getMeshBeaconData(scanRecord.getBytes());
                    if (beaconData != null) {
                        Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- with beacon data!");
                        Log.d("glamo-log", "beaconData is " + beaconData.toString());
                        mScannerLiveData.deviceDiscovered(result, mMeshManagerApi.getMeshBeacon(beaconData));
                    } else {
                        Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- without beacon data!");
                        mScannerLiveData.deviceDiscovered(result);
                    }
                    Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- device found!");
                    mScannerStateLiveData.deviceFound();
                }
            }
            Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- leave!");
        }
    And I got the output like this:

    ... D/glamo-log: ScannerRepository.updateScannerLiveData() -- start!
    ... D/glamo-log: result is ScanResult{device=C6:32:88:E4:FB:CB, scanRecord=ScanRecord [advertiseFlags=6, serviceUuids=[00001827-0000-1000-8000-00805f9b34fb], manufacturerSpecificData=null, serviceData={00001827-0000-1000-8000-00805f9b34fb=[-10, -113, -68, 115, -13, 106, 72, -118, -117, -5, -28, -120, 50, -58, 85, 126, 0, 0]}, txPowerLevel=-2147483648, deviceName=nRF5x Mesh Switch], rssi=-51, timestampNanos=27762065700561, eventType=17, primaryPhy=1, secondaryPhy=0, advertisingSid=255, txPower=127, periodicAdvertisingInterval=0}
    ... D/glamo-log: scanRecord is ScanRecord [advertiseFlags=6, serviceUuids=[00001827-0000-1000-8000-00805f9b34fb], manufacturerSpecificData=null, serviceData={00001827-0000-1000-8000-00805f9b34fb=[-10, -113, -68, 115, -13, 106, 72, -118, -117, -5, -28, -120, 50, -58, 85, 126, 0, 0]}, txPowerLevel=-2147483648, deviceName=nRF5x Mesh Switch]
    ... D/glamo-log: scanRecord.getBytes() is [B@ea1bea5
    ... D/glamo-log: ScannerRepository.updateScannerLiveData() -- without beacon data!
    ... D/glamo-log: ScannerRepository.updateScannerLiveData() -- device found!
    ... D/glamo-log: ScannerRepository.updateScannerLiveData() -- leave!



    Anyway, I didn't know that the Mesh Provisioning Service can be used to filter unprovisioned devices.
    I will study about it, and report the result here.
    But, it would be great if you could give me more information like the API to filter unprovisioned devices.

    Thanks.
Reply
  • Hi Roshan-san,
    Thank you so much for the reply!

    I have already checked updateScannerLiveData(), but I could not get the URI hash because the beaconData is null.
    I added the Log.d output to the method like below:
        private void updateScannerLiveData(final ScanResult result) {
            Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- start!");
            Log.d("glamo-log", "result is " + result.toString());
            final ScanRecord scanRecord = result.getScanRecord();
            if (scanRecord != null) {
                Log.d("glamo-log", "scanRecord is " + scanRecord.toString());
                if (scanRecord.getBytes() != null) {
                    Log.d("glamo-log", "scanRecord.getBytes() is " + scanRecord.getBytes().toString());
                    final byte[] beaconData = mMeshManagerApi.getMeshBeaconData(scanRecord.getBytes());
                    if (beaconData != null) {
                        Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- with beacon data!");
                        Log.d("glamo-log", "beaconData is " + beaconData.toString());
                        mScannerLiveData.deviceDiscovered(result, mMeshManagerApi.getMeshBeacon(beaconData));
                    } else {
                        Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- without beacon data!");
                        mScannerLiveData.deviceDiscovered(result);
                    }
                    Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- device found!");
                    mScannerStateLiveData.deviceFound();
                }
            }
            Log.d("glamo-log", "ScannerRepository.updateScannerLiveData() -- leave!");
        }
    And I got the output like this:

    ... D/glamo-log: ScannerRepository.updateScannerLiveData() -- start!
    ... D/glamo-log: result is ScanResult{device=C6:32:88:E4:FB:CB, scanRecord=ScanRecord [advertiseFlags=6, serviceUuids=[00001827-0000-1000-8000-00805f9b34fb], manufacturerSpecificData=null, serviceData={00001827-0000-1000-8000-00805f9b34fb=[-10, -113, -68, 115, -13, 106, 72, -118, -117, -5, -28, -120, 50, -58, 85, 126, 0, 0]}, txPowerLevel=-2147483648, deviceName=nRF5x Mesh Switch], rssi=-51, timestampNanos=27762065700561, eventType=17, primaryPhy=1, secondaryPhy=0, advertisingSid=255, txPower=127, periodicAdvertisingInterval=0}
    ... D/glamo-log: scanRecord is ScanRecord [advertiseFlags=6, serviceUuids=[00001827-0000-1000-8000-00805f9b34fb], manufacturerSpecificData=null, serviceData={00001827-0000-1000-8000-00805f9b34fb=[-10, -113, -68, 115, -13, 106, 72, -118, -117, -5, -28, -120, 50, -58, 85, 126, 0, 0]}, txPowerLevel=-2147483648, deviceName=nRF5x Mesh Switch]
    ... D/glamo-log: scanRecord.getBytes() is [B@ea1bea5
    ... D/glamo-log: ScannerRepository.updateScannerLiveData() -- without beacon data!
    ... D/glamo-log: ScannerRepository.updateScannerLiveData() -- device found!
    ... D/glamo-log: ScannerRepository.updateScannerLiveData() -- leave!



    Anyway, I didn't know that the Mesh Provisioning Service can be used to filter unprovisioned devices.
    I will study about it, and report the result here.
    But, it would be great if you could give me more information like the API to filter unprovisioned devices.

    Thanks.
Children
  • I would recommend using the Mesh Provisioning Service to filter the device because this is the simplest approach as the scanner will handle the filtering for you and this is how we have implemented the sample app as well. I will have to take a look at the UnprovisionedBeacon but i am busy with some other tasks right now. 

  • Thank you for the advice.  I will learn about the Mesh Provisioning Service.

    Here is the screen shot of unprovisioned device beacon captured with nRF Sniffer, just in case you need it.

  • Hi Roshan-san,

    I investigated Mesh Profile 1.0.1, section 7.1 Mesh Provisioning Service.
    Is this the right thing to study the Mesh Provisioning Service you mentioned?
    Please let me know if I have misunderstood something.

    Still, I am not sure if we can read URI or URI hash using the Mesh Provisioning Service.
    I am afraid that the URI or URI hash is not available in the characteristics of the service.

    Anyway, I think that the Mesh Provisioning Service does not help us to filter unprovisioned devices in our use case.

    Let's assume that we have 20 rooms, and there are 5 unprovisioned devices and a provisioner in each room.
    Each provisioner needs to find 5 devices in the same room and provision them.

    If a provisioner need to use the Mesh Provisioning Service to find the 5 devices, it needs to connect to GATT servers on many devices.
    It is a waste of time and resources, isn't it?

    This is why we need to use URI hash to filter the unprovisioned devices.
    The URI hash is carried on a unprovisioned device beacon.
    So, if we assign the same URI to the devices and the provisioner in the same room,
    the provisioner can determine which devices to provision when it receives unprovisioned device beacons.
    The provisioner does not need to make any unnecessary connections to the devices which have different URIs.

    I would appreciate any advice.
    How can I read URI hash on unprovisioned device beacon in Android app using Android nRF Mesh Library?
  • Hi, thanks for the detailed explanation. So I think you have misunderstood me here. You don't need to connect to a device to filter it. You can filter the unprovisioned devices based on the service the device is advertising with. Once you provision the device it will start advertising with a Mesh Proxy Service with which you can filter provisioned devices from unprovisioned devices. If you refer to our sample we use the mesh provisioning service to filter the unprovisioning service to filter the unprovisioned  mesh devices and also Mesh Proxy Service to filter the provisioned mesh devices. You don't need to use the beacons here at all in my opinion. Please check here this should let you understand what's happenning. We set the Mesh Provisioning Service UUID and this filters out and returns only the unprovisioned mesh devices allowing you to connect and provision them etc.

  • Hi Roshan-san,

    Thank you again for your kind reply.

    Now I understand what you said. You are trying to explain the way to select provisioned nodes from many devices using service UUID. I know it is not so difficult. Unprovisioned devices have the Mesh Provisioning Service, and provisioned nodes usually have the Mesh Proxy Service. This is what you are explaining, isn't it?
    Again, please let me know if I have misunderstood something.

    But, unfortunately, it is not what we want to do.
    Probably, I wrote something ambiguous or misleading. I am sorry for my poor English or explanation.

    Please let me explain what we want to do, using the use case I wrote above.
    At the beginning, all devices are unprovisioned.
    And, a provisioner needs to find the unprovisioned devices in the same room.

    To achieve this, we want to use the URI hash carried on unprovisioned device beacon.
    In this case, we assign a URI to the devices and the provisioner in the same room.
    (Of course, we use different URIs for different rooms.)

    I hope this clarifies what we want to do.
    Please ask me anything, if you need.


    Also, I found a similar Q&A in DevZone.
    Identifying unprovisioned mesh device
    In the Q&A, they also use URI to select a particular set of unprovisioned devices.
    They use a provisioner on iOS, but the issue is very close to my question.
    Please refer the Q&A, if something I wrote is unclear.


    Anyway, I investigated the code you mentioned. The ScanFilter uses service UUIDs, device name, device address, and something related to the service. I am afraid I can't use this to achieve what we want to do.

    It would be great if someone could tell me how I can read URI hash on unprovisioned device beacon in Android app using Android nRF Mesh Library.

    Best regards,
    Toshi

Related