# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Contexte général Dossier parent de tous les projets : `/home/etm/Projects/` - **`etm_powersync_app/`** (ce projet) — application Flutter HEMS, client mobile - **`etm-nymea/`** — serveur nymea et plugins associés (C++/Qt), le backend Ce projet est le **client Flutter** qui communique avec le serveur nymea via JSON-RPC 2.0. --- ## Commandes ```bash flutter pub get # installer/mettre à jour les dépendances flutter run # lancer sur device/émulateur connecté flutter build apk # build Android release flutter analyze # analyse statique Dart flutter test # lancer les tests ``` ## Architecture ### State management — un seul Provider `NymeaService` (`lib/services/nymea_service.dart`) est le seul `ChangeNotifier`. Il est fourni à la racine dans `main.dart` via `ChangeNotifierProvider`. Tous les écrans le consomment avec `context.watch()` ou `context.read()`. Il n'y a aucune autre couche de state management. ### Navigation `MainShell` dans `main.dart` utilise un `IndexedStack` de 5 écrans (l'état est préservé entre les onglets) : | Index | Écran | Fichier | |-------|-------|---------| | 0 | Dashboard | `lib/screens/dashboard_screen.dart` | | 1 | Énergie | `lib/screens/energy_screen.dart` | | 2 | Things | `lib/screens/things_screen.dart` | | 3 | A/C | `lib/screens/ac_screen.dart` | | 4 | Favoris | `lib/screens/favorites_screen.dart` | ### Communication avec nymea `NymeaService.connect()` supporte deux transports : - **TCP brut** port 2222 (défaut) : nymea parle **en premier** (JSON délimité par `\n`). La fragmentation est gérée via `StringBuffer`. - **WebSocket** port 4444 : c'est le **client qui parle en premier** en envoyant `JSONRPC.Hello`. Les requêtes utilisent des IDs auto-incrémentés stockés dans `_pendingRequests: Map`. Timeout global : 15 secondes. Les notifications push nymea (pas de champ `id`, ont un champ `notification`) sont dispatchées dans `_handleNotification()`. **Convention nymea énergie importante** : `currentPowerProduction` est **négatif** (producteur = négatif). Le service convertit en positif dans `_parsePowerBalance()`. ### Mode simulation `NymeaService.startSimulation()` déconnecte toute connexion live, active `_isSimulation = true`, génère des things fictifs et une production PV simulée en sinus (timer 2 s). Le dashboard démarre automatiquement la simulation au premier affichage si non connecté. Toutes les méthodes du service font un garde `if (_isSimulation) return …` pour éviter les vrais appels RPC. ### Modèles de données - **`EnergyData`** (`lib/models/energy_data.dart`) — objet immutable avec `copyWith`, regroupe toutes les métriques énergie temps-réel et journalières + état de la borne EV. - **`NymeaThing` / `NymeaThingClass` / `NymeaStateType` / `NymeaActionType`** (`lib/models/nymea_models.dart`) — miroir de l'API Integrations nymea. `NymeaThingClass.primaryStateType` détermine l'état affiché sur les cards. - **`ThingCategory` + `interfaceToCategoryMap`** (`lib/models/thing_category.dart`) — mappe les interfaces nymea (ex. `"evcharger"`, `"solarinverter"`) vers des catégories d'affichage utilisées par `ThingsScreen`. - **`FavoriteWidget`** (`lib/models/nymea_models.dart`) — descripteurs de widgets stockés en mémoire dans `NymeaService._favoriteWidgets`. ### Thème `AppTheme` (`lib/theme/app_theme.dart`) expose des constantes `Color` nommées : `primaryGreen`, `solarYellow`, `gridGray`, `homeBlue`, `batteryGreen`, `boostRed`, `pvGreen`, `minPvBlue`, etc. Toujours utiliser ces constantes plutôt que des valeurs hex brutes. ## Conventions - **Code** : anglais — **Commentaires** : français - **Nommage** : camelCase variables, PascalCase classes - Les écrans utilisent `Consumer` ou `context.watch` — ne jamais dupliquer l'état du service dans un `State` - **Unités** : Watts (W) pour les puissances instantanées, Wh pour les énergies journalières. L'API nymea retourne des totaux en kWh que le service multiplie par 1000. ## Méthodes nymea principales | Méthode | Rôle | |---------|------| | `JSONRPC.Hello` | Handshake (WebSocket uniquement — envoyé par le client) | | `Integrations.GetThings` | Charger les devices configurés | | `Integrations.GetThingClasses` | Charger les définitions de classes (filtre `thingClassIds` supporté) | | `Integrations.ExecuteAction` | Exécuter une action sur un thing | | `Integrations.GetStateValue` | Lire une valeur d'état | | `Energy.GetPowerBalance` | Snapshot du flux énergétique actuel | | `Energy.GetEnergyLogs` | Historique énergie (échantillons horaires) | | `Energy.SetChargingMode` | Mode borne EV : `pv`, `minpv`, `boost` | Notifications push gérées : `Energy.PowerBalanceChanged`, `Energy.RootMeterChanged`, `Integrations.StateChanged`, `Integrations.ThingAdded`, `Integrations.ThingRemoved`. ## Documentation API - `docs/nymea_api.md` — introspection complète de l'API nymea - `docs/nymea_integrations.md` — namespace Integrations en détail