11import Logger from '../helper/logger.js' ;
22import moment from 'moment' ;
3- import { writeFile , access , readFile } from 'fs/promises' ;
3+ import { writeFile } from 'fs/promises' ;
44import { join } from "path" ;
55
6- let settingState = false ;
7- let tasksInitialized = false ;
8- let lastGetStates = 0 ;
9- const delayTimer = { } ;
10-
116const timeout = ( ms ) => new Promise ( ( res ) => setTimeout ( res , ms ) ) ;
12- const aRefreshHistoryHandlers = [ ] ;
13-
14- export async function getPersistedStates ( storagePath ) {
15- try {
16- const sFilePath = join ( storagePath , "tado-states.json" ) ;
17- await access ( sFilePath ) ;
18- const sData = ( await readFile ( sFilePath , "utf-8" ) ) ;
19- if ( sData ) return JSON . parse ( sData ) ;
20- } catch ( error ) {
21- //no states data => ignore
22- Logger . debug ( `Failed to read tado states file: ${ error . message || error } ` ) ;
23- }
24- }
7+ const helpers = { } ;
258
269export default ( api , accessories , config , tado , telegram ) => {
27- const statesIntervalTime = Math . max ( config . polling , 30 ) * 1000 ;
28- const storagePath = api . user . storagePath ( ) ;
10+ //init helper variables for current home scope
11+ if ( ! helpers [ config . homeId ] ) {
12+ helpers [ config . homeId ] = {
13+ settingState : false ,
14+ tasksInitialized : false ,
15+ lastGetStates : 0 ,
16+ lastPersistZoneStates : 0 ,
17+ persistPromise : Promise . resolve ( ) ,
18+ updateZonesRunning : false ,
19+ updateZonesNextQueued : false ,
20+ delayTimer : { } ,
21+ refreshHistoryHandlers : [ ] ,
22+ statesIntervalTime : Math . max ( config . polling , 30 ) * 1000 ,
23+ storagePath : api . user . storagePath ( ) ,
24+ }
25+ }
2926
3027 async function setStates ( accessory , accs , target , value ) {
3128 let zoneUpdated = false ;
32-
3329 accessories = accs . filter ( ( acc ) => acc && acc . context . config . homeName === config . homeName ) ;
34-
3530 try {
36- settingState = true ;
37-
31+ helpers [ config . homeId ] . settingState = true ;
3832 value = typeof value === 'number' ? parseFloat ( value . toFixed ( 2 ) ) : value ;
39-
4033 Logger . info ( target + ': ' + value , accessory . displayName ) ;
4134
4235 switch ( accessory . context . config . subtype ) {
@@ -63,10 +56,10 @@ export default (api, accessories, config, tado, telegram) => {
6356 value < 5
6457 ) {
6558 if ( value === 0 ) {
66- if ( delayTimer [ accessory . displayName ] ) {
59+ if ( helpers [ config . homeId ] . delayTimer [ accessory . displayName ] ) {
6760 Logger . info ( 'Resetting delay timer' , accessory . displayName ) ;
68- clearTimeout ( delayTimer [ accessory . displayName ] ) ;
69- delayTimer [ accessory . displayName ] = null ;
61+ clearTimeout ( helpers [ config . homeId ] . delayTimer [ accessory . displayName ] ) ;
62+ helpers [ config . homeId ] . delayTimer [ accessory . displayName ] = null ;
7063 }
7164
7265 power = 'OFF' ;
@@ -111,14 +104,14 @@ export default (api, accessories, config, tado, telegram) => {
111104 let timer = accessory . context . delayTimer ;
112105 let tarState = value === 1 ? 'HEAT' : 'AUTO' ;
113106
114- if ( delayTimer [ accessory . displayName ] ) {
115- clearTimeout ( delayTimer [ accessory . displayName ] ) ;
116- delayTimer [ accessory . displayName ] = null ;
107+ if ( helpers [ config . homeId ] . delayTimer [ accessory . displayName ] ) {
108+ clearTimeout ( helpers [ config . homeId ] . delayTimer [ accessory . displayName ] ) ;
109+ helpers [ config . homeId ] . delayTimer [ accessory . displayName ] = null ;
117110 }
118111
119112 Logger . info ( 'Wait ' + timer + ' seconds before switching state' , accessory . displayName ) ;
120113
121- delayTimer [ accessory . displayName ] = setTimeout ( async ( ) => {
114+ helpers [ config . homeId ] . delayTimer [ accessory . displayName ] = setTimeout ( async ( ) => {
122115 Logger . info ( 'Delay timer finished, switching state to ' + tarState , accessory . displayName ) ;
123116
124117 //targetState
@@ -172,7 +165,7 @@ export default (api, accessories, config, tado, telegram) => {
172165 ) ;
173166 }
174167
175- delayTimer [ accessory . displayName ] = null ;
168+ helpers [ config . homeId ] . delayTimer [ accessory . displayName ] = null ;
176169 } , timer * 1000 ) ;
177170 }
178171 } else {
@@ -567,11 +560,11 @@ export default (api, accessories, config, tado, telegram) => {
567560 } catch ( err ) {
568561 errorHandler ( err ) ;
569562 } finally {
570- settingState = false ;
563+ helpers [ config . homeId ] . settingState = false ;
571564 //update zones to ensure correct state in Apple Home
572- const timeSinceLastGetStates = Date . now ( ) - lastGetStates ;
573- const statesIntervalTimeLeft = statesIntervalTime - timeSinceLastGetStates ;
574- if ( zoneUpdated && statesIntervalTimeLeft > 10_000 ) await updateZones ( ) ;
565+ const timeSinceLastGetStates = helpers [ config . homeId ] . lastGetStates === 0 ? 0 : ( Date . now ( ) - helpers [ config . homeId ] . lastGetStates ) ;
566+ const statesIntervalTimeLeft = helpers [ config . homeId ] . statesIntervalTime - timeSinceLastGetStates ;
567+ if ( zoneUpdated && statesIntervalTimeLeft > ( 10 * 1000 ) ) await updateZones ( ) ;
575568 }
576569 }
577570
@@ -729,61 +722,49 @@ export default (api, accessories, config, tado, telegram) => {
729722 }
730723 }
731724
732- async function persistZoneStates ( homeId , zoneStates ) {
725+ function persistZoneStates ( homeId , zoneStates ) {
726+ helpers [ config . homeId ] . persistPromise = helpers [ config . homeId ] . persistPromise . then ( ( ) => _persistZoneStates ( homeId , zoneStates ) ) ;
727+ }
728+
729+ async function _persistZoneStates ( homeId , zoneStates ) {
730+ if ( ( Date . now ( ) - helpers [ config . homeId ] . lastPersistZoneStates ) < ( 10 * 1000 ) ) return ;
733731 try {
734732 if ( zoneStates && Object . keys ( zoneStates ) . length ) {
735733 const homeData = { } ;
736734 homeData . zoneStates = zoneStates ;
737- await writeFile ( join ( storagePath , `tado-states-${ homeId } .json` ) , JSON . stringify ( homeData , null , 2 ) , "utf-8" ) ;
735+ await writeFile ( join ( helpers [ config . homeId ] . storagePath , `tado-states-${ homeId } .json` ) , JSON . stringify ( homeData , null , 2 ) , "utf-8" ) ;
736+ helpers [ config . homeId ] . lastPersistZoneStates = Date . now ( ) ;
738737 } else {
739- Logger . info ( `Skipping persistence of tado states for home ${ homeId } : zone states are empty.` ) ;
738+ Logger . warn ( `Skipping persistence of tado states file for home ${ homeId } : zone states are empty.` ) ;
740739 }
741740 } catch ( error ) {
742741 Logger . error ( `Error while updating the tado states file for home ${ homeId } : ${ error . message || error } ` ) ;
743742 }
744743 }
745744
746- async function persistStates ( ) {
747- try {
748- const data = { } ;
749- data . counterData = await tado . getCounterData ( ) ;
750- await writeFile ( join ( storagePath , "tado-states.json" ) , JSON . stringify ( data , null , 2 ) , "utf-8" ) ;
751- } catch ( error ) {
752- Logger . error ( `Error while updating the tado states file: ${ error . message || error } ` ) ;
753- }
745+ async function refreshHistoryServices ( ) {
746+ if ( ! helpers [ config . homeId ] . refreshHistoryHandlers . length ) return ;
754747 try {
755748 //wait for fakegato history services to be loaded
756749 await timeout ( 4000 ) ;
757- for ( const refreshHistory of aRefreshHistoryHandlers ) {
750+ for ( const refreshHistory of helpers [ config . homeId ] . refreshHistoryHandlers ) {
758751 refreshHistory ( ) ;
759752 }
760753 } catch ( error ) {
761- Logger . error ( `Error while refreshing history: ${ error . message || error } ` ) ;
762- }
763- }
764-
765- async function logCounter ( ) {
766- try {
767- const iCounter = ( await tado . getCounterData ( ) ) . counter ;
768- Logger . info ( `Tado API counter: ${ iCounter . toLocaleString ( 'en-US' ) } ` ) ;
769- } catch ( error ) {
770- Logger . warn ( `Failed to get Tado API counter: ${ error . message || error } ` ) ;
754+ Logger . error ( `Error while refreshing history services: ${ error . message || error } ` ) ;
771755 }
772756 }
773757
774758 function initTasks ( ) {
775- if ( tasksInitialized ) return ;
776- tasksInitialized = true ;
759+ if ( helpers [ config . homeId ] . tasksInitialized ) return ;
760+ helpers [ config . homeId ] . tasksInitialized = true ;
777761
778762 void getStates ( ) ;
779- setInterval ( ( ) => getStates ( ) , statesIntervalTime ) ;
780-
781- void logCounter ( ) ;
782- setInterval ( ( ) => logCounter ( ) , 60 * 60 * 1000 ) ;
763+ setInterval ( ( ) => void getStates ( ) , helpers [ config . homeId ] . statesIntervalTime ) ;
783764 }
784765
785766 async function getStates ( ) {
786- lastGetStates = Date . now ( ) ;
767+ helpers [ config . homeId ] . lastGetStates = Date . now ( ) ;
787768 try {
788769 //ME
789770 if ( ! config . homeId ) await updateMe ( ) ;
@@ -811,12 +792,12 @@ export default (api, accessories, config, tado, telegram) => {
811792 } catch ( err ) {
812793 errorHandler ( err ) ;
813794 } finally {
814- void persistStates ( ) ;
795+ void refreshHistoryServices ( ) ;
815796 }
816797 }
817798
818799 async function updateMe ( ) {
819- if ( settingState ) return ;
800+ if ( helpers [ config . homeId ] . settingState ) return ;
820801
821802 Logger . debug ( 'Polling User Info...' , config . homeName ) ;
822803
@@ -828,7 +809,7 @@ export default (api, accessories, config, tado, telegram) => {
828809 }
829810
830811 async function updateHome ( ) {
831- if ( settingState ) return ;
812+ if ( helpers [ config . homeId ] . settingState ) return ;
832813
833814 Logger . debug ( 'Polling Home Info...' , config . homeName ) ;
834815
@@ -853,7 +834,32 @@ export default (api, accessories, config, tado, telegram) => {
853834 }
854835
855836 async function updateZones ( ) {
856- if ( settingState ) return ;
837+ if ( helpers [ config . homeId ] . updateZonesRunning ) {
838+ helpers [ config . homeId ] . updateZonesNextQueued = true ;
839+ return ;
840+ }
841+ helpers [ config . homeId ] . updateZonesRunning = true ;
842+ try {
843+ while ( true ) {
844+ try {
845+ await _updateZones ( ) ;
846+ } catch ( error ) {
847+ Logger . error ( `Failed to update zones: ${ error . message || error } ` ) ;
848+ }
849+ if ( helpers [ config . homeId ] . updateZonesNextQueued ) {
850+ helpers [ config . homeId ] . updateZonesNextQueued = false ;
851+ //continue with loop
852+ } else {
853+ break ;
854+ }
855+ }
856+ } finally {
857+ helpers [ config . homeId ] . updateZonesRunning = false ;
858+ }
859+ }
860+
861+ async function _updateZones ( ) {
862+ if ( helpers [ config . homeId ] . settingState ) return ;
857863
858864 Logger . debug ( 'Polling Zones...' , config . homeName ) ;
859865
@@ -1316,7 +1322,7 @@ export default (api, accessories, config, tado, telegram) => {
13161322 }
13171323
13181324 async function updateMobileDevices ( ) {
1319- if ( settingState ) return ;
1325+ if ( helpers [ config . homeId ] . settingState ) return ;
13201326
13211327 Logger . debug ( 'Polling MobileDevices...' , config . homeName ) ;
13221328
@@ -1370,7 +1376,7 @@ export default (api, accessories, config, tado, telegram) => {
13701376 }
13711377
13721378 async function updateWeather ( ) {
1373- if ( settingState ) return ;
1379+ if ( helpers [ config . homeId ] . settingState ) return ;
13741380
13751381 const weatherTemperatureAccessory = accessories . filter (
13761382 ( acc ) => acc && acc . displayName === acc . context . config . homeName + ' Weather'
@@ -1425,7 +1431,7 @@ export default (api, accessories, config, tado, telegram) => {
14251431 }
14261432
14271433 async function updatePresence ( ) {
1428- if ( settingState ) return ;
1434+ if ( helpers [ config . homeId ] . settingState ) return ;
14291435
14301436 const presenceLockAccessory = accessories . filter (
14311437 ( acc ) => acc && acc . displayName === acc . context . config . homeName + ' Presence Lock'
@@ -1470,7 +1476,7 @@ export default (api, accessories, config, tado, telegram) => {
14701476 }
14711477
14721478 async function updateRunningTime ( ) {
1473- if ( settingState ) return ;
1479+ if ( helpers [ config . homeId ] . settingState ) return ;
14741480
14751481 const centralSwitchAccessory = accessories . filter (
14761482 ( acc ) => acc && acc . displayName === acc . context . config . homeName + ' Central Switch'
@@ -1515,7 +1521,7 @@ export default (api, accessories, config, tado, telegram) => {
15151521 }
15161522
15171523 async function updateDevices ( ) {
1518- if ( settingState ) return ;
1524+ if ( helpers [ config . homeId ] . settingState ) return ;
15191525
15201526 Logger . debug ( 'Polling Devices...' , config . homeName ) ;
15211527
@@ -1586,6 +1592,6 @@ export default (api, accessories, config, tado, telegram) => {
15861592 getStates : getStates ,
15871593 setStates : setStates ,
15881594 changedStates : changedStates ,
1589- refreshHistoryHandlers : aRefreshHistoryHandlers
1595+ refreshHistoryHandlers : helpers [ config . homeId ] . refreshHistoryHandlers
15901596 } ;
1591- } ;
1597+ } ;
0 commit comments