diff --git a/lib/ble/ble_bluez.c b/lib/ble/ble_bluez.c index 46af9753b..572fba6d4 100644 --- a/lib/ble/ble_bluez.c +++ b/lib/ble/ble_bluez.c @@ -445,7 +445,9 @@ static int properties(struct ble_backend* b, const char* path, const char* inter if (l->connected && l->resolved && !l->opened && !l->query && query_link(l) < 0) link_error(l, "discovery request failed"); } - if (mode == OBJECT_EVENT && strlen(path) < BLE_ENDPOINT_MAX) { + /* Snapshot запоминает UUID кешированного Device1, но не выдаёт его за свежий эфирный пакет. + * BlueZ не обязан повторять неизменившиеся UUIDs: следующий живой RSSI/Data использует этот кеш. */ + if ((mode == OBJECT_EVENT || (mode == OBJECT_SNAPSHOT && node)) && strlen(path) < BLE_ENDPOINT_MAX) { int slot = -1, oldest = 0; for (int i = 0; i < 64; i++) { if (!strcmp(b->peers[i].device, path)) { slot = i; break; } @@ -457,7 +459,8 @@ static int properties(struct ble_backend* b, const char* path, const char* inter if (node && b->peers[slot].identity.node_id != node) { memset(&b->peers[slot], 0, sizeof(b->peers[slot])); strcpy(b->peers[slot].device, path); b->peers[slot].identity.node_id = node; - DEBUG_INFO(CAT, "BLE BlueZ service discovered node=%016llx endpoint=%s", (unsigned long long)node, path); + DEBUG_DEBUG(CAT, "BLE BlueZ service identity cached node=%016llx endpoint=%s source=%s", + (unsigned long long)node, path, mode == OBJECT_EVENT ? "live" : "snapshot"); } struct ble_identity* identity = &b->peers[slot].identity; struct ble_identity metadata; @@ -468,7 +471,10 @@ static int properties(struct ble_backend* b, const char* path, const char* inter if (n > 0) ble_identity_decode(identity, data, (size_t)n); } int n = ble_identity_encode(data, identity->node_id, identity->name); - if (n > 0) { + if (n > 0 && mode == OBJECT_EVENT) { + if (!b->peers[slot].seen) + DEBUG_INFO(CAT, "BLE BlueZ service discovered node=%016llx endpoint=%s", + (unsigned long long)identity->node_id, path); struct ble_endpoint ep = {0}; strcpy(ep.id, path); b->peers[slot].seen = get_time_us(); ble_backend_broadcast(b->owner, &ep, data, (size_t)n, rssi); } diff --git a/lib/ble/tests/test_ble_bluez.c b/lib/ble/tests/test_ble_bluez.c index 7f02c43ea..a1be51cc9 100644 --- a/lib/ble/tests/test_ble_bluez.c +++ b/lib/ble/tests/test_ble_bluez.c @@ -199,7 +199,7 @@ static void connection(void* arg, ble_link_id id, uint64_t node, enum ble_state if (state == BLE_CLOSED) closed_links++; } static void broadcast(void* arg, const struct ble_endpoint* ep, const uint8_t* data, size_t len, int rssi) { - (void)arg; struct ble_identity identity; CHECK(strstr(ep->id, "dev_A")); + (void)arg; struct ble_identity identity; CHECK(strstr(ep->id, "dev_A") || !strcmp(ep->id, REMOTE)); CHECK(!ble_identity_decode(&identity, data, len) && identity.node_id == 3); CHECK(rssi == -42); broadcasts++; } static int replied(sd_bus_message* m, void* arg, sd_bus_error* error) { @@ -228,12 +228,14 @@ static void write_value(const char* device, const uint8_t* data, size_t len, int CHECK(sd_bus_call_async(bus, &reply.slot, m, replied, &reply, 1000000) >= 0); sd_bus_message_unref(m); poll_all(); CHECK(reply.done && !reply.failed); sd_bus_slot_unref(reply.slot); } -static void announce(void) { +static void announce(const char* path, int with_uuid) { sd_bus_message* m = NULL; - CHECK(sd_bus_message_new_signal(bus, &m, ADAPTER "/dev_A", "org.freedesktop.DBus.Properties", "PropertiesChanged") >= 0); - CHECK(sd_bus_message_append(m, "sa{sv}as", "org.bluez.Device1", 2, + CHECK(sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.Properties", "PropertiesChanged") >= 0); + if (with_uuid) CHECK(sd_bus_message_append(m, "sa{sv}as", "org.bluez.Device1", 2, "UUIDs", "as", 1, service_uuid, "RSSI", "n", -42, 0) >= 0); - CHECK(sd_bus_send(bus, m, NULL) >= 0); sd_bus_message_unref(m); poll_all(); CHECK(broadcasts == 1); + else CHECK(sd_bus_message_append(m, "sa{sv}as", "org.bluez.Device1", 1, "RSSI", "n", -42, 0) >= 0); + unsigned before = broadcasts; + CHECK(sd_bus_send(bus, m, NULL) >= 0); sd_bus_message_unref(m); poll_all(); CHECK(broadcasts == before + 1); } static void hello(const char* device, int fd, uint8_t node) { uint8_t data[32] = {0, 1, 1}; data[10] = node; data[18] = 200; @@ -272,7 +274,8 @@ int main(void) { CHECK(advertisement_queries == 1 && advertisement_uuid_count == 1); CHECK(!ble_advertise(transport, "abc", 3)); poll_all(); CHECK(advertisement_count == 1); CHECK(!ble_advertise(transport, "def", 3)); poll_all(); CHECK(advertisement_count == 2); - announce(); + announce(REMOTE, 0); /* UUID был лишь в начальном snapshot; живой RSSI делает наблюдение свежим. */ + announce(ADAPTER "/dev_A", 1); int fd1 = acquire(ADAPTER "/dev_A", 0), fd2 = acquire(ADAPTER "/dev_B", 0); int invite1 = acquire(ADAPTER "/dev_A", 1), invite2 = acquire(ADAPTER "/dev_B", 1); CHECK(ready_links == 0); /* Без обязательной ACK-подписки opened не наступает. */