13 KiB
Executable File
Feature: Classification intelligente des périphériques
Vue d'ensemble
Détection automatique du type_principal et sous_type des périphériques basée sur l'analyse du contenu CLI et des fichiers markdown.
Le système analyse intelligemment :
- Le contenu de la sortie
lsusb -v - Les fichiers markdown importés
- Les vendor/product IDs
- Les classes USB
- Les chaînes de caractères (manufacturer, product)
Fonctionnement
Stratégies de détection (par ordre de priorité)
-
USB Device Class - Basé sur
bDeviceClass08→ Clé USB (Mass Storage)03→ HID (Clavier/Souris, affiné par mots-clés)0e→ Webcam (Video)09→ Hube0→ Bluetooth (Wireless Controller)
-
Vendor/Product Info - Analyse des IDs et chaînes
- Recherche de mots-clés dans manufacturer/product strings
- Matching sur vendor_id/product_id connus
-
Analyse du contenu CLI - Mots-clés dans
lsusb -v- WiFi :
wifi,wireless,802.11,wlan,rtl81xx,mt76xx - Bluetooth :
bluetooth,bcm20702 - Storage :
mass storage,flash drive,sandisk - Hub :
usb hub,multi-port - Keyboard :
keyboard,clavier,hid.*keyboard - Mouse :
mouse,souris - Webcam :
webcam,camera,uvc - Ethernet :
ethernet,gigabit,rtl81xx.*ethernet
- WiFi :
-
Analyse du markdown - Mots-clés dans le fichier .md
- Même système de patterns que pour le CLI
- Utilisé lors de l'import de fichiers markdown
Système de scoring
- Chaque mot-clé trouvé augmente le score d'un type
- Le type avec le meilleur score est sélectionné
- Si aucun match : fallback sur
("USB", "Autre")
Exemples de détection
Exemple 1 : Adaptateur WiFi
Input CLI :
Bus 002 Device 005: ID 0bda:8176 Realtek RTL8188CUS
bDeviceClass 0
iManufacturer 1 Realtek
iProduct 2 802.11n WLAN Adapter
Détection :
- Mots-clés trouvés :
realtek,rtl8176,802.11n,wlan - Résultat :
type_principal = "USB",sous_type = "Adaptateur WiFi"
Exemple 2 : Clé USB
Input CLI :
Bus 002 Device 003: ID 0781:55ab SanDisk Corp.
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
iManufacturer 1 USB
iProduct 2 SanDisk 3.2Gen1
Interface Class: 08 — Mass Storage
Détection :
- Device Class 08 trouvé → Mass Storage
- Mots-clés :
sandisk,mass storage - Résultat :
type_principal = "USB",sous_type = "Clé USB"
Exemple 3 : Bluetooth
Input CLI :
Bus 001 Device 004: ID 0b05:17cb ASUSTek
bDeviceClass 224 Wireless
iManufacturer 1 Broadcom Corp
iProduct 2 BCM20702A0
Détection :
- Device Class e0 (Wireless Controller)
- Mots-clés :
bluetooth,bcm20702 - Résultat :
type_principal = "Bluetooth",sous_type = "Autre"
Exemple 4 : Import markdown
Fichier : ID_0bda_8176.md
# USB Device ID 0bda_8176
## Description
Realtek RTL8188CUS – Wi‑Fi USB
Détection :
- Analyse du contenu markdown
- Mots-clés :
wi-fi,usb,realtek - IDs extraits du nom de fichier :
vendor_id=0x0bda,product_id=0x8176 - Résultat :
type_principal = "USB",sous_type = "Adaptateur WiFi"
Fichiers modifiés
Backend
1. Nouveau classificateur
backend/app/utils/device_classifier.py (NOUVEAU)
Classe DeviceClassifier avec méthodes :
@staticmethod
def classify_device(cli_content: Optional[str] = None,
synthese_content: Optional[str] = None,
device_info: Optional[Dict] = None) -> Tuple[str, str]:
"""
Classify a device using all available information
Returns: (type_principal, sous_type)
"""
Dictionnaire TYPE_KEYWORDS - Mapping (type, sous_type) → liste de patterns regex
Dictionnaire USB_CLASS_MAPPING - Mapping USB class code → (type, sous_type)
2. Endpoints modifiés
backend/app/api/endpoints/peripherals.py
Ligne 28 - Import du classificateur :
from app.utils.device_classifier import DeviceClassifier
Ligne 737-746 - USB CLI extraction avec détection intelligente :
# Intelligent classification of device type
type_principal, sous_type = DeviceClassifier.classify_device(
cli_content=device_section,
synthese_content=None,
device_info=device_info
)
# Refine Bluetooth subtype if needed
if type_principal == "Bluetooth" and sous_type == "Autre":
sous_type = DeviceClassifier.refine_bluetooth_subtype(device_section)
Ligne 589-614 - Import markdown avec détection intelligente :
# Intelligent classification of device type from markdown content
type_principal = parsed_data.get("type_principal")
sous_type = parsed_data.get("sous_type")
if not type_principal or not sous_type:
device_info = {
"vendor_id": parsed_data.get("caracteristiques_specifiques", {}).get("vendor_id"),
"product_id": parsed_data.get("caracteristiques_specifiques", {}).get("product_id"),
"manufacturer": parsed_data.get("marque"),
"product": parsed_data.get("modele"),
"device_class": parsed_data.get("caracteristiques_specifiques", {}).get("device_class"),
}
detected_type_principal, detected_sous_type = DeviceClassifier.classify_device(
cli_content=None,
synthese_content=md_content,
device_info=device_info
)
if not type_principal:
type_principal = detected_type_principal
if not sous_type:
sous_type = detected_sous_type
Ligne 625 - Stockage de la synthèse markdown :
"synthese": md_content, # Store the full markdown content in synthese field
Frontend
frontend/js/peripherals.js - Ligne 452-477
Amélioration du pré-remplissage avec logique robuste :
// Set type_principal and wait for subtypes to load before setting sous_type
if (suggested.type_principal) {
document.getElementById('type_principal').value = suggested.type_principal;
// Trigger the change event to load subtypes
const typePrincipalSelect = document.getElementById('type_principal');
const changeEvent = new Event('change');
typePrincipalSelect.dispatchEvent(changeEvent);
// Wait for subtypes to load, then set sous_type
if (suggested.sous_type) {
// Use a Promise-based approach with retry logic
const setSousType = async () => {
for (let i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, 100));
const sousTypeSelect = document.getElementById('sous_type');
if (sousTypeSelect && sousTypeSelect.options.length > 1) {
// Options are loaded
sousTypeSelect.value = suggested.sous_type;
break;
}
}
};
setSousType();
}
}
Amélioration : Retry logic avec vérification du chargement des options au lieu d'un simple timeout
Flows utilisateur
Flow 1 : Import USB avec CLI
- Utilisateur clique "Importer USB"
- Popup : colle la sortie de
lsusb -v - Click "Importer"
- Backend détecte les périphériques
- Popup 2 : liste avec radio buttons
- Utilisateur sélectionne un périphérique
- Click "Finaliser"
- Backend analyse le CLI et détecte automatiquement le type
- Formulaire s'ouvre avec :
type_principal= "USB" (pré-sélectionné)sous_type= "Adaptateur WiFi" (pré-sélectionné automatiquement)nom,marque,modele,numero_seriepré-remplisclicontient le markdown formaté
Flow 2 : Import fichier markdown
- Utilisateur clique "Importer Markdown"
- Sélectionne un fichier
.md - Backend lit et analyse le contenu
- Détecte le type automatiquement depuis le markdown
- Formulaire s'ouvre avec :
type_principaletsous_typepré-sélectionnéssynthesecontient le contenu markdown complet- Autres champs extraits du markdown
Patterns de détection supportés
WiFi/Wireless
wi[‑-]?fi
wireless
802\.11[a-z]
rtl81\d+ # Realtek WiFi chips
mt76\d+ # MediaTek WiFi chips
atheros
qualcomm.*wireless
broadcom.*wireless
wlan
wireless\s+adapter
Bluetooth
bluetooth
bcm20702 # Broadcom BT chips
bt\s+adapter
Storage - Clé USB
flash\s+drive
usb\s+stick
cruzer # SanDisk Cruzer series
datatraveler # Kingston DataTraveler
usb.*flash
clé\s+usb
pendrive
Storage - Disque dur externe
external\s+hdd
external\s+ssd
portable\s+ssd
portable\s+drive
disk\s+drive
disque\s+dur\s+externe
my\s+passport # WD My Passport
expansion # Seagate Expansion
backup\s+plus # Seagate Backup Plus
elements # WD Elements
touro # Hitachi Touro
adata.*hd\d+ # ADATA external drives
Storage - Lecteur de carte
card\s+reader
lecteur.*carte
sd.*reader
microsd.*reader
multi.*card
cf.*reader
Hub
usb\s+hub
hub\s+controller
multi[‑-]?port
ZigBee
zigbee
conbee # Dresden Elektronik ConBee
cc2531 # Texas Instruments ZigBee chip
cc2652 # TI newer ZigBee chip
dresden\s+elektronik
zigbee.*gateway
zigbee.*coordinator
thread.*border
Lecteur biométrique (Fingerprint)
fingerprint
fingprint # Common typo
empreinte
biometric
biométrique
validity.*sensor # Validity sensors
synaptics.*fingerprint
goodix.*fingerprint
elan.*fingerprint
Clavier
keyboard
clavier
hid.*keyboard
Souris
mouse
souris
hid.*mouse
optical\s+mouse
Webcam
webcam
camera
video\s+capture
uvc # USB Video Class
Ethernet
ethernet
gigabit
network\s+adapter
lan\s+adapter
rtl81\d+.*ethernet
Extensibilité
Pour ajouter un nouveau type de périphérique :
- Ajouter le type dans
config/peripheral_types.yaml
- id: usb_nouveau_type
nom: Nouveau Type USB
type_principal: USB
sous_type: Mon Nouveau Type
icone: icon-name
- Ajouter les patterns dans
device_classifier.py
TYPE_KEYWORDS = {
# ...
("USB", "Mon Nouveau Type"): [
r"pattern1",
r"pattern2",
r"mot[‑-]?clé",
],
}
- Redémarrer le backend
Le nouveau type sera automatiquement :
- Détectable lors des imports
- Disponible dans les dropdowns
- Pré-sélectionné si les patterns matchent
Avantages
✅ Gain de temps - Plus besoin de sélectionner manuellement le type ✅ Précision - Détection basée sur plusieurs sources d'information ✅ Extensible - Facile d'ajouter de nouveaux types et patterns ✅ Robuste - Fallback sur "USB / Autre" si détection impossible ✅ Multilingue - Supporte patterns français et anglais ✅ Flexible - Fonctionne avec CLI et markdown
Limitations actuelles
⚠️ Périphériques hybrides - Un Unifying Receiver est détecté comme "USB / Autre" car il peut être clavier OU souris ⚠️ Périphériques rares - Types exotiques non couverts par les patterns ⚠️ Patterns manquants - Certains fabricants utilisent des termes non standards
Améliorations futures
- Machine Learning - Entraîner un modèle sur les périphériques existants
- Base de données USB ID - Intégration avec
usb.idspour reconnaissance par vendor/product - Détection multi-fonction - Support des périphériques combinés (ex: hub + ethernet)
- Historique - Apprendre des corrections manuelles utilisateur
- API externe - Interroger des APIs publiques (USB ID Repository)
Tests
Test 1 : WiFi Realtek
# Préparer un fichier test
cat > /tmp/test_wifi.txt << 'EOF'
Bus 002 Device 005: ID 0bda:8176 Realtek Semiconductor Corp.
bDeviceClass 0
iManufacturer 1 Realtek
iProduct 2 802.11n WLAN Adapter
EOF
# Dans l'interface :
# 1. Importer USB
# 2. Coller le contenu
# 3. Sélectionner le périphérique
# 4. Vérifier : type_principal = "USB", sous_type = "Adaptateur WiFi"
Résultat attendu : ✅ Détection automatique comme "Adaptateur WiFi"
Test 2 : Clé USB SanDisk
cat > /tmp/test_storage.txt << 'EOF'
Bus 002 Device 003: ID 0781:55ab SanDisk Corp.
bDeviceClass 0
iProduct 2 SanDisk 3.2Gen1
bInterfaceClass 8 Mass Storage
EOF
# Même procédure
Résultat attendu : ✅ Détection comme "Clé USB"
Test 3 : Import markdown WiFi
# Utiliser le fichier existant
# fichier_usb/ID_0bda_8176.md
Résultat attendu : ✅ Détection automatique depuis le markdown
Logs de détection
Pour débugger la détection, ajouter des logs dans DeviceClassifier.classify_device() :
logger.info(f"Classification attempt - CLI: {bool(cli_content)}, Synthese: {bool(synthese_content)}")
logger.info(f"Device info: {device_info}")
logger.info(f"Detected: type_principal={type_principal}, sous_type={sous_type}")