~/jackwent.co.uk
jack@jackwent:~$ cat rfid-films.yaml

RFID Cards That Start Films

published 7 October 20263 min read

Streaming menus are hard work for small children. Too many rows, too many buttons, and a remote that somehow always ends up down the back of the sofa. So we made films physical again.

There’s an RFID reader by the TV and a stack of cards, one per film. Tap a card on the reader and the film starts playing on the living room TV from our Plex server. We’re up to 32 cards now.

The hardware

  • An ESP32 with an RFID reader, running ESPHome. It reads the unique ID of any card you tap and sends it to Home Assistant as a sensor called Last RFID UID.
  • Blank RFID cards that match your reader (most cheap readers use 13.56MHz cards). Print the film’s poster and stick it on the front so little ones can pick by picture.
  • A Chromecast on the TV, which Home Assistant can send media to.
  • Plex, with the Plex integration set up in Home Assistant so it can browse the film library.

Finding each card’s ID

Tap a new card on the reader, then look at the Last RFID UID sensor in Home Assistant. It’ll show something like A1-B2-C3-D4. That’s the ID you’ll use in the automation. Do the same for each card.

The automation

Each card gets a trigger with its ID as the trigger id, and a matching action that plays the film. Here it is with two films. Mine just has thirty more of each.

alias: RFID play films
mode: single
triggers:
  - trigger: state
    entity_id: sensor.rfid_reader_last_rfid_uid
    to: "A1-B2-C3-D4"
    id: the-bad-guys
  - trigger: state
    entity_id: sensor.rfid_reader_last_rfid_uid
    to: "E5-F6-A7-B8"
    id: sing
actions:
  - alias: Wake the Chromecast if it's asleep
    if:
      - condition: state
        entity_id: media_player.living_room_chromecast
        state:
          - "idle"
          - "off"
          - "standby"
    then:
      - action: media_player.turn_off
        target:
          entity_id: media_player.living_room_chromecast
      - delay:
          seconds: 3
      - action: media_player.turn_on
        target:
          entity_id: media_player.living_room_chromecast
  - choose:
      - conditions:
          - condition: trigger
            id: the-bad-guys
        sequence:
          - action: media_player.play_media
            target:
              entity_id: media_player.living_room_chromecast
            data:
              media:
                media_content_type: movie
                media_content_id: plex://YOUR-SERVER-ID/20225
      - conditions:
          - condition: trigger
            id: sing
        sequence:
          - action: media_player.play_media
            target:
              entity_id: media_player.living_room_chromecast
            data:
              media:
                media_content_type: movie
                media_content_id: plex://YOUR-SERVER-ID/20004

Getting the Plex ID

The easiest way to find the media_content_id for a film is to let Home Assistant write it for you. Add a Play media action in the visual editor, pick the Chromecast, browse to the film in your Plex library, then switch to YAML mode and copy what it filled in.

When you do, you’ll notice the visual editor also saves a metadata block with a thumbnail URL. That URL contains your Plex token, which is effectively a password for your Plex server. It isn’t needed for playback, so I’d delete the whole metadata block, especially if you ever share your YAML online.

The Chromecast wake-up

The first action deals with a quirk. If the Chromecast has been sitting idle for a while, it sometimes ignores the first play_media call. Turning it off and on again first, only when it isn’t already playing, wakes it up properly so the film starts first time. It’s the oldest fix in IT and it still works.

If I built it again

It works well, but there are two things I’d do differently with hindsight:

  • Use Home Assistant tags instead of a sensor. ESPHome can send a proper tag_scanned event, and Home Assistant has a built-in Tags page where you name each card. You then trigger on the tag rather than a sensor value. The catch with the sensor approach is that a state trigger only fires when the value changes, so tapping the same card twice in a row may do nothing unless the reader clears the value in between.
  • One mapping instead of 32 triggers. A single trigger on any new card plus a lookup table of card ID to film would be much shorter than one trigger and one action per film. Adding a film would be one line instead of two blocks.

Even so, it’s a lovely first ESPHome project if you’ve got kids.

[jackwent]