raehDocs
Examples

Python

Runnable ingest and subscribe scripts.

These scripts work against api.raeh.io with just a raeh_* API key and a device_model_id from the dashboard. No other setup.

Install deps:

pip install httpx websockets

Set env:

export RAEH_CLIENT_KEY=raeh_...
export RAEH_DEVICE_MODEL_ID=<uuid from dashboard>

Ingest: stream synthetic PPG

Good for smoke-testing your key and device model without a real wearable.

# ingest_synth.py
import os, asyncio, json, time, uuid, struct, math
from urllib.parse import quote
import websockets

KEY = os.environ["RAEH_CLIENT_KEY"]
DM_ID = os.environ["RAEH_DEVICE_MODEL_ID"]

async def main():
    url = (
        f"wss://api.raeh.io/stream/ingest"
        f"?api_key={quote(KEY)}"
        f"&device_id=demo-{uuid.uuid4().hex[:8]}"
        f"&device_model_id={quote(DM_ID)}"
    )
    async with websockets.connect(url) as ws:
        handshake = json.loads(await ws.recv())
        slot_id = handshake["slots"][0]["slot_id"]
        print(f"session: {handshake['session_id']}")

        # 60 one-second frames of synthetic 1.2 Hz sinusoid (→ 72 bpm)
        for i in range(60):
            t0 = int(time.time() * 1000)
            samples = [int(2048 + 500 * math.sin(2 * math.pi * 1.2 * k / 100))
                       for k in range(100)]
            header = struct.pack(">BqHB", slot_id, t0, len(samples), 0)
            payload = b"".join(s.to_bytes(2, "little", signed=True) for s in samples)
            await ws.send(header + payload)
            print(f"  frame {i + 1}/60", end="\r", flush=True)
            await asyncio.sleep(1.0)
        print()

asyncio.run(main())

Subscribe: print insights live

Run this first, in its own terminal, then start ingest.

# subscribe.py
import os, asyncio, json
from urllib.parse import quote
import websockets

KEY = os.environ["RAEH_CLIENT_KEY"]

async def main():
    async with websockets.connect(
        f"wss://api.raeh.io/stream/subscribe?api_key={quote(KEY)}"
    ) as ws:
        await ws.recv()   # drain subscribe ack
        while True:
            msg = json.loads(await ws.recv())
            t, v, u = msg.get("type"), msg.get("value"), msg.get("unit", "")
            if t:
                print(f"{t:<5} {v:>6.1f} {u}")

asyncio.run(main())

Ingest: real PPG from a file

If you have a CSV of PPG samples (one value per line, int16), stream it at the sensor's native rate:

# ingest_csv.py
import os, asyncio, json, time, uuid, struct, sys
from urllib.parse import quote
import websockets

KEY = os.environ["RAEH_CLIENT_KEY"]
DM_ID = os.environ["RAEH_DEVICE_MODEL_ID"]
CSV_PATH = sys.argv[1]
RATE_HZ = 100  # match your device model's modality sample rate

async def main():
    samples = [int(line.strip()) for line in open(CSV_PATH)]
    frames = [samples[i:i + RATE_HZ] for i in range(0, len(samples), RATE_HZ)]

    url = (
        f"wss://api.raeh.io/stream/ingest"
        f"?api_key={quote(KEY)}"
        f"&device_id=csv-{uuid.uuid4().hex[:8]}"
        f"&device_model_id={quote(DM_ID)}"
    )
    async with websockets.connect(url) as ws:
        handshake = json.loads(await ws.recv())
        slot_id = handshake["slots"][0]["slot_id"]
        print(f"session: {handshake['session_id']}")
        print(f"streaming {len(frames)} frames ({len(frames)}s of data)")

        for i, frame_samples in enumerate(frames):
            t0 = int(time.time() * 1000)
            header = struct.pack(">BqHB", slot_id, t0, len(frame_samples), 0)
            payload = b"".join(s.to_bytes(2, "big", signed=True) for s in frame_samples)
            await ws.send(header + payload)
            await asyncio.sleep(1.0)

asyncio.run(main())
python ingest_csv.py my_recording.csv

What you should see in the subscribe terminal

About 15 seconds after ingest_synth.py starts:

hr      71.8 bpm
spo2    98.0 %
hr      72.1 bpm
rr      15.2 brpm
hr      72.0 bpm
...

On this page