onDeviceFound
Optional callback prop on <BTProvider>. Fires once for each advertisement that matches your acceptedDevices filter. This is the callback responsible for actually pairing + connecting — the provider hands you a BTManagedDevice, and your handler must call device.connect() to start receiving data.
Signature
import type { BTManagedDevice, BTManager, IntegratedDevices } from "@ovok/native";
onDeviceFound?: <T extends readonly IntegratedDevices[]>(
device: BTManagedDevice<T[number]>,
manager: BTManager<T>,
) => Promise<void>;
device is a typed wrapper around the underlying react-native-ble-plx peripheral. manager is the BT manager instance that owns scanning — most apps never need it; it's available so multi-device flows can stop scanning while pairing.
What device.connect() does
public connect = async () => { ... }
It is the only public method on BTManagedDevice your handler needs to call. Internally it:
- Opens a GATT connection to the peripheral.
- Discovers all services + characteristics.
- Subscribes to every characteristic the device exposes (the
subscribeToAllCharacteristicsstep is automatic and private — you do not call it). - Wires up the device's internal
BTDataProcessorso incoming bytes route through the parser. - Triggers the first
onDeviceStatusChanged→Connectedafter step 1 succeeds.
If any step throws, the error surfaces via onError (not via the promise — connect() resolves either way, errors are reported through the provider's error channel).
Usage
import React, { useCallback } from "react";
import { BleManager } from "react-native-ble-plx";
import { BTProvider, IntegratedDevices } from "@ovok/native";
const bleManager = new BleManager();
const acceptedDevices = [IntegratedDevices.BP2] as const;
function MyApp() {
const handleDeviceFound = useCallback(async (device) => {
// device.deviceData = { id, name, localName, sn, manufacturerData, measurementTypes }
console.log("Pairing with", device.deviceData.name, device.deviceData.sn);
await device.connect();
// Subscription happens inside `connect()`. Do NOT call
// `device.subscribeToAllCharacteristics()` — it is a private internal step.
}, []);
return (
<BTProvider
bleManager={bleManager}
acceptedDevices={acceptedDevices}
onDeviceFound={handleDeviceFound}
>
<YourScreens />
</BTProvider>
);
}
Filtering by device kind
If you accept multiple device kinds, branch in the handler before connecting (e.g. to surface different pairing UI):
const acceptedDevices = [
IntegratedDevices.BP2,
IntegratedDevices.SPO2,
IntegratedDevices.F4,
] as const;
const handleDeviceFound = useCallback(async (device) => {
switch (device.deviceData.name) {
case IntegratedDevices.BP2:
setPairingUI("bp-cuff");
break;
case IntegratedDevices.SPO2:
setPairingUI("pulse-oximeter");
break;
case IntegratedDevices.F4:
setPairingUI("scale");
break;
}
await device.connect();
}, []);
Refusing a device
onDeviceFound does not have an opt-out return value. If you want to refuse a peripheral your acceptedDevices filter matched (e.g. wrong serial number for a multi-device clinic), just don't call connect(). The provider will drop the reference and continue scanning; the device will fire onDeviceFound again on its next advertisement, and you can decide again.
const handleDeviceFound = useCallback(async (device) => {
if (!isAuthorizedSerial(device.deviceData.sn)) {
// Refuse — do not connect.
return;
}
await device.connect();
}, []);
Sequence after connect()
For a typical BP2 pairing:
onDeviceFound→ your handler callsawait device.connect().onDeviceStatusChanged→Connected.- (User initiates a reading on the cuff.)
onDeviceStatusChanged→Measuring(withmeasurementTypeKey).onResult→ parsed measurement.onDeviceStatusChanged→Connected.
If pairing fails:
onDeviceFound→ your handler callsawait device.connect().onErrorfires withdata.deviceDataset anddata.errordescribing the failure.- No
Connectedstatus arrives. Scanning continues — the next advertisement re-firesonDeviceFound.
Memoize the handler
onDeviceFound is the most expensive callback to re-register. Each new prop identity tears down + re-registers the scan subscription, and during teardown an in-flight pairing can be aborted. Wrap with useCallback and pin its dependencies:
const handleDeviceFound = useCallback(async (device) => {
await device.connect();
}, []); // empty deps — body uses only `device`, no closures over state
Related
- BTProvider — full provider reference
- on-device-status-changed — the
Connectedevent that follows yourconnect()call - on-result — the measurement payload that follows pairing
- on-error — failure path during
connect()