Меню

andipanda.dev

CaRadio: от первых экспериментов с Carlinkit до работающего CarPlay

В предыдущих статьях я рассказал, как собирал собственную автомобильную магнитолу CaRadio на Raspberry Pi, пытался использовать электронику Volkswagen RCD510 и в итоге установил работающую систему в свой Golf.

Но до сих пор я почти не рассказывал о программной части проекта.

Ведь Raspberry Pi, дисплей и усилитель сами по себе ещё не делают магнитолу полноценной мультимедийной системой. Мне нужен был CarPlay — желательно беспроводной, с навигацией, музыкой и управлением через сенсорный экран.

Сегодня всё это уже работает в автомобиле. Но путь к этому результату оказался гораздо длиннее, чем я первоначально рассчитывал.

Всё началось с выбора магнитолы

Несколько лет назад я искал новую магнитолу для автомобиля. Среди доступных вариантов одним из наиболее интересных мне казались устройства Teyes.

У них были разные комплектации, в том числе с поддержкой Apple CarPlay и без неё.

В процессе поисков я наткнулся на инструкции, в которых рассказывалось, как добавить поддержку CarPlay в некоторые модели Teyes, установив дополнительную микросхему.

Именно тогда у меня возникла мысль: если подобное решение можно использовать в Android-магнитоле, возможно, получится приспособить его и к Raspberry Pi?

У меня уже был опыт создания собственной автомобильной магнитолы, поэтому идея использовать Raspberry Pi вместо готового устройства выглядела вполне естественно.

Я начал искать информацию о микросхемах, способах подключения и программных реализациях CarPlay.

Но довольно быстро выяснилось, что всё несколько сложнее, чем просто подключить один чип.

Знакомство с pycarplay

Во время поисков мне попался проект pycarplay на GitHub.

Это была реализация на Python, позволявшая работать с USB-адаптерами CarPlay.

Сначала я не совсем понимал, как именно всё устроено. По описанию было видно, что проект позволяет запускать CarPlay на Raspberry Pi, но для работы требовалось дополнительное оборудование.

Постепенно разобравшись в документации и поискав информацию в интернете, я выяснил, что нужен специальный USB-донгл, подобный Carlinkit.

Оставалось его найти.

На Allegro мне попался недорогой послевыставочный адаптер — клон Carlinkit. По меркам того времени он стоил совсем немного, поэтому я решил попробовать.

Кстати, именно этот адаптер до сих пор работает в моей магнитоле.

После покупки я подключил его к Raspberry Pi, установил необходимое программное обеспечение и впервые увидел работающий CarPlay на собственном устройстве.

Это был важный момент.

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

CarPlay в браузере

Насколько я помню, первая реализация, которую мне удалось запустить, была связана с идеей использования CarPlay в автомобилях Tesla.

Raspberry Pi выступала в роли небольшого веб-сервера, а изображение CarPlay можно было открыть в браузере.

Для экспериментов это оказалось довольно удобным решением.

Система запускалась, телефон подключался, изображение появлялось, и в целом всё работало относительно неплохо.

Но у меня была другая задача.

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

Поэтому я продолжил искать другие реализации.

От mpv к VLC

Следующей находкой стал проект carplay-receiver.

Он также был написан на Python, но использовал другой подход к отображению видео. Вместо браузера изображение CarPlay выводилось через медиаплеер mpv.

Это было уже ближе к тому, что мне требовалось.

Я начал разбираться в коде и пробовать запустить проект на своей Raspberry Pi.

Однако с mpv у меня что-то не сложилось. Сейчас уже сложно вспомнить все подробности, но добиться желаемого результата быстро не удалось.

Зато у меня уже был опыт работы с VLC.

Поэтому я решил переделать вывод изображения под знакомый мне плеер.

После нескольких экспериментов CarPlay всё-таки удалось запустить.

Правда, работало это далеко не идеально.

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

Изображение заметно тормозило, а быстро разобраться с причинами у меня не получилось.

Попытка перейти на C++

К тому времени у меня уже был опыт разработки на C++ с использованием Qt.

Поэтому возникла идея отказаться от Python и перенести необходимую функциональность в собственное приложение.

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

Но одно дело — запустить готовый проект, и совсем другое — разобраться в его внутреннем устройстве настолько, чтобы переписать его на другом языке.

Нужно было понять, как организован обмен с USB-адаптером, каким образом передаются видео и звук, как обрабатываются касания и другие команды управления.

Тогда моих знаний и свободного времени для этого оказалось недостаточно.

Попытка не увенчалась успехом.

В результате я отложил разработку CarPlay для Raspberry Pi. Как оказалось, почти на два года.

Возвращение к проекту

Спустя почти два года я решил ещё раз изучить доступные решения. За это время многое изменилось, и я надеялся, что появились новые проекты, которые помогут продвинуться дальше.

В процессе поисков мне попался проект FastCarPlay.

FastCarPlay был написан на C++, то есть на языке, с которым я хотел работать с самого начала.

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

После первого запуска обнаружились проблемы, которые пришлось постепенно решать.

Но теперь у меня была гораздо более подходящая отправная точка.

В отличие от прежних экспериментов с Python, я мог работать непосредственно с C++-кодом и постепенно адаптировать его под собственные задачи.

Не только FastCarPlay

В процессе изучения существующих решений мне также попался проект LIVI.

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

При этом использовать LIVI в качестве основы CaRadio я не стал.

Для моих задач проект выглядел слишком громоздким, а язык, на котором он был написан, я практически не знал.

Тем не менее такие проекты очень полезны.

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

Причём LIVI продолжает активно развиваться и в некоторых направлениях, вполне возможно, уже опережает текущую версию CaRadio.

От эксперимента к автомобильной магнитоле

После запуска FastCarPlay работа над CaRadio наконец сдвинулась с места.

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

В дальнейшем приложение получило собственный интерфейс на C++ с использованием SDL3.

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

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

Конечно, это не означает, что я написал реализацию CarPlay с нуля.

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

Именно благодаря pycarplay, carplay-receiver, FastCarPlay и другим подобным разработкам у меня появилась возможность пройти этот путь.

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

Что дальше

Сегодня CaRadio уже несколько месяцев работает в моём Volkswagen Golf.

За это время она прошла тысячи километров, а беспроводной CarPlay стал обычной частью ежедневных поездок.

Но за внешне простым интерфейсом скрывается немало интересных технических решений.

Как Raspberry Pi взаимодействует с USB-донглом Carlinkit? Откуда берётся видеопоток? Как передаются звук и касания? И что именно пришлось изменить, чтобы всё это заработало в собственном приложении?

Обо всём этом я хочу рассказать подробнее в следующих статьях.

А пока главное, что стоит отметить: программная часть CaRadio не появилась за один вечер и не была написана с чистого листа.

Она стала результатом нескольких лет экспериментов, неудачных попыток, изучения чужих проектов и постепенного поиска подходящего решения.

И, пожалуй, именно эта часть истории оказалась для меня самой интересной.