@homebridge-plugins/homebridge-tado 6.0.14

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +152 -0
  2. package/LICENSE +21 -0
  3. package/README.md +560 -0
  4. package/config.schema.json +878 -0
  5. package/homebridge-ui/public/css/style.css +25 -0
  6. package/homebridge-ui/public/images/tado_logo.png +0 -0
  7. package/homebridge-ui/public/index.html +118 -0
  8. package/homebridge-ui/public/js/main.js +1582 -0
  9. package/homebridge-ui/public/js/modules/compareVersions.min.js +1 -0
  10. package/homebridge-ui/public/js/modules/jquery.min.js +2 -0
  11. package/homebridge-ui/public/js/modules/progressbar.min.js +6 -0
  12. package/homebridge-ui/public/js/progressbars.js +48 -0
  13. package/homebridge-ui/public/js/schema.js +864 -0
  14. package/homebridge-ui/server.js +80 -0
  15. package/images/tado_logo.png +0 -0
  16. package/index.js +14 -0
  17. package/package.json +66 -0
  18. package/src/accessories/airquality.js +56 -0
  19. package/src/accessories/contact.js +124 -0
  20. package/src/accessories/faucet.js +63 -0
  21. package/src/accessories/heatercooler.js +333 -0
  22. package/src/accessories/humidity.js +90 -0
  23. package/src/accessories/lightbulb.js +59 -0
  24. package/src/accessories/lightsensor.js +40 -0
  25. package/src/accessories/motion.js +79 -0
  26. package/src/accessories/occupancy.js +45 -0
  27. package/src/accessories/security.js +79 -0
  28. package/src/accessories/switch.js +261 -0
  29. package/src/accessories/temperature.js +95 -0
  30. package/src/accessories/thermostat.js +337 -0
  31. package/src/helper/handler.js +1467 -0
  32. package/src/helper/logger.js +51 -0
  33. package/src/helper/telegram.js +60 -0
  34. package/src/platform.js +337 -0
  35. package/src/tado/tado-api.js +404 -0
  36. package/src/tado/tado-config.js +1032 -0
  37. package/src/types/custom.js +264 -0
  38. package/src/types/eve.js +337 -0
@@ -0,0 +1,80 @@
1
+ const { HomebridgePluginUiServer } = require('@homebridge/plugin-ui-utils');
2
+ const { RequestError } = require('@homebridge/plugin-ui-utils');
3
+
4
+ const TadoApi = require('../src/tado/tado-api.js');
5
+
6
+ class UiServer extends HomebridgePluginUiServer {
7
+ constructor () {
8
+
9
+ super();
10
+
11
+ this.onRequest('/authenticate', this.authenticate.bind(this));
12
+ this.onRequest('/exec', this.exec.bind(this));
13
+ this.onRequest('/reset', this.reset.bind(this));
14
+
15
+ this.tado = false;
16
+
17
+ this.ready();
18
+ }
19
+
20
+ authenticate(config){
21
+
22
+ this.tado = new TadoApi('Config UI X', { username: config.username, password: config.password });
23
+
24
+ return;
25
+
26
+ }
27
+
28
+ reset(){
29
+
30
+ this.tado = false;
31
+
32
+ return;
33
+
34
+ }
35
+
36
+ async exec(payload){
37
+
38
+ if(this.tado){
39
+
40
+ try {
41
+
42
+ console.log('Executing /' + payload.dest);
43
+
44
+ let value1, value2, value3;
45
+
46
+ if(payload.data){
47
+ if(typeof payload.data === 'object'){
48
+ value1 = payload.data[0];
49
+ value2 = payload.data[1];
50
+ value3 = payload.data[2];
51
+ } else {
52
+ value1 = payload.data;
53
+ }
54
+ }
55
+
56
+ const data = await this.tado[payload.dest](value1, value2, value3);
57
+
58
+ return data;
59
+
60
+ } catch(err){
61
+
62
+ console.log(err);
63
+
64
+ throw new RequestError(err.message);
65
+
66
+ }
67
+
68
+ } else {
69
+
70
+ throw new RequestError('API not initialized!');
71
+
72
+ }
73
+
74
+ }
75
+
76
+ }
77
+
78
+ (() => {
79
+ return new UiServer;
80
+ })();
Binary file
package/index.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * v6
3
+ *
4
+ * @url https://github.com/homebridge-plugins/homebridge-tado
5
+ * @author SeydX <seyd55@outlook.de>
6
+ *
7
+ **/
8
+
9
+ 'use strict';
10
+
11
+ module.exports = function (homebridge) {
12
+ let TadoPlatform = require('./src/platform.js')(homebridge);
13
+ homebridge.registerPlatform('@homebridge-plugins/homebridge-tado', 'TadoPlatform', TadoPlatform, true);
14
+ };
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@homebridge-plugins/homebridge-tado",
3
+ "version": "6.0.14",
4
+ "description": "Homebridge plugin for controlling Tado devices",
5
+ "main": "index.js",
6
+ "funding": [
7
+ {
8
+ "type": "paypal",
9
+ "url": "https://paypal.me/seydx"
10
+ },
11
+ {
12
+ "type": "kofi",
13
+ "url": "https://ko-fi.com/seydx"
14
+ },
15
+ {
16
+ "type": "github",
17
+ "url": "https://github.com/sponsors/seydx"
18
+ }
19
+ ],
20
+ "scripts": {
21
+ "lint": "eslint --fix ."
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/homebridge-plugins/homebridge-tado.git"
26
+ },
27
+ "author": "SeydX (https://github.com/homebridge-plugins/homebridge-tado)",
28
+ "license": "MIT",
29
+ "bugs": {
30
+ "url": "https://github.com/homebridge-plugins/homebridge-tado/issues"
31
+ },
32
+ "homepage": "https://github.com/homebridge-plugins/homebridge-tado#readme",
33
+ "keywords": [
34
+ "tado",
35
+ "thermostat",
36
+ "homebridge",
37
+ "homebridge-plugin",
38
+ "plugin",
39
+ "boiler",
40
+ "presence",
41
+ "heat"
42
+ ],
43
+ "engines": {
44
+ "node": ">=12.18.3",
45
+ "homebridge": "^1.1.6"
46
+ },
47
+ "dependencies": {
48
+ "@homebridge/plugin-ui-utils": "^0.0.19",
49
+ "fakegato-history": "^0.6.1",
50
+ "form-data": "^4.0.0",
51
+ "fs-extra": "^10.0.0",
52
+ "got": "^11.8.2",
53
+ "moment": "^2.29.1",
54
+ "simple-oauth2": "^4.2.0"
55
+ },
56
+ "devDependencies": {
57
+ "@babel/core": "7.14.3",
58
+ "@babel/eslint-parser": "7.14.4",
59
+ "@babel/eslint-plugin": "7.13.16",
60
+ "eslint": "^7.27.0",
61
+ "eslint-config-prettier": "^8.3.0",
62
+ "eslint-plugin-import": "^2.23.4",
63
+ "eslint-plugin-prettier": "^3.4.0",
64
+ "prettier": "^2.3.0"
65
+ }
66
+ }
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ const Logger = require('../helper/logger.js');
4
+
5
+ class AirQualityAccessory {
6
+ constructor(api, accessory, accessories, tado) {
7
+ this.api = api;
8
+ this.accessory = accessory;
9
+ this.accessories = accessories;
10
+
11
+ this.tado = tado;
12
+
13
+ this.getService();
14
+ }
15
+
16
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
17
+ // Services
18
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
19
+
20
+ getService() {
21
+ let service = this.accessory.getService(this.api.hap.Service.AirQualitySensor);
22
+
23
+ if (!service) {
24
+ Logger.info('Adding AirQualitySensor service', this.accessory.displayName);
25
+ service = this.accessory.addService(
26
+ this.api.hap.Service.AirQualitySensor,
27
+ this.accessory.displayName,
28
+ this.accessory.context.config.subtype
29
+ );
30
+ }
31
+
32
+ if (!service.testCharacteristic(this.api.hap.Characteristic.PM10Density))
33
+ service.addCharacteristic(this.api.hap.Characteristic.PM10Density);
34
+
35
+ if (!service.testCharacteristic(this.api.hap.Characteristic.PM2_5Density))
36
+ service.addCharacteristic(this.api.hap.Characteristic.PM2_5Density);
37
+
38
+ if (!service.testCharacteristic(this.api.hap.Characteristic.NitrogenDioxideDensity))
39
+ service.addCharacteristic(this.api.hap.Characteristic.NitrogenDioxideDensity);
40
+
41
+ if (!service.testCharacteristic(this.api.hap.Characteristic.OzoneDensity))
42
+ service.addCharacteristic(this.api.hap.Characteristic.OzoneDensity);
43
+
44
+ if (!service.testCharacteristic(this.api.hap.Characteristic.SulphurDioxideDensity))
45
+ service.addCharacteristic(this.api.hap.Characteristic.SulphurDioxideDensity);
46
+
47
+ if (!service.testCharacteristic(this.api.hap.Characteristic.CarbonMonoxideLevel))
48
+ service.addCharacteristic(this.api.hap.Characteristic.CarbonMonoxideLevel);
49
+
50
+ service.getCharacteristic(this.api.hap.Characteristic.CarbonMonoxideLevel).setProps({
51
+ minStep: 0.01,
52
+ });
53
+ }
54
+ }
55
+
56
+ module.exports = AirQualityAccessory;
@@ -0,0 +1,124 @@
1
+ 'use strict';
2
+
3
+ const Logger = require('../helper/logger.js');
4
+
5
+ const moment = require('moment');
6
+
7
+ const timeout = (ms) => new Promise((res) => setTimeout(res, ms));
8
+
9
+ class ContactAccessory {
10
+ constructor(api, accessory, accessories, tado, deviceHandler, FakeGatoHistoryService) {
11
+ this.api = api;
12
+ this.accessory = accessory;
13
+ this.accessories = accessories;
14
+ this.FakeGatoHistoryService = FakeGatoHistoryService;
15
+
16
+ this.deviceHandler = deviceHandler;
17
+ this.tado = tado;
18
+
19
+ this.getService();
20
+ }
21
+
22
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
23
+ // Services
24
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
25
+
26
+ async getService() {
27
+ let service = this.accessory.getService(this.api.hap.Service.ContactSensor);
28
+ let serviceSwitch = this.accessory.getService(this.api.hap.Service.Switch);
29
+
30
+ if (serviceSwitch) {
31
+ Logger.info('Removing Switch service', this.accessory.displayName);
32
+ this.accessory.removeService(serviceSwitch);
33
+ }
34
+
35
+ if (!service) {
36
+ Logger.info('Adding ContactSensor service', this.accessory.displayName);
37
+ service = this.accessory.addService(
38
+ this.api.hap.Service.ContactSensor,
39
+ this.accessory.displayName,
40
+ this.accessory.context.config.subtype
41
+ );
42
+ }
43
+
44
+ let batteryService = this.accessory.getService(this.api.hap.Service.BatteryService);
45
+
46
+ if (!this.accessory.context.config.noBattery && this.accessory.context.config.type === 'HEATING') {
47
+ if (!batteryService) {
48
+ Logger.info('Adding Battery service', this.accessory.displayName);
49
+ batteryService = this.accessory.addService(this.api.hap.Service.BatteryService);
50
+ }
51
+ batteryService.setCharacteristic(
52
+ this.api.hap.Characteristic.ChargingState,
53
+ this.api.hap.Characteristic.ChargingState.NOT_CHARGEABLE
54
+ );
55
+ } else {
56
+ if (batteryService) {
57
+ Logger.info('Removing Battery service', this.accessory.displayName);
58
+ this.accessory.removeService(batteryService);
59
+ }
60
+ }
61
+
62
+ if (!service.testCharacteristic(this.api.hap.Characteristic.LastActivation))
63
+ service.addCharacteristic(this.api.hap.Characteristic.LastActivation);
64
+
65
+ if (!service.testCharacteristic(this.api.hap.Characteristic.TimesOpened))
66
+ service.addCharacteristic(this.api.hap.Characteristic.TimesOpened);
67
+
68
+ if (!service.testCharacteristic(this.api.hap.Characteristic.ResetTotal))
69
+ service.addCharacteristic(this.api.hap.Characteristic.ResetTotal);
70
+
71
+ if (!service.testCharacteristic(this.api.hap.Characteristic.OpenDuration))
72
+ service.addCharacteristic(this.api.hap.Characteristic.OpenDuration);
73
+
74
+ if (!service.testCharacteristic(this.api.hap.Characteristic.ClosedDuration))
75
+ service.addCharacteristic(this.api.hap.Characteristic.ClosedDuration);
76
+
77
+ service.getCharacteristic(this.api.hap.Characteristic.ResetTotal).onSet((value) => {
78
+ Logger.info(value + ': Resetting FakeGato..', this.accessory.displayName);
79
+
80
+ const now = Math.round(new Date().valueOf() / 1000);
81
+ const epoch = Math.round(new Date('2001-01-01T00:00:00Z').valueOf() / 1000);
82
+
83
+ service.getCharacteristic(this.api.hap.Characteristic.ResetTotal).updateValue(now - epoch);
84
+
85
+ this.accessory.context.timesOpened = 0;
86
+
87
+ service
88
+ .getCharacteristic(this.api.hap.Characteristic.TimesOpened)
89
+ .updateValue(this.accessory.context.timesOpened);
90
+ });
91
+
92
+ this.historyService = new this.FakeGatoHistoryService('door', this.accessory, {
93
+ storage: 'fs',
94
+ path: this.api.user.storagePath(),
95
+ disableTimer: true,
96
+ });
97
+
98
+ await timeout(250); //wait for historyService to load
99
+
100
+ service
101
+ .getCharacteristic(this.api.hap.Characteristic.ContactSensorState)
102
+ .on(
103
+ 'change',
104
+ this.deviceHandler.changedStates.bind(this, this.accessory, this.historyService, this.accessory.displayName)
105
+ );
106
+
107
+ this.refreshHistory(service);
108
+ }
109
+
110
+ refreshHistory(service) {
111
+ let state = service.getCharacteristic(this.api.hap.Characteristic.ContactSensorState).value;
112
+
113
+ this.historyService.addEntry({
114
+ time: moment().unix(),
115
+ status: state ? 1 : 0,
116
+ });
117
+
118
+ setTimeout(() => {
119
+ this.refreshHistory(service);
120
+ }, 10 * 60 * 1000);
121
+ }
122
+ }
123
+
124
+ module.exports = ContactAccessory;
@@ -0,0 +1,63 @@
1
+ 'use strict';
2
+
3
+ const Logger = require('../helper/logger.js');
4
+
5
+ class FaucetAccessory {
6
+ constructor(api, accessory, accessories, tado, deviceHandler) {
7
+ this.api = api;
8
+ this.accessory = accessory;
9
+ this.accessories = accessories;
10
+
11
+ this.deviceHandler = deviceHandler;
12
+ this.tado = tado;
13
+
14
+ this.getService();
15
+ }
16
+
17
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
18
+ // Services
19
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
20
+
21
+ getService() {
22
+ let service = this.accessory.getService(this.api.hap.Service.Valve);
23
+ let serviceSwitch = this.accessory.getService(this.api.hap.Service.Switch);
24
+ let serviceHeaterCooler = this.accessory.getService(this.api.hap.Service.HeaterCooler);
25
+ let serviceThermostat = this.accessory.getService(this.api.hap.Service.Thermostat);
26
+
27
+ if (serviceSwitch) {
28
+ Logger.info('Removing Switch service', this.accessory.displayName);
29
+ this.accessory.removeService(serviceSwitch);
30
+ }
31
+
32
+ if (serviceThermostat) {
33
+ Logger.info('Removing Thermostat service', this.accessory.displayName);
34
+ this.accessory.removeService(serviceThermostat);
35
+ }
36
+
37
+ if (serviceHeaterCooler) {
38
+ Logger.info('Removing HeaterCooler service', this.accessory.displayName);
39
+ this.accessory.removeService(serviceHeaterCooler);
40
+ }
41
+
42
+ if (!service) {
43
+ Logger.info('Adding Faucet service', this.accessory.displayName);
44
+ service = this.accessory.addService(
45
+ this.api.hap.Service.Valve,
46
+ this.accessory.displayName,
47
+ this.accessory.context.config.subtype
48
+ );
49
+ }
50
+
51
+ service
52
+ .setCharacteristic(this.api.hap.Characteristic.Name, this.accessory.displayName)
53
+ .setCharacteristic(this.api.hap.Characteristic.IsConfigured, this.api.hap.Characteristic.IsConfigured.CONFIGURED)
54
+ .setCharacteristic(this.api.hap.Characteristic.StatusFault, this.api.hap.Characteristic.StatusFault.NO_FAULT)
55
+ .setCharacteristic(this.api.hap.Characteristic.ValveType, this.api.hap.Characteristic.ValveType.WATER_FAUCET);
56
+
57
+ service
58
+ .getCharacteristic(this.api.hap.Characteristic.Active)
59
+ .onSet(this.deviceHandler.setStates.bind(this, this.accessory, this.accessories, 'State'));
60
+ }
61
+ }
62
+
63
+ module.exports = FaucetAccessory;