Document BLE startup sequencing and honor publication deadline

This commit is contained in:
evgeny committed 2026-10-30 17:55:26 +01:00
1 parent e81fe7030a
commit 8a02704f8b
2 files changed
+29 -4

No files matched your search

+22 -3
View File
@@ -290,21 +290,40 @@ payload_bytes — тело manufacturer data, manufacturer_ad_bytes включа
company ID, AD type и length; это не размер полного пакета, сформированного Windows.
Windows: проверка конкуренции GATT и manufacturer publisher на реальном адаптере:
Рабочий desktop передаёт initial_advertisement в ble_config до ble_start. Windows
сначала запускает publisher, проверяет событие Started и текущий Publisher.Status,
затем создаёт GATT-сервис/характеристики и запускает GATT-рекламу/scan. BLE_READY
выдаётся один раз, только после готовности GATT и scan. Без начального объявления
GATT/scan запускаются сразу. BlueZ/Android применяют начальные байты при готовности;
повтор тех же байтов в WinRT — no-op, без Stop/Start publisher.
Смена имени или включение объявления при работающем GATT временно останавливает
только GATT-рекламу, дожидается Stopped/Success либо Aborted/Success на Windows 1809,
обновляет publisher и возвращает GATT-рекламу после его Started. Существующие links
код не закрывает; доступность новых входящих в этот промежуток ограничена. Ошибка ОС
или таймаут публикации 20s переводит BLE в ошибку с причиной в GUI/логе. При выключении
объявления GATT-реклама сохраняется/восстанавливается. Изменения не касаются wire v4,
ACK, tx_window, RX-счётчиков и пакетирования звонков.
В рабочем логе ожидаются create GATT after publication enabled=1 publisher=2,
затем start GATT advertisement, service advertising state=2 и WinRT scan/GATT ready.
1. Закрыть VibeChat и другие экземпляры probe на проверяемом ПК.
2. После обычной сборки chatgui перейти в tools/chatgui/build и запустить:
.\ble_advertising_probe.exe
Либо собрать отдельно цель ble_advertising_probe в lib/ble (CMake, Windows).
3. Приложить ble_advertising_probe.log из текущего каталога.
Утилита создаёт тот же GATT-сервис/характеристики, scan и 18-байтовое объявление probe18
Утилита использует изолированный publisher, чтобы автоматическое согласование
публикаций рабочего backend не изменяло условия эксперимента. Она создаёт тот же
GATT-сервис/характеристики, scan и 18-байтовое объявление probe18
текущей wire-версии. Входящие подключения отклоняются: это тест обнаружения, не чат.
Три окна по 20 секунд: gatt_on, gatt_off, gatt_restored. Можно передать длительность
каждого окна 10..60 секунд единственным аргументом; startup ограничен ещё 20 секундами.
Publisher, payload и scan остаются теми же; меняется только реклама GATT-сервиса.
Только в probe явно запрошенная остановка принимает Stopped/Success и Aborted/Success:
Явно запрошенная остановка принимает Stopped/Success и Aborted/Success:
последний ответ наблюдается на Windows 1809. Подтверждение пишется как requested GATT
stop confirmed; без события остановки один снимок статуса не завершает этап gatt_off.
При восстановлении требуется новое событие Started. Ненулевой BluetoothError и Aborted
без запроса остановки остаются фатальными. Обработчик обычного чата этим не изменён.
без запроса остановки остаются фатальными. Рабочий backend использует то же правило
при замене publisher; экспериментальное ручное переключение остаётся только в probe.
В result: количество наблюдений Started/Waiting при нужном состоянии GATT и работающем
scan, unsettled_samples (переходные состояния), задержка первого Started и конечные
состояния ОС. first_started_ms имеет смысл только при started_samples>0.
+7 -1
View File
@@ -175,7 +175,12 @@ struct WinState : std::enable_shared_from_this<WinState> {
s.discovery_stats("periodic");
s.publication_timeout();
if (s.stopped || s.failed) return;
s.diagnostics_timer = uasync_set_timeout(s.ua, 100000, &s, diagnostics_tick, "ble_winrt_diagnostics"); /* 10s, TB=0.1ms. */
uint64_t delay = 100000; /* Сводка раз в 10s, но deadline publisher обслуживается без лишних 10s ожидания. TB=0.1ms. */
if (s.publication_deadline) {
auto now = get_time_us();
delay = std::min(delay, s.publication_deadline > now ? (s.publication_deadline - now + 99) / 100 : uint64_t(1));
}
s.diagnostics_timer = uasync_set_timeout(s.ua, delay, &s, diagnostics_tick, "ble_winrt_diagnostics");
if (!s.diagnostics_timer) DEBUG_WARN(CAT, "BLE WinRT diagnostics timer allocation failed; periodic summaries unavailable");
}
static void dispatch(void* arg) {
@@ -305,6 +310,7 @@ struct WinState : std::enable_shared_from_this<WinState> {
/* Первичная регистрация — только после Started publisher либо при выключенном объявлении. */
void ensure_service() {
if (!adapter_ready || failed || stopped || service_stop_pending) return;
if (broadcast_enabled && (publication_pending || publisher_status != int(BluetoothLEAdvertisementPublisherStatus::Started))) return;
if (!server_created) {
server_created = true;
DEBUG_INFO(CAT, "BLE WinRT create GATT after publication enabled=%d publisher=%d", broadcast_enabled, publisher_status);