Comment RADR découvre et crée des instances de périphérique à partir des UUID de service BLE
Le registre des appareils est le système principal qui associe les UUID de service Bluetooth Low Energy (BLE) aux fabriques d’appareils. Lorsque RADR recherche des appareils, il utilise les UUID de service pour déterminer quelle fabrique doit créer l’instance de périphérique.
Présentation de l'architecture
RADR utilise un système de registre à deux niveaux :
| Niveau | Description | Exemple |
|---|---|---|
| Codés en dur | Appareils enregistrés directement dans le code avec des fabriques personnalisées | OSSM |
| Dynamiques | Appareils chargés depuis registry.json à l'aide de la fabrique ButtplugIO | Lovense, Satisfyer, Kiiroo |
┌─────────────────────────────────────────────────────────────┐
│ Device Registry │
│ │
│ ┌─────────────────────┐ ┌─────────────────────────────┐│
│ │ Hardcoded Devices │ │ Dynamic Devices ││
│ │ (Custom Factory) │ │ (ButtplugIOFactory) ││
│ │ │ │ ││
│ │ Service UUID → │ │ registry.json → ││
│ │ Lambda → Device │ │ Service UUID → ││
│ │ │ │ Spec files → Device ││
│ └─────────────────────┘ └─────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘Le registre est renseigné une fois au démarrage de l'appareil via initRegistry().
Structure du registre
Le registre est une table globale qui associe les UUID de service aux fonctions de fabrique :
std::unordered_map<std::string, DeviceFactory> registry;où DeviceFactory est défini comme suit :
typedef Device *(*DeviceFactory)(const NimBLEAdvertisedDevice *advertisedDevice);Fonctions clés
| Fonction | But |
|---|---|
initRegistry() | Remplit le registre avec des appareils codés en dur et dynamiques |
getDeviceFactory() | Recherche une fabrique à partir de l’UUID de service |
Appareils codés en dur
Les appareils codés en dur sont enregistrés directement dans initRegistry() avec une fabrique lambda. Cette approche est utilisée pour les appareils dotés de protocoles personnalisés qui nécessitent une gestion spécialisée.
Exemple OSSM
registry.emplace(
OSSM_SERVICE_ID, // "522B443A-4F53-534D-0001-420BADBABE69"
[](const NimBLEAdvertisedDevice *advertisedDevice) -> Device * {
return new OSSM(advertisedDevice);
});L'OSSM utilise un protocole BLE personnalisé avec plusieurs caractéristiques pour la vitesse, la profondeur, la sensation et le contrôle de la course. Cela nécessite une classe d'appareil dédiée plutôt que l'implémentation générique de ButtplugIO.
Quand utiliser l’enregistrement codé en dur
Utilisez l'enregistrement codé en dur lorsque :
- L'appareil utilise un protocole personnalisé non couvert par Buttplug.io
- Vous avez besoin d'une interface utilisateur spécialisée ou d'une logique de contrôle
- L'appareil nécessite une gestion spécifique des caractéristiques
Appareils dynamiques (ButtplugIO)
Les appareils dynamiques sont chargés à partir du fichier data/registry.json sur le système de fichiers. Cela permet d'ajouter la prise en charge de nouveaux appareils sans modifier le code.
Structure de registry.json
Le registre associe les UUID de service à des tableaux de fichiers de spécifications de protocole :
{
"0000fff0-0000-1000-8000-00805f9b34fb": ["/protocols/lovense.json"],
"88f80580-0000-01e6-aace-0002a5d5c51b": ["/protocols/kiiroo-v2.json"],
"51361500-c5e7-47c7-8a6e-47ebc99d80e8": ["/protocols/satisfyer.json"]
}Chaque entrée associe un UUID de service BLE (clé) à un ou plusieurs fichiers de spécification de protocole (tableau de valeurs).
Flux de la fabrique
Lorsqu'un appareil avec un UUID de service enregistré est détecté :
ButtplugIODeviceFactorylitregistry.jsondepuis LittleFS- Récupère la liste des fichiers de spécifications pour l'UUID de service
- Pour chaque fichier de spécifications :
- Charge et analyse la configuration JSON
- Compare le nom de l'appareil annoncé aux modèles
communication[0].btle.names - Extrait les caractéristiques TX/RX pour l'UUID de service
- Crée une instance
LovenseDeviceavec la configuration correspondante
Format de fichier de spécifications de protocole
Les fichiers de spécifications suivent le format Buttplug.io v4 :
{
"defaults": {
"name": "Lovense Device",
"features": [...]
},
"configurations": [
{
"identifier": ["B"],
"name": "Max",
"features": [...]
}
],
"communication": [{
"btle": {
"names": ["LVS-*", "LOVE-*"],
"services": {
"0000fff0-0000-1000-8000-00805f9b34fb": {
"tx": "0000fff2-0000-1000-8000-00805f9b34fb",
"rx": "0000fff1-0000-1000-8000-00805f9b34fb"
}
}
}
}]
}| Champ | But |
|---|---|
defaults | Nom de l'appareil par défaut et ensemble de fonctionnalités |
configurations | Variantes et identifiants spécifiques à l'appareil |
communication[].btle.names | Modèles de nom de périphérique (prend en charge le caractère générique *) |
communication[].btle.services | UUID des caractéristiques TX/RX par service |
Flux de découverte des appareils
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ BLE Scan │────▶│ Get Service │────▶│ Lookup in │────▶│ Factory │
│ Discovers │ │ UUID │ │ Registry │ │ Creates │
│ Device │ │ │ │ │ │ Device │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘- Scan : RADR recherche des appareils BLE
- Extraire l'UUID : récupère l'UUID du service annoncé
- Recherche dans le registre :
getDeviceFactory(serviceUUID)trouve la fabrique - Créer un appareil : la fabrique instancie la classe d'appareil appropriée
Ajout de la prise en charge de nouveaux appareils
Option A : dynamique (registre Buttplug.io)
Pour les appareils compatibles avec le protocole Buttplug.io :
Obtenir ou créer le fichier de spécifications
Obtenez la spécification du protocole Buttplug.io v4 pour l'appareil. Celle-ci est disponible dans le dépôt de configuration des appareils Buttplug.
Ajouter un fichier de spécifications aux protocoles
Placez le fichier de spécifications JSON dans data/protocols/ :
data/protocols/your-device.jsonMettre à jour `registry.json`
Ajoutez le mappage UUID du service à data/registry.json :
{
"your-service-uuid": ["/protocols/your-device.json"]
}Téléverser le système de fichiers
Utilisez PlatformIO pour téléverser le système de fichiers sur l'appareil.
Option B : codé en dur (protocole personnalisé)
Pour les appareils nécessitant une gestion de protocole personnalisée :
Créer une classe d'appareil
Créez une nouvelle classe d'appareil dans src/devices/ qui étend la classe de base Device.
Mettre en œuvre les méthodes requises
Implémentez getServiceUUID(), getName() et toute logique de contrôle spécifique à l'appareil.
Enregistrer l'appareil dans initRegistry
Ajoutez le code d'enregistrement dans initRegistry() :
registry.emplace(
YOUR_SERVICE_UUID,
[](const NimBLEAdvertisedDevice *adv) -> Device * {
return new YourDevice(adv);
});Reconstruire le micrologiciel
Compilez et flashez le micrologiciel mis à jour.
Flux de travail de développement
Mise à jour du registre (développement)
Lors du développement local, utilisez la fonctionnalité « Upload Filesystem » de PlatformIO pour flasher le répertoire data/ sur LittleFS :
- Modifiez
data/registry.jsonou ajoutez des fichiers de spécifications àdata/protocols/ - Dans VS Code avec PlatformIO, cliquez sur Upload Filesystem (ou exécutez
pio run --target uploadfs) - L'appareil utilisera le registre mis à jour au prochain démarrage
"Upload Filesystem" efface la partition LittleFS existante avant l'écriture. Toutes les modifications effectuées pendant l'exécution seront perdues.
Mise à jour du registre (production)
Les mises à jour du registre OTA sont une fonctionnalité en attente. Actuellement, les mises à jour du registre nécessitent un flash du micrologiciel.
Le flux de travail prévu pour les appareils de production :
- Accédez à Settings > Look for updates sur l'appareil.
- RADR vérifie les mises à jour du registre à partir du serveur
- Les fichiers
registry.jsonet de protocole mis à jour sont téléchargés OTA - La prise en charge des nouveaux appareils est disponible sans mise à jour complète du micrologiciel
Fichiers sources clés
| Fichier | But |
|---|---|
src/devices/registry.h | Interface de registre et définitions de types |
src/devices/registry.cpp | Implémentation et initialisation du registre |
src/devices/buttplugio/buttplugIOFactory.cpp | Fabrique d'appareils dynamiques |
src/devices/device.h | Classe d'appareil de base |
data/registry.json | Associations entre UUID de service et fichiers de spécifications |
data/protocols/*.json | Spécifications d'appareils Buttplug.io v4 |