homebridge-tuya-plus 3.14.0-dev.51 → 3.14.0-dev.53
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.
|
@@ -271,10 +271,6 @@ class SimpleGarageDoorAccessory extends BaseAccessory {
|
|
|
271
271
|
// silently dropping the command (the write helpers would otherwise just
|
|
272
272
|
// log and skip, leaving HomeKit to believe the open/close succeeded).
|
|
273
273
|
if (!this.device.connected) throw this._commError();
|
|
274
|
-
// A direct open/close (the GarageDoorOpener target, a Force switch, or
|
|
275
|
-
// the partial switch tapped OFF) is manual control: cancel any pending
|
|
276
|
-
// partial-open auto-stop so it can't halt this movement part-way.
|
|
277
|
-
this._cancelPartialStop();
|
|
278
274
|
|
|
279
275
|
// The opener is level-triggered: act only when the requested target
|
|
280
276
|
// differs from the one we've already committed to. HomeKit re-sends the
|
|
@@ -291,6 +287,17 @@ class SimpleGarageDoorAccessory extends BaseAccessory {
|
|
|
291
287
|
this.log.debug(`[SimpleGarageDoor] ${this.device.context.name}: target unchanged — ignoring repeat request`);
|
|
292
288
|
return;
|
|
293
289
|
}
|
|
290
|
+
|
|
291
|
+
// A direct open/close (the GarageDoorOpener target, a Force switch, or
|
|
292
|
+
// the partial switch tapped OFF) is manual control: cancel any pending
|
|
293
|
+
// partial-open auto-stop so it can't halt this movement part-way. This
|
|
294
|
+
// must run only for a genuine target change, AFTER the repeat check
|
|
295
|
+
// above: a partial open drives the committed target to OPEN itself, so
|
|
296
|
+
// HomeKit's repeat of that OPEN re-enters here, and cancelling on that
|
|
297
|
+
// swallowed repeat would tear down the auto-stop the partial just armed —
|
|
298
|
+
// letting the gate run all the way open instead of parking part-way.
|
|
299
|
+
this._cancelPartialStop();
|
|
300
|
+
|
|
294
301
|
this._applyTarget(value);
|
|
295
302
|
}
|
|
296
303
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-tuya-plus",
|
|
3
|
-
"version": "3.14.0-dev.
|
|
4
|
-
"description": "A community-maintained Homebridge plugin for controlling Tuya devices
|
|
3
|
+
"version": "3.14.0-dev.53",
|
|
4
|
+
"description": "A community-maintained Homebridge plugin for controlling Tuya devices locally over LAN, with an optional Tuya Cloud fallback for whatever the LAN can't reach. Includes new features, fixes, and updated device support. PRs welcome: if it runs, it ships (almost).",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "jest",
|
|
@@ -602,6 +602,53 @@ describe('SimpleGarageDoorAccessory._handlePartialOpen', () => {
|
|
|
602
602
|
expect(device.update).toHaveBeenCalledTimes(3);
|
|
603
603
|
});
|
|
604
604
|
|
|
605
|
+
test('A repeat of the partial open\'s own OPEN target does not cancel the pending auto-stop', () => {
|
|
606
|
+
// The partial open drives TargetDoorState to OPEN itself, then waits for
|
|
607
|
+
// the gate to report it's moving before arming the auto-stop. HomeKit
|
|
608
|
+
// re-sends that same OPEN in the meantime (a second controller echoing
|
|
609
|
+
// it, or its own retry). That swallowed repeat must NOT tear down the
|
|
610
|
+
// pending partial, or the gate runs all the way open instead of parking
|
|
611
|
+
// part-way — the reported bug.
|
|
612
|
+
const { instance, device } = makeSimpleGarage();
|
|
613
|
+
instance.partialOpenMs = 2000;
|
|
614
|
+
device.state['105'] = STATE_CLOSING_OR_CLOSED; // starts closed → stop waits for movement
|
|
615
|
+
|
|
616
|
+
instance._handlePartialOpen();
|
|
617
|
+
expect(device.update).toHaveBeenCalledTimes(1);
|
|
618
|
+
expect(device.update).toHaveBeenNthCalledWith(1, { '101': true }); // open
|
|
619
|
+
expect(instance.partialPending).toBe(true);
|
|
620
|
+
|
|
621
|
+
// HomeKit's repeat of the same OPEN lands before the gate reports moving.
|
|
622
|
+
instance.setTargetDoorState(TDS.OPEN);
|
|
623
|
+
expect(instance.partialPending).toBe(true); // still pending — not cancelled
|
|
624
|
+
expect(device.update).toHaveBeenCalledTimes(1); // and no second open
|
|
625
|
+
|
|
626
|
+
// The gate now reports it's moving: the countdown arms and the stop fires.
|
|
627
|
+
emitState(device, STATE_OPENING_OR_OPEN);
|
|
628
|
+
expect(instance.partialStopTimer).not.toBeNull();
|
|
629
|
+
jest.advanceTimersByTime(2000);
|
|
630
|
+
expect(device.update).toHaveBeenNthCalledWith(2, { '103': true }); // partial stop
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
test('A repeat of OPEN after the auto-stop is armed leaves the timer intact', () => {
|
|
634
|
+
const { instance, device } = makeSimpleGarage();
|
|
635
|
+
instance.partialOpenMs = 2000;
|
|
636
|
+
device.state['105'] = STATE_OPENING_OR_OPEN; // arms immediately
|
|
637
|
+
|
|
638
|
+
instance._handlePartialOpen();
|
|
639
|
+
expect(instance.partialStopTimer).not.toBeNull();
|
|
640
|
+
|
|
641
|
+
// A repeat OPEN partway through must not cancel or push out the timer.
|
|
642
|
+
jest.advanceTimersByTime(500);
|
|
643
|
+
instance.setTargetDoorState(TDS.OPEN);
|
|
644
|
+
expect(instance.partialStopTimer).not.toBeNull();
|
|
645
|
+
expect(device.update).toHaveBeenCalledTimes(1); // no second open
|
|
646
|
+
|
|
647
|
+
// The original 2000ms deadline still fires the stop.
|
|
648
|
+
jest.advanceTimersByTime(1500);
|
|
649
|
+
expect(device.update).toHaveBeenNthCalledWith(2, { '103': true });
|
|
650
|
+
});
|
|
651
|
+
|
|
605
652
|
test('Does nothing when partialOpenMs is not configured', () => {
|
|
606
653
|
const { instance, device } = makeSimpleGarage();
|
|
607
654
|
instance.partialOpenMs = 0;
|