This commit is contained in:
2026-02-21 16:55:10 +01:00
commit 1b8bf79d46
49 changed files with 4347 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
# Design — HA Entity Scanner & Manager
**Date** : 2026-02-21
**Statut** : Approuvé
## Architecture globale
```
Frontend (Vue 3 + Vuetify 3) ──► Backend (FastAPI) ──► Home Assistant
SPA :5173 API :8000 :8123
SQLite DB REST + WS
```
- **Frontend** : SPA Vue 3 + Vite + Vuetify 3, appelle `/api/*`
- **Backend** : FastAPI, proxy sécurisé vers HA (token jamais exposé côté client)
- **DB** : SQLite via SQLModel, 3 tables (entities_cache, entity_flags, audit_log)
- **Client HA** : `aiohttp` pour REST (`/api/states`) et WebSocket (`/api/websocket`)
- **Déploiement** : Docker + docker-compose, variables d'env `HA_BASE_URL` / `HA_TOKEN`
## Backend — structure des modules
| Module | Responsabilité |
|--------|---------------|
| `app/main.py` | App FastAPI, CORS, lifespan |
| `app/config.py` | Settings via pydantic-settings (env vars) |
| `app/models.py` | SQLModel : EntityCache, EntityFlag, AuditLog |
| `app/database.py` | Init SQLite, get_session |
| `app/ha_client.py` | Client aiohttp : REST states + WS registry |
| `app/routers/health.py` | `GET /api/health` |
| `app/routers/scan.py` | `POST /api/scan` (async background task) |
| `app/routers/entities.py` | `GET /api/entities`, `GET /api/entities/{id}` |
| `app/routers/actions.py` | `POST /api/entities/actions` |
| `app/routers/audit.py` | `GET /api/audit` |
| `app/services/scanner.py` | Logique scan : fetch + normalize + upsert DB |
| `app/services/entity_actions.py` | Logique disable/enable/hide via WS ou fallback |
## Frontend — composants principaux
| Composant | Rôle |
|-----------|------|
| `App.vue` | Layout principal, header avec statut HA |
| `EntityTable.vue` | `v-data-table-server` avec tri, pagination, sélection |
| `FilterBar.vue` | Recherche texte + dropdowns domaine/état + chips actives |
| `EntityDetail.vue` | Panneau latéral détails + actions |
| `AuditLog.vue` | Page journal des actions |
| `ScanButton.vue` | Bouton scan + indicateur progression |
## Base de données SQLite
### entities_cache
- `entity_id` (PK), `domain`, `friendly_name`, `state`
- `attrs_json` (TEXT — attributs HA complets)
- `device_class`, `unit_of_measurement`, `area_id`, `device_id`, `integration`
- `is_disabled`, `is_hidden`, `is_available` (booléens déduits)
- `last_changed`, `last_updated`, `fetched_at`
### entity_flags
- `entity_id` (PK), `ignored_local` (bool), `favorite` (bool), `notes` (text)
### audit_log
- `id` (PK auto), `ts` (datetime), `action` (text), `entity_ids_json` (text), `result` (text), `error` (text)
## Scan asynchrone
`POST /api/scan` lance une `BackgroundTask` FastAPI. Un état en mémoire (`idle`/`scanning`/`done`/`error` + progression) est exposé via `GET /api/health`. Le frontend poll le health pour afficher la progression.
## Désactivation des entités
1. **Méthode principale** : WS API HA `config/entity_registry/update` avec `disabled_by: "user"`
2. **Fallback** : flag `ignored_local=true` en DB locale
3. L'UI affiche un badge distinct selon le mode utilisé (désactivé HA vs ignoré local)
4. Toute action journalisée dans `audit_log`
## Choix techniques
- **Python FastAPI** + **aiohttp** (client HA REST + WS)
- **SQLModel** (SQLAlchemy + Pydantic)
- **Vue 3** + **Vite** + **Vuetify 3**
- **Docker** + **docker-compose**
- UI en **français** uniquement