В предыдущих статьях я рассказал, как удалось запустить CarPlay на Raspberry Pi и какую роль в этой системе играет USB-донгл Carlinkit.
Но между первым успешным запуском FastCarPlay и появлением работающей CaRadio была ещё одна история, о которой я пока почти не упоминал.
Она связана с выбором программной основы, экспериментами с другим проектом и неожиданной проблемой, после которой CarPlay вообще перестал подключаться.
Почему я выбрал SDL3
В своих первых экспериментах с автомобильной магнитолой я использовал Qt и C++.
Qt — мощный инструмент, позволяющий создавать полноценные графические приложения. Но со временем я начал задумываться, насколько всё это необходимо для устройства, которое должно выполнять сравнительно небольшой набор задач.
Когда весной 2026 года я нашёл FastCarPlay, одним из его преимуществ для меня оказалось то, что проект был написан на C++ с использованием SDL.
Я начал знакомиться с SDL3 и понял, что такой подход мне нравится гораздо больше.
Для работы графического приложения не обязательно поднимать X11 и использовать целый Qt Framework. Можно обойтись значительно меньшим набором компонентов и самостоятельно организовать интерфейс.
Конечно, это не означает, что SDL3 во всём лучше Qt. Это инструменты для разных задач.
Но для моей магнитолы SDL3 оказался ближе к тому, что я хотел получить: относительно небольшое приложение без лишних программных слоёв.
К тому же FastCarPlay уже использовал SDL, поэтому переход к собственной реализации на той же основе выглядел вполне логичным.
Первый запуск FastCarPlay
После знакомства с исходниками я собрал FastCarPlay и попробовал запустить его с моим USB-донглом Carlinkit.
И CarPlay действительно заработал.
Правда, не всё было идеально.
Сейчас я уже не вспомню все проблемы, с которыми столкнулся во время первых запусков. Помню лишь, что система работала не совсем так, как ожидалось, и я начал искать возможные причины.
Во время этих поисков мне попался ещё один открытый проект — LIVI.
Я решил попробовать и его.
Знакомство с LIVI
LIVI оказался довольно большим проектом по сравнению с FastCarPlay.
Кроме того, он был написан на языке программирования, с которым я не был знаком.
Это не означает, что проект был плохим. Скорее наоборот: после установки LIVI у меня корректно заработал.
Но разбираться в большой кодовой базе на незнакомом языке и затем строить на её основе собственную магнитолу мне не хотелось.
Я предпочитаю C++, а для подобных самодельных устройств стараюсь придерживаться одного принципа: чем проще, тем надёжнее.
Разумеется, простота сама по себе ничего не гарантирует.
Но из собственного опыта я заметил, что чем сильнее начинаешь усложнять конструкцию на первых этапах, тем больше появляется потенциальных источников проблем.
Дополнительные зависимости, службы, программные прослойки — всё это приходится настраивать, поддерживать и учитывать при поиске неисправностей.
Поэтому мне хотелось сохранить FastCarPlay в качестве основы и постепенно адаптировать его под свои задачи.
Однако после эксперимента с LIVI возникла неожиданная проблема.
Когда CarPlay перестал подключаться
После запуска LIVI я вернулся к FastCarPlay.
И обнаружил, что теперь он вообще перестал видеть телефон.
До этого CarPlay хотя бы запускался, пусть и с некоторыми проблемами. Теперь подключение не происходило совсем.
Точную причину я так и не установил.
У меня возникло предположение, что во время работы LIVI в донгле Carlinkit могла измениться какая-то настройка или внутреннее состояние, из-за чего прежняя процедура подключения перестала работать.
Но это осталось предположением.
Факт был в другом: один проект продолжал корректно работать с адаптером, а второй больше не мог установить соединение.
Именно это различие и стало отправной точкой для дальнейшего поиска.
Восстановление инициализации Carlinkit
Поскольку LIVI продолжал работать, я решил использовать его как ориентир.
Задача заключалась не в том, чтобы переписать FastCarPlay на другом языке или перенести в него весь код LIVI.
Мне нужно было разобраться, чем отличается процедура инициализации USB-донгла в этих двух проектах.
Я начал изучать соответствующие части реализации и сравнивать последовательность взаимодействия с Carlinkit.
Постепенно удалось обнаружить отличия, которые могли влиять на установление соединения.
На основании этих наблюдений я внёс изменения в процедуру инициализации FastCarPlay.
После исправлений телефон снова начал подключаться.
Но на этот раз результат оказался лучше, чем при первых экспериментах: удалось добиться стабильного подключения и работы CarPlay.
Для меня это был важный этап.
До этого я в основном пытался запустить и адаптировать уже существующие решения. Теперь пришлось разбираться непосредственно во взаимодействии приложения с USB-донглом и искать причину несовместимости.
При этом я не занимался разработкой протокола CarPlay с нуля.
Я использовал существующие открытые реализации, сравнивал их поведение и исправлял ту часть взаимодействия с адаптером, которая мешала нормальной работе моей системы.
Почему я всё-таки остался с FastCarPlay
После этих экспериментов у меня были две работающие отправные точки.
LIVI показал, что адаптер способен корректно подключаться и работать. Более того, его реализация помогла разобраться с проблемой инициализации.
Но в качестве основы для дальнейшей разработки я всё равно предпочёл FastCarPlay.
Причин было несколько.
Прежде всего — C++. Это язык, с которым я давно работаю и на котором мне удобно разрабатывать и поддерживать собственные проекты.
Вторая причина — SDL3. Мне понравилась возможность построить графическое приложение без необходимости использовать X11 и Qt.
И третья — размер и сложность проекта.
Я не хотел превращать самодельную магнитолу в большую программную систему ещё до того, как заработают её основные функции.
Мой подход довольно простой: сначала добиться надёжной работы минимально необходимого набора компонентов, а уже затем постепенно добавлять новые возможности.
Конечно, по мере развития CaRadio приложение неизбежно становилось сложнее.
Но мне хотелось, чтобы это усложнение было следствием конкретных задач, а не появлялось заранее.
От экспериментов к собственной CaRadio
Когда проблему подключения удалось решить, у меня наконец появилась рабочая программная основа, на которую можно было опираться.
FastCarPlay обеспечивал взаимодействие с Carlinkit, SDL3 подходил для построения собственного интерфейса, а C++ позволял развивать приложение в привычной для меня среде.
Это ещё не была готовая автомобильная магнитола.
Предстояло объединить CarPlay с остальными функциями CaRadio, продумать управление приложением и адаптировать его к повседневной эксплуатации в автомобиле.
Но один из наиболее неприятных вопросов уже был решён: подключение телефона перестало быть непредсказуемым экспериментом.
Именно после этого я смог сосредоточиться на дальнейшем развитии собственной магнитолы, а не на постоянных попытках заставить CarPlay хотя бы запуститься.
Что дальше
Эта история в очередной раз напомнила мне, почему я предпочитаю не усложнять собственные проекты без необходимости.
Иногда небольшая программа, которую хорошо понимаешь, оказывается удобнее большого готового решения с множеством возможностей.
При этом без LIVI мне, возможно, потребовалось бы значительно больше времени, чтобы разобраться с проблемой подключения Carlinkit.
Поэтому оба проекта сыграли свою роль в развитии CaRadio.
FastCarPlay стал программной основой, а LIVI помог найти и устранить проблему, которая мешала двигаться дальше.
В следующих статьях я расскажу о других частях CaRadio и о том, какие задачи пришлось решать, чтобы превратить работающий CarPlay в полноценную автомобильную магнитолу.