В предыдущей статье я рассказал, как искал способ запустить Apple CarPlay на Raspberry Pi, экспериментировал с pycarplay и carplay-receiver, а спустя почти два года вернулся к проекту благодаря FastCarPlay.
Но там я практически не объяснил, зачем вообще нужен USB-донгл Carlinkit и какую роль он играет в работе моей магнитолы.
На первый взгляд всё выглядит довольно просто: подключаем адаптер к Raspberry Pi, соединяем iPhone и получаем CarPlay на экране.
На практике между телефоном и изображением на дисплее происходит немало интересного.
Попробую объяснить, как устроена эта система, без углубления в исходный код и подробности протокола.
Зачем вообще нужен Carlinkit
Когда я впервые заинтересовался CarPlay на Raspberry Pi, мне казалось, что достаточно найти подходящее программное обеспечение.
Ведь Raspberry Pi имеет USB, Bluetooth, Wi-Fi и вполне способен воспроизводить видео и звук.
Но CarPlay — это не обычная трансляция экрана телефона.
Для установления соединения и дальнейшей работы необходимо реализовать определённый механизм взаимодействия с iPhone. Именно здесь и появляется USB-донгл Carlinkit.
В моей конструкции адаптер выступает посредником между телефоном и Raspberry Pi.
Он обеспечивает часть взаимодействия, необходимого для работы CarPlay, а приложение на Raspberry Pi обменивается с ним данными через USB.
Таким образом, мне не пришлось самостоятельно реализовывать весь механизм подключения iPhone.
Однако сам по себе Carlinkit ещё не превращает Raspberry Pi в автомобильную магнитолу.
Для этого требуется программное обеспечение, которое сможет взаимодействовать с адаптером и обрабатывать полученные данные.
Как устроена система
В CaRadio участвуют несколько основных компонентов.
Первый — iPhone. На нём работают навигация, музыкальные приложения и другие функции CarPlay.
Второй — USB-донгл Carlinkit. Он обеспечивает взаимодействие с телефоном и передаёт данные компьютеру, к которому подключён.
Третий — Raspberry Pi. Именно на нём работает моя магнитола и выполняется приложение CaRadio.
И наконец, дисплей, усилитель и остальные компоненты автомобильной системы, которые позволяют видеть изображение, слышать звук и управлять приложением.
В упрощённом виде схема выглядит так:
iPhone ↔ Carlinkit ↔ USB ↔ Raspberry Pi → дисплей и звук
При этом управление работает и в обратном направлении. Когда я нажимаю на экран магнитолы, соответствующая команда должна попасть обратно на iPhone.
Именно поэтому работа с CarPlay не ограничивается одним лишь воспроизведением видео.
Подключение телефона
В моём случае используется беспроводной CarPlay.
Это удобно в повседневной эксплуатации: сел в автомобиль, включил магнитолу, и через некоторое время телефон подключается без кабеля.
Однако беспроводное подключение не означает, что Raspberry Pi напрямую работает с iPhone.
USB-донгл по-прежнему остаётся частью системы.
Со стороны Raspberry Pi взаимодействие происходит с подключённым USB-устройством, а адаптер уже обеспечивает связь с телефоном.
Для CaRadio это существенное упрощение.
Приложению не нужно самостоятельно управлять всеми этапами беспроводного подключения iPhone. Оно работает с интерфейсом адаптера и обрабатывает данные, необходимые для отображения CarPlay и управления им.
Откуда берётся изображение
Один из первых вопросов, который возникает при знакомстве с подобной системой: каким образом изображение CarPlay появляется на экране Raspberry Pi?
Сам интерфейс CarPlay формируется на стороне iPhone.
Телефон передаёт видеоданные через установленное соединение, а адаптер доставляет их приложению на Raspberry Pi.
Далее программе необходимо обработать видеопоток и вывести изображение на дисплей.
Именно с этой частью у меня возникали проблемы во время первых экспериментов.
В ранних проектах для отображения изображения использовались браузер или отдельные медиаплееры, например mpv.
Позже я пробовал переделать вывод под VLC.
Работало это не слишком хорошо: изображение заметно тормозило, и использовать такую систему в автомобиле было неудобно.
Когда я вернулся к разработке и начал работать с FastCarPlay, появилась возможность решать эти задачи непосредственно в C++.
В нынешней CaRadio отображение CarPlay встроено в собственное приложение с интерфейсом на SDL3.
Это позволяет использовать один интерфейс магнитолы вместо набора отдельных программ.
А что со звуком?
С изображением всё относительно понятно: телефон формирует картинку, а Raspberry Pi выводит её на дисплей.
Но для автомобильной магнитолы не менее важен звук.
Музыка, голосовые подсказки навигации и другие звуковые данные тоже должны пройти через систему и попасть на автомобильные динамики.
Поэтому программная часть CaRadio должна работать не только с видео, но и с аудиоданными.
В моей конструкции Raspberry Pi является основным вычислительным устройством магнитолы, а для воспроизведения используется отдельный усилитель.
Таким образом, CarPlay становится частью общей аудиосистемы автомобиля.
При этом обработка изображения и звука — разные задачи. Даже если видеопоток уже удалось вывести на экран, это ещё не означает, что вся мультимедийная система готова к работе.
Управление через сенсорный экран
Ещё одна важная часть — обратная связь с телефоном.
Когда я нажимаю на кнопку в интерфейсе CarPlay, действие должно выполняться на iPhone.
Сам по себе сенсорный экран Raspberry Pi ничего не знает о CarPlay. Он лишь сообщает приложению координаты касания.
Программное обеспечение должно обработать эти координаты и передать соответствующее событие через USB-адаптер.
После этого телефон реагирует на действие, а обновлённое изображение снова поступает на дисплей магнитолы.
Получается двусторонний обмен: телефон передаёт изображение и звук, а магнитола отправляет команды управления.
Без этой части CarPlay был бы просто изображением, на которое невозможно повлиять.
Почему недостаточно просто подключить донгл
Когда я впервые купил адаптер Carlinkit, мне хотелось как можно быстрее увидеть работающий CarPlay на Raspberry Pi.
И благодаря открытым проектам это действительно удалось.
Но между первым успешным запуском и полноценной магнитолой оказалась большая разница.
Недостаточно один раз вывести изображение на экран.
Нужно, чтобы система запускалась предсказуемо, телефон подключался, изображение и звук работали без заметных проблем, а сенсорное управление оставалось удобным.
Кроме того, автомобильная магнитола должна быть частью самого автомобиля.
В моём случае CaRadio необходимо корректно включаться, реагировать на выключение зажигания и завершать работу Raspberry Pi без риска повредить файловую систему.
Эти задачи уже выходят за рамки самого CarPlay и требуют отдельной логики приложения и аппаратной части.
Именно поэтому CaRadio постепенно превратилась из эксперимента с USB-донглом в самостоятельный проект.
Что в итоге делает CaRadio
Если упростить, USB-донгл Carlinkit помогает установить взаимодействие с iPhone, а CaRadio превращает полученные данные в работающую автомобильную мультимедийную систему.
Приложение взаимодействует с адаптером, обеспечивает отображение CarPlay, обработку звука и сенсорного управления, а также объединяет эти функции с остальной логикой магнитолы.
При этом я не разрабатывал протокол CarPlay с нуля.
В основе программной части лежат идеи и наработки открытых проектов, прежде всего FastCarPlay, которые я изучал и адаптировал под свою конструкцию.
Для меня главным результатом стало не просто появление CarPlay на экране Raspberry Pi, а возможность ежедневно пользоваться им в автомобиле.
Что дальше
В этой статье я постарался объяснить общий принцип работы системы, не углубляясь в технические подробности.
За каждым из описанных этапов скрывается гораздо больше деталей: обмен данными по USB, обработка видеопотока, передача звука, управление подключением и интеграция с интерфейсом приложения.
Возможно, со временем я расскажу об отдельных частях подробнее.
А если кто-то захочет повторить подобный проект или разобраться в программной части CaRadio, со мной можно связаться по электронной почте. По возможности поделюсь опытом и отдельными наработками.
Пока же главное для меня — то, что связка Raspberry Pi и Carlinkit оказалась вполне пригодной для повседневного использования в автомобиле.