Registre des appareils

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 :

NiveauDescriptionExemple
Codés en durAppareils enregistrés directement dans le code avec des fabriques personnaliséesOSSM
DynamiquesAppareils chargés depuis registry.json à l'aide de la fabrique ButtplugIOLovense, 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;

DeviceFactory est défini comme suit :

typedef Device *(*DeviceFactory)(const NimBLEAdvertisedDevice *advertisedDevice);

Fonctions clés

FonctionBut
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é :

  1. ButtplugIODeviceFactory lit registry.json depuis LittleFS
  2. Récupère la liste des fichiers de spécifications pour l'UUID de service
  3. 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
  4. Crée une instance LovenseDevice avec 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"
        }
      }
    }
  }]
}
ChampBut
defaultsNom de l'appareil par défaut et ensemble de fonctionnalités
configurationsVariantes et identifiants spécifiques à l'appareil
communication[].btle.namesModèles de nom de périphérique (prend en charge le caractère générique *)
communication[].btle.servicesUUID 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     │
└──────────────┘     └──────────────┘     └──────────────┘     └──────────────┘
  1. Scan : RADR recherche des appareils BLE
  2. Extraire l'UUID : récupère l'UUID du service annoncé
  3. Recherche dans le registre : getDeviceFactory(serviceUUID) trouve la fabrique
  4. 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.json

Mettre à 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 :

  1. Modifiez data/registry.json ou ajoutez des fichiers de spécifications à data/protocols/
  2. Dans VS Code avec PlatformIO, cliquez sur Upload Filesystem (ou exécutez pio run --target uploadfs)
  3. 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 :

  1. Accédez à Settings > Look for updates sur l'appareil.
  2. RADR vérifie les mises à jour du registre à partir du serveur
  3. Les fichiers registry.json et de protocole mis à jour sont téléchargés OTA
  4. La prise en charge des nouveaux appareils est disponible sans mise à jour complète du micrologiciel

Fichiers sources clés

FichierBut
src/devices/registry.hInterface de registre et définitions de types
src/devices/registry.cppImplémentation et initialisation du registre
src/devices/buttplugio/buttplugIOFactory.cppFabrique d'appareils dynamiques
src/devices/device.hClasse d'appareil de base
data/registry.jsonAssociations entre UUID de service et fichiers de spécifications
data/protocols/*.jsonSpécifications d'appareils Buttplug.io v4

Lectures complémentaires

Sur cette page