npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ihealth/ihealthlibrary-react-native

v2.0.0

Published

iHealth React Native SDK - supports React Native New Architecture (TurboModules) and Old Architecture

Readme

iHealth React Native SDK

npm version

Official React Native SDK for iHealth Bluetooth health devices.

v2.0.0 fully supports React Native New Architecture (TurboModules) while remaining backward compatible with the Old Architecture (Bridge mode).


Table of Contents


Requirements

| Platform | Minimum Version | |----------|----------------| | React Native | >= 0.76.0 | | iOS | 12.0+ | | Android | API 24+ (Android 7.0+) |


Installation

npm install @ihealth/ihealthlibrary-react-native
# or
yarn add @ihealth/ihealthlibrary-react-native

iOS Setup

1. Install Pods

cd ios && pod install

2. Add Permissions (Info.plist)

<key>NSBluetoothAlwaysUsageDescription</key>
<string>Required to connect to iHealth devices</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>Required to connect to iHealth devices</string>

3. Enable New Architecture (optional, recommended for RN 0.76+)

Edit ios/Podfile.properties.json:

{
  "newArchEnabled": "true"
}

Then run pod install again.


Android Setup

1. Add Permissions (AndroidManifest.xml)

<!-- Bluetooth (Android 11 and below) -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- Bluetooth (Android 12+) -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

2. Request Runtime Permissions

import { PermissionsAndroid, Platform } from 'react-native';

async function requestBluetoothPermissions() {
  if (Platform.OS !== 'android') return true;

  const permissions = Platform.Version >= 31
    ? [
        PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
        PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      ]
    : [
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      ];

  const result = await PermissionsAndroid.requestMultiple(permissions);
  return Object.values(result).every(
    v => v === PermissionsAndroid.RESULTS.GRANTED
  );
}

3. SDK License Authentication (Android only)

Place the .pem license file provided by iHealth into android/app/src/main/assets/, then call the following once on app startup:

import { iHealthDeviceManagerModule } from '@ihealth/ihealthlibrary-react-native';

iHealthDeviceManagerModule.sdkAuthWithLicense('your_license_file.pem');

iOS does not require license authentication.

4. Enable New Architecture (optional, recommended for RN 0.76+)

Edit android/gradle.properties:

newArchEnabled=true

Quick Start

The example below shows a complete flow — scan → connect → measure — using the BP5S blood pressure monitor:

import React, { useEffect, useState } from 'react';
import { View, Button, Text, NativeEventEmitter, NativeModules } from 'react-native';
import {
  iHealthDeviceManagerModule,
  BP5SModule,
} from '@ihealth/ihealthlibrary-react-native';

export default function BP5SScreen() {
  const [devices, setDevices]   = useState([]);
  const [connectedMac, setMac]  = useState(null);
  const [result, setResult]     = useState('');

  // Step 1 — Listen for scan and connection events
  useEffect(() => {
    const managerEmitter = new NativeEventEmitter(
      NativeModules.iHealthDeviceManagerModule
    );

    const onScan = managerEmitter.addListener(
      iHealthDeviceManagerModule.Event_Scan_Device,
      (e) => setDevices(prev => [...prev, e])
    );
    const onConnected = managerEmitter.addListener(
      iHealthDeviceManagerModule.Event_Device_Connected,
      (e) => setMac(e.mac)
    );
    const onDisconnect = managerEmitter.addListener(
      iHealthDeviceManagerModule.Event_Device_Disconnect,
      () => setMac(null)
    );

    return () => {
      onScan.remove();
      onConnected.remove();
      onDisconnect.remove();
    };
  }, []);

  // Step 2 — Listen for device data events
  useEffect(() => {
    const bp5sEmitter = new NativeEventEmitter(NativeModules.BP5SModule);

    const onData = bp5sEmitter.addListener(
      BP5SModule.Event_Notify,
      (e) => setResult(JSON.stringify(e))
    );

    return () => onData.remove();
  }, []);

  return (
    <View>
      <Button
        title="Scan"
        onPress={() => {
          setDevices([]);
          iHealthDeviceManagerModule.startDiscovery(
            iHealthDeviceManagerModule.BP5S
          );
        }}
      />
      {devices.map(d => (
        <Button
          key={d.mac}
          title={`Connect ${d.mac}`}
          onPress={() =>
            iHealthDeviceManagerModule.connectDevice(
              d.mac,
              iHealthDeviceManagerModule.BP5S
            )
          }
        />
      ))}
      {connectedMac && (
        <Button
          title="Start Measure"
          onPress={() => BP5SModule.startMeasure(connectedMac)}
        />
      )}
      <Text>{result}</Text>
    </View>
  );
}

Event Listening — Important

⚠️ Breaking change in v2.0.0: You must use NativeEventEmitter instead of DeviceEventEmitter.

Correct Usage

import { NativeEventEmitter, NativeModules } from 'react-native';
import { BP5SModule } from '@ihealth/ihealthlibrary-react-native';

useEffect(() => {
  // Pass the corresponding NativeModules instance for your device
  const emitter = new NativeEventEmitter(NativeModules.BP5SModule);

  const listener = emitter.addListener(BP5SModule.Event_Notify, (event) => {
    console.log(event);
  });

  return () => listener.remove(); // Always clean up on unmount
}, []);

Incorrect Usage (events will be lost)

// ❌ Do NOT use DeviceEventEmitter
import { DeviceEventEmitter } from 'react-native';
DeviceEventEmitter.addListener(BP5SModule.Event_Notify, handler);

// ❌ Do NOT create the emitter at module top-level (outside useEffect)
const emitter = new NativeEventEmitter(NativeModules.BP5SModule); // top-level — wrong

NativeModules Name Reference

| SDK Import Name | NativeModules Key | |----------------|-------------------| | iHealthDeviceManagerModule | NativeModules.iHealthDeviceManagerModule | | BP5Module | NativeModules.BP5Module | | BP5SModule | NativeModules.BP5SModule | | BP550BTModule | NativeModules.BP550BTModule | | BP3LModule | NativeModules.BP3LModule | | BP7Module | NativeModules.BP7Module | | BP7SModule | NativeModules.BP7SModule | | PO3Module | NativeModules.PO3Module | | PO1Module | NativeModules.PO1Module | | HS2SModule | NativeModules.HS2SModule | | HS2SProModule | NativeModules.HS2SProModule | | HS4SModule | NativeModules.HS4SModule | | HS6Module | NativeModules.HS6Module | | BG5SModule | NativeModules.BG5SModule | | BG5Module | NativeModules.BG5Module | | BG1Module | NativeModules.BG1Module | | BG1AModule | NativeModules.BG1AModule | | BG1SModule | NativeModules.BG1SModule | | AM3SModule | NativeModules.AM3SModule | | AM4Module | NativeModules.AM4Module | | AM5Module | NativeModules.AM5Module | | AM6Module | NativeModules.AM6Module | | BTMModule | NativeModules.BTMModule | | TS28BModule | NativeModules.TS28BModule | | NT13BModule | NativeModules.NT13BModule | | PT3SBTModule | NativeModules.PT3SBTModule | | ECGModule (iOS only) | NativeModules.ECGModule | | ECGUSBModule (iOS only) | NativeModules.ECGUSBModule |


Device Management

Scan for Devices

import { iHealthDeviceManagerModule } from '@ihealth/ihealthlibrary-react-native';

// Start scanning — pass the device type constant
iHealthDeviceManagerModule.startDiscovery(iHealthDeviceManagerModule.BP5S);

// Stop scanning
iHealthDeviceManagerModule.stopDiscovery();

Device type constants:

| Constant | Value | Device | |----------|-------|--------| | iHealthDeviceManagerModule.BP5 | 'BP5' | BP5 Blood Pressure Monitor | | iHealthDeviceManagerModule.BP5S | 'BP5S' | BP5S Blood Pressure Monitor | | iHealthDeviceManagerModule.BP7 | 'BP7' | BP7 Blood Pressure Monitor | | iHealthDeviceManagerModule.BP7S | 'BP7S' | BP7S Blood Pressure Monitor | | iHealthDeviceManagerModule.BP3L | 'BP3L' | BP3L Blood Pressure Monitor | | iHealthDeviceManagerModule.KN550 | 'KN550' | KN-550BT Blood Pressure Monitor | | iHealthDeviceManagerModule.PO3 | 'PO3' | PO3 Pulse Oximeter | | iHealthDeviceManagerModule.PO1 | 'PO1' | PO1 Pulse Oximeter | | iHealthDeviceManagerModule.HS2S | 'HS2S' | HS2S Body Scale | | iHealthDeviceManagerModule.AM6 | 'AM6' | AM6 Activity Tracker | | iHealthDeviceManagerModule.BG5S | 'BG5S' | BG5S Blood Glucose Meter | | iHealthDeviceManagerModule.BG1A | 'BG1A' | BG1A Blood Glucose Meter | | iHealthDeviceManagerModule.BG1S | 'BG1S' | BG1S Blood Glucose Meter | | iHealthDeviceManagerModule.BTM | 'FDIR_V3' | BTM Thermometer | | iHealthDeviceManagerModule.NT13B | 'NT13B' | NT13B Thermometer | | iHealthDeviceManagerModule.TS28B | 'TS28B' | TS28B Thermometer | | iHealthDeviceManagerModule.PT3SBT | 'PT3SBT' | PT3SBT Thermometer | | iHealthDeviceManagerModule.AM3S | 'AM3S' | AM3S Activity Monitor | | iHealthDeviceManagerModule.AM4 | 'AM4' | AM4 Activity Monitor | | iHealthDeviceManagerModule.AM5 | 'AM5' | AM5 Activity Monitor | | iHealthDeviceManagerModule.ECG3 | 'ECG3' | ECG3 (iOS only) | | iHealthDeviceManagerModule.ECG3USB | 'ECG3USB' | ECG3USB (iOS only) |

Connect / Disconnect

// Connect — mac comes from the scan event (event.mac)
iHealthDeviceManagerModule.connectDevice(mac, iHealthDeviceManagerModule.BP5S);

// Disconnect
iHealthDeviceManagerModule.disconnectDevice(mac, iHealthDeviceManagerModule.BP5S);

Device Manager Events

const managerEmitter = new NativeEventEmitter(
  NativeModules.iHealthDeviceManagerModule
);

// Device discovered during scan
// Payload: { mac: string, type: string, rssi?: number }
managerEmitter.addListener(
  iHealthDeviceManagerModule.Event_Scan_Device, handler
);

// Scan finished
managerEmitter.addListener(
  iHealthDeviceManagerModule.Event_Scan_Finish, handler
);

// Device connected successfully
// Payload: { mac: string, type: string }
managerEmitter.addListener(
  iHealthDeviceManagerModule.Event_Device_Connected, handler
);

// Device connection failed
// Payload: { mac: string, type: string }
managerEmitter.addListener(
  iHealthDeviceManagerModule.Event_Device_Connect_Failed, handler
);

// Device disconnected
// Payload: { mac: string, type: string }
managerEmitter.addListener(
  iHealthDeviceManagerModule.Event_Device_Disconnect, handler
);

// SDK license authentication result (Android only)
// Payload: { authen: boolean }
managerEmitter.addListener(
  iHealthDeviceManagerModule.Event_Authenticate_Result, handler
);

Device API Reference

Blood Pressure Monitor — BP5 / BP5S / BP3L / BP7

import { BP5SModule, BPProfileModule } from '@ihealth/ihealthlibrary-react-native';
import { NativeEventEmitter, NativeModules } from 'react-native';

const emitter = new NativeEventEmitter(NativeModules.BP5SModule);

emitter.addListener(BP5SModule.Event_Notify, (event) => {
  switch (event.action) {
    case BPProfileModule.ACTION_ONLINE_REAL_TIME_MEASUREMENT:
      // Real-time data: event.sys, event.dia, event.heartRate, event.pulse
      break;
    case BPProfileModule.ACTION_ONLINE_RESULT:
      // Final measurement result
      break;
    case BPProfileModule.ACTION_BATTERY_BP:
      // Battery level: event.battery (0–100)
      break;
    case BPProfileModule.ACTION_ERROR_BP:
      // Error: event.error
      break;
  }
});

// Measurement
BP5SModule.startMeasure(mac);
BP5SModule.stopMeasure(mac);

// Offline data
BP5SModule.enbleOffline(mac, 1);     // Enable offline mode
BP5SModule.enbleOffline(mac, 0);     // Disable offline mode
BP5SModule.getOffLineNum(mac);       // Get number of offline records
BP5SModule.getOffLineData(mac);      // Download offline data
BP5SModule.deleteData(mac);          // Delete downloaded offline data

// Device info
BP5SModule.getBattery(mac);
BP5SModule.getFunctionInfo(mac);
BP5SModule.getHardwareVersion(mac);

BP5SModule.disconnect(mac);

Blood Pressure Monitor — KN-550BT (BP550BTModule)

import { BP550BTModule } from '@ihealth/ihealthlibrary-react-native';

const emitter = new NativeEventEmitter(NativeModules.BP550BTModule);
emitter.addListener(BP550BTModule.Event_Notify, (event) => {
  console.log(event);
});

BP550BTModule.getBattery(mac);
BP550BTModule.getFirmVersion(mac);
BP550BTModule.getFunctionInfo(mac);
BP550BTModule.getOffLineNum(mac);
BP550BTModule.getOffLineData(mac);
BP550BTModule.getTime(mac);
BP550BTModule.getDisplayConfig(mac);
BP550BTModule.setDisplayConfig(mac, showSystolic, showDiastolic);
BP550BTModule.transferFinished(mac);
BP550BTModule.disconnect(mac);

Pulse Oximeter — PO3 / PO1

import { PO3Module } from '@ihealth/ihealthlibrary-react-native';

const emitter = new NativeEventEmitter(NativeModules.PO3Module);
emitter.addListener(PO3Module.Event_Notify, (event) => {
  // event: { action, spo2, pr, pi, waveformData, ... }
  console.log(event);
});

PO3Module.startMeasure(mac);      // Start real-time measurement
PO3Module.getBattery(mac);
PO3Module.getHistoryData(mac);    // Download history records
PO3Module.disconnect(mac);

Body Scale — HS2S / HS2S Pro

import { HS2SModule } from '@ihealth/ihealthlibrary-react-native';

const emitter = new NativeEventEmitter(NativeModules.HS2SModule);
emitter.addListener(HS2SModule.Event_Notify, (event) => {
  console.log(event);
});

// Unit: 1 = kg, 2 = jin (Chinese unit), 3 = lb
HS2SModule.setUnit(mac, 1);

// User management — userID must be a 16-character string
const userID = '1234567890123456';
HS2SModule.updateUserInfo(
  mac, userID, createTimestamp,
  weight,       // kg
  age,          // years
  height,       // cm
  sex,          // 0 = female, 1 = male
  impedanceMark,
  fitnessMark
);
HS2SModule.getUserInfo(mac);
HS2SModule.deleteUser(mac, userID);

// Measurement (userType: 1 = registered user, 0 = guest)
HS2SModule.measure(
  mac, 1, userID, createTimestamp,
  weight, age, height, sex, impedanceMark, fitnessMark
);

// History data
HS2SModule.getMemoryDataCount(mac, userID);
HS2SModule.getMemoryData(mac, userID);
HS2SModule.deleteMemoryData(mac, userID);
HS2SModule.getAnonymousMemoryDataCount(mac);
HS2SModule.getAnonymousMemoryData(mac);
HS2SModule.deleteAnonymousMemoryData(mac);

// Heart rate measurement mode (HS2S Pro)
HS2SProModule.enterHS2SProHeartRateMeasurementMode(mac);
HS2SProModule.exitHS2SProHeartRateMeasurementMode(mac);

HS2SModule.disconnect(mac);

Blood Glucose Meter — BG5S

import { BG5SModule } from '@ihealth/ihealthlibrary-react-native';

const emitter = new NativeEventEmitter(NativeModules.BG5SModule);
emitter.addListener(BG5SModule.Event_Notify, (event) => {
  console.log(event);
});

BG5SModule.getStatusInfo(mac);

// Sync time: date string + timezone offset (hours)
BG5SModule.setTime(mac, '2025-01-01 12:00:00', 8);

// Unit: 1 = mmol/L, 2 = mg/dL
BG5SModule.setUnit(mac, 1);

// Start measurement: testType 1 = blood, 2 = urine
BG5SModule.startMeasure(mac, 1);

// Offline data
BG5SModule.setOfflineModel(mac, true);
BG5SModule.getOfflineData(mac);
BG5SModule.deleteOfflineData(mac);
BG5SModule.deleteUsedStrip(mac);

// Note: both spellings are accepted
BG5SModule.disconnect(mac);   // recommended
BG5SModule.disConnect(mac);   // also valid

Blood Glucose Meter — BG1A

import { BG1AModule } from '@ihealth/ihealthlibrary-react-native';

const emitter = new NativeEventEmitter(NativeModules.BG1AModule);
emitter.addListener(BG1AModule.Event_Notify, (event) => {
  console.log(event);
});

BG1AModule.getDeviceInfo(mac);
BG1AModule.setMeasureMode(mac, 1);   // 1 = blood, 2 = urine
BG1AModule.setDeviceTime(mac);       // Sync phone time to device
BG1AModule.getHistoryData(mac);
BG1AModule.deleteHistoryData(mac);
BG1AModule.disconnect(mac);

Blood Glucose Meter — BG1S

import { BG1SModule } from '@ihealth/ihealthlibrary-react-native';

const emitter = new NativeEventEmitter(NativeModules.BG1SModule);
emitter.addListener(BG1SModule.Event_Notify, (event) => {
  console.log(event);
});

BG1SModule.getFunction(mac);         // Get device function info
BG1SModule.measure(mac, testType);   // testType: 1 = blood
BG1SModule.disconnect(mac);

Activity Tracker — AM6

import { AM6Module } from '@ihealth/ihealthlibrary-react-native';

const emitter = new NativeEventEmitter(NativeModules.AM6Module);
emitter.addListener(AM6Module.Event_Notify, (event) => {
  console.log(event);
});

// Initialization
AM6Module.getDeviceInfoAndSyncTime(mac, true);
AM6Module.setUserInfo(mac, userID, gender, age, height, weight);
AM6Module.setPhonePlatform(mac);

// Sync health data
AM6Module.readySyncData(mac);
AM6Module.getDailyData(mac);
AM6Module.getStepData(mac);
AM6Module.getSleepData(mac);
AM6Module.getHeartRateData(mac);
AM6Module.getBloodOxygenData(mac);
AM6Module.getActivityData(mac);
AM6Module.deleteData(mac, dataType);

// Reminders
AM6Module.setTargetRemind(mac, enable, stepTarget, calorieTarget);
AM6Module.setTargetRemind(mac, true, 8000, 300);   // example
AM6Module.getTargetRemind(mac);
AM6Module.setSedentaryRemind(mac, enable, startTime, endTime);
AM6Module.setRaiseToLightRemind(mac, enable, startTime, endTime);
AM6Module.setDoNotDisturbMode(mac, enable, startTime, endTime);

// Alarm clock — format: "repeat:days:time;..." e.g. "1:1-1-1-1-1-1-1:480"
AM6Module.setAlarmClockList(mac, alarmString);
AM6Module.getAlarmClockList(mac);

// Display & wear settings
AM6Module.setWearHand(mac, 1);     // 0 = left, 1 = right
AM6Module.getWearHand(mac);

// Notifications
AM6Module.notifyMessage(mac, timestamp, enable, type, title, content);

// Bind / unbind user
AM6Module.startBind(mac);
AM6Module.bindUserSuccess(mac, userID);
AM6Module.bindUserFail(mac);
AM6Module.unBindUser(mac, userID);

AM6Module.findDevice(mac, 1);   // Vibrate to locate the device
AM6Module.rebootDevice(mac);
AM6Module.disconnect(mac);

Thermometer — BTM / NT13B / TS28B / PT3SBT

import { BTMModule } from '@ihealth/ihealthlibrary-react-native';

const emitter = new NativeEventEmitter(NativeModules.BTMModule);
emitter.addListener(BTMModule.Event_Notify, (event) => {
  // event: { action, temperature, unit, ... }
  console.log(event);
});

BTMModule.getBattery(mac);
BTMModule.startMeasure(mac);
BTMModule.stopMeasure(mac);
BTMModule.disconnect(mac);

Supported Devices

| Category | Model | Module | Platform | |----------|-------|--------|----------| | Blood Pressure | BP5 | BP5Module | iOS & Android | | Blood Pressure | BP5S | BP5SModule | iOS & Android | | Blood Pressure | BP3L | BP3LModule | iOS & Android | | Blood Pressure | BP7 | BP7Module | iOS & Android | | Blood Pressure | BP7S | BP7SModule | iOS & Android | | Blood Pressure | KN-550BT | BP550BTModule | iOS & Android | | Pulse Oximeter | PO3 | PO3Module | iOS & Android | | Pulse Oximeter | PO1 | PO1Module | iOS & Android | | Body Scale | HS2S | HS2SModule | iOS & Android | | Body Scale | HS2S Pro | HS2SProModule | iOS & Android | | Body Scale | HS4S | HS4SModule | iOS & Android | | Body Scale | HS6 | HS6Module | iOS & Android | | Blood Glucose | BG5S | BG5SModule | iOS & Android | | Blood Glucose | BG5 | BG5Module | iOS & Android | | Blood Glucose | BG1 | BG1Module | iOS & Android | | Blood Glucose | BG1A | BG1AModule | iOS & Android | | Blood Glucose | BG1S | BG1SModule | iOS & Android | | Activity Tracker | AM3S | AM3SModule | iOS & Android | | Activity Tracker | AM4 | AM4Module | iOS & Android | | Activity Tracker | AM5 | AM5Module | iOS & Android | | Activity Tracker | AM6 | AM6Module | iOS & Android | | Thermometer | BTM | BTMModule | iOS & Android | | Thermometer | TS28B | TS28BModule | iOS & Android | | Thermometer | NT13B | NT13BModule | iOS & Android | | Thermometer | PT3SBT | PT3SBTModule | iOS & Android | | ECG | ECG3 | ECGModule | iOS only | | ECG | ECG3USB | ECGUSBModule | iOS only |


Migrating from v1.x

See MIGRATION_GUIDE.md for a full guide.

The only code change required is replacing DeviceEventEmitter with NativeEventEmitter:

// Before (v1.x) ❌
import { DeviceEventEmitter } from 'react-native';
DeviceEventEmitter.addListener(BP5SModule.Event_Notify, handler);

// After (v2.0+) ✅
import { NativeEventEmitter, NativeModules } from 'react-native';
const emitter = new NativeEventEmitter(NativeModules.BP5SModule);
emitter.addListener(BP5SModule.Event_Notify, handler);

FAQ

Q: I can scan and connect to a device, but never receive measurement data.
A: Make sure you are creating NativeEventEmitter inside useEffect, not at the module top-level or component function body. The emitter must be created after React Native has fully initialized the native modules.

Q: iOS pod install fails with a linker error about a missing static library.
A: Delete the ios/Pods directory and run cd ios && pod install again.

Q: Android method calls have no effect.
A: Confirm that the .pem license file is present in android/app/src/main/assets/ and that sdkAuthWithLicense() was called at app startup.

Q: NativeModules.XXXModule is null.
A: ECG3 and ECG3USB are iOS-only. They will be null on Android. Use Platform.OS === 'ios' before accessing these modules.

Q: What is the correct method name for HS2S heart rate mode?
A: Both spellings are supported and equivalent:

HS2SModule.enterHS2SHeartRateMeasurementMode(mac);      // v1.x name, still works
HS2SModule.enterHS2SProHeartRateMeasurementMode(mac);   // native method name

Q: How do I disconnect the BG5S?
A: Both of the following work identically:

BG5SModule.disconnect(mac);    // recommended
BG5SModule.disConnect(mac);    // also valid (legacy spelling)

Q: I'm upgrading from an older RN version — do I need to change anything else?
A: If you are upgrading to React Native >= 0.76 and enabling the New Architecture, the event listener change above is the only SDK-level change. Your device API calls (methods on BP5SModule, AM6Module, etc.) remain unchanged.


Release Notes

v2.0.0

  • Full support for React Native New Architecture (TurboModules / Fabric)
  • Minimum React Native version bumped to >= 0.76.0
  • iOS: all modules use initWithDisabledObservation to guarantee event dispatch in TurboModule mode
  • iOS: 29 +TurboModule.mm category files added for C++ JSI bridge
  • Android: @ReactModule annotations added to all modules for interop layer compatibility
  • 29 TypeScript spec files added (src/Native*.ts) for Codegen support
  • Event name constants are now hardcoded in JavaScript — no longer depend on constantsToExport
  • Breaking change: event listeners must use NativeEventEmitter (see Migrating from v1.x)

v1.9.1

  • Support Android 16KB page size
  • Bug fixes

v1.9.0

  • Adapt to Android 15
  • Code optimization and bug fixes

v1.8.0

  • Support new version of BP5S (hardware version > 2.0.0) with offline data time correction
  • Code optimization