Aller au contenu
  1. Portfolio/

Torque Graph – Application Android Kotlin à backend interchangeable (Bluetooth / Capteurs)

Présentation #

Torque Graph est une application Android développée au CNAM, en Kotlin (Android), destinée à la mesure et à la visualisation du couple mécanique en temps réel.

L’application peut fonctionner avec deux backends physiques interchangeables :

  • Capteur réel Bluetooth RFCOMM (SPP)
  • Capteurs inertiels du téléphone (mode Dummy), où le couple est dérivé de l’angle du téléphone via l’accéléromètre

L’interface utilisateur est réalisée avec Jetpack Compose, mais la logique métier et l’accès aux données sont découplés via une architecture MVVM.

Principe clé #

Le cœur de l’application dépend uniquement de l’interface :

SmartDriverRepository

Deux implémentations concrètes existent :

ImplémentationSource de données
SmartDriverRepositoryImplCouplemètre Bluetooth RFCOMM
DummySmartDriverRepositoryAccéléromètre / orientation du téléphone

Le reste du code (Use cases, ViewModels, UI) ignore totalement si les données viennent d’un capteur réel ou d’un capteur virtuel.

Architecture globale #

graph TD UI[Jetpack Compose UI] --> VM[ViewModel] VM --> UC[Use cases] UC --> R[SmartDriverRepository] R --> BT[BluetoothSmartDriverRepository] R --> D[DummySmartDriverRepository] D --> S[OrientationService] BT --> RFCOMM[Bluetooth RFCOMM]

Séparation des couches #

Le projet suit une architecture MVVM Android avec repository (peut-être Clean / Hexagonale plus tard)


presentation/
└─ Jetpack Compose UI + ViewModels

application/
└─ Cas d’usage (ObserveSmartDriver, TareTorqueSensor, etc.)

domain/
└─ Modèles métier (TorqueSample, TorqueUnit, SmartDriver)
└─ Ports (SmartDriverRepository)

infrastructure/
└─ Implémentations techniques
├─ Bluetooth RFCOMM
└─ Capteurs Android (dummy)

shared/
└─ Filtrage, conversions, utilitaires

Pipeline de données temps réel #

Le capteur publie un flux de données continu.

sequenceDiagram autonumber participant Sensor as Capteur participant Repo as SmartDriverRepository participant UC as UseCase participant VM as ViewModel participant UI as Compose UI Sensor->>Repo: échantillons (flux) Repo->>UC: Flow<TorqueSample> UC->>VM: Flow<TorqueSample> VM->>UI: StateFlow UI->>UI: recomposition automatique

Traitement du signal #

Les valeurs de couple sont filtrées en temps réel via un filtre de Kalman :

  • Q/R dynamiques selon l’amplitude du signal
  • Limitation des sauts brutaux en fonction de la capacité du capteur
  • Deadband configurable pour éliminer le bruit faible

Cela permet d’obtenir :

  • une courbe fluide
  • une faible latence
  • une stabilité visuelle

Bluetooth RFCOMM #

La communication avec le couplemètre repose sur :

  • Bluetooth SPP (RFCOMM)
  • Encodage de trames binaires
  • Parsing robuste (FrameParser + FrameValidator)
  • Watchdog de reconnexion
  • Flux temps réel non bloquant

La couche Bluetooth est encapsulée dans le repository et n’est jamais manipulée directement par l’UI.

Mode Dummy (capteurs du téléphone) #

Lorsqu’aucun capteur Bluetooth n’est disponible, l’application fonctionne par défaut en mode Dummy, afin de permettre la démonstration sans configuration préalable.

Dans ce mode :

  • l’angle du téléphone est calculé via l’accéléromètre
  • l’angle est transformé en valeur de couple simulée
  • le reste de l’application fonctionne sans aucune modification

Cela permet :

  • le développement sans matériel
  • les démonstrations
  • les tests UI
  • les tests de filtrage

Technologies #

  • Kotlin
  • Jetpack Compose
  • Coroutines & Flow
  • Bluetooth RFCOMM (SPP)
  • Architecture MVVM
  • Filtrage numérique (Kalman)

Ce que démontre ce projet #

  • Mise en œuvre d’une application Android réactive pour des flux de données temps réel
  • Traitement temps réel de flux de données physiques
  • Découplage UI / logique / accès matériel via un repository
  • Intégration Bluetooth robuste
  • Simulation physique par capteurs Android
  • Utilisation avancée de Kotlin Flow et de Jetpack Compose

Pour la suite #

L’objectif est de faire évoluer le projet vers une architecture réellement indépendante des plateformes, dans laquelle le cœur métier ne dépendra plus ni d’Android, ni du Bluetooth, ni de Jetpack Compose.

Les axes de travail envisagés sont :

  • Extraction d’un noyau métier pur Kotlin, ne dépendant ni de Flow, ni de coroutines Android, ni de classes framework.
  • Introduction de ports formels pour l’accès au temps, aux capteurs, au transport et à la persistance.
  • Refonte des cas d’usage afin de centraliser les décisions métier (démarrage, arrêt, reconnexion, filtrage, gestion d’état).
  • Transformation des implémentations actuelles (Bluetooth et Dummy) en véritables adaptateurs branchés sur ces ports.
  • Séparation stricte UI / métier / IO, permettant de réutiliser le cœur du système sur Android, desktop ou en test automatisé.
  • Cette évolution viserait une véritable architecture hexagonale, tout en conservant la base MVVM actuelle comme couche de présentation Android.