{"_id":"@brilliantsole/noble","name":"@brilliantsole/noble","dist-tags":{"latest":"1.12.0"},"versions":{"1.12.0":{"author":{"name":"Sandeep Mistry","email":"sandeep.mistry@gmail.com"},"maintainers":[{"name":"brilliantsole","email":"zack@brilliantsole.com"}],"license":"MIT","name":"@brilliantsole/noble","description":"A Node.js BLE (Bluetooth Low Energy) central library.","version":"1.12.0","repository":{"type":"git","url":"git+https://github.com/stoprocent/noble.git"},"bugs":{"url":"https://github.com/stoprocent/noble/issues"},"keywords":["bluetooth","BLE","bluetooth low energy","bluetooth smart","central"],"main":"./index.js","types":"./index.d.ts","gypfile":true,"engines":{"node":">=14"},"dependencies":{"debug":"^4.3.7","node-addon-api":"^8.1.0","node-gyp-build":"^4.8.1","patch-package":"^8.0.0"},"optionalDependencies":{"@stoprocent/bluetooth-hci-socket":"^2.2.6"},"devDependencies":{"@babel/eslint-parser":"^7.27.0","@commitlint/cli":"^19.3.0","@commitlint/config-conventional":"^19.2.2","@semantic-release/changelog":"^6.0.3","@semantic-release/exec":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/github":"^10.1.1","async":"^3.2.6","cross-env":"^7.0.3","eslint":"^8.57.1","eslint-config-node":"^4.1.0","eslint-plugin-import":"^2.31.0","eslint-plugin-jest":"^28.11.0","eslint-plugin-n":"^17.10.3","eslint-plugin-node":"^11.1.0","eslint-plugin-promise":"^7.1.0","jest":"^29.7.0","jshint":"^2.13.6","prebuildify":"^6.0.1","prebuildify-cross":"^5.1.1","prettier":"^3.3.3","proxyquire":"^2.1.3","semantic-release":"^24.1.1","should":"^13.2.3","sinon":"^15.0.1"},"scripts":{"install":"node-gyp-build","lint":"eslint \"**/*.js\"","lint-fix":"eslint \"**/*.js\" --fix","prebuildify":"prebuildify --napi --target 17.0.0 --force --strip --verbose","prebuildify-cross":"patch-package && prebuildify-cross --napi --target 17.0.0 --force --strip --verbose","semantic-release":"semantic-release","pretest":"npm run rebuild","rebuild":"node-gyp rebuild","test":"npx jest"},"publishConfig":{"access":"public"},"_id":"@brilliantsole/noble@1.12.0","gitHead":"2eb1c08b8ab197181162ab42b7c2aa9fb4ebd2b2","homepage":"https://github.com/stoprocent/noble#readme","_nodeVersion":"22.16.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-m5J/y/oZ3I/1fo0gRDzwGUvKQpDDNrnshyz7VaZRk8FGM+TCQJaGRcuyQxDq+wEFiWuj5aon6UoMC6O8Cvsoyg==","shasum":"7d4f0d78d2099f6bebcba26c2cad9f02f019bf16","tarball":"https://registry.npmjs.org/@brilliantsole/noble/-/noble-1.12.0.tgz","fileCount":86,"unpackedSize":810173,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDmwPXUpB3sgXdvgbkY3HN5VXdGyubYtgzsxH/v9k0lBwIhAO9JkgdKuF65Xhafn1wPV/6oAqi3i+PcDj0JeXrQaHRZ"}]},"_npmUser":{"name":"brilliantsole","email":"zack@brilliantsole.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/noble_1.12.0_1774290893977_0.23836861803431963"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-23T18:34:53.890Z","1.12.0":"2026-03-23T18:34:54.160Z","modified":"2026-03-23T18:34:54.358Z"},"maintainers":[{"name":"brilliantsole","email":"zack@brilliantsole.com"}],"description":"A Node.js BLE (Bluetooth Low Energy) central library.","homepage":"https://github.com/stoprocent/noble#readme","keywords":["bluetooth","BLE","bluetooth low energy","bluetooth smart","central"],"repository":{"type":"git","url":"git+https://github.com/stoprocent/noble.git"},"author":{"name":"Sandeep Mistry","email":"sandeep.mistry@gmail.com"},"bugs":{"url":"https://github.com/stoprocent/noble/issues"},"license":"MIT","readme":"# ![noble](assets/noble-logo.png)\n\n[![npm version](https://badgen.net/npm/v/@stoprocent/noble)](https://www.npmjs.com/package/@stoprocent/noble)\n[![npm downloads](https://badgen.net/npm/dt/@stoprocent/noble)](https://www.npmjs.com/package/@stoprocent/noble)\n\n\nA Node.js BLE (Bluetooth Low Energy) central module.\n\nWant to implement a peripheral? Check out [@stoprocent/bleno](https://github.com/stoprocent/bleno).\n\n> **Note:** Currently, running both noble (central) and bleno (peripheral) together only works with macOS bindings or when using separate HCI/UART dongles. Support for running both on a single HCI adapter (e.g., on Linux systems) will be added in future releases.\n\n## About This Fork\n\nThis fork of `noble` was created to introduce several key improvements and new features:\n\n1. **Flexible Bluetooth Driver Selection**:\n   - This library enables flexible selection of Bluetooth drivers through the new `withBindings()` API. Use native platform bindings (Mac, Windows) or HCI bindings with UART/serial support for hardware dongles, allowing Bluetooth connectivity across various platforms and hardware setups.\n   \n2. **Native Bindings Improvements**: \n   - Fixed and optimized native bindings for macOS, ensuring better compatibility and performance on Apple devices\n   - Overhauled Windows native bindings with support for `Service Data` from advertisements\n   - Aligned behavior across different bindings (macOS, Windows, HCI) for consistent behavior \n\n3. **Modern JavaScript Support**:\n   - Added full Promise-based API with async/await support throughout the library\n   - Implemented async iterators for device discovery with `for await...of` syntax\n   - Refactored codebase to use modern JavaScript patterns and best practices\n\n4. **Enhanced Testing and Reliability**:\n   - Migrated tests to Jest for improved coverage and reliability\n   - Added comprehensive TypeScript type definitions\n   - Fixed numerous edge cases and stability issues\n\n5. **New Features**: \n   - A `setAddress(...)` function to set the MAC address of the central device\n   - Direct device connection with `connect(...)/connectAsync(...)` without requiring a prior scan\n   - `waitForPoweredOnAsync(...)` function to simplify async workflows\n   - Support for multiple adapter configurations through the new `withBindings()` API\n   - Extended debugging capabilities and error handling\n   - Additionally, I plan to add raw L2CAP channel support, enhancing low-level Bluetooth communication capabilities\n\n\nIf you appreciate these enhancements and the continued development of this project, please consider supporting my work. \n\n[![Buy me a coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/stoprocent)\n\n## Install\n\n```sh\nnpm install @stoprocent/noble\n```\n\n## Usage\n\n### TypeScript (Recommended)\n\n```typescript\n// Auto-select based on platform\nimport noble from '@stoprocent/noble';\n// or\nimport { withBindings } from '@stoprocent/noble';\n// Auto-select based on platform\nconst noble = withBindings('default'); // 'hci', 'win', 'mac'\n```\n\nFor more detailed examples and API documentation, see [Binding Types](#Binding-Types) below.\n\n### JavaScript\n\n```javascript\nconst noble = require('@stoprocent/noble');\n// or \nconst { withBindings } = require('@stoprocent/noble');\nconst noble = withBindings('default'); // 'hci', 'win', 'mac'\n```\n\n\n## Quick Start Example\n\n### TypeScript Example (Modern Async/Await)\n\n#### Basic Scan\n\n```typescript\nimport noble from '@stoprocent/noble';\n\n// Discover peripherals as an async generator\ntry {\n  // Wait for Adapter poweredOn state\n  await noble.waitForPoweredOnAsync();\n  // Start scanning first\n  await noble.startScanningAsync();\n  \n  // Use the async generator with proper boundaries\n  for await (const peripheral of noble.discoverAsync()) {\n    console.log(`Found device: ${peripheral.advertisement.localName || 'Unknown'}`);\n    // Process the peripheral as needed\n    \n    // Optional: stop scanning when a specific device is found\n    if (peripheral.advertisement.localName === 'MyDevice') {\n      break;\n    }\n  }\n  \n  // Clean up after discovery\n  await noble.stopScanningAsync();\n} catch (error) {\n  console.error('Discovery error:', error);\n  await noble.stopScanningAsync();\n}\n```\n\nFor a more detailed example, please check out [examples/peripheral-explorer.ts](examples/peripheral-explorer.ts)\n\nAlternatively, you can still use the legacy event-based API:\n\n``` javascript\nconst noble = require('@stoprocent/noble');\n\n// State change event is emitted when adapter state changes\nnoble.on('stateChange', function (state) {\n  if (state === 'poweredOn') {\n    // Start scanning when adapter is ready\n    noble.startScanning();\n  } else {\n    // Stop scanning if adapter becomes unavailable\n    noble.stopScanning();\n  }\n});\n\n// Discover event is emitted when a peripheral is found\nnoble.on('discover', peripheral => {\n  console.log(peripheral);\n  // From here you can work with the peripheral:\n  // - Connect to it: peripheral.connect()\n  // - Check advertisement data: peripheral.advertisement\n  // - See signal strength: peripheral.rssi\n});\n```\n\n#### Connecting to the device\n\n``` typescript\n// Stop scan\nawait noble.stopScanningAsync();\n// Connect\nawait peripheral.connectAsync();\n// Discover\nconst { services, characteristics } = await peripheral.discoverAllServicesAndCharacteristicsAsync();\n```\n\n#### Working with Services and Characteristics\n\n```typescript\nasync function exploreServices(peripheral) {\n  // Discover all services and characteristics at once\n  const { services } = await peripheral.discoverAllServicesAndCharacteristicsAsync();\n  \n  const results = [];\n  \n  for (const service of services) {\n    const serviceInfo = {\n      uuid: service.uuid,\n      characteristics: []\n    };\n    \n    for (const characteristic of service.characteristics) {\n      const characteristicInfo = {\n        uuid: characteristic.uuid,\n        properties: characteristic.properties\n      };\n      \n      // Read the characteristic if it's readable\n      if (characteristic.properties.includes('read')) {\n        characteristicInfo.value = await characteristic.readAsync();\n      }\n      \n      serviceInfo.characteristics.push(characteristicInfo);\n    }\n    \n    results.push(serviceInfo);\n  }\n  \n  return results;\n}\n```\n\n#### Reading and Writing Data\n\n```typescript\nasync function readBatteryLevel(peripheral) {\n  // Get battery service (0x180F is the standard UUID for Battery Service)\n  const { characteristics } = await peripheral.discoverSomeServicesAndCharacteristicsAsync(\n    ['180f'], // Battery Service\n    ['2a19']  // Battery Level Characteristic\n  );\n  \n  if (characteristics.length > 0) {\n    const data = await characteristics[0].readAsync();\n    return data[0]; // Battery percentage\n  }\n  \n  return null;\n}\n\nasync function writeCharacteristic(peripheral, serviceUuid, characteristicUuid, data) {\n  const { characteristics } = await peripheral.discoverSomeServicesAndCharacteristicsAsync(\n    [serviceUuid], \n    [characteristicUuid]\n  );\n  \n  if (characteristics.length > 0) {\n    // false = with response, true = without response\n    const requiresResponse = !characteristics[0].properties.includes('writeWithoutResponse');\n    await characteristics[0].writeAsync(data, !requiresResponse);\n    return true;\n  }\n  \n  return false;\n}\n```\n\n### JavaScript Example (Battery Level)\n\n```javascript\nconst { withBindings } = require('@stoprocent/noble');\n\n// Read the battery level of the first found peripheral exposing the Battery Level characteristic\nasync function readBatteryLevel() {\n  const noble = withBindings('default');\n\n  try {\n    await noble.waitForPoweredOnAsync();\n    await noble.startScanningAsync(['180f'], false);\n    \n    noble.on('discover', async (peripheral) => {\n      await noble.stopScanningAsync();\n      await peripheral.connectAsync();\n      \n      const { characteristics } = await peripheral.discoverSomeServicesAndCharacteristicsAsync(['180f'], ['2a19']);\n      const batteryLevel = (await characteristics[0].readAsync())[0];\n\n      console.log(`${peripheral.address} (${peripheral.advertisement.localName}): ${batteryLevel}%`);\n\n      await peripheral.disconnectAsync();\n      process.exit(0);\n    });\n  } catch (error) {\n    console.error(error);\n  }\n}\n\nreadBatteryLevel();\n```\n\n## API Overview\n\nNoble provides both callback-based and Promise-based (Async) APIs:\n\n### Binding Types\n\n```typescript\n// Default binding (automatically selects based on platform)\nimport noble from '@stoprocent/noble';\n// or\nimport { withBindings } from '@stoprocent/noble';\nconst noble = withBindings('default');\n\n// Specific bindings\nconst nobleHci = withBindings('hci');  // HCI socket binding\nconst nobleMac = withBindings('mac');  // macOS binding\nconst nobleWin = withBindings('win');  // Windows binding\n\n// Custom options for HCI binding (Using UART HCI Dongle)\nconst nobleCustom = withBindings('hci', { \n  hciDriver: 'uart',\n  bindParams: {\n    uart: {\n      port: '/dev/ttyUSB0',\n      baudRate: 1000000\n    }\n  }\n});\n\n// Custom options for HCI binding (Native)\nconst nobleCustom = withBindings('hci', { \n  hciDriver: 'native',\n  deviceId: 0 // This could be also set by env.NOBLE_HCI_DEVICE_ID=0\n});\n```\n\n### Core Methods\n\n```typescript\n// Wait for adapter to be powered on\nawait noble.waitForPoweredOnAsync(timeout?: number);\n\n// Start scanning\nawait noble.startScanningAsync(serviceUUIDs?: string[], allowDuplicates?: boolean);\n\n// Stop scanning\nawait noble.stopScanningAsync();\n\n// Discover peripherals as an async generator\nfor await (const peripheral of noble.discoverAsync()) {\n  // handle each discovered peripheral\n}\n\n// Connect directly to a peripheral by ID or address\nconst peripheral = await noble.connectAsync(idOrAddress, options?);\n\n// Set adapter address (HCI only on supported devices)\nnoble.setAddress('00:11:22:33:44:55');\n\n// Reset adapter\nnoble.reset();\n\n// Stop noble\nnoble.stop();\n```\n\n### Peripheral Methods\n\n```typescript\n// Connect to peripheral\nawait peripheral.connectAsync();\n\n// Disconnect from peripheral\nawait peripheral.disconnectAsync();\n\n// Update RSSI\nconst rssi = await peripheral.updateRssiAsync();\n\n// Discover services\nconst services = await peripheral.discoverServicesAsync(['180f']); // Optional service UUIDs\n\n// Discover all services and characteristics\nconst { services, characteristics } = await peripheral.discoverAllServicesAndCharacteristicsAsync();\n\n// Discover specific services and characteristics\nconst { services, characteristics } = await peripheral.discoverSomeServicesAndCharacteristicsAsync(\n  ['180f'], ['2a19']\n);\n\n// Read and write handles\nconst data = await peripheral.readHandleAsync(handle);\nawait peripheral.writeHandleAsync(handle, data, withoutResponse);\n```\n\n### Service Methods\n\n```typescript\n// Discover included services\nconst includedServiceUuids = await service.discoverIncludedServicesAsync([serviceUUIDs]);\n\n// Discover characteristics\nconst characteristics = await service.discoverCharacteristicsAsync([characteristicUUIDs]);\n```\n\n### Characteristic Methods\n\n> **Note:** The `data` event is the primary event for handling both read responses and notifications. When using the event-based approach, you can differentiate between read responses and notifications using the `isNotification` parameter. The previously used `read` event **has been deprecated and removed**. Instead, use the `data` event with `isNotification=false` to identify read responses.\n\n```typescript\n// Read characteristic value\nconst data = await characteristic.readAsync();\n\n// Write characteristic value\nawait characteristic.writeAsync(data, withoutResponse);\n\n// Subscribe to notifications\nawait characteristic.subscribeAsync();\n\n// Unsubscribe from notifications\nawait characteristic.unsubscribeAsync();\n\n// Receive notifications using async iterator\nfor await (const data of characteristic.notificationsAsync()) {\n  console.log(`Received notification: ${data}`);\n}\n\n// Discover descriptors\nconst descriptors = await characteristic.discoverDescriptorsAsync();\n```\n\n### Characteristic Events\n\n```typescript\n// Receive data (both read responses and notifications)\ncharacteristic.on('data', (data: Buffer, isNotification: boolean) => {\n  console.log(`Received ${isNotification ? 'notification' : 'read response'}: ${data}`);\n});\n\n// Write completion \ncharacteristic.on('write', (error: Error | undefined) => {\n  console.log('Write completed');\n});\n\n// Descriptor discovery\ncharacteristic.on('descriptorsDiscover', (descriptors: Descriptor[]) => {\n  console.log('Descriptors discovered');\n});\n```\n\n### Descriptor Methods\n\n```typescript\n// Read descriptor value\nconst value = await descriptor.readValueAsync();\n\n// Write descriptor value\nawait descriptor.writeValueAsync(data);\n```\n\n## Installation\n\n* [Prerequisites](#prerequisites)\n  * [UART](#uart)\n  * [OS X](#os-x)\n  * [Linux](#linux)\n    * [Ubuntu, Debian, Raspbian](#ubuntu-debian-raspbian)\n    * [Fedora and other RPM-based distributions](#fedora-and-other-rpm-based-distributions)\n    * [Intel Edison](#intel-edison)\n  * [FreeBSD](#freebsd)\n  * [Windows](#windows)\n  * [Docker](#docker)\n* [Installing and using the package](#installing-and-using-the-package)\n\n### Prerequisites\n\n#### UART (Any OS)\n\nPlease refer to [https://github.com/stoprocent/node-bluetooth-hci-socket#uartserial-any-os](https://github.com/stoprocent/node-bluetooth-hci-socket#uartserial-any-os)\n\n__NOTE:__ While environmental variables are still supported for backward compatibility, the recommended approach is to specify driver options directly in the `withBindings()` call as shown below:\n\n##### Recommended Approach (UART port specified in `bindParams`)\n\n```typescript\nimport { withBindings } from '@stoprocent/noble';\nconst noble = withBindings('hci', { \n  hciDriver: 'uart',\n  bindParams: {\n    uart: {\n      port: '/dev/ttyUSB0',\n      baudRate: 1000000\n    }\n  }\n});\n```\n\n##### Legacy Approach (Using environmental variables - not recommended for new implementations)\n\n```bash\n$ export BLUETOOTH_HCI_SOCKET_UART_PORT=/dev/tty...\n$ export BLUETOOTH_HCI_SOCKET_UART_BAUDRATE=1000000\n```\n\n__NOTE:__ `BLUETOOTH_HCI_SOCKET_UART_BAUDRATE` defaults to `1000000` so only needed if different.\n\n```typescript\nimport noble from '@stoprocent/noble';\n```\n\n#### OS X\n\n * Install [Xcode](https://itunes.apple.com/ca/app/xcode/id497799835?mt=12)\n * On newer versions of OSX, allow bluetooth access on the terminal app: \"System Preferences\" —> \"Security & Privacy\" —> \"Bluetooth\" -> Add terminal app (see [Sandboxed terminal](#sandboxed-terminal))\n\n#### Linux\n\n * Kernel version 3.6 or above\n * `libbluetooth-dev` needs to be installed. For instructions for specific distributions, see below.\n * To set the necessary privileges to run without sudo, [see this section](#running-without-rootsudo-linux-specific). This is required for all distributions (Raspbian, Ubuntu, Fedora, etc). You will not get any errors if running without sudo, but nothing will happen.\n\n##### Ubuntu, Debian, Raspbian\n\nSee the [generic Linux notes above](#linux) first.\n\n```sh\nsudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev\n```\n\nMake sure `node` is on your `PATH`. If it's not, some options:\n * Symlink `nodejs` to `node`: `sudo ln -s /usr/bin/nodejs /usr/bin/node`\n * [Install Node.js using the NodeSource package](https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions)\n\nIf you are having trouble connecting to BLE devices on a Raspberry Pi, you should disable the `pnat` plugin. Add the following line at the bottom of `/etc/bluetooth/main.conf`:\n\n```\nDisablePlugins=pnat\n```\n\nThen restart the system.\n\nSee [Issue #425 · OpenWonderLabs/homebridge-switchbot](https://github.com/OpenWonderLabs/homebridge-switchbot/issues/425#issuecomment-1190864279).\n\n##### Fedora and other RPM-based distributions\n\nSee the [generic Linux notes above](#linux) first.\n\n```sh\nsudo yum install bluez bluez-libs bluez-libs-devel\n```\n\n##### Intel Edison\n\nSee the [generic Linux notes above](#linux) first.\n\nSee [Configure Intel Edison for Bluetooth LE (Smart) Development](http://rexstjohn.com/configure-intel-edison-for-bluetooth-le-smart-development/).\n\n#### FreeBSD\n\nMake sure you have GNU Make:\n\n```sh\nsudo pkg install gmake\n```\n\nDisable automatic loading of the default Bluetooth stack by putting [no-ubt.conf](https://gist.github.com/myfreeweb/44f4f3e791a057bc4f3619a166a03b87) into `/usr/local/etc/devd/no-ubt.conf` and restarting devd (`sudo service devd restart`).\n\nUnload `ng_ubt` kernel module if already loaded:\n\n```sh\nsudo kldunload ng_ubt\n```\n\nMake sure you have read and write permissions on the `/dev/usb/*` device that corresponds to your Bluetooth adapter.\n\n#### Windows\n\n[node-gyp requirements for Windows](https://github.com/TooTallNate/node-gyp#installation)\n\nInstall the required tools and configurations using Microsoft's [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools) from an elevated PowerShell or cmd.exe (run as Administrator).\n\n```cmd\nnpm install --global --production windows-build-tools\n```\n\n[node-bluetooth-hci-socket prerequisites](#windows)\n   * Compatible Bluetooth 5.0 Zephyr HCI-USB adapter (you need to add BLUETOOTH_HCI_SOCKET_USB_VID and BLUETOOTH_HCI_SOCKET_USB_PID to the process env)\n   * Compatible Bluetooth 4.0 USB adapter\n   * [WinUSB](https://msdn.microsoft.com/en-ca/library/windows/hardware/ff540196(v=vs.85).aspx) driver setup for Bluetooth 4.0 USB adapter, using [Zadig tool](http://zadig.akeo.ie/)\n\nSee [@don](https://github.com/don)'s setup guide on [Bluetooth LE with Node.js and Noble on Windows](https://www.youtube.com/watch?v=mL9B8wuEdms&feature=youtu.be&t=1m46s)\n\n#### Docker\n\nMake sure your container runs with `--network=host` options and all specific environment prerequisites are verified.\n\n### Running without root/sudo (Linux-specific)\n\nRun the following command:\n\n```sh\nsudo setcap cap_net_raw+eip $(eval readlink -f `which node`)\n```\n\nThis grants the `node` binary `cap_net_raw` privileges, so it can start/stop BLE advertising.\n\n__Note:__ The above command requires `setcap` to be installed.\nIt can be installed the following way:\n\n * apt: `sudo apt-get install libcap2-bin`\n * yum: `su -c \\'yum install libcap2-bin\\'`\n\n### Multiple Adapters (Linux-specific)\n\n`hci0` is used by default.\n\nYou can specify which HCI adapter to use in two ways:\n\n#### 1. Using `withBindings` (Recommended)\n\n```typescript\nimport { withBindings } from '@stoprocent/noble';\n\n// Specify HCI adapter in code\nconst noble = withBindings('hci', { \n  hciDriver: 'native',\n  deviceId: 1 // Using hci1\n});\n```\n\n#### 2. Using environment variable\n\nTo override using environment variables, set the `NOBLE_HCI_DEVICE_ID` environment variable to the interface number.\n\nFor example, to specify `hci1`:\n\n```sh\nsudo NOBLE_HCI_DEVICE_ID=1 node <your file>.js\n```\n\nIf you are using multiple HCI devices in one setup you can run two instances of noble with different binding configurations by initializing them seperatly in code:\n\n``` typescript\nimport { withBindings } from '@stoprocent/noble';\n\n// Create two noble instances with different HCI adapters\nconst nobleAdapter0 = withBindings('hci', { \n  hciDriver: 'native',\n  deviceId: 0 // Using hci0\n});\n\nconst nobleAdapter1 = withBindings('hci', { \n  hciDriver: 'native',\n  deviceId: 1 // Using hci1\n});\n```\n\n\n### Reporting all HCI events (Linux-specific)\n\nBy default, noble waits for both the advertisement data and scan response data for each Bluetooth address. If your device does not use scan response, the `NOBLE_REPORT_ALL_HCI_EVENTS` environment variable can be used to bypass it.\n\n```sh\nsudo NOBLE_REPORT_ALL_HCI_EVENTS=1 node <your file>.js\n```\n\n## Environment Variables\n\nThe following environment variables can configure noble's behavior:\n\n| Variable | Purpose | Default | Example |\n|----------|---------|---------|---------|\n| NOBLE_HCI_DEVICE_ID | Specify which HCI adapter to use | 0 | `export NOBLE_HCI_DEVICE_ID=1` |\n| NOBLE_REPORT_ALL_HCI_EVENTS | Report HCI events without waiting for scan response | false | `export NOBLE_REPORT_ALL_HCI_EVENTS=1` |\n| BLUETOOTH_HCI_SOCKET_UART_PORT | UART port for HCI communication | none | `export BLUETOOTH_HCI_SOCKET_UART_PORT=/dev/ttyUSB0` |\n| BLUETOOTH_HCI_SOCKET_UART_BAUDRATE | UART baudrate | 1000000 | `export BLUETOOTH_HCI_SOCKET_UART_BAUDRATE=1000000` |\n\n> **Note:** The preferred method for configuration is now using the `withBindings()` API rather than environment variables.","readmeFilename":"README.md","_rev":"1-a980a543a914a33038749ec272976bd3"}