@gaozh1024/rn-veepoo-sdk
v1.0.0
Published
Expo module for Veepoo SDK Bluetooth connectivity
Maintainers
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:iosAndroid
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):获取最新一条指标
这些接口优先复用统一层已经归一化后的:
origin5morigin30mdaySummaryspo2Origin- 最近一次测量缓存
因此业务侧不需要再分别处理 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> | nullgetLatestXxx():统一返回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
