Skip to content

Commit dee32b6

Browse files
committed
Merge branch 'feat/ble-adapter-option' into 'master'
provision: Add --ble_adapter CLI option for selecting HCI adapter See merge request app-frameworks/esp-rainmaker-cli!98
2 parents 277711f + 3d84eb2 commit dee32b6

9 files changed

Lines changed: 40 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
All major changes to ESP RainMaker CLI will be documented in this file.
44

5+
## [Unreleased]
6+
### Added
7+
- `--ble_adapter` option for the `provision` command to select the HCI adapter used for BLE transport (default: `hci0`). Useful with `vhci_bridge` for emulated devices, e.g. `--ble_adapter hci1`. Linux/BlueZ only.
8+
59
## [1.14.1] - 05-Jun-2026
610
### Bugfixes
711
- Security 2 fixes across provisioning and local control:

docs/commands/provisioning.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ esp-rainmaker-cli provision [--pop <pop>] [options]
2828
- `--transport <mode>`: Communication method (softap, ble, console, on-network)
2929
- `--sec_ver <version>`: Security scheme (0, 1, or 2)
3030
- `--qrcode <json>`: QR code payload as JSON string (extracts transport, device_name, and pop)
31+
- `--ble_adapter <name>`: HCI adapter to use for BLE transport (default: `hci0`). Useful with `vhci_bridge` for emulated devices, e.g. `--ble_adapter hci1`. Linux/BlueZ only; ignored on macOS/Windows.
3132

3233
### Transport Modes
3334

@@ -193,6 +194,15 @@ esp-rainmaker-cli provision --pop abcd1234 \
193194
--passphrase "MyWiFiPassword"
194195
```
195196

197+
### BLE Provisioning with a Specific HCI Adapter
198+
```bash
199+
# Target a non-default adapter (e.g. hci1 from vhci_bridge for emulated devices)
200+
esp-rainmaker-cli provision --pop abcd1234 \
201+
--transport ble \
202+
--device_name PROV_d76c30 \
203+
--ble_adapter hci1
204+
```
205+
196206
### SoftAP Provisioning with Security 2
197207
```bash
198208
# Use advanced security with username/password

rainmaker/rainmaker.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,12 @@ def main():
564564
help='Metadata as JSON string to attach during node mapping\n'
565565
'(e.g., \'{"serial_no": "abc123", "region": "us"}\')')
566566

567+
provision_parser.add_argument('--ble_adapter',
568+
type=str,
569+
default='hci0',
570+
help='HCI adapter to use for BLE transport (default: hci0).\n'
571+
'Useful with vhci_bridge for emulated devices, e.g. --ble_adapter hci1')
572+
567573
add_profile_argument(provision_parser)
568574
provision_parser.set_defaults(func=provision)
569575

rmaker_cmd/provision.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@ def provision(vars=None):
244244
no_wifi=no_wifi,
245245
disable_chal_resp=disable_chal_resp,
246246
tags=mapping_tags,
247-
metadata=mapping_metadata
247+
metadata=mapping_metadata,
248+
ble_adapter=vars.get('ble_adapter', 'hci0')
248249
)
249250
except RuntimeError as claim_err:
250251
# Handle claim requirement error specifically

rmaker_tools/common/transport/ble_cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ async def connect(self, devname, iface, chrc_names, fallback_srv_uuid):
5858

5959
print('Discovering...')
6060
try:
61-
discovery = await bleak.BleakScanner.discover(return_adv=True)
61+
discovery = await bleak.BleakScanner.discover(return_adv=True, adapter=iface)
6262
devices = list(discovery.values())
6363
except bleak.exc.BleakDBusError as e:
6464
if str(e) == '[org.bluez.Error.NotReady] Resource Not Ready':
@@ -92,7 +92,7 @@ async def connect(self, devname, iface, chrc_names, fallback_srv_uuid):
9292
if select != 0:
9393
break
9494

95-
discovery = await bleak.BleakScanner.discover(return_adv=True)
95+
discovery = await bleak.BleakScanner.discover(return_adv=True, adapter=iface)
9696
devices = list(discovery.values())
9797

9898
self.devname = devices[select - 1][0].name
@@ -115,7 +115,7 @@ async def connect(self, devname, iface, chrc_names, fallback_srv_uuid):
115115
self.srv_uuid_adv = uuids[0]
116116

117117
print('Connecting...')
118-
self.device = bleak.BleakClient(found_device[0].address)
118+
self.device = bleak.BleakClient(found_device[0].address, adapter=iface)
119119
await self.device.connect()
120120
# must be paired on Windows to access characteristics;
121121
# cannot be paired on Mac

rmaker_tools/common/transport/transport_ble.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
from . import ble_cli
66
from .transport import Transport
77

8+
DEFAULT_BLE_ADAPTER = 'hci0'
9+
810

911
class Transport_BLE(Transport):
10-
def __init__(self, service_uuid, nu_lookup):
12+
def __init__(self, service_uuid, nu_lookup, ble_adapter=DEFAULT_BLE_ADAPTER):
1113
# Store original endpoint IDs (e.g., 'ff54', 'ff55') for fallback calculation
1214
self.endpoint_ids = nu_lookup.copy()
1315
self.service_uuid = service_uuid
@@ -23,13 +25,15 @@ def __init__(self, service_uuid, nu_lookup):
2325
# Result: '0000ff54-0000-1000-8000-00805f9b34fb'
2426
self.fallback_lookup[name] = service_uuid[:4] + endpoint_id + service_uuid[8:]
2527

28+
self.ble_adapter = ble_adapter
29+
2630
# Get BLE client module
2731
self.cli = ble_cli.get_client()
2832

2933
async def connect(self, devname):
3034
# Use client to connect to BLE device and bind to service
3135
# Pass endpoint names (not UUIDs) for auto-discovery via user descriptors
32-
if not await self.cli.connect(devname=devname, iface='hci0',
36+
if not await self.cli.connect(devname=devname, iface=self.ble_adapter,
3337
chrc_names=self.endpoint_ids.keys(),
3438
fallback_srv_uuid=self.service_uuid):
3539
raise RuntimeError('Failed to initialize transport')

rmaker_tools/rmaker_local_ctrl/esp_prov.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def get_security(secver, sec_patch_ver, username, password, pop='', verbose=Fals
4848
return None
4949

5050

51-
async def get_transport(sel_transport, service_name):
51+
async def get_transport(sel_transport, service_name, ble_adapter=transport.DEFAULT_BLE_ADAPTER):
5252
try:
5353
tp = None
5454
if (sel_transport in ['softap', 'httpd']):
@@ -65,7 +65,7 @@ async def get_transport(sel_transport, service_name):
6565
# will fallback to using the provided UUIDs instead
6666
nu_lookup = {'prov-session': 'ff51', 'prov-config': 'ff52', 'proto-ver': 'ff53'}
6767
tp = transport.Transport_BLE(service_uuid='021a9004-0382-4aea-bff4-6b3f1c5adfb4',
68-
nu_lookup=nu_lookup)
68+
nu_lookup=nu_lookup, ble_adapter=ble_adapter)
6969
await tp.connect(devname=service_name)
7070
elif (sel_transport == 'console'):
7171
tp = transport.Transport_Console()

rmaker_tools/rmaker_prov/esp_rainmaker_prov.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def get_wifi_creds_from_scanlist(transport_mode, obj_transport,
164164
def provision_device(transport_mode, pop, userid, secretkey,
165165
ssid=None, passphrase=None, security_version=None,
166166
sec2_username='', sec2_password='', device_name=None, session=None, no_retry=False, no_wifi=False, disable_chal_resp=False,
167-
tags=None, metadata=None):
167+
tags=None, metadata=None, ble_adapter=esp_prov.transport.DEFAULT_BLE_ADAPTER):
168168
"""
169169
Wi-Fi Provision a device
170170
@@ -235,7 +235,7 @@ def provision_device(transport_mode, pop, userid, secretkey,
235235
else:
236236
service_name = None # Use default for SoftAP (192.168.4.1:80)
237237

238-
obj_transport = esp_prov.get_transport(transport_mode, service_name)
238+
obj_transport = esp_prov.get_transport(transport_mode, service_name, ble_adapter)
239239
if obj_transport is None:
240240
print("Establishing connection to node - Failed")
241241
return None

rmaker_tools/rmaker_prov/prov/prov_util.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,12 @@ def get_sec_patch_ver(tp, verbose=False):
8888
except Exception:
8989
return 0
9090

91-
def get_transport(sel_transport, service_name):
91+
def get_transport(sel_transport, service_name, ble_adapter=transport.DEFAULT_BLE_ADAPTER):
9292
"""
9393
Get object of class `Transport` based on input parameters
9494
`sel_transport` - Transport Mode (softap/ble)
9595
`service_name` - Service Name to connect to
96+
`ble_adapter` - HCI adapter name for BLE transport
9697
"""
9798
try:
9899
tp = None
@@ -115,9 +116,10 @@ def get_transport(sel_transport, service_name):
115116
import inspect
116117
import asyncio
117118
sig = inspect.signature(transport.Transport_BLE.__init__)
118-
if len(sig.parameters) == 3: # self, service_uuid, nu_lookup
119+
if len(sig.parameters) == 4: # self, service_uuid, nu_lookup, ble_adapter
119120
ble_transport = transport.Transport_BLE(service_uuid='0000ffff-0000-1000-8000-00805f9b34fb',
120-
nu_lookup=nu_lookup)
121+
nu_lookup=nu_lookup,
122+
ble_adapter=ble_adapter)
121123

122124
# Create sync wrapper for async transport
123125
class SyncBLETransport:

0 commit comments

Comments
 (0)