В детстве у нас с сестрой была гора VHS-кассет, которые мы бесконечно пересматривали. Современная видеоколлекция моих детей сильно от них отличается. Она полностью цифровая и разбросана по разным сервисам. Я хотел поделиться с ними магией осязаемости носителя из моего детства.
У меня двое пацанов, старшему разрешается посмотреть полчаса телевизор с утра и ещё полчаса вечером. Обычно он точно знает, что хочет посмотреть, но ему приходится ждать, пока кто-то из родителей возьмёт пульт и откроет нужное приложение.
Это заставило меня задуматься: почему бы не объединить новое и старое? Я хотел, чтобы у сына была более активная роль в выборе того, что он хочет посмотреть, несмотря на цифровой формат.
Несколько лет назад я увидел, как кто-то распечатал любимые музыкальные альбомы с NFC-меткой внутри, и решил сделать что-то подобное для своих детей.
▍ Конечный результат
Вот, что я в результате создал:
Это коллекция ламинированных обложек фильмов и мультфильмов с NFC-меткой внутри. Сыну остаётся только выбрать нужный фильм и положить его на считыватель NFC. Всем остальным займётся Home Assistant.
Вот видео того, как работает система:
▍ Proof-of-concept и материалы
Я начал с изготовления простого прототипа. В одном из моих наборов электроники нашёлся считыватель NFC (RC522) и несколько NFC-меток.
Я подключил считыватель NFC к плате ESP32 и прошил на неё ESPHome. Затем я положил NFC-метку на считыватель и увидел, что она появляется в логах ESPHome.
И это всё, что мне нужно было проверить. Я зашёл на AliExpress и купил оборудование для «продакшена»:
- 50 NFC-карт из ПВХ (NTAG215): €9,43.
- ESP32-C3 (Super Mini): €2,93.
У меня уже было множество плат 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'
Если вы будете собирать устройство самостоятельно, то необязательно использовать те же номера контактов.
--- 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-метку и позволял извлечь её в будущем.
▍ Автоматизация Home Assistant
И последняя часть проекта: создание автоматизации Home Assistant, которая будет воспроизводить нужный фильм после сканирования метки.
Мы храним фильмы в Plex и воспроизводим их через Apple TV. В Plex есть два способа воспроизведения видео:
- Через интеграцию с Apple TV, при помощи «глубоких ссылок» Plex.
- Через интеграцию Plex с Home Assistant.
По моему опыту, интеграция 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/
Добавить комментарий