Lot Connexions multi-HEMS : - modèle Installation + InstallationStore (persistance par UUID ; métadonnées SharedPreferences, token via flutter_secure_storage) - ConnectionManager au-dessus de nymea_service : mono-connexion, switchTo, connectNew, enterDemo (démo = active factice), contrôle d'identité DHCP - nymea_service : connect() réveillé (ws://4444, token par UUID), capture Hello (uuid/name/initialSetupRequired), authenticate/createUser, resetState - écran Installations (3 états) + déverrouillage installateur depuis la racine - écran Connexion : auth 2 branches (JSONRPC.Authenticate / CreateUser), détection auto via initialSetupRequired, segmenteur de repli - gate de routage (redirect + refreshListenable merge[cm,svc]) ; hasActiveConnection = isSimulation || (connected && authenticated) - en-tête drawer cliquable → Installations - invalidation des caches au switch (service.resetState + clearForSwitch rôles/scheduler/tariff), sans persist() Lot Rôles & appareils : - EnergySetupProvider refondu en tri-état (present/absent/non-configuré) - écran roles_devices_screen (3 zones, drag-priorité, inférence solaire/batterie) - LoadDescriptor (etmvariableload, rév.2 : PAC exclue → SG-Ready) ; Energy.SetRootMeter réel, Get/SetLoadConfig en stub loggé Correctifs : - bug signe énergie : production +, consommation NÉGATIVE sur nymea 1.15.2 → consumptionW/home en .abs() (autoconso n'est plus clouée à 0) - UUID Hello brace-wrapped normalisé Tests : flutter analyze 0 erreur ; gate + zéro-fuite au switch (5/5 verts). Validé en vrai : login auth .120, .75 ouvert, switch, déverrouillage installateur. Note : embarque aussi le WIP dashboard/thème déjà présent dans l'arbre. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
64 lines
1.5 KiB
Dart
64 lines
1.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// Icône du cœur HEMS (« Héos ») : étincelle de marque au centre,
|
|
/// 4 nœuds pilotés alignés sur les pointes.
|
|
class HemsIcon extends StatelessWidget {
|
|
final double size;
|
|
final Color? color;
|
|
|
|
const HemsIcon({super.key, this.size = 24, this.color});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final c = color ??
|
|
IconTheme.of(context).color ??
|
|
const Color(0xFF28A06A);
|
|
return SizedBox(
|
|
width: size,
|
|
height: size,
|
|
child: CustomPaint(painter: _HemsPainter(c)),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _HemsPainter extends CustomPainter {
|
|
final Color color;
|
|
_HemsPainter(this.color);
|
|
|
|
static const _nodes = <Offset>[
|
|
Offset(12, 3.4),
|
|
Offset(20.6, 12),
|
|
Offset(12, 20.6),
|
|
Offset(3.4, 12),
|
|
];
|
|
static const _nodeR = 1.7;
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final s = size.width / 24.0;
|
|
final paint = Paint()
|
|
..color = color
|
|
..style = PaintingStyle.fill
|
|
..isAntiAlias = true;
|
|
|
|
final spark = Path()
|
|
..moveTo(12 * s, 7.4 * s)
|
|
..lineTo(13.25 * s, 10.75 * s)
|
|
..lineTo(16.6 * s, 12 * s)
|
|
..lineTo(13.25 * s, 13.25 * s)
|
|
..lineTo(12 * s, 16.6 * s)
|
|
..lineTo(10.75 * s, 13.25 * s)
|
|
..lineTo(7.4 * s, 12 * s)
|
|
..lineTo(10.75 * s, 10.75 * s)
|
|
..close();
|
|
canvas.drawPath(spark, paint);
|
|
|
|
for (final n in _nodes) {
|
|
canvas.drawCircle(Offset(n.dx * s, n.dy * s), _nodeR * s, paint);
|
|
}
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(_HemsPainter old) => old.color != color;
|
|
}
|