HeatSync is local-first by design. The device sits on your WiFi, talks
to your heat pump over a wired RS-485 bus, and exposes its state via
HTTP + MQTT on your network. There’s no HeatSync cloud, no telemetry,
no analytics, no account to make.
A few features do need external HTTPS calls — weather, carbon intensity,
Octopus tariff lookup, OTA updates. This page lists every one, what gets
sent, what comes back, and how often.
These never leave your network:
- Bus reads + writes — every NASA packet decoded from your heat
pump, every command you send. Lives in the device’s RAM and on
the F1/F2 wire.
- Web UI traffic — the dashboard, settings pages, API calls. All
to the device’s local IP (or
heatsync.local via mDNS).
- MQTT messages — to your broker (HA Mosquitto add-on or whichever
you’ve pointed it at). The device doesn’t connect to any remote
MQTT broker.
- Home Assistant integration — both paths (HACS HTTP polling +
MQTT auto-discovery) run entirely on your LAN.
- The HACS integration’s coordinator state — cached in HA’s own
storage, not sent anywhere.
Each row: what’s called, the exact data sent, what comes back, how often.
| |
|---|
| Host | api.open-meteo.com (HTTPS, port 443) |
| Account required | No |
| What’s sent | Your latitude + longitude (4-decimal precision, ~10 m) in the query string |
| What comes back | 48-hour hourly outdoor temperature forecast (~1.5 KB JSON) |
| How often | Every 30 minutes when the device is online |
| Why | Powers the dashboard’s “Next 24 h” panel and the Efficiency / Combo hot-water modes that pick the warmest hour to heat |
| Privacy policy | open-meteo.com — they state “no API key required, no user tracking” |
| |
|---|
| Host | geocoding-api.open-meteo.com (HTTPS) |
| What’s sent | Whatever you typed into the Look up box on /config/data-sources → Weather (a postcode like SO51 or a place name like “Southampton”) |
| What comes back | Best-match lat/lon + display name |
| How often | Only when you click Look up |
| Why | Translates a postcode/city into coordinates so the weather fetch works without typing decimals |
| |
|---|
| Host | api.carbonintensity.org.uk (HTTPS) |
| Account required | No |
| What’s sent | Your outward postcode (e.g. SO51 — first half only, never the full house-level postcode) |
| What comes back | Current + 48-slot half-hourly carbon-intensity forecast for the relevant regional grid (~18 KB) |
| How often | Every 30 minutes when carbon-intensity tracking is enabled |
| Why | Drives the dashboard’s grid-carbon chart and the Carbon hot-water mode |
| Privacy policy | carbonintensity.org.uk — open data, no auth, no logging of identifying info |
| |
|---|
| Host | api.postcodes.io (HTTPS) |
| What’s sent | Your outward postcode (when you click “Use my weather location” on the Carbon card) |
| What comes back | The DNO region for that postcode (one of 14 GB regions) |
| How often | One-shot when you set up the carbon-intensity tracker |
| Why | The National Grid carbon API needs a regional ID, not a postcode — postcodes.io is the bridge |
| |
|---|
| Host | api.octopus.energy (HTTPS) |
| Account required | Yes — your Octopus account number + API key |
| What’s sent | Your account number (e.g. A-12345678) and API key as HTTP Basic auth, on calls to /v1/accounts/{account}/ and /v1/products/{slug}/electricity-tariffs/{tariff_code}/standard-unit-rates/ |
| What comes back | Your active tariff code, half-hourly or static rates |
| How often | On-demand when you click Look up, then every 30 minutes if you’re on Agile/Tracker (mode 4) |
| Stored on the device | Your API key (NVS-persisted, plaintext — same risk model as the WiFi PSK; mask-displayed in API responses as sk_live_***...abcd) and account number |
| Permissions used | Read-only — accounts:read + products:read. No write/billing access requested |
| Privacy policy | octopus.energy — the API only returns data on your own account |
| |
|---|
| Host | heatsync.dev (HTTPS) |
| Account required | No |
| What’s sent | Your running firmware version as a User-Agent: HeatSync/<version> header. The path of the manifest + binary, both public |
| What comes back | manifest.json (release metadata) + firmware.bin (~1.7 MB) |
| How often | Manifest check on demand (you press Check for updates on /config/firmware); optionally daily if auto-check is enabled. The binary downloads only when you press Install |
| Privacy policy | GitHub Privacy Statement — server-access logs may be retained per GitHub’s normal policy |
| |
|---|
| Hosts | pool.ntp.org + time.google.com (UDP, port 123) |
| What’s sent | Empty NTP request packet — IP-address-level only, no identifying payload |
| What comes back | Current UTC time |
| How often | Once at boot, then approximately hourly to correct drift |
| Why | The DHW scheduler needs accurate local time; the device has no battery-backed RTC |
- No analytics or telemetry. The device doesn’t phone home. There is no “HeatSync server” — Michael (the maintainer) can’t see who installed it, when, or how it’s running.
- No usage data. Sensor readings, set-points, fault codes — none of these are reported to any external service.
- No identifiers. The device doesn’t generate a UUID and broadcast it. The closest thing is the
User-Agent: HeatSync/<version> header sent to GitHub Pages on update checks, which doesn’t identify a particular device.
- No third-party tracking. No Google Analytics, no Mixpanel, no Sentry, no Datadog. The docs site (this one) uses GitHub Pages hosting + Pagefind for client-side search — neither involves third-party trackers.
- The full HTTPS call list lives in the source —
src/net/{weather,carbon,octopus,octopus_agile,updater}.cpp are the only files that open an outbound TLS connection. Search the repo for WiFiClientSecure to confirm.
- The device’s API surface is public — every endpoint is listed at
/config/api on your device or in the
HTTP API reference.
- The build is reproducible from MIT-licensed source. No closed-source
binaries shipped in the firmware (NimBLE + mbedTLS are vendored open
source).
- Octopus credentials: Settings → Data sources → Octopus → leave the
API key field empty and Save. The persisted key is overwritten with
empty string. The matching account number too.
- Weather location: Settings → Data sources → Weather → clear the
lat/lon and Save.
- Carbon-intensity postcode: Settings → Data sources → Carbon
intensity → toggle off + clear postcode + Save.
- Full factory reset: hold the Atom S3 Lite’s button at boot to
enter the captive-portal setup mode, then re-onboard with no API
key / postcode / lat-lon. The NVS partition holds everything else
(Wi-Fi PSK, MQTT password, API token) and that gets wiped on a
full NVS erase via
esptool.py erase_flash.
If you think HeatSync is sending data it shouldn’t, open an issue at
github.com/dr-harper/heatsync/issues
or grab a packet capture (tcpdump, Wireshark) on your router and
post the output. The full-source nature of the project means anything
unexpected is a bug, not a feature.