Skip to main content

Types & Interfaces

Comprehensive TypeScript type definitions for the BT Management module, providing type safety and clear API contracts for medical device integration.

Overview​

The BT Management module uses a robust type system to ensure type safety across device communication, data parsing, and event handling. This document covers all TypeScript interfaces, enums, and type definitions used throughout the system.

Core Interfaces​

IBaseDevice​

Base interface that all medical devices must implement.

export interface IBaseDevice {
readonly deviceData: DeviceData;
readonly deviceModel: IMedicalDevice;
readonly deviceId: string;
readonly deviceName: IntegratedDevices;

// Connection method — connect() auto-subscribes to all characteristics
// internally via the private bt-connection-handler.subscribeToAllCharacteristics.
// Do NOT add a separate subscribe call to your public interface; the SDK
// handles it.
connect: () => Promise<void>;
}

Usage:

// All device implementations must extend IBaseDevice
class DeviceF4 extends BaseDevice implements IBaseDevice {
// Implementation
}

DeviceData​

Complete device information structure containing all device metadata.

export type DeviceData = {
model: IMedicalDevice;
name: IntegratedDevices;
localName: string;
manufacturerData: string;
sn: string;
id: string;
supportedMeasurementTypeKeys: MeasurementTypeKey[];
};

Example:

const deviceData: DeviceData = {
model: {
deviceName: IntegratedDevices.F4,
mainService: {
/* service config */
},
},
name: IntegratedDevices.F4,
localName: "F4",
manufacturerData: "0x1234",
sn: "F4-123456",
id: "ble-device-id-123",
supportedMeasurementTypeKeys: [MeasurementTypeKey.bodyWeight],
};

IMedicalDevice​

Device configuration interface defining BLE services and parsing models.

export interface IMedicalDevice {
deviceName: IntegratedDevices;
mainService: IService | IService[];
}

Single Service Example:

const glucoseMeter: IMedicalDevice = {
deviceName: IntegratedDevices.TAIDOC_GLUCOSE,
mainService: {
uuid: "00001523-1212-efde-1523-785feabcd123",
monitorUuids: [
/* monitoring characteristics */
],
writeUuid: {
uuid: "00001524-1212-efde-1523-785feabcd123",
mainCommandUuid: "512600000000A31A",
},
},
};

Multi-Service Example:

const multiSensorDevice: IMedicalDevice = {
deviceName: IntegratedDevices.COSINUSS,
mainService: [
{
uuid: "0000180d-0000-1000-8000-00805f9b34fb", // Heart Rate
monitorUuids: [
/* HR characteristics */
],
},
{
uuid: "00001822-0000-1000-8000-00805f9b34fb", // Pulse Oximeter
monitorUuids: [
/* SpO2 characteristics */
],
},
{
uuid: "00001809-0000-1000-8000-00805f9b34fb", // Temperature
monitorUuids: [
/* Temperature characteristics */
],
},
],
};

Service & Characteristic Types​

IService​

BLE service definition with monitoring and write characteristics.

export interface IService {
uuid: string;
monitorUuids: IMonitorCharacteristic[];
writeUuid?: IWriteCharacteristic;
}

IMonitorCharacteristic​

Characteristic configuration for data monitoring and parsing.

export interface IMonitorCharacteristic {
uuid: string;
parsingModel: ParsingModel;
}

IWriteCharacteristic​

Characteristic configuration for sending commands to devices.

export interface IWriteCharacteristic {
uuid: string;
mainCommandUuid: string;
}

Example:

const writeCharacteristic: IWriteCharacteristic = {
uuid: "8b00ace7-eb0b-49b0-bbe9-9aee0a26e1a3",
mainCommandUuid: "a508f700000000ee", // Command to start measurement
};

Data Parsing Types​

ParsingModel​

Model for parsing BLE characteristic data into measurements.

export interface ParsingModel {
caseValuePosition?: number[];
cases: ParsingCase[];
messageCountParsingDefinition?: (msg: string[]) => number;
}

Example:

const bloodPressureParsingModel: ParsingModel = {
caseValuePosition: [0, 1, 7], // Bytes that determine message type
messageCountParsingDefinition: (msg: string[]): number =>
parseInt((msg?.[6] ?? "0") + (msg?.[5] ?? "0"), 16) + 8,
cases: [
{
returnType: MeasurementTypeKey.bloodPressure,
caseType: CaseType.RESULT,
caseValue: "a50805",
parseDefinitions: [
/* parsing rules */
],
},
],
};

ParsingCase​

Individual case definition for different message types.

export interface ParsingCase {
returnType?: MeasurementTypeKey;
caseType: CaseType;
parseDefinitions: ParserDefinition[];
caseValue: string;
description?: string;
}

Types of Cases:

// Result case - final measurement
const resultCase: ParsingCase = {
returnType: MeasurementTypeKey.bloodPressure,
caseType: CaseType.RESULT,
caseValue: "a50805",
parseDefinitions: [
{
name: "systolic",
parseType: "number",
byteIndexes: [21, 20],
parseReference: 16,
},
],
};

// Stream case - real-time data
const streamCase: ParsingCase = {
returnType: MeasurementTypeKey.bloodPressure,
caseType: CaseType.STREAM,
caseValue: "a50804",
parseDefinitions: [],
};

// Other case - status/control
const otherCase: ParsingCase = {
caseType: CaseType.OTHER,
caseValue: "a50803",
parseDefinitions: [],
description: "User on home screen",
};

ParserDefinition​

Definition for extracting and converting individual data fields.

export interface ParserDefinition {
name: string;
parseType: string;
byteIndexes: number[];
parseReference?: number;
bitParseDefinition?: ParserDefinition[];
customParserDefinition?: (data: any) => any;
}

Parse Types:

// Number parsing
const numberField: ParserDefinition = {
name: "systolic",
parseType: "number",
byteIndexes: [21, 20],
parseReference: 16, // Hexadecimal
};

// String parsing
const stringField: ParserDefinition = {
name: "deviceId",
parseType: "string",
byteIndexes: [5, 6, 7],
parseReference: 16,
};

// Boolean parsing
const booleanField: ParserDefinition = {
name: "isConnected",
parseType: "boolean",
byteIndexes: [8],
parseReference: 16,
};

// Custom parsing
const customField: ParserDefinition = {
name: "bodyWeight",
parseType: "custom",
byteIndexes: [5, 6, 7, 8],
customParserDefinition: (a: string): number => parseInt(a, 16) / 100,
};

// Date parsing
const dateField: ParserDefinition = {
name: "timestamp",
parseType: "date",
byteIndexes: [10, 11],
parseReference: 16,
};

Enums​

IntegratedDevices​

Enumeration of all supported medical device types.

export enum IntegratedDevices {
// Scales
F4 = "F4",
FORA_SCALE = "FORA W550",
RPM_SCALE = "GBS-2012-B",
S5 = "Le S5",

// Blood Pressure Monitors
BP2 = "BP2",

// Pulse Oximeters
SPO2 = "Oxyfit",
PC60WF = "OxySmart",
COSINUSS = "two",
CMED = "cmed",

// Thermometers
AOJ20A = "AOJ-20A",
ANDESFITTEMP = "TEMP",
FORATEMP = "FORA IR20",
CLEVERTEMP = "TAIDOC TD1107",

// Glucose Meters
TAIDOC_GLUCOSE = "TAIDOC TD4216",
GLUCOCHECK = "GlucoCheck",
BGM = "BGM",

// Urinalysis
BC01 = "BC01",

// Spirometers
SP80B = "PULMO80B",

// Other
ALIVE_COR = "alivecor",
}

DeviceStatus​

Device connection and operation status enumeration.

Note: The DeviceStatus enum has exactly 4 values: Connected, Disconnected, Measuring, and LowBattery. No other status values exist in the SDK.

export enum DeviceStatus {
CONNECTED = "Connected",
DISCONNECTED = "Disconnected",
MEASURING = "Measuring",
LOW_BATTERY = "LowBattery",
}

Usage in Event Handling:

const handleDeviceStatus = (status: DeviceStatus, device: DeviceData) => {
switch (status) {
case DeviceStatus.CONNECTED:
console.log(`${device.name} is ready for measurements`);
break;
case DeviceStatus.MEASURING:
console.log(`${device.name} is taking a measurement`);
break;
case DeviceStatus.DISCONNECTED:
console.log(`${device.name} has disconnected`);
break;
case DeviceStatus.LOW_BATTERY:
console.log(`${device.name} battery is low`);
break;
}
};

CaseType​

Message type classification for data parsing.

export enum CaseType {
RESULT = "result", // Final measurement data
STREAM = "stream", // Real-time data stream
OTHER = "other", // Status/control messages
SN = "sn", // Serial number data
ERROR = "error", // Error conditions
}

BleCustomEvents​

Event types for device communication.

export enum BleCustomEvents {
ON_DEVICE_STATUS = "onDeviceStatus",
ON_MEASUREMENT = "onMeasurement",
ON_START_SCAN = "onStartScan",
ON_DEVICE_ERROR = "onDeviceError",
ON_COSINUSS_DEVICE_PARAMS = "onCosinussDevice",
}

Event & Communication Types​

BTProviderProps​

Props interface for the BTProvider component. The provider exposes exactly five user-facing callbacks plus permissionFallback, and is generic over the tuple of accepted devices.

export interface BTProviderChildWrapperProps<T extends readonly IntegratedDevices[]> {
bleManager: BleManager;
acceptedDevices: T;
onDeviceFound?: (
device: BTManagedDevice<T[number]>,
manager: BTManager<T>,
) => Promise<void>;
onError?: (data: ErrorCallback) => void;
onDeviceStatusChanged?: (data: DeviceStatusChangeCallback) => void;
onResult?: (data: ResultCallback<T[number]>) => void;
}

export interface BTProviderProps<T> extends BTProviderChildWrapperProps<T> {
onAccessPermissionChanged?: (accessPermission: boolean) => void;
permissionFallback?: () => React.ReactNode;
}

Callback contract:

  • onDeviceFound(device, manager) — invoked when a matching device is discovered. Call await device.connect() to establish the connection; connect() auto-subscribes to all relevant characteristics internally. Do not call device.subscribeToAllCharacteristics() directly — it is a private method on the connection handler.
  • onError({ error, deviceData? }) — invoked on scan or device errors, with the underlying error and optional device context.
  • onResult({ deviceData, data }) — invoked when a final measurement is produced.
  • onDeviceStatusChanged({ deviceData, status, measurementTypeKey? }) — invoked when a connected device transitions to one of the four DeviceStatus states.
  • onAccessPermissionChanged(granted) — invoked when Bluetooth / location permission state changes.

DeviceStatusInfo​

Event data structure for device status changes.

export interface DeviceStatusInfo {
status: DeviceStatus;
device: DeviceData;
measurementTypeKey?: MeasurementTypeKey;
}

MeasurementInfo​

Event data structure for measurement updates.

export interface MeasurementInfo {
measurement: Measurement;
device: DeviceData;
}

Queue Management Types​

IDeviceQueueManager​

Interface for managing device connection queues.

export interface IDeviceQueueManager {
subscribeToTimer: (
onTimerWorks: (device: IBaseDevice) => Promise<void>,
) => EmitterSubscription;

addTimerForDevice: (device: IBaseDevice) => void;
removeAllTimersForDevice: (deviceName: IntegratedDevices) => void;
}

ScanEvents​

Scanning event enumeration for internal event handling.

export enum ScanEvents {
ON_START_SCAN = "ON_START_SCAN",
ON_DEVICE_FOUND_INTERNAL = "ON_DEVICE_FOUND_INTERNAL",
ON_ERROR_INTERNAL = "ON_ERROR_INTERNAL",
ON_DEVICE_FOUND_EXTERNAL = "ON_DEVICE_FOUND_EXTERNAL",
ON_ERROR_EXTERNAL = "ON_ERROR_EXTERNAL",
}

ScanDeviceQueueEvents​

Queue management event enumeration.

export enum ScanDeviceQueueEvents {
ON_DEVICE_TIMEOUT = "ON_DEVICE_TIMEOUT",
}

Diagnostic & Error Types​

BloodPressureStates​

Blood pressure measurement status enumeration.

export enum BloodPressureStates {
REGULAR = "Regular",
LOOSE_SLEEVE = "The sleeve is loose. Unable to analyze.",
DISTURB_DETECTED = "Disturb Detected.",
WEAK_SIGNAL = "Weak Signal.",
DEVICE_ERROR = "Unknown device error.",
}

DiagnosticKeyEnum​

Urinalysis parameter enumeration.

export enum DiagnosticKeyEnum {
URO = "URO", // Urobilinogen
BLD_PRO_LEU_VC = "BLD_PRO_LEU_VC", // Blood/Protein/Leukocytes/Vitamin C
BIL_KET = "BIL_KET", // Bilirubin/Ketones
GLU = "GLU", // Glucose
NIT = "NIT", // Nitrites
PH = "PH", // pH
SG = "SG", // Specific Gravity
}

DiagnosticKeys​

Type alias for diagnostic result keys.

export type DiagnosticKeys = keyof typeof diagnosticResults;

// Usage with diagnostic results
const diagnosticResults = {
URO: ["Norm", "1+", "2+", "3+"],
BLD_PRO_LEU_VC: ["-", "+-", "1+", "2+", "3+"],
BIL_KET: ["-", "1+", "2+", "3+"],
GLU: ["-", "+-", "1+", "2+", "3+", "4+"],
NIT: ["-", "+"],
PH: ["5", "6", "7", "8", "9"],
SG: ["1.005", "1.010", "1.015", "1.020", "1.025", "1.030"],
};

Type Guards & Utilities​

Type Guards​

Type guard functions for runtime type checking.

// Device type guard
export function isValidDevice(device: any): device is IBaseDevice {
return (
device &&
typeof device.deviceId === "string" &&
typeof device.deviceName === "string" &&
typeof device.connect === "function"
);
}

// Measurement type guard
export function isBloodPressureMeasurement(
measurement: Measurement,
): measurement is BloodPressureMeasurement {
return measurement.measurementTypeKey === MeasurementTypeKey.bloodPressure;
}

// Device data validation
export function isValidDeviceData(data: any): data is DeviceData {
return (
data &&
typeof data.id === "string" &&
typeof data.name === "string" &&
Array.isArray(data.supportedMeasurementTypeKeys)
);
}

Utility Types​

Helpful utility types for working with the BT Management system.

// Extract device names from IntegratedDevices enum
export type DeviceName = keyof typeof IntegratedDevices;

// Create a union type of all measurement types
export type AnyMeasurement =
| BloodPressureMeasurement
| BodyWeightMeasurement
| BodyTemperatureMeasurement
| BloodGlucoseMeasurement
| PulseOximeterMeasurement
| EcgMeasurement
| SpirometryMeasurement
| UrineAnalyzeMeasurement;

// Device configuration partial type for testing
export type PartialDeviceConfig = Partial<IMedicalDevice> & {
deviceName: IntegratedDevices;
};

// Event callback types
export type DeviceFoundCallback = (
device: IBaseDevice,
scanInstance: ScanManagerImplementation,
) => void;
export type MeasurementCallback = (
measurement: Measurement,
device: DeviceData,
) => void;
export type DeviceStatusCallback = (
status: DeviceStatus,
device: DeviceData,
measurementType?: MeasurementTypeKey,
) => void;
export type DeviceErrorCallback = (error: string, device: DeviceData) => void;

Generic Types​

Generic Device Interface​

Generic interface for type-safe device implementations.

export interface ITypedDevice<TMeasurement extends Measurement>
extends IBaseDevice {
readonly supportedMeasurementType: MeasurementTypeKey;

// Type-safe measurement processing
processMeasurement(data: TMeasurement): void;
validateMeasurement(data: TMeasurement): string | undefined;
}

// Usage example
export class TypedDeviceF4 implements ITypedDevice<BodyWeightMeasurement> {
readonly supportedMeasurementType = MeasurementTypeKey.bodyWeight;

processMeasurement(data: BodyWeightMeasurement): void {
// Type-safe access to bodyWeight property
console.log(`Weight: ${data.bodyWeight} kg`);
}

validateMeasurement(data: BodyWeightMeasurement): string | undefined {
if (data.bodyWeight <= 0) {
return "Invalid weight measurement";
}
return undefined;
}
}

Generic Parser Type​

Generic type for custom parser functions.

export type CustomParser<TInput, TOutput> = (input: TInput) => TOutput;

// Specific parser implementations
export type HexToNumberParser = CustomParser<string, number>;
export type HexToStringParser = CustomParser<string, string>;
export type HexToBooleanParser = CustomParser<string, boolean>;

// Parser definition with generic typing
export interface TypedParserDefinition<TOutput> {
name: string;
parseType: "custom";
byteIndexes: number[];
customParserDefinition: CustomParser<string, TOutput>;
}

// Usage
const weightParser: TypedParserDefinition<number> = {
name: "bodyWeight",
parseType: "custom",
byteIndexes: [5, 6, 7, 8],
customParserDefinition: (hex: string): number => parseInt(hex, 16) / 100,
};

Type Examples​

Complete Device Implementation Type​

// Full type definition for a device implementation
interface CompleteDeviceImplementation {
// Device identification
deviceInfo: DeviceData;
deviceConfig: IMedicalDevice;

// Connection management
connectionState: DeviceStatus;
connectionPromise: Promise<void> | null;

// Data processing
messageCollector: MessageCollector;
parsingModel: ParsingModel;
lastMeasurement: Measurement | null;

// Event handling
statusCallbacks: DeviceStatusCallback[];
measurementCallbacks: MeasurementCallback[];
errorCallbacks: DeviceErrorCallback[];

// Lifecycle methods
initialize(): Promise<void>;
connect(): Promise<void>;
disconnect(): Promise<void>;
cleanup(): void;

// Data methods
processIncomingData(data: string[]): void;
validateMeasurement(measurement: Measurement): boolean;
handleError(error: string): void;
}

Event System Types​

// Event emitter types for type-safe event handling
interface TypedEventEmitter {
on<T extends keyof BleEventMap>(event: T, listener: BleEventMap[T]): void;
emit<T extends keyof BleEventMap>(
event: T,
...args: Parameters<BleEventMap[T]>
): void;
removeListener<T extends keyof BleEventMap>(
event: T,
listener: BleEventMap[T],
): void;
}

// Event map for type safety
interface BleEventMap {
[BleCustomEvents.ON_DEVICE_STATUS]: (info: DeviceStatusInfo) => void;
[BleCustomEvents.ON_MEASUREMENT]: (info: MeasurementInfo) => void;
[BleCustomEvents.ON_DEVICE_ERROR]: (
error: string,
device: DeviceData,
) => void;
}

Testing Types​

Mock Types​

Types for testing and mocking.

// Mock device for testing
export interface MockDevice extends IBaseDevice {
simulateConnection(): Promise<void>;
simulateDisconnection(): void;
simulateMeasurement(measurement: Measurement): void;
simulateError(error: string): void;
getConnectionHistory(): string[];
}

// Test fixture types
export interface DeviceTestFixture {
device: MockDevice;
expectedMeasurements: Measurement[];
simulatedMessages: string[][];
expectedErrors: string[];
}

// Test configuration
export interface TestConfiguration {
deviceType: IntegratedDevices;
testData: DeviceTestFixture;
timeout: number;
retryCount: number;
}

Type Safety Best Practices​

Strict Typing​

// Always use strict typing for device operations
interface StrictDeviceOperations {
// Use specific enums instead of strings
status: DeviceStatus; // Good
// status: string; // Avoid

// Use specific measurement types
measurement: BloodPressureMeasurement; // Good
// measurement: any; // Avoid

// Use type guards for runtime checks
validateDevice(device: unknown): device is IBaseDevice;

// Use generics for reusable code
processTypedMeasurement<T extends Measurement>(measurement: T): T;
}

Error Handling Types​

// Structured error types
export interface BleError {
code: number;
message: string;
deviceId?: string;
context?: Record<string, any>;
}

export interface DeviceError extends BleError {
deviceName: IntegratedDevices;
measurementContext?: MeasurementTypeKey;
}

// Result types for operations that can fail
export type DeviceOperationResult<T> =
| { success: true; data: T }
| { success: false; error: DeviceError };

// Usage
async function connectDevice(
device: IBaseDevice,
): Promise<DeviceOperationResult<DeviceData>> {
try {
await device.connect();
return { success: true, data: device.deviceData };
} catch (error) {
return {
success: false,
error: {
code: 1001,
message: "Connection failed",
deviceName: device.deviceName,
deviceId: device.deviceId,
},
};
}
}

Dependencies​

The types depend on these external libraries:

// External dependencies
import {
Measurement,
MeasurementTypeKey,
BloodPressureMeasurement,
} from "@ovok/core";
import { BleManager, Device, BleError } from "react-native-ble-plx";
import { EmitterSubscription } from "react-native";
import { EffectCallback } from "react";