diff --git a/lib/ble/ble_backend.h b/lib/ble/ble_backend.h index 0417b0e0..1b5b9067 100644 --- a/lib/ble/ble_backend.h +++ b/lib/ble/ble_backend.h @@ -6,10 +6,10 @@ #ifndef VIBECHAT_BLE_BACKEND_H #define VIBECHAT_BLE_BACKEND_H #include "ble_transport.h" +#include "ble_identity.h" #ifdef __cplusplus extern "C" { #endif -#define BLE_SERVICE_UUID "f61a9020-4abc-45ac-98e1-761df4c13811" #define BLE_RX_UUID "f61a9021-4abc-45ac-98e1-761df4c13811" #define BLE_TX_UUID "f61a9022-4abc-45ac-98e1-761df4c13811" #define BLE_INVITE_UUID "f61a9023-4abc-45ac-98e1-761df4c13811" diff --git a/lib/ble/ble_identity.c b/lib/ble/ble_identity.c index 7c8cf09c..fe85b178 100644 --- a/lib/ble/ble_identity.c +++ b/lib/ble/ble_identity.c @@ -1,6 +1,7 @@ #include "ble_identity.h" #include "../debug_config.h" #include +#include /* Строгая проверка scalar value: запрещены overlong, surrogate и > U+10FFFF. */ static int character(const unsigned char* p, size_t n) { unsigned v; int k; @@ -15,6 +16,26 @@ static int character(const unsigned char* p, size_t n) { if ((k == 3 && v < 0x800) || (k == 4 && v < 0x10000) || (v >= 0xd800 && v <= 0xdfff) || v > 0x10ffff) return -1; return k; } +int ble_service_uuid_encode(char out[37], uint64_t id) { + if (!out || !id) { DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "BLE service UUID requires output and nonzero node ID"); return -1; } + snprintf(out, 37, "f61a9020-%04x-4505-98e1-%012llx", (unsigned)(id >> 48), (unsigned long long)(id & UINT64_C(0xffffffffffff))); + return 0; +} +int ble_service_uuid_decode(const char* uuid, uint64_t* node_id) { + if (!uuid || !node_id || strlen(uuid) != 36) return -1; + static const char pattern[] = BLE_SERVICE_UUID_FILTER; + uint64_t id = 0; + for (unsigned i = 0; i < 36; i++) { + char c = uuid[i]; if (c >= 'A' && c <= 'F') c += 'a' - 'A'; + if ((i >= 9 && i < 13) || i >= 24) { + unsigned value = c >= '0' && c <= '9' ? (unsigned)(c - '0') : c >= 'a' && c <= 'f' ? (unsigned)(c - 'a' + 10) : 16; + if (value == 16) return -1; + id = (id << 4) | value; + } else if (c != pattern[i]) return -1; + } + if (!id) return -1; + *node_id = id; return 0; +} int ble_identity_encode(uint8_t out[24], uint64_t id, const char* name) { if (!out || !id || !name) goto invalid; size_t length = strlen(name), offset = 0; diff --git a/lib/ble/ble_identity.h b/lib/ble/ble_identity.h index d306a236..0332edaa 100644 --- a/lib/ble/ble_identity.h +++ b/lib/ble/ble_identity.h @@ -1,11 +1,14 @@ -/* Объявление VibeChat: VC, версия 4, node_id BE64, имя UTF-8 до 13 байт. +/* Идентичность VibeChat: VC, версия5, node_id BE64, имя UTF-8 до13 байт. + * Обнаружение/выбор endpoint идёт по UUID подключаемого GATT-сервиса; bytes — общий формат события/метаданных. * encode возвращает размер 11..24 либо -1; decode возвращает ble_identity_result. * Имя сокращается по целому символу; decode отклоняет неверный UTF-8 и нулевой ID. */ #ifndef VIBECHAT_BLE_IDENTITY_H #define VIBECHAT_BLE_IDENTITY_H #include #include -#define BLE_IDENTITY_VERSION 4 /* DATA с 16-bit flow ID; ACK использует Without Response/Notify. */ +#define BLE_IDENTITY_VERSION 5 /* node_id в UUID подключаемого сервиса; DATA/ACK сохраняют прежний формат. */ +#define BLE_SERVICE_UUID_FILTER "f61a9020-0000-4505-98e1-000000000000" +#define BLE_SERVICE_UUID_MASK "ffffffff-0000-ffff-ffff-000000000000" #ifdef __cplusplus extern "C" { #endif @@ -21,6 +24,10 @@ enum ble_identity_result { BLE_IDENTITY_ERR_UTF8 = -6 }; int ble_identity_encode(uint8_t output[24], uint64_t node_id, const char* name); +/* UUID: f61a9020--4505-98e1-. Canonical string37 с NUL;0/-1, ID ненулевой. */ +int ble_service_uuid_encode(char output[37], uint64_t node_id); +/* Проверить семейство/версию/ненулевой ID. Регистр hex произвольный, node_id меняется лишь при успехе;0/-1. */ +int ble_service_uuid_decode(const char* uuid, uint64_t* node_id); /* Разбирает data[size]; output меняется только при успехе. Ошибка — отрицательный код. */ int ble_identity_decode(struct ble_identity* output, const uint8_t* data, size_t size); /* Короткое имя результата decode для диагностики; возвращает статическую строку. */