Skip to content
View jaybaron1's full-sized avatar

Block or report jaybaron1

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Maximum 250 characters. Please don't include any personal information such as legal names or email addresses. Markdown supported. This note will be visible to only you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
jaybaron1/README.md

Mobi-To-Tidepool

This repository hosts a small, focused toolchain for migrating Tandem Mobi data captured via tconnectsync or Nightscout into Tidepool. The initial focus is converting Nightscout export_treatments.json bolus data into a Tidepool data payload that can be uploaded with the Tidepool API.

Why this exists

Switching pumps should not mean losing historical data. Building on the methodologies used in the tconnectsync and tidepooltoNightScoutSync projects, this repo provides:

  • A conversion library that maps Nightscout treatments into Tidepool bolus events.
  • A CLI that can output a Tidepool-ready JSON payload and optionally upload it to the Tidepool platform.
  • A lightweight Tidepool API helper for authenticated uploads.

Installation

Create a virtual environment and install the dependencies:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Configure environment variables

Create a .env file in the project root (or alongside your CLI invocation) so you don't need to pass secrets on the command line. An .env.example template is included—copy it to .env and fill in your values. Example:

# Nightscout
NIGHTSCOUT_URL=https://your-nightscout.example.com
NIGHTSCOUT_SECRET=your-nightscout-secret
NS_URL=https://your-nightscout.example.com        # alias used by tconnectsync
NS_SECRET=your-nightscout-secret                 # alias used by tconnectsync

# Tidepool
[email protected]
TIDEPOOL_PASSWORD=your-tidepool-password

# t:connect (for tconnectsync exports)
[email protected]
TCONNECT_PASSWORD=your-tconnect-password
TCONNECT_REGION=US                               # optional (US/EU)
TIMEZONE_NAME=America/New_York                   # optional
PUMP_SERIAL_NUMBER=11111111                      # optional

The CLI automatically loads this file via python-dotenv.

If you use the upstream tconnectsync exporter to populate Nightscout before running this tool, keeping the TCONNECT_*, NS_URL, and NS_SECRET environment variables in the same .env file lets both workflows share credentials without editing source code.

What you still need to provide manually

This repo bundles the conversion and upload logic, but a few inputs still rely on you:

  • Fill in .env with NIGHTSCOUT_URL/NIGHTSCOUT_SECRET and TIDEPOOL_USERNAME/TIDEPOOL_PASSWORD (plus any TCONNECT_* values if you also run the upstream exporter). Copy .env.example as a starting point.
  • Ensure Nightscout has data from tconnectsync or your preferred source; the converter assumes bolus/combobolus records already exist in Nightscout.
  • Install Python 3.9+ (or your platform’s supported version) so the provided CLI and batch script can create a virtual environment and run.
  • Pick your entry point: either double-click sync_mobi_to_tidepool.bat on Windows or run python -m mobi_to_tidepool.cli on other platforms with the desired flags. The sync will still honor your .env file.

Usage

One-shot Windows script

On Windows, run sync_mobi_to_tidepool.bat from the repo root. It will create a virtual environment (if missing), install requirements, and perform the Nightscout → Tidepool sync using the values in your .env file:

sync_mobi_to_tidepool.bat

If you want to pass custom CLI arguments (for example, to change the date window), append them after the script name:

sync_mobi_to_tidepool.bat --start-date 2024-01-01T00:00:00Z --end-date 2025-01-01T00:00:00Z

The script requires NIGHTSCOUT_URL (and typically NIGHTSCOUT_SECRET) to be set in .env. Tidepool credentials are also read from .env unless you pass them as CLI flags.

If Python is not on PATH (for example, installed under C:\Users\you\Python\python.exe), set MTP_PYTHON before running the script to point at your interpreter:

set MTP_PYTHON=C:\Users\you\Python\python.exe
sync_mobi_to_tidepool.bat

MTP_PYTHON only affects how the batch file creates the virtual environment; the sync itself always runs with the .venv\Scripts\python.exe it manages.

The batch file now sets PYTHONPATH to the repo root and invokes python -m pip from the virtual environment, so module imports resolve reliably without needing a local install. If you still see pip upgrade notices, you can optionally run the printed python.exe -m pip install --upgrade pip command inside the .venv created by the script.

Convert a Nightscout export

You can either point at an existing export_treatments.json file or let the CLI pull data directly from Nightscout in one step.

Fetch the last year from Nightscout, convert, and upload to Tidepool:

python -m mobi_to_tidepool.cli \
  --nightscout-url "https://your-nightscout.example.com" \
  --nightscout-secret "your-nightscout-secret" \
  --upload \
  --username "[email protected]" \
  --password "your-tidepool-password"

The Nightscout export is saved to export_treatments.json by default. To reuse an existing export instead of fetching, pass its path as the first argument:

python -m mobi_to_tidepool.cli /path/to/export_treatments.json tidepool_upload.json

This writes tidepool_upload.json containing Tidepool-formatted bolus events.

End-to-end workflow

  1. Prepare a .env file with your Nightscout and Tidepool credentials (see Configure environment variables).

  2. Run the CLI with only the Nightscout URL and --upload flag to fetch, convert, and upload in a single step:

    python -m mobi_to_tidepool.cli \
      --nightscout-url "$NIGHTSCOUT_URL" \
      --upload
    • Nightscout credentials are read from NIGHTSCOUT_SECRET (and optionally NIGHTSCOUT_URL) in your .env if not provided explicitly.
    • Tidepool credentials are read from TIDEPOOL_USERNAME and TIDEPOOL_PASSWORD.
    • The Nightscout export is stored in export_treatments.json unless you pass --skip-nightscout-export-file.
    • Tidepool uploads automatically use .tidepool_upload_manifest.json to skip any GUIDs that were already sent in a prior run, preventing duplicate writes. Delete the manifest if you intentionally want to re-upload.
    • Before writing, the CLI validates your Tidepool session can read from your data bucket. Pass --skip-write-check to bypass the permission probe.

Upload to Tidepool (optional)

To upload directly to Tidepool, provide credentials via environment variables or CLI flags:

export TIDEPOOL_USERNAME="[email protected]"
export TIDEPOOL_PASSWORD="your-api-password"
python -m mobi_to_tidepool.cli /path/to/export_treatments.json tidepool_upload.json --upload

When pulling from Nightscout directly you can also control the time window:

python -m mobi_to_tidepool.cli \
  --nightscout-url "https://your-nightscout.example.com" \
  --nightscout-secret "your-nightscout-secret" \
  --start-date 2024-01-01T00:00:00Z \
  --end-date 2025-01-01T00:00:00Z

You can adjust how combo boluses are split and their duration assumptions:

python -m mobi_to_tidepool.cli /path/to/export_treatments.json tidepool.json \
  --combo-split 0.3 \
  --combo-duration 30

To change the dedupe manifest location or disable it entirely:

```bash
python -m mobi_to_tidepool.cli /path/to/export_treatments.json tidepool.json --upload \
  --manifest /path/to/custom_manifest.json

# or skip dedupe tracking (may produce duplicates if rerun)
python -m mobi_to_tidepool.cli /path/to/export_treatments.json tidepool.json --upload --skip-manifest

### Example input
```json
{
  "eventType": "Combo Bolus",
  "created_at": "2025-12-04 10:05:03-05:00",
  "carbs": 0,
  "insulin": 0.85,
  "notes": "Automatic Bolus",
  "enteredBy": "Pump (tconnectsync)",
  "pump_event_id": "513404,513389,513390,513391",
  "glucose": "181"
}

Example output

The converter produces Tidepool-compatible bolus entries. With the above input and default combo settings (50/50 split, zero duration), an example Tidepool payload looks like:

{
  "type": "bolus",
  "source": "Pump (tconnectsync)",
  "deviceId": "tconnect-mobi",
  "time": "2025-12-04T10:05:03-05:00",
  "deviceTime": "2025-12-04T10:05:03",
  "timezoneOffset": -300,
  "uploadId": "mobi-to-tidepool-<run-uuid>",
  "guid": "<entry-uuid>",
  "subType": "dual/square",
  "normal": 0.425,
  "extended": 0.425,
  "duration": 0,
  "expectedNormal": 0.425,
  "expectedExtended": 0.425,
  "bgInput": 181.0,
  "carbInput": 0.0,
  "annotations": [
    {
      "code": "mobi-to-tidepool/assumed-combo-split",
      "value": 0.5,
      "durationMinutes": 0,
      "insulinTotal": 0.85
    }
  ],
  "payload": {
    "pumpEventId": "513404,513389,513390,513391",
    "notes": "Automatic Bolus",
    "originalTreatment": { "...": "full Nightscout record preserved here" }
  }
}

UUIDs and uploadId values will differ on each run, but the shape and field names match Tidepool's bolus schema.

Nightscout → Tidepool field mapping

The converter targets Tidepool's bolus schema (see the Tidepool data model docs) and fills the minimum required fields automatically:

  • time is the original created_at timestamp with its timezone preserved.
  • deviceTime is the local timestamp (timezone removed) derived from created_at.
  • timezoneOffset is computed from the created_at offset (minutes from UTC).
  • deviceId defaults to tconnect-mobi unless overridden.
  • uploadId is auto-generated per run (or set via --upload-id).
  • guid uniquely identifies the converted event.
  • subType/normal/extended/duration are set based on eventType and insulin following Nightscout combo/bolus conventions.

Nightscout metadata such as pump_event_id, notes, carbs, and glucose are preserved either in top-level Tidepool fields (bgInput, carbInput) or under payload.

Coverage of upstream projects

This tool intentionally mirrors the data Nightscout produces when fed by tconnectsync and the Tidepool payload structure demonstrated in TidepoolToNightScoutSync:

  • Nightscout inputs: created_at, eventType, insulin, carbs, glucose, notes, enteredBy, and pump_event_id are all read directly from the exported treatments.json entries, matching what tconnectsync writes for bolus and combo bolus events.
  • Tidepool requirements: the converter fills type, subType, insulin amounts, duration, time, deviceTime, timezoneOffset, deviceId, unique uploadId/guid, and preserves Nightscout context inside payload, aligning with the bolus examples in TidepoolToNightScoutSync while keeping the raw Nightscout treatment for traceability.
  • Scope: the current workflow focuses on bolus and combo bolus records (the data paths present in tconnectsync Nightscout exports). Additional Nightscout entities (basals, device statuses, activity) can be layered in later using the same pattern if needed.

Are we embedding tconnectsync?

Yes—at least the Nightscout-facing pieces needed for this bridge. The built-in NightscoutClient mirrors the behavior of the modified nightscout.py you shared (hashing api-secret, accepting URL/secret from environment variables, and preserving timestamps as returned by Nightscout) so you do not need to vendor the full tconnectsync repository just to export bolus data.

What is not embedded is the full Tandem login/ingestion pipeline from tconnectsync. If you still run that project to pull pump data, keep using it to populate Nightscout and then run this tool to convert/upload to Tidepool. As we add more data types, we will continue to mirror the Nightscout portions of tconnectsync so the workflow stays unified.

For a concise inventory of which upstream artifacts are represented here—and which remain future work—see UPSTREAM_COVERAGE.md.

Testing

Run the unit tests with:

python -m pytest

Notes and assumptions

  • Combo boluses default to a 50/50 split and zero duration unless you override the settings. The exact split is preserved as an annotation in the Tidepool payload.
  • Records with unsupported event types or zero insulin are skipped instead of raising, keeping the conversion resilient to Nightscout data quirks.
  • The Tidepool API client is intentionally minimal. If your account requires special authentication flows, use the generated JSON with the official Tidepool uploader instead.

Popular repositories Loading

  1. cgm-remote-monitor cgm-remote-monitor Public

    Forked from nightscout/cgm-remote-monitor

    nightscout web monitor

    JavaScript

  2. pancreabble pancreabble Public

    Forked from mddub/pancreabble

    Send OpenAPS status updates to a Pebble watch via Bluetooth.

    Python

  3. oref0 oref0 Public

    Forked from openaps/oref0

    oref0: The open reference implementation of the OpenAPS reference design.

    JavaScript

  4. docs docs Public

    Forked from openaps/docs

    Documentation for setting up OpenAPS

    Makefile

  5. jaybaron1 jaybaron1 Public

    Config files for my GitHub profile.

    Python

  6. mobi-to-tidepool mobi-to-tidepool Public