Skip to content

Commit

Permalink
Merge pull request #570 from google/gbg/bench-mobly-snippets
Browse files Browse the repository at this point in the history
bench mobly snippets
  • Loading branch information
barbibulle authored Oct 28, 2024
2 parents 32642c5 + fcd6bd7 commit 4b25eed
Show file tree
Hide file tree
Showing 30 changed files with 1,163 additions and 226 deletions.
231 changes: 138 additions & 93 deletions apps/bench.py

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion apps/rfcomm_bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ def __init__(
address: str,
tcp_host: str,
tcp_port: int,
authenticate: bool,
encrypt: bool,
):
self.channel = channel
Expand All @@ -245,6 +246,7 @@ def __init__(
self.address = address
self.tcp_host = tcp_host
self.tcp_port = tcp_port
self.authenticate = authenticate
self.encrypt = encrypt
self.device: Optional[Device] = None
self.connection: Optional[Connection] = None
Expand Down Expand Up @@ -274,6 +276,11 @@ async def connect(self) -> None:
print(color(f"@@@ Bluetooth connection: {self.connection}", "blue"))
self.connection.on("disconnection", self.on_disconnection)

if self.authenticate:
print(color("@@@ Authenticating Bluetooth connection", "blue"))
await self.connection.authenticate()
print(color("@@@ Bluetooth connection authenticated", "blue"))

if self.encrypt:
print(color("@@@ Encrypting Bluetooth connection", "blue"))
await self.connection.encrypt()
Expand Down Expand Up @@ -491,15 +498,17 @@ def server(context, tcp_host, tcp_port):
@click.argument("bluetooth-address")
@click.option("--tcp-host", help="TCP host", default="_")
@click.option("--tcp-port", help="TCP port", default=DEFAULT_CLIENT_TCP_PORT)
@click.option("--authenticate", is_flag=True, help="Authenticate the connection")
@click.option("--encrypt", is_flag=True, help="Encrypt the connection")
def client(context, bluetooth_address, tcp_host, tcp_port, encrypt):
def client(context, bluetooth_address, tcp_host, tcp_port, authenticate, encrypt):
bridge = ClientBridge(
context.obj["channel"],
context.obj["uuid"],
context.obj["trace"],
bluetooth_address,
tcp_host,
tcp_port,
authenticate,
encrypt,
)
asyncio.run(run(context.obj["device_config"], context.obj["hci_transport"], bridge))
Expand Down
56 changes: 34 additions & 22 deletions docs/mkdocs/src/apps_and_tools/bench.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,44 @@ Usage: bumble-bench [OPTIONS] COMMAND [ARGS]...
Options:
--device-config FILENAME Device configuration file
--role [sender|receiver|ping|pong]
--scenario [send|receive|ping|pong]
--mode [gatt-client|gatt-server|l2cap-client|l2cap-server|rfcomm-client|rfcomm-server]
--att-mtu MTU GATT MTU (gatt-client mode) [23<=x<=517]
--extended-data-length TEXT Request a data length upon connection,
specified as tx_octets/tx_time
--rfcomm-channel INTEGER RFComm channel to use
--role-switch [central|peripheral]
Request role switch upon connection (central
or peripheral)
--rfcomm-channel INTEGER RFComm channel to use (specify 0 for channel
discovery via SDP)
--rfcomm-uuid TEXT RFComm service UUID to use (ignored if
--rfcomm-channel is not 0)
--rfcomm-l2cap-mtu INTEGER RFComm L2CAP MTU
--rfcomm-max-frame-size INTEGER
RFComm maximum frame size
--rfcomm-initial-credits INTEGER
RFComm initial credits
--rfcomm-max-credits INTEGER RFComm max credits
--rfcomm-credits-threshold INTEGER
RFComm credits threshold
--l2cap-psm INTEGER L2CAP PSM to use
--l2cap-mtu INTEGER L2CAP MTU to use
--l2cap-mps INTEGER L2CAP MPS to use
--l2cap-max-credits INTEGER L2CAP maximum number of credits allowed for
the peer
-s, --packet-size SIZE Packet size (client or ping role)
[8<=x<=4096]
-c, --packet-count COUNT Packet count (client or ping role)
-sd, --start-delay SECONDS Start delay (client or ping role)
--repeat N Repeat the run N times (client and ping
roles)(0, which is the fault, to run just
-s, --packet-size SIZE Packet size (send or ping scenario)
[8<=x<=8192]
-c, --packet-count COUNT Packet count (send or ping scenario)
-sd, --start-delay SECONDS Start delay (send or ping scenario)
--repeat N Repeat the run N times (send and ping
scenario)(0, which is the fault, to run just
once)
--repeat-delay SECONDS Delay, in seconds, between repeats
--pace MILLISECONDS Wait N milliseconds between packets (0,
which is the fault, to send as fast as
possible)
--linger Don't exit at the end of a run (server and
pong roles)
--linger Don't exit at the end of a run (receive and
pong scenarios)
--help Show this message and exit.
Commands:
Expand Down Expand Up @@ -71,19 +83,19 @@ using the ``--peripheral`` option. The address will be printed by the Peripheral
it starts.

Independently of whether the device is the Central or Peripheral, each device selects a
``mode`` and and ``role`` to run as. The ``mode`` and ``role`` of the Central and Peripheral
``mode`` and and ``scenario`` to run as. The ``mode`` and ``scenario`` of the Central and Peripheral
must be compatible.

Device 1 mode | Device 2 mode
Device 1 scenario | Device 2 scenario
------------------|------------------
``gatt-client`` | ``gatt-server``
``l2cap-client`` | ``l2cap-server``
``rfcomm-client`` | ``rfcomm-server``

Device 1 role | Device 2 role
--------------|--------------
``sender`` | ``receiver``
``ping`` | ``pong``
Device 1 scenario | Device 2 scenario
------------------|--------------
``send`` | ``receive``
``ping`` | ``pong``


# Examples
Expand All @@ -92,7 +104,7 @@ In the following examples, we have two USB Bluetooth controllers, one on `usb:0`
the other on `usb:1`, and two consoles/terminals. We will run a command in each.

!!! example "GATT Throughput"
Using the default mode and role for the Central and Peripheral.
Using the default mode and scenario for the Central and Peripheral.

In the first console/terminal:
```
Expand Down Expand Up @@ -137,12 +149,12 @@ the other on `usb:1`, and two consoles/terminals. We will run a command in each.
!!! example "Ping/Pong Latency"
In the first console/terminal:
```
$ bumble-bench --role pong peripheral usb:0
$ bumble-bench --scenario pong peripheral usb:0
```

In the second console/terminal:
```
$ bumble-bench --role ping central usb:1
$ bumble-bench --scenario ping central usb:1
```

!!! example "Reversed modes with GATT and custom connection interval"
Expand All @@ -167,13 +179,13 @@ the other on `usb:1`, and two consoles/terminals. We will run a command in each.
$ bumble-bench --mode l2cap-server central --phy 2m usb:1
```

!!! example "Reversed roles with L2CAP"
!!! example "Reversed scenarios with L2CAP"
In the first console/terminal:
```
$ bumble-bench --mode l2cap-client --role sender peripheral usb:0
$ bumble-bench --mode l2cap-client --scenario send peripheral usb:0
```

In the second console/terminal:
```
$ bumble-bench --mode l2cap-server --role receiver central usb:1
$ bumble-bench --mode l2cap-server --scenario receive central usb:1
```
47 changes: 47 additions & 0 deletions examples/mobly/bench/one_device_bench_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from mobly import base_test
from mobly import test_runner
from mobly.controllers import android_device


class OneDeviceBenchTest(base_test.BaseTestClass):

def setup_class(self):
self.ads = self.register_controller(android_device)
self.dut = self.ads[0]
self.dut.load_snippet("bench", "com.github.google.bumble.btbench")

def test_rfcomm_client_ping(self):
runner = self.dut.bench.runRfcommClient(
"ping", "DC:E5:5B:E5:51:2C", 100, 970, 100
)
print("### Initial status:", runner)
final_status = self.dut.bench.waitForRunnerCompletion(runner["id"])
print("### Final status:", final_status)

def test_rfcomm_client_send(self):
runner = self.dut.bench.runRfcommClient(
"send", "DC:E5:5B:E5:51:2C", 100, 970, 0
)
print("### Initial status:", runner)
final_status = self.dut.bench.waitForRunnerCompletion(runner["id"])
print("### Final status:", final_status)

def test_l2cap_client_ping(self):
runner = self.dut.bench.runL2capClient(
"ping", "4B:2A:67:76:2B:E3", 128, True, 100, 970, 100
)
print("### Initial status:", runner)
final_status = self.dut.bench.waitForRunnerCompletion(runner["id"])
print("### Final status:", final_status)

def test_l2cap_client_send(self):
runner = self.dut.bench.runL2capClient(
"send", "7E:90:D0:F2:7A:11", 131, True, 100, 970, 0
)
print("### Initial status:", runner)
final_status = self.dut.bench.waitForRunnerCompletion(runner["id"])
print("### Final status:", final_status)


if __name__ == "__main__":
test_runner.main()
9 changes: 9 additions & 0 deletions examples/mobly/bench/sample_config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
TestBeds:
- Name: BenchTestBed
Controllers:
AndroidDevice:
- serial: 37211FDJG000DJ
local_bt_address: 94:45:60:5E:03:B0

- serial: 23071FDEE001F7
local_bt_address: DC:E5:5B:E5:51:2C
38 changes: 38 additions & 0 deletions examples/mobly/bench/two_devices_bench_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import time

from mobly import base_test
from mobly import test_runner
from mobly.controllers import android_device


class TwoDevicesBenchTest(base_test.BaseTestClass):
def setup_class(self):
self.ads = self.register_controller(android_device)
self.dut1 = self.ads[0]
self.dut1.load_snippet("bench", "com.github.google.bumble.btbench")
self.dut2 = self.ads[1]
self.dut2.load_snippet("bench", "com.github.google.bumble.btbench")

def test_rfcomm_client_send_receive(self):
print("### Starting Receiver")
receiver = self.dut2.bench.runRfcommServer("receive")
receiver_id = receiver["id"]
print("--- Receiver status:", receiver)
while not receiver["model"]["running"]:
print("--- Waiting for Receiver to be running...")
time.sleep(1)
receiver = self.dut2.bench.getRunner(receiver_id)

print("### Starting Sender")
sender = self.dut1.bench.runRfcommClient(
"send", "DC:E5:5B:E5:51:2C", 100, 970, 100
)
print("--- Sender status:", sender)

print("--- Waiting for Sender to complete...")
sender_result = self.dut1.bench.waitForRunnerCompletion(sender["id"])
print("--- Sender result:", sender_result)


if __name__ == "__main__":
test_runner.main()
2 changes: 2 additions & 0 deletions extras/android/BtBench/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ dependencies {
implementation(libs.ui.graphics)
implementation(libs.ui.tooling.preview)
implementation(libs.material3)
implementation(libs.mobly.snippet)
implementation(libs.androidx.core)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)
Expand Down
9 changes: 7 additions & 2 deletions extras/android/BtBench/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.BTBench"
>
<meta-data
android:name="mobly-snippets"
android:value="com.github.google.bumble.btbench.AutomationSnippet"/>
<activity
android:name=".MainActivity"
android:exported="true"
Expand All @@ -35,5 +38,7 @@
</activity>
<!-- <profileable android:shell="true"/>-->
</application>

</manifest>
<instrumentation
android:name="com.google.android.mobly.snippet.SnippetRunner"
android:targetPackage="com.github.google.bumble.btbench" />
</manifest>
Loading

0 comments on commit 4b25eed

Please sign in to comment.