Skip to content

Instantly share code, notes, and snippets.

@kosciolek
Created February 28, 2026 11:05
Show Gist options
  • Select an option

  • Save kosciolek/78d4f17283ed75787175f3bed5779aa4 to your computer and use it in GitHub Desktop.

Select an option

Save kosciolek/78d4f17283ed75787175f3bed5779aa4 to your computer and use it in GitHub Desktop.
/** Standard 16-bit Bluetooth SIG UUID or 128-bit vendor-specific UUID */
type UUID = string;
/** 16-bit attribute handle (0x0001 - 0xFFFF) */
type Handle = number;
type CharacteristicProperty =
| "read"
| "write"
| "write-without-response"
| "notify"
| "indicate"
| "broadcast"
| "authenticated-signed-writes"
| "extended-properties";
type ServiceType = "primary" | "secondary";
// ── Descriptors ──────────────────────────────────────────────
interface Descriptor {
handle: Handle;
uuid: UUID;
value: Uint8Array;
/** Read the descriptor value */
read(): Promise<Uint8Array>;
/** Write a new descriptor value */
write(value: Uint8Array): Promise<void>;
}
interface CCCD extends Descriptor {
uuid: "0x2902";
notifications: boolean;
indications: boolean;
/** Enable/disable notifications from this characteristic */
setNotifications(enabled: boolean): Promise<void>;
/** Enable/disable indications from this characteristic */
setIndications(enabled: boolean): Promise<void>;
}
// ── Characteristic ───────────────────────────────────────────
interface Characteristic {
declarationHandle: Handle;
valueHandle: Handle;
uuid: UUID;
properties: CharacteristicProperty[];
value: Uint8Array;
descriptors: Descriptor[];
/** Read the characteristic value (requires "read" property) */
readValue(): Promise<Uint8Array>;
/** Write with acknowledgment (requires "write" property) */
writeValue(value: Uint8Array): Promise<void>;
/** Write without acknowledgment — faster, no confirmation
* (requires "write-without-response" property) */
writeWithoutResponse(value: Uint8Array): void;
/** Subscribe to value change notifications (requires "notify" property).
* Writes 0x0001 to the CCCD descriptor under the hood. */
startNotifications(callback: (value: Uint8Array) => void): Promise<void>;
/** Unsubscribe from notifications. Writes 0x0000 to CCCD. */
stopNotifications(): Promise<void>;
/** Subscribe to indications — like notifications but with acknowledgment
* (requires "indicate" property). Writes 0x0002 to CCCD. */
startIndications(callback: (value: Uint8Array) => void): Promise<void>;
/** Unsubscribe from indications */
stopIndications(): Promise<void>;
/** Get a specific descriptor by UUID */
getDescriptor(uuid: UUID): Promise<Descriptor | undefined>;
/** Discover all descriptors for this characteristic */
discoverDescriptors(): Promise<Descriptor[]>;
}
// ── Service ──────────────────────────────────────────────────
interface Service {
handle: Handle;
endGroupHandle: Handle;
uuid: UUID;
type: ServiceType;
characteristics: Characteristic[];
includedServices: Service[];
/** Discover all characteristics within this service's handle range.
* Sends "Read By Type" requests for UUID 0x2803. */
discoverCharacteristics(): Promise<Characteristic[]>;
/** Find a characteristic by UUID */
getCharacteristic(uuid: UUID): Promise<Characteristic | undefined>;
/** Discover services included (referenced) by this service.
* Sends "Read By Type" requests for UUID 0x2802. */
discoverIncludedServices(): Promise<Service[]>;
}
// ── Device ───────────────────────────────────────────────────
interface BLEDevice {
name: string | null;
address: string;
services: Service[];
/** Establish a BLE connection to the device */
connect(): Promise<void>;
/** Disconnect from the device */
disconnect(): Promise<void>;
/** Discover all primary services (UUID 0x2800).
* Typically the first thing you do after connecting. */
discoverServices(): Promise<Service[]>;
/** Find a primary service by UUID */
getService(uuid: UUID): Promise<Service | undefined>;
/** Read the RSSI (signal strength) of the connection */
readRSSI(): Promise<number>;
/** Listen for connection state changes */
onDisconnect(callback: () => void): void;
}
// ── Scanner ──────────────────────────────────────────────────
interface BLEScanner {
/** Start scanning for nearby BLE devices.
* Listens for advertising packets. */
startScan(
filters?: { serviceUUIDs?: UUID[]; name?: string },
callback?: (device: BLEDevice) => void
): Promise<void>;
/** Stop scanning */
stopScan(): Promise<void>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment