В предыдущих статьях я рассказал, как собирал собственную автомобильную магнитолу 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 не появилась за один вечер и не была написана с чистого листа.
Она стала результатом нескольких лет экспериментов, неудачных попыток, изучения чужих проектов и постепенного поиска подходящего решения.
И, пожалуй, именно эта часть истории оказалась для меня самой интересной.