Skip to main content

Bluetooth integration

Bluetooth support is opt-in per provider. The host app supplies a react-native-ble-plx BleManager and an acceptedDevices tuple. BTProvider requests access, creates the BTManager, starts a continuous scan, and destroys the manager when it unmounts.

Foreground setup​

import {
BTProvider,
IntegratedDevices,
createBackgroundBleManager,
} from "@ovok/native";

const bleManager = createBackgroundBleManager({
restoreStateIdentifier: "com.example.app.bluetooth",
});

const acceptedDevices = [
IntegratedDevices.BP2,
IntegratedDevices.F4,
] as const;

export function BluetoothScreen() {
return (
<BTProvider
bleManager={bleManager}
acceptedDevices={acceptedDevices}
onDeviceFound={async (device, manager) => {
console.log("found", device.deviceData);
// Call device.connect() here, or use manager options when constructing BTManager.
}}
onDeviceStatusChanged={({ deviceData, status }) => {
console.log(deviceData.name, status);
}}
onResult={({ deviceData, data }) => {
console.log("measurement", deviceData, data);
}}
onError={({ deviceData, error }) => {
console.error(deviceData?.name, error);
}}
>
{/* The scan-owned screen and device list */}
</BTProvider>
);
}

Use one long-lived manager per app flow. Creating a new BleManager during render breaks iOS restoration and creates competing scans.

Provider props​

PropMeaning
bleManagerThe host-owned BleManager instance
acceptedDevicesBuilt-in IntegratedDevices values and/or custom declarations
onDeviceFoundReceives the wrapped BTManagedDevice and its BTManager
onDeviceStatusChangedReceives Connected, Disconnected, Measuring, or LowBattery
onResultReceives deviceData plus the decoded measurement
onErrorReceives a device (when known) and the BLE/protocol error
oneReadingPerConnectionStops a device from delivering more than one result per connection
deliveredEcgFileNamesFile names already delivered by Viatom ECG devices
backgroundSyncEnables the durable background-result queue; see background sync
permissionFallbackReplaces the default permission/settings fallback UI
onAccessPermissionChangedReceives the BLE access state

The status enum is deliberately small. Do not build UI around invented states such as Pairing, Ready, Syncing, or Complete.

Device catalog versus accepted devices​

The root package exports:

import {
SUPPORTED_ACCEPTED_DEVICES,
SUPPORTED_DEVICES,
} from "@ovok/native";

SUPPORTED_DEVICES is the canonical joined catalog. Each definition includes an id, display metadata, image URL/data, exact image credit, measurement types, optional manual URL, and acceptedDevices ready for BTProvider. SUPPORTED_ACCEPTED_DEVICES is the de-duplicated accept-list when an app wants every catalog declaration.

For a smaller app, select entries by id or use the exact built-in value. Do not pass a catalog display object as acceptedDevices.

Discovery and connection lifecycle​

  1. BTProvider checks Bluetooth permission.
  2. The manager waits for Bluetooth to be powered on.
  3. The foreground scan uses balanced scanning and accepts matching advertisement names and service UUIDs.
  4. A matching peripheral becomes a BTManagedDevice.
  5. onDeviceFound can connect the device. The wrapper exposes connect() and deviceData.
  6. The device-specific protocol reads a live frame or stored file.
  7. onDeviceStatusChanged reports lifecycle changes and onResult reports decoded values.
  8. Unmounting the provider stops the scan, removes subscriptions, and destroys devices.

On iOS, advertisement data may expose the model through localName before name is available. The manager checks both. If a device still cannot be found, inspect the advertised name and service UUIDs before changing the protocol.

Standard profiles​

The SDK exposes declarations for standard Bluetooth profiles:

  • blood pressure;
  • heart rate;
  • pulse oximetry;
  • thermometer;
  • weight scale.

The standard profile factory accepts the advertised name supplied by the device. A standard profile is not a wildcard for every BLE peripheral; the device must advertise the expected service and produce a valid profile frame.

Custom devices​

Use defineCustomDevice and the custom field/frame/service types when the device is not a built-in declaration:

import {
defineCustomDevice,
CustomCaseKind,
CustomFieldEncoding,
} from "@ovok/native";

Custom declarations define an id, name matcher, main services, commands, frame cases, fields, units, and measurement type. Pass the returned declaration in the acceptedDevices tuple. Keep the id unique and stable; built-in names must not be reused.

Protocol helpers for the Lepu/Viatom family, Veroval, boso, Visomat, AOJ, and standard GATT devices are exported for apps that need to compose or test declarations. They are lower-level API than SUPPORTED_DEVICES and should be treated as protocol API.

Scan policy controls​

BTManager also exports BTManagerOptions, BTDeviceSelection, and public methods used by advanced integrations. The manager supports:

  • background low-power scanning with service UUID filtering;
  • one-reading-per-connection mode for streaming devices;
  • delivered ECG file names for de-duplication;
  • automatic connection after a settle window;
  • a selection callback when several devices are found;
  • setBackgroundScanEnabled for app-owned managers.

If the app drives BTManager itself, it owns the scan lifecycle. Do not mount a second BTProvider against the same manager.