# BLE Demo — WebBLE

Scan for nearby Bluetooth Low Energy devices using the Web Bluetooth API.

## How This Demo Works

This demo page uses the Web Bluetooth API to scan for nearby BLE devices. It demonstrates the core `requestDevice()` flow that the WebBLE extension enables on iOS Safari.

It also includes a background sync panel for the companion-app-only APIs:

- `requestBackgroundConnection()` to keep a BLE device connected while Safari is backgrounded
- `registerCharacteristicNotifications()` to raise iOS notifications for characteristic changes
- `registerBeaconScanning()` to watch for matching BLE advertisements

Background sync notification registrations require a `condition` object. A minimal example is `{ decode: 'uint8', operator: 'changed', threshold: 0 }`.

## Code Example

```html
<!-- Status indicator -->
<div id="status">Checking extension...</div>

<!-- Scan button — MUST be triggered by user gesture -->
<button id="scanBtn" onclick="scanForDevices()">Scan for Devices</button>

<script>
// Check if Web Bluetooth is available
function checkSupport() {
  if (navigator.bluetooth) {
    // Extension is active or browser has native support
    document.getElementById('scanBtn').disabled = false;
    document.getElementById('status').textContent = 'WebBLE extension active';
  }
}

// Scan for devices — called from button click (user gesture required)
async function scanForDevices() {
  try {
    const device = await navigator.bluetooth.requestDevice({
      acceptAllDevices: true
    });
    console.log('Found device:', device.name, device.id);
  } catch (err) {
    if (err.name !== 'NotFoundError') {
      console.error('Scan error:', err.message);
    }
  }
}

checkSupport();
</script>
```

## Key Points

- **User gesture required**: The "Scan for Devices" button triggers `requestDevice()` from a click handler. This is mandatory on Safari iOS — calling it on page load throws `SecurityError`.
- **Extension detection**: The demo checks for `navigator.bluetooth` availability and also listens for the `webble:extension:ready` event.
- **Error handling**: `NotFoundError` is normal (user cancelled the picker). Other errors are displayed to the user.
- **No persistent pairing**: Each page load starts fresh. Previously discovered devices are not remembered.

## Using with the SDK

Instead of raw `navigator.bluetooth`, use the SDK for a better developer experience:

```typescript
import '@ios-web-bluetooth/core/auto';
import { WebBLE } from '@ios-web-bluetooth/core';

const ble = new WebBLE();

// Triggered from a button click handler
async function scan() {
  const device = await ble.requestDevice({
    acceptAllDevices: true
  });
  console.log('Found:', device.name);
}
```

## React Version

```typescript
import { useWebBLE } from '@ios-web-bluetooth/react';

function Scanner() {
  const { requestDevice, isAvailable, devices } = useWebBLE();

  // requestDevice is called from onClick — user gesture is satisfied
  return (
    <div>
      <button onClick={() => requestDevice({ acceptAllDevices: true })} disabled={!isAvailable}>
        Scan for Devices
      </button>
      {devices.map(d => (
        <div key={d.id}>{d.name || 'Unknown'} — {d.id}</div>
      ))}
    </div>
  );
}
```
