python-bluezero icon indicating copy to clipboard operation
python-bluezero copied to clipboard

How to respond to a Write Request?

Open CodeEagle opened this issue 3 years ago • 8 comments

https://github.com/ukBaz/python-bluezero/blob/main/bluezero/localGATT.py#L359-L370 as the code show, is no way to respond for a write request

aka WRITE_TYPE_DEFAULT for Android

and write for iOS

A property that indicates a peripheral can write the characteristic’s value, with a response to indicate that the write succeeded.

CodeEagle avatar Aug 17 '22 13:08 CodeEagle

Sorry, what is not working for you?

Have you created a peripheral and you want it to be write-without-response?

What flags have you set for the characteristic? Here is the BlueZ list to choose from: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt#n251

ukBaz avatar Aug 17 '22 13:08 ukBaz

From a Bluezero example: https://github.com/ukBaz/python-bluezero/blob/7cb8e8f019a3a045f074322a08deb1aa9af6ee67/examples/heartrate_monitor_peripheral.py#L183

ukBaz avatar Aug 17 '22 13:08 ukBaz

like read_value, write request aka flags=['write'] also need to return value to the call

If a characteristic has this property set, it returns an error to the central when it fails to write the characteristic’s value.

and also here

"request": Write with response

CodeEagle avatar Aug 17 '22 13:08 CodeEagle

Hmmm? I didn't think that is how it worked. I thought the responsibility for the response was at a deeper level than the application.

The official BlueZ test example has a write (with response) but they don't send a response from the method. https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server#n590

Have you tested this to see if it works if you send a response back?

ukBaz avatar Aug 17 '22 13:08 ukBaz

do you ever test this case? I can test it later, devices not around now.

CodeEagle avatar Aug 17 '22 14:08 CodeEagle

We have the Heart Rate Monitor where the control point is expecting a response according to the specification . I've tested it with numerous apps and it seems to work.

ukBaz avatar Aug 17 '22 14:08 ukBaz

The Heart Rate Monitor is not the same point of what I ask for.

specification not required reply for write action

Write with response is required peripheral to reply the action success or failure on the same characteristic, not notify or indicate.

this is how swift does

CodeEagle avatar Aug 17 '22 14:08 CodeEagle

I created the following example with one write characteristic:

"""Example of how to create a Peripheral device/GATT Server"""
# Standard modules
import logging

# Bluezero modules
from bluezero import adapter
from bluezero import peripheral

TEST_SRV_UUID = '00000001-F00D-C0DE-C0C0-DEADBEEFCAFE'
WRT_RSP_UUID = '00000002-F00D-C0DE-C0C0-DEADBEEFCAFE'


def write_cb(value, options):
    print(f"{value:} - {options:}")


def main(adapter_address):
    logger = logging.getLogger('localGATT')
    logger.setLevel(logging.DEBUG)

    # Create peripheral
    test_srv = peripheral.Peripheral(adapter_address)
    # Add service
    test_srv.add_service(srv_id=1, uuid=TEST_SRV_UUID, primary=True)

    # Add characteristics
    test_srv.add_characteristic(srv_id=1, chr_id=1, uuid=WRT_RSP_UUID,
                                value=[], notifying=False,
                                flags=['write', 'write-without-response'],
                                read_callback=None,
                                write_callback=write_cb,
                                notify_callback=None
                                )

    # Publish peripheral and start event loop
    test_srv.publish()


if __name__ == '__main__':
    # Get the default adapter address and pass it to main
    main(list(adapter.Adapter.available())[0].address)

I did a "command" and a "request" write from nRF Connect on Android and it gave the same output for both:

bytearray(b'\x05') - {'device': '/org/bluez/hci0/dev_xx_xx_xx_xx_xx_xx', 'link': 'LE', 'mtu': 517}

I think what you are saying is that there should be a 'type': 'request' or 'type': 'command' in the options also.

Is this the correct test?

ukBaz avatar Aug 17 '22 16:08 ukBaz

I think what you are saying is that there should be a 'type': 'request' or 'type': 'command' in the options also.

yes, and need to respond the 'request' call in some way

CodeEagle avatar Aug 18 '22 01:08 CodeEagle

Do you get the type value with your client?

Unless you know how to make the type value appear in the options given to WriteValue. I would suggest this is a BlueZ issue.

You might want to raise a question to the BlueZ developers by using one of their communication channels documented at http://www.bluez.org/contact/

Looking through the archives, these two items look related but not specific to this issue:

https://marc.info/?l=linux-bluetooth&m=154895139507840&w=2

https://marc.info/?l=linux-bluetooth&m=165912705016516&w=2

I couldn't find anything that looked related on Slack workspace.

ukBaz avatar Aug 18 '22 05:08 ukBaz

thanks a lot buddy.

CodeEagle avatar Aug 18 '22 12:08 CodeEagle

@CodeEagle if you get an answer about this it would be appreciated if you could report back. Thanks

ukBaz avatar Aug 19 '22 07:08 ukBaz