2014-07-21 23:40:33

by Arman Uguray

[permalink] [raw]
Subject: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

* v1:
- Added back the "Value" property. Changed its meaning so that the property
represents the cached characteristic/descriptor value and there are no
read/write request semantics tied to Get/Set. PropertiesChanged is sent on
notifications/indications and after successful read requests. The property
is now read-only and optional, i.e. it won't be present until a read
request or a not/ind.

- Replaced the "Authentication", "Authorization", and "Encryption" errors
with a simpler "NotPaired" error, since there's not much the external
application can do on these errors other than try to pair. bluetoothd will
automatically attempt to raise the security level of the connection on
these errors.

Arman Uguray (1):
doc/gatt-api: New API properties and methods for the GATT D-Bus API.

doc/gatt-api.txt | 118 +++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 106 insertions(+), 12 deletions(-)

--
2.0.0.526.g5318336



2014-08-01 03:11:23

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Marcel,

I think this all makes sense and the API is in a reasonable shape now.
All of the properties/methods can integrate nicely with client and
server implementations (with one or two properties being optional for
server). I think we can revisit GattManager1 once we start thinking
about the server code but for now I think this is good for client.
And, of course, we can always add new properties/methods later.

2014-07-30 16:46:07

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,

>> If we encounter one condition that the value is determine with the "Write Command" procedure which no response for client, should we expose this kind of property ? If we expose it, we have to write command to the remote and read value back immediately, then emit propertychanged signal if read value equals to write value(different from old one).
>>
>
> I don't think we should expose this value until we have done an
> initial read (either internally before we construct the D-Bus
> hierarchy or after a call to ReadValue) or via notification. I think
> we should just keep the property hidden until we know what the value
> is, even in the case of a write.

that is the beauty of properties with D-Bus Object Manager, we can actually also invalidate a property and tell the applications that it went away. So yes, initially the value should not be present. If we never read it, then there is no cached value. If we are connecting to a know device, then we only provide the value once we verified that the services have not changed.

>> In your proposal , I think we also should read initial value from remote at the beginning of DBus Hierachy setup. Whatever "read", "notify", or "indicate" even write request to remote, only different value compared with exist cache value such as initial value, then bluez emit propertychanged signal. This would be good, right?
>>
>
> I'm not opposed to this, though we can only read the initial value if
> the characteristic supports reads. If the characteristic only supports
> notify or indicate, then we should wait until we receive the first
> notification/indication to expose the property and we keep it hidden
> until then.

Exactly. And with that it is nice for the application since it still does not have to learn any new tricks to get the value. It just sits there and waits until it shows up.

Regards

Marcel


2014-07-29 19:07:24

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Chaojie,


> If we encounter one condition that the value is determine with the "Write=
Command" procedure which no response for client, should we expose this kin=
d of property ? If we expose it, we have to write command to the remote and=
read value back immediately, then emit propertychanged signal if read valu=
e equals to write value(different from old one).
>

I don't think we should expose this value until we have done an
initial read (either internally before we construct the D-Bus
hierarchy or after a call to ReadValue) or via notification. I think
we should just keep the property hidden until we know what the value
is, even in the case of a write.


> In your proposal , I think we also should read initial value from remote =
at the beginning of DBus Hierachy setup. Whatever "read", "notify", or "ind=
icate" even write request to remote, only different value compared with exi=
st cache value such as initial value, then bluez emit propertychanged signa=
l. This would be good, right?
>

I'm not opposed to this, though we can only read the initial value if
the characteristic supports reads. If the characteristic only supports
notify or indicate, then we should wait until we receive the first
notification/indication to expose the property and we keep it hidden
until then.


Cheers,
Arman

2014-07-29 06:03:10

by Gu, Chao Jie

[permalink] [raw]
Subject: RE: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

SGkgYXJtYW4sDQoNCjwgWWVzLCB3ZSBzaG91bGRuJ3QgZXhwb3NlIHRoZSBWYWx1ZSBwcm9wZXJ0
eSBpZiB0aGUgY2hhcmFjdGVyaXN0aWMgcHJvcGVydGllcyBmaWVsZCBkb2Vzbid0IGNvbnRhaW4g
InJlYWQiLCAibm90aWZ5Iiwgb3IgImluZGljYXRlIi4gV2l0aCByZXNwZWN0IHRvIGNhY2hpbmcg
dGhlDQo8IHZhbHVlIGJlZm9yZSBhIHdyaXRlIG9wZXJhdGlvbiwgSSdtIHN0aWxsIGhlc2l0YW50
IHRvd2FyZHMgbWFraW5nIGFueSBhc3N1bXB0aW9ucyBhYm91dCB0aGUgdmFsdWUuIEkgd291bGRu
J3Qgd2FudCB0byBjYWNoZSB0aGUgdmFsdWUgdW50aWwgYWZ0ZXIgdGhlIHdyaXRlDQo8IG9wZXJh
dGlvbiBoYXMgY29tcGxldGVkIHN1Y2Nlc3NmdWxseSAod2hpY2ggaXMgb25seSBwb3NzaWJsZSB0
byBkZXRlcm1pbmUgd2l0aCB0aGUgIndyaXRlIHJlcXVlc3QiIGFuZCAicmVsaWFibGUgbG9uZyB3
cml0ZSIgcHJvY2VkdXJlKSBhbmQgdGhlcmUgbWF5IGJlDQo8IHNvbWUgcmFjZSBjb25kaXRpb25z
IHdoZXJlIGEgY2hhcmFjdGVyaXN0aWMgbWlnaHQgaW1tZWRpYXRlbHkgY2hhbmdlIGl0J3MgdmFs
dWUgYW5kIHNlbmQgYSBub3RpZmljYXRpb24gYmVmb3JlIHdlIGhhZCBhIGNoYW5jZSB0byBzdG9y
ZSB0aGUgd3JpdGUgdmFsdWUuIEluDQo8IHRoaXMgY2FzZSB0aGUgbGF0ZXN0IGNhY2hlZCB2YWx1
ZSB3b3VsZCBiZSBpbmNvcnJlY3QuDQo8SSB1bmRlcnN0YW5kIHRoYXQgdGhpcyBpcyBhbiBlZGdl
IGNhc2UgYnV0IGl0J3MgZW5vdWdoIHRvIHJhaXNlIHNvbWUgY29uY2Vybi4NCg0KSWYgd2UgZW5j
b3VudGVyIG9uZSBjb25kaXRpb24gdGhhdCB0aGUgdmFsdWUgaXMgZGV0ZXJtaW5lIHdpdGggdGhl
ICJXcml0ZSBDb21tYW5kIiBwcm9jZWR1cmUgd2hpY2ggbm8gcmVzcG9uc2UgZm9yIGNsaWVudCwg
c2hvdWxkIHdlIGV4cG9zZSB0aGlzIGtpbmQgb2YgcHJvcGVydHkgPyBJZiB3ZSBleHBvc2UgaXQs
IHdlIGhhdmUgdG8gd3JpdGUgY29tbWFuZCB0byB0aGUgcmVtb3RlIGFuZCByZWFkIHZhbHVlIGJh
Y2sgaW1tZWRpYXRlbHksIHRoZW4gZW1pdCBwcm9wZXJ0eWNoYW5nZWQgc2lnbmFsIGlmIHJlYWQg
dmFsdWUgZXF1YWxzIHRvIHdyaXRlIHZhbHVlKGRpZmZlcmVudCBmcm9tIG9sZCBvbmUpLg0KDQpJ
biB5b3VyIHByb3Bvc2FsICwgSSB0aGluayB3ZSBhbHNvIHNob3VsZCByZWFkIGluaXRpYWwgdmFs
dWUgZnJvbSByZW1vdGUgYXQgdGhlIGJlZ2lubmluZyBvZiBEQnVzIEhpZXJhY2h5IHNldHVwLiBX
aGF0ZXZlciAicmVhZCIsICJub3RpZnkiLCBvciAiaW5kaWNhdGUiIGV2ZW4gd3JpdGUgcmVxdWVz
dCB0byByZW1vdGUsIG9ubHkgZGlmZmVyZW50IHZhbHVlIGNvbXBhcmVkIHdpdGggZXhpc3QgY2Fj
aGUgdmFsdWUgc3VjaCBhcyBpbml0aWFsIHZhbHVlLCB0aGVuIGJsdWV6IGVtaXQgcHJvcGVydHlj
aGFuZ2VkIHNpZ25hbC4gVGhpcyB3b3VsZCBiZSBnb29kLCByaWdodD8NCg0KVGhhbmtzDQpDaGFv
amllIA0KDQo=

2014-07-28 23:51:21

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,

>> I think this depends a little bit. Most values will be return the exact same value that you write into it. That is what they are suppose to do anyway. The only exception here are control endpoints. So I would agree that for control endpoints we do not expose the Value property at all.
>>
>
> Yes, we shouldn't expose the Value property if the characteristic
> properties field doesn't contain "read", "notify", or "indicate". With
> respect to caching the value before a write operation, I'm still
> hesitant towards making any assumptions about the value. I wouldn't
> want to cache the value until after the write operation has completed
> successfully (which is only possible to determine with the "write
> request" and "reliable long write" procedure) and there may be some
> race conditions where a characteristic might immediately change it's
> value and send a notification before we had a chance to store the
> write value. In this case the latest cached value would be incorrect.
> I understand that this is an edge case but it's enough to raise some
> concern.

without thinking too much about the details, I think when notification is enabled, then we just wait for the update from the remote device. If notification is not enabled, then we update the value on write. Since everything is central in bluetoothd, we should be able to make smart decisions.

Regards

Marcel


2014-07-28 23:31:45

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Marcel,


> I think one detail that has to be clear os that most likely nobody is cal=
ling Get directly. I will be available, but mostly all applications will ge=
t the value from calling GetManagedObjects.
>
> So lets say we talk about standard service like Device Information or Bat=
tery Status etc., every application gets these information in one go. This =
is comparing to x number of application calling ReadValue for each value in=
dividually. For values that do not change at all or change only every x day=
s this is something that makes sense and I really want. It means that appli=
cations do not have to do anything extra for these values. They are just av=
ailable and they are most likely recent or recent enough.
>

Fair enough, this was enough to sell this to me :)

> I think this depends a little bit. Most values will be return the exact s=
ame value that you write into it. That is what they are suppose to do anywa=
y. The only exception here are control endpoints. So I would agree that for=
control endpoints we do not expose the Value property at all.
>

Yes, we shouldn't expose the Value property if the characteristic
properties field doesn't contain "read", "notify", or "indicate". With
respect to caching the value before a write operation, I'm still
hesitant towards making any assumptions about the value. I wouldn't
want to cache the value until after the write operation has completed
successfully (which is only possible to determine with the "write
request" and "reliable long write" procedure) and there may be some
race conditions where a characteristic might immediately change it's
value and send a notification before we had a chance to store the
write value. In this case the latest cached value would be incorrect.
I understand that this is an edge case but it's enough to raise some
concern.

Anyway, we can start out by caching the write value and if people run
into any issues in the field, we can then change the behavior in the
future.


Cheers,
Arman

2014-07-28 22:34:25

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,

>> In this weekend, I think about this API again , and there is one question for you:
>> In your new proposal , bluez offer two ways for application to read characteristic value, one is to get property array of value, the other is to use ReadValue method.
>> For applications, in which condition they use property array of value and in which condition they use ReadValue ? will it cause a confusion for user when offer two ways for user at the same time?
>>
>
> In this new proposal, the "Value" property simply stores the most
> recently cached value after the most recent read procedure or
> notification/indication. So, Get will simply return this cached value.
> If an application wants to issue a read request to the remote
> peripheral, then they will call ReadValue.

I think one detail that has to be clear os that most likely nobody is calling Get directly. I will be available, but mostly all applications will get the value from calling GetManagedObjects.

So lets say we talk about standard service like Device Information or Battery Status etc., every application gets these information in one go. This is comparing to x number of application calling ReadValue for each value individually. For values that do not change at all or change only every x days this is something that makes sense and I really want. It means that applications do not have to do anything extra for these values. They are just available and they are most likely recent or recent enough.

>> You said "What if the characteristic doesn't support notifications but it's value can change?" It means cached array of value cannot be trusted in the condition you said exist if this value changes happen not result from writing to the remote end device.
>
> This is why the property is optional and wouldn't exist if the value
> cannot be read or notified.

Your proposal also had the Notifying property in there. Which means an application can know if it is cached value where the up-to-date status is either valid or it is unknown.

And of course if the value can not be read, then as you said, the property just does not exist at all.

>> So in my understanding, there is no worth to read characteristic value by property array of value, the property's role is just to emit propertychanged signal when write/read/notification operation changes its value. If so, we just define a signal such as ValueUpdated to tell user value has been changed is ok.
>>
>
> I only added this property back after initial feedback, which seemed
> to suggest that having this cached property might have some value for
> certain profile implementations. In short, if an application is always
> interested in the latest, most accurate characteristic value, then
> yeah, they would use ReadValue and not bother with the property at
> all, as you said. I personally find that caching the value after a
> write request is a bad idea, since bluetoothd can only guess what the
> new value of the remote characteristic is based on the write value
> that it just sent. My proposal is to only set this property and emit a
> PropertiesChanged after a successful read request and on
> notifications/indications. If we use PropertiesChanged this way, then
> there wouldn't be a need for ValueUpdated.

I think this depends a little bit. Most values will be return the exact same value that you write into it. That is what they are suppose to do anyway. The only exception here are control endpoints. So I would agree that for control endpoints we do not expose the Value property at all.

> I agree that this might be confusing, especially for applications that
> didn't issue a read request. If one application performs a read, all
> applications will then receive a PropertiesChanged signal, yet it is
> not clear to them if this was due to a notification or because
> somebody performed a read.

Does this really matter for an application that is not actively interested in interacting with that remote service. Why would it care what triggered the update.

Lets say you just want to monitor your temperature sensor and its battery status. So even if you are a single application and only your application is using that sensor. You just enable notifications for the values you care about and then sit back. Meaning a GetManagedObjects gets you started and PropertiesChanged notification will keep you updated. That sounds like a really nice and simple application interface to me.

> This is why, in my initial proposal, I removed the "Value" property
> entirely, since any caching needed by an application can be performed
> directly by them as necessary, since most apps will be interested in
> getting the value directly from the remote peripheral via a call to
> ReadValue anyway. Then we would just have a ValueUpdated (or
> ValueNotified) signal which would only be emitted on
> notifications/indications. Marcel, any thoughts on this?

I do not like having extra signals that you need to monitor and that do not fit into the standard model of the Object Manager. There is really no point in that we keep playing ping-pong with the remote device to all values some application is interested in. Some stuff should just come with a single call or should be notified once the device connects.

This is especially important when you think about the latency to connect to a sensor and get all information back to the application. The user interface should be able to show all information right away and then just update the ones that changed a few seconds later. However if another application or some system service has already updated these, why would the application need to request them again. It does not make sense to me. Especially once we have sensors that can provide valuable information to more than just one application.

>> So there are two API design can be used:
>> 1. array of value property Get/Set (This design just happen only one condition that client write the value to remote, not in which remote change its value itself spontaneously and not send notification.)
>> 2. ReadValue /WriteValue method and signal ValueUpdated
>>
>> However, in the conclusion, array of value property and ReadValue/WriteValue can not be coexist, otherwise that design will result in ambiguity and not make sense.
>>
>
> Aside from the ambiguity that I mentioned above, these CAN nicely
> coexist. Again, the latest proposal is to add a read-only "Value"
> property which represents the cached value and have
> ReadValue/WriteValue for the remote procedures on the peripheral. Set
> is not allowed in this scenario and no read semantics are bound to
> Get/GetAll.

I think this is how we should start right now. If we figure out later that this makes no sense, then we correct it. However only after we get some testing applications talking to some sensors or devices, we will see how this works out.

Please keep in mind that I want to make applications simpler. The less they have to do to get things right, the better. And D-Bus is not a low-level API for me. It is high-level API that an application can use directly without having to pull in a binding or framework to make us of it.

Regards

Marcel


2014-07-28 20:52:43

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Chaojie,


> In this weekend, I think about this API again , and there is one =
question for you:
> In your new proposal , bluez offer two ways for application to re=
ad characteristic value, one is to get property array of value, the other i=
s to use ReadValue method.
> For applications, in which condition they use property array of v=
alue and in which condition they use ReadValue ? will it cause a confusion =
for user when offer two ways for user at the same time?
>

In this new proposal, the "Value" property simply stores the most
recently cached value after the most recent read procedure or
notification/indication. So, Get will simply return this cached value.
If an application wants to issue a read request to the remote
peripheral, then they will call ReadValue.


> You said "What if the characteristic doesn't support notifications but it=
's value can change?" It means cached array of value cannot be trusted in t=
he condition you said exist if this value changes happen not result from wr=
iting to the remote end device.

This is why the property is optional and wouldn't exist if the value
cannot be read or notified.

> So in my understanding, there is no worth to read characteristic value by=
property array of value, the property's role is just to emit propertychang=
ed signal when write/read/notification operation changes its value. If so, =
we just define a signal such as ValueUpdated to tell user value has been ch=
anged is ok.
>

I only added this property back after initial feedback, which seemed
to suggest that having this cached property might have some value for
certain profile implementations. In short, if an application is always
interested in the latest, most accurate characteristic value, then
yeah, they would use ReadValue and not bother with the property at
all, as you said. I personally find that caching the value after a
write request is a bad idea, since bluetoothd can only guess what the
new value of the remote characteristic is based on the write value
that it just sent. My proposal is to only set this property and emit a
PropertiesChanged after a successful read request and on
notifications/indications. If we use PropertiesChanged this way, then
there wouldn't be a need for ValueUpdated.

I agree that this might be confusing, especially for applications that
didn't issue a read request. If one application performs a read, all
applications will then receive a PropertiesChanged signal, yet it is
not clear to them if this was due to a notification or because
somebody performed a read.

This is why, in my initial proposal, I removed the "Value" property
entirely, since any caching needed by an application can be performed
directly by them as necessary, since most apps will be interested in
getting the value directly from the remote peripheral via a call to
ReadValue anyway. Then we would just have a ValueUpdated (or
ValueNotified) signal which would only be emitted on
notifications/indications. Marcel, any thoughts on this?


> So there are two API design can be used:
> 1. array of value property Get/Set (This design just happen only one co=
ndition that client write the value to remote, not in which remote change i=
ts value itself spontaneously and not send notification.)
> 2. ReadValue /WriteValue method and signal ValueUpdated
>
> However, in the conclusion, array of value property and ReadValue/WriteVa=
lue can not be coexist, otherwise that design will result in ambiguity and =
not make sense.
>


Aside from the ambiguity that I mentioned above, these CAN nicely
coexist. Again, the latest proposal is to add a read-only "Value"
property which represents the cached value and have
ReadValue/WriteValue for the remote procedures on the peripheral. Set
is not allowed in this scenario and no read semantics are bound to
Get/GetAll.


-Arman

2014-07-28 09:17:09

by Gu, Chao Jie

[permalink] [raw]
Subject: RE: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,
In this weekend, I think about this API again , and there is one question =
for you:
In your new proposal , bluez offer two ways for application to read charac=
teristic value, one is to get property array of value, the other is to use =
ReadValue method.
For applications, in which condition they use property array of value and =
in which condition they use ReadValue ? will it cause a confusion for user =
when offer two ways for user at the same time?

> I have to disagree here. I think making the DBus.Properties interface wor=
k for this particular case doesn't make the API particularly simpler, in fa=
ct I think it adds unnecessary complexity and ambiguity to the semantics in=
volved. It's not clear, for instance, if Get should always return the cache=
d value or if it should issue a=20
> Read request to the remote end. You suggest making an initial read reques=
t and storing that value and updating it on notifications. What if the char=
acteristic doesn't support notifications but it's value can change? What if=
the client is implementing a profile that warrants a read request to the r=
emote end to get the
> freshest value on demand?
You said "What if the characteristic doesn't support notifications but it's=
value can change?" It means cached array of value cannot be trusted in the=
condition you said exist if this value changes happen not result from writ=
ing to the remote end device.=20
So in my understanding, there is no worth to read characteristic value by p=
roperty array of value, the property's role is just to emit propertychanged=
signal when write/read/notification operation changes its value. If so, we=
just define a signal such as ValueUpdated to tell user value has been chan=
ged is ok.

"What if the characteristic doesn't support notifications but it's value ca=
n change?", if this value change just happen only one condition that client=
write the value to remote, not in which remote change its value itself spo=
ntaneously and not send notification. In fact, Set/Get property also can ac=
hieve the same result as your new proposal. Because the cache value can be =
trusted in this condition. And the cache value is the freshest value becaus=
e client write value to the remote would let cache value send propertychang=
ed signal to refresh itself to newest value.

So there are two API design can be used:
1. array of value property Get/Set (This design just happen only one cond=
ition that client write the value to remote, not in which remote change its=
value itself spontaneously and not send notification.)
2. ReadValue /WriteValue method and signal ValueUpdated=20

However, in the conclusion, array of value property and ReadValue/WriteValu=
e can not be coexist, otherwise that design will result in ambiguity and no=
t make sense.

Thanks
Chaojie
-----Original Message-----
From: [email protected] [mailto:linux-bluetooth-owner@v=
ger.kernel.org] On Behalf Of Arman Uguray
Sent: Tuesday, July 22, 2014 7:41 AM
To: [email protected]
Cc: Arman Uguray
Subject: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the =
GATT D-Bus API.

This patch proposes changes to the currently unimplemented GATT D-Bus API f=
or desktop bluetoothd. This is the first step in implementing a GATT client=
layer for bluetoothd that will change the way remote attributes are access=
ed via bluetoothd plugins and external applications.
---
doc/gatt-api.txt | 118 +++++++++++++++++++++++++++++++++++++++++++++++++--=
----
1 file changed, 106 insertions(+), 12 deletions(-)

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt index 8c7975c..741bd18 100=
644
--- a/doc/gatt-api.txt
+++ b/doc/gatt-api.txt
@@ -32,6 +32,25 @@ Properties string UUID [read-only]
=20
128-bit service UUID.
=20
+ boolean Primary [read-only]
+
+ Indicates whether or not this GATT service is a
+ primary service. If false, the service is secondary.
+
+ object Device [read-only, optional]
+
+ Object path of the Bluetooth device the service
+ belongs to. Only present on services from remote
+ devices.
+
+ array{object} Characteristics [read-only]
+
+ Array of object paths representing the characteristics
+ of this service. This property is set only when the
+ characteristic discovery has been completed, however the
+ characteristic objects will become available via
+ ObjectManager as soon as they get discovered.
+
array{object} Includes [read-only]: Not implemented
=20
Array of object paths representing the included
@@ -48,6 +67,47 @@ Service org.bluez
Interface org.bluez.GattCharacteristic1 [Experimental]
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/servic=
eXX/charYYYY
=20
+Methods array{byte} ReadValue()
+
+ Issues a request to read the value of the
+ characteristic and returns the value if the
+ operation was successful.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.ReadNotPermitted
+ org.bluez.Error.NotPaired
+ org.bluez.Error.NotSupported
+
+ void WriteValue(array{byte} value)
+
+ Issues a request to write the value of the
+ characteristic.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.WriteNotPermitted
+ org.bluez.Error.NotPaired
+ org.bluez.Error.NotSupported
+
+ void StartNotify()
+
+ Starts a notification session from this characteristic
+ if it supports value notifications or indications.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.NotSupported
+
+ void StopNotify()
+
+ This method will cancel any previous StartNotify
+ transaction. Note that notifications from a
+ characteristic are shared between sessions thus
+ calling StopNotify will release a single session.
+
+ Possible Errors: org.bluez.Error.Failed
+
Properties string UUID [read-only]
=20
128-bit characteristic UUID.
@@ -57,12 +117,19 @@ Properties string UUID [read-only]
Object path of the GATT service the characteristc
belongs to.
=20
- array{byte} Value [read-write]
+ array{byte} Value [read-only, optional]
+
+ The cached value of the characteristic. This property
+ gets updated only after a successful read request and
+ when a notification or indication is received, upon
+ which a PropertiesChanged signal will be emitted.
=20
- Value read from the remote Bluetooth device or from
- the external application implementing GATT services.
+ boolean Notifying [read-only]
=20
- array{string} Flags [read-only, optional]
+ True, if notifications or indications on this
+ characteristic are currently enabled.
+
+ array{string} Flags [read-only]
=20
Defines how the characteristic value can be used. See
Core spec "Table 3.5: Characteristic Properties bit
@@ -79,6 +146,14 @@ Properties string UUID [read-only]
"reliable-write"
"writable-auxiliaries"
=20
+ array{object} Descriptors [read-only]
+
+ Array of object paths representing the descriptors
+ of this service. This property is set only when the
+ descriptor discovery has been completed, however the
+ descriptor objects will become available via
+ ObjectManager as soon as they get discovered.
+
=20
Characteristic Descriptors hierarchy
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
@@ -89,6 +164,29 @@ Service org.bluez
Interface org.bluez.GattDescriptor1 [Experimental]
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/servic=
eXX/charYYYY/descriptorZZZ
=20
+Methods array{byte} ReadValue()
+
+ Issues a request to read the value of the
+ characteristic and returns the value if the
+ operation was successful.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.ReadNotPermitted
+ org.bluez.Error.NotPaired
+ org.bluez.Error.NotSupported
+
+ void WriteValue(array{byte} value)
+
+ Issues a request to write the value of the
+ characteristic.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.WriteNotPermitted
+ org.bluez.Error.NotPaired
+ org.bluez.Error.NotSupported
+
Properties string UUID [read-only]
=20
128-bit descriptor UUID.
@@ -98,16 +196,12 @@ Properties string UUID [read-only]
Object path of the GATT characteristc the descriptor
belongs to.
=20
- array{byte} Value [read-write]
-
- Raw characteristic descriptor value read from the
- remote Bluetooth device or from the external
- application implementing GATT services.
+ array{byte} Value [read-only, optional]
=20
- string Permissions [read-only]: To be defined
+ The cached value of the descriptor. This property
+ gets updated only after a successful read request, upon
+ which a PropertiesChanged signal will be emitted.
=20
- Defines read/write authentication and authorization
- requirements.
=20
Service Manager hierarchy
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D
--
2.0.0.526.g5318336

2014-07-25 21:06:30

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Luiz & Marcel,


> The one thing I always wanted is a string representation of the Value property as a second property. That way some clients and tools that only need to display the value can rely on bluetoothd giving it a nice translated string.
>

We could do something like this, then again, if a tool wants to
display the value as a string couldn't they just convert it to a
string themselves and simply format it however they like?


>> Well a variant is a container so it can carry any of those values
>> including string or even an array of strings and I believe it would
>> make things even more simple to a client generic API because it can
>> directly be based on D-Bus variant type that most bindings do already
>> support.
>

IMO bluetoothd is not the right place to do this. The high-level API
can allow programmers to do some of these conversions, using features
of the programming language (like in JavaScript or Python) or by
providing additional API functions to perform these conversions (like
on Android). Just returning the raw value also makes the development
of these APIs easier, especially those that have internal bindings for
other platforms such as Windows and Mac that don't necessarily provide
the same variant-based data in their Bluetooth APIs (the new Chrome
bluetooth APIs are such an example).

Cheers,
Arman

2014-07-25 19:28:27

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Luiz,

>>> Im just wondering why we did not use variant type instead of array of bytes
>>> for value, imo it seems a better fit since it can be extended with different
>>> types in host byte order.
>>>
>>
>> I don't think that is such a good idea. Characteristic/descriptor
>> values are usually meant to be interpreted as a series of bytes
>> encoding different kinds of data of various lengths based on the
>> profile (e.g. the first byte is a bit mask, the following two bytes
>> are a uint16, etc). I think it's better to just leave it as an array
>> of bytes in the order that it was received from the wire as this is
>> what clients will expect and the order in which the bytes should be
>> interpreted will be explicitly specified by the profile
>
> In case we know the profile we could go ahead an decode upfront and in
> case we don't know how to decode we keep the array of bytes inside the
> variant.

I prefer we keep the Value property as array of bytes. We should always expose the real value information for all characteristics. This is especially important for custom services.

The one thing I always wanted is a string representation of the Value property as a second property. That way some clients and tools that only need to display the value can rely on bluetoothd giving it a nice translated string.

>> On occasion you have a characteristic value that encodes, for example,
>> a complete string. Then again, if we put a variant of string as the
>> value property there, only those clients that know beforehand that the
>> value contains a string will be able to work with it. If you're
>> implementing a high-level generic application API, this won't work.
>
> Well a variant is a container so it can carry any of those values
> including string or even an array of strings and I believe it would
> make things even more simple to a client generic API because it can
> directly be based on D-Bus variant type that most bindings do already
> support.

The problem is that values are include also types of what their content is. Being it a temperature value, percentage or some other value.

Regards

Marcel


2014-07-25 19:17:19

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,

On Fri, Jul 25, 2014 at 9:50 PM, Arman Uguray <[email protected]> wrote:
> Hi Luiz,
>
>> Im just wondering why we did not use variant type instead of array of bytes
>> for value, imo it seems a better fit since it can be extended with different
>> types in host byte order.
>>
>
> I don't think that is such a good idea. Characteristic/descriptor
> values are usually meant to be interpreted as a series of bytes
> encoding different kinds of data of various lengths based on the
> profile (e.g. the first byte is a bit mask, the following two bytes
> are a uint16, etc). I think it's better to just leave it as an array
> of bytes in the order that it was received from the wire as this is
> what clients will expect and the order in which the bytes should be
> interpreted will be explicitly specified by the profile

In case we know the profile we could go ahead an decode upfront and in
case we don't know how to decode we keep the array of bytes inside the
variant.

> On occasion you have a characteristic value that encodes, for example,
> a complete string. Then again, if we put a variant of string as the
> value property there, only those clients that know beforehand that the
> value contains a string will be able to work with it. If you're
> implementing a high-level generic application API, this won't work.

Well a variant is a container so it can carry any of those values
including string or even an array of strings and I believe it would
make things even more simple to a client generic API because it can
directly be based on D-Bus variant type that most bindings do already
support.


--
Luiz Augusto von Dentz

2014-07-25 18:50:41

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Luiz,

> Im just wondering why we did not use variant type instead of array of bytes
> for value, imo it seems a better fit since it can be extended with different
> types in host byte order.
>

I don't think that is such a good idea. Characteristic/descriptor
values are usually meant to be interpreted as a series of bytes
encoding different kinds of data of various lengths based on the
profile (e.g. the first byte is a bit mask, the following two bytes
are a uint16, etc). I think it's better to just leave it as an array
of bytes in the order that it was received from the wire as this is
what clients will expect and the order in which the bytes should be
interpreted will be explicitly specified by the profile

On occasion you have a characteristic value that encodes, for example,
a complete string. Then again, if we put a variant of string as the
value property there, only those clients that know beforehand that the
value contains a string will be able to work with it. If you're
implementing a high-level generic application API, this won't work.

Cheers,
Arman

2014-07-24 08:01:32

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi,

On Thu, Jul 24, 2014 at 10:58 AM, Luiz Augusto von Dentz
<[email protected]> wrote:
> Hi Arman,
>
>
> On Thu, Jul 24, 2014 at 7:11 AM, Gu, Chao Jie <[email protected]> wrote:
>>
>> Hi Arman,
>>
>> > Explain to me how, using only the InterfacesAdded signal, an
>> > application can know that all characteristic objects under a service
>> > hierarchy have been added? The only way is if the external application
>> > already knows about service it's interacting with, which is not the
>> > case if you're building a generic application API on top of
>> > bluetoothd. Without what I'm proposing, you can't build a generic GATT
>> > application API without requiring cumbersome event handling for each
>> > service, characteristic, and descriptor object as they get added and
>> > have only partial access to these objects in the handlers as the
>> > objects are getting processed. This might be fine for low-level
>> > applications that interact with D-Bus directly, but for higher level
>> > app developers this is a real issue that we want to handle properly
>> > and make their lives easier.
>
>
> Im just wondering why we did not use variant type instead of array of bytes
> for value, imo it seems a better fit since it can be extended with different
> types in host byte order.
>
>>
>> You are right, we work on Tizen Bluetooth-frwk which is low-level
>> service/application in system . Bluetooth-frwk can take a role to handle
>> D-Bus informaiton and give defined API to application such as characteristic
>> discovery method, so we refer to different level application indeed.
>> From your aspect, I understood that you consider that high level app
>> developer how to get characteristic array directly from bluetoothd. .
>>
>>
>
> Tizen has to follow BlueZ design, you can offer a C binding for it exposing
> the exact same (or a subset) of the D-Bus API, anything other than that will
> cause a maintenance burden in your end.

Resending since vger rejected my last email claiming it contained HTML subparts.


--
Luiz Augusto von Dentz

2014-07-24 07:58:48

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,


On Thu, Jul 24, 2014 at 7:11 AM, Gu, Chao Jie <[email protected]> wrote:

> Hi Arman,
>
> > Explain to me how, using only the InterfacesAdded signal, an
> > application can know that all characteristic objects under a service
> > hierarchy have been added? The only way is if the external application
> > already knows about service it's interacting with, which is not the
> > case if you're building a generic application API on top of
> > bluetoothd. Without what I'm proposing, you can't build a generic GATT
> > application API without requiring cumbersome event handling for each
> > service, characteristic, and descriptor object as they get added and
> > have only partial access to these objects in the handlers as the
> > objects are getting processed. This might be fine for low-level
> > applications that interact with D-Bus directly, but for higher level
> > app developers this is a real issue that we want to handle properly
> > and make their lives easier.
>

Im just wondering why we did not use variant type instead of array of bytes
for value, imo it seems a better fit since it can be extended with
different types in host byte order.


> You are right, we work on Tizen Bluetooth-frwk which is low-level
> service/application in system . Bluetooth-frwk can take a role to handle
> D-Bus informaiton and give defined API to application such as
> characteristic discovery method, so we refer to different level application
> indeed.
> From your aspect, I understood that you consider that high level app
> developer how to get characteristic array directly from bluetoothd. .
>

>
Tizen has to follow BlueZ design, you can offer a C binding for it exposing
the exact same (or a subset) of the D-Bus API, anything other than that
will cause a maintenance burden in your end.

--
Luiz Augusto von Dentz

2014-07-24 04:11:23

by Gu, Chao Jie

[permalink] [raw]
Subject: RE: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,=20

> Explain to me how, using only the InterfacesAdded signal, an=20
> application can know that all characteristic objects under a service=20
> hierarchy have been added? The only way is if the external application=20
> already knows about service it's interacting with, which is not the=20
> case if you're building a generic application API on top of=20
> bluetoothd. Without what I'm proposing, you can't build a generic GATT=20
> application API without requiring cumbersome event handling for each=20
> service, characteristic, and descriptor object as they get added and=20
> have only partial access to these objects in the handlers as the=20
> objects are getting processed. This might be fine for low-level=20
> applications that interact with D-Bus directly, but for higher level=20
> app developers this is a real issue that we want to handle properly=20
> and make their lives easier.

You are right, we work on Tizen Bluetooth-frwk which is low-level service/a=
pplication in system . Bluetooth-frwk can take a role to handle D-Bus infor=
maiton and give defined API to application such as characteristic discovery=
method, so we refer to different level application indeed.
>From your aspect, I understood that you consider that high level app develo=
per how to get characteristic array directly from bluetoothd. .=20

Thanks
Chaojie
-----Original Message-----
From: Marcel Holtmann [mailto:[email protected]]=20
Sent: Thursday, July 24, 2014 12:33 AM
To: Arman Uguray
Cc: Gu, Chao Jie; BlueZ development; Johan Hedberg
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for =
the GATT D-Bus API.

Hi Arman,

>> Of course if DBus has these array object of characteristic property, the=
re is more clear and easy for client to get. However, in my opinion, bluez =
just put out least but enough information in DBus Hierarchy for application=
to use. Just you said, to add array object property , this could even be a=
simple boolean property such as "DiscoveryComplete". That would be add mor=
e property in DBus, so on the contrary it would not let DBus Hierarchy look=
simple and clear.
>> Through the objectAdded and InterfaceAdded Signal, application can acqui=
re this subset of object in fact.
>=20
> Explain to me how, using only the InterfacesAdded signal, an=20
> application can know that all characteristic objects under a service=20
> hierarchy have been added? The only way is if the external application=20
> already knows about service it's interacting with, which is not the=20
> case if you're building a generic application API on top of=20
> bluetoothd. Without what I'm proposing, you can't build a generic GATT=20
> application API without requiring cumbersome event handling for each=20
> service, characteristic, and descriptor object as they get added and=20
> have only partial access to these objects in the handlers as the=20
> objects are getting processed. This might be fine for low-level=20
> applications that interact with D-Bus directly, but for higher level=20
> app developers this is a real issue that we want to handle properly=20
> and make their lives easier.

since InterfacesAdded is per object path, the extra Characteristics array m=
akes sense. However that really only applies to application passively monit=
oring the bus objects and properties. The initiator of service discovery sh=
ould only return from that method call when all other object signals have b=
een send out. Similar to what we are doing with pairing or other potential =
long run asynchronous method calls.

Regards

Marcel

2014-07-23 20:39:27

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Marcel,

> since InterfacesAdded is per object path, the extra Characteristics array=
makes sense. However that really only applies to application passively mon=
itoring the bus objects and properties. The initiator of service discovery =
should only return from that method call when all other object signals have=
been send out. Similar to what we are doing with pairing or other potentia=
l long run asynchronous method calls.
>

That makes sense. Then again we don't really have a clear method for
this yet other than org.bluez.Device1.Connect. We are going to have to
figure out the behavior of that method when plugins and the GATT DBus
API are involved as we build the new stack. I also have in mind a
separate, application-specific method for creating a GATT connection
(something like ConnectGatt), where the system UI would call the old
Connect/Disconnect methods but applications would have to use a
ConnectGatt/DisconnectGatt API that keeps track of the different dbus
connections/sessions, but that's a subject for another discussion and
I haven't fully thought this through yet.

Coming back to your point, yes, the application that called Connect
should receive InterfacesAdded for all objects before the call
returns, as you said. Other applications might be passively observing
these events, so they can also wait for PropertiesChanged on
"Characteristics" to know that object creation for a particular
service is complete.

Cheers,
Arman

2014-07-23 16:32:56

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,

>> Of course if DBus has these array object of characteristic property, there is more clear and easy for client to get. However, in my opinion, bluez just put out least but enough information in DBus Hierarchy for application to use. Just you said, to add array object property , this could even be a simple boolean property such as "DiscoveryComplete". That would be add more property in DBus, so on the contrary it would not let DBus Hierarchy look simple and clear.
>> Through the objectAdded and InterfaceAdded Signal, application can acquire this subset of object in fact.
>
> Explain to me how, using only the InterfacesAdded signal, an
> application can know that all characteristic objects under a service
> hierarchy have been added? The only way is if the external application
> already knows about service it's interacting with, which is not the
> case if you're building a generic application API on top of
> bluetoothd. Without what I'm proposing, you can't build a generic GATT
> application API without requiring cumbersome event handling for each
> service, characteristic, and descriptor object as they get added and
> have only partial access to these objects in the handlers as the
> objects are getting processed. This might be fine for low-level
> applications that interact with D-Bus directly, but for higher level
> app developers this is a real issue that we want to handle properly
> and make their lives easier.

since InterfacesAdded is per object path, the extra Characteristics array makes sense. However that really only applies to application passively monitoring the bus objects and properties. The initiator of service discovery should only return from that method call when all other object signals have been send out. Similar to what we are doing with pairing or other potential long run asynchronous method calls.

Regards

Marcel


2014-07-23 16:20:11

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Marcin,

> We could also add Invalid Value Length error.

Good point, I will add that to the list of errors for WriteValue.

Cheers,
Arman

2014-07-23 16:18:58

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Chaojie,

> Of course if DBus has these array object of characteristic property, there is more clear and easy for client to get. However, in my opinion, bluez just put out least but enough information in DBus Hierarchy for application to use. Just you said, to add array object property , this could even be a simple boolean property such as "DiscoveryComplete". That would be add more property in DBus, so on the contrary it would not let DBus Hierarchy look simple and clear.
> Through the objectAdded and InterfaceAdded Signal, application can acquire this subset of object in fact.

Explain to me how, using only the InterfacesAdded signal, an
application can know that all characteristic objects under a service
hierarchy have been added? The only way is if the external application
already knows about service it's interacting with, which is not the
case if you're building a generic application API on top of
bluetoothd. Without what I'm proposing, you can't build a generic GATT
application API without requiring cumbersome event handling for each
service, characteristic, and descriptor object as they get added and
have only partial access to these objects in the handlers as the
objects are getting processed. This might be fine for low-level
applications that interact with D-Bus directly, but for higher level
app developers this is a real issue that we want to handle properly
and make their lives easier.


>why adapter did not export array object of devices and device not export array object of services ?

Because it doesn't need to. You always deal with individual devices as
they get added. You do NOT have this hierarchy with adapter where
doing anything meaningful with the adapter requires you to have seen a
certain set of multiple device objects.


> I am totally ok with generic notify API to application, but I am afraid that there would be conflict between LE profile and generic notify API. Because application does not know RegisterWatcher method has enable the notification. I do not know org.bluez.Inprogress error code could warn this condition or not.
>

You're right, as we move to the new shared GATT/ATT stack, we will
have to change the way the LE plugins work. We need an internal API
for bluetoothd that will handle discovery and other resource
management (such as the CCC write) among daemon plugins and external
applications. Without that, there will be conflict since the plugins,
as they are today, perform these operations directly.

Eventually what we want is to allow plugins to expose methods such as
RegisterWatcher but have that call an internal API method so that
UnregisterWatcher won't cause a write to the CCC descriptor if an
external app called StartNotify on that characteristic and vice versa.

So yes, there will be conflict unless we fix the whole stack, but
that's what we'll do as we deprecate attrib/*.


> BTW, you saidi that calling WriteValue on the CCC descriptor will always fail with WriteNotPermitted. I think gatt_write_char function can write CCC descriptor , do you mean in WriteValue method to refuse write CCC descriptor on purpose and return WriteNotPermitted ?

Yes, I meant the latter (WriteValue method will refuse on purpose).

Cheers and thanks for the comments,
Arman

2014-07-23 13:22:08

by Gu, Chao Jie

[permalink] [raw]
Subject: RE: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

SGkgQXJtYW4sDQoNCj5UaGUgcHJvYmxlbSBpcyB0aGF0IE9iamVjdE1hbmFnZXIgaGFzIG5vIGNs
ZWFyIHdheSB0byB0ZWxsIGEgY2xpZW50IHRoYXQgInRoaXMgc3Vic2V0IG9mIG9iamVjdCBwYXRo
cyBoYXZlIGJlZW4gcHVibGlzaGVkIiBhbmQgd2hlbiB0aGV5IGFyZSBhbGwgYXZhaWxhYmxlIHZp
YSBHZXRNYW5hZ2VkT2JqZWN0cy4gVGhlIG1vc3QgYSBjbGllbnQgY2FuIGRvIGlzIG9ic2VydmUg
dGhlIEludGVyZmFjZXNBZGRlZCBzaWduYWwgYW5kIHRoYXQgc2lnbmFsIGlzIHNlbnQgb24gYSBw
ZXIgb2JqZWN0IHBhdGggYmFzaXMuIEZvciBtb3N0IGV4dGVybmFsIGFwcGxpY2F0aW9ucywgDQo+
aXQgbWlnaHQgYmUgZW5vdWdoIGJ1dCBJIHdvdWxkIGxpa2UgYXBwbGljYXRpb24gQVBJcyB0byBo
YXZlIHRvIGFiaWxpdHkgdG8gc2F5ICJhbGwgb2JqZWN0cyBwdWJsaXNoZWQsIHNlcnZpY2UgaXMg
cmVhZHkgdG8gdXNlIi4NCg0KT2YgY291cnNlIGlmIERCdXMgaGFzIHRoZXNlIGFycmF5IG9iamVj
dCBvZiBjaGFyYWN0ZXJpc3RpYyBwcm9wZXJ0eSwgdGhlcmUgaXMgbW9yZSBjbGVhciBhbmQgZWFz
eSBmb3IgY2xpZW50IHRvIGdldC4gSG93ZXZlciwgaW4gbXkgb3BpbmlvbiwgYmx1ZXoganVzdCBw
dXQgb3V0IGxlYXN0IGJ1dCBlbm91Z2ggaW5mb3JtYXRpb24gaW4gREJ1cyBIaWVyYXJjaHkgZm9y
IGFwcGxpY2F0aW9uIHRvIHVzZS4gSnVzdCB5b3Ugc2FpZCwgdG8gYWRkIGFycmF5IG9iamVjdCBw
cm9wZXJ0eSAsIHRoaXMgY291bGQgZXZlbiBiZSBhIHNpbXBsZSBib29sZWFuIHByb3BlcnR5IHN1
Y2ggYXMgIkRpc2NvdmVyeUNvbXBsZXRlIi4gVGhhdCB3b3VsZCBiZSBhZGQgbW9yZSBwcm9wZXJ0
eSBpbiBEQnVzLCBzbyBvbiB0aGUgY29udHJhcnkgaXQgd291bGQgbm90IGxldCBEQnVzIEhpZXJh
cmNoeSBsb29rIHNpbXBsZSBhbmQgY2xlYXIuDQpUaHJvdWdoIHRoZSBvYmplY3RBZGRlZCBhbmQg
SW50ZXJmYWNlQWRkZWQgU2lnbmFsLCBhcHBsaWNhdGlvbiBjYW4gYWNxdWlyZSB0aGlzIHN1YnNl
dCBvZiBvYmplY3QgaW4gZmFjdC4gSSBhZG1pdCB0aGF0IGFwcGxpY2F0aW9ucyBoYXZlIHRvIGhh
bmRsZSB0aGVzZSBvYmplY3QgaW5mb3JtYXRpb24gaW4gdGhlaXIgY29kZSB0byBnZXQgdGhpcyBz
dWJzZXQgb2Ygb2JqZWN0IHBhdGhzLCBidXQgaXQgbWFrZSBzZW5zZS4gSWYgYmx1ZXogZXhwb3J0
IHRoZSBhcnJheSBvYmplY3Qgb2YgY2hhcmFjdGVyaXN0aWMgdG8gYXBwbGljYXRpb24gLCB3aHkg
YWRhcHRlciBkaWQgbm90IGV4cG9ydCBhcnJheSBvYmplY3Qgb2YgZGV2aWNlcyBhbmQgZGV2aWNl
IG5vdCBleHBvcnQgYXJyYXkgb2JqZWN0IG9mIHNlcnZpY2VzID8NCg0KPlRoaXMgaXMgZXhhY3Rs
eSB0aGUgcHJvYmxlbS4gQSBzaW1wbGUgdXBkYXRlIG9mIHRoaXMgcHJvcGVydHkgbGV0cyB0aGUg
dXNlciBrbm93IHRoYXQgdGhlIGhpZXJhcmNoeSBoYXMgYmVlbiBzZXQgdXAuIEZvciBhbGwgSSBj
YXJlLCB0aGlzIGNvdWxkIGV2ZW4gYmUgYSBzaW1wbGUgYm9vbGVhbiBwcm9wZXJ0eSBzdWNoIGFz
ICJEaXNjb3ZlcnlDb21wbGV0ZSINCj5idXQgSSBraW5kIG9mIGxpa2UgdGhlIGxpc3Qgb2YgY2hh
cmFjdGVyaXN0aWNzIGV2ZW4gdGhvdWdoIEdldE1hbmFnZWRPYmplY3RzL0ludGVyZmFjZXNBZGRl
ZCwgYXMgeW91IHNheSwgY2FuIGFjaGlldmUgdGhlIHNhbWUgcmVzdWx0LiBXZSBoYXZlIHRoZSBz
aW1pbGFyICJJbmNsdWRlcyIgcHJvcGVydHkgYWxyZWFkeSwgc28gaXQncyBub3QgZW50aXJlbHkg
aW5jb25zaXN0ZW50IGZyb20gYW4gQVBJIHN0YW5kcG9pbnQNCg0KU29tZSBwb2ludHMgSSBoYXZl
IHJlZmVycmVkIHRvIGFzIGFib3ZlICwgdGhlcmUgaXMgYW5vdGhlciBwb2ludCBJIGRpc2FncmVl
IHdpdGggeW91LiAiSW5jbHVkZWQgIiBwcm9wZXJ0eSBpcyB0b3RhbGx5IGRpZmZlcmVudCB3aXRo
IGFycmF5IG9iamVjdCBvZiBjaGFyYWN0ZXJpc3RpYywgIkluY2x1ZGVzIiBwcm9wZXJ0eSBpcyBl
c3NlbnRpYWwgdGhhdCBjb25mb3JtIHRvIGxlYXN0IGJ1dCBlbm91Z2ggaW5mb3JtYXRpb24gaW4g
REJ1cyBwcmluY2lwbGUuIEJlY2F1c2UgaWYgYmx1ZXogZG9lcyBub3QgZXhwb3J0IGluY2x1ZGUg
cHJvcGVydHksIGFwcGxpY2F0aW9uIHdpbGwgbm90IGtub3cgaWYgb25lIHNlcnZpY2UgaGF2ZSBp
bmNsdWRlZCBzZXJ2aWNlIG9yIG5vdCwgYW5kIHdoaWNoIG9iamVjdCBzZXJ2aWNlcyBiZWxvbmcg
dG8gaXQgaWYgaW5jbHVkZXMgZXhpc3QuIFRoZXNlIGluZm9ybWF0aW9uIGNhbm5vdCBiZSBhY2Nl
c3NlZCB3aXRob3V0ICJJbmNsdWRlcyIgcHJvcGVydHkuDQoNCj5BcmUgeW91IHJlZmVycmluZyB0
byB0aGUgSGVhcnRSYXRlTWFuYWdlcjEgaGllcmFyY2h5PyBTaW5jZSB3ZSdyZSBub3cgYnVpbGRp
bmcgYSBnZW5lcmljIEFQSSwgd2UgbmVlZCBhIHByb3BlciB3YXkgb2YgcmVmZXJlbmNlLWNvdW50
ZWQsIHBlci1jb25uZWN0aW9uIHdheSB0byBhY2Nlc3MgdGhlIENsaWVudCBDaGFyYWN0ZXJpc3Rp
YyBDb25maWd1cmF0aW9uIGRlc2NyaXB0b3IuIEluIHRoaXMgcHJvcG9zYWwsIGNhbGxpbmcgV3Jp
dGVWYWx1ZSBvbiB0aGUgQ0NDIGRlc2NyaXB0b3Igd2lsbCBhbHdheXMgZmFpbCB3aXRoIFdyaXRl
Tm90UGVybWl0dGVkLg0KDQo+RG8geW91IGhhdmUgYW55IHN1Z2dlc3Rpb25zIGZvciB0aGUgbWV0
aG9kIG5hbWUgb3IgYXJlIHlvdSBPSyB3aXRoIFN0YXJ0Tm90aWZ5IGZvciBub3c/IFdlIGNhbiBh
bHdheXMgY2hhbmdlIGl0IGxhdGVyLg0KDQpZZXMgLCBJIHJlZmVyIHRvIEhlYXJ0UmF0ZU1hbmFn
ZXIxLiBUaGUgcmVhc29uIHRoYXQgSSByZWZlciB0byB0aGlzIEhlYXJ0UmF0ZU1hbmdlcjEgaXMg
aW4gbXkgaW1wbGVtZXRhaXRvbiBmb3IgZXhpc3RpbmcgZ2F0dC1hcGksIEkgZm91bmQgTEUgcHJv
ZmlsZSB3aWxsIGFsc28gYWZmZWN0IHRoZSBHYXR0IERCdXMgSGllcmFyY2h5LiBGb3IgZXhhbXBs
ZSwgd2hlbiBhcHBsaWNhdGlvbiB1c2UgdGhlIFJlZ2lzdGVyV2F0Y2hlciBtZXRob2QgaW4gSGVh
cnRyYXRlIHByb2ZpbGUsIGhlYXJ0cmF0ZSBjaGFyYWN0ZXJpc3RpYyB3aG9zZSBDQ0MgZGVzY3Jp
cHRvciBub3RpZmljYXRpb24gYml0IGlzIG9uLiBUaGVuIGhlYXJ0cmF0ZSBjaGFyYWN0ZXJpc3Rp
YyBpbiBEQnVzIGFuZCBpdHMnIENDQyBkZXNjcmlwdG9yIGhhdmUgdG8gZW1pdCBwcm9wZXJ0eWNo
YW5nZWQgc2lnbmFsIHRvIGFwcGxpY2F0aW9uLiBXaGVuIHVucmVnc2l0ZXJXYXRjaGVyICxDQ0Mg
ZGVzY3JpcHRvciBpbiBEQnVzIGFsc28gaGFzIHRvIGVtaXQgcHJvcGVydHljaGFuZ2VkIHNpZ25h
bC4gRXZlbiBpZiBidWlsZGluZyB0aGlzIGdlbmVyaWMgQVBJLCBJdCBzdGlpbCBjYW4gbm90IGln
bm9yZSB0aGlzIHRhc2suDQoNCkkgYW0gdG90YWxseSBvayB3aXRoIGdlbmVyaWMgbm90aWZ5IEFQ
SSB0byBhcHBsaWNhdGlvbiwgYnV0IEkgYW0gYWZyYWlkIHRoYXQgdGhlcmUgd291bGQgYmUgY29u
ZmxpY3QgYmV0d2VlbiBMRSBwcm9maWxlIGFuZCBnZW5lcmljIG5vdGlmeSBBUEkuIEJlY2F1c2Ug
YXBwbGljYXRpb24gZG9lcyBub3Qga25vdyBSZWdpc3RlcldhdGNoZXIgbWV0aG9kIGhhcyBlbmFi
bGUgdGhlIG5vdGlmaWNhdGlvbi4gSSBkbyBub3Qga25vdyBvcmcuYmx1ZXouSW5wcm9ncmVzcyBl
cnJvciBjb2RlIGNvdWxkIHdhcm4gdGhpcyBjb25kaXRpb24gb3Igbm90LiANCg0KQlRXLCB5b3Ug
c2FpZGkgdGhhdCBjYWxsaW5nIFdyaXRlVmFsdWUgb24gdGhlIENDQyBkZXNjcmlwdG9yIHdpbGwg
YWx3YXlzIGZhaWwgd2l0aCBXcml0ZU5vdFBlcm1pdHRlZC4gSSB0aGluayBnYXR0X3dyaXRlX2No
YXIgZnVuY3Rpb24gY2FuIHdyaXRlIENDQyBkZXNjcmlwdG9yICwgZG8geW91IG1lYW4gaW4gV3Jp
dGVWYWx1ZSBtZXRob2QgdG8gcmVmdXNlIHdyaXRlIENDQyBkZXNjcmlwdG9yIG9uIHB1cnBvc2Ug
YW5kIHJldHVybiBXcml0ZU5vdFBlcm1pdHRlZCA/DQoNClRoYW5rcw0KQ2hhb2ppZSBHdQ0KLS0t
LS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCkZyb206IGFybWFuc2l0b0Bnb29nbGUuY29tIFttYWls
dG86YXJtYW5zaXRvQGdvb2dsZS5jb21dIE9uIEJlaGFsZiBPZiBBcm1hbiBVZ3VyYXkNClNlbnQ6
IFdlZG5lc2RheSwgSnVseSAyMywgMjAxNCA0OjQxIEFNDQpUbzogQmx1ZVogZGV2ZWxvcG1lbnQ7
IEpvaGFuIEhlZGJlcmc7IEd1LCBDaGFvIEppZQ0KU3ViamVjdDogUmU6IFtSRkMgdjEgMC8xXSBk
b2MvZ2F0dC1hcGk6IE5ldyBBUEkgcHJvcGVydGllcyBhbmQgbWV0aG9kcyBmb3IgdGhlIEdBVFQg
RC1CdXMgQVBJLg0KDQpIaSBDaGFvamllLCBKb2hhbiwNCg0KUGxlYXNlIHNlZSBteSByZXNwb25z
ZXMgaW5saW5lOg0KDQoNCj4+ICsgICAgICAgICAgICAgYXJyYXl7b2JqZWN0fSBDaGFyYWN0ZXJp
c3RpY3MgW3JlYWQtb25seV0NCj4+ICsNCj4+ICsgICAgICAgICAgICAgICAgICAgICBBcnJheSBv
ZiBvYmplY3QgcGF0aHMgcmVwcmVzZW50aW5nIHRoZSBjaGFyYWN0ZXJpc3RpY3MNCj4+ICsgICAg
ICAgICAgICAgICAgICAgICBvZiB0aGlzIHNlcnZpY2UuIFRoaXMgcHJvcGVydHkgaXMgc2V0IG9u
bHkgd2hlbiB0aGUNCj4+ICsgICAgICAgICAgICAgICAgICAgICBjaGFyYWN0ZXJpc3RpYyBkaXNj
b3ZlcnkgaGFzIGJlZW4gY29tcGxldGVkLCBob3dldmVyIHRoZQ0KPj4gKyAgICAgICAgICAgICAg
ICAgICAgIGNoYXJhY3RlcmlzdGljIG9iamVjdHMgd2lsbCBiZWNvbWUgYXZhaWxhYmxlIHZpYQ0K
Pj4gKyAgICAgICAgICAgICAgICAgICAgIE9iamVjdE1hbmFnZXIgYXMgc29vbiBhcyB0aGV5IGdl
dCBkaXNjb3ZlcmVkLg0KPiBGb3IgdGhpcyBuZXcgcHJvcGVydHksIEkgdGhpbmsgdGhlcmUgaXMg
bm90IGVzc2VudGlhbCBhcyBvdGhlciANCj4gcHJvcGVydHksIGJlY2F1c2Ugd2hlbiBjaGFyYWN0
ZXJpc3RpYyBkaXNjb3ZlcnkgaGFwcGVuICwgYWxsIHRoZSANCj4gb2JqZWN0IHBhdGggd2lsbCBz
ZXR1cCBvbiBEQnVzIEhpZXJhcmNoeS4gQW5kIHVzZXIgY2FuIGdldCBhbGwgdGhlIGNoYXJhY3Rl
cmlzdGljIGJ5IE9iamVjdE1hbmdlci4NCg0KVGhlIHByb2JsZW0gaXMgdGhhdCBPYmplY3RNYW5h
Z2VyIGhhcyBubyBjbGVhciB3YXkgdG8gdGVsbCBhIGNsaWVudCB0aGF0ICJ0aGlzIHN1YnNldCBv
ZiBvYmplY3QgcGF0aHMgaGF2ZSBiZWVuIHB1Ymxpc2hlZCIgYW5kIHdoZW4gdGhleSBhcmUgYWxs
IGF2YWlsYWJsZSB2aWEgR2V0TWFuYWdlZE9iamVjdHMuIFRoZSBtb3N0IGEgY2xpZW50IGNhbiBk
byBpcyBvYnNlcnZlIHRoZSBJbnRlcmZhY2VzQWRkZWQgc2lnbmFsIGFuZCB0aGF0IHNpZ25hbCBp
cyBzZW50IG9uIGEgcGVyIG9iamVjdCBwYXRoIGJhc2lzLiBGb3IgbW9zdCBleHRlcm5hbCBhcHBs
aWNhdGlvbnMsIGl0IG1pZ2h0IGJlIGVub3VnaCBidXQgSSB3b3VsZCBsaWtlIGFwcGxpY2F0aW9u
IEFQSXMgdG8gaGF2ZSB0byBhYmlsaXR5IHRvIHNheSAiYWxsIG9iamVjdHMgcHVibGlzaGVkLCBz
ZXJ2aWNlIGlzIHJlYWR5IHRvIHVzZSIuDQoNCg0KPiBUaHJvdWdoIHRoaXMsIFVzZXIgY2FuIHVz
ZSB0aGVpciBvd24gc3RydWN0dXJlIHRvIGdldCB0aGlzIGFycmF5IG9mIG9iamVjdC4NCj4gVGhh
dCBpcyBhbHNvIHdoeSB3ZSBuZWVkIG9iamVjdCBwcm9wZXJ0eSBzdWNoIGFzIERldmljZSwgU2Vy
dmljZSBhbmQgc28gb24uDQo+DQo+IEFuZCBhbm90aGVyIHJlYXNvbiAsIGl0IGhhdmUgdG8gd2Fp
dCBmb3IgY2hhcmFjdGVyaXN0aWMgZGlzY292ZXJ5IA0KPiBjb21wbGV0ZWQsIGl0IGFsc28gY2Fu
IHNheSB0aGF0IGl0IGhhdmUgdG8gd2FpdCBmb3IgY2hhcmFjdGVyaXN0aWMgDQo+IHNldHVwIERC
dXMgSGlyYXJjaHkgaXMgcmVhZHkuIFRoZXJlIGV4aXN0cyBhc3luY2hyb25vdXMgaXNzdWVzLCBp
ZiANCj4gdXNlciBnZXQgdGhpcyBwcm9wZXJ0eSBvcGVyYXRpb24gYmVmb3JlIGFsbCB0aGUgY2hh
cmFjdGVyaXN0aWMgREJ1cyBzZXR1cCBpcyByZWFkeSwgaXQgd2lsbCBtYWtlIGEgbWlzdGFrZS4N
Cj4NCg0KVGhpcyBpcyBleGFjdGx5IHRoZSBwcm9ibGVtLiBBIHNpbXBsZSB1cGRhdGUgb2YgdGhp
cyBwcm9wZXJ0eSBsZXRzIHRoZSB1c2VyIGtub3cgdGhhdCB0aGUgaGllcmFyY2h5IGhhcyBiZWVu
IHNldCB1cC4gRm9yIGFsbCBJIGNhcmUsIHRoaXMgY291bGQgZXZlbiBiZSBhIHNpbXBsZSBib29s
ZWFuIHByb3BlcnR5IHN1Y2ggYXMgIkRpc2NvdmVyeUNvbXBsZXRlIg0KYnV0IEkga2luZCBvZiBs
aWtlIHRoZSBsaXN0IG9mIGNoYXJhY3RlcmlzdGljcyBldmVuIHRob3VnaCBHZXRNYW5hZ2VkT2Jq
ZWN0cy9JbnRlcmZhY2VzQWRkZWQsIGFzIHlvdSBzYXksIGNhbiBhY2hpZXZlIHRoZSBzYW1lIHJl
c3VsdC4gV2UgaGF2ZSB0aGUgc2ltaWxhciAiSW5jbHVkZXMiIHByb3BlcnR5IGFscmVhZHksIHNv
IGl0J3Mgbm90IGVudGlyZWx5IGluY29uc2lzdGVudCBmcm9tIGFuIEFQSSBzdGFuZHBvaW50Lg0K
DQoNCj4+ICsgICAgICAgICAgICAgdm9pZCBTdGFydE5vdGlmeSgpDQo+PiArDQo+PiArICAgICAg
ICAgICAgICAgICAgICAgU3RhcnRzIGEgbm90aWZpY2F0aW9uIHNlc3Npb24gZnJvbSB0aGlzIGNo
YXJhY3RlcmlzdGljDQo+PiArICAgICAgICAgICAgICAgICAgICAgaWYgaXQgc3VwcG9ydHMgdmFs
dWUgbm90aWZpY2F0aW9ucyBvciBpbmRpY2F0aW9ucy4NCj4+ICsNCj4+ICsgICAgICAgICAgICAg
ICAgICAgICBQb3NzaWJsZSBFcnJvcnM6IG9yZy5ibHVlei5FcnJvci5GYWlsZWQNCj4+ICsgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZy5ibHVlei5FcnJvci5JblByb2dy
ZXNzDQo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmcuYmx1ZXou
RXJyb3IuTm90U3VwcG9ydGVkDQo+IEFib3V0IHRoaXMgbWV0aG9kICwgSSB0aGluayBvdGhlciBM
RSBwcm9maWxlIG9mZmVyIHNpbWlsYXIgaW50ZXJmYWNlIA0KPiB0byB1c2VyLCBzdWNoIGFzIGlu
IGhlYXJ0cmF0ZSBwcm9maWxlLiBJdCB3aWxsIGdpdmUgcmVnaXN0ZXJ3YXRjaGVyIA0KPiBtZXRo
b2QsIGluIHdoaWNoIGl0IHdpbGwgZW5hYmxlIG5vdGlmeSBmb3IgaGVhcnRyYXRlLiBUaGlzIHdp
bGwgaGVscCANCj4gdG8gdHJhY2UgZGVzY3JpcHRvciBpbmNsdWRpbmcgbm90aWZpY2F0aW9uIGJp
dCBjaGFuZ2VkIGFuZCBzZW5kIFByb3BlcnR5Y2hhbmdlZCBzaWduYWwuDQoNCkFyZSB5b3UgcmVm
ZXJyaW5nIHRvIHRoZSBIZWFydFJhdGVNYW5hZ2VyMSBoaWVyYXJjaHk/IFNpbmNlIHdlJ3JlIG5v
dyBidWlsZGluZyBhIGdlbmVyaWMgQVBJLCB3ZSBuZWVkIGEgcHJvcGVyIHdheSBvZiByZWZlcmVu
Y2UtY291bnRlZCwgcGVyLWNvbm5lY3Rpb24gd2F5IHRvIGFjY2VzcyB0aGUgQ2xpZW50IENoYXJh
Y3RlcmlzdGljIENvbmZpZ3VyYXRpb24gZGVzY3JpcHRvci4gSW4gdGhpcyBwcm9wb3NhbCwgY2Fs
bGluZyBXcml0ZVZhbHVlIG9uIHRoZSBDQ0MgZGVzY3JpcHRvciB3aWxsIGFsd2F5cyBmYWlsIHdp
dGggV3JpdGVOb3RQZXJtaXR0ZWQuDQoNCkRvIHlvdSBoYXZlIGFueSBzdWdnZXN0aW9ucyBmb3Ig
dGhlIG1ldGhvZCBuYW1lIG9yIGFyZSB5b3UgT0sgd2l0aCBTdGFydE5vdGlmeSBmb3Igbm93PyBX
ZSBjYW4gYWx3YXlzIGNoYW5nZSBpdCBsYXRlci4NCg0KDQo+ICJJbnN1ZmZpY2llbnQgQXV0aG9y
aXphdGlvbiIgc2VlbXMgZGlmZmVyZW50IGZyb20gdGhlIG90aGVyIHR3byBpbiANCj4gdGhhdCBp
dCdzIHNvbWV0aGluZyB0aGF0IGNhbid0IGJlIGF0dGVtcHRlZCB0byBiZSAiZml4ZWQiIGZyb20g
dGhlIA0KPiBjbGllbnQgc2lkZS4gSXQgZWZmZWN0aXZlbHkgbWVhbnMgdGhhdCBvdXIgcmVxdWVz
dCB3YXMgcmVqZWN0ZWQgYnkgdGhlIA0KPiByZW1vdGUgdXNlciwgZG9lc24ndCBpdD8NCg0KR29v
ZCBwb2ludCwgdGhlcmUgaXMgcmVhbGx5IG5vdCBtdWNoIGJsdWV0b290aGQgb3IgdGhlIGV4dGVy
bmFsIGFwcCBjYW4gZG8gaW4gdGhpcyBjYXNlIHNvIHdlIHNob3VsZCBwcm9iYWJseSBwcm9wYWdh
dGUgdGhlIGF1dGhlbnRpY2F0aW9uIGVycm9yIHNlcGFyYXRlbHkgZnJvbSB0aGUgTm90UGFpcmVk
IGNhc2VzLiBPciBkbyB5b3UgdGhpbmsgdGhhdCBpdCB3b3VsZCBiZSBiZW5lZmljaWFsIHRvIGhh
dmUgc2VwYXJhdGUgZXJyb3IgZGVmaW5pdGlvbnMgZm9yIEVuY3J5cHRpb24gYW5kIEF1dGhlbnRp
Y2F0aW9uIGFzIHdlbGw/IEhhdmluZyBFcnJvci5Ob3RQYWlyZWQgYW5kIEVycm9yLkF1dGhlbnRp
Y2F0aW9uIHNlZW1zIHJlYXNvbmFibGUgdG8gbWUuDQoNCkNoZWVycywNCkFybWFuDQo=

2014-07-23 05:24:16

by Marcin Kraglak

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,

On 22 July 2014 22:40, Arman Uguray <[email protected]> wrote:
> Hi Chaojie, Johan,
>
> Please see my responses inline:
>
>
>>> + array{object} Characteristics [read-only]
>>> +
>>> + Array of object paths representing the characteristics
>>> + of this service. This property is set only when the
>>> + characteristic discovery has been completed, however the
>>> + characteristic objects will become available via
>>> + ObjectManager as soon as they get discovered.
>> For this new property, I think there is not essential as other property,
>> because when characteristic discovery happen , all the object path will setup
>> on DBus Hierarchy. And user can get all the characteristic by ObjectManger.
>
> The problem is that ObjectManager has no clear way to tell a client
> that "this subset of object paths have been published" and when they
> are all available via GetManagedObjects. The most a client can do is
> observe the InterfacesAdded signal and that signal is sent on a per
> object path basis. For most external applications, it might be enough
> but I would like application APIs to have to ability to say "all
> objects published, service is ready to use".
>
>
>> Through this, User can use their own structure to get this array of object.
>> That is also why we need object property such as Device, Service and so on.
>>
>> And another reason , it have to wait for characteristic discovery completed, it
>> also can say that it have to wait for characteristic setup DBus Hirarchy is
>> ready. There exists asynchronous issues, if user get this property operation
>> before all the characteristic DBus setup is ready, it will make a mistake.
>>
>
> This is exactly the problem. A simple update of this property lets the
> user know that the hierarchy has been set up. For all I care, this
> could even be a simple boolean property such as "DiscoveryComplete"
> but I kind of like the list of characteristics even though
> GetManagedObjects/InterfacesAdded, as you say, can achieve the same
> result. We have the similar "Includes" property already, so it's not
> entirely inconsistent from an API standpoint.
>
>
>>> + void StartNotify()
>>> +
>>> + Starts a notification session from this characteristic
>>> + if it supports value notifications or indications.
>>> +
>>> + Possible Errors: org.bluez.Error.Failed
>>> + org.bluez.Error.InProgress
>>> + org.bluez.Error.NotSupported
>> About this method , I think other LE profile offer similar interface to user,
>> such as in heartrate profile. It will give registerwatcher method, in which
>> it will enable notify for heartrate. This will help to trace descriptor
>> including notification bit changed and send Propertychanged signal.
>
> Are you referring to the HeartRateManager1 hierarchy? Since we're now
> building a generic API, we need a proper way of reference-counted,
> per-connection way to access the Client Characteristic Configuration
> descriptor. In this proposal, calling WriteValue on the CCC descriptor
> will always fail with WriteNotPermitted.
>
> Do you have any suggestions for the method name or are you OK with
> StartNotify for now? We can always change it later.
>
>
>> "Insufficient Authorization" seems different from the other two in that
>> it's something that can't be attempted to be "fixed" from the client
>> side. It effectively means that our request was rejected by the remote
>> user, doesn't it?
>
> Good point, there is really not much bluetoothd or the external app
> can do in this case so we should probably propagate the authentication
> error separately from the NotPaired cases. Or do you think that it
> would be beneficial to have separate error definitions for Encryption
> and Authentication as well? Having Error.NotPaired and
> Error.Authentication seems reasonable to me.

Error.Authorization seems to be higher layer specific:

"The authorization requirements for access
to a given attribute are not defined in this specification. Each
device implemen-
tation will determine how authorization occurs. Authorization procedures are
defined in GAP, and may be further refined in a higher layer specification."

so it seems reasonable to send this error to application.
We could also add Invalid Value Length error.

>
> Cheers,
> Arman
> --
> 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

BR
Marcin

2014-07-22 20:40:48

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Chaojie, Johan,

Please see my responses inline:


>> + array{object} Characteristics [read-only]
>> +
>> + Array of object paths representing the characteristics
>> + of this service. This property is set only when the
>> + characteristic discovery has been completed, however the
>> + characteristic objects will become available via
>> + ObjectManager as soon as they get discovered.
> For this new property, I think there is not essential as other property,
> because when characteristic discovery happen , all the object path will setup
> on DBus Hierarchy. And user can get all the characteristic by ObjectManger.

The problem is that ObjectManager has no clear way to tell a client
that "this subset of object paths have been published" and when they
are all available via GetManagedObjects. The most a client can do is
observe the InterfacesAdded signal and that signal is sent on a per
object path basis. For most external applications, it might be enough
but I would like application APIs to have to ability to say "all
objects published, service is ready to use".


> Through this, User can use their own structure to get this array of object.
> That is also why we need object property such as Device, Service and so on.
>
> And another reason , it have to wait for characteristic discovery completed, it
> also can say that it have to wait for characteristic setup DBus Hirarchy is
> ready. There exists asynchronous issues, if user get this property operation
> before all the characteristic DBus setup is ready, it will make a mistake.
>

This is exactly the problem. A simple update of this property lets the
user know that the hierarchy has been set up. For all I care, this
could even be a simple boolean property such as "DiscoveryComplete"
but I kind of like the list of characteristics even though
GetManagedObjects/InterfacesAdded, as you say, can achieve the same
result. We have the similar "Includes" property already, so it's not
entirely inconsistent from an API standpoint.


>> + void StartNotify()
>> +
>> + Starts a notification session from this characteristic
>> + if it supports value notifications or indications.
>> +
>> + Possible Errors: org.bluez.Error.Failed
>> + org.bluez.Error.InProgress
>> + org.bluez.Error.NotSupported
> About this method , I think other LE profile offer similar interface to user,
> such as in heartrate profile. It will give registerwatcher method, in which
> it will enable notify for heartrate. This will help to trace descriptor
> including notification bit changed and send Propertychanged signal.

Are you referring to the HeartRateManager1 hierarchy? Since we're now
building a generic API, we need a proper way of reference-counted,
per-connection way to access the Client Characteristic Configuration
descriptor. In this proposal, calling WriteValue on the CCC descriptor
will always fail with WriteNotPermitted.

Do you have any suggestions for the method name or are you OK with
StartNotify for now? We can always change it later.


> "Insufficient Authorization" seems different from the other two in that
> it's something that can't be attempted to be "fixed" from the client
> side. It effectively means that our request was rejected by the remote
> user, doesn't it?

Good point, there is really not much bluetoothd or the external app
can do in this case so we should probably propagate the authentication
error separately from the NotPaired cases. Or do you think that it
would be beneficial to have separate error definitions for Encryption
and Authentication as well? Having Error.NotPaired and
Error.Authentication seems reasonable to me.

Cheers,
Arman

2014-07-22 08:55:07

by Johan Hedberg

[permalink] [raw]
Subject: Re: [RFC v1 0/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,

On Mon, Jul 21, 2014, Arman Uguray wrote:
> - Replaced the "Authentication", "Authorization", and "Encryption" errors
> with a simpler "NotPaired" error, since there's not much the external
> application can do on these errors other than try to pair. bluetoothd will
> automatically attempt to raise the security level of the connection on
> these errors.

"Insufficient Authorization" seems different from the other two in that
it's something that can't be attempted to be "fixed" from the client
side. It effectively means that our request was rejected by the remote
user, doesn't it?

Johan


2014-07-22 08:38:37

by Gu, Chao Jie

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

On Mon, Jul 21, 2014 at 04:40:34PM -0700, Arman Uguray wrote:
Through the disscussion , I think this proposal make lots of sense. Below is my
thought about new property and method.
> This patch proposes changes to the currently unimplemented GATT D-Bus API for
> desktop bluetoothd. This is the first step in implementing a GATT client layer
> for bluetoothd that will change the way remote attributes are accessed via
> bluetoothd plugins and external applications.
> ---
> doc/gatt-api.txt | 118 +++++++++++++++++++++++++++++++++++++++++++++++++------
> 1 file changed, 106 insertions(+), 12 deletions(-)
>
> diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
> index 8c7975c..741bd18 100644
> --- a/doc/gatt-api.txt
> +++ b/doc/gatt-api.txt
> @@ -32,6 +32,25 @@ Properties string UUID [read-only]
>
> 128-bit service UUID.
>
> + boolean Primary [read-only]
> +
> + Indicates whether or not this GATT service is a
> + primary service. If false, the service is secondary.
> +
This is useful to help user differenciate between primary and secondary.
> + object Device [read-only, optional]
> +
> + Object path of the Bluetooth device the service
> + belongs to. Only present on services from remote
> + devices.
This property is to get which service belong to which device, just like other
hierachy interfaces do, such as org.bluez.Device1, org.bluez.GattService1 ...
> + array{object} Characteristics [read-only]
> +
> + Array of object paths representing the characteristics
> + of this service. This property is set only when the
> + characteristic discovery has been completed, however the
> + characteristic objects will become available via
> + ObjectManager as soon as they get discovered.
For this new property, I think there is not essential as other property,
because when characteristic discovery happen , all the object path will setup
on DBus Hierarchy. And user can get all the characteristic by ObjectManger.
Through this, User can use their own structure to get this array of object.
That is also why we need object property such as Device, Service and so on.

And another reason , it have to wait for characteristic discovery completed, it
also can say that it have to wait for characteristic setup DBus Hirarchy is
ready. There exists asynchronous issues, if user get this property operation
before all the characteristic DBus setup is ready, it will make a mistake.

Let user get all the characteristics under the service by DBus Hierarchy, it
will be no problem.

All in one, I think this property that user can get by existing DBus
Information already .

> array{object} Includes [read-only]: Not implemented
>
> Array of object paths representing the included
> @@ -48,6 +67,47 @@ Service org.bluez
> Interface org.bluez.GattCharacteristic1 [Experimental]
> Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY
>
> +Methods array{byte} ReadValue()
> +
> + Issues a request to read the value of the
> + characteristic and returns the value if the
> + operation was successful.
> +
> + Possible Errors: org.bluez.Error.Failed
> + org.bluez.Error.InProgress
> + org.bluez.Error.ReadNotPermitted
> + org.bluez.Error.NotPaired
> + org.bluez.Error.NotSupported
By my Implementaion old dbus-api testing, I found most characteristic will not
changed. So in previous email that I said listen for characteristic notification
such as heartrate. But this also very useful especially control point characteristic
to ensure the value has been written into remote device and send PropertyChanged
signal. I agree with you.
> + void WriteValue(array{byte} value)
> +
> + Issues a request to write the value of the
> + characteristic.
> +
> + Possible Errors: org.bluez.Error.Failed
> + org.bluez.Error.InProgress
> + org.bluez.Error.WriteNotPermitted
> + org.bluez.Error.NotPaired
> + org.bluez.Error.NotSupported
Let characteristic value property be read-only, this make sense.
> + void StartNotify()
> +
> + Starts a notification session from this characteristic
> + if it supports value notifications or indications.
> +
> + Possible Errors: org.bluez.Error.Failed
> + org.bluez.Error.InProgress
> + org.bluez.Error.NotSupported
About this method , I think other LE profile offer similar interface to user,
such as in heartrate profile. It will give registerwatcher method, in which
it will enable notify for heartrate. This will help to trace descriptor
including notification bit changed and send Propertychanged signal.
> + void StopNotify()
> +
> + This method will cancel any previous StartNotify
> + transaction. Note that notifications from a
> + characteristic are shared between sessions thus
> + calling StopNotify will release a single session.
> +
> + Possible Errors: org.bluez.Error.Failed
> +
> Properties string UUID [read-only]
>
> 128-bit characteristic UUID.
> @@ -57,12 +117,19 @@ Properties string UUID [read-only]
> Object path of the GATT service the characteristc
> belongs to.
>
> - array{byte} Value [read-write]
> + array{byte} Value [read-only, optional]
> +
> + The cached value of the characteristic. This property
> + gets updated only after a successful read request and
> + when a notification or indication is received, upon
> + which a PropertiesChanged signal will be emitted.
>
> - Value read from the remote Bluetooth device or from
> - the external application implementing GATT services.
> + boolean Notifying [read-only]
>
> - array{string} Flags [read-only, optional]
> + True, if notifications or indications on this
> + characteristic are currently enabled.
> +
> + array{string} Flags [read-only]
>
> Defines how the characteristic value can be used. See
> Core spec "Table 3.5: Characteristic Properties bit
> @@ -79,6 +146,14 @@ Properties string UUID [read-only]
> "reliable-write"
> "writable-auxiliaries"
>
> + array{object} Descriptors [read-only]
> +
> + Array of object paths representing the descriptors
> + of this service. This property is set only when the
> + descriptor discovery has been completed, however the
> + descriptor objects will become available via
> + ObjectManager as soon as they get discovered.
> +
>
> Characteristic Descriptors hierarchy
> ====================================
> @@ -89,6 +164,29 @@ Service org.bluez
> Interface org.bluez.GattDescriptor1 [Experimental]
> Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ
>
> +Methods array{byte} ReadValue()
> +
> + Issues a request to read the value of the
> + characteristic and returns the value if the
> + operation was successful.
> +
> + Possible Errors: org.bluez.Error.Failed
> + org.bluez.Error.InProgress
> + org.bluez.Error.ReadNotPermitted
> + org.bluez.Error.NotPaired
> + org.bluez.Error.NotSupported
> +
> + void WriteValue(array{byte} value)
> +
> + Issues a request to write the value of the
> + characteristic.
> +
> + Possible Errors: org.bluez.Error.Failed
> + org.bluez.Error.InProgress
> + org.bluez.Error.WriteNotPermitted
> + org.bluez.Error.NotPaired
> + org.bluez.Error.NotSupported
> +
> Properties string UUID [read-only]
>
> 128-bit descriptor UUID.
> @@ -98,16 +196,12 @@ Properties string UUID [read-only]
> Object path of the GATT characteristc the descriptor
> belongs to.
>
> - array{byte} Value [read-write]
> -
> - Raw characteristic descriptor value read from the
> - remote Bluetooth device or from the external
> - application implementing GATT services.
> + array{byte} Value [read-only, optional]
>
> - string Permissions [read-only]: To be defined
> + The cached value of the descriptor. This property
> + gets updated only after a successful read request, upon
> + which a PropertiesChanged signal will be emitted.
>
> - Defines read/write authentication and authorization
> - requirements.
>
> Service Manager hierarchy
> =============================
> --
> 2.0.0.526.g5318336
>
> --
> 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

2014-07-21 23:40:34

by Arman Uguray

[permalink] [raw]
Subject: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

This patch proposes changes to the currently unimplemented GATT D-Bus API for
desktop bluetoothd. This is the first step in implementing a GATT client layer
for bluetoothd that will change the way remote attributes are accessed via
bluetoothd plugins and external applications.
---
doc/gatt-api.txt | 118 +++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 106 insertions(+), 12 deletions(-)

diff --git a/doc/gatt-api.txt b/doc/gatt-api.txt
index 8c7975c..741bd18 100644
--- a/doc/gatt-api.txt
+++ b/doc/gatt-api.txt
@@ -32,6 +32,25 @@ Properties string UUID [read-only]

128-bit service UUID.

+ boolean Primary [read-only]
+
+ Indicates whether or not this GATT service is a
+ primary service. If false, the service is secondary.
+
+ object Device [read-only, optional]
+
+ Object path of the Bluetooth device the service
+ belongs to. Only present on services from remote
+ devices.
+
+ array{object} Characteristics [read-only]
+
+ Array of object paths representing the characteristics
+ of this service. This property is set only when the
+ characteristic discovery has been completed, however the
+ characteristic objects will become available via
+ ObjectManager as soon as they get discovered.
+
array{object} Includes [read-only]: Not implemented

Array of object paths representing the included
@@ -48,6 +67,47 @@ Service org.bluez
Interface org.bluez.GattCharacteristic1 [Experimental]
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY

+Methods array{byte} ReadValue()
+
+ Issues a request to read the value of the
+ characteristic and returns the value if the
+ operation was successful.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.ReadNotPermitted
+ org.bluez.Error.NotPaired
+ org.bluez.Error.NotSupported
+
+ void WriteValue(array{byte} value)
+
+ Issues a request to write the value of the
+ characteristic.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.WriteNotPermitted
+ org.bluez.Error.NotPaired
+ org.bluez.Error.NotSupported
+
+ void StartNotify()
+
+ Starts a notification session from this characteristic
+ if it supports value notifications or indications.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.NotSupported
+
+ void StopNotify()
+
+ This method will cancel any previous StartNotify
+ transaction. Note that notifications from a
+ characteristic are shared between sessions thus
+ calling StopNotify will release a single session.
+
+ Possible Errors: org.bluez.Error.Failed
+
Properties string UUID [read-only]

128-bit characteristic UUID.
@@ -57,12 +117,19 @@ Properties string UUID [read-only]
Object path of the GATT service the characteristc
belongs to.

- array{byte} Value [read-write]
+ array{byte} Value [read-only, optional]
+
+ The cached value of the characteristic. This property
+ gets updated only after a successful read request and
+ when a notification or indication is received, upon
+ which a PropertiesChanged signal will be emitted.

- Value read from the remote Bluetooth device or from
- the external application implementing GATT services.
+ boolean Notifying [read-only]

- array{string} Flags [read-only, optional]
+ True, if notifications or indications on this
+ characteristic are currently enabled.
+
+ array{string} Flags [read-only]

Defines how the characteristic value can be used. See
Core spec "Table 3.5: Characteristic Properties bit
@@ -79,6 +146,14 @@ Properties string UUID [read-only]
"reliable-write"
"writable-auxiliaries"

+ array{object} Descriptors [read-only]
+
+ Array of object paths representing the descriptors
+ of this service. This property is set only when the
+ descriptor discovery has been completed, however the
+ descriptor objects will become available via
+ ObjectManager as soon as they get discovered.
+

Characteristic Descriptors hierarchy
====================================
@@ -89,6 +164,29 @@ Service org.bluez
Interface org.bluez.GattDescriptor1 [Experimental]
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY/descriptorZZZ

+Methods array{byte} ReadValue()
+
+ Issues a request to read the value of the
+ characteristic and returns the value if the
+ operation was successful.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.ReadNotPermitted
+ org.bluez.Error.NotPaired
+ org.bluez.Error.NotSupported
+
+ void WriteValue(array{byte} value)
+
+ Issues a request to write the value of the
+ characteristic.
+
+ Possible Errors: org.bluez.Error.Failed
+ org.bluez.Error.InProgress
+ org.bluez.Error.WriteNotPermitted
+ org.bluez.Error.NotPaired
+ org.bluez.Error.NotSupported
+
Properties string UUID [read-only]

128-bit descriptor UUID.
@@ -98,16 +196,12 @@ Properties string UUID [read-only]
Object path of the GATT characteristc the descriptor
belongs to.

- array{byte} Value [read-write]
-
- Raw characteristic descriptor value read from the
- remote Bluetooth device or from the external
- application implementing GATT services.
+ array{byte} Value [read-only, optional]

- string Permissions [read-only]: To be defined
+ The cached value of the descriptor. This property
+ gets updated only after a successful read request, upon
+ which a PropertiesChanged signal will be emitted.

- Defines read/write authentication and authorization
- requirements.

Service Manager hierarchy
=============================
--
2.0.0.526.g5318336


2014-08-11 20:38:38

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Marcel,

> then send me a patch that updates the API documentation for what it is suppose to be and deletes pieces are obsolete now.
>

Sent v2 with the most recent feedback addressed.

-Arman

2014-08-11 19:03:33

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Arman,

>> I have no major objections to the API, but just an API description is not enough. What is important to also deliver an implementation of this API.
>>
>
> The implementation will come in the next few months as the shared
> stack takes shape. The thing is, the existing proposal is not
> accompanied by an implementation (it's not even included in the
> release bundles) either and it looks like there are several parties
> that are implementing their own version of the API based on the
> unimplemented proposal. I think it makes sense to update it with the
> changes that we discussed so that people can plan their code for
> future compatibility.
>
> Either that or remove doc/gatt-api.txt entirely for the time being.

then send me a patch that updates the API documentation for what it is suppose to be and deletes pieces are obsolete now.

Regards

Marcel


2014-08-11 18:46:00

by Arman Uguray

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Marcel,

> I have no major objections to the API, but just an API description is not enough. What is important to also deliver an implementation of this API.
>

The implementation will come in the next few months as the shared
stack takes shape. The thing is, the existing proposal is not
accompanied by an implementation (it's not even included in the
release bundles) either and it looks like there are several parties
that are implementing their own version of the API based on the
unimplemented proposal. I think it makes sense to update it with the
changes that we discussed so that people can plan their code for
future compatibility.

Either that or remove doc/gatt-api.txt entirely for the time being.

-Arman

2014-08-11 17:49:06

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

Hi Chaojie,

the mailing list policy is to NOT top post. So please keep that in mind and do proper inline quoting.

> For the New Gatt DBus API definition is important for user to use, so through the discussion, arman's proposal make much sense.
> Will this proposal be accepted and when wiil bluez announces new Gatt API ?

I have no major objections to the API, but just an API description is not enough. What is important to also deliver an implementation of this API.

Regards

Marcel


2014-08-11 09:56:28

by Gu, Chao Jie

[permalink] [raw]
Subject: RE: [RFC v1 1/1] doc/gatt-api: New API properties and methods for the GATT D-Bus API.

SGkgbWFyY2VsLA0KCUZvciB0aGUgTmV3IEdhdHQgREJ1cyBBUEkgZGVmaW5pdGlvbiBpcyBpbXBv
cnRhbnQgZm9yIHVzZXIgdG8gdXNlLCBzbyB0aHJvdWdoIHRoZSBkaXNjdXNzaW9uLCBhcm1hbidz
IHByb3Bvc2FsIG1ha2UgbXVjaCBzZW5zZS4NCglXaWxsIHRoaXMgcHJvcG9zYWwgYmUgYWNjZXB0
ZWQgYW5kIHdoZW4gd2lpbCBibHVleiBhbm5vdW5jZXMgbmV3IEdhdHQgQVBJID8NCiANClRoYW5r
cw0KQ2hhb2ppZQ0KPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBsaW51eC1i
bHVldG9vdGgtb3duZXJAdmdlci5rZXJuZWwub3JnDQo+IFttYWlsdG86bGludXgtYmx1ZXRvb3Ro
LW93bmVyQHZnZXIua2VybmVsLm9yZ10gT24gQmVoYWxmIE9mIEFybWFuIFVndXJheQ0KPiBTZW50
OiBGcmlkYXksIEF1Z3VzdCAwMSwgMjAxNCAxMToxMSBBTQ0KPiBUbzogTWFyY2VsIEhvbHRtYW5u
DQo+IENjOiBHdSwgQ2hhbyBKaWU7IGxpbnV4LWJsdWV0b290aEB2Z2VyLmtlcm5lbC5vcmcNCj4g
U3ViamVjdDogUmU6IFtSRkMgdjEgMS8xXSBkb2MvZ2F0dC1hcGk6IE5ldyBBUEkgcHJvcGVydGll
cyBhbmQgbWV0aG9kcyBmb3IgdGhlDQo+IEdBVFQgRC1CdXMgQVBJLg0KPiANCj4gSGkgTWFyY2Vs
LA0KPiANCj4gSSB0aGluayB0aGlzIGFsbCBtYWtlcyBzZW5zZSBhbmQgdGhlIEFQSSBpcyBpbiBh
IHJlYXNvbmFibGUgc2hhcGUgbm93Lg0KPiBBbGwgb2YgdGhlIHByb3BlcnRpZXMvbWV0aG9kcyBj
YW4gaW50ZWdyYXRlIG5pY2VseSB3aXRoIGNsaWVudCBhbmQgc2VydmVyDQo+IGltcGxlbWVudGF0
aW9ucyAod2l0aCBvbmUgb3IgdHdvIHByb3BlcnRpZXMgYmVpbmcgb3B0aW9uYWwgZm9yIHNlcnZl
cikuIEkgdGhpbmsNCj4gd2UgY2FuIHJldmlzaXQgR2F0dE1hbmFnZXIxIG9uY2Ugd2Ugc3RhcnQg
dGhpbmtpbmcgYWJvdXQgdGhlIHNlcnZlciBjb2RlIGJ1dA0KPiBmb3Igbm93IEkgdGhpbmsgdGhp
cyBpcyBnb29kIGZvciBjbGllbnQuDQo+IEFuZCwgb2YgY291cnNlLCB3ZSBjYW4gYWx3YXlzIGFk
ZCBuZXcgcHJvcGVydGllcy9tZXRob2RzIGxhdGVyLg0KPiAtLQ0KPiBUbyB1bnN1YnNjcmliZSBm
cm9tIHRoaXMgbGlzdDogc2VuZCB0aGUgbGluZSAidW5zdWJzY3JpYmUgbGludXgtYmx1ZXRvb3Ro
IiBpbiB0aGUNCj4gYm9keSBvZiBhIG1lc3NhZ2UgdG8gbWFqb3Jkb21vQHZnZXIua2VybmVsLm9y
ZyBNb3JlIG1ham9yZG9tbyBpbmZvIGF0DQo+IGh0dHA6Ly92Z2VyLmtlcm5lbC5vcmcvbWFqb3Jk
b21vLWluZm8uaHRtbA0K