<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Identifying unprovisioned mesh device</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/48729/identifying-unprovisioned-mesh-device</link><description>I&amp;#39;m struggling with how to properly identify an unprovisioned mesh device. Basically when i scan for unprovisioned devices from my iOS app, I&amp;#39;d like for only our devices to show up, not any random mesh device. I&amp;#39;m still struggling to understand all the</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 16 Jul 2019 08:03:39 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/48729/identifying-unprovisioned-mesh-device" /><item><title>RE: Identifying unprovisioned mesh device</title><link>https://devzone.nordicsemi.com/thread/198625?ContentTypeID=1</link><pubDate>Tue, 16 Jul 2019 08:03:39 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c012028d-8fb5-4859-b19d-eb47e54f055d</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;Hi Nicklas,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Advertising it exclusivly related to the Generic Access Profile, hence the&amp;nbsp;sd_ble_gap_-&amp;nbsp; prefix to all SoftDevice functions related to advertisment.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A node, i.e. an unprovisioned device, can be provisioned through the Advertisment bearer or the GATT bearer using the Mesh Provisioning Service. I assumed that you would be able to receive both the PB-ADV and PB-GATT advertisement data with iOS devices as the nRF device will interleave these, see quote below:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If PB-ADV is supported, an unprovisioned Provisioning Server that supports PB-GATT has to interleave the connectable advertising for PB-GATT with the Unprovisioned Device beacon (see Section 3.9.2).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;However, it could be that iOS devices filter out advertisment packets with the ADV type used by the&amp;nbsp;Unprovisioned Device beacon. So adding a custom ID to the scan response data for the PB-GATT advertisment data is the way to go.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Best regards&lt;/p&gt;
&lt;p&gt;Bjørn&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Identifying unprovisioned mesh device</title><link>https://devzone.nordicsemi.com/thread/196914?ContentTypeID=1</link><pubDate>Fri, 05 Jul 2019 20:59:18 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2bd3d603-49d8-4425-a967-10173a4b8a12</guid><dc:creator>jnicklas</dc:creator><description>&lt;p&gt;I&amp;#39;ve finally understood why and how this works. What I&amp;#39;m receiving is in fact not the GAP advertising data, but rather the GATT scan response. As per the mesh spec (Table 7.3) the service data in the GATT information only contains the Device UUID (first 16 bytes) and the OOB information (last 2 bytes), which matches exactly what I receive. I&amp;#39;ve been unable to find any reference to reading GAP data in iOS, I wonder if it&amp;#39;s even supported at all. Looking at the CoreBluetooth API, it seems there is no other way of searching for devices.&lt;/p&gt;
&lt;p&gt;So by looking into GATT, I found out that the application can override `mesh_adv_data_set` and that this allows me to hook into the advertised data. I&amp;#39;ve added some manufacture data in the scan response which allows me to identify the device.&lt;/p&gt;
&lt;p&gt;Something like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;typedef struct __attribute((packed))
{
    uint16_t product_id;
    uint16_t app_version;
} lc_mesh_manuf_data_t;

void mesh_adv_data_set(uint16_t service_uuid, const uint8_t * p_service_data, uint8_t length)
{
    // [...]

    /* The application may freely set anything into the scan response data. */
    ble_advdata_t srdata;
    memset(&amp;amp;srdata, 0, sizeof(srdata));
    srdata.name_type = BLE_ADVDATA_FULL_NAME;

    ble_advdata_manuf_data_t manuf_data;

    lc_mesh_manuf_data_t manuf_data_data;

    manuf_data_data.product_id = APP_PRODUCT_ID;
    manuf_data_data.app_version = APP_VERSION;

    manuf_data.company_identifier = APP_COMPANY_ID;
    manuf_data.data.p_data = (uint8_t *) &amp;amp;manuf_data_data;
    manuf_data.data.size = sizeof(manuf_data_data);

    srdata.p_manuf_specific_data = &amp;amp;manuf_data;

    // [...]
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This seems to work quite well. And I can read out this information in iOS like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="golang"&gt;extension MeshNetworkScanner: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        // FIXME: handle central manager being unavailable
    }

    func centralManager(_ central: CBCentralManager,
                        didDiscover peripheral: CBPeripheral,
                        advertisementData: [String: Any],
                        rssi RSSI: NSNumber) {
        
        if let serviceData = advertisementData[CBAdvertisementDataManufacturerDataKey] as! Data? {
            if serviceData.count &amp;gt;= 6 {
                let manufacturerId = UInt16(littleEndian: serviceData[0...1].withUnsafeBytes { $0.pointee })
                let productId = UInt16(littleEndian: serviceData[2...3].withUnsafeBytes { $0.pointee })
                
                // we&amp;#39;ll check that this is an actual LightCore device
                if manufacturerId == MeshNetwork.companyId &amp;amp;&amp;amp; productId == MeshNetwork.productId {
                    let newNode = UnprovisionedMeshNode(withPeripheral: peripheral, andAdvertisementDictionary: advertisementData, RSSI: RSSI)
                    delegate?.nodeDiscovered(newNode)
                }
            }
        }
    }
}
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Identifying unprovisioned mesh device</title><link>https://devzone.nordicsemi.com/thread/196318?ContentTypeID=1</link><pubDate>Wed, 03 Jul 2019 14:31:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b92aecee-6e4f-4e48-9da7-b337f1d3bf9a</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;I am no iOS or Swift expert, but I would assume that you will get the content of the advertisment packet as an array of bytes. The advertisment packet will consist of several AD structures&lt;/p&gt;
&lt;p&gt;&lt;img src="https://devzone.nordicsemi.com/resized-image/__size/320x240/__key/support-attachments/beef5d1b77644c448dabff31668f3a47-f1ab8ec90cb14b198e38ff64406b051b/pastedimage1562164123466v2.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;Each of these ad structures start with a byte indicating the length of the structure. The second byte is the type, which will be 0x16 for the Mesh beacon structure. So once youve foudn the correct structure you can fin the&amp;nbsp;URI Hash which will be the the four last octets in that structure.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://devzone.nordicsemi.com/resized-image/__size/320x240/__key/support-attachments/beef5d1b77644c448dabff31668f3a47-f1ab8ec90cb14b198e38ff64406b051b/pastedimage1562163817375v1.png" alt=" " /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Identifying unprovisioned mesh device</title><link>https://devzone.nordicsemi.com/thread/194940?ContentTypeID=1</link><pubDate>Wed, 26 Jun 2019 16:22:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ccacb810-d451-458f-abb7-69637884fd87</guid><dc:creator>jnicklas</dc:creator><description>&lt;p&gt;Hi Bj&amp;oslash;rn,&lt;/p&gt;
&lt;p&gt;Thanks for the reply, yes I&amp;#39;ve added a device URI (though I&amp;#39;m not quite sure if its content matters, or is supposed to have any specific format, I&amp;#39;ve just picked something random). So I think this is supposed to be included in the device beacon.&lt;/p&gt;
&lt;p&gt;What I don&amp;#39;t know is how to extract and compare this information in iOS. In other words, when I have discovered a device via the CentralManager in iOS, I will need to do something to compare the data that I receive against the URI that I&amp;#39;ve set when I call `mesh_provisionee_prov_start`, but how do I do this? Since I just receive a random jumble of bytes, part of which *may* be the hashed URI, it&amp;#39;s really hard to tell.&lt;/p&gt;
&lt;p&gt;As I wrote in the original post, the nRF Connect app does extract this information, but its source code is not open source, so I can&amp;#39;t check how it does this, and I&amp;#39;ve been unable to find any documentation. But maybe you could check the source code for nRF Connect on how it does this. I&amp;#39;ve posted a screenshot from nRF where it shows Device UUID and OOB information below.&lt;/p&gt;
&lt;p&gt;Thank you for the help,&lt;/p&gt;
&lt;p&gt;/Jonas&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="nRF Connect showing Device UUID etc" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/IMG_5F00_0150.png" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Identifying unprovisioned mesh device</title><link>https://devzone.nordicsemi.com/thread/194938?ContentTypeID=1</link><pubDate>Wed, 26 Jun 2019 16:06:21 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:676a5013-348e-43b1-8e77-09bdda3db671</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;Hi Jonas,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Yes, you are correct. The Device UUID will be unique per device, so placing a hash of a common identifier in the unprovisioned beacon packet may be the way to go.&amp;nbsp;Have you added the URI data to the example? The pointer to the URI data is passed to&amp;nbsp;mesh_provisionee_prov_start() in the&amp;nbsp;start() function in main(). By defualt this is set to NULL.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void start(void)
{
    rtt_input_enable(app_rtt_input_handler, RTT_INPUT_POLL_PERIOD_MS);

    if (!m_device_provisioned)
    {
        static const uint8_t static_auth_data[NRF_MESH_KEY_SIZE] = STATIC_AUTH_DATA;
        mesh_provisionee_start_params_t prov_start_params =
        {
            .p_static_data    = static_auth_data,
            .prov_complete_cb = provisioning_complete_cb,
            .prov_device_identification_start_cb = device_identification_start_cb,
            .prov_device_identification_stop_cb = NULL,
            .prov_abort_cb = provisioning_aborted_cb,
            .p_device_uri = NULL
        };
        ERROR_CHECK(mesh_provisionee_prov_start(&amp;amp;prov_start_params));
    }

    const uint8_t *p_uuid = nrf_mesh_configure_device_uuid_get();
    UNUSED_VARIABLE(p_uuid);
    __LOG_XB(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;Device UUID &amp;quot;, p_uuid, NRF_MESH_UUID_SIZE);

    ERROR_CHECK(mesh_stack_start());

    hal_led_mask_set(LEDS_MASK, LED_MASK_STATE_OFF);
    hal_led_blink_ms(LEDS_MASK, LED_BLINK_INTERVAL_MS, LED_BLINK_CNT_START);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Best regards&lt;br /&gt; Bjørn&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Identifying unprovisioned mesh device</title><link>https://devzone.nordicsemi.com/thread/194459?ContentTypeID=1</link><pubDate>Mon, 24 Jun 2019 18:32:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c568905b-ddd7-4a27-b847-7d733eb266d2</guid><dc:creator>jnicklas</dc:creator><description>&lt;p&gt;Hi Bj&amp;oslash;rn,&lt;/p&gt;
&lt;p&gt;Thanks for the response :) From what I understand, the device UUID is unique per device, but what I&amp;#39;m trying to do is identify a &amp;quot;class&amp;quot; of devices, not a specific device. I&amp;#39;m building a product and an accompanying iOS app, when a client purchases the product and downloads the iOS app, I want only this specific product to show up in the provisionable list, but I obviously don&amp;#39;t know which exact device they have purchased, if that makes sense?&lt;/p&gt;
&lt;p&gt;Section 3.9.1 is exactly the part of the mesh spec that I screenshotet in my original question, where the unprovisioned device beacon comes out to 23 bytes according to the layout given in the screenshot. What I haven&amp;#39;t been able to figure out is how to extract this information in iOS, and then how to use this infromation to identify a class of devices.&lt;/p&gt;
&lt;p&gt;All the best,&lt;/p&gt;
&lt;p&gt;/Jonas&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Identifying unprovisioned mesh device</title><link>https://devzone.nordicsemi.com/thread/194435?ContentTypeID=1</link><pubDate>Mon, 24 Jun 2019 15:06:47 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:25c13866-26b1-47e3-8809-a29a817876bf</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;HI Jnicklas,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;cant you identify your devices by looking at the 16-byte Device UUID field in the&amp;nbsp;Unprovisioned Device beacon advertisment packet?,(see section&amp;nbsp;3.9.2 Unprovisioned Device beacon in the v1.0.1 spec)&lt;/p&gt;
&lt;p&gt;Best regards&lt;/p&gt;
&lt;p&gt;Bjørn&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>