2019-01-31 16:16:17

by Emil Lenngren

[permalink] [raw]
Subject: Flag for specifying write type to WriteValue in gatt-api.

Hi,

I was looking through the quite lengthy discussion at
https://github.com/WebBluetoothCG/web-bluetooth/issues/238 on the
issue that in Web-Bluetooth, only a single "write value" API is
available, causing Web-Bluetooth to decide on its own if Write With
Response or Write Without Response should be used, in case both are
supported by the characteristic.

But in the Bluetooth spec about Write Without Response:

"This sub-procedure is used to write a Characteristic Value to a
server when the client knows the Characteristic Value Handle and the
client does not need an acknowledgement that the write was
successfully performed."

Basically, it says it's up to the client/application to decide if an
acknowledgement is needed or not, and hence it's the app that should
decide if Write With or Without Response should be used. The "client"
can't mean a bluetooth stack here since it can of course not know if
an acknowledgement is needed or not.

I noticed that according to gatt-api.txt, BlueZ has the same
limitation in the WriteValue method, in that the stack chooses the
write type "arbitrarily" if both write types are supported (or really
the Write With Response is chosen, which might cause unwanted
latency). Therefore I suggest that an option should be added to the
WriteValue method, for example "write-without-response" (bool) to
force Write Without Response.

Note how iOS has a write type parameter to the write method, and
Android has a write type property you set before you execute the
write.

I see that it might be possible to achieve the same result with
AcquireWrite -> write to socket -> release but that wouldn't be a good
solution for bluetooth stacks built on top of BlueZ that would like to
differentiate between the two write types (such as Web-Bluetooth)
since AcquireWrite can fail, for example if two apps write the value
at the same time (I guess the lock is exclusive?). It also seems like
unnecessary overhead to open and close sockets.

/Emil


2019-01-31 17:03:20

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: Flag for specifying write type to WriteValue in gatt-api.

Hi Emil,

On Thu, Jan 31, 2019 at 6:19 PM Emil Lenngren <[email protected]> wrote:
>
> Hi,
>
> I was looking through the quite lengthy discussion at
> https://github.com/WebBluetoothCG/web-bluetooth/issues/238 on the
> issue that in Web-Bluetooth, only a single "write value" API is
> available, causing Web-Bluetooth to decide on its own if Write With
> Response or Write Without Response should be used, in case both are
> supported by the characteristic.
>
> But in the Bluetooth spec about Write Without Response:
>
> "This sub-procedure is used to write a Characteristic Value to a
> server when the client knows the Characteristic Value Handle and the
> client does not need an acknowledgement that the write was
> successfully performed."
>
> Basically, it says it's up to the client/application to decide if an
> acknowledgement is needed or not, and hence it's the app that should
> decide if Write With or Without Response should be used. The "client"
> can't mean a bluetooth stack here since it can of course not know if
> an acknowledgement is needed or not.

There is a property indicating if write without response is supported
though, but you are right regarding that not excluding regular write
so at that point the client would have a choice whether to use it or
not.

> I noticed that according to gatt-api.txt, BlueZ has the same
> limitation in the WriteValue method, in that the stack chooses the
> write type "arbitrarily" if both write types are supported (or really
> the Write With Response is chosen, which might cause unwanted
> latency). Therefore I suggest that an option should be added to the
> WriteValue method, for example "write-without-response" (bool) to
> force Write Without Response.

It gets a bit trickier if the attribute is in fact a control point in
which case perhaps only write-without-response really works, anyway
control points are better off using AcquireWrite.

> Note how iOS has a write type parameter to the write method, and
> Android has a write type property you set before you execute the
> write.
>
> I see that it might be possible to achieve the same result with
> AcquireWrite -> write to socket -> release but that wouldn't be a good
> solution for bluetooth stacks built on top of BlueZ that would like to
> differentiate between the two write types (such as Web-Bluetooth)
> since AcquireWrite can fail, for example if two apps write the value
> at the same time (I guess the lock is exclusive?). It also seems like
> unnecessary overhead to open and close sockets.

AcquireWrite is to be used when the app needs exclusive access, like
control points such as those commonly used for things like DFU, I
don't think that is your intent here (or is it?) so I guess adding an
option for WriteValue is probably better. Note though that obviously
one cannot use such a flag with things like e.g. offset as that is not
supported which makes the API a little trickier to use but I guess
that ok given that setting flags is optional.

--
Luiz Augusto von Dentz

2019-01-31 17:46:34

by Emil Lenngren

[permalink] [raw]
Subject: Re: Flag for specifying write type to WriteValue in gatt-api.

Hi Luiz,

Den tors 31 jan. 2019 kl 18:03 skrev Luiz Augusto von Dentz
<[email protected]>:
>
> Hi Emil,
>
> On Thu, Jan 31, 2019 at 6:19 PM Emil Lenngren <[email protected]> wrote:
> >
> > Hi,
> >
> > I was looking through the quite lengthy discussion at
> > https://github.com/WebBluetoothCG/web-bluetooth/issues/238 on the
> > issue that in Web-Bluetooth, only a single "write value" API is
> > available, causing Web-Bluetooth to decide on its own if Write With
> > Response or Write Without Response should be used, in case both are
> > supported by the characteristic.
> >
> > But in the Bluetooth spec about Write Without Response:
> >
> > "This sub-procedure is used to write a Characteristic Value to a
> > server when the client knows the Characteristic Value Handle and the
> > client does not need an acknowledgement that the write was
> > successfully performed."
> >
> > Basically, it says it's up to the client/application to decide if an
> > acknowledgement is needed or not, and hence it's the app that should
> > decide if Write With or Without Response should be used. The "client"
> > can't mean a bluetooth stack here since it can of course not know if
> > an acknowledgement is needed or not.
>
> There is a property indicating if write without response is supported
> though, but you are right regarding that not excluding regular write
> so at that point the client would have a choice whether to use it or
> not.
>
> > I noticed that according to gatt-api.txt, BlueZ has the same
> > limitation in the WriteValue method, in that the stack chooses the
> > write type "arbitrarily" if both write types are supported (or really
> > the Write With Response is chosen, which might cause unwanted
> > latency). Therefore I suggest that an option should be added to the
> > WriteValue method, for example "write-without-response" (bool) to
> > force Write Without Response.
>
> It gets a bit trickier if the attribute is in fact a control point in
> which case perhaps only write-without-response really works, anyway
> control points are better off using AcquireWrite.
>
> > Note how iOS has a write type parameter to the write method, and
> > Android has a write type property you set before you execute the
> > write.
> >
> > I see that it might be possible to achieve the same result with
> > AcquireWrite -> write to socket -> release but that wouldn't be a good
> > solution for bluetooth stacks built on top of BlueZ that would like to
> > differentiate between the two write types (such as Web-Bluetooth)
> > since AcquireWrite can fail, for example if two apps write the value
> > at the same time (I guess the lock is exclusive?). It also seems like
> > unnecessary overhead to open and close sockets.
>
> AcquireWrite is to be used when the app needs exclusive access, like
> control points such as those commonly used for things like DFU, I
> don't think that is your intent here (or is it?) so I guess adding an
> option for WriteValue is probably better. Note though that obviously
> one cannot use such a flag with things like e.g. offset as that is not
> supported which makes the API a little trickier to use but I guess
> that ok given that setting flags is optional.

No DFU etc. wasn't really the intention here.

I guess most (all?) people don't use the offset parameter. The reason
the offset parameter exists in the Prepare Write Request is so that
it's possible to write a long value in several chunks I guess. Anyway,
the solution is to simply disallow offset != 0 and
write-without-response=true at the same time.

By the way, I see "Reliable Write" is also forced/first choice if the
characteristic supports that (even though I think nobody uses it?).
The downside of using Reliable Write over a simple Write Request is
that it requires more packets/overhead so I was thinking that maybe,
to cover all cases, instead of having a bool "write-without-response",
it should be a "write-type" option which can take the values
"reliable-write", "write-with-response" or "write-without-response"
(or use automatic logic like today if the option is not specified).
What do you think?

/Emil

2019-01-31 17:55:25

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: Flag for specifying write type to WriteValue in gatt-api.

Hi Emil,

On Thu, Jan 31, 2019 at 7:46 PM Emil Lenngren <[email protected]> wrote:
>
> Hi Luiz,
>
> Den tors 31 jan. 2019 kl 18:03 skrev Luiz Augusto von Dentz
> <[email protected]>:
> >
> > Hi Emil,
> >
> > On Thu, Jan 31, 2019 at 6:19 PM Emil Lenngren <[email protected]> wrote:
> > >
> > > Hi,
> > >
> > > I was looking through the quite lengthy discussion at
> > > https://github.com/WebBluetoothCG/web-bluetooth/issues/238 on the
> > > issue that in Web-Bluetooth, only a single "write value" API is
> > > available, causing Web-Bluetooth to decide on its own if Write With
> > > Response or Write Without Response should be used, in case both are
> > > supported by the characteristic.
> > >
> > > But in the Bluetooth spec about Write Without Response:
> > >
> > > "This sub-procedure is used to write a Characteristic Value to a
> > > server when the client knows the Characteristic Value Handle and the
> > > client does not need an acknowledgement that the write was
> > > successfully performed."
> > >
> > > Basically, it says it's up to the client/application to decide if an
> > > acknowledgement is needed or not, and hence it's the app that should
> > > decide if Write With or Without Response should be used. The "client"
> > > can't mean a bluetooth stack here since it can of course not know if
> > > an acknowledgement is needed or not.
> >
> > There is a property indicating if write without response is supported
> > though, but you are right regarding that not excluding regular write
> > so at that point the client would have a choice whether to use it or
> > not.
> >
> > > I noticed that according to gatt-api.txt, BlueZ has the same
> > > limitation in the WriteValue method, in that the stack chooses the
> > > write type "arbitrarily" if both write types are supported (or really
> > > the Write With Response is chosen, which might cause unwanted
> > > latency). Therefore I suggest that an option should be added to the
> > > WriteValue method, for example "write-without-response" (bool) to
> > > force Write Without Response.
> >
> > It gets a bit trickier if the attribute is in fact a control point in
> > which case perhaps only write-without-response really works, anyway
> > control points are better off using AcquireWrite.
> >
> > > Note how iOS has a write type parameter to the write method, and
> > > Android has a write type property you set before you execute the
> > > write.
> > >
> > > I see that it might be possible to achieve the same result with
> > > AcquireWrite -> write to socket -> release but that wouldn't be a good
> > > solution for bluetooth stacks built on top of BlueZ that would like to
> > > differentiate between the two write types (such as Web-Bluetooth)
> > > since AcquireWrite can fail, for example if two apps write the value
> > > at the same time (I guess the lock is exclusive?). It also seems like
> > > unnecessary overhead to open and close sockets.
> >
> > AcquireWrite is to be used when the app needs exclusive access, like
> > control points such as those commonly used for things like DFU, I
> > don't think that is your intent here (or is it?) so I guess adding an
> > option for WriteValue is probably better. Note though that obviously
> > one cannot use such a flag with things like e.g. offset as that is not
> > supported which makes the API a little trickier to use but I guess
> > that ok given that setting flags is optional.
>
> No DFU etc. wasn't really the intention here.
>
> I guess most (all?) people don't use the offset parameter. The reason
> the offset parameter exists in the Prepare Write Request is so that
> it's possible to write a long value in several chunks I guess. Anyway,
> the solution is to simply disallow offset != 0 and
> write-without-response=true at the same time.
>
> By the way, I see "Reliable Write" is also forced/first choice if the
> characteristic supports that (even though I think nobody uses it?).
> The downside of using Reliable Write over a simple Write Request is
> that it requires more packets/overhead so I was thinking that maybe,
> to cover all cases, instead of having a bool "write-without-response",
> it should be a "write-type" option which can take the values
> "reliable-write", "write-with-response" or "write-without-response"
> (or use automatic logic like today if the option is not specified).
> What do you think?

I would have named it just type since it is for WriteValue we should
not need to repeat the write term on the flags, so Id would go for
type="reliable" (reliable-write), "command" (write-without-response),
"request" (write-with-response). Also, I assume this would force the
operation no matter what the flags indicate so people can work around
if the regular WriteValue don't work for some reason, perhaps the
service is not really adhering to the spec or it is a vendor service
just not setting the properties properly.

> /Emil



--
Luiz Augusto von Dentz

2019-01-31 18:09:42

by Emil Lenngren

[permalink] [raw]
Subject: Re: Flag for specifying write type to WriteValue in gatt-api.

Hi Luiz,

Den tors 31 jan. 2019 kl 18:55 skrev Luiz Augusto von Dentz
<[email protected]>:
>
> Hi Emil,
>
> On Thu, Jan 31, 2019 at 7:46 PM Emil Lenngren <[email protected]> wrote:
> >
> > Hi Luiz,
> >
> > Den tors 31 jan. 2019 kl 18:03 skrev Luiz Augusto von Dentz
> > <[email protected]>:
> > >
> > > Hi Emil,
> > >
> > > On Thu, Jan 31, 2019 at 6:19 PM Emil Lenngren <[email protected]> wrote:
> > > >
> > > > Hi,
> > > >
> > > > I was looking through the quite lengthy discussion at
> > > > https://github.com/WebBluetoothCG/web-bluetooth/issues/238 on the
> > > > issue that in Web-Bluetooth, only a single "write value" API is
> > > > available, causing Web-Bluetooth to decide on its own if Write With
> > > > Response or Write Without Response should be used, in case both are
> > > > supported by the characteristic.
> > > >
> > > > But in the Bluetooth spec about Write Without Response:
> > > >
> > > > "This sub-procedure is used to write a Characteristic Value to a
> > > > server when the client knows the Characteristic Value Handle and the
> > > > client does not need an acknowledgement that the write was
> > > > successfully performed."
> > > >
> > > > Basically, it says it's up to the client/application to decide if an
> > > > acknowledgement is needed or not, and hence it's the app that should
> > > > decide if Write With or Without Response should be used. The "client"
> > > > can't mean a bluetooth stack here since it can of course not know if
> > > > an acknowledgement is needed or not.
> > >
> > > There is a property indicating if write without response is supported
> > > though, but you are right regarding that not excluding regular write
> > > so at that point the client would have a choice whether to use it or
> > > not.
> > >
> > > > I noticed that according to gatt-api.txt, BlueZ has the same
> > > > limitation in the WriteValue method, in that the stack chooses the
> > > > write type "arbitrarily" if both write types are supported (or really
> > > > the Write With Response is chosen, which might cause unwanted
> > > > latency). Therefore I suggest that an option should be added to the
> > > > WriteValue method, for example "write-without-response" (bool) to
> > > > force Write Without Response.
> > >
> > > It gets a bit trickier if the attribute is in fact a control point in
> > > which case perhaps only write-without-response really works, anyway
> > > control points are better off using AcquireWrite.
> > >
> > > > Note how iOS has a write type parameter to the write method, and
> > > > Android has a write type property you set before you execute the
> > > > write.
> > > >
> > > > I see that it might be possible to achieve the same result with
> > > > AcquireWrite -> write to socket -> release but that wouldn't be a good
> > > > solution for bluetooth stacks built on top of BlueZ that would like to
> > > > differentiate between the two write types (such as Web-Bluetooth)
> > > > since AcquireWrite can fail, for example if two apps write the value
> > > > at the same time (I guess the lock is exclusive?). It also seems like
> > > > unnecessary overhead to open and close sockets.
> > >
> > > AcquireWrite is to be used when the app needs exclusive access, like
> > > control points such as those commonly used for things like DFU, I
> > > don't think that is your intent here (or is it?) so I guess adding an
> > > option for WriteValue is probably better. Note though that obviously
> > > one cannot use such a flag with things like e.g. offset as that is not
> > > supported which makes the API a little trickier to use but I guess
> > > that ok given that setting flags is optional.
> >
> > No DFU etc. wasn't really the intention here.
> >
> > I guess most (all?) people don't use the offset parameter. The reason
> > the offset parameter exists in the Prepare Write Request is so that
> > it's possible to write a long value in several chunks I guess. Anyway,
> > the solution is to simply disallow offset != 0 and
> > write-without-response=true at the same time.
> >
> > By the way, I see "Reliable Write" is also forced/first choice if the
> > characteristic supports that (even though I think nobody uses it?).
> > The downside of using Reliable Write over a simple Write Request is
> > that it requires more packets/overhead so I was thinking that maybe,
> > to cover all cases, instead of having a bool "write-without-response",
> > it should be a "write-type" option which can take the values
> > "reliable-write", "write-with-response" or "write-without-response"
> > (or use automatic logic like today if the option is not specified).
> > What do you think?
>
> I would have named it just type since it is for WriteValue we should
> not need to repeat the write term on the flags, so Id would go for
> type="reliable" (reliable-write), "command" (write-without-response),
> "request" (write-with-response). Also, I assume this would force the
> operation no matter what the flags indicate so people can work around
> if the regular WriteValue don't work for some reason, perhaps the
> service is not really adhering to the spec or it is a vendor service
> just not setting the properties properly.
>
Yes, that sounds great!

/Emil