A browser-based companion app for the PineTime smartwatch that retrieves, decodes, and visualises raw actigraphy and heart rate logs over Bluetooth β no installation required.
The InfiniTime Research Webapp is the data retrieval and visualisation half of a research-grade actigraphy pipeline built on the PineTime open-source smartwatch. It pairs with the PineTime Research Firmware, which logs raw accelerometer and heart rate data silently to the watch's internal flash.
A researcher opens the page in Chrome or Edge, connects to the watch over Bluetooth, and can immediately browse the watch's filesystem, download binary log files, decode them, and export clean CSV files ready for analysis in tools like GGIR or agcounts. If the BLE Protocol Hijacker app is active on the watch, the entire pipeline runs automatically the moment the watch is placed on its charger β no researcher interaction needed.
This project was developed by Marios Louca under the supervision of Dr. Lucas FranΓ§a and Dr. Mario Leocadio-Miguel as a BSc Computer Science final-year project at Northumbria University (2025β2026). It was built on top of an existing, mostly-abandoned BLE file explorer for InfiniTime; all binary decoding, charge-triggered automation, live streaming, and visualisation capabilities were added as part of this work.
- π Zero-install BLE connection β runs entirely in the browser via the Web Bluetooth API; no drivers, no native app, no admin privileges required
- π Filesystem browser β list, download, upload, and delete files in the watch's LittleFS over BLE
- π¦ Binary decode β 30-bit accelerometer stream unpacker and HR byte parser; exact inverse of the firmware's compression pipeline
- π CSV export β five timestamp columns (
ts_ms,ts_ms_str,date_utc,time_utc,iso) for compatibility with R, Python, pandas, and Excel - β‘ Charge-triggered auto-download β detects watch charging via the BLE Protocol Hijacker; downloads, decodes, and exports all new logs automatically with no user action
- π Live streaming viewer β real-time heart rate and accelerometer plots rendered directly to Canvas at up to 25 Hz; LTTB downsampling preserves peaks and troughs for multi-hour recordings
- π§ 3D accelerometer view β Three.js arrow and trail showing the live acceleration vector; interactive rotate and zoom
- π CSV replay tool β drag-and-drop previously exported CSVs back into the visualiser offline, without needing the watch
- π οΈ Offline binary interpreter β drag-and-drop raw
.binfiles for local decode without a BLE connection - π‘ Bulk operations β download or delete all log files with a single action; sequential pacing prevents BLE buffer exhaustion and filesystem inconsistency
- π Clock sync β writes the computer's current time to the watch's RTC on every connection via the Current Time Service (CTS)
- π² OTA firmware update β drag-and-drop DFU packages to update firmware over BLE
InfiniTime-webapp/
βββ src/
β βββ App.vue # Root component; terminal-themed UI shell
β βββ main.ts # App entry point
β βββ registerServiceWorker.ts # PWA service worker registration
β βββ components/
β β βββ FileExplorer.vue # Main component (~5,500 lines):
β β β # BLE connection & GATT initialisation
β β β # BLEFS file transfer protocol
β β β # 30-bit binary decoder
β β β # CSV assembler & browser download
β β β # Live streaming (Canvas 2D + Three.js)
β β β # LTTB downsampling
β β β # Charge-detection state machine
β β β # Bulk operations & OTA
β β βββ utils.ts # Component utility functions
β β βββ index.ts # Component exports
β βββ assets/
β βββ logo.png
βββ public/
β βββ index.html
β βββ site.webmanifest # PWA manifest
β βββ (favicon + PWA icons)
βββ doc/
β βββ explorer_1.jpg # UI screenshots
β βββ explorer_2.jpg
β βββ explorer_3.jpg
β βββ infinitime.jpg
βββ package.json
βββ vue.config.js
| Requirement | Notes |
|---|---|
| Chrome or Edge (latest) | Required for Web Bluetooth API; Firefox is not supported |
| Node.js β₯ 16 | For local development only |
| PineTime with research firmware | See PineTime Research Firmware |
The webapp is hosted and ready to use β no setup needed:
https://w23000633.nuwebspace.co.uk/infinitive/
Open in Chrome or Edge, click Connect to InfiniTime, and select your watch.
git clone https://github.com/circadia-bio/infinitive-webapp.git
cd infinitive-webapp
npm install
npm run serve # development server with hot reload
npm run build # production build β dist/Note: Web Bluetooth requires a secure context (HTTPS or localhost). The development server runs on
localhostso this works out of the box.
- Flash the PineTime Research Firmware to the watch
- On the watch, configure sampling rates in Calculator8 (Settings Manager)
- Activate Calculator6 (BLE Protocol Hijacker) β required for charge-triggered auto-download
- Start Calculator7 (Master Switch) β both sensors begin logging in the background
- Participant wears the watch normally
- When the watch is returned to its charger, open the webapp in Chrome; it detects the charging signal automatically, downloads all new log files, decodes them, and triggers CSV downloads β no further interaction needed
If you prefer not to use the charge trigger, connect to the watch at any time, browse to the root directory (/), and use Download All to retrieve log files manually.
Each session produces two CSV files:
hr.csv β one row per heart rate sample
| Column | Example | Description |
|---|---|---|
ts_ms |
1773740000000 |
Unix timestamp in milliseconds (numeric) |
ts_ms_str |
"1773740000000" |
Same value as a quoted string (Excel-safe) |
date_utc |
2026-05-01 |
UTC date |
time_utc |
14:23:01.000 |
UTC time with milliseconds |
iso |
2026-05-01T14:23:01Z |
ISO 8601 |
hr |
68 |
Heart rate in BPM (uint8, 0β255) |
raw.csv β one row per accelerometer sample
Same five timestamp columns, plus:
| Column | Description |
|---|---|
x |
X-axis acceleration (approximate 12-bit signed, Β±2048 counts) |
y |
Y-axis acceleration |
z |
Z-axis acceleration |
corrupted |
true only for a partial terminal sample at end-of-file; exclude from analysis |
Timestamps are reconstructed from the filename β no per-sample timestamps are stored in the binary files. The ts_ms_str column is included because Excel silently converts large integers to scientific notation; use this column when opening CSVs in Excel.
The raw accelerometer CSV can be loaded directly into GGIR, agcounts, and pyActigraphy after minor column renaming. The tri-axial values are in the 12-bit signed integer domain (Β±2048 counts at Β±2 g default range); convert to g by dividing by 1024. The maximum compression artefact is Β±3 counts (β Β±0.003 g at Β±2 g range), which is below the sensor noise floor and undetectable at any epoch timescale used in standard actigraphy.
The webapp declares six GATT services at connection time (required before the browser's device picker closes):
| UUID | Service | Purpose |
|---|---|---|
0xFEBB |
BLEFS | File transfer: list, read, write, delete |
0x180A |
Device Information | Firmware version and device name |
0x180F |
Battery Service | Battery level + charging-state detection via Protocol Hijacker |
0x180D |
Heart Rate | Live BPM streaming |
0x1805 |
Current Time Service | Clock sync on connect |
00030000-78fc-β¦ |
Motion (custom) | Live X/Y/Z accelerometer streaming |
Services are initialised in a fixed serial sequence with a mandatory 200 ms pause before the clock-sync write. This prevents NimBLE TX buffer exhaustion and ensures the CTS write is not silently dropped before the battery ACK is processed.
The BLE Protocol Hijacker (Calculator6 on the watch) encodes charging state into the Battery Service characteristic by alternating between the real battery percentage and a flag value (0 = not charging, 1 = charging) on 2-second cycles. The webapp classifies incoming bytes:
> 1β real battery percentage== 1β charging== 0β not charging
A consecutive-readings counter guards against a genuine 1% battery reading being misclassified. Once charging is confirmed, the auto-download pipeline runs subject to a 5-minute cooldown.
| Package | Version | Purpose |
|---|---|---|
| vue | ^3.2.13 | Reactive component framework |
| vuex | ^4.0.2 | State management |
| naive-ui | ^2.26.0 | UI component library |
| three | ^0.182.0 | 3D accelerometer visualisation |
| jszip | ^3.7.1 | ZIP/resource file processing |
| crc-32 | ^1.2.2 | File integrity checksums |
| vue-webble | ^0.1.0 | Web Bluetooth abstraction |
| web-bluetooth-dfu | ^1.2.1 | OTA firmware update support |
| Web Bluetooth API | browser-native | BLE communication (no npm package) |
The live streaming charts use the native Canvas 2D API directly rather than Chart.js to achieve smooth rendering at 25 Hz. Routing samples through Vue's reactivity system at this rate produced an unusable frame rate in the initial Chart.js prototype.
If you use this webapp in your research, please cite:
@mastersthesis{louca2026pinetime,
author = {Louca, Marios},
title = {A Research-Grade {PineTime} Firmware for Actigraphy and Heart Rate Monitoring},
school = {Northumbria University},
year = {2026},
type = {{BSc (Hons) Computer Science Individual Computing Project}},
supervisor = {Franca, Lucas},
note = {Module KV6013}
}| Role | Name | Affiliation |
|---|---|---|
| Developer | Marios Louca | Northumbria University |
| Principal Investigator | Dr. Lucas FranΓ§a | Northumbria University / Circadia Lab |
| Principal Investigator | Dr. Mario Leocadio-Miguel | Northumbria University / Circadia Lab |
- β PineTime Research Firmware β The InfiniTime firmware extension that generates the log files this webapp retrieves
- π SleepDiaries β Progressive web app for digital sleep diary collection in research studies
- π§ͺ ptestR β R package for permutation-based statistical testing of wearable time-series data
- β‘ ACTT_validation_study β Validation of actigraphy devices against polysomnography
- π¬ circadia-bio β The Circadia Lab GitHub organisation
Released under the GNU General Public License v3.0.
The InfiniTime firmware this webapp was developed alongside is licensed under GPL-3.0. This webapp is distributed under the same licence to maintain compatibility.
Copyright Β© Marios Louca, Lucas FranΓ§a, Mario Leocadio-Miguel, 2026