@homebridge-plugins/homebridge-tado 8.3.0-beta.4 → 8.3.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/helper/handler.js +23 -13
- package/src/tado/tado-api.js +12 -19
package/package.json
CHANGED
package/src/helper/handler.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Logger from '../helper/logger.js';
|
|
2
2
|
import moment from 'moment';
|
|
3
|
-
import { writeFile } from 'fs/promises';
|
|
3
|
+
import { writeFile, access, readFile } from 'fs/promises';
|
|
4
4
|
import { join } from "path";
|
|
5
5
|
|
|
6
6
|
var settingState = false;
|
|
@@ -10,6 +10,18 @@ let tasksInitialized = false;
|
|
|
10
10
|
const timeout = (ms) => new Promise((res) => setTimeout(res, ms));
|
|
11
11
|
const aRefreshHistoryHandlers = [];
|
|
12
12
|
|
|
13
|
+
export async function getPersistedStates(storagePath) {
|
|
14
|
+
try {
|
|
15
|
+
const sFilePath = join(storagePath, "tado-states.json");
|
|
16
|
+
await access(sFilePath);
|
|
17
|
+
const sData = (await readFile(sFilePath, "utf-8"));
|
|
18
|
+
if (sData) return JSON.parse(sData);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
//no states data => ignore
|
|
21
|
+
Logger.debug(`Failed to read tado states file: ${error.message || error}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
13
25
|
export default (api, accessories, config, tado, telegram) => {
|
|
14
26
|
const storagePath = api.user.storagePath();
|
|
15
27
|
|
|
@@ -705,26 +717,24 @@ export default (api, accessories, config, tado, telegram) => {
|
|
|
705
717
|
|
|
706
718
|
async function persistStates(homeId, zoneStates) {
|
|
707
719
|
try {
|
|
708
|
-
const
|
|
709
|
-
|
|
710
|
-
await writeFile(join(storagePath, `tado-states-${homeId}.json`), JSON.stringify(
|
|
720
|
+
const homeData = {};
|
|
721
|
+
homeData.zoneStates = zoneStates ?? {};
|
|
722
|
+
await writeFile(join(storagePath, `tado-states-${homeId}.json`), JSON.stringify(homeData, null, 2), "utf-8");
|
|
711
723
|
} catch (error) {
|
|
712
|
-
Logger.error(`Error while updating tado states file for home id ${homeId}: ${error.message || error}`);
|
|
724
|
+
Logger.error(`Error while updating the tado states file for home id ${homeId}: ${error.message || error}`);
|
|
713
725
|
}
|
|
714
726
|
try {
|
|
715
727
|
const data = {};
|
|
716
728
|
data.counterData = await tado.getCounterData();
|
|
717
|
-
await writeFile(join(storagePath, "tado-
|
|
729
|
+
await writeFile(join(storagePath, "tado-states.json"), JSON.stringify(data, null, 2), "utf-8");
|
|
718
730
|
} catch (error) {
|
|
719
|
-
Logger.error(`Error while updating tado
|
|
731
|
+
Logger.error(`Error while updating the tado states file: ${error.message || error}`);
|
|
720
732
|
}
|
|
721
733
|
try {
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
fnRefreshHistory();
|
|
727
|
-
}
|
|
734
|
+
//wait for fakegato services to be loaded
|
|
735
|
+
await new Promise(r => setTimeout(r, 4000));
|
|
736
|
+
for (const fnRefreshHistory of aRefreshHistoryHandlers) {
|
|
737
|
+
fnRefreshHistory();
|
|
728
738
|
}
|
|
729
739
|
} catch (error) {
|
|
730
740
|
Logger.error(`Error while refreshing history: ${error.message || error}`);
|
package/src/tado/tado-api.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import Logger from '../helper/logger.js';
|
|
2
|
+
import { getPersistedStates } from '../helper/handler.js';
|
|
2
3
|
import got from 'got';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { access, readFile, writeFile } from 'fs/promises';
|
|
5
6
|
|
|
6
7
|
const tado_url = "https://my.tado.com";
|
|
7
8
|
const tado_auth_url = "https://login.tado.com/oauth2";
|
|
@@ -25,7 +26,7 @@ export default class Tado {
|
|
|
25
26
|
return (hash >>> 0).toString(36).padStart(7, '0');
|
|
26
27
|
};
|
|
27
28
|
this.username = usesExternalTokenFile ? undefined : config.username;
|
|
28
|
-
this._tadoInternalTokenFilePath = usesExternalTokenFile ? undefined :
|
|
29
|
+
this._tadoInternalTokenFilePath = usesExternalTokenFile ? undefined : join(this.storagePath, `.tado-token-${fnSimpleHash(config.username)}.json`);
|
|
29
30
|
this._tadoApiClientId = tado_client_id;
|
|
30
31
|
this._tadoTokenPromise = undefined;
|
|
31
32
|
this._tadoAuthenticationCallback = undefined;
|
|
@@ -34,17 +35,9 @@ export default class Tado {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
async _initCounter() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
await access(sFilePath);
|
|
41
|
-
const sData = (await readFile(sFilePath, "utf-8"));
|
|
42
|
-
counterData = JSON.parse(sData)?.counterData;
|
|
43
|
-
} catch (_err) {
|
|
44
|
-
//no counter data => ignore
|
|
45
|
-
}
|
|
46
|
-
this._counter = counterData?.counter ?? 0;
|
|
47
|
-
this._counterTimestamp = counterData?.counterTimestamp ?? new Date().toISOString();
|
|
38
|
+
const persistedCounterData = (await getPersistedStates(this.storagePath))?.counterData;
|
|
39
|
+
this._counter = persistedCounterData?.counter ?? 0;
|
|
40
|
+
this._counterTimestamp = persistedCounterData?.counterTimestamp ?? new Date().toISOString();
|
|
48
41
|
this._checkCounterMidnightReset();
|
|
49
42
|
}
|
|
50
43
|
|
|
@@ -106,7 +99,7 @@ export default class Tado {
|
|
|
106
99
|
async _retrieveToken() {
|
|
107
100
|
try {
|
|
108
101
|
if (this._tadoBearerToken.refresh_token) return this._refreshToken(this._tadoBearerToken.refresh_token);
|
|
109
|
-
await
|
|
102
|
+
await access(this._tadoInternalTokenFilePath);
|
|
110
103
|
const refresh_token = await this._retrieveRefreshTokenFromInternalFile();
|
|
111
104
|
return this._refreshToken(refresh_token);
|
|
112
105
|
|
|
@@ -119,7 +112,7 @@ export default class Tado {
|
|
|
119
112
|
const maxRetries = 3;
|
|
120
113
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
121
114
|
try {
|
|
122
|
-
const data = await
|
|
115
|
+
const data = await readFile(this._tadoInternalTokenFilePath, "utf8");
|
|
123
116
|
const json = JSON.parse(data);
|
|
124
117
|
if (json.refresh_token) return json.refresh_token;
|
|
125
118
|
} catch (error) {
|
|
@@ -145,7 +138,7 @@ export default class Tado {
|
|
|
145
138
|
await this._increaseCounter();
|
|
146
139
|
const { access_token, refresh_token } = response.body;
|
|
147
140
|
if (!access_token || !refresh_token) throw new Error("Empty access/refresh token.");
|
|
148
|
-
await
|
|
141
|
+
await writeFile(this._tadoInternalTokenFilePath, JSON.stringify({ access_token, refresh_token }));
|
|
149
142
|
this._tadoBearerToken = { access_token, refresh_token, timestamp: Date.now() };
|
|
150
143
|
} catch (error) {
|
|
151
144
|
Logger.warn(`Error while refreshing token: ${error.message || error}`);
|
|
@@ -187,7 +180,7 @@ export default class Tado {
|
|
|
187
180
|
if (tokenResponse?.body) {
|
|
188
181
|
const { access_token, refresh_token } = tokenResponse.body;
|
|
189
182
|
if (access_token && refresh_token) {
|
|
190
|
-
await
|
|
183
|
+
await writeFile(this._tadoInternalTokenFilePath, JSON.stringify({ access_token, refresh_token }));
|
|
191
184
|
this._tadoBearerToken = { access_token, refresh_token, timestamp: Date.now() };
|
|
192
185
|
Logger.info("Authentication successful!");
|
|
193
186
|
return;
|
|
@@ -202,7 +195,7 @@ export default class Tado {
|
|
|
202
195
|
const maxRetries = 3;
|
|
203
196
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
204
197
|
try {
|
|
205
|
-
const data = await
|
|
198
|
+
const data = await readFile(this._tadoExternalTokenFilePath, 'utf8');
|
|
206
199
|
const json = JSON.parse(data);
|
|
207
200
|
if (json.access_token) {
|
|
208
201
|
this._tadoBearerToken = { access_token: json.access_token, refresh_token: undefined, timestamp: Date.now() };
|