Document X4 Android reconnect protocol research and recovery options

This commit is contained in:
DCCONSTRUCTIONS
2026-09-10 11:25:07 +03:00
parent 3b85299fd9
commit b536f0049a
6 changed files with 334 additions and 4 deletions
@@ -800,3 +800,62 @@ Private0600 handoff.json SHA-256
Канонический Core оставлен работающим. Никаких новых viewer/worker/observer
процессов не запускалось; root descriptor reader завершился. Локальное
диагностическое окно после результата ждёт Enter, не выполняет работу.
## RESEARCH01 — Android hot-replug, 10.09.2026
По прямому запросу владельца исследованы официальные инструкции X4, API/FAQ,
93 Desktop SDK issue records и комментарии пяти релевантных issues, открытые
Linux BLE/Wi-Fi проекты. Полный отчёт и точные ссылки —
[план12](12_INSTA360_X4_ANDROID_RECONNECT_RESEARCH.md).
Начало фиксации источников 08:10:53.043126 UTC, Mac monotonic448333.003748166.
Официально предусмотрена память USB mode; при отсутствии USB-страницы X4
документирован camera restart/reconnect. Готового подтверждённого исправления
нашего hot-replug в прочитанных материалах нет. Найдены два проверяемых пути:
внутренний Options.udisk_mode и BLE remote off/on с отдельным BLE wake-up.
Прежний вывод PORT01 о необходимости хаба как ближайшего шага исправлен:
No power switching относится к встроенному контроллеру, а не ко всем способам
перезапуска камеры. Измерения PORT01 сохраняются.
Источники закреплены: insta360ctl f94193ce03c5af0921a9992bfd1af6bd946150d0;
insta360-ble-gps-spec 7964f1133e5d0f2c7eb73aaaaf5d6ebdd2127199;
официальный Desktop SDK repo 8c2c765207d7c4d89137893901412f45b9340657.
CLI не исполнялся: обнаружены legacy GO 3 message codes с иными назначениями
в общем протоколе, поэтому его README не принимается как квалификация X4.
Добавлен versioned read-only reader
plugins/insta360-x4/packaging/inspect_sdk_control_schema.py,
SHA-256 7d7351e855811e94d28c2e760a19eb93ac84756fcbc745e32e5245086988fd8a.
Он использует только существующий Python stdlib на Mac; читает pinned SDK bytes
без загрузки/исполнения библиотеки и без device/network access. Hash mismatch
или отсутствие обязательных descriptors завершают работу ошибкой. Повторный
запуск не меняет систему/камеру; rollback не требуется. Это исследовательский
reader, не новая runtime prerequisite и не установленный control driver.
Schema evidence 08:14:30.414190 UTC, Mac monotonic448550.373271375:
подтверждены udisk_mode field95 / OptionType95 / ANDROID1, Get/SetOptions8/7,
bt_wakeup_sw97 и generic RebootCamera32. Наличие схемы не подтверждает поддержку,
writability или USB transition на X4. Повторный разбор закреплённых bytes и
assertions поля95/ANDROID1 прошли. Числа не отправлялись устройству.
Private ignored research/android-reconnect, JSON0600, SHA-256:
- manifest.json: 0e6d8aa32e32d89950ed41828219b5fe0f094550cb3f14faeea79e118d748b37;
- schema-evidence.json: 98888b8a89251a6e3a6aedde2e4d853a3675c50e76980ac6c4585956c42ea775;
- desktop-issues.json: c17909ceea258b5b57a36e52144c32d136faaf4925cc0680c5ddb4ece681ee94;
- desktop-issue-comments.json: 51b8c363734b37ff338a3d3ca6ebc9c751b53272ca3400802ff1a01bf1b9270c.
Новых действий на Ubuntu, BLE scanning/pairing/writes, USB reset, firmware или
изменений питания не было. Installed Node0.8.19 / X40.1.3-3 не менялись.
Следующий аппаратный опыт сначала входит в installer/versioned preparation:
точная BLE identity и framing/auth → read Options95 → при подтверждённой
семантике setter; резерв — BLE remote off/on с проверенным wake-up и уже
вставленным USB. ACK не является результатом; нужны прежняя X4, новый SDK
сеанс и свежий Core frame. Hardware recovery остаётся непринятым.
RESEARCH01 handoff 2026-09-10T08:25:02.264009+00:00, Mac monotonic449182.212671875:
Core8000 operational; canonical service оставлен работающим. Собственные
viewer/worker/observer не запускались. Private0600 handoff.json SHA-256
72c684e32906e19f0808f7cb2c028391fecba52f1b39d74bc6a5ee65d2b67c9e.
Python urllib health probe был запрещён sandbox до соединения; штатный
curl GET подтвердил здоровье сервиса, изменения прав/службы не требовались.
Ops MISSIONCOR-77 обновлён; аппаратные acceptance items остались открыты.
@@ -1,5 +1,17 @@
# Insta360 X4 — состояние реализации 10.09.2026
## RESEARCH01 — программный возврат Android после USB out/in
[Исследование точного сценария](12_INSTA360_X4_ANDROID_RECONNECT_RESEARCH.md)
уточняет следующий шаг: X4 штатно сохраняет последний USB mode. В закреплённом
SDK статически подтверждены Options.udisk_mode (95), ANDROID=1 и Get/SetOptions;
найдены также X4 BLE remote off/on и официальный BLE wake-up. Это кандидаты на
аппаратную проверку, не доказанный recovery. Сначала — проверка точной identity,
framing/auth и чтение параметра по беспроводному каналу; затем ограниченный
setter либо отдельно BLE off/on. Обязательность управляемого хаба была
преждевременным выводом из PORT01. Команды камере, BLE pairing и изменения Ubuntu
в RESEARCH01 не выполнялись; установленные Node 0.8.19 / X4 0.1.3-3 сохранены.
## B11 применён и проверен10.09.2026 — PREP05/LIVE06
Подготовлен X40.1.3-3 в Node0.8.18-1.38 Ubuntu tests passed, включая real-codec stream с единственным initial keyframe после повторного START и active verify двух новых кадров общего decoder. Повторный START больше не сбрасывает generation при уже активном preview; unknown такого повторного START не закрывает существующий decoder. Idle verification остаётся в worker, active verification использует broker source; единый verification journal сохраняет дедупликацию при изменении preview state. Собственные причины ошибок доступны через allowlisted messages.
+3 -3
View File
@@ -12,7 +12,7 @@ B11/P09,09.09: эта реализация готова и прошла38 Ubuntu
Предварительное условие NET01 закрыто NET02/NET03,10.09: CoreNode восстановили канал через Tailscale с прежними trust/identity. В Core подтверждены несколько свежих mTLS heartbeat, endpoint revision1. После восстановления заново читать актуальное состояние камеры перед любыми preview/model операциями; прежний stale inventory не подтверждает её текущее состояние.
P10/PREP05 complete: Node0.8.19 и X4 model0.1.3-3 установлены штатно. LIVE06 подтвердил первый и повторный START, active verify и viewer reopen:1083 декодированных кадра1280×640, без SD записи. REPLUG01 выявил отказ active USB replug; REPLUG02/LIVE07 восстановили камеру после camera off/on. OWNER03 подтвердил автоматический Android mode после этого включения. REPLUG03 подтвердил такой же отказ при fresh idle/preview0. Владелец исключил замену кабеля из ближайшего gate. PORT01: порты/контроллер активны, early_stop=no, перегрузок0; измерителей VBUS/тока нет. Root reader подтвердил No power switching у обоих xHCI root hubs: штатно снимать VBUS встроенного порта нельзя. Следующая аппаратная ветка — управляемый хаб, с отдельной квалификацией питания/полного выключения X4; программный recovery SDK/preview — после возврата USB. Задержка NET03 recovery и длительная video stability остаются открытыми.
P10/PREP05 complete: Node0.8.19 и X4 model0.1.3-3 установлены штатно. LIVE06 подтвердил первый и повторный START, active verify и viewer reopen:1083 декодированных кадра1280×640, без SD записи. REPLUG01 выявил отказ active USB replug; REPLUG02/LIVE07 восстановили камеру после camera off/on. OWNER03 подтвердил автоматический Android mode после этого включения. REPLUG03 подтвердил такой же отказ при fresh idle/preview0. Владелец исключил замену кабеля из ближайшего gate. PORT01: порты/контроллер активны, early_stop=no, перегрузок0; измерителей VBUS/тока нет. Root reader подтвердил No power switching у обоих xHCI root hubs: штатно снимать VBUS встроенного порта нельзя. RESEARCH01 уточнил приоритет: сначала беспроводное чтение внутреннего udisk_mode и проверка программного возврата Android либо BLE off/on самой камеры по плану12. Управляемый хаб отдельная аппаратная альтернатива; отсутствие VBUS switching не доказывает невозможность программного обхода. Recovery SDK/preview — после возврата USB. Задержка NET03 recovery и длительная video stability остаются открытыми.
OWNER03: владелец видит изображение X4 и D455 через Core при переходах между карточками. Read-only Node snapshot обеих камер online/streaming. Длительная одновременная работа и измерения ещё не приняты.
@@ -30,7 +30,7 @@ camera settings/file download. Конкретная матрица, доказа
|---|---|---|
| Завершено, P5 | Общие состояния loading в DG: pending инициирующей кнопки, центр content region, отсутствие бесконечной загрузки после ошибки. Shared frontend для Core и Node, каталог и правила. | UI01/N09 установлен в Core8000 и Node0.8.18. Сборки/819 Core tests, DG tests/catalog и Node checks прошли. Browser geometry, normal/expanded/Escape, light/dark и error lifecycle проверены. Native Node visual QA ещё открыта. |
| B11 ограниченно принят, P3/P4 | Исправлено очищение feed при повторном START и проверка активного потока через новый decoder. PREP05/LIVE06: repeat START, live verify, viewer reopen complete. |1083 кадра1280×640; долгий capture и все возможные причины stale отдельно не приняты. |
| Первый следующий, P3/P4 | PORT01: штатное VBUS switching встроенного Mini не поддерживается. Для power recovery нужен проверенный управляемый хаб и раздельные battery/power/boot controls; изменения сначала входят в packaged preparation. Замену кабеля владелец не выбрал. После возврата USB — SDK recovery/preview intent по плану11. | Возврат того же экземпляра без переустановки и ручного режима, восстановление изображения; VBUS доказан отдельным физическим тестом. |
| Первый следующий, P3/P4 | RESEARCH01: через versioned artifact проверить BLE identity/framing/auth и прочитать Options.udisk_mode (95). Затем при подтверждённой семантике — ограниченный Android setter; резерв — BLE remote off/on при уже вставленном USB. [Доказательства и границы](12_INSTA360_X4_ANDROID_RECONNECT_RESEARCH.md). Хаб — альтернативная аппаратная ветка. После USB enumeration — SDK recovery/preview intent по плану11. | Прежняя X4 без рук возвращается в Android, новая SDK session и свежий кадр; прочие камеры/Node online. Наличие параметра в SDK и ACK не являются приёмкой. |
| Следующий, P4 + P5 | Совместимый локальный просмотр в установленном Node/WebKit. Исходный план предусматривает HTTP/fMP4 carrier от той же медиа-сессии; переиспользуются общие media lifecycle/lease части K1, без импорта K1 protocol или второго SDK владельца X4. | На Ubuntu в приложении Node есть движущееся изображение; одновременно открыт удалённый Core. Закрытие одного зрителя сохраняет другого, не меняет SD recording. Все runtime dependencies входят в .deb/profile. |
| Затем, P4C | Матрица поддержанных действий по фактическим SDK headers и capabilities: camera settings, normal photo/video, ISO/exposure/WB/resolution, отдельные SD start/stop и фото. Проверять readback, mode dependencies и отображение результата. | Явные адресные команды из обеих UI, реальные результаты на камере, неизвестный outcome не переигрывается автоматически. Не обещать все режимы SDK до их проверки; shutter/EV setters и неподдержанные поля перечисляются отдельно. |
| P4C + общий source-record workflow | Получение содержимого выбранного файла на Node и в Core, bounded transfer, прерывание/продолжение, длина/hash и происхождение. Каталог уже есть, download ещё нет. | Пользователь получает существующий файл без shell; повторы/обрыв связи не меняют оригинал на SD. Незавершённый записываемый файл обрабатывается явно. |
@@ -38,7 +38,7 @@ camera settings/file download. Конкретная матрица, доказа
| P1/P3/P6 | Несколько одинаковых X4 и D455, одновременная K1, exact-device routing, isolation/crash/replug. D455 shared-process migration остаётся отдельной реализацией. |2/4 реальные камеры независимы;500 synthetic descriptors не превращаются в обещание500 потоков. Текущий admission4 sources/4 peers/2 peers per camera пересматривается только по измерениям. При отсутствии устройств hardware часть остаётся открытой. |
| P7 | Чистая Ubuntu24.04 Desktop amd64 с закреплённым образом; полный installer → discovery → prepare из обеих UI → image → управление; upgrade/repair/rollback/failure matrix. | Никакой системной предпосылки вне installer, repeat/recovery сохраняют identity/trust/recordings. Текущий рабочий диск Mini не стирается. Отдельный чистый носитель/образ — необходимое условие, не предположение о наличии второй машины. |
Критический путь по последнему решению владельца: **USB replugcold start/SDK recovery/preview intent → адресное питание → локальное видео Node → приёмка управления/фото → получение файлов**. B11 имеет ограниченную аппаратную приёмку; длительная устойчивость остаётся самостоятельным gate. Контракт и учёт clean install проверяются при каждом изменении, финальная установка на чистый носитель завершает воспроизводимость. Общее наблюдение K1/monitor и их открытые fault/backfill/source-import проверки сохраняются в исходной матрице; успех X4 их не закрывает.
Критический путь по последнему решению владельца: **беспроводной возврат Android (план12) → replug/cold start/SDK recovery/preview intent → локальное видео Node → приёмка управления/фото → получение файлов**. Адресное питание остаётся альтернативной веткой восстановления. B11 имеет ограниченную аппаратную приёмку; длительная устойчивость остаётся самостоятельным gate. Контракт и учёт clean install проверяются при каждом изменении, финальная установка на чистый носитель завершает воспроизводимость. Общее наблюдение K1/monitor и их открытые fault/backfill/source-import проверки сохраняются в исходной матрице; успех X4 их не закрывает.
Stitching не включается: текущая цель — операторский обзор с низкой задержкой. Worker, AI и управление движением не являются зависимостями. Если нужен сшитый обзор позднее, это отдельный профиль с собственной измеренной задержкой.
@@ -6,6 +6,12 @@
существующего Ubuntu Mac mini. Ниже разделены выполненные проверки и оставшаяся
приёмка; успешная полная автономность пока не доказана.
**Уточнение RESEARCH01:** [исследование Android reconnect](12_INSTA360_X4_ANDROID_RECONNECT_RESEARCH.md)
выявило внутренний udisk_mode и независимый BLE remote off/on. Ближайший шаг —
проверка беспроводного управления и чтение настройки у точной X4 через versioned
artifact. Отсутствие VBUS switching в PORT01 не доказывает невозможность
программного восстановления камеры; внешний хаб остаётся альтернативной веткой.
## Что подтверждено
- Rover006 online через Tailscale, Node0.8.19. Модель X4 обновлена штатной подготовкой PREP05 до0.1.3-3;
@@ -128,13 +134,16 @@ returncode0,stderr empty. USB2 и USB3 root hubs имеют wHubCharacteristic0x
переключения VBUS этот контроллер не предоставляет; попытка sysfs disable
не рассматривается как доказанный power cycle. Root/port writes не выполнялись.
Следующий путь полного автономного восстановления требует отдельно проверить
Для аппаратной ветки восстановления требуется отдельно проверить
хаб с индивидуальным VBUS switching и достаточным внешним питанием. Само
отключение VBUS при батарее не перезапускает гарантированно X4; режим без
батареи и USB power-on требуют отдельной аппаратной приёмки. До её появления
подтверждённый способ возврата — camera off/on, затем USB in (REPLUG02).
Никакая новая покупка/схема питания здесь не выполнялась. Программный recovery
SDK/preview остаётся отдельным инкрементом после возврата правильного USB mode.
RESEARCH01 отменяет прежний приоритет обязательного хаба: сначала проверяется
беспроводной возврат режима либо BLE off/on самой камеры по плану12. Возможности
портов, измеренные в PORT01, этим исследованием не опровергаются.
## Поведение текущего приложения
@@ -187,6 +196,12 @@ disconnect для части прошивок; текущий bridge его не
Приоритет владельца: после применения B11 поставить автономность и питание
перед расширением настроек камеры и загрузкой файлов.
Первый текущий эксперимент — RESEARCH01 из плана12: BLE identity/transport,
read-only GetOptions95, затем только при подтверждённой семантике setter;
резерв — эмуляция пульта и BLE off/on с уже вставленным USB. Остальная матрица
ниже сохраняется; аппаратная ветка5 больше не является обязательным условием
исследования программного обхода.
| Шаг | Проверка и результат |
|---|---|
| 1. Стабильный baseline — PREP05/LIVE06 пройден | Штатный preview STOP при подтверждённом recording0 → model preparation B11 из Core/Node → START, повторный START, verify, viewer reopen. Сохранить timestamps и реальные кадры. |
@@ -0,0 +1,142 @@
# X4: возврат Control with Android после USB out/in
RESEARCH01, 10.09.2026. Запрос владельца: исследовать именно повторное подключение
включённой X4 и возможность программно вернуть Android mode. Это исследование
документации и исходных данных, не аппаратная приёмка новой команды.
## Вывод и исправление предыдущего плана
Штатно X4 должна помнить последний USB mode. Подтверждённой готовой команды,
которая возвращает X4 v1.7.18 в Android после нашего отказа, пока нет. Однако
обнаружены конкретный параметр внутреннего протокола и независимый BLE путь
выключения/пробуждения. Программную автономность нельзя объявлять невозможной.
PORT01 достоверно установил отсутствие стандартного VBUS switching встроенного
Mini. Это ограничение USB-контроллера, а не доказательство отсутствия способов
перезапуска/переключения самой камеры. Управляемый хаб больше не является
обязательным ближайшим шагом: сначала проверяется беспроводной control path.
## Что говорят первичные источники
1. [Официальная инструкция X4](https://onlinemanual.insta360.com/x4/en-us/operating-tutorials/connect/connect-app)
описывает сохранение последнего режима и его повторное использование при
следующем подключении. Исключение — Reverse Charging. Наш REPLUG02 подтвердил
память после camera off/on→USB in, но REPLUG01/03 без camera restart не прошли.
Инструкция описывает ожидаемое поведение, не гарантирует исправность нашей
комбинации firmware/host/питание.
2. [Официальное устранение USB-проблем X4](https://onlinemanual.insta360.com/x4/en-us/troubleshooting/connect/connect-computer)
отдельно разбирает отсутствие USB-страницы: если она не появилась за 5 s,
предлагается перезапуск камеры и повторное подключение. Это близкий симптом,
но не точный отчёт об Android hot-replug на нашей версии.
3. [Desktop Camera API](https://insta360develop.github.io/Insta360-Developer_Docs/en/x/desktop/camera/)
требует Android mode до открытия SDK. После неожиданного отключения —
Close, новое discovery, новый Camera/Open. Публичного SetUsbMode нет;
ShutdownCamera документирован для X5+. Этот SDK recovery не доставит
команду устройству, отсутствующему на USB.
4. [Integration FAQ](https://onlinemanual.insta360.com/developer/en-us/resource/integration)
разделяет USB-only Desktop SDK и BLE/Wi-Fi мобильных SDK. Его Q23 связывает
неуспешный переход с нестабильным питанием и предлагает powered-hub control.
Это возможная причина и контрольный опыт, не диагноз нашего случая.
5. [Android Camera API](https://insta360develop.github.io/Insta360-Developer_Docs/en/x/android/camera-api/)
и [OSC API](https://insta360develop.github.io/Insta360-Developer_Docs/en/x/osc/api/)
в прочитанной публичной документации не предоставляют переключатель Android
USB mode. Названия connectUsb/setCaptureMode не означают переключение USB
firmware mode. Наличие get/setOptions в OSC не доказывает, что внутренний
protobuf-параметр доступен как одноимённое OSC JSON property.
В официальном Desktop SDK API прочитаны 93 issue records (open+closed), 28
отобраны по X4/USB/Android/disconnect. Дополнительно прочитаны комментарии
к 53/62/65/76/92. [Issue 53](https://github.com/Insta360Develop/Desktop-CameraSDK-Cpp/issues/53)
разбирает старые X4 firmware 1.1.x без Android mode; проблему устранило обновление.
Это не готовое исправление нашего hot-replug на 1.7.18.
[Issue 92](https://github.com/Insta360Develop/Desktop-CameraSDK-Cpp/issues/92#issuecomment-5073231006)
описывает X5/Windows и краткое окно для установки USB-драйвера; переносить
такой рецепт на Ubuntu/X4 нельзя. Точного доказанного hot-replug workaround
для X4 в прочитанных материалах не найдено. Это ограниченный результат поиска,
а не доказательство отсутствия решения вообще.
## Внутренний параметр найден в наших закреплённых SDK bytes
Статически прочитана libCameraSDK.so 2.1.8, SHA-256
6d20aca1930101293308c056cef552c0beb8cbf1d6c7d567a79e95a52f9b1373.
Код библиотеки не загружался и не выполнялся. Встроенные protobuf descriptors
разобраны воспроизводимым stdlib-only
[inspect_sdk_control_schema.py](../../plugins/insta360-x4/packaging/inspect_sdk_control_schema.py).
| Элемент схемы | Найденное значение |
|---|---|
| Options.udisk_mode | поле 95, enum Options.UdiskMode |
| OptionType.UDISK_MODE | 95 |
| UdiskMode | PC=0, ANDROID=1 |
| GET_OPTIONS / SET_OPTIONS | command codes 8 / 7 |
| GetOptions | repeated option_types в поле 1 |
| GetOptionsResp | option_types поле 1, Options value поле 2 |
| SetOptions | option_types поле 1, Options value поле 2 |
| REBOOT_CAMERA | command code 32, только наличие в общей схеме |
| Options.bt_wakeup_sw / OptionType.BT_WAKEUP_SW | поле 97 / enum 97 |
Это сильнее поиска строк: подтверждены номера/типы связанных protobuf fields
и оболочки Get/SetOptions. Но данные общей SDK схемы не доказывают реализацию
поля 95 в X4, разрешение записи через BLE/Wi-Fi, сохранение настройки или
немедленное переключение USB. На старых моделях этот параметр мог иметь иной
смысл; X4 нужно спросить отдельно. Числа в таблице не являются полным кадром
команды: transport/session/auth/sequence/length/framing ещё должны быть сверены.
## BLE даёт второй независимый путь
[Разбор TheAngryRaven](https://github.com/TheAngryRaven/insta360-ble-gps-spec/tree/7964f1133e5d0f2c7eb73aaaaf5d6ebdd2127199)
сообщает о наблюдениях физической X4 и GPS-пульта. Camera выступает central,
эмулятор пульта — peripheral с CE80. Через CE82 передаются события кнопок;
выключение требует удержания с последовательностью кадров, один пакет может
только изменить состояние экрана. Отдельная адресная BLE-реклама пробуждает
камеру по её serial suffix. Это первичный отчёт автора; raw capture и версия
firmware в скачанном README не приложены, на нашей X4 не проверено.
Независимые официальные основания:
[X4 поддерживает GPS-пульты](https://onlinemanual.insta360.com/x4/en-us/faq/compatibility/accessory),
[пульт умеет выключать подключённую камеру](https://onlinemanual.insta360.com/gpspreviewremote/en-us/camera/basicuse),
[Android SDK описывает BLE wake-up с CameraType.X4](https://insta360develop.github.io/Insta360-Developer_Docs/en/x/android/camera-integration/).
Они подтверждают наличие класса функций, не всю последовательность
BLE off/on→USB Android на нашей связке.
Прямое управление из приложения (camera BE80 server) и эмуляция GPS-пульта
(host CE80 server) — разные протоколы и роли. Их framing/auth не смешиваются.
[xaionaro-go/insta360ctl](https://github.com/xaionaro-go/insta360ctl/tree/f94193ce03c5af0921a9992bfd1af6bd946150d0)
— кандидат для изучения Linux BLE/Wi-Fi transport, не готовая зависимость.
В прочитанном коде direct PowerOff использует legacy 0x37, помеченный там же
как официальный GetSyncCaptureMode; SetMode использует legacy 0x0c, помеченный
как DeleteFiles с GO 3-спецификой. Remote PowerOff отправляет одно событие, тогда
как X4-отчёт выше требует удержания. Слепой запуск CLI на X4 не допускается;
README support matrix не заменяет проверку точных команд. Код не запускался.
## Следующий эксперимент и критерии решения
1. Подготовить versioned X4 diagnostic/control artifact. Использовать существующую
Ubuntu, изоляцию экземпляра, явный allowlist команд и session journal. Все новые
BlueZ/Python dependencies, permissions и persistent pairing — через installer.
Не устанавливать исследовательский CLI глобально и не менять маршруты Node.
2. Проверить доступный BLE adapter/role и связь с точной X4 при её отсутствии
на USB. Первое pairing может требовать локального подтверждения. Сопоставлять
полную hardware identity, не только suffix/MAC/имя; никакого auto-merge камер.
3. После доказанного framing/auth и identity читать состояние и Options 95.
Unsupported/timeout/default scalar без присутствия поля не считать успешным
чтением. Если транспорт BLE не предоставляет параметр — исследовать Wi-Fi
control, сохраняя Tailscale/Core uplink и ownership SDK.
4. Только после успешного чтения и проверки семантики допустить ограниченную
запись прежнего Android value, с readback, UTC/monotonic и USB observer.
Если уже ANDROID=1, простое сохранение предпочтения может не перезапустить
USB — это отдельный отрицательный исход. При неясном результате повторной
записи нет. PC→Android цикл не допускать без проверенного возврата.
5. Если прямой путь не действует — отдельный опыт эмуляции пульта BLE off/on,
с подтверждённым отсутствием SD-записи и включённым/проверенным wake-up до
выключения. Нужна работоспособность при уже вставленном USB: наш прежний
успех off/on→USB in не доказывает этот другой порядок.
6. Успех — без рук появляется прежняя X4 в 2e1a:0002, новая SDK session и свежий
кадр в Core; остальные камеры/Node online. Повторить несколько циклов.
ACK, новое BLE соединение или появление Mass Storage успехом не являются.
Если поле 95 отвергнуто, это закрывает только данный setter. Если BLE-пульт
off/on не восстановил USB, это закрывает конкретную последовательность.
Управляемое питание и firmware остаются отдельными альтернативами. Ни успех
автономности, ни её принципиальная невозможность текущим исследованием не доказаны.
@@ -0,0 +1,102 @@
"""Read selected protobuf descriptors from the pinned SDK without loading its code.
Research only: schema presence does not establish X4 firmware support, writability,
transport availability or a complete command frame. No device/network access.
"""
import hashlib
import json
import re
import time
from datetime import datetime, timezone
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SDK_SHA256 = "6d20aca1930101293308c056cef552c0beb8cbf1d6c7d567a79e95a52f9b1373"
FILES = {"options.proto", "message_code.proto", "commands/get_options.proto", "commands/set_options.proto"}
OPTIONS = {"udisk_mode", "bt_wakeup_sw"}
VALUES = {"UDISK_MODE", "UDISK_MODE_PC", "UDISK_MODE_ANDROID", "BT_WAKEUP_SW",
"PHONE_COMMAND_GET_OPTIONS", "PHONE_COMMAND_SET_OPTIONS", "PHONE_COMMAND_REBOOT_CAMERA"}
def varint(data, cursor):
result = 0
for shift in range(0, 70, 7):
value = data[cursor]
cursor += 1
result |= (value & 127) << shift
if not value & 128:
return result, cursor
raise ValueError("Invalid varint")
def fields(data, terminated=False):
result, cursor = {}, 0
while cursor < len(data):
key, cursor = varint(data, cursor)
if key == 0 and terminated:
break
number, wire = key >> 3, key & 7
if not number:
raise ValueError("Invalid field number")
if wire == 0:
value, cursor = varint(data, cursor)
elif wire == 2:
length, cursor = varint(data, cursor)
value = data[cursor:cursor + length]
cursor += length
if len(value) != length:
raise ValueError("Truncated field")
else:
raise ValueError("Unsupported descriptor wire type")
result.setdefault(number, []).append(value)
return result
def name(record):
return record[1][0].decode("utf-8")
def enum(record):
return {name(item): item[2][0] for raw in record.get(2, [])
if (item := fields(raw)) and name(item) in VALUES}
def message(record, all_fields=False):
selected = []
for raw in record.get(2, []):
field = fields(raw)
if all_fields or name(field) in OPTIONS:
selected.append({"name": name(field), "number": field[3][0],
"label": field[4][0], "type": field[5][0],
"type_name": field.get(6, [b""])[0].decode()})
enums = {name(item): values for raw in record.get(4, [])
if (item := fields(raw)) and (values := enum(item))}
return {"fields": selected, "enums": enums}
def inspect(data):
if hashlib.sha256(data).hexdigest() != SDK_SHA256:
raise ValueError("SDK bytes differ from the inspected version")
found = {}
for match in re.finditer(rb"\n([\x01-\x7f])([\w/.-]+\.proto)\x12", data):
filename = match[2].decode()
if match[1][0] != len(match[2]) or filename not in FILES:
continue
descriptor = fields(data[match.start():match.start() + 65536], terminated=True)
messages = {name(item): message(item, filename.startswith("commands/"))
for raw in descriptor.get(4, []) if (item := fields(raw))}
found[filename] = {"offset": match.start(), "messages": messages,
"enums": {name(item): enum(item) for raw in descriptor.get(5, [])
if (item := fields(raw)) and enum(item)}}
if set(found) != FILES:
raise ValueError("Required descriptors not found")
return found
if __name__ == "__main__":
data = (ROOT / "build/sdk/lib/libCameraSDK.so").read_bytes()
print(json.dumps({"session": "RESEARCH01-schema", "utc": datetime.now(timezone.utc).isoformat(),
"monotonic": time.monotonic(), "sdk_sha256": SDK_SHA256,
"source_sha256": hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
"hardware_tested": False, "descriptors": inspect(data)}, indent=2))