1- import type { API , DynamicPlatformPlugin , Logger , PlatformAccessory , PlatformConfig } from 'homebridge' ;
1+ import type {
2+ API ,
3+ DynamicPlatformPlugin ,
4+ Logger ,
5+ PlatformAccessory ,
6+ PlatformConfig ,
7+ } from 'homebridge' ;
28import { PLATFORM_NAME , PLUGIN_NAME } from './settings' ;
39import { TokenStore } from './tokenStore' ;
410import { AuthClient } from './auth' ;
511import { OtodoClient } from './otodoClient' ;
12+ import { ThermostatClient } from './thermostatClient' ;
13+ import type { ThermostatService , Room , Hub } from './types' ;
14+ import { ThermostatAccessory } from './thermostatAccessory' ;
615
716export class OtodoVavPlatform implements DynamicPlatformPlugin {
817 public readonly accessories : PlatformAccessory [ ] = [ ] ;
18+
919 private auth ! : AuthClient ;
1020 private client ! : OtodoClient ;
21+ private tClient ! : ThermostatClient ;
22+
23+ private roomsById : Map < string , Room > = new Map ( ) ;
24+ private hubsById : Map < string , Hub > = new Map ( ) ;
1125
1226 constructor (
1327 public readonly log : Logger ,
1428 public readonly config : PlatformConfig ,
1529 public readonly api : API ,
1630 ) {
17- // Vérification de la configuration
1831 if ( ! config || ! config . email || ! config . password ) {
1932 this . log . error ( '❌ Configuration invalide : email et password requis' ) ;
2033 return ;
2134 }
2235
23- // ⭐ Activation du mode debug si demandé
2436 if ( config . debug === true ) {
2537 this . log . debug ( '🔍 Mode debug activé' ) ;
2638 }
@@ -31,19 +43,16 @@ export class OtodoVavPlatform implements DynamicPlatformPlugin {
3143 try {
3244 await this . initializePlugin ( ) ;
3345 } catch ( error ) {
34- this . log . error ( ' ❌ Échec de l\ 'initialisation du plugin:' , error ) ;
46+ this . log . error ( " ❌ Échec de l'initialisation du plugin:" , error ) ;
3547 }
3648 } ) ;
3749 }
3850
39- /**
40- * Méthode d'initialisation séparée pour plus de clarté
41- */
4251 private async initializePlugin ( ) : Promise < void > {
4352 this . log . debug ( '📦 Création du TokenStore...' ) ;
4453 const store = new TokenStore ( this . api . user . storagePath ( ) ) ;
4554
46- this . log . debug ( ' 🔐 Initialisation de l\ 'authentification...' ) ;
55+ this . log . debug ( " 🔐 Initialisation de l'authentification..." ) ;
4756 this . auth = new AuthClient ( this . log , store , {
4857 email : String ( this . config . email ) ,
4958 password : String ( this . config . password ) ,
@@ -52,60 +61,112 @@ export class OtodoVavPlatform implements DynamicPlatformPlugin {
5261
5362 await this . auth . init ( ) ;
5463
55- this . log . debug ( '🌐 Création du client API...' ) ;
64+ this . log . debug ( '🌐 Création des clients API...' ) ;
5665 this . client = new OtodoClient ( this . log , this . auth ) ;
66+ this . tClient = new ThermostatClient ( this . log , this . auth ) ;
5767
58- this . log . info ( '✅ Plugin initialisé avec succès' ) ;
59- this . log . info ( ` HomeId: ${ this . auth . homeId } ` ) ;
60- this . log . info ( ` UserId: ${ this . auth . userId } ` ) ;
61- this . log . info ( ` ParkId: ${ this . auth . parkId } ` ) ;
68+ this . log . info ( '✅ Plugin initialisé' ) ;
69+ if ( this . auth . homeId ) {
70+ this . log . info ( ` HomeId: ${ this . auth . homeId } ` ) ;
71+ }
72+ if ( this . auth . userId ) {
73+ this . log . info ( ` UserId: ${ this . auth . userId } ` ) ;
74+ }
75+ if ( this . auth . parkId ) {
76+ this . log . info ( ` ParkId: ${ this . auth . parkId } ` ) ;
77+ }
6278
63- // TODO: Découverte des thermostats
64- // await this.discoverDevices();
79+ await this . loadRooms ( ) ;
80+ await this . loadHubs ( ) ;
81+ this . hubsById . forEach ( async hub => {
82+ await this . discoverDevices ( hub . _id ) ;
83+ } ) ;
6584 }
6685
6786 /**
68- * Appelé par Homebridge pour restaurer les accessoires en cache
87+ * Chargement optionnel des pièces pour des noms plus jolis
88+ */
89+ private async loadRooms ( ) : Promise < void > {
90+ try {
91+ this . log . debug ( '📂 Récupération des rooms...' ) ;
92+ const rooms = await this . tClient . getRooms ( ) ;
93+ this . roomsById = new Map ( rooms . map ( r => [ r . _id , r ] ) ) ;
94+ this . log . debug ( `📂 ${ rooms . length } rooms chargées` ) ;
95+ } catch ( e ) {
96+ this . log . warn (
97+ '⚠️ Impossible de récupérer les rooms (optionnel) : ' + String ( e ) ,
98+ ) ;
99+ }
100+ }
101+
102+ /**
103+ * Chargement des hubs
104+ */
105+ private async loadHubs ( ) : Promise < void > {
106+ try {
107+ this . log . debug ( '📂 Récupération des rooms...' ) ;
108+ const hubs = await this . tClient . getHubs ( ) ;
109+ this . hubsById = new Map ( hubs . map ( r => [ r . _id , r ] ) ) ;
110+ this . log . debug ( `📂 ${ hubs . length } hubs chargées` ) ;
111+ } catch ( e ) {
112+ this . log . warn ( '⚠️ Impossible de récupérer les hubs : ' + String ( e ) ) ;
113+ }
114+ }
115+
116+ /**
117+ * Restaurer depuis le cache
69118 */
70119 configureAccessory ( accessory : PlatformAccessory ) : void {
71- this . log . debug ( '🔄 Restauration de l\'accessoire depuis le cache:' , accessory . displayName ) ;
120+ this . log . debug (
121+ "🔄 Restauration de l'accessoire depuis le cache:" ,
122+ accessory . displayName ,
123+ ) ;
72124 this . accessories . push ( accessory ) ;
73125 }
74126
75127 /**
76- * Méthode pour créer ou mettre à jour un thermostat
128+ * Upsert d'un thermostat : création ou restauration
77129 */
78- private upsertThermostat ( device : { name : string ; id : string } ) : void {
79- const uuid = this . api . hap . uuid . generate ( device . id ) ;
130+ private upsertThermostat ( t : ThermostatService ) : void {
131+ const uuid = this . api . hap . uuid . generate ( `hub: ${ t . hubId } :svc: ${ t . _id } ` ) ;
80132 const existing = this . accessories . find ( acc => acc . UUID === uuid ) ;
81133
134+ const roomName = this . roomsById . get ( t . roomId ) ?. name ;
135+ const displayName = roomName
136+ ? `Thermostat ${ roomName } `
137+ : `Thermostat ${ t . _id } ` ;
138+
82139 if ( existing ) {
83- this . log . info ( '♻️ Restauration du thermostat:' , device . name ) ;
84- // TODO: new ThermostatAccessory(this, existing, device , this.client );
140+ this . log . info ( '♻️ Restauration du thermostat:' , displayName ) ;
141+ new ThermostatAccessory ( this , existing , t , this . tClient ) ;
85142 } else {
86- this . log . info ( '➕ Enregistrement du nouveau thermostat:' , device . name ) ;
87- const accessory = new this . api . platformAccessory ( device . name , uuid ) ;
88- // TODO: new ThermostatAccessory(this, accessory, device, this.client);
89- this . api . registerPlatformAccessories ( PLUGIN_NAME , PLATFORM_NAME , [ accessory ] ) ;
143+ this . log . info ( '➕ Enregistrement du nouveau thermostat:' , displayName ) ;
144+ const accessory = new this . api . platformAccessory ( displayName , uuid ) ;
145+ new ThermostatAccessory ( this , accessory , t , this . tClient ) ;
146+
147+ this . api . registerPlatformAccessories ( PLUGIN_NAME , PLATFORM_NAME , [
148+ accessory ,
149+ ] ) ;
150+ this . accessories . push ( accessory ) ;
90151 }
91152 }
92153
93154 /**
94- * Future méthode de découverte des appareils
155+ * Découverte des thermostats via /local-services
95156 */
96- private async discoverDevices ( ) : Promise < void > {
97- this . log . debug ( '🔍 Recherche des thermostats...' ) ;
98-
99- // TODO: Implémenter quand tu auras l'endpoint de découverte
100- // Exemple :
101- // const devices = await this.client.getJson<DeviceSummary[]>(
102- // `https://api.gateway.otodo.io/homes/${this.auth.homeId}/devices`
103- // );
104- //
105- // for (const device of devices ) {
106- // if (device.type === 'thermostat') {
107- // this.upsertThermostat(device);
108- // }
109- // }
157+ private async discoverDevices ( hubId : string ) : Promise < void > {
158+ this . log . info ( '🔍 Recherche des thermostats Otodo VAV ...' ) ;
159+ try {
160+ const thermostats = await this . tClient . getAllThermostats ( hubId ) ;
161+ this . log . info ( ` ${ thermostats . length } thermostat(s) trouvé(s)` ) ;
162+
163+ for ( const t of thermostats ) {
164+ this . upsertThermostat ( t ) ;
165+ }
166+ } catch ( e ) {
167+ this . log . error (
168+ '❌ Erreur lors de la découverte des thermostats : ' + String ( e ) ,
169+ ) ;
170+ }
110171 }
111- }
172+ }
0 commit comments