@akospasztor/homebridge-create-ceiling-fan 1.0.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.
@@ -0,0 +1,542 @@
1
+ import { Mutex } from './mutex.js';
2
+ import TuyAPI from 'tuyapi';
3
+ /**
4
+ * CreateCeilingFanAccessory: the accessory implementation for CREATE ceiling fans.
5
+ *
6
+ * This class contains the accessory implementation and follows the Homebridge
7
+ * plugin development recommendations.
8
+ *
9
+ * #### Exposed services and characteristics
10
+ *
11
+ * | Service | Characteristics |
12
+ * | ------------| ------------------------------------------------ |
13
+ * | `Fanv2` | `Active`, `Rotation Direction`, `Rotation Speed` |
14
+ * | `Lightbulb` | `On` |
15
+ *
16
+ * Note: the `Lightbulb` service is only exposed if the accessory has been
17
+ * configured with the light option enabled.
18
+ *
19
+ * #### Fan rotation speed representation
20
+ *
21
+ * CREATE fans have speed settings ranging from `1` (lowest) to `6` (highest).
22
+ * The HomeKit UI slider for the fan rotation speed provides a value from `1`
23
+ * to `100` and `0` means the fan is turned off. The slider steps can be
24
+ * configured to a desired value via the `Min Step` Characteristic. This works
25
+ * well e.g. for Dyson devices where the speed settings ranges from `1` to `10`.
26
+ * In this case the `Min Step` Characteristic can be configured to `10`,
27
+ * resulting in a nice user experience where the `0` - `100` UI slider is
28
+ * divided into 10 steps. However, this does not work well for CREATE fans with
29
+ * 6 speed steps. In order to provide smooth user experience, the following
30
+ * representation is implemented:
31
+ *
32
+ * - The UI slider is configured with the default `Min Step` Characteristic of
33
+ * `1`. This provides smooth and fluid user input and slider operation.
34
+ * - The following UI slider inputs represent the different speed settings of
35
+ * the fan:
36
+ * | Device fan speed | Corresponding UI slider value | User input range on the slider |
37
+ * | :--------------: | :---------------------------: | :----------------------------: |
38
+ * | 1 | 10 | 1 - 19 |
39
+ * | 2 | 30 | 20 - 39 |
40
+ * | 3 | 50 | 40 - 59 |
41
+ * | 4 | 70 | 60 - 79 |
42
+ * | 5 | 90 | 80 - 94 |
43
+ * | 6 | 100 | 95 - 100 |
44
+ *
45
+ * - When the user operates the slider, a debouncing timer with the value of
46
+ * {@link fanSetSpeedDebouncePeriod} member is set. When the timer fires, the
47
+ * current state of the slider value is converted to the nearest value that
48
+ * corresponds to the device fan speed. The purpose of the debounce timer is
49
+ * to provide great user experience. Without the debounce timer, every moment
50
+ * the user slides the finger would result in generating lots of events -
51
+ * making the slider jump around immediately, without waiting for the user to
52
+ * finish adjusting the speed.
53
+ *
54
+ * ```text
55
+ * UI slider │ Fan speed
56
+ * input value │ value
57
+ * ─────────────┼──────────────
58
+ * ┌──────┐ │
59
+ * │ 100 ─┼─────┼─► Fan speed 6
60
+ * │ │ ▲ │
61
+ * │ 95 ├─┘ │
62
+ * │ 94 ├─┐ │
63
+ * │ │ ▼ │
64
+ * │ 90 ─┼─────┼─► Fan speed 5
65
+ * │ │ ▲ │
66
+ * │ 80 ├─┘ │
67
+ * │ 79 ├─┐ │
68
+ * │ │ ▼ │
69
+ * │ 70 ─┼─────┼─► Fan speed 4
70
+ * │ │ ▲ │
71
+ * │ 60 ├─┘ │
72
+ * │ 59 ├─┐ │
73
+ * │ │ ▼ │
74
+ * │ 50 ─┼─────┼─► Fan speed 3
75
+ * │ │ ▲ │
76
+ * │ 40 ├─┘ │
77
+ * │ 39 ├─┐ │
78
+ * │ │ ▼ │
79
+ * │ 30 ─┼─────┼─► Fan speed 2
80
+ * │ │ ▲ │
81
+ * │ 20 ├─┘ │
82
+ * │ 19 ├─┐ │
83
+ * │ │ ▼ │
84
+ * │ 10 ─┼─────┼─► Fan speed 1
85
+ * │ │ ▲ │
86
+ * │ 1 ├─┘ │
87
+ * │ 0 ─┼─────┼─► Fan off
88
+ * └──────┘ │
89
+ * ```
90
+ *
91
+ * #### Fan rotation direction representation
92
+ *
93
+ * The rotation of the device as seen from standing below the fan follows the
94
+ * HomeKit rotation representation.
95
+ *
96
+ * | Device direction raw value | HomeKit representation | Fan operation |
97
+ * | -------------------------- | ---------------------- | --------------------------------------- |
98
+ * | `forward` (default) | Counter-clockwise | Fan blows downwards (i.e. summer mode) |
99
+ * | `reverse` | Clockwise | Fan blows upwards (i.e. winter mode) |
100
+ *
101
+ * #### Device communication
102
+ *
103
+ * The fan is a Tuya-compatible device and its firmware is mildly put: not the best.
104
+ * Among other issues, devices with these firmware are known to stop responding
105
+ * to commands, randomly drop connection, etc (see e.g.
106
+ * https://github.com/jasonacox/tinytuya/discussions/443 and
107
+ * https://github.com/moifort/homebridge-create-fan/issues/18).
108
+ *
109
+ * To provide reliable operation via HomeKit, this plugin implements the device
110
+ * communication the following way:
111
+ *
112
+ * - The device accepts one connection at a time. Therefore, a mutex with a
113
+ * waiting queue is used for ensuring that only one command is sent to the
114
+ * device at a time. For detailed description refer to: {@link Mutex}.
115
+ * - The device state is cached. Whenever the device state is requested by
116
+ * HomeKit (e.g. the user opens up the Home app), the implementation
117
+ * immediately returns the requested value from the cache.
118
+ * - The status of the device is periodically (defined by
119
+ * {@link getDeviceStatusPeriod}) queried from the device. After obtaining the
120
+ * device status, the device state cache as well as the HomeKit
121
+ * Characteristics are automatically updated.
122
+ * - If the device fails to respond to the get status request, the polling
123
+ * period is reduced significantly (defined by
124
+ * {@link getDeviceStatusFastRetryPeriod}), so that the attempt is retried
125
+ * quickly.
126
+ * - The communication with the device happens in a synchronous way, supported
127
+ * by the mutex queue and timeout mechanism. This seems to provide the most
128
+ * reliable communication with the device.
129
+ *
130
+ * Communication failure tends to happen when attempting to control the device
131
+ * via HomeKit right after using the device's physical remote. The device used
132
+ * for development & testing (CREATE Wind Calm model purchased in 2025) seemed
133
+ * to always recover from a failed communication latest after a few retry
134
+ * attempts.
135
+ *
136
+ * @see https://developers.homebridge.io/#/
137
+ * @see [Fanv2 service type](https://developers.homebridge.io/#/service/Fanv2)
138
+ * @see [Lightbulb service type](https://developers.homebridge.io/#/service/Lightbulb)
139
+ */
140
+ export class CreateCeilingFanAccessory {
141
+ platform;
142
+ accessory;
143
+ fanService;
144
+ lightService;
145
+ getDeviceStatusTimer;
146
+ fanSetSpeedDebounceTimer = null;
147
+ deviceCommunicator;
148
+ mutex;
149
+ isGetStatusInProgress = false;
150
+ fanSetSpeedDebouncePeriod = 500;
151
+ getDeviceStatusFastRetryPeriod = 1000;
152
+ getDeviceStatusPeriod = 10000;
153
+ getDeviceStatusConnectTimeout = 3000;
154
+ getDeviceStatusReadTimeout = 1000;
155
+ fanRotationSpeedNormalized = [10, 30, 50, 70, 90, 100];
156
+ state = {
157
+ fanOn: false,
158
+ fanSpeed: 1,
159
+ fanRotationClockwise: false,
160
+ lightOn: false,
161
+ isValid: false,
162
+ };
163
+ /**
164
+ * Constructor for the CreateCeilingFanAccessory object.
165
+ *
166
+ * @param platform The plugin platform object.
167
+ * @param accessory The homebridge platform accessory object.
168
+ */
169
+ constructor(platform, accessory) {
170
+ this.platform = platform;
171
+ this.accessory = accessory;
172
+ // Set accessory information
173
+ this.accessory.getService(this.platform.Service.AccessoryInformation)
174
+ .setCharacteristic(this.platform.Characteristic.Manufacturer, 'CREATE')
175
+ .setCharacteristic(this.platform.Characteristic.Model, accessory.context.device.name)
176
+ .setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.context.device.id);
177
+ // Get the fan service if it exists, otherwise create a new service
178
+ this.fanService =
179
+ this.accessory.getService(this.platform.Service.Fanv2) ||
180
+ this.accessory.addService(this.platform.Service.Fanv2);
181
+ // Set the fan service name: this is what is displayed as the default name on the Home app
182
+ this.fanService.setCharacteristic(this.platform.Characteristic.Name, accessory.context.device.name);
183
+ // Register handlers for the fan Active (On/Off) Characteristic
184
+ this.fanService.getCharacteristic(this.platform.Characteristic.Active)
185
+ .onGet(this.handleFanActiveStateGet.bind(this))
186
+ .onSet(this.handleFanActiveStateSet.bind(this));
187
+ // Register handlers for the fan Rotation Speed Characteristic
188
+ this.fanService.getCharacteristic(this.platform.Characteristic.RotationSpeed)
189
+ .onGet(this.handleFanRotationSpeedGet.bind(this))
190
+ .onSet(this.handleFanRotationSpeedSet.bind(this));
191
+ // Set the properties of the fan RotationSpeed Characteristic
192
+ // Note: the fan has 6 different speed settings, which cannot be divided nicely into the 0-100% range of the UI
193
+ // slider that is displayed in the Home app. Therefore we allow the user to smoothly adjust the speed with the UI
194
+ // slider by setting the slider step size to 1, and we re-adjust the slider (after a debouncing timeout) to the
195
+ // value that corresponds to the fan speed (see `fanRotationSpeed` array).
196
+ this.fanService.getCharacteristic(this.platform.Characteristic.RotationSpeed)
197
+ .setProps({
198
+ minValue: 0,
199
+ maxValue: 100,
200
+ minStep: 1,
201
+ });
202
+ // Register handlers for the fan Rotation Direction Characteristic
203
+ this.fanService.getCharacteristic(this.platform.Characteristic.RotationDirection)
204
+ .onGet(this.handleFanRotationDirectionGet.bind(this))
205
+ .onSet(this.handleFanRotationDirectionSet.bind(this));
206
+ // Note: the light service is only created if the device is configured with the light option
207
+ if (this.accessory.context.device.hasLight) {
208
+ // Get the light service if it exists, otherwise create a new service
209
+ this.lightService =
210
+ this.accessory.getService(this.platform.Service.Lightbulb) ||
211
+ this.accessory.addService(this.platform.Service.Lightbulb);
212
+ // Set the light service name
213
+ this.lightService.setCharacteristic(this.platform.Characteristic.Name, accessory.context.device.name + ' Light');
214
+ // Register handlers for the light On/Off Characteristic
215
+ this.lightService.getCharacteristic(this.platform.Characteristic.On)
216
+ .onGet(this.handleLightOnGet.bind(this))
217
+ .onSet(this.handleLightOnSet.bind(this));
218
+ }
219
+ else {
220
+ this.lightService =
221
+ this.accessory.getService(this.platform.Service.Lightbulb);
222
+ if (this.lightService) {
223
+ this.accessory.removeService(this.lightService);
224
+ this.platform.log.info('Stale light service has been removed');
225
+ }
226
+ }
227
+ // Create the device communicator object
228
+ this.deviceCommunicator = new TuyAPI({
229
+ id: this.accessory.context.device.id,
230
+ key: this.accessory.context.device.key,
231
+ ip: this.accessory.context.device.ip,
232
+ version: this.accessory.context.device.protocolVersion,
233
+ issueGetOnConnect: false,
234
+ });
235
+ this.deviceCommunicator.on('error', (error) => {
236
+ this.platform.log.info('Error during device communication:', error);
237
+ });
238
+ // Create the mutex to prevent concurrent communication with the device
239
+ this.mutex = new Mutex();
240
+ // Start the periodic get status timer
241
+ this.getDeviceStatusTimer = setTimeout(() => this.getDeviceStatus(), this.getDeviceStatusPeriod);
242
+ this.platform.log.info('Accessory initialized: %s (device id: %s)', this.accessory.context.device.name, this.accessory.context.device.id);
243
+ this.platform.log.debug('Accessory details:', this.accessory.context.device);
244
+ }
245
+ /**
246
+ * Handle the get requests from HomeKit to get the current value of the Fanv2 Active characteristic
247
+ *
248
+ * @return The Fanv2 Active characteristic value from the device state cache.
249
+ */
250
+ async handleFanActiveStateGet() {
251
+ this.getDeviceStatus();
252
+ this.throwErrorIfDeviceUnresponsive();
253
+ return this.fanActiveValueToCharacteristicValue();
254
+ }
255
+ /**
256
+ * Handle the set requests from HomeKit to set the device with the Fanv2 Active characteristic value
257
+ *
258
+ * @param value The Fanv2 Active characteristic value to be set.
259
+ */
260
+ async handleFanActiveStateSet(value) {
261
+ this.platform.log.debug('Set Fan Active:', value);
262
+ await this.setDeviceValue(60, (value === this.platform.Characteristic.Active.ACTIVE) ? true : false);
263
+ }
264
+ /**
265
+ * Handle the get requests from HomeKit to get the current value of the Fanv2 Rotation Speed characteristic
266
+ *
267
+ * @return The Fanv2 Rotation Speed characteristic value from the device state cache.
268
+ */
269
+ async handleFanRotationSpeedGet() {
270
+ this.getDeviceStatus();
271
+ this.throwErrorIfDeviceUnresponsive();
272
+ return this.fanRotationSpeedValueToCharacteristicValue();
273
+ }
274
+ /**
275
+ * Handle the set requests from HomeKit to set the device with the Fanv2 Rotation Speed characteristic value
276
+ *
277
+ * @param value The Fanv2 Rotation Speed characteristic value to be set.
278
+ */
279
+ async handleFanRotationSpeedSet(value) {
280
+ this.platform.log.debug('Set RotationSpeed input:', value);
281
+ const adjustedValue = this.adjustInputRotationSpeed(Number(value));
282
+ // Stop any existing debounce timer
283
+ if (this.fanSetSpeedDebounceTimer) {
284
+ clearTimeout(this.fanSetSpeedDebounceTimer);
285
+ }
286
+ if (adjustedValue !== 0) {
287
+ this.fanService.updateCharacteristic(this.platform.Characteristic.RotationSpeed, adjustedValue);
288
+ this.platform.log.debug('Set RotationSpeed adjusted:', adjustedValue);
289
+ // Start a new debounce timer
290
+ this.fanSetSpeedDebounceTimer = setTimeout(async () => {
291
+ const dpsRotationSpeed = this.fanRotationSpeedNormalized.indexOf(adjustedValue) + 1;
292
+ this.platform.log.debug('Set RotationSpeed debounced, setting DPS value:', dpsRotationSpeed);
293
+ await this.setDeviceValue(62, dpsRotationSpeed);
294
+ }, this.fanSetSpeedDebouncePeriod);
295
+ }
296
+ }
297
+ /**
298
+ * Handle the get requests from HomeKit to get the current value of the Fanv2 Rotation Direction characteristic
299
+ *
300
+ * @return The Fanv2 Rotation Direction characteristic value from the device state cache.
301
+ */
302
+ async handleFanRotationDirectionGet() {
303
+ this.getDeviceStatus();
304
+ this.throwErrorIfDeviceUnresponsive();
305
+ return this.fanRotationDirectionValueToCharacteristicValue();
306
+ }
307
+ /**
308
+ * Handle the set requests from HomeKit to set the device with the Fanv2 Rotation Direction characteristic value
309
+ *
310
+ * @param value The Fanv2 Rotation Direction characteristic value to be set.
311
+ */
312
+ async handleFanRotationDirectionSet(value) {
313
+ this.platform.log.debug('Set Fan RotationDirection:', (value === this.platform.Characteristic.RotationDirection.COUNTER_CLOCKWISE) ? 'COUNTER_CLOCKWISE' : 'CLOCKWISE');
314
+ await this.setDeviceValue(63, (value === this.platform.Characteristic.RotationDirection.COUNTER_CLOCKWISE) ? 'forward' : 'reverse');
315
+ }
316
+ /**
317
+ * Handle the get requests from HomeKit to get the current value of the Lightbulb On characteristic
318
+ *
319
+ * @return The Lightbulb On characteristic value from the device state cache.
320
+ */
321
+ async handleLightOnGet() {
322
+ this.getDeviceStatus();
323
+ this.throwErrorIfDeviceUnresponsive();
324
+ return this.lightOnValueToCharacteristicValue();
325
+ }
326
+ /**
327
+ * Handle the set requests from HomeKit to set the device with the Lightbulb On characteristic value
328
+ *
329
+ * @param value The Lightbulb On characteristic value to be set.
330
+ */
331
+ async handleLightOnSet(value) {
332
+ this.platform.log.debug('Set Light On:', value);
333
+ await this.setDeviceValue(20, value);
334
+ }
335
+ /**
336
+ * Get device status.
337
+ *
338
+ * This method reads the status of the device periodically and updates the
339
+ * accessory state after completing the operation. The actual communication
340
+ * is carried out with a timeout mechanism, so that an unresponsive device
341
+ * will not make the plugin and HomeKit unresponsive. If the communication
342
+ * fails, the periodic timer will be set with a shorter timeout so that the
343
+ * next retry attempt happens fast. After the communication with the device
344
+ * is recovered, the period will be reset to the original period value.
345
+ *
346
+ * The function can be called in two ways:
347
+ *
348
+ * 1. Calling it with `await`: the method starts the reading operation and
349
+ * waits (i.e. blocks) until the reading has been completed (or timed out).
350
+ * 2. Simply calling it (without `await`): the method starts the reading
351
+ * operation and returns right afterwards, not waiting for the reading
352
+ * to be completed. This is used when handling accessory GET requests
353
+ * from HomeKit. Get requests should return as fast as possible, because
354
+ * long delays will result in HomeKit being unresponsive and a bad user
355
+ * experience in general.
356
+ *
357
+ * If the function is called again while there is already an ongoing read
358
+ * operation, the reading will simply be skipped - the accessory status will
359
+ * be updated anyway after executing the already ongoing reading operation.
360
+ * This can happen e.g. when a periodic read operation is already in place
361
+ * and a GET request arrives from HomeKit at the same time.
362
+ */
363
+ async getDeviceStatus() {
364
+ this.platform.log.debug('[getDeviceStatus] --- Start');
365
+ let isCommunicationError = false;
366
+ clearTimeout(this.getDeviceStatusTimer);
367
+ if (!this.isGetStatusInProgress) {
368
+ this.isGetStatusInProgress = true;
369
+ const releaseMutex = await this.mutex.lock();
370
+ this.platform.log.debug(' * Mutex granted for reading, connecting to device...');
371
+ try {
372
+ await this.waitForPromiseWithTimeout(this.deviceCommunicator.connect(), this.getDeviceStatusConnectTimeout);
373
+ this.platform.log.debug(' * Device connected, reading...');
374
+ const status = await this.waitForPromiseWithTimeout(this.deviceCommunicator.get({ schema: true }), this.getDeviceStatusReadTimeout);
375
+ this.platform.log.debug(' * Status:', status);
376
+ this.updateDeviceState(status);
377
+ this.state.isValid = true;
378
+ this.updateAccessoryState();
379
+ }
380
+ catch (error) {
381
+ this.platform.log.info(' *', error);
382
+ this.deviceCommunicator.disconnect();
383
+ this.state.isValid = false;
384
+ isCommunicationError = true;
385
+ }
386
+ finally {
387
+ this.isGetStatusInProgress = false;
388
+ releaseMutex();
389
+ this.platform.log.debug(' * Mutex unlocked after reading');
390
+ }
391
+ }
392
+ else {
393
+ this.platform.log.debug(' * Get device status has already been in progress');
394
+ }
395
+ const nextGetStatusPeriod = (isCommunicationError)
396
+ ? this.getDeviceStatusFastRetryPeriod
397
+ : this.getDeviceStatusPeriod;
398
+ this.getDeviceStatusTimer = setTimeout(() => this.getDeviceStatus(), nextGetStatusPeriod);
399
+ this.platform.log.debug(`[getDeviceStatus] --- Done. Next periodic getDeviceStatus in: ${nextGetStatusPeriod} ms`);
400
+ }
401
+ /**
402
+ * Set device value.
403
+ *
404
+ * This method sends a command to the device to set the device into the
405
+ * required state. Only one parameter can be set at a time.
406
+ *
407
+ * @param dps The data point index of the device to be set.
408
+ * @param value The value to be set.
409
+ */
410
+ async setDeviceValue(dps, value) {
411
+ this.platform.log.debug('[setDeviceStatus] --- Start');
412
+ const releaseMutex = await this.mutex.lock();
413
+ this.platform.log.debug(' * Mutex granted for sending, connecting to device...');
414
+ try {
415
+ await this.deviceCommunicator.connect();
416
+ this.platform.log.debug(' * Device connected, sending...');
417
+ const status = await this.deviceCommunicator.set({ dps: dps, set: value });
418
+ this.platform.log.debug(' * Status:', status);
419
+ }
420
+ catch (error) {
421
+ this.platform.log.debug(' *', error);
422
+ this.deviceCommunicator.disconnect();
423
+ }
424
+ finally {
425
+ releaseMutex();
426
+ this.platform.log.debug(' * Mutex unlocked after sending');
427
+ }
428
+ this.platform.log.debug('[setDeviceStatus] --- Done');
429
+ }
430
+ /**
431
+ * Wait for a promise to be resolved within a given timeout.
432
+ *
433
+ * @param promise The promise to be resolved within a given timeout.
434
+ * @param ms The timeout in [ms] within the promise should be resolved.
435
+ * @return The resolved promise if it gets resolved within the timeout, otherwise reject the promise.
436
+ */
437
+ async waitForPromiseWithTimeout(promise, ms) {
438
+ const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error(`Waiting for promise timed out after ${ms} ms`)), ms));
439
+ return Promise.race([promise, timeout]);
440
+ }
441
+ /**
442
+ * Throw a HomeKit No Response status if the accessory state is invalid.
443
+ */
444
+ throwErrorIfDeviceUnresponsive() {
445
+ if (!this.state.isValid) {
446
+ throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */);
447
+ }
448
+ }
449
+ /**
450
+ * Update the accessory state with the values received from the device.
451
+ *
452
+ * @param status The raw data points object received from the device.
453
+ */
454
+ updateDeviceState(status) {
455
+ this.state.fanOn = status.dps['60'];
456
+ this.state.fanSpeed = status.dps['62'];
457
+ this.state.fanRotationClockwise = (status.dps['63'] === 'forward') ? false : true;
458
+ this.state.lightOn = status.dps['20'];
459
+ }
460
+ /**
461
+ * Update all accessory service characteristics based on the accessory state.
462
+ */
463
+ updateAccessoryState() {
464
+ this.fanService.updateCharacteristic(this.platform.Characteristic.Active, this.fanActiveValueToCharacteristicValue());
465
+ this.fanService.updateCharacteristic(this.platform.Characteristic.RotationSpeed, this.fanRotationSpeedValueToCharacteristicValue());
466
+ this.fanService.updateCharacteristic(this.platform.Characteristic.RotationDirection, this.fanRotationDirectionValueToCharacteristicValue());
467
+ if (this.lightService) {
468
+ this.lightService.updateCharacteristic(this.platform.Characteristic.On, this.lightOnValueToCharacteristicValue());
469
+ }
470
+ }
471
+ /**
472
+ * Convert the fan active state of the accessory to Fanv2 Active characteristic value.
473
+ *
474
+ * @return The Fanv2 Active characteristic value.
475
+ */
476
+ fanActiveValueToCharacteristicValue() {
477
+ return (this.state.fanOn)
478
+ ? this.platform.Characteristic.Active.ACTIVE
479
+ : this.platform.Characteristic.Active.INACTIVE;
480
+ }
481
+ /**
482
+ * Convert the fan rotation speed of the accessory to Fanv2 Rotation Speed characteristic value.
483
+ *
484
+ * @return The Fanv2 Rotation Speed characteristic value.
485
+ */
486
+ fanRotationSpeedValueToCharacteristicValue() {
487
+ return this.fanRotationSpeedNormalized[this.state.fanSpeed - 1];
488
+ }
489
+ /**
490
+ * Convert the fan rotation direction of the accessory to Fanv2 Rotation Direction characteristic value.
491
+ *
492
+ * @return The Fanv2 Rotation Direction characteristic value.
493
+ */
494
+ fanRotationDirectionValueToCharacteristicValue() {
495
+ return (this.state.fanRotationClockwise)
496
+ ? this.platform.Characteristic.RotationDirection.CLOCKWISE
497
+ : this.platform.Characteristic.RotationDirection.COUNTER_CLOCKWISE;
498
+ }
499
+ /**
500
+ * Convert the light on state of the accessory to Lightbulb On characteristic value.
501
+ *
502
+ * @return The Lightbulb On characteristic value.
503
+ */
504
+ lightOnValueToCharacteristicValue() {
505
+ return this.state.lightOn;
506
+ }
507
+ /**
508
+ * Adjust the rotation speed input value.
509
+ *
510
+ * This method is used for converting the input state of the slider value to
511
+ * the nearest value that corresponds to the device fan speed.
512
+ *
513
+ * See the {@link CreateCeilingFanAccessory} class description for more details.
514
+ *
515
+ * @param value The input value of the rotation speed.
516
+ * @return The adjusted value of the rotation speed.
517
+ */
518
+ adjustInputRotationSpeed(value) {
519
+ if (value === 0) {
520
+ return 0;
521
+ }
522
+ if (value < 20) {
523
+ return this.fanRotationSpeedNormalized[0];
524
+ }
525
+ else if (value < 40) {
526
+ return this.fanRotationSpeedNormalized[1];
527
+ }
528
+ else if (value < 60) {
529
+ return this.fanRotationSpeedNormalized[2];
530
+ }
531
+ else if (value < 80) {
532
+ return this.fanRotationSpeedNormalized[3];
533
+ }
534
+ else if (value < 95) {
535
+ return this.fanRotationSpeedNormalized[4];
536
+ }
537
+ else {
538
+ return this.fanRotationSpeedNormalized[5];
539
+ }
540
+ }
541
+ }
542
+ //# sourceMappingURL=platformAccessory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platformAccessory.js","sourceRoot":"","sources":["../src/platformAccessory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This is the name of the platform that users will use to register the plugin in the Homebridge config.json
3
+ */
4
+ export declare const PLATFORM_NAME = "CreateCeilingFanPlatform";
5
+ /**
6
+ * This must match the name of your plugin as defined the package.json `name` property
7
+ */
8
+ export declare const PLUGIN_NAME = "homebridge-create-ceiling-fan";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * This is the name of the platform that users will use to register the plugin in the Homebridge config.json
3
+ */
4
+ export const PLATFORM_NAME = 'CreateCeilingFanPlatform';
5
+ /**
6
+ * This must match the name of your plugin as defined the package.json `name` property
7
+ */
8
+ export const PLUGIN_NAME = 'homebridge-create-ceiling-fan';
9
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,0BAA0B,CAAC;AAExD;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,+BAA+B,CAAC"}
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@akospasztor/homebridge-create-ceiling-fan",
3
+ "displayName": "Homebridge Create Ceiling Fan",
4
+ "type": "module",
5
+ "version": "1.0.0",
6
+ "private": false,
7
+ "description": "Homebridge plugin for CREATE ceiling fans",
8
+ "author": "Akos Pasztor",
9
+ "license": "Apache-2.0",
10
+ "homepage": "https://github.com/akospasztor/homebridge-create-ceiling-fan#readme",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/akospasztor/homebridge-create-ceiling-fan.git"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/akospasztor/homebridge-create-ceiling-fan/issues"
17
+ },
18
+ "keywords": [
19
+ "homebridge-plugin",
20
+ "ceiling fan",
21
+ "fan",
22
+ "create",
23
+ "wind calm",
24
+ "windcalm",
25
+ "tuya"
26
+ ],
27
+ "main": "dist/index.js",
28
+ "files": [
29
+ "dist",
30
+ "docs",
31
+ "config.schema.json",
32
+ "CHANGELOG.md"
33
+ ],
34
+ "engines": {
35
+ "node": "^18.20.4 || ^20.18.0 || ^22.10.0",
36
+ "homebridge": "^1.8.0 || ^2.0.0-beta.0"
37
+ },
38
+ "scripts": {
39
+ "build": "rimraf ./dist && tsc",
40
+ "docs": "typedoc",
41
+ "lint": "eslint . --max-warnings=0",
42
+ "prepublishOnly": "npm run lint && npm run build",
43
+ "watch": "npm run build && npm link && nodemon"
44
+ },
45
+ "dependencies": {
46
+ "tuyapi": "^7.7.1"
47
+ },
48
+ "devDependencies": {
49
+ "@eslint/js": "^9.21.0",
50
+ "@types/node": "^22.13.5",
51
+ "eslint": "^9.21.0",
52
+ "homebridge": "^2.0.0-beta.0",
53
+ "nodemon": "^3.1.9",
54
+ "rimraf": "^6.0.1",
55
+ "ts-node": "^10.9.2",
56
+ "typedoc": "^0.28.7",
57
+ "typescript": "^5.7.3",
58
+ "typescript-eslint": "^8.24.1"
59
+ }
60
+ }