Skip to content

Neighbourhood Comparison

ha-taggle edited this page Nov 2, 2026 · 4 revisions

Neighbourhood comparison

New in 0.2.0. On by default.

Neighbourhood comparison is on by default. It shows group figures from nearby meters your receiver can hear, once enough qualify. Their litres per pulse are unknown. If your first configured meter is calibrated, the comparison assumes the same litres per pulse for neighbours; displayed litres are estimates. This is a rough comparison, not a ranking of household efficiency.

With default logging, neighbour IDs are not written to state, JSONL or MQTT. Scan output prints heard IDs, and enabling both log_all_meters and jsonl_logging writes IDs into private JSONL summaries. Keep those outputs private. To stop collection, disable it in the receiver and restart; hiding the card row only changes the display.

On the card it looks like this (fictional numbers):

Today 370 L · Neighbourhood avg 410 L · 10% below
Median 350 L · 14 homes

The card currently labels qualifying meters as “homes”; it does not identify households.

How the privacy works

Important

Short version: neighbours' IDs are scrambled the moment they're heard. Only group figures over at least 3 qualifying meters are published. You can turn it off, and turning it off deletes the stored data.

  1. IDs are scrambled immediately. To track each neighbour's counter from hour to hour, ha-taggle needs some label for each one. It uses an HMAC, a keyed one-way scramble (HMAC-SHA256), of the decimal ID, cut to 16 hex characters. Saved neighbour state uses these opaque keys. Scan output and explicitly enabled JSONL logging can contain real IDs, as described above.
  2. The key is unique to your install. The key ("salt") is 32 random bytes made on first run. It's saved as neighbourhood.salt in your data folder, readable only by the receiver (file mode 0600), and never published. Two installs scramble the same neighbour differently, so their labels can't be matched up.
  3. Only group figures leave the receiver. Home Assistant gets one Taggle neighbourhood device with five aggregate sensors. There are no per-neighbour entities, and no neighbour IDs in MQTT topics, payloads, attributes, default logs or state.json. Explicit broad JSONL logging is the exception described above.
  4. Minimum of 3 meters per group. Each figure stays unknown until at least neighbourhood_min_meters meters qualify. The add-on accepts integers of 3 or greater; standalone configuration clamps lower integers to 3. Raise it for a larger minimum. This k-anonymity floor prevents aggregates over fewer than three meters.
  5. Old data is pruned. A neighbour not heard for more than 7 days is deleted, both at startup and during operation. state.json stores neighbours only under their opaque tracking keys.
  6. Your own meters are always excluded from the neighbourhood group.
  7. Encrypted meters count towards "meters heard" only. Their usage is unknown, so they're left out of averages.

Note

Two existing exceptions are unchanged. Scan mode still prints every heard ID, because that's how you find your own. log_all_meters: true (off by default) still lets other IDs into JSONL logs if jsonl_logging is on. Leave it off.

Warning

Keep your data folder private. It holds the salt and the scrambled labels. They aren't public identifiers, but don't share them.

Turning it off

Install Setting
Add-on Set neighbourhood: false in add-on options, Save, then restart Taggle water meter
Docker Set "neighbourhood": false in config.json, save, then run docker compose restart taggle from the receiver repository
Python Set "neighbourhood": false in config.json, save, then stop and restart the receiver process

On startup this deletes the neighbour state and the salt. On MQTT reconnect it removes neighbourhood discovery and retained aggregate state from Home Assistant. Your own meter's data is kept.

To just hide the card row, use neighbourhood: false on the card. Collection keeps running in that case.

Settings

Option Default Meaning
neighbourhood true Turn the feature on or off
neighbourhood_min_meters 3 Privacy floor (minimum qualifying meters per figure). Can be raised, never below 3.
neighbourhood_litres_per_count unset An assumed litres-per-pulse for neighbours (see below)

The sensors

Home Assistant may rename these. Check under the Taggle neighbourhood device.

Entity Unit Meaning
sensor.taggle_neighbourhood_meters_heard meters Different other meters heard in the last 24 h, including encrypted ones
sensor.taggle_neighbourhood_meters_counted meters Clear neighbours that qualify for today
sensor.taggle_neighbourhood_average_today L or pulses Average observed use today across qualifying neighbours
sensor.taggle_neighbourhood_median_today L or pulses Median of the same totals
sensor.taggle_neighbourhood_average_last_hour L or pulses Average of each clear neighbour's latest interval ending within the last 2 h
sensor.taggle_123456_vs_neighbourhood_today % Your use today ÷ neighbourhood average × 100. 100% = the same as average.

The averages and median use the measurement state class, never total_increasing. They're not Energy totals.

Who "qualifies" for today?

A neighbour counts towards today's average only once ha-taggle has recovered at least 6 hourly intervals today, and at least 75% of the hours elapsed since midnight. For example, at 08:00, six intervals is enough. A minute later, it needs a seventh.

Unrecovered intervals are never estimated or scaled up. A later frame can recover a single missed transmission. A neighbour with 20 of 24 hours shows 20 hours' worth. Just after midnight the figures reset and may show unknown until enough data arrives.

Litres or pulses?

ha-taggle can't know your neighbours' litres per pulse. It does this:

  1. If you set neighbourhood_litres_per_count, it uses that.
  2. Otherwise, if your first meter in meter_ids is calibrated, it assumes neighbours use the same litres per pulse.
  3. Otherwise it shows pulses.

Note

This assumption is unverified. Even nearby meters can use different litres per pulse. Calibrating your meter does not calibrate neighbours, and a shared council or similar appearance is not evidence of a shared pulse size.

Calibrating your first configured meter therefore also changes the default neighbourhood display to assumed litres. An explicit neighbour litres-per-pulse setting overrides that fallback; it does not calibrate any individual neighbour.

The card hides its percentage when displayed units differ or the average is zero. Receiver 0.3.0 limitation: if the first configured meter is uncalibrated and a later meter is calibrated, MQTT can still publish a raw-pulse vs_neighbourhood_today percentage for that later meter while the neighbourhood remains in pulses. Do not interpret it as a litres comparison. With assumed neighbour litres and an uncalibrated own meter, the receiver publishes no percentage.

Caveats: read before you compare

  • It's who you can hear, not a survey. Strong, nearby signals are over-represented. Your "neighbourhood" might be one side of the street.
  • Average vs median. One leaking neighbour can drag the average up. The median (the middle value) barely moves, so the card shows both.
  • Partial days stay partial. Everyone's "today" is what was heard, not a full day.
  • Household size differs. A family of six and a single person aren't comparable.
  • Experimental. It isn't billing data or a leak detector.

Technical detail: cohorts, timing and MQTT

Each aggregate applies the privacy minimum to its own cohort (the meters qualifying for that particular figure): meters heard in the last 24 hours, clear neighbours qualifying for today, or clear neighbours with a recent interval for last hour. Even the heard/counted counts stay unknown below their own floor. Today's average, median and counted count use the same daily cohort. The last-hour average independently uses each clear neighbour's most recent interval ending within the last two hours; it does not require today's coverage qualification.

Today's six-interval and 75% requirements use observed intervals ending on the current local date, and elapsed local clock hours including fractional hours. Totals follow the same counter-wrap handling, overlap deduplication, gap handling and local interval-end date as your own meter. They are recomputed every minute; the daily cohort resets at midnight.

Discovery is retained under homeassistant/sensor/, with one Taggle neighbourhood device and default state topic taggle/neighbourhood/state. Stable default entity IDs are listed above; existing registry IDs and user renames are preserved, and collisions may add a suffix. See Configuration reference for all option ranges.

Further reading

Clone this wiki locally