ukBaz / python-bluezero

A simple Python interface to Bluez
MIT License
387 stars 112 forks source link

How to respond to a Write Request? #379

Closed CodeEagle closed 1 year ago

CodeEagle commented 1 year ago

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.

ukBaz commented 1 year ago

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 commented 1 year ago

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

CodeEagle commented 1 year ago

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

ukBaz commented 1 year ago

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?

CodeEagle commented 1 year ago

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

ukBaz commented 1 year ago

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.

CodeEagle commented 1 year ago

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

ukBaz commented 1 year ago

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?

CodeEagle commented 1 year ago

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

ukBaz commented 1 year ago

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.

CodeEagle commented 1 year ago

thanks a lot buddy.

ukBaz commented 1 year ago

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