2015-05-13 01:16:11

by Tony DiCola

[permalink] [raw]
Subject: BLE device advertised manufacturer data cached?

Hi all, I'm playing with the latest bluez 5.30 and bluetooth low
energy devices and am noticing that the manufacturer data field from a
device's advertisement data appears to be cached somewhere internally.
I wanted to check if this was expected and see if there was any way to
disable that caching or work around getting back stale manufacturer
data.

For some context I'm using bluez 5.30's dbus API and applied these
patches to make the gatt support non-experimental (so I can run
bluetoothd without the --experimental flag):
https://chromium.googlesource.com/chromiumos/third_party/bluez/+/2b3a91a12c86a5708329edf58d0cea237f319f6f%5E%21/#F0
https://chromium.googlesource.com/chromiumos/third_party/bluez/+/5755965a9944f158dd8aba63655f2b0a414a1f49%5E%21/#F0
However I've also tried it with the stock 5.30 code and the
--experimental flag and see the same results.

For my device I'm using a Nordic nRF51822-based board that I have
control over the firmware and am using it to send custom advertisement
data for my device. In my advertisement data I'm sending manufacturer
data that looks like this: 0x07FFFFFF00000001. This breaks down as
the length of the advertisement section (0x07 bytes), the manufacturer
data advertisement type (0xFF), the testing manufacturer ID (0xFFFF),
and then 4 bytes with a value of 1 (0x00000001).

I see when I enable scanning on an adapter that a device object is
created for my device in bluez's dbus hiearchy. It has a
ManufacturerData field that looks just like what my advertisement
sends, for example here's the output of the device's dbus tree (using
python):

[ /org/bluez/hci0/dev_C5_25_55_09_6A_B1 ]
org.bluez.Device1
Name = UART
Paired = 0
Adapter = /org/bluez/hci0
LegacyPairing = 0
Alias = UART
ManufacturerData = dbus.Dictionary({dbus.UInt16(65535):
dbus.Array([dbus.Byte(0), dbus.Byte(0), dbus.Byte(0), dbus.Byte(1)],
signature=dbus.Signature('y'), variant_level=1)},
signature=dbus.Signature('qv'), variant_level=1)
Connected = 0
UUIDs = dbus.Array([], signature=dbus.Signature('s'), variant_level=1)
Address = C5:25:55:09:6A:B1
Trusted = 0
Blocked = 0

Everything looks great and the manufacturer data is parsed out as I
expect. However the problem is when I have the nRF51822 change the
advertised manufacturer data. For example if I change to
0x07FFFFFF00000002 (so the last 4 bytes change to 0x00000002) I'm not
seeing the updated value in bluez's dbus hierarchy. When I query the
device object's ManufacturerData property I still see the old value
that ends in 1. Even if I sit in a loop querying the value every
second for over a minute I still don't see the updated value (for
reference the nRF51822 is advertising this updated value every
second).

I do notice that if I remove the device from bluez's dbus hiearchy (by
getting its parent adapter and calling RemoveDevice on it) then I do
see the device added back with the current/updated ManufacturerData
property. This makes me think there's something up with the
manufacturer data field getting cached or never being updated.

I wanted to check is this expected behavior, that the manufacturer
data property won't be updated when it changes? If so is there any
clean way to disable this caching or get access to the most recently
seen/up to date manufacturer data field?

Let me know if anything isn't clear or if perhaps I'm doing something
completely wrong. Thanks!

-Tony


2015-05-15 19:00:39

by Tony DiCola

[permalink] [raw]
Subject: Re: BLE device advertised manufacturer data cached?

On Fri, May 15, 2015 at 6:41 AM, Luiz Augusto von Dentz
<[email protected]> wrote:
> Hi Tony,
>
> On Fri, May 15, 2015 at 2:57 PM, Luiz Augusto von Dentz
> <[email protected]> wrote:
>> Hi Tony,
>>
>> On Wed, May 13, 2015 at 11:15 PM, Tony DiCola <[email protected]> wrote:
>>> On Wed, May 13, 2015 at 9:53 AM, Michael Janssen <[email protected]> wrote:
>>>> Hi Tony,
>>>>
>>>> On Tue, May 12, 2015 at 6:16 PM, Tony DiCola <[email protected]> wrote:
>>>>> Hi all, I'm playing with the latest bluez 5.30 and bluetooth low
>>>>> energy devices and am noticing that the manufacturer data field from a
>>>>> device's advertisement data appears to be cached somewhere internally.
>>>>> I wanted to check if this was expected and see if there was any way to
>>>>> disable that caching or work around getting back stale manufacturer
>>>>> data.
>>>>>
>>>>> For some context I'm using bluez 5.30's dbus API and applied these
>>>>> patches to make the gatt support non-experimental (so I can run
>>>>> bluetoothd without the --experimental flag):
>>>>> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/2b3a91a12c86a5708329edf58d0cea237f319f6f%5E%21/#F0
>>>>> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/5755965a9944f158dd8aba63655f2b0a414a1f49%5E%21/#F0
>>>>> However I've also tried it with the stock 5.30 code and the
>>>>> --experimental flag and see the same results.
>>>>>
>>>>> For my device I'm using a Nordic nRF51822-based board that I have
>>>>> control over the firmware and am using it to send custom advertisement
>>>>> data for my device. In my advertisement data I'm sending manufacturer
>>>>> data that looks like this: 0x07FFFFFF00000001. This breaks down as
>>>>> the length of the advertisement section (0x07 bytes), the manufacturer
>>>>> data advertisement type (0xFF), the testing manufacturer ID (0xFFFF),
>>>>> and then 4 bytes with a value of 1 (0x00000001).
>>>>>
>>>>> I see when I enable scanning on an adapter that a device object is
>>>>> created for my device in bluez's dbus hiearchy. It has a
>>>>> ManufacturerData field that looks just like what my advertisement
>>>>> sends, for example here's the output of the device's dbus tree (using
>>>>> python):
>>>>>
>>>>> [ /org/bluez/hci0/dev_C5_25_55_09_6A_B1 ]
>>>>> org.bluez.Device1
>>>>> Name = UART
>>>>> Paired = 0
>>>>> Adapter = /org/bluez/hci0
>>>>> LegacyPairing = 0
>>>>> Alias = UART
>>>>> ManufacturerData = dbus.Dictionary({dbus.UInt16(65535):
>>>>> dbus.Array([dbus.Byte(0), dbus.Byte(0), dbus.Byte(0), dbus.Byte(1)],
>>>>> signature=dbus.Signature('y'), variant_level=1)},
>>>>> signature=dbus.Signature('qv'), variant_level=1)
>>>>> Connected = 0
>>>>> UUIDs = dbus.Array([], signature=dbus.Signature('s'), variant_level=1)
>>>>> Address = C5:25:55:09:6A:B1
>>>>> Trusted = 0
>>>>> Blocked = 0
>>>>>
>>>>> Everything looks great and the manufacturer data is parsed out as I
>>>>> expect. However the problem is when I have the nRF51822 change the
>>>>> advertised manufacturer data. For example if I change to
>>>>> 0x07FFFFFF00000002 (so the last 4 bytes change to 0x00000002) I'm not
>>>>> seeing the updated value in bluez's dbus hierarchy. When I query the
>>>>> device object's ManufacturerData property I still see the old value
>>>>> that ends in 1. Even if I sit in a loop querying the value every
>>>>> second for over a minute I still don't see the updated value (for
>>>>> reference the nRF51822 is advertising this updated value every
>>>>> second).
>>>>>
>>>>> I do notice that if I remove the device from bluez's dbus hiearchy (by
>>>>> getting its parent adapter and calling RemoveDevice on it) then I do
>>>>> see the device added back with the current/updated ManufacturerData
>>>>> property. This makes me think there's something up with the
>>>>> manufacturer data field getting cached or never being updated.
>>>>>
>>>>> I wanted to check is this expected behavior, that the manufacturer
>>>>> data property won't be updated when it changes? If so is there any
>>>>> clean way to disable this caching or get access to the most recently
>>>>> seen/up to date manufacturer data field?
>>>>>
>>>>> Let me know if anything isn't clear or if perhaps I'm doing something
>>>>> completely wrong. Thanks!
>>>>>
>>>>> -Tony
>>>>> --
>>>>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>>>>> the body of a message to [email protected]
>>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>>
>>>> BlueZ doesn't update the Advertising Data unless there is an active
>>>> discovery client or the device is already paired. Is the device
>>>> paired, or are you calling the StartDiscovery method on the device?
>>>>
>>>> Note that the link layer does not need to send duplicate reports (the
>>>> same device address) to the host even if the advertising data changes.
>>>> This is acceptable behavior per the spec, as outlined in Vol 6, Part
>>>> B, Section 4.4.3 "Scanning State": "The advertising data may change;
>>>> advertising data or scan response data is not considered significant
>>>> when determining duplicate advertising reports."
>>>>
>>>> --
>>>> M Janssen
>>>
>>> Thanks for the reply! Yeah I've called StartDiscovery on an adapter
>>> so I should see advertisement data come in (and in practice I do see
>>> my deivce show up after StartDiscovery is called).
>>>
>>> However I'm not pairing or connecting to the device because I'd like
>>> to read advertisement data from multiple devices at the same time.
>>> I'm thinking of a scenario kind of like Apple's iBeacon or Google's
>>> UriBeacon but for reading sensors, where each device/sensor puts its
>>> data into an advertisement packet (just using some custom manufacturer
>>> data field for now) and broadcasts that reading to any device
>>> listening for advertisements.
>>>
>>> Here's pseudo code of what I'm doing:
>>> - Setup my device firmware to start advertising custom manufacturer
>>> data with value 1 (for example).
>>> - Get BLE adapter org.bluez.Adapter1 object.
>>> - Set adapter's Powered property to True/1 to make sure it's powered up.
>>> - Call adapter's StartDiscovery function to start listening for advertisements.
>>> - See that my device is added to the bluez dbus tree with the
>>> org.bluez.Device1 interface.
>>> - Verify the device's ManufacturerData property has the expected value of 1.
>>> - Change my device's firmware to advertise custom manufacturer data
>>> with value 2.
>>> - Sit in a loop reading the bluez device's ManufacturerData property
>>> every second.
>>
>> Are you still discovering at this point? If yes then we might have a
>> bug as it should be updating the data if provided it is not the same.
>>
>>> - See that the ManufacturerData from bluez still shows the old value of 1.
>>>
>>> Here's the pseudo code of something that works, but feels pretty hacky
>>> to have to remove the device to get an updated value:
>>> - Setup my device firmware to start advertising custom manufacturer
>>> data with value 1 (for example).
>>> - Get BLE adapter org.bluez.Adapter1 object.
>>> - Set adapter's Powered property to True/1 to make sure it's powered up.
>>> - Call adapter's StartDiscovery function to start listening for advertisements.
>>> - See that my device is added to the bluez dbus tree with the
>>> org.bluez.Device1 interface.
>>> - Verify the device's ManufacturerData property has the expected value of 1.
>>> - Change my device's firmware to advertise custom manufacturer data
>>> with value 2.
>>> - Call the adapter's RemoveDevice function to remove the device from
>>> bluez's dbus hierararchy.
>>> - See that my device is added back to the bluez dbus tree again (after
>>> it send another advertisement).
>>> - Verify the device's ManufacturerData property has the new value of 2.
>>
>> Something is not right then.
>
> So I found the problem, please check the last 2 patches I send to the
> mailing list. The second is not exactly by the spec since it might be
> possible to have duplicated entries, even if they have the data, in
> the same report but I doubt anyone would try to do that since the
> space in the AD is very limited, anyway so what it does is detect if
> there already an entry and replace the data which should trigger
> PropertiesChanged(ManufacturerData) signal.
>
>
> --
> Luiz Augusto von Dentz

Oh nice, thanks for taking a look and the quick response! I'll check
out the patch this weekend and see if it resolves the issue. Thanks!

-Tony

2015-05-15 13:41:03

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: BLE device advertised manufacturer data cached?

Hi Tony,

On Fri, May 15, 2015 at 2:57 PM, Luiz Augusto von Dentz
<[email protected]> wrote:
> Hi Tony,
>
> On Wed, May 13, 2015 at 11:15 PM, Tony DiCola <[email protected]> wrote:
>> On Wed, May 13, 2015 at 9:53 AM, Michael Janssen <[email protected]> wrote:
>>> Hi Tony,
>>>
>>> On Tue, May 12, 2015 at 6:16 PM, Tony DiCola <[email protected]> wrote:
>>>> Hi all, I'm playing with the latest bluez 5.30 and bluetooth low
>>>> energy devices and am noticing that the manufacturer data field from a
>>>> device's advertisement data appears to be cached somewhere internally.
>>>> I wanted to check if this was expected and see if there was any way to
>>>> disable that caching or work around getting back stale manufacturer
>>>> data.
>>>>
>>>> For some context I'm using bluez 5.30's dbus API and applied these
>>>> patches to make the gatt support non-experimental (so I can run
>>>> bluetoothd without the --experimental flag):
>>>> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/2b3a91a12c86a5708329edf58d0cea237f319f6f%5E%21/#F0
>>>> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/5755965a9944f158dd8aba63655f2b0a414a1f49%5E%21/#F0
>>>> However I've also tried it with the stock 5.30 code and the
>>>> --experimental flag and see the same results.
>>>>
>>>> For my device I'm using a Nordic nRF51822-based board that I have
>>>> control over the firmware and am using it to send custom advertisement
>>>> data for my device. In my advertisement data I'm sending manufacturer
>>>> data that looks like this: 0x07FFFFFF00000001. This breaks down as
>>>> the length of the advertisement section (0x07 bytes), the manufacturer
>>>> data advertisement type (0xFF), the testing manufacturer ID (0xFFFF),
>>>> and then 4 bytes with a value of 1 (0x00000001).
>>>>
>>>> I see when I enable scanning on an adapter that a device object is
>>>> created for my device in bluez's dbus hiearchy. It has a
>>>> ManufacturerData field that looks just like what my advertisement
>>>> sends, for example here's the output of the device's dbus tree (using
>>>> python):
>>>>
>>>> [ /org/bluez/hci0/dev_C5_25_55_09_6A_B1 ]
>>>> org.bluez.Device1
>>>> Name = UART
>>>> Paired = 0
>>>> Adapter = /org/bluez/hci0
>>>> LegacyPairing = 0
>>>> Alias = UART
>>>> ManufacturerData = dbus.Dictionary({dbus.UInt16(65535):
>>>> dbus.Array([dbus.Byte(0), dbus.Byte(0), dbus.Byte(0), dbus.Byte(1)],
>>>> signature=dbus.Signature('y'), variant_level=1)},
>>>> signature=dbus.Signature('qv'), variant_level=1)
>>>> Connected = 0
>>>> UUIDs = dbus.Array([], signature=dbus.Signature('s'), variant_level=1)
>>>> Address = C5:25:55:09:6A:B1
>>>> Trusted = 0
>>>> Blocked = 0
>>>>
>>>> Everything looks great and the manufacturer data is parsed out as I
>>>> expect. However the problem is when I have the nRF51822 change the
>>>> advertised manufacturer data. For example if I change to
>>>> 0x07FFFFFF00000002 (so the last 4 bytes change to 0x00000002) I'm not
>>>> seeing the updated value in bluez's dbus hierarchy. When I query the
>>>> device object's ManufacturerData property I still see the old value
>>>> that ends in 1. Even if I sit in a loop querying the value every
>>>> second for over a minute I still don't see the updated value (for
>>>> reference the nRF51822 is advertising this updated value every
>>>> second).
>>>>
>>>> I do notice that if I remove the device from bluez's dbus hiearchy (by
>>>> getting its parent adapter and calling RemoveDevice on it) then I do
>>>> see the device added back with the current/updated ManufacturerData
>>>> property. This makes me think there's something up with the
>>>> manufacturer data field getting cached or never being updated.
>>>>
>>>> I wanted to check is this expected behavior, that the manufacturer
>>>> data property won't be updated when it changes? If so is there any
>>>> clean way to disable this caching or get access to the most recently
>>>> seen/up to date manufacturer data field?
>>>>
>>>> Let me know if anything isn't clear or if perhaps I'm doing something
>>>> completely wrong. Thanks!
>>>>
>>>> -Tony
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>>>> the body of a message to [email protected]
>>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>>
>>> BlueZ doesn't update the Advertising Data unless there is an active
>>> discovery client or the device is already paired. Is the device
>>> paired, or are you calling the StartDiscovery method on the device?
>>>
>>> Note that the link layer does not need to send duplicate reports (the
>>> same device address) to the host even if the advertising data changes.
>>> This is acceptable behavior per the spec, as outlined in Vol 6, Part
>>> B, Section 4.4.3 "Scanning State": "The advertising data may change;
>>> advertising data or scan response data is not considered significant
>>> when determining duplicate advertising reports."
>>>
>>> --
>>> M Janssen
>>
>> Thanks for the reply! Yeah I've called StartDiscovery on an adapter
>> so I should see advertisement data come in (and in practice I do see
>> my deivce show up after StartDiscovery is called).
>>
>> However I'm not pairing or connecting to the device because I'd like
>> to read advertisement data from multiple devices at the same time.
>> I'm thinking of a scenario kind of like Apple's iBeacon or Google's
>> UriBeacon but for reading sensors, where each device/sensor puts its
>> data into an advertisement packet (just using some custom manufacturer
>> data field for now) and broadcasts that reading to any device
>> listening for advertisements.
>>
>> Here's pseudo code of what I'm doing:
>> - Setup my device firmware to start advertising custom manufacturer
>> data with value 1 (for example).
>> - Get BLE adapter org.bluez.Adapter1 object.
>> - Set adapter's Powered property to True/1 to make sure it's powered up.
>> - Call adapter's StartDiscovery function to start listening for advertisements.
>> - See that my device is added to the bluez dbus tree with the
>> org.bluez.Device1 interface.
>> - Verify the device's ManufacturerData property has the expected value of 1.
>> - Change my device's firmware to advertise custom manufacturer data
>> with value 2.
>> - Sit in a loop reading the bluez device's ManufacturerData property
>> every second.
>
> Are you still discovering at this point? If yes then we might have a
> bug as it should be updating the data if provided it is not the same.
>
>> - See that the ManufacturerData from bluez still shows the old value of 1.
>>
>> Here's the pseudo code of something that works, but feels pretty hacky
>> to have to remove the device to get an updated value:
>> - Setup my device firmware to start advertising custom manufacturer
>> data with value 1 (for example).
>> - Get BLE adapter org.bluez.Adapter1 object.
>> - Set adapter's Powered property to True/1 to make sure it's powered up.
>> - Call adapter's StartDiscovery function to start listening for advertisements.
>> - See that my device is added to the bluez dbus tree with the
>> org.bluez.Device1 interface.
>> - Verify the device's ManufacturerData property has the expected value of 1.
>> - Change my device's firmware to advertise custom manufacturer data
>> with value 2.
>> - Call the adapter's RemoveDevice function to remove the device from
>> bluez's dbus hierararchy.
>> - See that my device is added back to the bluez dbus tree again (after
>> it send another advertisement).
>> - Verify the device's ManufacturerData property has the new value of 2.
>
> Something is not right then.

So I found the problem, please check the last 2 patches I send to the
mailing list. The second is not exactly by the spec since it might be
possible to have duplicated entries, even if they have the data, in
the same report but I doubt anyone would try to do that since the
space in the AD is very limited, anyway so what it does is detect if
there already an entry and replace the data which should trigger
PropertiesChanged(ManufacturerData) signal.


--
Luiz Augusto von Dentz

2015-05-15 11:57:27

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: BLE device advertised manufacturer data cached?

Hi Tony,

On Wed, May 13, 2015 at 11:15 PM, Tony DiCola <[email protected]> wrote:
> On Wed, May 13, 2015 at 9:53 AM, Michael Janssen <[email protected]> wrote:
>> Hi Tony,
>>
>> On Tue, May 12, 2015 at 6:16 PM, Tony DiCola <[email protected]> wrote:
>>> Hi all, I'm playing with the latest bluez 5.30 and bluetooth low
>>> energy devices and am noticing that the manufacturer data field from a
>>> device's advertisement data appears to be cached somewhere internally.
>>> I wanted to check if this was expected and see if there was any way to
>>> disable that caching or work around getting back stale manufacturer
>>> data.
>>>
>>> For some context I'm using bluez 5.30's dbus API and applied these
>>> patches to make the gatt support non-experimental (so I can run
>>> bluetoothd without the --experimental flag):
>>> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/2b3a91a12c86a5708329edf58d0cea237f319f6f%5E%21/#F0
>>> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/5755965a9944f158dd8aba63655f2b0a414a1f49%5E%21/#F0
>>> However I've also tried it with the stock 5.30 code and the
>>> --experimental flag and see the same results.
>>>
>>> For my device I'm using a Nordic nRF51822-based board that I have
>>> control over the firmware and am using it to send custom advertisement
>>> data for my device. In my advertisement data I'm sending manufacturer
>>> data that looks like this: 0x07FFFFFF00000001. This breaks down as
>>> the length of the advertisement section (0x07 bytes), the manufacturer
>>> data advertisement type (0xFF), the testing manufacturer ID (0xFFFF),
>>> and then 4 bytes with a value of 1 (0x00000001).
>>>
>>> I see when I enable scanning on an adapter that a device object is
>>> created for my device in bluez's dbus hiearchy. It has a
>>> ManufacturerData field that looks just like what my advertisement
>>> sends, for example here's the output of the device's dbus tree (using
>>> python):
>>>
>>> [ /org/bluez/hci0/dev_C5_25_55_09_6A_B1 ]
>>> org.bluez.Device1
>>> Name = UART
>>> Paired = 0
>>> Adapter = /org/bluez/hci0
>>> LegacyPairing = 0
>>> Alias = UART
>>> ManufacturerData = dbus.Dictionary({dbus.UInt16(65535):
>>> dbus.Array([dbus.Byte(0), dbus.Byte(0), dbus.Byte(0), dbus.Byte(1)],
>>> signature=dbus.Signature('y'), variant_level=1)},
>>> signature=dbus.Signature('qv'), variant_level=1)
>>> Connected = 0
>>> UUIDs = dbus.Array([], signature=dbus.Signature('s'), variant_level=1)
>>> Address = C5:25:55:09:6A:B1
>>> Trusted = 0
>>> Blocked = 0
>>>
>>> Everything looks great and the manufacturer data is parsed out as I
>>> expect. However the problem is when I have the nRF51822 change the
>>> advertised manufacturer data. For example if I change to
>>> 0x07FFFFFF00000002 (so the last 4 bytes change to 0x00000002) I'm not
>>> seeing the updated value in bluez's dbus hierarchy. When I query the
>>> device object's ManufacturerData property I still see the old value
>>> that ends in 1. Even if I sit in a loop querying the value every
>>> second for over a minute I still don't see the updated value (for
>>> reference the nRF51822 is advertising this updated value every
>>> second).
>>>
>>> I do notice that if I remove the device from bluez's dbus hiearchy (by
>>> getting its parent adapter and calling RemoveDevice on it) then I do
>>> see the device added back with the current/updated ManufacturerData
>>> property. This makes me think there's something up with the
>>> manufacturer data field getting cached or never being updated.
>>>
>>> I wanted to check is this expected behavior, that the manufacturer
>>> data property won't be updated when it changes? If so is there any
>>> clean way to disable this caching or get access to the most recently
>>> seen/up to date manufacturer data field?
>>>
>>> Let me know if anything isn't clear or if perhaps I'm doing something
>>> completely wrong. Thanks!
>>>
>>> -Tony
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>>> the body of a message to [email protected]
>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>> BlueZ doesn't update the Advertising Data unless there is an active
>> discovery client or the device is already paired. Is the device
>> paired, or are you calling the StartDiscovery method on the device?
>>
>> Note that the link layer does not need to send duplicate reports (the
>> same device address) to the host even if the advertising data changes.
>> This is acceptable behavior per the spec, as outlined in Vol 6, Part
>> B, Section 4.4.3 "Scanning State": "The advertising data may change;
>> advertising data or scan response data is not considered significant
>> when determining duplicate advertising reports."
>>
>> --
>> M Janssen
>
> Thanks for the reply! Yeah I've called StartDiscovery on an adapter
> so I should see advertisement data come in (and in practice I do see
> my deivce show up after StartDiscovery is called).
>
> However I'm not pairing or connecting to the device because I'd like
> to read advertisement data from multiple devices at the same time.
> I'm thinking of a scenario kind of like Apple's iBeacon or Google's
> UriBeacon but for reading sensors, where each device/sensor puts its
> data into an advertisement packet (just using some custom manufacturer
> data field for now) and broadcasts that reading to any device
> listening for advertisements.
>
> Here's pseudo code of what I'm doing:
> - Setup my device firmware to start advertising custom manufacturer
> data with value 1 (for example).
> - Get BLE adapter org.bluez.Adapter1 object.
> - Set adapter's Powered property to True/1 to make sure it's powered up.
> - Call adapter's StartDiscovery function to start listening for advertisements.
> - See that my device is added to the bluez dbus tree with the
> org.bluez.Device1 interface.
> - Verify the device's ManufacturerData property has the expected value of 1.
> - Change my device's firmware to advertise custom manufacturer data
> with value 2.
> - Sit in a loop reading the bluez device's ManufacturerData property
> every second.

Are you still discovering at this point? If yes then we might have a
bug as it should be updating the data if provided it is not the same.

> - See that the ManufacturerData from bluez still shows the old value of 1.
>
> Here's the pseudo code of something that works, but feels pretty hacky
> to have to remove the device to get an updated value:
> - Setup my device firmware to start advertising custom manufacturer
> data with value 1 (for example).
> - Get BLE adapter org.bluez.Adapter1 object.
> - Set adapter's Powered property to True/1 to make sure it's powered up.
> - Call adapter's StartDiscovery function to start listening for advertisements.
> - See that my device is added to the bluez dbus tree with the
> org.bluez.Device1 interface.
> - Verify the device's ManufacturerData property has the expected value of 1.
> - Change my device's firmware to advertise custom manufacturer data
> with value 2.
> - Call the adapter's RemoveDevice function to remove the device from
> bluez's dbus hierararchy.
> - See that my device is added back to the bluez dbus tree again (after
> it send another advertisement).
> - Verify the device's ManufacturerData property has the new value of 2.

Something is not right then.


--
Luiz Augusto von Dentz

2015-05-13 20:15:17

by Tony DiCola

[permalink] [raw]
Subject: Re: BLE device advertised manufacturer data cached?

On Wed, May 13, 2015 at 9:53 AM, Michael Janssen <[email protected]> wrote:
> Hi Tony,
>
> On Tue, May 12, 2015 at 6:16 PM, Tony DiCola <[email protected]> wrote:
>> Hi all, I'm playing with the latest bluez 5.30 and bluetooth low
>> energy devices and am noticing that the manufacturer data field from a
>> device's advertisement data appears to be cached somewhere internally.
>> I wanted to check if this was expected and see if there was any way to
>> disable that caching or work around getting back stale manufacturer
>> data.
>>
>> For some context I'm using bluez 5.30's dbus API and applied these
>> patches to make the gatt support non-experimental (so I can run
>> bluetoothd without the --experimental flag):
>> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/2b3a91a12c86a5708329edf58d0cea237f319f6f%5E%21/#F0
>> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/5755965a9944f158dd8aba63655f2b0a414a1f49%5E%21/#F0
>> However I've also tried it with the stock 5.30 code and the
>> --experimental flag and see the same results.
>>
>> For my device I'm using a Nordic nRF51822-based board that I have
>> control over the firmware and am using it to send custom advertisement
>> data for my device. In my advertisement data I'm sending manufacturer
>> data that looks like this: 0x07FFFFFF00000001. This breaks down as
>> the length of the advertisement section (0x07 bytes), the manufacturer
>> data advertisement type (0xFF), the testing manufacturer ID (0xFFFF),
>> and then 4 bytes with a value of 1 (0x00000001).
>>
>> I see when I enable scanning on an adapter that a device object is
>> created for my device in bluez's dbus hiearchy. It has a
>> ManufacturerData field that looks just like what my advertisement
>> sends, for example here's the output of the device's dbus tree (using
>> python):
>>
>> [ /org/bluez/hci0/dev_C5_25_55_09_6A_B1 ]
>> org.bluez.Device1
>> Name = UART
>> Paired = 0
>> Adapter = /org/bluez/hci0
>> LegacyPairing = 0
>> Alias = UART
>> ManufacturerData = dbus.Dictionary({dbus.UInt16(65535):
>> dbus.Array([dbus.Byte(0), dbus.Byte(0), dbus.Byte(0), dbus.Byte(1)],
>> signature=dbus.Signature('y'), variant_level=1)},
>> signature=dbus.Signature('qv'), variant_level=1)
>> Connected = 0
>> UUIDs = dbus.Array([], signature=dbus.Signature('s'), variant_level=1)
>> Address = C5:25:55:09:6A:B1
>> Trusted = 0
>> Blocked = 0
>>
>> Everything looks great and the manufacturer data is parsed out as I
>> expect. However the problem is when I have the nRF51822 change the
>> advertised manufacturer data. For example if I change to
>> 0x07FFFFFF00000002 (so the last 4 bytes change to 0x00000002) I'm not
>> seeing the updated value in bluez's dbus hierarchy. When I query the
>> device object's ManufacturerData property I still see the old value
>> that ends in 1. Even if I sit in a loop querying the value every
>> second for over a minute I still don't see the updated value (for
>> reference the nRF51822 is advertising this updated value every
>> second).
>>
>> I do notice that if I remove the device from bluez's dbus hiearchy (by
>> getting its parent adapter and calling RemoveDevice on it) then I do
>> see the device added back with the current/updated ManufacturerData
>> property. This makes me think there's something up with the
>> manufacturer data field getting cached or never being updated.
>>
>> I wanted to check is this expected behavior, that the manufacturer
>> data property won't be updated when it changes? If so is there any
>> clean way to disable this caching or get access to the most recently
>> seen/up to date manufacturer data field?
>>
>> Let me know if anything isn't clear or if perhaps I'm doing something
>> completely wrong. Thanks!
>>
>> -Tony
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
> BlueZ doesn't update the Advertising Data unless there is an active
> discovery client or the device is already paired. Is the device
> paired, or are you calling the StartDiscovery method on the device?
>
> Note that the link layer does not need to send duplicate reports (the
> same device address) to the host even if the advertising data changes.
> This is acceptable behavior per the spec, as outlined in Vol 6, Part
> B, Section 4.4.3 "Scanning State": "The advertising data may change;
> advertising data or scan response data is not considered significant
> when determining duplicate advertising reports."
>
> --
> M Janssen

Thanks for the reply! Yeah I've called StartDiscovery on an adapter
so I should see advertisement data come in (and in practice I do see
my deivce show up after StartDiscovery is called).

However I'm not pairing or connecting to the device because I'd like
to read advertisement data from multiple devices at the same time.
I'm thinking of a scenario kind of like Apple's iBeacon or Google's
UriBeacon but for reading sensors, where each device/sensor puts its
data into an advertisement packet (just using some custom manufacturer
data field for now) and broadcasts that reading to any device
listening for advertisements.

Here's pseudo code of what I'm doing:
- Setup my device firmware to start advertising custom manufacturer
data with value 1 (for example).
- Get BLE adapter org.bluez.Adapter1 object.
- Set adapter's Powered property to True/1 to make sure it's powered up.
- Call adapter's StartDiscovery function to start listening for advertisements.
- See that my device is added to the bluez dbus tree with the
org.bluez.Device1 interface.
- Verify the device's ManufacturerData property has the expected value of 1.
- Change my device's firmware to advertise custom manufacturer data
with value 2.
- Sit in a loop reading the bluez device's ManufacturerData property
every second.
- See that the ManufacturerData from bluez still shows the old value of 1.

Here's the pseudo code of something that works, but feels pretty hacky
to have to remove the device to get an updated value:
- Setup my device firmware to start advertising custom manufacturer
data with value 1 (for example).
- Get BLE adapter org.bluez.Adapter1 object.
- Set adapter's Powered property to True/1 to make sure it's powered up.
- Call adapter's StartDiscovery function to start listening for advertisements.
- See that my device is added to the bluez dbus tree with the
org.bluez.Device1 interface.
- Verify the device's ManufacturerData property has the expected value of 1.
- Change my device's firmware to advertise custom manufacturer data
with value 2.
- Call the adapter's RemoveDevice function to remove the device from
bluez's dbus hierararchy.
- See that my device is added back to the bluez dbus tree again (after
it send another advertisement).
- Verify the device's ManufacturerData property has the new value of 2.

Does that help clarify the usage? Thanks!

2015-05-13 16:53:44

by Michael Janssen

[permalink] [raw]
Subject: Re: BLE device advertised manufacturer data cached?

Hi Tony,

On Tue, May 12, 2015 at 6:16 PM, Tony DiCola <[email protected]> wrote:
> Hi all, I'm playing with the latest bluez 5.30 and bluetooth low
> energy devices and am noticing that the manufacturer data field from a
> device's advertisement data appears to be cached somewhere internally.
> I wanted to check if this was expected and see if there was any way to
> disable that caching or work around getting back stale manufacturer
> data.
>
> For some context I'm using bluez 5.30's dbus API and applied these
> patches to make the gatt support non-experimental (so I can run
> bluetoothd without the --experimental flag):
> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/2b3a91a12c86a5708329edf58d0cea237f319f6f%5E%21/#F0
> https://chromium.googlesource.com/chromiumos/third_party/bluez/+/5755965a9944f158dd8aba63655f2b0a414a1f49%5E%21/#F0
> However I've also tried it with the stock 5.30 code and the
> --experimental flag and see the same results.
>
> For my device I'm using a Nordic nRF51822-based board that I have
> control over the firmware and am using it to send custom advertisement
> data for my device. In my advertisement data I'm sending manufacturer
> data that looks like this: 0x07FFFFFF00000001. This breaks down as
> the length of the advertisement section (0x07 bytes), the manufacturer
> data advertisement type (0xFF), the testing manufacturer ID (0xFFFF),
> and then 4 bytes with a value of 1 (0x00000001).
>
> I see when I enable scanning on an adapter that a device object is
> created for my device in bluez's dbus hiearchy. It has a
> ManufacturerData field that looks just like what my advertisement
> sends, for example here's the output of the device's dbus tree (using
> python):
>
> [ /org/bluez/hci0/dev_C5_25_55_09_6A_B1 ]
> org.bluez.Device1
> Name = UART
> Paired = 0
> Adapter = /org/bluez/hci0
> LegacyPairing = 0
> Alias = UART
> ManufacturerData = dbus.Dictionary({dbus.UInt16(65535):
> dbus.Array([dbus.Byte(0), dbus.Byte(0), dbus.Byte(0), dbus.Byte(1)],
> signature=dbus.Signature('y'), variant_level=1)},
> signature=dbus.Signature('qv'), variant_level=1)
> Connected = 0
> UUIDs = dbus.Array([], signature=dbus.Signature('s'), variant_level=1)
> Address = C5:25:55:09:6A:B1
> Trusted = 0
> Blocked = 0
>
> Everything looks great and the manufacturer data is parsed out as I
> expect. However the problem is when I have the nRF51822 change the
> advertised manufacturer data. For example if I change to
> 0x07FFFFFF00000002 (so the last 4 bytes change to 0x00000002) I'm not
> seeing the updated value in bluez's dbus hierarchy. When I query the
> device object's ManufacturerData property I still see the old value
> that ends in 1. Even if I sit in a loop querying the value every
> second for over a minute I still don't see the updated value (for
> reference the nRF51822 is advertising this updated value every
> second).
>
> I do notice that if I remove the device from bluez's dbus hiearchy (by
> getting its parent adapter and calling RemoveDevice on it) then I do
> see the device added back with the current/updated ManufacturerData
> property. This makes me think there's something up with the
> manufacturer data field getting cached or never being updated.
>
> I wanted to check is this expected behavior, that the manufacturer
> data property won't be updated when it changes? If so is there any
> clean way to disable this caching or get access to the most recently
> seen/up to date manufacturer data field?
>
> Let me know if anything isn't clear or if perhaps I'm doing something
> completely wrong. Thanks!
>
> -Tony
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

BlueZ doesn't update the Advertising Data unless there is an active
discovery client or the device is already paired. Is the device
paired, or are you calling the StartDiscovery method on the device?

Note that the link layer does not need to send duplicate reports (the
same device address) to the host even if the advertising data changes.
This is acceptable behavior per the spec, as outlined in Vol 6, Part
B, Section 4.4.3 "Scanning State": "The advertising data may change;
advertising data or scan response data is not considered significant
when determining duplicate advertising reports."

--
M Janssen