Skip to content

RFID Cat-Door Tracker — Project Plan & Build Guide

Use the RFID collar tags that came with the PetLibro feeder + Dockstream fountain to know, in Home Assistant, which cat went through the cat door and which way — in or out. An ESPHome microcontroller at the door reads the tag and publishes the passage to HA, which keeps each cat's indoor/outdoor status, fires a push notification, and logs the history.

Status: design + build guide (not yet built)

This is a project plan. It reuses the ESP32 dev board originally bought for the Food Temperature Sensor build — that project can run on a cheaper Wemos D1 mini instead, freeing this ESP32 for the cat door. Nothing here is wired or deployed yet. The one true unknown is the tag frequency/encoding — resolve Step 0 before buying a reader.


How it works

        OUTSIDE                CAT DOOR                INSIDE
                          ┌──────────────────┐
                          │   flap aperture   │
       cat approaches  →  │  ╔════════════╗  │  → cat enters
                          │  ║ RFID coil   ║  │
                          │  ║ antenna ring║  │     collar tag passes
                          │  ╚════════════╝  │     through the coil
                          │   IR beam OUT ─┐ │
                          │   IR beam IN  ─┘ │  ← "which beam first" = direction
                          └────────┬─────────┘
                                   │ USB power + WiFi
                              ┌────▼─────┐
                              │  ESP32   │  reads tag UID (who)
                              │ (ESPHome)│  + beam order (which way)
                              └────┬─────┘
                                   │ local ESPHome API
                            Home Assistant
              per-cat indoor/outdoor status · push alert · history
  1. As a cat passes through the flap, its collar tag couples with a coil antenna wrapped around the door aperture (the same trick SureFlap uses) → the reader emits the tag's UID.
  2. A tag UID maps to a cat (you pair each tag once).
  3. A cheap direction gate (two IR break-beams, or the simpler options below) tells in vs out.
  4. The ESP32 runs ESPHome, talks to HA over the local encrypted API (no cloud), and HA does the rest: updates each cat's status, notifies, and records the passage.

Step 0 — Identify your tag (do this FIRST)

Everything downstream (which reader to buy, the antenna, the firmware) depends on the tag's frequency and encoding. PetLibro states the collar tag "does not support microchips," which rules out the 134.2 kHz FDX-B pet-microchip standard and strongly points to a proprietary 125 kHz LF tag — but confirm before buying a reader.

How to identify it, easiest first:

Method What it tells you
Flipper Zero (125 kHz RFID → Read, then NFC → Read) The gold standard — reports frequency and protocol (EM4100 / HID / Indala / proprietary) and the raw UID. Borrow one if you can.
Phone NFC app (NXP TagInfo) If your phone reads it, it's 13.56 MHz (and an RC522 is your reader). If the phone sees nothing, it's low-frequency (125/134 kHz) — the likely case.
RDM6300 module ($3, 125 kHz EM4100) If this reads the tag, it's 125 kHz EM4100 and you're done — that's the cheapest, best-supported path. If it powers up but never reads the tag, the tag is 125 kHz non-EM4100 or 134.2 kHz.

If it's 125 kHz but NOT EM4100

Some proprietary 125 kHz tags (e.g. EM4305/T5577-style or vendor-custom encodings) won't read on an RDM6300. In that case use a 125 kHz multi-protocol reader (e.g. a module based on the EM4095 front-end with raw-bitstream output, or a Flipper as the reader) and a custom UART parser in ESPHome. Decide the reader after Step 0 — don't pre-buy.

The rest of this guide assumes the likely 125 kHz EM4100 outcome and notes where a different result changes things.


The hard part — telling "in" from "out"

A single RFID reader knows who, never which way. Pick one of these, simplest first:

One reader; each read flips the cat's status (was in → now out, and vice-versa). Zero extra hardware. Weakness: a cat that sniffs the door without going through, or a double-read, desyncs the state. Fine to prove the reader works; not trustworthy long-term.

One RFID reader for identity + two IR break-beam sensors (an emitter/receiver pair on each side of the tunnel, ~3 cm apart). The order the beams break = direction; the RFID read in the same window = which cat. Cheap, reliable, no false flips.

Two coil antennas/readers, one on the outer face and one on the inner face of the tunnel. Read order = direction and you get a confirmed RFID event on each side. Most robust, most wiring (two UARTs / two boards), trickiest antenna tuning to stop the coils interfering.

Recommendation: build the IR beam gate. It separates the two jobs — RFID = who, beams = which way — so each is simple and each is reliable. You can also cross-check passages against the new Cat Camera if it covers the door.


Bill of materials

Part Qty ~Cost Notes
ESP32 dev board (esp32dev) 1 Reused from the thermometer project. 3 hardware UARTs + plenty of GPIO — ideal here.
125 kHz RFID reader (RDM6300 if EM4100) 1 $3–6 Buy only after Step 0. RDM6300 is UART, ESPHome-native. Swap per your tag result.
Coil antenna wire (enamelled magnet wire, ~0.3 mm) 1 spool $6 Hand-wind the aperture coil; the RDM6300's stock antenna is too small for a doorway.
Tuning capacitor assortment (1–10 nF) 1 $5 Resonate the coil to 125 kHz (see Antenna).
IR break-beam sensor pair (3–5 mm, 5 V) 2 $3 ea The direction gate (recommended approach).
5 V USB charger + cable 1 $5 Continuous power — an RFID reader polling 24/7 is not a battery device.
Project box, magnet wire, dupont/heat-shrink $8 Weatherproof box if the door is exterior.

Total ≈ $30–45 on top of the reused ESP32. Borrowing a Flipper Zero for Step 0 saves buying the wrong reader.


Antenna — the make-or-break part

Low-frequency RFID has a short read range (a few cm), so the tag must pass close to the antenna. The reliable trick (how commercial cat flaps do it) is a coil ring around the flap aperture so the tag passes through the coil:

  • Wind ~30–60 turns of enamelled magnet wire in a flat ring framing the opening (tape it to the tunnel, or route through a slim 3D-printed channel).
  • The coil + a parallel capacitor form a tuned circuit; aim for resonance at 125 kHz. Start near the reader's recommended value and adjust the cap (1–10 nF range) for the strongest, most consistent read across the whole opening.
  • Keep the coil away from metal (metal detunes and shields it). If the door frame is metal, stand the coil off it.
  • Test read range with the actual collar tag at several heights/angles — the collar hangs under the chin, so the tag sweeps the lower third of the opening as the cat ducks through. Place the coil to catch that zone.

Tune for the worst case

A fast cat gives the reader only a fraction of a second. Tune for a solid read when the tag crosses the plane quickly and off-center, not just when held still in the middle.


Signal ESP32 pin Notes
RDM6300 TX → ESP32 RX GPIO16 (UART1 RX) Reader only transmits; ESP only needs RX.
RDM6300 VCC / GND 5 V / GND
IR beam OUTER receiver → GPIO18 Breaks first when a cat heads out.
IR beam INNER receiver → GPIO19 Breaks first when a cat heads in.
IR beam emitters VCC/GND 5 V / GND Align each emitter to its receiver across the tunnel.
ESP32 power 5 V USB

The coil antenna connects to the RDM6300's antenna terminals (with its tuning cap), not to the ESP32.


ESPHome firmware

Create the device in Home Assistant → ESPHome → New Device, named cat-door. Base config (same api/ota/wifi pattern as the food-temp build):

substitutions:
  name: cat-door
  friendly_name: Cat Door

esphome:
  name: ${name}
  friendly_name: ${friendly_name}

esp32:
  board: esp32dev

logger:                     # needed to read unknown tag UIDs on first pass
api:
  encryption:
    key: !secret cat_door_api_key
ota:
  - platform: esphome
    password: !secret ota_password
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "Cat-Door Fallback"
captive_portal:

uart:
  id: uart_rfid
  rx_pin: GPIO16
  baud_rate: 9600           # RDM6300 default

rdm6300:
  uart_id: uart_rfid

First pass — learn each cat's UID. With just the block above, flash the board, then wave each collar tag past the coil and read the ESPHome logs:

[rdm6300]: RDM6300 Tag: '1234567' (...)

Note the decimal UID per cat. Then add a binary_sensor per known tag plus the two direction beams:

binary_sensor:
  # ---- known cats (fill in real UIDs from the logs) ----
  - platform: rdm6300
    uid: 1234567
    name: "Cat Door  Mittens tag"
    id: tag_mittens
  - platform: rdm6300
    uid: 7654321
    name: "Cat Door  Smokey tag"
    id: tag_smokey

  # ---- direction gate ----
  - platform: gpio
    pin: { number: GPIO18, mode: INPUT_PULLUP, inverted: true }
    name: "Cat Door Beam Outer"
    id: beam_outer
  - platform: gpio
    pin: { number: GPIO19, mode: INPUT_PULLUP, inverted: true }
    name: "Cat Door Beam Inner"
    id: beam_inner

  - platform: status
    name: "Cat Door Status"     # online/offline health

Each tag_* turns on while its collar is in the field and off when it leaves — that's the per-cat passage signal HA keys on. The beams expose the direction. (Add the direction state-machine in ESPHome with globals + on_press if you prefer it on-device; doing it in HA, below, keeps it tweakable without re-flashing.)

If Step 0 said 134.2 kHz or non-EM4100

Replace the rdm6300 block with a uart: + a custom parser for your reader's frame format, exposing a text_sensor of the last UID. The HA logic below keys on UID either way.


Home Assistant integration

ESPHome auto-discovers — accept the device and you get binary_sensor.cat_door_mittens_tag, ..._smokey_tag, binary_sensor.cat_door_beam_outer/_inner, and binary_sensor.cat_door_status.

Add one indoor/outdoor helper per cat (in configuration.yaml):

input_boolean:
  cat_mittens_indoors:
    name: "Mittens  Indoors"
    icon: mdi:cat
  cat_smokey_indoors:
    name: "Smokey  Indoors"
    icon: mdi:cat

And a per-cat passage automation that reads direction from which beam broke last, sets the status, and notifies (one per cat; Mittens shown):

- alias: "Cat Door  Mittens Passage"
  id: cat_door_mittens
  triggers:
    - trigger: state
      entity_id: binary_sensor.cat_door_mittens_tag
      to: "on"
  action:
    - variables:
        # whichever beam is currently broken (or broke most recently) gives direction
        going_out: "{{ is_state('binary_sensor.cat_door_beam_outer','on') }}"
    - choose:
        - conditions: "{{ going_out }}"
          sequence:
            - action: input_boolean.turn_off
              target: { entity_id: input_boolean.cat_mittens_indoors }
            - action: notify.mobile_app_louis_iphone
              data:
                title: "🐈 Mittens went out"
                message: "Left through the cat door just now."
                data: { tag: "cat_door_mittens", group: "cat_door" }
        - conditions: "{{ not going_out }}"
          sequence:
            - action: input_boolean.turn_on
              target: { entity_id: input_boolean.cat_mittens_indoors }
            - action: notify.mobile_app_louis_iphone
              data:
                title: "🐈 Mittens came in"
                message: "Back inside through the cat door."
                data: { tag: "cat_door_mittens", group: "cat_door" }
  mode: single

Cross-check with the Cat Camera

If the Cat Camera sees the door, a binary_sensor.cat_camera_cat hit within a few seconds of a passage corroborates it — useful while you tune antenna reliability.


Useful automations to layer on

  • "Out too long" at night — if any cat_*_indoors is off after, say, 10 PM for > 2 hours, notify both phones (mirrors the household alert style in Notifications).
  • Everyone-in confirmation — a bedtime check: announce which cats are still out.
  • Door-left-ajar / stuck-open — if a beam stays broken for minutes, the flap may be propped; alert.
  • Curfew nudge — at dusk, if a cat is out, ping a reminder.

Dashboard

Add a Cat Door card to the Command dashboard (or the Cat Camera area): a per-cat row showing 🏠 In / 🌳 Out from input_boolean.cat_*_indoors, the last passage time, and a mini logbook of recent in/out events. Pairs naturally next to the Cat Camera tile.


Power, mounting & weatherproofing

  • Continuous 5 V USB — the reader polls constantly; batteries are a non-starter. Run a USB cable to the nearest outlet.
  • Mount the ESP32 in a project box beside the door; keep the coil at the aperture and the box away from the metal frame.
  • Exterior door: use a weatherproof (IP65) box, gland the cable, and keep the ESP32 above any splash line. Confirm WiFi reaches the door (same check as the food-temp build — a dead spot means relocating a mesh node).

Phased build plan

  1. Step 0 — identify the tag. Don't buy a reader until you know frequency + encoding.
  2. Bench the reader. Wire RDM6300 → ESP32, flash the base config, confirm it reads each collar tag in the logs; record UIDs.
  3. Build & tune the coil for reliable reads across the whole aperture at speed.
  4. Add the direction gate (two IR beams) and confirm beam order tracks direction.
  5. Pair in HA, add the per-cat helpers + passage automations; verify in/out status flips correctly.
  6. Mount at the door, weatherproof, confirm WiFi, live-test with the cats.
  7. Tune antenna position and debounce until misses/double-reads are rare; then add the night/curfew automations and the dashboard card.

Risks & open questions

  • Tag frequency/encoding (Step 0) — the single biggest unknown. PetLibro saying it "does not support microchips" implies a proprietary 125 kHz tag; verify before buying a reader.
  • Read reliability at speed — LF range is short; a fast or off-center cat can be missed. Antenna tuning and coil placement are where the time goes. The beam gate degrades gracefully (you still get a direction event even on an RFID miss; you just won't know which cat that once).
  • Two cats at once — rare through a small flap, but the logic should handle near-simultaneous reads (per-tag binary_sensors already separate them).
  • Tag wear / loss — collars use a 6.6 lb snap-release, so a tag can pop off outdoors. A long "out" with no return is worth an alert anyway.
  • Proprietary lock-in — if the PetLibro tag turns out to be an unreadable custom protocol, fallback options: add a cheap standard 125 kHz EM4100 tag to each collar alongside the PetLibro one, or switch to implantable-microchip reading (134.2 kHz FDX-B) if the cats are chipped.

Future expansion

  • Selective entry — drive a servo/latch so only known tags unlock the flap (DIY SureFlap).
  • Per-cat analytics — time-outdoors trends in Grafana, like the energy/circuit panels.
  • Litter / feeding correlation — combine cat-door passages with the PetLibro feeder/fountain data for a fuller activity picture.
  • Multi-door — replicate the rig at a second door; HA already tracks per-cat state centrally.

Related pages: Cameras · Notifications & Alerts · Automations Reference · Food Temp Sensor Build · Hardware Inventory