NFC-видеотека для моих детей

от автора


В детстве у нас с сестрой была гора VHS-кассет, которые мы бесконечно пересматривали. Современная видеоколлекция моих детей сильно от них отличается. Она полностью цифровая и разбросана по разным сервисам. Я хотел поделиться с ними магией осязаемости носителя из моего детства.

У меня двое пацанов, старшему разрешается посмотреть полчаса телевизор с утра и ещё полчаса вечером. Обычно он точно знает, что хочет посмотреть, но ему приходится ждать, пока кто-то из родителей возьмёт пульт и откроет нужное приложение.

Это заставило меня задуматься: почему бы не объединить новое и старое? Я хотел, чтобы у сына была более активная роль в выборе того, что он хочет посмотреть, несмотря на цифровой формат.

Несколько лет назад я увидел, как кто-то распечатал любимые музыкальные альбомы с NFC-меткой внутри, и решил сделать что-то подобное для своих детей.

▍ Конечный результат

Вот, что я в результате создал:

Это коллекция ламинированных обложек фильмов и мультфильмов с NFC-меткой внутри. Сыну остаётся только выбрать нужный фильм и положить его на считыватель NFC. Всем остальным займётся Home Assistant.

Вот видео того, как работает система:

▍ Proof-of-concept и материалы

Я начал с изготовления простого прототипа. В одном из моих наборов электроники нашёлся считыватель NFC (RC522) и несколько NFC-меток.

Я подключил считыватель NFC к плате ESP32 и прошил на неё ESPHome. Затем я положил NFC-метку на считыватель и увидел, что она появляется в логах ESPHome.

И это всё, что мне нужно было проверить. Я зашёл на AliExpress и купил оборудование для «продакшена»:

У меня уже было множество плат ESP32 (LOLIN32 lite), но когда я увидел версию Super Mini, то обязан был её купить. Посмотрите на эту красоту:

▍ Прошиваем ESPHome

Когда все детали прибыли, я подключил считыватель NFC к ESP32 с помощью следующих контактов:

SS (SDA) -> GPIO7
SCK (SCK) -> GPIO4
MOSI -> GPIO6
MISO -> GPIO5

Ещё я добавил динамик, чтобы можно было издавать писк при успешном сканировании метки.

Затем я создал файл конфигурации ESPHome. Мне пришлось добавить несколько особых platformio_options, чтобы он заработал на версии ESP32 Super Mini, но в целом это оказалась очень простая конфигурация.

--- substitutions:   devicename: "nfc-scanner"   friendly_name: "NFC Scanner"  packages:   esphome: !include common/esphome.yaml   api: !include common/api.yaml   logger: !include common/logger.yaml   wifi: !include common/wifi.yaml  esphome:   # Магические переменные, необходимые, чтобы заработала ESP32C3 Super Mini   platformio_options:     board_build.f_flash: 40000000L     board_build.flash_mode: dio     board_build.flash_size: 4MB   on_boot:     priority: 600     then:       - rtttl.play: 'short:d=4,o=5,b=100:16e6,16e6'  esp32:   variant: ESP32C3   board: esp32-c3-devkitm-1   framework:     type: esp-idf  status_led:   pin:     number: GPIO8     inverted: true  output:   - platform: ledc     pin: GPIO3     id: buzzer  rtttl:   output: buzzer  spi:   clk_pin: GPIO4   mosi_pin: GPIO6   miso_pin: GPIO5  rc522_spi:   cs_pin: GPIO7   on_tag:     then:       - rtttl.stop:       - homeassistant.tag_scanned: !lambda 'return x;'       - rtttl.play: 'short:d=4,o=5,b=100:16e6,16e6'

Если вы будете собирать устройство самостоятельно, то необязательно использовать те же номера контактов.

Моя старая конфигурация ESPHome для LOLIN32 Lite

--- substitutions:   devicename: "nfc-scanner"   friendly_name: "NFC Scanner"  packages:   esphome: !include common/esphome.yaml   api: !include common/api.yaml   logger: !include common/logger.yaml   wifi: !include common/wifi.yaml  esphome:   platform: ESP32   board: lolin32   on_boot:     priority: 600     then:       - rtttl.play: 'short:d=4,o=5,b=100:16e6,16e6'  output:   - platform: ledc     pin: GPIO32     id: buzzer  rtttl:   output: buzzer  spi:   clk_pin: GPIO18   mosi_pin: GPIO23   miso_pin: GPIO19  rc522_spi:   cs_pin: GPIO15   on_tag:     then:       - rtttl.stop:       - homeassistant.tag_scanned: !lambda 'return x;'       - rtttl.play: 'short:d=4,o=5,b=100:16e6,16e6'

После завершения прошивки ESPHome устройство отобразится в Home Assistant, но без записей. Не нужно паниковать, это нормально. Оно будет отправлять события tag_scanned. Подробнее об этом я расскажу позже, когда мы всё автоматизируем.

▍ 3D-печать корпуса и коробки для видеоколлекции

Чтобы защитить электронику и провода от шаловливых детских ручек, я спроектировал и распечатал простой корпус.

Это корпус

У него очень простая конструкция. Единственная сложность возникла с креплением ESP32. В отличие от других плат разработки, у ESP32C3 Super Mini нет отверстий под винты, поэтому я спроектировал простой механизм с зажимами.

Не волнуйтесь, ESP32 не висит в воздухе. Он опирается на припаянные контакты GPIO внизу корпуса.

Для проектирования и компоновки всех деталей я использовал Fusion360 (благодарю Ханса Вурста за публикацию модели Super Mini на GrabCAD).

Смоделировав каждую деталь, можно проверить, хорошо ли они сочетаются друг с другом

Ещё я распечатал красивую коробочку для хранения NFC-карт:

▍ Создание карт «DVD»

После завершения разработки считывателя мне оставалось лишь изготовить карты «DVD». Я хотел печатать непосредственно на ПВХ-картах, но мой принтер на это неспособен.

Поэтому я выбрал чуть менее оптимальный вариант: купил виниловую бумагу для наклеек и распечатал обложки на ней.

Затем я вырезал наклейки и приклеил их на ПВХ-карты.

Ещё я задизайнил обратную сторону карт, на которой изложен краткий сюжет фильма, дата выпуска и студия.

Первую версию карт я просто распечатал на принтере и ламинировал

Я распечатал небольшие обложки фильмов в формате буклета, засунул внутрь NFC-метки, а потом ламинировал их.

Буклет защищал NFC-метку и позволял извлечь её в будущем.

▍ Автоматизация Home Assistant

И последняя часть проекта: создание автоматизации Home Assistant, которая будет воспроизводить нужный фильм после сканирования метки.

Мы храним фильмы в Plex и воспроизводим их через Apple TV. В Plex есть два способа воспроизведения видео:

По моему опыту, интеграция Plex слишком неудобна и ненадёжна. Нужно включить Apple TV, запустить приложение Plex и дождаться, пока оно станет доступным в Home Assistant; лишь после этого можно отправить команду воспроизведения конкретного фильма.

Интеграция с Apple TV работает практически мгновенно. Достаточно лишь отправить «глубокую ссылку»!

Формат «глубоких ссылок» (deep link) задокументирован на форуме Plex, он довольно прост. Вот «глубокая ссылка» для воспроизведения медиа:

plex://play/?metadataKey=UNIQUE_MEDIA_ID&server=SERVER_ID

ID сервера Plex можно найти на этой странице или поискав clientIdentifier вашего сервера.

Дальше мне нужно было понять, какие данные ESPHome отправляет Home Assistant при сканировании метки. Я открыл Developer Tools в Home Assistant и начал прослушивать события tag_scanned. Положив метку на считыватель, я увидел событие:

event_type: tag_scanned data:   tag_id: 1D-20-E2-06-96-00-00   device_id: a93f971bb9622b266286460c3f2ac640 origin: LOCAL time_fired: "2023-11-13T14:57:06.765528+00:00" context:   id: 01HF4JZB6DHY26TWZ903Z01BJ9   parent_id: null   user_id: null

Самое интересное здесь — это tag_id. Этот ID я сопоставил с ID фильма в Plex.

Вот как выглядит полная автоматизация:

- alias: "NFC Reader - Plex"   description: ""   mode: single   trigger:   - platform: event     event_type: tag_scanned    # Разрешаем воспроизводить фильмы только по утрам и вечерам.   # Широкое временное окно, чтобы обеспечить гибкость расписания.   condition:   - condition: or     conditions:     - condition: time       after: '05:00:00'       before: '09:00:00'     - condition: time       after: '18:00:00'       before: '19:50:00'  # Пора спать!   action:   - variables:   # Сопоставляем ID каждой метки с Plex ID. Атрибут "name"   #  не используется, но удобен для отладки.       NFC_MAPPING:         53-77-08-69-71-00-01:           name: Ratatouille           plex_id: 37353         53-72-08-69-71-00-01:           name: Coco           plex_id: 3135         04-D3-F2-FD-9F-61-81:           name: Bing           playlist_id: 4586         04-36-F6-32-5F-61-80:           name: Bumba           playlist_id: 4587 # ...    - if:     # Проверяем, находится ли отсканированная метка в mapping     - alias: "NFC tag is in the mapping"       condition: template       value_template: "{{ trigger.event.data.tag_id in NFC_MAPPING }}"     then:     # Включаем Apple TV (и сам телевизор), когда он находится в режиме ожидания     - if:       - condition: state         entity_id: media_player.appletv_living         state: standby       then:       - service: media_player.turn_on         data: {}         target:           entity_id: media_player.appletv_living       - delay:           seconds: 5      # Если сопоставленная метка имеет "plex_id", то воспроизводим его как фильм.     - if:         - condition: template           value_template: "{{ \"plex_id\" in NFC_MAPPING[trigger.event.data.tag_id] }}"       then:         - action: media_player.play_media           data:             media_content_type: url             media_content_id: >-               plex://play/?metadataKey=%2Flibrary%2Fmetadata%2F{{NFC_MAPPING[trigger.event.data.tag_id].plex_id}}&server=xxxxxxxxxxxxxx         target:           entity_id: media_player.appletv_living        # Если сопоставленная метка имеет "playlist_id", воспроизводим случайный пункт из плейлиста.     - if:         - condition: template           value_template: "{{ \"playlist_id\" in NFC_MAPPING[trigger.event.data.tag_id] }}"       then:         - action: media_player.play_media           data:             media_content_type: url             media_content_id: >-               plex://play/?metadataKey=%2Fplaylists%2F{{NFC_MAPPING[trigger.event.data.tag_id].playlist_id}}&server=xxxxxxxxx         target:           entity_id: media_player.appletv_living  # Устанавливаем подходящую (низкую) громкость на Sonos Beam # При работе с динамиком eARC элементы управления громкостью # Apple TV поддерживают только команды вверх/вниз.     - service: media_player.volume_set   data:     volume_level: 0.17   target:     entity_id: media_player.sonos_tv

Автоматизация проста и быстра. Apple TV требуется примерно пять секунд, чтобы включить телевизор, запустить приложение Plex и начать воспроизводить через него нужный фильм.

Я был впечатлён! И мой старший сын тоже. Он сразу понял, что можно использовать эту систему в любое время. Я стремился не к этому, поэтому добавил условие, позволяющее запускать автоматизацию только по утрам и вечерам.

Apple TV поддерживает «глубокие ссылки» и для других сервисов. Вот примеры для самых популярных сервисов потокового воспроизведения:

  • Netflix (используется обычный URL):
    • https://www.netflix.com/title/80234304

  • Disney+ (используется обычный URL):
    • https://www.disneyplus.com/movies/coco/db9orsI5O4gC

  • YouTube (используется обычный URL, в котором https:// заменено на youtube://)
    • Отдельное видео: youtube://www.youtube.com/watch?v=ah3ezprtgmc
    • Плейлист: youtube://www.youtube.com/watch?v=v=FkUn86bH34M&list=PLzvRQMJ9HDiQF_5bEErheiAawrJ-2zQoI&pp=iAQB

Единственная проблема с этими сервисами заключается в том, что перед началом воспроизведения они требуют выбрать профиль. В случае Plex можно включить «auto login», но для других сервисов я этого не пробовал.

▍ Воспроизведение случайных эпизодов

У меня возникла проблема с «глубокими ссылками» Plex — невозможность воспроизведения случайного эпизода сериала. Я обошёл эту трудность, просто не став делать NFC-карты для сериалов, к разочарованию моих сыновей.

Спустя пару месяцев после разработки этой системы я нашёл пост на форуме Plex о том, что можно создавать умные плейлисты, перемешивающиеся при каждом открывании. И это работало даже с «глубокими ссылками»!

То есть, решить проблему оказалось довольно просто: создать «умный плейлист» в Plex. Перейти в библиотеку (фильм или сериал) и изменить значение первого раскрывающегося меню с «All» на «Advanced Filters».

Далее нужно сконфигурировать фильтры. Я создал по одному умному плейлисту для каждого сериала, но можно и перемешивать разные сериалы.

Затем я поменял порядок сортировки с «Title» на «Randomly». После этого Plex будет перемешивать плейлист при каждом открытии, в том числе и при переходе по «глубокой ссылке»!

ID плейлиста можно найти, перейдя к плейлисту в Plex Web UI и скопировав URL:

http://192.168.2.1:32400/web/index.html#!/server/{SERVER_ID}/playlist?key=%2Fplaylists%2F{PLAYLIST_ID}&context=source%3Acontent.playlists.video~0~0

«Глубокая ссылка» для плейлиста немного отличается от ссылки для фильма:

plex://play/?metadataKey=%2Fplaylists%2F{PLAYLIST_ID_GOES_HERE}&server={ЗДЕСЬ_SERVER_ID}

▍ Дальнейшее развитие проекта

Меня впечатлила даже первая версия, но в будущем я бы хотел кое-что изменить.

Во-первых, я хочу заменить считыватель NFC на PN532. Он намного меньше и позволит сделать корпус поменьше.

▍ Почему физические носители — это здорово

Почему же я заморочился всем этим, чтобы у моих детей было что-то осязаемое? Мне кажется, у такой системы есть множество преимуществ.

Первое: ограниченный выбор фильмов. В детстве у меня не было бесконечного каталога фильмов, только с десяток VHS-кассет и DVD. Мы смотрели одни и те же фильмы снова и снова, каждый раз обнаруживая новые детали, которые бы в противном случае упустили.

Второе: это даёт моим детям независимость. Они сами могут решать, что хотят посмотреть, не прося нас брать пульт и запускать приложение. Они просто подходят к коробке с картами, выбирают фильм и включают его. Точно так же, как мы делали с VHS и DVD.

Третье: свобода порождает ответственность. Мы разрешаем им смотреть телевизор в определённые часы. Они могут смотреть любой фильм, даже переключаться между ними. Но временной промежуток ограничен. Они могут посмотреть большую часть одного фильма или понемногу из десяти фильмов. Выбор полностью за ними.

Наконец, у нас есть только один телевизор и два получасовых интервала на его просмотр. То есть им придётся учиться договариваться и идти на компромиссы. Они должны быстро выбрать фильм, или потерять это время просмотра. Или, например, подойти к этой задаче творчески и придумать систему, определяющую, кто будет выбирать фильм: ты можешь выбирать утром, я выбираю вечером.

Я не могу подтвердить все эти утверждения доказательствами или исследованиями. Но я искренне верю, что это поможет им освоить ценные навыки. И я считаю, что это намного лучше, чем давать детям неограниченный доступ к Netflix, Disney+, YouTube или любому другому потоковому сервису.

▍ Я ненавижу потоковые сервисы?

Конечно, нет. У меня уже много лет есть подписка на Spotify, и время от времени я подписываюсь на другие потоковые сервисы. Дело в том, что я смотрю не так много фильмов и сериалов, так что их стоимость себя не оправдывает.

Вместо них я покупаю любимые фильмы на Blu-ray и сохраняю их на сервер Plex. Это даёт мне три важных преимущества.

Во-первых, мой сын снова и снова смотрит одни и те же фильмы (особенно мультфильмы Pixar). Подписка на Disney+ стоит €10,99 в месяц, но за такую цену я могу купить с рук 3-4 диска Blu-ray. Они очень дешёвые, а после покупки диска он ваш навечно.

Во-вторых, на дисках Blu-ray есть множество дополнительного контента. Особенно мне нравятся разделы «За кулисами» («behind the scenes») и «Удалённые сцены» («deleted scenes»), которые есть на большинстве дисков. В потоковых сервисах их не всегда можно найти.

Наконец, на Blu-ray есть дублированные версии на разных языках. Для детей это большой плюс, особенно если они маленькие.

▍ Заключение и файлы

Я очень доволен этой системой, и жду, когда мой младший сможет пользоваться ею.

Если хотите изготовить что-то подобное сами, то вот мой файл Fusion360, который можно использовать или доделать.

Telegram-канал со скидками, розыгрышами призов и новостями IT 💻


ссылка на оригинал статьи https://habr.com/ru/articles/842488/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *