Skip to main content

TILT

Tilt integration (device attach)

This document describes how Tilt Hydrometer logging is integrated into Brewery App.

For the full end-to-end integration overview (tokens + attach + readings + charts), see:

  • docs/integrations/FLOATING-HYDROMETERS.md

How data reaches our API

Tilt Hydrometers broadcast readings via BLE. They cannot call our API directly. A gateway must be used, typically:

  • TiltPi (Raspberry Pi / Node-RED)
  • Tilt phone app (only logs while the app is open/awake)

The gateway is configured with a Cloud URL. It performs HTTP POST requests to that URL on an interval (often 15 minutes, depending on gateway settings).

Public ingest endpoint (Cloud URL)

  • URL to paste in Tilt gateway: https://<our-domain>/api/integrations/tilt/<token>
  • Method: POST
  • Auth: token in URL; server stores only a SHA-256 hash of the token

Token reveal (Option 1)

Tokens are deterministic and can be re-visualized from any browser (no client-side remembering):

  • Reveal: GET /api/workspaces/:workspaceId/integrations/tilt/reveal
  • Generic (by kind): GET /api/workspaces/:workspaceId/integrations/:kind/reveal

Token generation uses INTEGRATIONS_TOKEN_SECRET (required in production). The DB does not store plaintext tokens.

Supported payload (v1)

We support the Tilt “Cloud URL” JSON keys and accept extra keys for forward compatibility (stored in rawJson).

Typical fields (strings or numbers):

  • Temp: temperature (assumed Fahrenheit, converted to °C on ingest)
  • SG: specific gravity (stored as float)
  • Color: Tilt color (used as identity if no uuid/mac is provided)
  • Beer, Comment, Timepoint: stored in rawJson

Optional identity fields (if present):

  • uuid
  • mac / macid
  • timestamp

Routing to brew sessions (Option B)

The ingest endpoint does not infer the brew session from the payload.

Instead:

  • each discovered device is registered under the workspace integration
  • the user attaches the device to a Brew Session
  • future readings are routed to the currently active attachment (“single-active”)

Management endpoints (authenticated, workspace-scoped)

All endpoints below require an authenticated web session and an active workspace.

  • Create integration / generate token: POST /api/workspaces/:workspaceId/integrations/tilt
  • Rotate token: POST /api/workspaces/:workspaceId/integrations/tilt/rotate-token
  • Revoke integration: POST /api/workspaces/:workspaceId/integrations/tilt/revoke
  • Reveal token + Cloud URL: GET /api/workspaces/:workspaceId/integrations/tilt/reveal
  • Integration status: GET /api/workspaces/:workspaceId/integrations/tilt
  • Devices list (with active attachment + last reading): GET /api/workspaces/:workspaceId/integrations/tilt/devices
  • Attach device: POST /api/workspaces/:workspaceId/integrations/tilt/devices/:deviceId/attach body { brewSessionId }
  • Detach device: POST /api/workspaces/:workspaceId/integrations/tilt/devices/:deviceId/detach
  • Recent brew sessions: GET /api/workspaces/:workspaceId/brew-sessions/recent?limit=25

Web UI

The initial UX lands here:

  • apps/web/app/[locale]/ferm-data-integration/page.tsx → accordion section Integrations

Flow:

  • Create integration → copy Cloud URL into Tilt gateway
  • Reveal Cloud URL anytime to reconfigure gateways
  • Wait for first log (device appears)
  • Attach device to brew session