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
  • Hi uri_ee,

    I will support you with this case. However, I will need to do some investigation, while there is a bit too much on my schedule at the moment; so I cannot give you an answer right away.

    I'm sorry for the inconvenience. Unless someone from the community already helped you then, I will return by the end of Friday Mar 17

    Hieu

Reply
  • Hi uri_ee,

    I will support you with this case. However, I will need to do some investigation, while there is a bit too much on my schedule at the moment; so I cannot give you an answer right away.

    I'm sorry for the inconvenience. Unless someone from the community already helped you then, I will return by the end of Friday Mar 17

    Hieu

Children
  • Hi uri_ee,

    My apology but I have still been occupied and haven't been able to start looking into this yet. I will try to get to it within next week, likely before Wednesday.

    Hieu

  • Hi uri_ee,

    I just want to update you that I started looking into it today, but still couldn't find the reason for the failure.

    I will continue looking into it and update you every two-three workdays.

    Hieu

  • Hi Uri,

    I look at it today and see that the exception originates from the CPP code from pc-ble-driver returning NRF_ERROR_INVALID_PARAM:

    // main.py
            try:
                adapter.driver.ble_gattc_exchange_mtu_req(conn_handle=conn, mtu=178)
            except Exception as ex:
                logger.exception("Exception ble_gattc_exchange_mtu_req: {}".format(ex))

    // Log
    2023-03-24 01:05:45,233 [28288/MainThread] Exception ble_gattc_exchange_mtu_req: Failed to ble_gattc_exchange_mtu_req. Error code: NRF_ERROR_INVALID_PARAM
    Traceback (most recent call last):
      File "C:\_w\c\c304548_pc_ble_driver_py_mtu\python\main.py", line 181, in main
        adapter.driver.ble_gattc_exchange_mtu_req(conn_handle=conn, mtu=178)
      File "C:\Users\hivo\AppData\Local\Programs\Python\Python38\lib\site-packages\pc_ble_driver_py\ble_driver.py", line 106, in wrapper
        raise NordicSemiException(
    pc_ble_driver_py.exceptions.NordicSemiException: Failed to ble_gattc_exchange_mtu_req. Error code: NRF_ERROR_INVALID_PARAM

    I believe the driver just provide a transparent interface to the SoftDevice API. The SoftDevice API sd_ble_gattc_exchange_mtu_request(). From its documentation, we see:

    It returns NRF_ERROR_INVALID_PARAM when a parameter is invalid.

    The parameter conn_handle should be correct, as it is just 0 for the simple case of freshly restarted central and peripheral.

    The parameter mtu has the following constraint:

    Client RX MTU size.

    Meanwhile, from the log, we know that an exchange did previously happen with a reply from the GATT Server. 

    Therefore, essentially, this means that after the initial MTU exchange, MTU value cannot be changed. This matches with what we found above, because in this case I am trying to set a different MTU value from the result of the first negotiation.

    In your case where you cannot set the value to anything other than 23, it is likely because your Server negotiated the MTU size to 23. You should be able to see a log similar to the one in my screenshot above where this is shown.

    I believe the idea is that the first MTU exchange should have already set MTU to the highest value both the Client and the Server can support, so there is no need to set it to any other value.

    While it could be inconsequential, this seems a bit too inflexible and basically render this API meaningless after the first MTU exchange. That makes me doubt my own understanding. I am out of office until the end of the week, but I will double check in the Bluetooth spec and with my team next week.


    On the other hand, I see that adjusting default MTU will help set the connection MTU just fine. Is this going to satisfy your need?

    Of course, it is also dependent on the Server's capability.

     


    Other references:

    Message Sequence Chart for GATTC ATT_MTU Exchange
    Message Sequence Chart for GATTS ATT_MTU Exchange

    Hieu

  • Hello Hieu.

    When connected to the tag through the "nrf connect" GUI the i can change the MTU once per session. so we can deduce that the server device MTU can be changed to a value bigger then 23.

    It is also worth to mention that the default computer's BLE driver have no problem getting a full notification from the server device

    I have already tried to set the adapters default_mtu (and the gatt_cfg.att_mtu) but still got MTU=23.

    I also tried to set all default in driver and adapter mode to MTU > 23 but for no avail.

    Is there any other way i can start a session with a right MTU or update the MTU?

  • I am a bit surprised. Do you not even have a MTU higher than 23 at all?

    As you can see in the second screenshot in my last reply, when I set the default_mtu field to 121, the negotiation happened automatically, and the two devices successfully agreed on 121 as the MTU.

    That experiment was based on the heart_rate_collector.py example. When I tried the code unmodified, I observed the negotiation to ended with MTU of 247 instead.

    How are you setting up your project? Can you try to use the HRS sample unmodified and see if the MTU is updated automatically? 

Related