АУДИО Интернет радио на базе смартфона Android + пульта на базе ESP32

DmitrySazonov

✩✩✩✩✩✩✩
27 Ноя 2022
3
2
Всем привет!
Приемник интернет-радио, собранный в предыдущем проекте, имел некоторые недостатки. А именно: были частые потери сигнала wifi, медленная и глючная работа в целом, случайные перезагрузки. Короче, он перестал меня устраивать и я решил продолжить тему проигрывателя интернет радио, но на базе другой аппаратной платформы.
В качестве самой платформы я решил развивать решение на базе обычного смартфона на Android с разъемом minijack 3.5, к которому бы были подключены колонки. Как решение для реализации логики проигрывателя, родилось приложение flutter radio. Сам проект доступен на github, и через github release выложил уже собранный apk для установки ни телефон.

home.png

Основные возможности приложения:
  • Тёмная тема, полноэкранный режим.
  • Поддержка MP3/AAC потоков
  • Плей/пауза, след/пред станция, громкость (слайдер).
  • Редактирование станций: добавление, удаление, изменение порядка (перетаскивание).
  • Отображение текущей играющей композиции (ICY-метаданные, если их отдаёт станция).
  • Встроенный веб-пульт по Wi-Fi:
  • Удалённое управление со страницы в локальной сети.
  • Локальный REST API (OpenAPI спецификация).
Требования (Android):
  • Android 7.0+ (API 24+) — рекомендуется Android 8.0+.
  • Подключение к интернету (для потоков).
Использованные технологии:
  • Flutter (Material 3).
  • just_audio — плеер для работы с потоками.
  • audio_service — уведомление/сервис воспроизведения и интеграция с системными контролами.
  • Чистый dart:io для HTTP-сервера (без внешних зависимостей).
  • ICY-метаданные из just_audio (icyMetadataStream).

Как предустановленные значения станций я добавил несколько станций моей любимой площадки 1.FM, значения станций можно поменять после запуска приложения.
Как базовые настройки (кроме редактирования списка самих станций) я добавил тоггл для старта веб интерфейса и тоггл по логике паузы.

Т.к. радиостанции - это бесконечный прогрессивный поток (MP3/AAC по HTTP), то плеер (ExoPlayer внутри just_audio) ведёт себя так:
  • при Pause он просто останавливает воспроизведение и оставляет уже загруженный буфер;
  • при Play он продолжает с того места буфера, где остановился (получается эффект «тайм-шифта»), а не «переподключение на живой край».
Решено сделать настройкой - или обеспечить проигрывание с живого края, или с места паузы. Кому как больше нравится. Мне больше нравится «живой край».

Из известных багов в приложении осталось неявное переключение тогглов. При первичном старте и нажатии на тоггл он не отображается переключенным. Но, если закрыть меню настроек (шестерня), и открыть снова, то он будет отображаться включенным.
settings.png

Ну, и , основная фишка - это веб интерфейс по управлению. Если не предполагается частого переключения или пауз проигрывания, то само устройство можно вообще спрятать за колонкой и забыть про него, управляя чисто через веб интерфейс.
web_ui.png

Итого, со стабильностью работы с сетью и воспроизведением самих радиостанций проблем нет. Это основное, ради чего все затевалось. Но, были некоторые неудобства по интерфейсу.

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

Поэтому родилась идея сделать пульт для управления. По сути, это клиент, который по http будет использовать то же API веба, но при этом он будет аналоговым по интерфейсам управления.

ESP32 Radio Remote

Идея сделать пульт была реализована как связанный проект, также выложен на gihub. Аналоговый пульт, очень похожий внешне на первое решение, но внутри которого только плата ESP32. Мне очень нравилась работа экрана 2.42" OLED и отображение информации на нем, управление через энкодер. Поэтому компоновка будет примерно такой же. Запасные детали от старого проекта еще были в наличии (ESP32, экран, энкодер), поэтому решил все сделать на их базе. Также в процессе эксплуатации я решил, что переключение станций удобнее сделать на отдельные кнопки, поэтому в финальной версии предполагается использование двух кнопок без фиксации.

Кстати по кнопкам. Сначала я купил просто обычные кнопки без фиксации, но они были очень тугими, и поразмыслив, понял, что идеально на роль кнопок без фиксации подходят клавиатурные свитчи! Они бывают разные с разной тактильной отдачей, я решил остановится на cherry MX Brown (как раз они были в наличии). В итоге финальная версия корпуса и решения именно на них.

IMG_7578.jpg

Схема сборки:

esp32_radio_remote.png

Основные компоненты:

  • ESP 32 38P
  • Цифровой энкодер
  • Дисплей 2.42" OLED 4 pin
  • Кнопка без фиксации (2 шт)
Модели для печати находятся в папке /stl проекта. Я печатал корпус полностью из PLA Carbon Fiber, очень уж понравилось делать из него корпуса. Рекомендации по печати и расположению деталей аналогичны предыдущему проекту. Плату решил расположить с выводом питания слева и немного уменьшить размеры корпуса. Сборка также аналогична, требуется 10 болтов M2.5x5 мм. Единственное, что я поменял при сборке - полностью срезал изоляцию с крайних ножек ESP32. Так она не мешает фиксации ESP32 болтами на площадке корпуса.

Из основных фишек самого пульта, которые я решил реализовать:

1) Тройное нажатие энкодера - отображение текущего адреса для доступа к веб интерфейсу

2) Двойное нажатие - переключение уровня яркости. Варианты значение (0.255) можно настроить как массив значений в веб интерфейсе

3) Инверсия энкодера по громкости. Думаю, это или косяк кода, или сборки, но, для удобства стоит инвертировать поворот. Хотя, кому-то может, наоборот, удобнее как по умолчанию.

4) Ускорение при вращении громкости. Можно установить его, и при долгом вращении шаг будет сам собой увеличиваться. Мне показалось удобным. За меньший поворот делать больше громкость

5) Ночной режим. При прошествии (300с по умолчанию) и при отсутствии взаимодействия с пультом экран снижает яркость до значения (настраивается, по умолчанию 10).

6) Выключение экрана - спустя значение (3600с по умолчанию) при отсутствии взаимодействия с пультом экран вообще выключается.

7) Информация об исполнителе и композиции. В виде бегущей строки или (если помещается в 2 строки) без.

8) Настройки, которые остались как легаси в режиме добавления фичей (режим STA/AP, сохранять уровень громкости при перезагрузке), но решил их оставить.

Более подробная инструкция по заливке прошивке есть в readme проекта, не вижу смысла ее тут дублировать.

После заливки прошивки и первого запуска через какое то время (не сразу, не пофиксил этот некритичный баг) будет переход в режим AP, те плата станет точкой доступа, к которой можно подключиться и выполнить базовую настройку SSID и пароль целевого WIFI, ip адрес телефона с flutter_radio. Дополнительно можно указать токен, но его же нужно задавать в flutter_radio. Это предварительный функционал по аутентификации запросов, который пока решил не реализовывать. Для домашней сети считаю это излишним.

IMG_7571.jpg