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

@gaozh1024/rn-veepoo-sdk

v1.0.0

Published

Expo module for Veepoo SDK Bluetooth connectivity

Readme

@gaozh1024/rn-veepoo-sdk

Expo 模块,用于 Veepoo 设备蓝牙连接和健康数据交互。

当前包默认导出已经切换为新的统一接口

  • TS 层统一返回结构:UnifiedResult<T>
  • Android / iOS 字段差异统一收敛
  • 仅提供临时内存缓存
  • 所有读取能力都支持统一读取策略
  • 所有测量能力都走统一 startMeasurement / stopMeasurement

包入口已经切到统一接口,业务侧应只面向新接口开发。


安装

npm install @gaozh1024/rn-veepoo-sdk

平台要求

| 平台 | 最低版本 | Expo Go | 说明 | | --- | --- | --- | --- | | iOS | 13.4+ | ❌ | 需要开发构建 | | Android | 6.0+ | ❌ | 需要开发构建 |


配置

iOS

app.json / app.config.js 中添加插件:

{
  "expo": {
    "plugins": [
      [
        "@gaozh1024/rn-veepoo-sdk",
        {
          "bluetoothAlwaysPermission": "需要蓝牙权限来连接设备",
          "bluetoothPeripheralPermission": "需要蓝牙权限来扫描设备"
        }
      ]
    ]
  }
}

然后执行:

npx expo prebuild --clean
cd ios && pod install && cd ..
npx expo run:ios

Android

Android 权限自动配置,无需额外修改。


快速开始

import VeepooSDK from '@gaozh1024/rn-veepoo-sdk';

await VeepooSDK.init();

const bluetooth = await VeepooSDK.getBluetoothStatus();
if (bluetooth.state !== 'poweredOn') {
  throw new Error('请先打开蓝牙');
}

const permission = await VeepooSDK.requestPermissions();
if (!permission.granted) {
  throw new Error('请先授予蓝牙权限');
}

VeepooSDK.on('scan.deviceFound', ({ device }) => {
  console.log('发现设备', device);
});

await VeepooSDK.startScan({ timeout: 10000 });

const connected = await VeepooSDK.connect('device-id', { password: '0000' });
console.log('连接结果', connected.data);

const battery = await VeepooSDK.getBatteryInfo({
  strategy: 'device-first',
});
console.log('电量', battery.data.level, battery.source);

await VeepooSDK.startMeasurement('heartRate');

VeepooSDK.on('measurement.updated', ({ type, state }) => {
  if (type === 'heartRate') {
    console.log('心率状态', state.state, state.result);
  }
});

统一接口设计

1. 统一返回结构

所有查询型接口统一返回:

type UnifiedResult<T> = {
  data: T;
  source: 'device' | 'memory-cache' | 'storage-cache';
  deviceId?: string;
  timestamp: number;
  cachedAt?: number;
  stale?: boolean;
};

当前实现里:

  • device:直接来自设备
  • memory-cache:来自内存临时缓存
  • storage-cache:类型预留,当前未启用持久化

2. 统一读取策略

所有读取接口支持:

type ReadStrategy =
  | 'device-only'
  | 'cache-only'
  | 'cache-first'
  | 'device-first';

示例:

await VeepooSDK.getSleepData('2026-03-23', {
  strategy: 'cache-first',
  maxAgeMs: 5 * 60 * 1000,
});

3. 仅内存缓存

当前缓存是临时内存缓存

  • App 进程结束即失效
  • 不落盘
  • 不做持久化恢复
  • 适合“先读缓存,再补设备数据”的链路

核心接口

初始化与连接

await VeepooSDK.init();
VeepooSDK.getSDKState();
await VeepooSDK.getBluetoothStatus();
await VeepooSDK.requestPermissions();

await VeepooSDK.startScan();
await VeepooSDK.stopScan();

await VeepooSDK.connect(deviceId, { password: '0000' });
await VeepooSDK.disconnect(deviceId);
await VeepooSDK.getConnectionState(deviceId);
await VeepooSDK.verifyPassword('0000', false);

设备信息

await VeepooSDK.getDeviceProfile();
await VeepooSDK.getBatteryInfo();
await VeepooSDK.getDeviceFunctions();
await VeepooSDK.getDeviceVersion();
await VeepooSDK.getSocialMessageSettings();

数据同步与读取

await VeepooSDK.syncHealthData({
  include: ['sleep', 'sport', 'origin5m', 'origin30m', 'daySummary', 'spo2Origin'],
  saveToCache: true,
});

VeepooSDK.getLastSyncState();
await VeepooSDK.cancelSyncHealthData();

await VeepooSDK.getSleepData(date);
await VeepooSDK.getSportData(date);
await VeepooSDK.getOrigin5mData(date);
await VeepooSDK.getOrigin30mData(date);
await VeepooSDK.getDaySummaryData(date);
await VeepooSDK.getSpo2OriginData(date);
await VeepooSDK.getDailyHealthSnapshot(date);

await VeepooSDK.getHeartRateList(date);
await VeepooSDK.getHeartRateItem({ date, time: '10:30' });
await VeepooSDK.getLatestHeartRate(date);

await VeepooSDK.getBloodPressureList(date);
await VeepooSDK.getBloodPressureItem({ date, time: '10:30' });
await VeepooSDK.getLatestBloodPressure(date);

await VeepooSDK.getBloodOxygenList(date);
await VeepooSDK.getBloodOxygenItem({ date, time: '10:30' });
await VeepooSDK.getLatestBloodOxygen(date);

await VeepooSDK.getTemperatureList(date);
await VeepooSDK.getTemperatureItem({ date, time: '10:30' });
await VeepooSDK.getLatestTemperature(date);

await VeepooSDK.getStressList(date);
await VeepooSDK.getStressItem({ date, time: '10:30' });
await VeepooSDK.getLatestStress(date);

await VeepooSDK.getBloodGlucoseList(date);
await VeepooSDK.getBloodGlucoseItem({ date, time: '10:30' });
await VeepooSDK.getLatestBloodGlucose(date);

await VeepooSDK.getSportList(date);
await VeepooSDK.getSportItem({ date, time: '10:30' });
await VeepooSDK.getLatestSport(date);

指标化统一接口

针对心率、血压、血氧、体温、压力、血糖、运动,统一层现在都提供三类方法:

  • getXxxList(date, options):获取某一天的指标列表
  • getXxxItem({ date, time | timestamp }, options):按时间点获取单条指标
  • getLatestXxx(date?, options):获取最新一条指标

这些接口优先复用统一层已经归一化后的:

  • origin5m
  • origin30m
  • daySummary
  • spo2Origin
  • 最近一次测量缓存

因此业务侧不需要再分别处理 Android / iOS 的差异字段。

测量

await VeepooSDK.startMeasurement('heartRate');
await VeepooSDK.startMeasurement('bloodPressure');
await VeepooSDK.startMeasurement('bloodOxygen');
await VeepooSDK.startMeasurement('temperature');
await VeepooSDK.startMeasurement('stress');
await VeepooSDK.startMeasurement('bloodGlucose');

await VeepooSDK.stopMeasurement('heartRate');

VeepooSDK.getMeasurementState('stress');
await VeepooSDK.getLastMeasurementResult('bloodGlucose');

设置类能力

await VeepooSDK.syncPersonalInfo(info);
await VeepooSDK.getAutoMeasureSettings();
await VeepooSDK.updateAutoMeasureSetting(setting);
await VeepooSDK.setLanguage('english');

缓存与诊断

VeepooSDK.getCacheStatus();
VeepooSDK.getCachedValue({ key: 'sleep:device-id:2026-03-23' });
await VeepooSDK.clearCache();
VeepooSDK.invalidateCache('sleep:device-id:2026-03-23');
await VeepooSDK.warmupCache({ include: ['sleep', 'sport'] });
await VeepooSDK.getDiagnostics();

完整统一接口清单

下表对应当前对外暴露的统一接口;业务接入时可以只面向这一层开发。

| 分类 | 接口 | 返回/说明 | | --- | --- | --- | | 生命周期 | init() | 初始化 SDK | | 生命周期 | destroy() | 销毁 SDK | | 状态 | getSDKState() | SDKState | | 蓝牙/权限 | getBluetoothStatus() | Promise<BluetoothStatus> | | 蓝牙/权限 | requestPermissions() | Promise<PermissionsResult> | | 扫描 | startScan(options?) | 开始扫描 | | 扫描 | stopScan() | 停止扫描 | | 连接 | connect(deviceId, options?) | Promise<UnifiedResult<ConnectionSession>> | | 连接 | disconnect(deviceId?) | 断开连接 | | 连接 | getConnectionState(deviceId?) | Promise<ConnectionSnapshot> | | 连接 | verifyPassword(password?, is24Hour?) | Promise<UnifiedResult<PasswordData>> | | 设备信息 | getDeviceProfile(options?) | UnifiedResult<DeviceProfile> | | 设备信息 | getBatteryInfo(options?) | UnifiedResult<BatteryInfo> | | 设备信息 | getDeviceFunctions(options?) | UnifiedResult<DeviceFunctions> | | 设备信息 | getDeviceVersion(options?) | UnifiedResult<DeviceVersion> | | 设备信息 | getSocialMessageSettings(options?) | UnifiedResult<SocialMsgData> | | 同步 | syncHealthData(options?) | Promise<SyncTaskResult> | | 同步 | cancelSyncHealthData(taskId?) | 取消同步 | | 同步 | getLastSyncState() | SyncState | | 日数据 | getSleepData(date?, options?) | UnifiedResult<SleepData> | | 日数据 | getSportData(date?, options?) | UnifiedResult<SportStepData> | | 日数据 | getOrigin5mData(date?, options?) | UnifiedResult<OriginData[]> | | 日数据 | getOrigin30mData(date?, options?) | UnifiedResult<HalfHourData[]> | | 日数据 | getDaySummaryData(date?, options?) | UnifiedResult<DaySummaryData> | | 日数据 | getSpo2OriginData(date?, options?) | UnifiedResult<Spo2OriginData[]> | | 日数据 | getDailyHealthSnapshot(date?, options?) | UnifiedResult<DailyHealthSnapshot> | | 指标化接口 | getHeartRateList / getHeartRateItem / getLatestHeartRate | 心率列表 / 单项 / 最新 | | 指标化接口 | getBloodPressureList / getBloodPressureItem / getLatestBloodPressure | 血压列表 / 单项 / 最新 | | 指标化接口 | getBloodOxygenList / getBloodOxygenItem / getLatestBloodOxygen | 血氧列表 / 单项 / 最新 | | 指标化接口 | getTemperatureList / getTemperatureItem / getLatestTemperature | 体温列表 / 单项 / 最新 | | 指标化接口 | getStressList / getStressItem / getLatestStress | 压力列表 / 单项 / 最新 | | 指标化接口 | getBloodGlucoseList / getBloodGlucoseItem / getLatestBloodGlucose | 血糖列表 / 单项 / 最新 | | 指标化接口 | getSportList / getSportItem / getLatestSport | 运动列表 / 单项 / 最新 | | 测量 | startMeasurement(type) | 启动统一测量 | | 测量 | stopMeasurement(type) | 停止统一测量 | | 测量 | getMeasurementState(type) | 本地测量状态快照 | | 测量 | getLastMeasurementResult(type, options?) | 最近一次测量结果 | | 设置 | syncPersonalInfo(info) | Promise<boolean> | | 设置 | getAutoMeasureSettings(options?) | UnifiedResult<AutoMeasureSetting[]> | | 设置 | updateAutoMeasureSetting(setting) | UnifiedResult<AutoMeasureSetting[]> | | 设置 | setLanguage(language) | Promise<boolean> | | 缓存 | getCacheStatus(deviceId?) | CacheStatus | | 缓存 | getCachedValue({ key }) | CacheValue<T> \| null | | 缓存 | clearCache(scope?) | 清空内存缓存 | | 缓存 | invalidateCache(key) | 失效指定缓存 | | 缓存 | warmupCache(options) | Promise<SyncTaskResult> | | 诊断 | getDiagnostics(options?) | Promise<UnifiedDiagnostics> | | 事件 | on(event, listener) | 注册监听 | | 事件 | off(event, listener) | 移除监听 | | 事件 | once(event, listener) | 一次性监听 | | 事件 | removeAllListeners(event?) | 清空监听 |

指标接口返回约定

  • getXxxList():统一返回 UnifiedResult<PointType[]>
  • getXxxItem():统一返回 UnifiedResult<PointType> | null
  • getLatestXxx():统一返回 UnifiedResult<PointType> | null

其中 PointType 统一包含:

type MetricPointBase = {
  date: string;
  time: string;
  timestamp: number;
  sourceType: 'origin5m' | 'origin30m' | 'daySummary' | 'spo2Origin' | 'measurement';
};

统一事件

新接口统一事件名如下:

type UnifiedEventMap = {
  'scan.deviceFound': { device: VeepooDevice; timestamp: number };
  'connection.changed': { deviceId: string; status: ConnectionStatus; authenticated?: boolean; ready?: boolean };
  'device.ready': { deviceId: string; isOadModel?: boolean };
  'sync.progress': { taskId: string; progress: ReadOriginProgress };
  'sync.completed': { taskId: string; success: boolean; timestamp: number };
  'measurement.updated': { type: MeasurementType; state: MeasurementState };
  'cache.updated': { key: string; domain: CacheDomain; deviceId?: string; date?: string; timestamp: number };
  error: VeepooError;
};

监听示例:

VeepooSDK.on('measurement.updated', ({ type, state }) => {
  console.log(type, state.state);
});

VeepooSDK.on('sync.progress', ({ progress }) => {
  console.log(progress.progress);
});

推荐功能链路

1. 扫描并连接

await VeepooSDK.init();
await VeepooSDK.requestPermissions();
await VeepooSDK.startScan();
await VeepooSDK.connect(deviceId, { password: '0000' });

2. 同步并缓存

await VeepooSDK.syncHealthData({
  include: ['sleep', 'sport', 'origin30m'],
  saveToCache: true,
});

3. 页面优先读缓存

const snapshot = await VeepooSDK.getDailyHealthSnapshot('2026-03-23', {
  strategy: 'cache-first',
});

4. 测量统一走单入口

await VeepooSDK.startMeasurement('stress');
await VeepooSDK.stopMeasurement('stress');

旧接口迁移映射

| 旧接口 | 新接口 | | --- | --- | | checkBluetoothStatus() | getBluetoothStatus() | | getConnectionStatus() | getConnectionState() | | readBattery() | getBatteryInfo() | | readDeviceFunctions() | getDeviceFunctions() | | readDeviceVersion() | getDeviceVersion() | | readSocialMsgData() | getSocialMessageSettings() | | startReadOriginData() / readDeviceAllData() | syncHealthData() | | readSleepData() | getSleepData() | | readSportStepData() | getSportData() | | readOriginData() | getOrigin5mData() | | readDaySummaryData() | getDaySummaryData() | | readAutoMeasureSetting() | getAutoMeasureSettings() | | modifyAutoMeasureSetting() | updateAutoMeasureSetting() | | startHeartRateTest() 等 | startMeasurement(type) | | stopHeartRateTest() 等 | stopMeasurement(type) | | 旧原生事件名 | 统一事件名 scan.* / connection.* / sync.* / measurement.* |


导出

import VeepooSDK from '@gaozh1024/rn-veepoo-sdk';
import {
  VeepooUnifiedSDK,
  type UnifiedResult,
  type MeasurementType,
  type SDKState,
  type UnifiedEventMap,
} from '@gaozh1024/rn-veepoo-sdk';
  • default = 新统一接口
  • VeepooSDK = 新统一接口
  • VeepooUnifiedSDK = 新统一接口

开发验证

npm run typecheck
npm run build

许可证

MIT