Меню

andipanda.dev

CaRadio: FastCarPlay, LIVI и восстановление работы Carlinkit

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