Cannot alter MTU after connecting a peripheral device using the python library "pc_ble_driver_py"

Hello, 

I'm using the nRF device to communicate with a peripheral device I get some characteristic notifications but only 20 bytes for a packet.

When using the 'nRF connect' GUI I manage to update the MTU from 23 to any larger value and get the full notification.

But I cannot alter MTU after connecting a peripheral device using the python library "pc_ble_driver_py".

Iv'e tried many ways like setting the default_mtu and the att_mtu on adapter initialization:

driver = BLEDriver(
    serial_port=port,
    auto_flash=auto_flash,
    baud_rate=baud_rate,
    retransmission_interval=retransmission_interval,
    response_timeout=response_timeout,
    log_severity_level=driver_log_level,
)
driver.ble_gattc_exchange_mtu_req
adapter = BLEAdapter(driver)
adapter.default_mtu = 247
adapter.driver.open()
gatt_cfg = BLEConfigConnGatt()
gatt_cfg.att_mtu = adapter.default_mtu
adapter.driver.ble_cfg_set(BLEConfig.conn_gatt, gatt_cfg)
adapter.driver.ble_enable()


And to use the adapter.att_mtu_exchange function to but for no avail.
when i execute tyhe command : 
self.ble_adapter.att_mtu_exchange(self.conn_handler, 23)
 

it's running fine but when i try to increece the mtu to a different level like:
self.ble_adapter.att_mtu_exchange(self.conn_handler, 247)
 (or any number greater then 23)

it allways raise the folowing exception:

NordicSemiException: MTU exchange request failed. Common causes are: missing att_mtu setting in ble_cfg_set, different config tags used in ble_cfg_set and connect.

Is there any way to overcome this hurdle?

Thanks,
Uri


Parents Reply Children
  • Hello Uri,

    If you can update MTU once, and not again, then the behavior is expected. Please refer to Bluetooth Core Spec Version 4.0/5.0/5.4 | Vol 3, Part G, Section 4.3.1 Exchange MTU

    This sub-procedure is used by the client to set the ATT_MTU to the maximum possible value that can be supported by both devices when the client supports a value greater than the default ATT_MTU for the Attribute Protocol. This subprocedure shall only be initiated once during a connection.
  • Hello Hieu.

    The Problem is that I can only update the MTU from the GUI not from Python script.

  • Hi Uri,

    I looked into it finally understood (maybe) everything. 

    On the Peripheral/nRF device side, the ble_app_hrs example by default initiates the MTU exchange first because NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED is set.

    If you set that config to 0, then the Peripheral will not initiate the negotiation, and from the Python side, you can initiate the negotiation. I did this with:

        if conn is not None:
            try:
                adapter.driver.ble_gattc_exchange_mtu_req(conn_handle=conn, mtu=129)
            except Exception as ex:
                logger.exception("Exception ble_gattc_exchange_mtu_req: {}".format(ex))

    You cannot see the final MTU, but you can derive it by looking into parameters of certain functions using breakpoints.

    Note that breakpoints can break a connection depends on where it is set. If you don't want to have to think too much about it, just restart the experiment from the beginning after each "sampling" using breakpoints.

    If the nRF device side initiates the negotiation,

    If the Python side initiates the negotiation,

    Then the MTU will be decided as the minimal between both sides' preferred MTUs. 

  • Hello Hieu,

    Unfortunately, we are unable to modify or access the code and configuration of the Peripheral device.

    I've already went over all the functions you mentioned. I examined the values and also tried to manipulate then with no avail.

    We are still in need for a solution.

    As a reminder, using the GUI app we manage to change the MTU and get the full notification. we need to be able to do the same from a python script.

    Thank you.

  • Hi Uri,

    uri_ee said:
    I've already went over all the functions you mentioned. I examined the values and also tried to manipulate then with no avail.

    The functions I mentioned is a part of the library and should not be manipulated. I just asked you to examine what the parameter values of those functions are.

    What values did you see?

    uri_ee said:
    As a reminder, using the GUI app we manage to change the MTU and get the full notification. we need to be able to do the same from a python script.

    Is your issue that MTU exchange did not happen, or is it something about the notification?

    If your issue is with the notification, are you certain that the cause is with MTU?

    All this time, we have been so invested into checking if MTU is exchanged, but are we certain that the full notification wasn't sent successfully, and the problem isn't somewhere else?

    Could the problem be in your notification handling code?

    From what we have seen, I think the MTU should be exchanged correctly if you are setting things up similar to the Heart Rate example. Furthermore, if the MTU is insufficient, it usually resulted in the message just cannot be sent.

    Can you get me a sniffer trace of a test? It will reveal whether MTU was successfully exchanged, and whether the notification was sent in full or shortened.

    If you need instruction on getting a sniffer trace, please refer to Lesson 6 of our BLE Fundamentals online course.

    Hieu

Related