1+ // platform.ts
12import type {
23 API ,
34 DynamicPlatformPlugin ,
@@ -18,15 +19,19 @@ import { ThermostatClient } from './thermostatClient';
1819import type { ThermostatService , Room , Hub , DeviceCapability } from './types' ;
1920import { ThermostatAccessory } from './thermostatAccessory' ;
2021import { OtodoModeSliderAccessory } from './otodoModeSliderAccessory' ;
21- import { OtodoTempSensorAccessory } from './otodoTempAccessory' ;
2222
2323export class OtodoVavPlatform implements DynamicPlatformPlugin {
2424 public readonly accessories : PlatformAccessory [ ] = [ ] ;
2525
2626 private auth ! : AuthClient ;
2727 private client ! : OtodoClient ;
2828 private tClient ! : ThermostatClient ;
29- private tempSensors : Map < number , OtodoTempSensorAccessory > = new Map ( ) ;
29+
30+ /**
31+ * 🔥 NOUVEAU :
32+ * deviceId → ThermostatAccessory
33+ */
34+ private thermostatByDeviceId : Map < number , ThermostatAccessory > = new Map ( ) ;
3035
3136 private roomsById : Map < string , Room > = new Map ( ) ;
3237 private hubsById : Map < string , Hub > = new Map ( ) ;
@@ -270,8 +275,6 @@ export class OtodoVavPlatform implements DynamicPlatformPlugin {
270275
271276 this . log . debug ( '📦 Création du TokenStore...' ) ;
272277 const store = new TokenStore ( this . api . user . storagePath ( ) ) ;
273-
274- this . log . debug ( "🔐 Initialisation de l'authentification..." ) ;
275278 this . auth = new AuthClient ( this . log , store , {
276279 email : String ( cfg . email || '' ) . trim ( ) ,
277280 password : String ( cfg . password || '' ) ,
@@ -329,118 +332,88 @@ export class OtodoVavPlatform implements DynamicPlatformPlugin {
329332
330333 private async loadRooms ( ) : Promise < void > {
331334 try {
332- this . log . debug ( '📂 Récupération des rooms...' ) ;
333335 const rooms = await this . tClient . getRooms ( ) ;
334336 this . roomsById = new Map ( rooms . map ( r => [ r . _id , r ] ) ) ;
335- this . log . debug ( `📂 ${ rooms . length } rooms chargées` ) ;
336337 } catch ( e ) {
337- this . log . warn (
338- '⚠️ Impossible de récupérer les rooms (optionnel) : ' + String ( e ) ,
339- ) ;
338+ this . log . warn ( '⚠️ Impossible de récupérer les rooms : ' + String ( e ) ) ;
340339 }
341340 }
342341
343342 private async loadHubs ( ) : Promise < void > {
344343 try {
345- this . log . debug ( '📂 Récupération des hubs...' ) ;
346344 const hubs = await this . tClient . getHubs ( ) ;
347345 this . hubsById = new Map ( hubs . map ( r => [ r . _id , r ] ) ) ;
348- this . log . debug ( `📂 ${ hubs . length } hubs chargés` ) ;
349346 } catch ( e ) {
350347 this . log . warn ( '⚠️ Impossible de récupérer les hubs : ' + String ( e ) ) ;
351348 }
352349 }
353350
354351 configureAccessory ( accessory : PlatformAccessory ) : void {
355- this . log . debug ( "🔄 Restauration de l'accessoire:" , accessory . displayName ) ;
356352 this . accessories . push ( accessory ) ;
357353 }
358354
355+ /**
356+ * 🔥 THERMOSTAT UNIQUEMENT
357+ * ET enregistrement deviceId → ThermostatAccessory
358+ */
359359 private upsertThermostat ( t : ThermostatService ) : void {
360- const uuidThermo = this . api . hap . uuid . generate ( `thermo:${ t . hubId } :${ t . _id } ` ) ;
360+ const uuid = this . api . hap . uuid . generate ( `thermo:${ t . hubId } :${ t . _id } ` ) ;
361361 const uuidSlider = this . api . hap . uuid . generate ( `slider:${ t . hubId } :${ t . _id } ` ) ;
362- const uuidTemp = this . api . hap . uuid . generate ( `temp:${ t . hubId } :${ t . _id } ` ) ;
363362
364363 const roomName = this . roomsById . get ( t . roomId ) ?. name ;
365364 const thermoName = roomName
366365 ? `Thermostat ${ roomName } `
367366 : `Thermostat ${ t . _id } ` ;
368367 const sliderName = roomName ? `Mode ${ roomName } ` : `Mode ${ t . _id } ` ;
369368
370- // ========== THERMOSTAT ACCESSORY ==========
371- const existingThermo = this . accessories . find ( a => a . UUID === uuidThermo ) ;
372- if ( existingThermo ) {
373- new ThermostatAccessory ( this , existingThermo , t , this . tClient ) ;
369+ // --- THERMOSTAT ---
370+ let acc = this . accessories . find ( a => a . UUID === uuid ) ;
371+
372+ if ( acc ) {
373+ this . log . info ( `♻️ Restauration thermostat: ${ thermoName } ` ) ;
374374 } else {
375- const acc = new this . api . platformAccessory ( thermoName , uuidThermo ) ;
376- new ThermostatAccessory ( this , acc , t , this . tClient ) ;
375+ acc = new this . api . platformAccessory ( thermoName , uuid ) ;
377376 this . api . registerPlatformAccessories ( PLUGIN_NAME , PLATFORM_NAME , [ acc ] ) ;
378377 this . accessories . push ( acc ) ;
379378 }
380379
381- // ========== MODE SLIDER ACCESSORY ==========
382- const existingSlider = this . accessories . find ( a => a . UUID === uuidSlider ) ;
380+ const thermoCtrl = new ThermostatAccessory ( this , acc , t , this . tClient ) ;
383381
384- if ( this . displayModeSliders ) {
385- // Création / restauration
386- if ( existingSlider ) {
387- this . log . info ( `♻️ Restauration du mode slider: ${ sliderName } ` ) ;
388- new OtodoModeSliderAccessory ( this , existingSlider , t , this . tClient ) ;
389- } else {
390- this . log . info ( `➕ Ajout du mode slider: ${ sliderName } ` ) ;
391- const acc = new this . api . platformAccessory ( sliderName , uuidSlider ) ;
392- new OtodoModeSliderAccessory ( this , acc , t , this . tClient ) ;
393- this . api . registerPlatformAccessories ( PLUGIN_NAME , PLATFORM_NAME , [ acc ] ) ;
394- this . accessories . push ( acc ) ;
395- }
396- } else {
397- // 🔥 SUPPRESSION AUTOMATIQUE SI désactivé
398- if ( existingSlider ) {
399- this . log . info ( `🗑️ Suppression du mode slider désactivé: ${ sliderName } ` ) ;
400- this . api . unregisterPlatformAccessories ( PLUGIN_NAME , PLATFORM_NAME , [
401- existingSlider ,
402- ] ) ;
403- this . accessories . splice ( this . accessories . indexOf ( existingSlider ) , 1 ) ;
404- }
382+ // 🔥 ENREGISTREMENT deviceId → thermostat
383+ const deviceId = t . modules ?. [ 0 ] ?. deviceId ;
384+ if ( deviceId ) {
385+ this . thermostatByDeviceId . set ( deviceId , thermoCtrl ) ;
386+ acc . context . deviceId = deviceId ;
405387 }
406388
407- // ========= TEMP SENSOR ACCESSORY =========
408- const tempName = roomName
409- ? `Température ${ roomName } `
410- : `Température ${ t . _id } ` ;
411- const existingTemp = this . accessories . find ( a => a . UUID === uuidTemp ) ;
412-
413- let tempAccessory : OtodoTempSensorAccessory ;
389+ // --- MODE SLIDER ---
390+ let accSlider = this . accessories . find ( a => a . UUID === uuidSlider ) ;
414391
415- if ( existingTemp ) {
416- tempAccessory = new OtodoTempSensorAccessory ( this , existingTemp , t ) ;
417- } else {
418- const acc = new this . api . platformAccessory ( tempName , uuidTemp ) ;
419- tempAccessory = new OtodoTempSensorAccessory ( this , acc , t ) ;
420- this . api . registerPlatformAccessories ( PLUGIN_NAME , PLATFORM_NAME , [ acc ] ) ;
421- this . accessories . push ( acc ) ;
392+ if ( this . displayModeSliders ) {
393+ if ( ! accSlider ) {
394+ accSlider = new this . api . platformAccessory ( sliderName , uuidSlider ) ;
395+ this . api . registerPlatformAccessories ( PLUGIN_NAME , PLATFORM_NAME , [
396+ accSlider ,
397+ ] ) ;
398+ this . accessories . push ( accSlider ) ;
399+ }
400+ new OtodoModeSliderAccessory ( this , accSlider , t , this . tClient ) ;
401+ } else if ( accSlider ) {
402+ this . api . unregisterPlatformAccessories ( PLUGIN_NAME , PLATFORM_NAME , [
403+ accSlider ,
404+ ] ) ;
405+ this . accessories . splice ( this . accessories . indexOf ( accSlider ) , 1 ) ;
422406 }
423-
424- // Stockage (deviceId → sensorInstance)
425- this . tempSensors . set ( tempAccessory . deviceId , tempAccessory ) ;
426407 }
427408
428409 private async discoverDevices ( hubId : string ) : Promise < void > {
429- this . log . info ( '🔍 Recherche des thermostats Otodo VAV...' ) ;
430- try {
431- const thermostats = await this . tClient . getAllThermostats ( hubId ) ;
432- this . log . info ( ` ${ thermostats . length } thermostat(s) trouvé(s)` ) ;
433-
434- for ( const t of thermostats ) {
435- this . upsertThermostat ( t ) ;
436- }
437- } catch ( e ) {
438- this . log . error (
439- '❌ Erreur lors de la découverte des thermostats : ' + String ( e ) ,
440- ) ;
410+ const thermostats = await this . tClient . getAllThermostats ( hubId ) ;
411+ for ( const t of thermostats ) {
412+ this . upsertThermostat ( t ) ;
441413 }
442414 }
443415
416+ // 🔥 Poller TRV → mise à jour du thermostat associé
444417 private async startDevicesPolling ( ) : Promise < void > {
445418 this . log . info (
446419 `📡 Mise en place du poller global /devices (intervalle: ${
@@ -457,9 +430,6 @@ export class OtodoVavPlatform implements DynamicPlatformPlugin {
457430 } , this . pollIntervalMs ) ;
458431 }
459432
460- /**
461- * Fonction interne : récupère /devices et met à jour les capteurs
462- */
463433 private async refreshDevicesOnce ( ) : Promise < void > {
464434 try {
465435 const devices = await this . tClient . getDevices ( ) ;
@@ -477,19 +447,19 @@ export class OtodoVavPlatform implements DynamicPlatformPlugin {
477447 continue ;
478448 }
479449
480- const deviceId = dev . _id ;
481- const sensor = this . tempSensors . get ( deviceId ) ;
482- if ( ! sensor ) {
483- continue ;
484- }
485-
486450 const kelvinX10 = tempCap . value ;
487451 const celsius = Number ( ( ( kelvinX10 - 2731 ) / 10 ) . toFixed ( 1 ) ) ;
488452
489- sensor . updateTemperature ( celsius ) ;
453+ // Trouver le ThermostatAccessory correspondant
454+ const ctrl = this . thermostatByDeviceId . get ( dev . _id ) ;
455+ if ( ! ctrl ) {
456+ continue ;
457+ }
458+
459+ ctrl . updateCurrentTemperature ( celsius ) ;
490460 }
491- } catch ( err ) {
492- this . log . warn ( `⚠️ Poller devices: ${ String ( err ) } ` ) ;
461+ } catch ( e ) {
462+ this . log . warn ( `⚠️ Erreur polling / devices : ${ e } ` ) ;
493463 }
494464 }
495465}
0 commit comments