# Pilot Bio-Data — Pulse Oximeter Logger Receives real-time **heart rate (BPM)** and **blood-oxygen (SpO₂)** readings from the Controlytics AI pulse oximeter over a wired Ethernet connection and logs them to a timestamped CSV file. --- ## Hardware | Item | Detail | |---|---| | Device | Controlytics AI Pulse Oximeter v1.0.0 | | Interface | Ethernet (UDP) | | Device Ethernet IP | `192.168.1.2` | | Device WiFi AP | `PULSE_OXI_WIFI` / password `controlytics` | | Device config page | `http://192.168.4.1` (Admin / Admin) | --- ## Network Setup The device sends UDP packets to a configured destination address. The one-time setup below is already done; repeat only if hardware changes. ### Computer (receiver) Assign a static IP to the Ethernet interface connected to the device: ```bash sudo ip addr add 192.168.1.100/24 dev ``` On this machine the interface is `enp1s0`: ```bash sudo ip addr add 192.168.1.100/24 dev enp1s0 ``` ### Device configuration Connect to `PULSE_OXI_WIFI`, open `http://192.168.4.1`, log in, and set: | Field | Value | |---|---| | IP | `192.168.1.2` | | Gateway | `192.168.1.1` | | Subnet | `255.255.255.0` | | Destination address | `192.168.1.100` | | Destination port | `5005` | | Send interval (ms) | `500` | Submit and restart the device (Log Out button). --- ## Requirements Python 3.10 or later. No third-party packages — only the standard library is used. ```bash python3 --version # 3.10+ ``` --- ## Running ```bash python3 receive.py ``` Place the pilot's index finger on the sensor with light, steady pressure. Hold still for a few seconds for the reading to stabilise. ### Example output ``` Listening on UDP 0.0.0.0:5005 | Logging to readings.csv TIME BPM SpO2 % STATUS ---------------------------------------------------- 11:34:00.464 92 97 OK 11:34:00.965 92 97 OK 11:34:01.466 74 97 OK 11:34:22.034 87 98 OK 11:35:14.207 --- --- No finger ``` Press `Ctrl+C` to stop. --- ## Output — readings.csv Every packet is appended to `readings.csv` in the same directory. Rows where no finger is detected have empty `bpm` and `spo2` fields. | Column | Description | |---|---| | `timestamp` | ISO-8601 local timestamp | | `bpm` | Heart rate in beats per minute (empty if no finger) | | `spo2` | Blood-oxygen saturation % (empty if no finger) | | `raw` | Raw JSON packet from device | ### Example rows ``` timestamp,bpm,spo2,raw 2026-06-12T11:34:00.464000,92,97,"{""bpm"":92,""spo2"":97}" 2026-06-12T11:34:01.466000,74,97,"{""bpm"":74,""spo2"":97}" 2026-06-12T11:35:14.207000,,,"{""bpm"":-1,""spo2"":-1}" ``` --- ## Packet Format The device sends a UDP JSON payload every 500 ms: ```json {"bpm": 92, "spo2": 97} ``` Values of `-1` indicate no finger is on the sensor. The parser also accepts `key=value` and bare CSV formats for forward compatibility. --- ## Project Structure ``` pilot_bio_data/ ├── receive.py # UDP listener and CSV logger ├── readings.csv # Auto-generated log (appended on each run) └── README.md ``` --- *Axial Aero — Internal tooling*