Device Library Peripheral
ble.json
Merged GATT database snapshot: services, characteristics, descriptors. The format matches WHAD tool “profile” JSON, with some extra fields.
services[]
| Field | Peripheral |
|---|---|
uuid | Required. 16-bit ("1800") or 128-bit (32/36 hex, dashes optional). |
start_handle, end_handle | Stored in JSON; registration ignores for logic. |
characteristics[] | See below. |
Characteristic
| Field | Notes |
|---|---|
handle | Declaration handle (0x2803 for Characteristic according to Bluetooth SIG specification). |
properties | Numeric GATT property bitmask according to Bluetooth SIG specification (standard bits: read 0x02, write 0x08, notify 0x10, … |
value | object required with uuid; optional handle, data (hex). Booleans encryption_required / authentication_required optionally enable security for this characteristic (trigger pairing on request). |
dynamic | Optional. on_read and on_write strings only - dynamic Lua functions to call. |
descriptors[] | Optional. uuid plus hex payload in data. UUID 2902 (CCCD) may be skipped (handled internally by NimBLE). |
devinfo (optional)
The devinfo field is kept for WHAD compatibility and largely ignored by ESP32 peripheral. For advertising the separate adv.json is used in practice.
| Field | Purpose |
|---|---|
adv_data | Hex → raw advertising (legacy embed). Prefer peripheral/adv.json + manifest advertisement. |
scan_rsp | Hex → scan response. |
bd_addr | String (AA:BB:…). |
addr_type | Number (0 = public-style, 1 = random). |
pdu_type | String; default ADV_IND. |
pairing_info (optional, peripheral SMP)
| Field | Notes |
|---|---|
initiate_pairing_on_connection | Boolean - whether to trigger pairing on connection or only on access to protected characteristics. |
passkey | Six-digit string when fixed passkey is desired. |
response | Responder SMP block: io_capability, auth_req, oob_data_flag, max_key_size, init_key_dist, resp_key_dist (numbers; defaults if object missing). |
adv.json
Peripheral advertising profiles for simulation (peripheral/adv.json).
Root
| Field | Required | Notes |
|---|---|---|
profiles | Yes | Non-empty array of advertising profiles. Invalid entries are skipped. |
It is possible for a single device to have multiple advertising profiles - to be visible at different addresses with different payloads at the same time.
Profile object (profiles[])
| Field | Default / notes |
|---|---|
id | String; profile0, profile1, … if omitted. Used by Lua adv_enable, adv_disable, adv_set_data, get_adv_bd_addr. |
enabled | Boolean. true → started on sim start. false → loaded but skipped until adv_enable(id). |
legacy_pdu | Boolean. true sets the “legacy” (Bluetooth 4) advertising type. false - Advertising Extensions (Bluetooth 5) |
connectable | Boolean. |
scannable | Boolean. |
channel_map | Number according to Bluetooth SIG Specification byte; default 7 (all channels). |
primary_phy, secondary_phy - for extended advertising | "1M" | "2M" | "coded"; default 1M. |
tx_power | Integer; 127 = controller default. |
adv_interval_ms | Number; defines how often the packet is broadcasted. Default 100 ms interval = 10x per second (converted to 0.625 ms units). |
addr_type | See table below. |
bd_addr | "AA:BB:CC:DD:EE:FF". If empty and not public_hardware, may copy devinfo.bd_addr from ble.json. |
adv_data_hex | Hex advertising PDU (no spaces). |
scan_rsp_hex | Optional hex scan response. |
rotation | Optional; see below. |
addr_type values:
| Value | Behavior |
|---|---|
random_generated | New random address every time the profile starts. |
random_specific | Use bd_addr as random address (default if unknown string). |
public_hardware | Controller public address (static); bd_addr filled from hardware when started. |
Rotation (rotation)
Intended to simulate devices that quickly rotate the advertising payloads.
Optional object on a profile:
| Field | Notes |
|---|---|
interval_ms | Period between payload switches; default 1000. |
payloads | Array of { "adv_data_hex": "…" }; ≥ 2 required or rotation is ignored. |
When rotation is active, top-level adv_data_hex is replaced by payloads[0]; a FreeRTOS timer cycles through payloads. scan_rsp_hex stays static (not rotated).
Runtime (Lua)
After simulation starts, peripheral Lua can change live advertising:
adv_set_data(profile_id, adv_hex [, scan_rsp_hex])adv_enable(profile_id)/adv_disable(profile_id)get_adv_bd_addr(profile_id)→ address string when available
Active profiles are also summarized in WebSocket sim_status → adv array (id, instance, running, bd_addr, addr_type).
Fallback
If peripheral/adv.json is missing or invalid, firmware may build a single profile from ble.json → devinfo WHAD format (adv_data, scan_rsp, bd_addr, pdu_type). Without either adv profiles or devinfo, advertising cannot start.
interface.json
Defines the simulated device “physical” interface (local buttons, panel, …). For example a button to switch into a pairing mode or turn on/off. Displayed in simulation screen (mobile, web) as additional buttons, and optionally tied to ESP32 physical buttons.
- Root
buttons: required array (may be empty). - Each accepted button requires
id,name,lua(dynamic function name to call after pressing the button).
Optional:
physical_button_id(1 | 2) - press ESP32 button to trigger this functionphysical_button_press(string; e.g."single","double")