bluetooth
stableBluetooth Low Energy toolkit providing a simulated BtDevice class for scan/connect/GATT workflows plus utilities for UUID expansion, MAC parsing, advertisement decoding, and RSSI classification.
use plugin bluetooth::{BtDevice.new, connect, disconnect, …} Functions (19)
- BtDevice.new Create a simulated BLE device handle
- connect Connect to the device
- disconnect Disconnect from the device
- is_connected Check whether the device is connected
- get_name Get the device name
- get_mac Get the device MAC address
- get_rssi Get the current signal strength
- set_rssi Set the simulated signal strength
- discover_services List the device's GATT services
- add_service Add a service UUID to the device
- info Get a summary table of device state
- scan Run a simulated BLE scan
- uuid128_from_short Expand a 16-bit UUID to a full 128-bit UUID
- parse_mac Parse a MAC address string into 6 bytes
- format_mac Format 6 bytes as a MAC address string
- parse_advertisement_data Decode BLE advertisement data structures
- service_name Look up a BLE service name by 16-bit UUID
- gatt_characteristic_name Look up a GATT characteristic name by 16-bit UUID
- rssi_quality Classify an RSSI value as a quality string
Overview
The bluetooth plugin is a Bluetooth Low Energy (BLE) toolkit built around a simulated BtDevice class and a set of stateless protocol utilities. The simulation lets you exercise full scan, connect, and GATT-discovery workflows without real hardware: scan returns a fixed table of sample devices, and each BtDevice is a stateful handle that tracks its connection status, RSSI, and registered services. The utility functions are pure helpers for the data formats BLE works with — 16-bit and 128-bit UUIDs, MAC addresses, advertisement payloads, and signal strength in dBm.
Reach for this plugin when prototyping BLE logic, testing signal-quality or service-discovery code paths, or decoding the raw byte structures that show up in advertisement data. Because BtDevice is a handle, you create one with BtDevice.new(name, mac) and then call methods on it; the underlying device state persists for the life of the handle.
Common patterns
Scan, connect to the strongest device, and enumerate its services:
use plugin bluetooth::{scan, rssi_quality, BtDevice, service_name}
for d in scan() {
print("{d["name"]} {d["mac"]} ({rssi_quality(d["rssi"])})")
}
let dev = BtDevice.new("Heart Rate Monitor", "AA:BB:CC:DD:EE:01")
dev.connect()
for svc in dev.discover_services() {
print("service {svc["uuid"]} -> {service_name(svc["uuid"])}")
}
Build a device, register an extra service, and inspect its summary:
use plugin bluetooth::{BtDevice, service_name}
let dev = BtDevice.new("Fitness Band", "AA:BB:CC:DD:EE:03")
dev.add_service(0x180F) // Battery Service
dev.add_service(0x180D) // Heart Rate
let i = dev.info()
print("{i["name"]}: {i["service_count"]} services, connected={i["connected"]}")
Normalize identifiers across the UUID and MAC formats:
use plugin bluetooth::{uuid128_from_short, parse_mac, format_mac}
print(uuid128_from_short("180D")) // 0000180D-0000-1000-8000-00805F9B34FB
print(format_mac(parse_mac("aa-bb-cc-dd-ee-ff"))) // AA:BB:CC:DD:EE:FF
Create a simulated BLE device handle
Creates a simulated BLE device handle with the given name and MAC address. The device starts disconnected with a default RSSI of -50 and the Generic Access (0x1800) and Generic Attribute (0x1801) services.
use plugin bluetooth::{BtDevice}
let dev = BtDevice.new("Heart Rate Monitor", "AA:BB:CC:DD:EE:01")
print(dev.get_name())
Connect to the device
Connects to the device and returns true. Errors if the device is already connected.
use plugin bluetooth::{BtDevice}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
dev.connect()
print(dev.is_connected()) // true
Disconnect from the device
Disconnects from the device and returns true. Errors if the device is not connected.
use plugin bluetooth::{BtDevice}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
dev.connect()
dev.disconnect()
print(dev.is_connected()) // false
Check whether the device is connected
Returns true if the device is currently connected, false otherwise. Useful for guarding operations that require a live connection, such as discover_services.
use plugin bluetooth::{BtDevice}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
if !dev.is_connected() {
dev.connect()
}
print(dev.is_connected()) // true
Get the device name
Returns the device name supplied at construction.
Get the device MAC address
Returns the device MAC address supplied at construction.
Get the current signal strength
Returns the device's current RSSI (received signal strength) in dBm.
use plugin bluetooth::{BtDevice, rssi_quality}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
let rssi = dev.get_rssi()
print("signal: {rssi} dBm ({rssi_quality(rssi)})")
Set the simulated signal strength
Sets the simulated RSSI value for the device. Useful for testing signal-quality logic.
use plugin bluetooth::{BtDevice}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
dev.set_rssi(-85)
print(dev.get_rssi()) // -85
List the device's GATT services
Returns a table of the device's GATT services, each entry a table with uuid (16-bit integer) and name fields. Errors if the device is not connected.
use plugin bluetooth::{BtDevice}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
dev.connect()
for svc in dev.discover_services() {
print("{svc["uuid"]} -> {svc["name"]}")
}
Combine with service_name to resolve any UUID, including services added after construction:
use plugin bluetooth::{BtDevice, service_name}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
dev.connect()
dev.add_service(0x181A) // Environmental Sensing
for svc in dev.discover_services() {
print("{service_name(svc["uuid"])}")
}
Add a service UUID to the device
Adds a 16-bit service UUID to the device's service list, visible in subsequent discover_services calls.
use plugin bluetooth::{BtDevice}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
dev.add_service(0x180F) // Battery Service
Get a summary table of device state
Returns a summary table of the device's current state: name, MAC, RSSI, connection status, and number of registered services.
use plugin bluetooth::{BtDevice}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
let i = dev.info()
print("{i["name"]} ({i["mac"]}) connected={i["connected"]}")
Run a simulated BLE scan
Runs a simulated BLE scan and returns a table of discovered devices. Each entry has name, mac, rssi, and a services table of 16-bit service UUIDs.
use plugin bluetooth::{scan, rssi_quality}
for dev in scan() {
print("{dev["name"]} {dev["mac"]} rssi={dev["rssi"]} ({rssi_quality(dev["rssi"])})")
}
Expand a 16-bit UUID to a full 128-bit UUID
Expands a 16-bit BLE UUID given as a hex string (e.g. "180A" or "0x180A", at most 4 hex characters) into the full 128-bit UUID using the Bluetooth Base UUID 0000XXXX-0000-1000-8000-00805F9B34FB.
use plugin bluetooth::{uuid128_from_short}
let full = uuid128_from_short("180D")
print(full) // 0000180D-0000-1000-8000-00805F9B34FB
Parse a MAC address string into 6 bytes
Parses a MAC address string in AA:BB:CC:DD:EE:FF or AA-BB-CC-DD-EE-FF form into 6 raw bytes. Errors if the string does not have exactly 6 valid hex octets.
use plugin bluetooth::{parse_mac}
let bytes = parse_mac("AA:BB:CC:DD:EE:FF")
Format 6 bytes as a MAC address string
Formats exactly 6 bytes as an uppercase colon-separated MAC address string. Errors if the input is not 6 bytes long.
use plugin bluetooth::{parse_mac, format_mac}
let bytes = parse_mac("aa-bb-cc-dd-ee-ff")
print(format_mac(bytes)) // AA:BB:CC:DD:EE:FF
Decode BLE advertisement data structures
Decodes raw BLE advertisement payload bytes into a table of AD structures. Each entry is a table with length, type (AD type byte), and data (the structure's payload bytes). Parsing stops at a zero-length entry or truncated data.
use plugin bluetooth::{parse_advertisement_data}
let entries = parse_advertisement_data(adv_bytes)
for entry in entries {
print("type={entry["type"]} length={entry["length"]}")
}
Pair it with parse_mac to build the byte payload that an advertisement might carry:
use plugin bluetooth::{parse_mac, parse_advertisement_data}
let adv_bytes = parse_mac("02:01:06:03:03:0D")
for entry in parse_advertisement_data(adv_bytes) {
print("AD type {entry["type"]}")
}
Look up a BLE service name by 16-bit UUID
Looks up the human-readable name of a standard BLE service by its 16-bit UUID (e.g. 0x180D → "Heart Rate", 0x180F → "Battery Service"). Returns "Unknown Service" for unrecognized UUIDs.
use plugin bluetooth::{service_name}
print(service_name(0x180D)) // Heart Rate
print(service_name(0x181A)) // Environmental Sensing
Look up a GATT characteristic name by 16-bit UUID
Looks up the human-readable name of a standard GATT characteristic by its 16-bit UUID (e.g. 0x2A19 → "Battery Level", 0x2A37 → "Heart Rate Measurement"). Returns "Unknown Characteristic" for unrecognized UUIDs.
use plugin bluetooth::{gatt_characteristic_name}
print(gatt_characteristic_name(0x2A19)) // Battery Level
Classify an RSSI value as a quality string
Classifies an RSSI value (dBm) into a quality string: "excellent" (≥ -30), "good" (≥ -50), "fair" (≥ -70), "weak" (≥ -90), or "unusable" (below -90).
use plugin bluetooth::{rssi_quality}
print(rssi_quality(-45)) // good
print(rssi_quality(-95)) // unusable
Drive it from a live device to label its current signal:
use plugin bluetooth::{BtDevice, rssi_quality}
let dev = BtDevice.new("Sensor", "AA:BB:CC:DD:EE:02")
dev.set_rssi(-25)
print(rssi_quality(dev.get_rssi())) // excellent