ibags

A $2 buttonless BLE keyfinder rides in your bag. Home Assistant knows which room the bag is in, whether it left home, and can beep it on demand — no cloud, no vendor app, no idle connections.

☁︎ no cloud 📵 no vendor app 🏠 Home Assistant 📦 HACS ⚖︎ AGPL-3.0

The $2 bag tracker

The same Telink-family "iTAG" keyfinder as its sister project itags — but the buttonless variant: a coin cell, a beeper, and a radio. Nothing to press, nothing to pair, no app. Zip it into a bag and forget it exists.

Which inverts the interesting problem. A button tag must be connected to, permanently, or the button is dead. A bag tag's whole job is presence — and presence comes free with its advertisements. So this integration does the opposite of its sister: it never holds a connection it doesn't need.

No button, no app — a beeper and a radio in a bag, advertising away.

📍The elegant core: connect-then-release

Every ESPHome Bluetooth proxy that hears the tag advertise becomes a room vote. The strongest fresh signal wins — with hysteresis, so the room doesn't flip-flop when the bag sits between two proxies:

score = rssi − age_penalty × seconds_since_heard, and a challenger proxy must beat the incumbent by 8 dBm to steal the room. A connected BLE peripheral stops advertising — so the integration opens a GATT link only to beep or read the battery, then lets go. Presence stays passive, the coin cell stays happy, and no proxy ever loses an active-connection slot to an idle link.
 tag advertises ─▶ Laundry proxy   rssi −74 · 2s ago  ┐
                ─▶ Kitchen proxy   rssi −85 · 6s ago  ├─▶  strongest fresh advert = "the room"
                ─▶ Bedroom proxy   rssi −88 · 4s ago  ┘    (challenger needs +8 dBm to win)

 "find the bag" ─▶ connect ─▶ silence link-loss ─▶ beep 1802/2A06=0x01 ─▶ stop ─▶ release

🎒 Home / away that matters

A real device_tracker entity: home while any proxy hears the bag, away when the house goes quiet — ready for "you left without your bag" automations. A frozen last seen timestamp tells you when it left.

🔔 Find-my, held politely

Find connects, disarms the tag's link-loss alarm (1803/2A06 → 0x00) so a dropped link can't false-beep, then writes the beep. The link is held only while ringing — silence it and the tag goes back to advertising.

🔋 Battery, silently

A daily automatic read (and an on-demand button) connects, reads 180F/2A19, and releases — without ever beeping the bag at 4 a.m. Variants without a battery service are probed once and left alone.

🧭 No calibration

No trilateration, no surveyed anchors, no reference powers. Room = the proxy that hears it best, which is exactly the granularity a bag needs.

🧩Two ways to run it

🎯 The native integration · start here

A custom ibags integration with a config flow and Bluetooth auto-discovery through Home Assistant's own stack — it works over your existing ESPHome BLE proxies, no local adapter required. You get the device_tracker, room / last-seen / battery / signal sensors, Find / Stop beep buttons, and ibags.find / ibags.stop / ibags.read_battery services.

🛰️ The ESPHome node · alternative

Prefer the ring logic on the ESP32 itself? esphome/ibags-ring-node.yaml implements the same connect-then-release dance in firmware — a ring-intent flag splits beeping connects from silent battery reads — plus an example HA package and dashboard for wiring it up. Pairs with room presence from Bermuda if you already run it.

🔬The tag, over GATT

Advertisements carry presence for free; everything else lives behind a short-lived connection.

ServiceCharDoesOn this tag
1802 Immediate Alert2a06 Beep — write 0x01 / 0x00✔ find-my
180f Battery2a19 Battery % — read✔ daily silent read
1803 Link Loss2a06 Beeps on link drop unless 0x00✔ disarmed on every connect
ffe0 vendor (Telink)ffe1 Button press — notify✘ dormant (no button — see itags)

Note 0x2A06 exists under both 1802 and 1803 — it must always be resolved through its parent service. MACs in the repo are placeholders like FF:FF:AA:BB:CC:DD; these tags use a static-random address that can rotate after a battery swap.

📂What's in the repo

custom_components/ibags/The native Home Assistant integration — config flow, Bluetooth auto-discovery, device_tracker + room/battery/last-seen sensors, find/stop beep.
esphome/ibags-ring-node.yamlThe on-device alternative: connect-then-release ring + silent battery read as ESP32 firmware.
ha-packages/bags_tag.yamlExample package for the ESPHome-node path — friendly wrapper sensors, ring scripts, daily battery poll.
dashboards/An example "iBags" dashboard — location, ring/silence, coverage per proxy, battery, history.

Quick start

Install through HACS as a custom repository, then let HA discover the tag:

HACS → ⋮ → Custom repositories
  Repository:  https://github.com/jphein/ibags
  Category:    Integration

# then, in Home Assistant:
Settings → Devices & Services → Add Integration → "iBags"
#   → auto-discovers tags seen by your ESPHome BLE proxies
#   → or type the tag's MAC address directly

Or one tap: add this repository to HACS →

📣Share this project

On a phone, “Share…” opens your native share sheet — Instagram, WhatsApp, Messenger and friends live there.