homebridge-verano 2.0.5 → 2.1.0
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/README.md +6 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +65 -53
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +76 -61
package/README.md
ADDED
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,8 @@ export declare class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
|
8
8
|
private readonly informationService;
|
|
9
9
|
private readonly name;
|
|
10
10
|
private readonly service;
|
|
11
|
-
private
|
|
11
|
+
private thermostatState;
|
|
12
|
+
private lastFetchTime;
|
|
12
13
|
private isAuthorized;
|
|
13
14
|
private sessionCookie;
|
|
14
15
|
private Characteristic;
|
|
@@ -16,8 +17,7 @@ export declare class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
|
16
17
|
identify?(): void;
|
|
17
18
|
getServices(): Service[];
|
|
18
19
|
getControllers?(): Controller[];
|
|
19
|
-
private
|
|
20
|
-
private fetchCurrentTemperature;
|
|
20
|
+
private requestThermostatState;
|
|
21
21
|
private fetchDataTiles;
|
|
22
22
|
private requestAuthorization;
|
|
23
23
|
private requestTemperatureChange;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAC,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAC,MAAM,YAAY,CAAC;AAa/F,qBAAa,qBAAsB,YAAW,eAAe;IAoBrD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IApBxB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAc;IAClD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAc;IAEtD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAM;IACzC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,eAAe,CAIrB;IACF,OAAO,CAAC,aAAa,CAAc;IAEnC,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAM;gBAGP,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,eAAe,EACvB,GAAG,EAAE,GAAG;IAmG7B,QAAQ,CAAC,IAAI,IAAI;IAIjB,WAAW,IAAI,OAAO,EAAE;IAOxB,cAAc,CAAC,IAAI,UAAU,EAAE;YAIjB,sBAAsB;YAatB,cAAc;YAmCd,oBAAoB;YAwBpB,wBAAwB;CA4BzC"}
|
package/dist/index.js
CHANGED
|
@@ -15,79 +15,82 @@ class VeranoAccessoryPlugin {
|
|
|
15
15
|
this.api = api;
|
|
16
16
|
this.TEMPERATURE_DIVIDER = 10;
|
|
17
17
|
this.TURN_ON_OFF_TEMPERATURE = 10;
|
|
18
|
-
this.
|
|
18
|
+
this.thermostatState = {
|
|
19
|
+
currentTemperature: 0,
|
|
20
|
+
targetTemperature: 0,
|
|
21
|
+
heating: false
|
|
22
|
+
};
|
|
23
|
+
this.lastFetchTime = -1;
|
|
19
24
|
this.log = log;
|
|
25
|
+
this.log.info('Verano accessory plugin initializing');
|
|
20
26
|
this.config = config;
|
|
21
27
|
this.name = config.name;
|
|
22
28
|
this.api = api;
|
|
23
29
|
this.isAuthorized = false;
|
|
24
30
|
this.sessionCookie = '';
|
|
25
|
-
this.
|
|
31
|
+
this.requestThermostatState()
|
|
32
|
+
.then(thermostatState => this.log.info('Fetched initial thermostat state', thermostatState));
|
|
26
33
|
this.Characteristic = this.api.hap.Characteristic;
|
|
27
34
|
this.informationService = new this.api.hap.Service.AccessoryInformation()
|
|
28
35
|
.setCharacteristic(this.api.hap.Characteristic.Manufacturer, "Verano")
|
|
29
36
|
.setCharacteristic(this.api.hap.Characteristic.Model, "VER-24 WiFi");
|
|
30
37
|
this.service = new this.api.hap.Service.Thermostat(this.name);
|
|
38
|
+
// GET CURRENT STATE
|
|
31
39
|
this.service.getCharacteristic(this.Characteristic.CurrentHeatingCoolingState)
|
|
32
40
|
.on('get', (callback) => {
|
|
33
|
-
this.log.debug('
|
|
34
|
-
const
|
|
35
|
-
callback(null,
|
|
41
|
+
this.log.debug('Get CurrentHeatingCoolingState');
|
|
42
|
+
const heatingState = this.thermostatState.heating ? this.Characteristic.CurrentHeatingCoolingState.HEAT : this.Characteristic.CurrentHeatingCoolingState.OFF;
|
|
43
|
+
callback(null, heatingState);
|
|
36
44
|
});
|
|
45
|
+
// GET TARGET STATE
|
|
37
46
|
this.service.getCharacteristic(this.Characteristic.TargetHeatingCoolingState)
|
|
38
47
|
.setProps({
|
|
39
48
|
validValues: [
|
|
40
49
|
this.Characteristic.TargetHeatingCoolingState.OFF,
|
|
41
50
|
this.Characteristic.TargetHeatingCoolingState.HEAT
|
|
42
51
|
]
|
|
43
|
-
})
|
|
44
|
-
this.service.getCharacteristic(this.Characteristic.TargetHeatingCoolingState)
|
|
52
|
+
})
|
|
45
53
|
.on('get', (callback) => {
|
|
46
|
-
this.log.debug('
|
|
47
|
-
this.
|
|
48
|
-
.then(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
this.log.debug('Get TargetHeatingCoolingState');
|
|
55
|
+
this.requestThermostatState()
|
|
56
|
+
.then(thermostatState => {
|
|
57
|
+
const heatingState = thermostatState.heating ? this.Characteristic.TargetHeatingCoolingState.HEAT : this.Characteristic.TargetHeatingCoolingState.OFF;
|
|
58
|
+
callback(null, heatingState);
|
|
59
|
+
})
|
|
60
|
+
.catch(error => callback(error));
|
|
53
61
|
})
|
|
54
62
|
.on('set', (value, callback) => {
|
|
55
|
-
this.
|
|
56
|
-
if (this.
|
|
63
|
+
this.thermostatState.heating = value === this.Characteristic.TargetHeatingCoolingState.HEAT;
|
|
64
|
+
if (this.thermostatState.heating) {
|
|
57
65
|
callback(null);
|
|
58
66
|
return;
|
|
59
67
|
}
|
|
60
|
-
this.log.info('Turning off');
|
|
68
|
+
this.log.info('Turning off heating...');
|
|
61
69
|
this.requestTemperatureChange(this.TURN_ON_OFF_TEMPERATURE)
|
|
62
|
-
.then(() =>
|
|
70
|
+
.then(() => {
|
|
71
|
+
this.log.info('Heating turned off');
|
|
72
|
+
callback(null);
|
|
73
|
+
})
|
|
63
74
|
.catch(error => callback(error));
|
|
64
75
|
});
|
|
76
|
+
// GET TEMPERATURE
|
|
65
77
|
this.service.getCharacteristic(this.Characteristic.CurrentTemperature)
|
|
66
78
|
.on('get', (callback) => {
|
|
67
|
-
this.log.debug('
|
|
68
|
-
this.
|
|
69
|
-
.then(
|
|
70
|
-
callback(
|
|
71
|
-
})
|
|
72
|
-
.catch(error => {
|
|
73
|
-
this.log.error('Error during current temperature fetch', error);
|
|
74
|
-
callback(error);
|
|
75
|
-
});
|
|
79
|
+
this.log.debug('Get CurrentTemperature');
|
|
80
|
+
this.requestThermostatState()
|
|
81
|
+
.then(thermostatState => callback(null, thermostatState.currentTemperature))
|
|
82
|
+
.catch(error => callback(error));
|
|
76
83
|
});
|
|
84
|
+
// GET TARGET TEMPERATURE
|
|
77
85
|
this.service.getCharacteristic(this.Characteristic.TargetTemperature)
|
|
78
86
|
.on('get', (callback) => {
|
|
79
|
-
this.log.debug('
|
|
80
|
-
this.
|
|
81
|
-
.then(
|
|
82
|
-
callback(
|
|
83
|
-
})
|
|
84
|
-
.catch(error => {
|
|
85
|
-
this.log.error('Error during current temperature fetch', error);
|
|
86
|
-
callback(error);
|
|
87
|
-
});
|
|
87
|
+
this.log.debug('Get TargetTemperature');
|
|
88
|
+
this.requestThermostatState()
|
|
89
|
+
.then(thermostatState => callback(null, thermostatState.targetTemperature))
|
|
90
|
+
.catch(error => callback(error));
|
|
88
91
|
})
|
|
89
92
|
.on('set', (value, callback) => {
|
|
90
|
-
this.log.debug('
|
|
93
|
+
this.log.debug('Set TargetTemperature:', value);
|
|
91
94
|
this.requestTemperatureChange(value)
|
|
92
95
|
.then(() => callback(null))
|
|
93
96
|
.catch(error => callback(error));
|
|
@@ -103,8 +106,7 @@ class VeranoAccessoryPlugin {
|
|
|
103
106
|
})
|
|
104
107
|
.on('set', (value, callback) => {
|
|
105
108
|
});
|
|
106
|
-
this.log.
|
|
107
|
-
this.requestAuthorization();
|
|
109
|
+
this.log.info('Verano accessory plugin initialized');
|
|
108
110
|
}
|
|
109
111
|
identify() {
|
|
110
112
|
this.log('Identify!');
|
|
@@ -118,18 +120,26 @@ class VeranoAccessoryPlugin {
|
|
|
118
120
|
getControllers() {
|
|
119
121
|
return [];
|
|
120
122
|
}
|
|
121
|
-
async
|
|
123
|
+
async requestThermostatState() {
|
|
122
124
|
const tiles = await this.fetchDataTiles();
|
|
123
125
|
const foundTile = tiles.filter(tile => tile.id === 58)[0];
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
const targetTemperature = foundTile.params.widget1.value / this.TEMPERATURE_DIVIDER;
|
|
127
|
+
const currentTemperature = foundTile.params.widget2.value / this.TEMPERATURE_DIVIDER;
|
|
128
|
+
this.thermostatState = {
|
|
129
|
+
currentTemperature: currentTemperature,
|
|
130
|
+
targetTemperature: targetTemperature,
|
|
131
|
+
heating: targetTemperature > this.TURN_ON_OFF_TEMPERATURE
|
|
132
|
+
};
|
|
133
|
+
return this.thermostatState;
|
|
130
134
|
}
|
|
131
135
|
async fetchDataTiles() {
|
|
132
|
-
|
|
136
|
+
const currentTime = new Date().getTime();
|
|
137
|
+
if (this.lastFetchTime > 0 && currentTime - this.lastFetchTime < 2500) {
|
|
138
|
+
this.log.debug('Returning cached thermostat state', this.thermostatState);
|
|
139
|
+
return this.thermostatState;
|
|
140
|
+
}
|
|
141
|
+
this.log.debug('Fetching data tiles...');
|
|
142
|
+
this.lastFetchTime = currentTime;
|
|
133
143
|
if (!this.isAuthorized) {
|
|
134
144
|
this.log.error('Not authorized, cannot get tiles, trying to authorize');
|
|
135
145
|
await this.requestAuthorization();
|
|
@@ -138,13 +148,14 @@ class VeranoAccessoryPlugin {
|
|
|
138
148
|
headers: {
|
|
139
149
|
'Cookie': this.sessionCookie
|
|
140
150
|
},
|
|
141
|
-
withCredentials: true
|
|
151
|
+
withCredentials: true,
|
|
142
152
|
};
|
|
143
153
|
return axios_1.default
|
|
144
154
|
.get('https://emodul.pl/frontend/module_data', config)
|
|
145
155
|
.then(response => {
|
|
146
156
|
const tiles = response.data.tiles;
|
|
147
|
-
this.log.
|
|
157
|
+
this.log.debug("Fetched", tiles.length, "data tiles");
|
|
158
|
+
this.log.debug(tiles);
|
|
148
159
|
return tiles;
|
|
149
160
|
}).catch(error => {
|
|
150
161
|
this.log.error("Error during tiles fetch", error);
|
|
@@ -164,20 +175,21 @@ class VeranoAccessoryPlugin {
|
|
|
164
175
|
return axios_1.default
|
|
165
176
|
.post('https://emodul.pl/login', requestBody)
|
|
166
177
|
.then(loginResponse => {
|
|
167
|
-
this.log.info('Successfully authorized');
|
|
178
|
+
this.log.info('Successfully authorized', requestBody.username);
|
|
168
179
|
const cookies = loginResponse.headers['set-cookie'];
|
|
169
180
|
this.sessionCookie = cookies.filter(cookie => cookie.includes('session'))[0];
|
|
170
181
|
this.isAuthorized = true;
|
|
171
182
|
return loginResponse;
|
|
172
183
|
})
|
|
173
184
|
.catch(error => {
|
|
174
|
-
this.log.error("Error during authorization", error);
|
|
185
|
+
this.log.error("Error during authorization", requestBody.username, error);
|
|
175
186
|
this.isAuthorized = false;
|
|
176
187
|
throw error;
|
|
177
188
|
});
|
|
178
189
|
}
|
|
179
190
|
async requestTemperatureChange(targetTemperature) {
|
|
180
|
-
this.log.info('Changing temperature to', targetTemperature);
|
|
191
|
+
this.log.info('Changing temperature to', targetTemperature + '°C');
|
|
192
|
+
this.lastFetchTime = -1;
|
|
181
193
|
const requestBody = [
|
|
182
194
|
{
|
|
183
195
|
ido: 139,
|
|
@@ -194,7 +206,7 @@ class VeranoAccessoryPlugin {
|
|
|
194
206
|
return axios_1.default
|
|
195
207
|
.post('https://emodul.pl/send_control_data', requestBody, config)
|
|
196
208
|
.then(response => {
|
|
197
|
-
this.log.info('Successfully changed temperature');
|
|
209
|
+
this.log.info('Successfully changed temperature to', targetTemperature + '°C');
|
|
198
210
|
return response === null || response === void 0 ? void 0 : response.data;
|
|
199
211
|
})
|
|
200
212
|
.catch(error => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AACA,kDAA0B;AAE1B,MAAM,CAAC,OAAO,GAAG,CAAC,GAAQ,EAAE,EAAE;IAC1B,GAAG,CAAC,iBAAiB,CAAC,uBAAuB,EAAE,qBAAqB,CAAC,CAAC;AAC1E,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AACA,kDAA0B;AAE1B,MAAM,CAAC,OAAO,GAAG,CAAC,GAAQ,EAAE,EAAE;IAC1B,GAAG,CAAC,iBAAiB,CAAC,uBAAuB,EAAE,qBAAqB,CAAC,CAAC;AAC1E,CAAC,CAAA;AAQD,MAAa,qBAAqB;IAmB9B,YACqB,GAAY,EACZ,MAAuB,EACvB,GAAQ;QAFR,QAAG,GAAH,GAAG,CAAS;QACZ,WAAM,GAAN,MAAM,CAAiB;QACvB,QAAG,GAAH,GAAG,CAAK;QApBZ,wBAAmB,GAAW,EAAE,CAAC;QACjC,4BAAuB,GAAW,EAAE,CAAC;QAK9C,oBAAe,GAAoB;YACvC,kBAAkB,EAAE,CAAC;YACrB,iBAAiB,EAAE,CAAC;YACpB,OAAO,EAAE,KAAK;SACjB,CAAC;QACM,kBAAa,GAAW,CAAC,CAAC,CAAC;QAW/B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QAExB,IAAI,CAAC,sBAAsB,EAAE;aACxB,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kCAAkC,EAAE,eAAe,CAAC,CAAC,CAAA;QAEhG,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC;QAElD,IAAI,CAAC,kBAAkB,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,oBAAoB,EAAE;aACpE,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,QAAQ,CAAC;aACrE,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QAEzE,IAAI,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE9D,oBAAoB;QACpB,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,0BAA0B,CAAC;aACzE,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE;YACpB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACjD,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,0BAA0B,CAAC,GAAG,CAAC;YAC7J,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEP,mBAAmB;QACnB,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,yBAAyB,CAAC;aACxE,QAAQ,CAAC;YACN,WAAW,EAAE;gBACT,IAAI,CAAC,cAAc,CAAC,yBAAyB,CAAC,GAAG;gBACjD,IAAI,CAAC,cAAc,CAAC,yBAAyB,CAAC,IAAI;aACrD;SACJ,CAAC;aACD,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE;YACpB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAChD,IAAI,CAAC,sBAAsB,EAAE;iBACxB,IAAI,CAAC,eAAe,CAAC,EAAE;gBACpB,MAAM,YAAY,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,yBAAyB,CAAC,GAAG,CAAC;gBACtJ,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;YACjC,CAAC,CAAC;iBACD,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC;aACD,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;YAC3B,IAAI,CAAC,eAAe,CAAC,OAAO,GAAG,KAAK,KAAK,IAAI,CAAC,cAAc,CAAC,yBAAyB,CAAC,IAAI,CAAC;YAC5F,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;gBAC9B,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACf,OAAO;aACV;YACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YACxC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,uBAAuB,CAAC;iBACtD,IAAI,CAAC,GAAG,EAAE;gBACP,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBACpC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC,CAAC;iBACD,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEP,kBAAkB;QAClB,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,kBAAkB,CAAC;aACjE,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE;YACpB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACzC,IAAI,CAAC,sBAAsB,EAAE;iBACxB,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,kBAAkB,CAAC,CAAC;iBAC3E,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEP,yBAAyB;QACzB,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC;aAChE,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE;YACpB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YACxC,IAAI,CAAC,sBAAsB,EAAE;iBACxB,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,iBAAiB,CAAC,CAAC;iBAC1E,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC;aACD,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;YAC3B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;YAChD,IAAI,CAAC,wBAAwB,CAAC,KAAe,CAAC;iBACzC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;iBAC1B,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC;aACD,QAAQ,CAAC;YACN,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,EAAE;YACZ,OAAO,EAAE,GAAG;SACf,CAAC,CAAC;QAEP,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,uBAAuB,CAAC;aACtE,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE;YACpB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC;QACxE,CAAC,CAAC;aACD,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC/B,CAAC,CAAC,CAAC;QACP,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,QAAQ;QACJ,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC;IAED,WAAW;QACP,OAAO;YACH,IAAI,CAAC,kBAAkB;YACvB,IAAI,CAAC,OAAO;SACf,CAAC;IACN,CAAC;IAED,cAAc;QACV,OAAO,EAAE,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,sBAAsB;QAChC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,iBAAiB,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC;QACpF,MAAM,kBAAkB,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC;QACrF,IAAI,CAAC,eAAe,GAAG;YACnB,kBAAkB,EAAE,kBAAkB;YACtC,iBAAiB,EAAE,iBAAiB;YACpC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC,uBAAuB;SAC5D,CAAC;QACF,OAAO,IAAI,CAAC,eAAe,CAAC;IAChC,CAAC;IAEO,KAAK,CAAC,cAAc;QAExB,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,WAAW,GAAG,IAAI,CAAC,aAAa,GAAG,IAAI,EAAE;YACnE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,mCAAmC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;YAC1E,OAAO,IAAI,CAAC,eAAe,CAAC;SAC/B;QACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACzC,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC;QAEjC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACpB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;YACxE,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;SACrC;QAED,MAAM,MAAM,GAAG;YACX,OAAO,EAAE;gBACL,QAAQ,EAAE,IAAI,CAAC,aAAa;aAC/B;YACD,eAAe,EAAE,IAAI;SACxB,CAAC;QACF,OAAO,eAAK;aACP,GAAG,CAAC,wCAAwC,EAAE,MAAM,CAAC;aACrD,IAAI,CAAC,QAAQ,CAAC,EAAE;YACb,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;YAClC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACtD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACtB,OAAO,KAAK,CAAC;QACjB,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;YACb,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC1B,MAAM,KAAK,CAAC;QAChB,CAAC,CAAC,CAAC;IACX,CAAC;IAAA,CAAC;IAEM,KAAK,CAAC,oBAAoB;QAC9B,MAAM,WAAW,GAAG;YAChB,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC9B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC9B,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,IAAI;SACnB,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QACrE,OAAO,eAAK;aACP,IAAI,CAAC,yBAAyB,EAAE,WAAW,CAAC;aAC5C,IAAI,CAAC,aAAa,CAAC,EAAE;YAClB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,yBAAyB,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC/D,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YACpD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7E,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,OAAO,aAAa,CAAC;QACzB,CAAC,CAAC;aACD,KAAK,CAAC,KAAK,CAAC,EAAE;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,4BAA4B,EAAE,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC1E,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC1B,MAAM,KAAK,CAAC;QAChB,CAAC,CAAC,CAAC;IACX,CAAC;IAEO,KAAK,CAAC,wBAAwB,CAAC,iBAAyB;QAC5D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,yBAAyB,EAAE,iBAAiB,GAAG,IAAI,CAAC,CAAC;QACnE,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;QACxB,MAAM,WAAW,GAAG;YAChB;gBACI,GAAG,EAAE,GAAG;gBACR,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC,mBAAmB;gBACpD,YAAY,EAAE,CAAC;aAClB;SACJ,CAAA;QACD,MAAM,MAAM,GAAG;YACX,OAAO,EAAE;gBACL,QAAQ,EAAE,IAAI,CAAC,aAAa;aAC/B;YACD,eAAe,EAAE,IAAI;SACxB,CAAC;QACF,OAAO,eAAK;aACP,IAAI,CAAC,qCAAqC,EAAE,WAAW,EAAE,MAAM,CAAC;aAChE,IAAI,CAAC,QAAQ,CAAC,EAAE;YACb,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,qCAAqC,EAAE,iBAAiB,GAAG,IAAI,CAAC,CAAC;YAC/E,OAAO,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,CAAC;QAC1B,CAAC,CAAC;aACD,KAAK,CAAC,KAAK,CAAC,EAAE;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;YACzD,MAAM,KAAK,CAAC;QAChB,CAAC,CAAC,CAAA;IACV,CAAC;CAEJ;AA5OD,sDA4OC"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -5,16 +5,27 @@ module.exports = (api: API) => {
|
|
|
5
5
|
api.registerAccessory('VeranoAccessoryPlugin', VeranoAccessoryPlugin);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
interface ThermostatState {
|
|
9
|
+
currentTemperature: number;
|
|
10
|
+
targetTemperature: number;
|
|
11
|
+
heating: boolean;
|
|
12
|
+
}
|
|
8
13
|
|
|
9
14
|
export class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
10
15
|
|
|
11
16
|
private readonly TEMPERATURE_DIVIDER: number = 10;
|
|
12
17
|
private readonly TURN_ON_OFF_TEMPERATURE: number = 10;
|
|
18
|
+
|
|
13
19
|
private readonly informationService: any;
|
|
14
20
|
private readonly name: string;
|
|
15
21
|
private readonly service: Service;
|
|
22
|
+
private thermostatState: ThermostatState = {
|
|
23
|
+
currentTemperature: 0,
|
|
24
|
+
targetTemperature: 0,
|
|
25
|
+
heating: false
|
|
26
|
+
};
|
|
27
|
+
private lastFetchTime: number = -1;
|
|
16
28
|
|
|
17
|
-
private isOn: boolean;
|
|
18
29
|
private isAuthorized: boolean;
|
|
19
30
|
private sessionCookie: string;
|
|
20
31
|
private Characteristic: any;
|
|
@@ -24,14 +35,16 @@ export class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
|
24
35
|
private readonly config: AccessoryConfig,
|
|
25
36
|
private readonly api: API,
|
|
26
37
|
) {
|
|
27
|
-
this.log.debug('Verano accessory plugin initializing');
|
|
28
38
|
this.log = log;
|
|
39
|
+
this.log.info('Verano accessory plugin initializing');
|
|
29
40
|
this.config = config;
|
|
30
41
|
this.name = config.name;
|
|
31
42
|
this.api = api;
|
|
32
43
|
this.isAuthorized = false;
|
|
33
44
|
this.sessionCookie = '';
|
|
34
|
-
|
|
45
|
+
|
|
46
|
+
this.requestThermostatState()
|
|
47
|
+
.then(thermostatState => this.log.info('Fetched initial thermostat state', thermostatState))
|
|
35
48
|
|
|
36
49
|
this.Characteristic = this.api.hap.Characteristic;
|
|
37
50
|
|
|
@@ -41,72 +54,65 @@ export class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
|
41
54
|
|
|
42
55
|
this.service = new this.api.hap.Service.Thermostat(this.name);
|
|
43
56
|
|
|
57
|
+
// GET CURRENT STATE
|
|
44
58
|
this.service.getCharacteristic(this.Characteristic.CurrentHeatingCoolingState)
|
|
45
59
|
.on('get', (callback) => {
|
|
46
|
-
this.log.debug('
|
|
47
|
-
const
|
|
48
|
-
callback(null,
|
|
60
|
+
this.log.debug('Get CurrentHeatingCoolingState');
|
|
61
|
+
const heatingState = this.thermostatState.heating ? this.Characteristic.CurrentHeatingCoolingState.HEAT : this.Characteristic.CurrentHeatingCoolingState.OFF;
|
|
62
|
+
callback(null, heatingState);
|
|
49
63
|
});
|
|
50
64
|
|
|
65
|
+
// GET TARGET STATE
|
|
51
66
|
this.service.getCharacteristic(this.Characteristic.TargetHeatingCoolingState)
|
|
52
67
|
.setProps({
|
|
53
68
|
validValues: [
|
|
54
69
|
this.Characteristic.TargetHeatingCoolingState.OFF,
|
|
55
70
|
this.Characteristic.TargetHeatingCoolingState.HEAT
|
|
56
71
|
]
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
this.service.getCharacteristic(this.Characteristic.TargetHeatingCoolingState)
|
|
72
|
+
})
|
|
60
73
|
.on('get', (callback) => {
|
|
61
|
-
this.log.debug('
|
|
62
|
-
this.
|
|
63
|
-
.then(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
this.log.debug('Get TargetHeatingCoolingState');
|
|
75
|
+
this.requestThermostatState()
|
|
76
|
+
.then(thermostatState => {
|
|
77
|
+
const heatingState = thermostatState.heating ? this.Characteristic.TargetHeatingCoolingState.HEAT : this.Characteristic.TargetHeatingCoolingState.OFF;
|
|
78
|
+
callback(null, heatingState);
|
|
79
|
+
})
|
|
80
|
+
.catch(error => callback(error));
|
|
68
81
|
})
|
|
69
82
|
.on('set', (value, callback) => {
|
|
70
|
-
this.
|
|
71
|
-
if (this.
|
|
83
|
+
this.thermostatState.heating = value === this.Characteristic.TargetHeatingCoolingState.HEAT;
|
|
84
|
+
if (this.thermostatState.heating) {
|
|
72
85
|
callback(null);
|
|
73
86
|
return;
|
|
74
87
|
}
|
|
75
|
-
this.log.info('Turning off');
|
|
88
|
+
this.log.info('Turning off heating...');
|
|
76
89
|
this.requestTemperatureChange(this.TURN_ON_OFF_TEMPERATURE)
|
|
77
|
-
.then(() =>
|
|
90
|
+
.then(() => {
|
|
91
|
+
this.log.info('Heating turned off');
|
|
92
|
+
callback(null);
|
|
93
|
+
})
|
|
78
94
|
.catch(error => callback(error));
|
|
79
|
-
|
|
80
|
-
|
|
81
95
|
});
|
|
82
96
|
|
|
97
|
+
// GET TEMPERATURE
|
|
83
98
|
this.service.getCharacteristic(this.Characteristic.CurrentTemperature)
|
|
84
99
|
.on('get', (callback) => {
|
|
85
|
-
this.log.debug('
|
|
86
|
-
this.
|
|
87
|
-
.then(
|
|
88
|
-
|
|
89
|
-
})
|
|
90
|
-
.catch(error => {
|
|
91
|
-
this.log.error('Error during current temperature fetch', error);
|
|
92
|
-
callback(error);
|
|
93
|
-
});
|
|
100
|
+
this.log.debug('Get CurrentTemperature');
|
|
101
|
+
this.requestThermostatState()
|
|
102
|
+
.then(thermostatState => callback(null, thermostatState.currentTemperature))
|
|
103
|
+
.catch(error => callback(error));
|
|
94
104
|
});
|
|
95
105
|
|
|
106
|
+
// GET TARGET TEMPERATURE
|
|
96
107
|
this.service.getCharacteristic(this.Characteristic.TargetTemperature)
|
|
97
108
|
.on('get', (callback) => {
|
|
98
|
-
this.log.debug('
|
|
99
|
-
this.
|
|
100
|
-
.then(
|
|
101
|
-
|
|
102
|
-
})
|
|
103
|
-
.catch(error => {
|
|
104
|
-
this.log.error('Error during current temperature fetch', error);
|
|
105
|
-
callback(error);
|
|
106
|
-
});
|
|
109
|
+
this.log.debug('Get TargetTemperature');
|
|
110
|
+
this.requestThermostatState()
|
|
111
|
+
.then(thermostatState => callback(null, thermostatState.targetTemperature))
|
|
112
|
+
.catch(error => callback(error));
|
|
107
113
|
})
|
|
108
114
|
.on('set', (value, callback) => {
|
|
109
|
-
this.log.debug('
|
|
115
|
+
this.log.debug('Set TargetTemperature:', value);
|
|
110
116
|
this.requestTemperatureChange(value as number)
|
|
111
117
|
.then(() => callback(null))
|
|
112
118
|
.catch(error => callback(error));
|
|
@@ -123,9 +129,7 @@ export class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
|
123
129
|
})
|
|
124
130
|
.on('set', (value, callback) => {
|
|
125
131
|
});
|
|
126
|
-
|
|
127
|
-
this.log.debug('Verano accessory plugin initialized');
|
|
128
|
-
this.requestAuthorization();
|
|
132
|
+
this.log.info('Verano accessory plugin initialized');
|
|
129
133
|
}
|
|
130
134
|
|
|
131
135
|
identify?(): void {
|
|
@@ -143,20 +147,29 @@ export class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
|
143
147
|
return [];
|
|
144
148
|
}
|
|
145
149
|
|
|
146
|
-
private async
|
|
147
|
-
const tiles = await this.fetchDataTiles()
|
|
148
|
-
const foundTile = tiles.filter(tile => tile.id === 58)[0]
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
150
|
+
private async requestThermostatState() {
|
|
151
|
+
const tiles = await this.fetchDataTiles();
|
|
152
|
+
const foundTile = tiles.filter(tile => tile.id === 58)[0];
|
|
153
|
+
const targetTemperature = foundTile.params.widget1.value / this.TEMPERATURE_DIVIDER;
|
|
154
|
+
const currentTemperature = foundTile.params.widget2.value / this.TEMPERATURE_DIVIDER;
|
|
155
|
+
this.thermostatState = {
|
|
156
|
+
currentTemperature: currentTemperature,
|
|
157
|
+
targetTemperature: targetTemperature,
|
|
158
|
+
heating: targetTemperature > this.TURN_ON_OFF_TEMPERATURE
|
|
159
|
+
};
|
|
160
|
+
return this.thermostatState;
|
|
156
161
|
}
|
|
157
162
|
|
|
158
163
|
private async fetchDataTiles() {
|
|
159
|
-
|
|
164
|
+
|
|
165
|
+
const currentTime = new Date().getTime();
|
|
166
|
+
if (this.lastFetchTime > 0 && currentTime - this.lastFetchTime < 2500) {
|
|
167
|
+
this.log.debug('Returning cached thermostat state', this.thermostatState);
|
|
168
|
+
return this.thermostatState;
|
|
169
|
+
}
|
|
170
|
+
this.log.debug('Fetching data tiles...');
|
|
171
|
+
this.lastFetchTime = currentTime;
|
|
172
|
+
|
|
160
173
|
if (!this.isAuthorized) {
|
|
161
174
|
this.log.error('Not authorized, cannot get tiles, trying to authorize');
|
|
162
175
|
await this.requestAuthorization();
|
|
@@ -166,13 +179,14 @@ export class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
|
166
179
|
headers: {
|
|
167
180
|
'Cookie': this.sessionCookie
|
|
168
181
|
},
|
|
169
|
-
withCredentials: true
|
|
182
|
+
withCredentials: true,
|
|
170
183
|
};
|
|
171
184
|
return axios
|
|
172
185
|
.get('https://emodul.pl/frontend/module_data', config)
|
|
173
186
|
.then(response => {
|
|
174
187
|
const tiles = response.data.tiles;
|
|
175
|
-
this.log.
|
|
188
|
+
this.log.debug("Fetched", tiles.length, "data tiles");
|
|
189
|
+
this.log.debug(tiles);
|
|
176
190
|
return tiles;
|
|
177
191
|
}).catch(error => {
|
|
178
192
|
this.log.error("Error during tiles fetch", error);
|
|
@@ -192,21 +206,22 @@ export class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
|
192
206
|
return axios
|
|
193
207
|
.post('https://emodul.pl/login', requestBody)
|
|
194
208
|
.then(loginResponse => {
|
|
195
|
-
this.log.info('Successfully authorized');
|
|
209
|
+
this.log.info('Successfully authorized', requestBody.username);
|
|
196
210
|
const cookies = loginResponse.headers['set-cookie'];
|
|
197
211
|
this.sessionCookie = cookies.filter(cookie => cookie.includes('session'))[0];
|
|
198
212
|
this.isAuthorized = true;
|
|
199
213
|
return loginResponse;
|
|
200
214
|
})
|
|
201
215
|
.catch(error => {
|
|
202
|
-
this.log.error("Error during authorization", error);
|
|
216
|
+
this.log.error("Error during authorization", requestBody.username, error);
|
|
203
217
|
this.isAuthorized = false;
|
|
204
218
|
throw error;
|
|
205
219
|
});
|
|
206
220
|
}
|
|
207
221
|
|
|
208
222
|
private async requestTemperatureChange(targetTemperature: number) {
|
|
209
|
-
this.log.info('Changing temperature to', targetTemperature);
|
|
223
|
+
this.log.info('Changing temperature to', targetTemperature + '°C');
|
|
224
|
+
this.lastFetchTime = -1;
|
|
210
225
|
const requestBody = [
|
|
211
226
|
{
|
|
212
227
|
ido: 139,
|
|
@@ -223,7 +238,7 @@ export class VeranoAccessoryPlugin implements AccessoryPlugin {
|
|
|
223
238
|
return axios
|
|
224
239
|
.post('https://emodul.pl/send_control_data', requestBody, config)
|
|
225
240
|
.then(response => {
|
|
226
|
-
this.log.info('Successfully changed temperature');
|
|
241
|
+
this.log.info('Successfully changed temperature to', targetTemperature + '°C');
|
|
227
242
|
return response?.data;
|
|
228
243
|
})
|
|
229
244
|
.catch(error => {
|