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:

sudo ip addr add 192.168.1.100/24 dev <eth-interface>

On this machine the interface is enp1s0:

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.

python3 --version   # 3.10+

Running

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:

{"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

Description
No description provided
Readme 28 KiB
Languages
Python 100%