chenders/emay-sleepo2

GitHub: chenders/emay-sleepo2

逆向工程得到的 EMAY SleepO2 脉搏血氧仪多语言 BLE SDK,提供统一的跨平台实时数据采集接口。

Stars: 0 | Forks: 0

# EMAY SleepO2 BLE SDK 每个包都暴露了**相同且简单的 API**。选择您的语言 —— 在 Swift、Python、Node.js、Rust、Go 和 Kotlin 中,`EMAYClient` 接口完全一致。 ## 快速入门 ### Swift ``` import EMAYSleepO2 let emay = EMAYClient() emay.onReading = { reading in print("SpO₂: \(reading.spo2 ?? 0)% HR: \(reading.pulse ?? 0)") } try await emay.start() ``` ### Python ``` import asyncio from emay_sleepo2 import EMAYClient async def main(): emay = EMAYClient() emay.on_reading = lambda r: print(f"SpO₂: {r.spo2}% HR: {r.pulse}") await emay.start() await asyncio.sleep(30) # stream for 30 seconds await emay.stop() asyncio.run(main()) ``` ### Node.js ``` import { EMAYClient } from 'emay-sleepo2'; const emay = new EMAYClient(); emay.on('reading', (r) => { console.log(`SpO₂: ${r.spo2}% HR: ${r.pulse}`); }); await emay.start(); // ... stream ... await emay.stop(); ``` ### Rust ``` use emay_sleepo2::EMAYClient; #[tokio::main] async fn main() { let mut emay = EMAYClient::new().await?; emay.on_reading(|r| println!("SpO₂: {}% HR: {}", r.spo2, r.pulse)); emay.start().await?; tokio::time::sleep(Duration::from_secs(30)).await; emay.stop().await?; } ``` ### Go ``` package main import ( "fmt" "time" emay "github.com/chenders/emay-sleepo2" ) func main() { client, _ := emay.NewClient(emay.DefaultAdapter()) client.OnReading = func(r emay.Reading) { fmt.Printf("SpO₂: %d%% HR: %d\n", r.SpO2, r.Pulse) } client.Start() time.Sleep(30 * time.Second) client.Stop() } ``` ### Kotlin (Android) ``` val emay = EMAYClient(context) emay.onReading = { reading -> println("SpO₂: ${reading.spo2}% HR: ${reading.pulse}") } emay.start(scope = lifecycleScope) ``` ## API 参考 每个绑定都暴露了相同的最小化接口: ``` class EMAYClient { // Lifecycle start() — connect and begin streaming stop() — stop streaming and disconnect isStreaming: bool — whether currently streaming // Data onReading: (Reading) -> void — called at ~1 Hz with new readings // Status status: Status — Idle | Scanning | Connecting | Streaming | Failed onStatusChange: (Status) -> void // Advanced start(address) — connect to a specific device by address batteryLevel: Int? — battery percentage (after connection) heartbeatInterval: Duration — default 1.5s // CSV (parse only, no BLE) static parseCSV(data) -> [Reading] static parseCSVFile(path) -> [Reading] } ``` ## 读取类型 ``` Reading { spo2: Int? // SpO₂ percent (0–100), nil when finger off pulse: Int? // Pulse rate in bpm, nil when no reading timestamp: Instant // When this reading was captured } ``` ## 协议说明 (太长不看) - BLE 服务 `FF12`,写入 `FF01`,通知 `FF02` - 命令格式:`payload + sum(payload) & 0x7F` - 启动序列:`hello → deviceState → startRealtime → getBattery` - 每隔约 1.5 秒发送一次心跳命令以维持连接 - 数据帧:8 字节 — `EB 01 05 [PR] [SpO2] 7F 00 [cks]` - 完整规范:[`spec.md`](spec.md) ## 包 | 语言 | 源码 | 平台 | BLE 库 | |----------|------------------|----------------|----------------| | Swift | [`swift/`](swift)| iOS/macOS | CoreBluetooth | | Python | [`python/`](python) | macOS/Linux/Windows/RPi | bleak | | Node.js | [`node/`](node) | macOS/Linux/Windows/RPi | noble | | Rust | [`rust/`](rust) | macOS/Linux/Windows | btleplug | | Go | [`go/`](go) | macOS/Linux/Windows/embedded | TinyGo BLE | | Kotlin | [`kotlin/`](kotlin) | Android 8.0+ | Android BLE | ## 关于 EMAY SleepO2 是一款售价 30 美元的连续式脉搏血氧仪,支持夜间数据流传输。 此前没有关于其协议的公开文档。我们对其进行了逆向工程,并将结果开源,以便健康应用开发者、研究人员和极客们无需自己破解协议即可传输血氧数据。 ## 许可证 MIT
标签:MITM代理, 云资产清单, 医疗设备, 可视化界面, 日志审计, 物联网, 蓝牙(BLE), 血氧仪, 跨平台SDK, 逆向工具, 逆向工程