homebridge-tydom 0.21.9
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/CHANGELOG.md +9 -0
- package/README.md +287 -0
- package/config.schema.json +38 -0
- package/lib/accessories/contactSensor.d.ts +4 -0
- package/lib/accessories/contactSensor.js +49 -0
- package/lib/accessories/fan.d.ts +4 -0
- package/lib/accessories/fan.js +17 -0
- package/lib/accessories/garageDoorOpener.d.ts +3 -0
- package/lib/accessories/garageDoorOpener.js +49 -0
- package/lib/accessories/lightbulb.d.ts +4 -0
- package/lib/accessories/lightbulb.js +147 -0
- package/lib/accessories/securitySystem.d.ts +5 -0
- package/lib/accessories/securitySystem.js +422 -0
- package/lib/accessories/securitySystemSensors.d.ts +5 -0
- package/lib/accessories/securitySystemSensors.js +160 -0
- package/lib/accessories/services/switchableService.d.ts +5 -0
- package/lib/accessories/services/switchableService.js +66 -0
- package/lib/accessories/switch.d.ts +4 -0
- package/lib/accessories/switch.js +17 -0
- package/lib/accessories/temperatureSensor.d.ts +4 -0
- package/lib/accessories/temperatureSensor.js +52 -0
- package/lib/accessories/thermostat.d.ts +4 -0
- package/lib/accessories/thermostat.js +340 -0
- package/lib/accessories/windowCovering.d.ts +5 -0
- package/lib/accessories/windowCovering.js +167 -0
- package/lib/config/env.d.ts +3 -0
- package/lib/config/env.js +7 -0
- package/lib/config/i18n/en.d.ts +1021 -0
- package/lib/config/i18n/en.js +1022 -0
- package/lib/config/i18n/fr.d.ts +1035 -0
- package/lib/config/i18n/fr.js +1036 -0
- package/lib/config/locale.d.ts +4110 -0
- package/lib/config/locale.js +12 -0
- package/lib/controller.d.ts +40 -0
- package/lib/controller.js +199 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +13 -0
- package/lib/platform.d.ts +37 -0
- package/lib/platform.js +114 -0
- package/lib/typings/tydom.d.ts +186 -0
- package/lib/typings/tydom.js +2 -0
- package/lib/utils/accessory.d.ts +19 -0
- package/lib/utils/accessory.js +139 -0
- package/lib/utils/array.d.ts +2 -0
- package/lib/utils/array.js +8 -0
- package/lib/utils/assert.d.ts +2 -0
- package/lib/utils/assert.js +9 -0
- package/lib/utils/chalk.d.ts +7 -0
- package/lib/utils/chalk.js +21 -0
- package/lib/utils/debug.d.ts +14 -0
- package/lib/utils/debug.js +44 -0
- package/lib/utils/hap.d.ts +6 -0
- package/lib/utils/hap.js +8 -0
- package/lib/utils/hash.d.ts +4 -0
- package/lib/utils/hash.js +28 -0
- package/lib/utils/request.d.ts +10 -0
- package/lib/utils/request.js +43 -0
- package/lib/utils/tydom.d.ts +27 -0
- package/lib/utils/tydom.js +126 -0
- package/lib/utils/webhook.d.ts +19 -0
- package/lib/utils/webhook.js +31 -0
- package/package.json +62 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateSwitch = exports.setupSwitch = void 0;
|
|
4
|
+
const hap_1 = require("../utils/hap");
|
|
5
|
+
const accessory_1 = require("../utils/accessory");
|
|
6
|
+
const switchableService_1 = require("./services/switchableService");
|
|
7
|
+
const setupSwitch = (accessory, controller) => {
|
|
8
|
+
accessory_1.setupAccessoryInformationService(accessory, controller);
|
|
9
|
+
accessory_1.setupAccessoryIdentifyHandler(accessory, controller);
|
|
10
|
+
// Add the actual accessory Service
|
|
11
|
+
switchableService_1.addAccessorySwitchableService(accessory, controller, hap_1.Service.Switch);
|
|
12
|
+
};
|
|
13
|
+
exports.setupSwitch = setupSwitch;
|
|
14
|
+
const updateSwitch = (accessory, controller, updates) => {
|
|
15
|
+
switchableService_1.updateAccessorySwitchableService(accessory, controller, updates, hap_1.Service.Switch);
|
|
16
|
+
};
|
|
17
|
+
exports.updateSwitch = updateSwitch;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PlatformAccessory } from 'homebridge';
|
|
2
|
+
import TydomController from '../controller';
|
|
3
|
+
export declare const setupTemperatureSensor: (accessory: PlatformAccessory, controller: TydomController) => void;
|
|
4
|
+
export declare const updateTemperatureSensor: (accessory: PlatformAccessory, _controller: TydomController, updates: Record<string, unknown>[]) => void;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateTemperatureSensor = exports.setupTemperatureSensor = void 0;
|
|
4
|
+
const accessory_1 = require("../utils/accessory");
|
|
5
|
+
const debug_1 = require("../utils/debug");
|
|
6
|
+
const hap_1 = require("../utils/hap");
|
|
7
|
+
const tydom_1 = require("../utils/tydom");
|
|
8
|
+
const setupTemperatureSensor = (accessory, controller) => {
|
|
9
|
+
const { context } = accessory;
|
|
10
|
+
const { client } = controller;
|
|
11
|
+
const { CurrentTemperature } = hap_1.Characteristic;
|
|
12
|
+
const { deviceId, endpointId } = context;
|
|
13
|
+
accessory_1.setupAccessoryInformationService(accessory, controller);
|
|
14
|
+
accessory_1.setupAccessoryIdentifyHandler(accessory, controller);
|
|
15
|
+
// Add the actual accessory Service
|
|
16
|
+
const service = accessory_1.addAccessoryService(accessory, hap_1.Service.TemperatureSensor, `${accessory.displayName}`, true);
|
|
17
|
+
service
|
|
18
|
+
.getCharacteristic(CurrentTemperature)
|
|
19
|
+
.setProps({
|
|
20
|
+
minValue: -100
|
|
21
|
+
})
|
|
22
|
+
.on("get" /* GET */, async (callback) => {
|
|
23
|
+
debug_1.debugGet(CurrentTemperature, service);
|
|
24
|
+
try {
|
|
25
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
26
|
+
const outTemperature = tydom_1.getTydomDataPropValue(data, 'outTemperature');
|
|
27
|
+
debug_1.debugGetResult(CurrentTemperature, service, outTemperature);
|
|
28
|
+
callback(null, outTemperature);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
callback(err);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
exports.setupTemperatureSensor = setupTemperatureSensor;
|
|
36
|
+
const updateTemperatureSensor = (accessory, _controller, updates) => {
|
|
37
|
+
updates.forEach((update) => {
|
|
38
|
+
const { name, value } = update;
|
|
39
|
+
const { CurrentTemperature } = hap_1.Characteristic;
|
|
40
|
+
switch (name) {
|
|
41
|
+
case 'outTemperature': {
|
|
42
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.TemperatureSensor);
|
|
43
|
+
debug_1.debugSetUpdate(CurrentTemperature, service, value);
|
|
44
|
+
service.updateCharacteristic(CurrentTemperature, value);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
exports.updateTemperatureSensor = updateTemperatureSensor;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PlatformAccessory } from 'homebridge';
|
|
2
|
+
import TydomController from '../controller';
|
|
3
|
+
export declare const setupThermostat: (accessory: PlatformAccessory, controller: TydomController) => void;
|
|
4
|
+
export declare const updateThermostat: (accessory: PlatformAccessory, _controller: TydomController, updates: Record<string, unknown>[]) => void;
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.updateThermostat = exports.setupThermostat = void 0;
|
|
26
|
+
const lodash_1 = require("lodash");
|
|
27
|
+
const locale_1 = __importDefault(require("../config/locale"));
|
|
28
|
+
const accessory_1 = require("../utils/accessory");
|
|
29
|
+
const chalk_1 = require("../utils/chalk");
|
|
30
|
+
const debug_1 = __importStar(require("../utils/debug"));
|
|
31
|
+
const hap_1 = require("../utils/hap");
|
|
32
|
+
const tydom_1 = require("../utils/tydom");
|
|
33
|
+
const setupThermostat = (accessory, controller) => {
|
|
34
|
+
const { context } = accessory;
|
|
35
|
+
const { client } = controller;
|
|
36
|
+
const { TargetHeatingCoolingState, CurrentHeatingCoolingState, TargetTemperature, CurrentTemperature, On } = hap_1.Characteristic;
|
|
37
|
+
const { deviceId, endpointId, metadata } = context;
|
|
38
|
+
accessory_1.setupAccessoryInformationService(accessory, controller);
|
|
39
|
+
accessory_1.setupAccessoryIdentifyHandler(accessory, controller);
|
|
40
|
+
// Add the actual accessory Service
|
|
41
|
+
const service = accessory_1.addAccessoryService(accessory, hap_1.Service.Thermostat, `${accessory.displayName}`, true);
|
|
42
|
+
service
|
|
43
|
+
.getCharacteristic(CurrentHeatingCoolingState)
|
|
44
|
+
.setProps({ validValues: [0, 1] }) // [OFF, HEAT, COOL]
|
|
45
|
+
.on("get" /* GET */, async (callback) => {
|
|
46
|
+
debug_1.debugGet(CurrentHeatingCoolingState, service);
|
|
47
|
+
try {
|
|
48
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
49
|
+
const authorization = tydom_1.getTydomDataPropValue(data, 'authorization');
|
|
50
|
+
const setpoint = tydom_1.getTydomDataPropValue(data, 'setpoint');
|
|
51
|
+
const temperature = tydom_1.getTydomDataPropValue(data, 'temperature');
|
|
52
|
+
const nextValue = authorization === 'HEATING' && setpoint > temperature
|
|
53
|
+
? CurrentHeatingCoolingState.HEAT
|
|
54
|
+
: CurrentHeatingCoolingState.OFF;
|
|
55
|
+
debug_1.debugGetResult(CurrentHeatingCoolingState, service, nextValue);
|
|
56
|
+
callback(null, nextValue);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
callback(err);
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
.getValue();
|
|
63
|
+
service
|
|
64
|
+
.getCharacteristic(TargetHeatingCoolingState)
|
|
65
|
+
.setProps({ validValues: [0, 1] }) // [OFF, HEAT, COOL, AUTO]
|
|
66
|
+
.on("get" /* GET */, async (callback) => {
|
|
67
|
+
debug_1.debugGet(TargetHeatingCoolingState, service);
|
|
68
|
+
try {
|
|
69
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
70
|
+
const hvacMode = tydom_1.getTydomDataPropValue(data, 'hvacMode');
|
|
71
|
+
const authorization = tydom_1.getTydomDataPropValue(data, 'authorization');
|
|
72
|
+
const nextValue = authorization === 'HEATING' && ['NORMAL'].includes(hvacMode)
|
|
73
|
+
? TargetHeatingCoolingState.HEAT
|
|
74
|
+
: TargetHeatingCoolingState.OFF;
|
|
75
|
+
debug_1.debugGetResult(TargetHeatingCoolingState, service, nextValue);
|
|
76
|
+
callback(null, nextValue);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
callback(err);
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
.on("set" /* SET */, async (value, callback) => {
|
|
83
|
+
debug_1.debugSet(TargetHeatingCoolingState, service, value);
|
|
84
|
+
try {
|
|
85
|
+
const shouldHeat = [TargetHeatingCoolingState.HEAT, TargetHeatingCoolingState.AUTO].includes(value);
|
|
86
|
+
const tydomValue = shouldHeat ? 'NORMAL' : 'STOP';
|
|
87
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/data`, [
|
|
88
|
+
{
|
|
89
|
+
name: 'hvacMode',
|
|
90
|
+
value: tydomValue
|
|
91
|
+
}
|
|
92
|
+
]);
|
|
93
|
+
debug_1.debugSetResult(TargetHeatingCoolingState, service, value, tydomValue);
|
|
94
|
+
// @NOTE directly update currentHeadingCoolingState
|
|
95
|
+
service
|
|
96
|
+
.getCharacteristic(CurrentHeatingCoolingState)
|
|
97
|
+
.updateValue(shouldHeat ? CurrentHeatingCoolingState.HEAT : CurrentHeatingCoolingState.OFF);
|
|
98
|
+
callback();
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
callback(err);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
service
|
|
105
|
+
.getCharacteristic(CurrentTemperature)
|
|
106
|
+
.on("get" /* GET */, async (callback) => {
|
|
107
|
+
debug_1.debugGet(CurrentTemperature, service);
|
|
108
|
+
try {
|
|
109
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
110
|
+
const temperature = tydom_1.getTydomDataPropValue(data, 'temperature');
|
|
111
|
+
debug_1.debugGetResult(CurrentTemperature, service, temperature);
|
|
112
|
+
callback(null, temperature);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
callback(err);
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
.getValue();
|
|
119
|
+
service
|
|
120
|
+
.getCharacteristic(TargetTemperature)
|
|
121
|
+
.on("get" /* GET */, async (callback) => {
|
|
122
|
+
debug_1.debugGet(TargetTemperature, service);
|
|
123
|
+
try {
|
|
124
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
125
|
+
const setpoint = tydom_1.getTydomDataPropValue(data, 'setpoint');
|
|
126
|
+
debug_1.debugGetResult(TargetTemperature, service, setpoint);
|
|
127
|
+
callback(null, setpoint);
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
callback(err);
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
.on("set" /* SET */, async (value, callback) => {
|
|
134
|
+
try {
|
|
135
|
+
debug_1.debugSet(TargetTemperature, service, value);
|
|
136
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/data`, [
|
|
137
|
+
{
|
|
138
|
+
name: 'setpoint',
|
|
139
|
+
value: value
|
|
140
|
+
}
|
|
141
|
+
]);
|
|
142
|
+
debug_1.debugSetResult(TargetTemperature, service, value);
|
|
143
|
+
callback();
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
callback(err);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
const thermicLevelData = metadata.find(({ name }) => name === 'thermicLevel');
|
|
150
|
+
if (!thermicLevelData) {
|
|
151
|
+
controller.log.error(`Failed to properly create the thermostat accesory for device ${deviceId}, did not found object in array that matches {"name": "thermicLevel"} in ${JSON.stringify(metadata)}`);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const thermicLevelValues = thermicLevelData.enum_values;
|
|
155
|
+
// Only absence (aka. anti-frost) mode
|
|
156
|
+
if (thermicLevelValues.length === 1) {
|
|
157
|
+
const absenceModeId = `hvacMode_absence`;
|
|
158
|
+
const absenceModeName = lodash_1.get(locale_1.default, 'HVAC_INFO_ABSENCE', 'N/A');
|
|
159
|
+
const absenceModeService = accessory_1.addAccessoryServiceWithSubtype(accessory, hap_1.Service.Switch, absenceModeName, absenceModeId, true);
|
|
160
|
+
debug_1.debugAddSubService(absenceModeService, accessory);
|
|
161
|
+
service.addLinkedService(absenceModeService);
|
|
162
|
+
absenceModeService
|
|
163
|
+
.getCharacteristic(On)
|
|
164
|
+
.on("get" /* GET */, async (callback) => {
|
|
165
|
+
debug_1.debugGet(On, absenceModeService);
|
|
166
|
+
try {
|
|
167
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
168
|
+
const hvacMode = tydom_1.getTydomDataPropValue(data, 'hvacMode');
|
|
169
|
+
// const antifrostOn = getTydomDataPropValue<boolean>(data, 'antifrostOn');
|
|
170
|
+
// const nextValue = hvacMode === 'ANTI_FROST' && antifrostOn;
|
|
171
|
+
const nextValue = hvacMode === 'ANTI_FROST';
|
|
172
|
+
debug_1.debugGetResult(On, absenceModeService, nextValue);
|
|
173
|
+
callback(null, nextValue);
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
callback(err);
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
.on("set" /* SET */, async (value, callback) => {
|
|
180
|
+
debug_1.debugSet(On, absenceModeService, value);
|
|
181
|
+
try {
|
|
182
|
+
const tydomValue = value ? 'ANTI_FROST' : 'NORMAL';
|
|
183
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/data`, [
|
|
184
|
+
{
|
|
185
|
+
name: 'hvacMode',
|
|
186
|
+
value: tydomValue
|
|
187
|
+
}
|
|
188
|
+
]);
|
|
189
|
+
debug_1.debugSetResult(On, absenceModeService, value, tydomValue);
|
|
190
|
+
callback();
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
callback(err);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// Multiple thermic levels
|
|
198
|
+
// "enum_values": ["ECO", "MODERATO", "MEDIO", "COMFORT", "STOP", "ANTI_FROST"]
|
|
199
|
+
if (thermicLevelValues.length > 1) {
|
|
200
|
+
const THERMIC_LEVELS_WHITELIST = ['ANTI_FROST', 'ECO', 'COMFORT'];
|
|
201
|
+
const thermicLevelServices = thermicLevelValues
|
|
202
|
+
.filter((value) => THERMIC_LEVELS_WHITELIST.includes(value))
|
|
203
|
+
.map((thermicLevelValue) => {
|
|
204
|
+
const thermicLevelId = `thermicLevel_${thermicLevelValue.toLowerCase()}`;
|
|
205
|
+
const thermicLevelName = lodash_1.get(locale_1.default, `HVAC_LEVEL_${thermicLevelValue}`, 'N/A');
|
|
206
|
+
const thermicLevelService = accessory_1.addAccessoryServiceWithSubtype(accessory, hap_1.Service.Switch, thermicLevelName, thermicLevelId, true);
|
|
207
|
+
debug_1.debugAddSubService(thermicLevelService, accessory);
|
|
208
|
+
service.addLinkedService(thermicLevelService);
|
|
209
|
+
thermicLevelService
|
|
210
|
+
.getCharacteristic(On)
|
|
211
|
+
.on("get" /* GET */, async (callback) => {
|
|
212
|
+
debug_1.debugGet(On, thermicLevelService);
|
|
213
|
+
try {
|
|
214
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
215
|
+
const thermicLevel = tydom_1.getTydomDataPropValue(data, 'thermicLevel');
|
|
216
|
+
const nextValue = thermicLevel === thermicLevelValue;
|
|
217
|
+
debug_1.debugGetResult(On, thermicLevelService, nextValue);
|
|
218
|
+
callback(null, nextValue);
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
callback(err);
|
|
222
|
+
}
|
|
223
|
+
})
|
|
224
|
+
.on("set" /* SET */, async (value, callback) => {
|
|
225
|
+
debug_1.debugSet(On, thermicLevelService, value);
|
|
226
|
+
try {
|
|
227
|
+
const tydomValue = value ? thermicLevelValue : 'NORMAL';
|
|
228
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/data`, [
|
|
229
|
+
{
|
|
230
|
+
name: 'hvacMode',
|
|
231
|
+
value: tydomValue
|
|
232
|
+
}
|
|
233
|
+
]);
|
|
234
|
+
debug_1.debugSetResult(On, thermicLevelService, tydomValue);
|
|
235
|
+
callback();
|
|
236
|
+
// @NOTE disable any other existing thermicLevel
|
|
237
|
+
thermicLevelServices
|
|
238
|
+
.filter(({ value }) => value !== thermicLevelValue)
|
|
239
|
+
.forEach(({ service }) => {
|
|
240
|
+
service.updateCharacteristic(On, false);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
callback(err);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
return { value: thermicLevelValue, service: thermicLevelService };
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
exports.setupThermostat = setupThermostat;
|
|
252
|
+
const updateThermostat = (accessory, _controller, updates) => {
|
|
253
|
+
const { TargetHeatingCoolingState, CurrentHeatingCoolingState, TargetTemperature, CurrentTemperature, On } = hap_1.Characteristic;
|
|
254
|
+
updates.forEach((update) => {
|
|
255
|
+
const { name, value } = update;
|
|
256
|
+
switch (name) {
|
|
257
|
+
case 'authorization': {
|
|
258
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.Thermostat);
|
|
259
|
+
const authorization = value;
|
|
260
|
+
if (authorization === 'HEATING') {
|
|
261
|
+
// @TODO Trigger a get as we miss info
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (authorization === 'STOP') {
|
|
265
|
+
debug_1.debugSetUpdate(CurrentHeatingCoolingState, service, CurrentHeatingCoolingState.OFF);
|
|
266
|
+
service.updateCharacteristic(CurrentHeatingCoolingState, CurrentHeatingCoolingState.OFF);
|
|
267
|
+
// External update probably comes from the Tydom app, let's agree on the target state
|
|
268
|
+
debug_1.debugSetUpdate(TargetHeatingCoolingState, service, TargetHeatingCoolingState.OFF);
|
|
269
|
+
service.updateCharacteristic(TargetHeatingCoolingState, TargetHeatingCoolingState.OFF);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
case 'hvacMode': {
|
|
275
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.Thermostat);
|
|
276
|
+
const hvacMode = value;
|
|
277
|
+
if (hvacMode === 'NORMAL') {
|
|
278
|
+
// @TODO Trigger a get as we miss info
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
service.updateCharacteristic(TargetHeatingCoolingState, CurrentHeatingCoolingState.OFF);
|
|
282
|
+
if (hvacMode === 'ANTI_FROST') {
|
|
283
|
+
const subtype = 'hvacMode_absence';
|
|
284
|
+
const service = accessory.getServiceByUUIDAndSubType(hap_1.Service.Switch, subtype);
|
|
285
|
+
if (service) {
|
|
286
|
+
debug_1.debugSetUpdate(On, service, true);
|
|
287
|
+
service.updateCharacteristic(On, true);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
case 'thermicLevel': {
|
|
294
|
+
const thermicLevel = value;
|
|
295
|
+
if (thermicLevel === null) {
|
|
296
|
+
debug_1.default(`Encountered a ${chalk_1.chalkString('thermicLevel')} update with a null value!`);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const service = accessory.getServiceByUUIDAndSubType(hap_1.Service.Switch, `thermicLevel_${thermicLevel.toLowerCase()}`);
|
|
300
|
+
if (service) {
|
|
301
|
+
debug_1.debugSetUpdate(On, service, true);
|
|
302
|
+
service.updateCharacteristic(On, true);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
// case 'antifrostOn': {
|
|
308
|
+
// const subtype = 'antifrostOn';
|
|
309
|
+
// const service = accessory.getServiceByUUIDAndSubType(Service.Switch, subtype);
|
|
310
|
+
// assert(service, `Unexpected missing service "Service.Switch" with subtype="${subtype}" in accessory`);
|
|
311
|
+
// const antifrostOn = value as boolean;
|
|
312
|
+
// service.updateCharacteristic(Characteristic, antifrostOn);
|
|
313
|
+
// return;
|
|
314
|
+
// }
|
|
315
|
+
case 'setpoint': {
|
|
316
|
+
const setpoint = value;
|
|
317
|
+
if (setpoint === null) {
|
|
318
|
+
debug_1.default(`Encountered a ${chalk_1.chalkString('setpoint')} update with a null value!`);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.Thermostat);
|
|
322
|
+
debug_1.debugSetUpdate(TargetTemperature, service, setpoint);
|
|
323
|
+
service.updateCharacteristic(TargetTemperature, setpoint);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
case 'temperature': {
|
|
327
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.Thermostat);
|
|
328
|
+
debug_1.debugSetUpdate(CurrentTemperature, service, value);
|
|
329
|
+
service.updateCharacteristic(CurrentTemperature, value);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
default:
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
exports.updateThermostat = updateThermostat;
|
|
338
|
+
// OFF -> authorization === STOP
|
|
339
|
+
// ANTI_FROST -> hvacMode === ANTI_FROST
|
|
340
|
+
// CHAUFFAGE -> authorization === HEATING
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PlatformAccessory } from 'homebridge';
|
|
2
|
+
import TydomController from '../controller';
|
|
3
|
+
import { TydomAccessoryUpdateType } from '../utils/accessory';
|
|
4
|
+
export declare const setupWindowCovering: (accessory: PlatformAccessory, controller: TydomController) => void;
|
|
5
|
+
export declare const updateWindowCovering: (accessory: PlatformAccessory, _controller: TydomController, updates: Record<string, unknown>[], type: TydomAccessoryUpdateType) => void;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateWindowCovering = exports.setupWindowCovering = void 0;
|
|
4
|
+
const lodash_1 = require("lodash");
|
|
5
|
+
const accessory_1 = require("../utils/accessory");
|
|
6
|
+
const chalk_1 = require("../utils/chalk");
|
|
7
|
+
const debug_1 = require("../utils/debug");
|
|
8
|
+
const hap_1 = require("../utils/hap");
|
|
9
|
+
const tydom_1 = require("../utils/tydom");
|
|
10
|
+
const setupWindowCovering = (accessory, controller) => {
|
|
11
|
+
const { context } = accessory;
|
|
12
|
+
const { client } = controller;
|
|
13
|
+
const { CurrentPosition, TargetPosition, PositionState, HoldPosition } = hap_1.Characteristic;
|
|
14
|
+
const { deviceId, endpointId, state } = context;
|
|
15
|
+
accessory_1.setupAccessoryInformationService(accessory, controller);
|
|
16
|
+
accessory_1.setupAccessoryIdentifyHandler(accessory, controller);
|
|
17
|
+
Object.assign(state, {
|
|
18
|
+
latestPosition: 100,
|
|
19
|
+
pendingUpdatedValues: [],
|
|
20
|
+
lastUpdatedAt: 0
|
|
21
|
+
});
|
|
22
|
+
// Add the actual accessory Service
|
|
23
|
+
const service = accessory_1.addAccessoryService(accessory, hap_1.Service.WindowCovering, `${accessory.displayName}`, true);
|
|
24
|
+
const debouncedSetPosition = lodash_1.debounce(async (value) => {
|
|
25
|
+
debug_1.debugTydomPut('position', accessory, value);
|
|
26
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/data`, [
|
|
27
|
+
{
|
|
28
|
+
name: 'position',
|
|
29
|
+
value
|
|
30
|
+
}
|
|
31
|
+
]);
|
|
32
|
+
Object.assign(state, {
|
|
33
|
+
pendingUpdatedValues: state.pendingUpdatedValues.concat([value])
|
|
34
|
+
});
|
|
35
|
+
}, 250, { leading: true, trailing: false });
|
|
36
|
+
service
|
|
37
|
+
.getCharacteristic(PositionState)
|
|
38
|
+
.on("get" /* GET */, async (callback) => {
|
|
39
|
+
debug_1.debugGet(PositionState, service);
|
|
40
|
+
try {
|
|
41
|
+
// @NOTE Tydom does not track the current position
|
|
42
|
+
const nextValue = PositionState.STOPPED;
|
|
43
|
+
debug_1.debugGetResult(CurrentPosition, service, nextValue);
|
|
44
|
+
callback(null, nextValue);
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
callback(err);
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
.getValue();
|
|
51
|
+
service
|
|
52
|
+
.getCharacteristic(HoldPosition)
|
|
53
|
+
.on("set" /* SET */, async (value, callback) => {
|
|
54
|
+
debug_1.debugSet(HoldPosition, service, value);
|
|
55
|
+
if (!value) {
|
|
56
|
+
// @NOTE asked to not hold position
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const nextValue = 'STOP';
|
|
60
|
+
debug_1.debugTydomPut('positionCmd', accessory, nextValue);
|
|
61
|
+
await client.put(`/devices/${deviceId}/endpoints/${endpointId}/data`, [
|
|
62
|
+
{
|
|
63
|
+
name: 'positionCmd',
|
|
64
|
+
value: nextValue
|
|
65
|
+
}
|
|
66
|
+
]);
|
|
67
|
+
debug_1.debugSetResult(HoldPosition, service, value, nextValue);
|
|
68
|
+
callback();
|
|
69
|
+
})
|
|
70
|
+
.getValue();
|
|
71
|
+
service
|
|
72
|
+
.getCharacteristic(CurrentPosition)
|
|
73
|
+
.on("get" /* GET */, async (callback) => {
|
|
74
|
+
debug_1.debugGet(CurrentPosition, service);
|
|
75
|
+
try {
|
|
76
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
77
|
+
const position = tydom_1.getTydomDataPropValue(data, 'position') || 0;
|
|
78
|
+
const nextValue = accessory_1.asNumber(position);
|
|
79
|
+
debug_1.debugGetResult(CurrentPosition, service, nextValue);
|
|
80
|
+
callback(null, nextValue);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
callback(err);
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
.getValue();
|
|
87
|
+
service
|
|
88
|
+
.getCharacteristic(TargetPosition)
|
|
89
|
+
.on("get" /* GET */, async (callback) => {
|
|
90
|
+
debug_1.debugGet(TargetPosition, service);
|
|
91
|
+
try {
|
|
92
|
+
const data = await tydom_1.getTydomDeviceData(client, { deviceId, endpointId });
|
|
93
|
+
const position = tydom_1.getTydomDataPropValue(data, 'position') || 0;
|
|
94
|
+
const nextValue = accessory_1.asNumber(position);
|
|
95
|
+
debug_1.debugGetResult(CurrentPosition, service, nextValue);
|
|
96
|
+
callback(null, nextValue);
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
callback(err);
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
.on("set" /* SET */, async (value, callback) => {
|
|
103
|
+
debug_1.debugSet(TargetPosition, service, value);
|
|
104
|
+
try {
|
|
105
|
+
const nextValue = value;
|
|
106
|
+
Object.assign(state, {
|
|
107
|
+
latestPosition: nextValue,
|
|
108
|
+
lastUpdatedAt: Date.now()
|
|
109
|
+
});
|
|
110
|
+
await debouncedSetPosition(nextValue);
|
|
111
|
+
debug_1.debugSetResult(TargetPosition, service, value, nextValue);
|
|
112
|
+
callback();
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
callback(err);
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
.getValue();
|
|
119
|
+
};
|
|
120
|
+
exports.setupWindowCovering = setupWindowCovering;
|
|
121
|
+
const updateWindowCovering = (accessory, _controller, updates, type) => {
|
|
122
|
+
const { context } = accessory;
|
|
123
|
+
const { state } = context;
|
|
124
|
+
const { CurrentPosition, TargetPosition, ObstructionDetected } = hap_1.Characteristic;
|
|
125
|
+
// Process command updates
|
|
126
|
+
if (type === 'cdata') {
|
|
127
|
+
updates.forEach((update) => {
|
|
128
|
+
const { values } = update;
|
|
129
|
+
const { event } = values;
|
|
130
|
+
debug_1.debug(`New ${chalk_1.chalkKeyword('WindowCovering')} event=${chalk_1.chalkJson(event)}`);
|
|
131
|
+
});
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
updates.forEach((update) => {
|
|
135
|
+
const { name, value } = update;
|
|
136
|
+
switch (name) {
|
|
137
|
+
case 'position': {
|
|
138
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.WindowCovering);
|
|
139
|
+
const position = accessory_1.asNumber(value);
|
|
140
|
+
if (position === null) {
|
|
141
|
+
debug_1.debug(`Encountered a ${chalk_1.chalkString('position')} update with a null value!`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
debug_1.debugSetUpdate(CurrentPosition, service, position);
|
|
145
|
+
service.updateCharacteristic(CurrentPosition, position);
|
|
146
|
+
// @NOTE ignore pending updates
|
|
147
|
+
if (state.pendingUpdatedValues.includes(position)) {
|
|
148
|
+
debug_1.debug(`Ignoring a pending ${chalk_1.chalkString('position')} update with value=${chalk_1.chalkNumber(position)} !`);
|
|
149
|
+
state.pendingUpdatedValues = [];
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
debug_1.debugSetUpdate(TargetPosition, service, position);
|
|
153
|
+
service.updateCharacteristic(TargetPosition, position);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
case 'obstacleDefect': {
|
|
157
|
+
const service = accessory_1.getAccessoryService(accessory, hap_1.Service.WindowCovering);
|
|
158
|
+
debug_1.debugSetUpdate(ObstructionDetected, service, value);
|
|
159
|
+
service.updateCharacteristic(ObstructionDetected, value);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
default:
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
exports.updateWindowCovering = updateWindowCovering;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a, _b;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.HOMEBRIDGE_TYDOM_LOCALE = exports.HOMEBRIDGE_TYDOM_PIN = exports.HOMEBRIDGE_TYDOM_PASSWORD = exports.DEBUG = exports.PLATFORM_NAME = exports.PLUGIN_NAME = void 0;
|
|
5
|
+
exports.PLUGIN_NAME = 'homebridge-tydom';
|
|
6
|
+
exports.PLATFORM_NAME = 'Tydom';
|
|
7
|
+
_a = process.env, exports.DEBUG = _a.DEBUG, exports.HOMEBRIDGE_TYDOM_PASSWORD = _a.HOMEBRIDGE_TYDOM_PASSWORD, exports.HOMEBRIDGE_TYDOM_PIN = _a.HOMEBRIDGE_TYDOM_PIN, _b = _a.HOMEBRIDGE_TYDOM_LOCALE, exports.HOMEBRIDGE_TYDOM_LOCALE = _b === void 0 ? 'fr' : _b;
|