This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Isn't the client normally the central and the peripheral normally the server (ATT_MTU_THOUGHPUT)

While still trying to debug the disconnect problem in a different thread (unsuccessfully), I've gone to the ATT_MTU_THOUGHPUT example, to try and understand it and gain more insight. I'm having difficulty on understanding how it was set up; this might be due to some degree due to many different terms. First, let me state what I thought (incorrectly) is a normal setup. Could you please correct me on this as it doesn't seem to be how the example is set up.

1) In the example, their are many different roles I'm trying to sort out. These include: Tester, Peripheral, Server, Responder, Slave, Central, Client, Master. The board connected to the PC is the Tester and in the example, one is directed to push button 3 on this board, configure the example, and then run the test. Below is a typical example (the gibberish is because gnome terminal running minterm.py does not handle ANSI color escapes properly:

␛[1;32mthroughput example:~$ ␛[1;37mconfig
config - Configure the example
␛[mOptions:
␛[1;37m  -h, --help  :Show command help.
␛[mSubcommands:
␛[1;37m  att_mtu           :Configure ATT MTU size
  data_length       :Configure data length
  conn_evt_len_ext  :Enable or disable Data Length Extension
  conn_interval     :Configure GAP connection interval
  print             :Print current configuration
  phy               :Configure preferred PHY
  gap_evt_len       :Configure GAP event length
␛[1;32mthroughput example:~$ ␛[1;37mconfig data_length 240
Data length set to 240.
␛[1;32mthroughput example:~$ ␛[1;37mrun
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:23.904,968] <info> app: Preparing the test.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:23.904,968] <info> app: Starting scanning.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:24.039,733] <info> app: Device "Nordic_ATT_MTU" found, sending a connection request.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:24.987,487] <info> app: Connected as a central.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:24.987,548] <info> app: Discovering GATT database...
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:25.004,089] <info> app: ATT MTU exchange completed. MTU set to 247 bytes.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:25.010,925] <info> app: Data length updated to 240 bytes.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:25.083,862] <info> app: PHY update accepted. PHY set to 2 Mbps.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:25.107,788] <info> app: AMT service discovered at peer.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:25.115,295] <info> app: Notifications enabled.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:25.121,215] <info> app: Test started
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:25.131,591] <info> app: Sent 1 KBytes
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:25.141,357] <info> app: Sent 2 KBytes
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:25.152,770] <info> app: Sent 3 KBytes
...
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.670,410] <info> app: Sent 1023 KBytes
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.679,748] <info> app: Sent 1024 KBytes
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.683,532] <info> app: Done.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.683,593] <info> app: =============================
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.683,593] <info> app: Time: 14.545 seconds elapsed.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.683,593] <info> app: Throughput: 576.80 Kbps.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.683,593] <info> app: =============================
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.683,654] <info> app: Sent 1048712 bytes of ATT payload.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.683,654] <info> app: Retrieving amount of bytes received from peer...
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.698,547] <info> app: Peer received 1048712 bytes of ATT payload.
␛[1;32mthroughput example:~$ ␛[1;37m␛[22D␛[J[00:01:39.698,547] <info> app: Disconnecting...
␛[1;32mthroughput example:~$ ␛[1;37m

As far as I can tell, the board connected to the PC is the Server, and is the one sending the Notifications, and that this should be the Peripheral, not the Central. What I thought was a normal case is: The Central is normally scanning for Peripherals, and that the Peripherals are the devices acquiring data (that is the Servers), and that when they have appropriate data, they then advertise, the Central then connects, and controls the connection (that is the Central is the Master, the Peripheral is the Slave - two more roles to be sorted out), the Peripheral can request connection changes, but the Central - that is the Master) decides if the connection parameters will be allowed, and that after the connection is established, the Peripheral (that is the Server, that is the Slave), sends the data using Notifications. The data is being sent by the board connected to the computer using Notifications in the example, yet the board connected to the computer states it's the Central; it seems to me it should be the Peripheral not the Central, as it's the one sending the Notifications. It also reports that it was the one discovering services on the peer (yet another role?); "AMT service discovered at peer.". Isn't the peer the device doing the advertising? which normally would not be the device sending the Notifications? Could you please help explain where I am going wrong? The device connected to the computer is the server, as it's the one that reacts to:

/**@brief AMT server event handler. */
static void amts_evt_handler(nrf_ble_amts_evt_t evt)
{

but if it's the server, why is it the Central and not the Peripheral (which is the Slave)? In the function test_begin(), we see:

        case BLE_GAP_ROLE_PERIPH:
            advertising_start();
            m_test_params.phys.tx_phys = BLE_GAP_PHY_2MBPS;
            break;

        case BLE_GAP_ROLE_CENTRAL:
            scan_start();
            break;

This is as I expect, the Peripheral does the advertising and the Central does the scanning; the Peripheral sends the Notifications which the Central should receive once it connects, but then why did the device connected to the PC report earlier that it was the Central?

Parents
  • Hi Kenneth,

    I can understand your confusion. Your understanding on what should be server/client/central/peripheral according to the specification is correct. But there is  small twist in the example of MTU throughput.

    When you run the test, the role of the devices are not defined. Both devices do both advertising and scanning. That is both the tester and the device under test at the start of the behave as both scanner and advertiser 

    At these point when both devices are scanning and also advertising, we cannot tell which device scanner will find the other device advertising packet. In short, it is timing related and any of the device can become a central or a peripheral. the m_gap_role in the main.c will explain you more on how this is done if you track how this is assigned and managed.

    OK, most likely you know all the above and your confusion is how the central is able to do a notification?

    I think the trick is that irrespective of the what role it is connected to, each device has both GATT server and GATT client inside them. Since the softdevice is configured to have a multirole and hence the softdevice is initialized to have both GATT server and GATT client. So when the device gets connected )on_ble_gap_evt_connected) irrespective of it is a central or peripheral, both sides of the servers tries to do the database discovery of the peer servers. This you can see in on_ble_gap_evt_connected calling ble_db_discovery_start irrespective of what role it is in.

    So in your case, the central is actually sending notifications to peripheral since the central has both GATT server and GATT client inside them. This example is not about mapping GATT server or client role to central or peripheral, it is about maximum data transfer from the server to client. The TESTER can be both central or peripheral but only the GATT server inside the TESTER will send notifications to the GATT client of the responder.

    This is not illegal and the spec has not limited the central to have only the client. It is just normal that in low power usecases most of the time centrals happen to be clients.

Reply
  • Hi Kenneth,

    I can understand your confusion. Your understanding on what should be server/client/central/peripheral according to the specification is correct. But there is  small twist in the example of MTU throughput.

    When you run the test, the role of the devices are not defined. Both devices do both advertising and scanning. That is both the tester and the device under test at the start of the behave as both scanner and advertiser 

    At these point when both devices are scanning and also advertising, we cannot tell which device scanner will find the other device advertising packet. In short, it is timing related and any of the device can become a central or a peripheral. the m_gap_role in the main.c will explain you more on how this is done if you track how this is assigned and managed.

    OK, most likely you know all the above and your confusion is how the central is able to do a notification?

    I think the trick is that irrespective of the what role it is connected to, each device has both GATT server and GATT client inside them. Since the softdevice is configured to have a multirole and hence the softdevice is initialized to have both GATT server and GATT client. So when the device gets connected )on_ble_gap_evt_connected) irrespective of it is a central or peripheral, both sides of the servers tries to do the database discovery of the peer servers. This you can see in on_ble_gap_evt_connected calling ble_db_discovery_start irrespective of what role it is in.

    So in your case, the central is actually sending notifications to peripheral since the central has both GATT server and GATT client inside them. This example is not about mapping GATT server or client role to central or peripheral, it is about maximum data transfer from the server to client. The TESTER can be both central or peripheral but only the GATT server inside the TESTER will send notifications to the GATT client of the responder.

    This is not illegal and the spec has not limited the central to have only the client. It is just normal that in low power usecases most of the time centrals happen to be clients.

Children
  • Thank you, if I understand correctly, it's random on which device becomes the Central and which device becomes the Peripheral ("In short, it is timing related and any of the device can become a central or a peripheral.")? and "This example is not about mapping GATT server or client role to central or peripheral" but I do need to understand this in order to develop my project. I also need high throughput and this is the only example I have found (that I can get to work) that has high throughput so I need to modify it so it is deterministic on who is the Central and who is the Peripheral. Is Central just a different term for Master, and Peripheral synonymous with Slave? Can both a Central and a Peripheral send Notifications? Can both enable Notifications on the other? And what does "peer" designate? Thank you.

  • kw_martin said:
    I also need high throughput and this is the only example I have found (that I can get to work) that has high throughput so I need to modify it so it is deterministic

     Kenneth,

    If your goal is to get high throughtput then you should focus more on AMTS service and the MTU size and data length values. The state machine of this example is not suitable for you inherit the roles of the device.

    Each device in this example can be both central and peripheral, but you would like to change the for example make TESTER only work as central or peripheral and vice versa for the RESPONDER.

    I agree, that this is a bit confusing to take this example as a template for the project, but the intention of this example was to demonstrate the transfer of big chunk of data at high speed. Please assign fixed roles to your device if you are inheriting this into a project and higher throughput and big chunk data transfer is the main goal for you, then focus on how AMTS service achieved it.

Related