homebridge-winix-purifiers 2.2.5 → 2.2.6
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/dist/characteristic.js +10 -1
- package/dist/device.js +17 -10
- package/package.json +2 -2
package/dist/characteristic.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CharacteristicWrapper = exports.CharacteristicManager = void 0;
|
|
4
|
+
const winix_api_1 = require("winix-api");
|
|
4
5
|
const errors_1 = require("./errors");
|
|
5
6
|
/**
|
|
6
7
|
* Manager to provide a consistent way to get and set characteristics
|
|
@@ -62,7 +63,15 @@ class CharacteristicWrapper {
|
|
|
62
63
|
}
|
|
63
64
|
catch (e) {
|
|
64
65
|
(0, errors_1.assertError)(e);
|
|
65
|
-
|
|
66
|
+
// Known transient upstream conditions (rate limit, 5xx, DNS, malformed body)
|
|
67
|
+
// still fail the HAP call so HomeKit knows the action didn't land, but log at
|
|
68
|
+
// warn without the implication of a plugin bug.
|
|
69
|
+
if (e instanceof winix_api_1.RateLimitError || e instanceof winix_api_1.UpstreamUnavailableError) {
|
|
70
|
+
this.log.warn(`Winix API transient: ${e.constructor.name}: ${e.message}`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.log.error('error calling Winix API:', e.message);
|
|
74
|
+
}
|
|
66
75
|
throw new this.platform.HapStatusError(-70402 /* HAPStatus.SERVICE_COMMUNICATION_FAILURE */);
|
|
67
76
|
}
|
|
68
77
|
}
|
package/dist/device.js
CHANGED
|
@@ -5,6 +5,9 @@ const winix_api_1 = require("winix-api");
|
|
|
5
5
|
const MAX_BACKOFF_MS = 5 * 60 * 1000;
|
|
6
6
|
const COMMAND_DELAY_MS = 1500;
|
|
7
7
|
const UNREACHABLE_THRESHOLD = 3;
|
|
8
|
+
// 90s clears WinixClient's internal 60s rate-limit cooldown plus a small buffer,
|
|
9
|
+
// so the first poll after a rate-limited initialFetch actually has a chance to succeed.
|
|
10
|
+
const FAILED_FETCH_RETRY_MS = 90 * 1000;
|
|
8
11
|
class Device {
|
|
9
12
|
constructor(deviceId, pollIntervalMs, log, client) {
|
|
10
13
|
this.deviceId = deviceId;
|
|
@@ -41,8 +44,8 @@ class Device {
|
|
|
41
44
|
this.log.debug('device:initialFetch()', JSON.stringify(this.state));
|
|
42
45
|
}
|
|
43
46
|
catch (e) {
|
|
44
|
-
if (e instanceof winix_api_1.RateLimitError) {
|
|
45
|
-
this.log.warn(
|
|
47
|
+
if (e instanceof winix_api_1.RateLimitError || e instanceof winix_api_1.UpstreamUnavailableError) {
|
|
48
|
+
this.log.warn(`device:initialFetch() ${e.constructor.name}, using defaults (will retry soon)`);
|
|
46
49
|
return;
|
|
47
50
|
}
|
|
48
51
|
this.log.warn('device:initialFetch() failed, using defaults:', e.message);
|
|
@@ -50,10 +53,14 @@ class Device {
|
|
|
50
53
|
}
|
|
51
54
|
startPolling(onUpdate) {
|
|
52
55
|
this.onUpdate = onUpdate;
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
// If initialFetch failed (rate limited, upstream unavailable, etc.), the device
|
|
57
|
+
// is unreachable in HomeKit until the first successful poll. Skip the full-interval
|
|
58
|
+
// jitter and retry soon to close that window. Otherwise stagger the first poll
|
|
59
|
+
// with a random delay to avoid all devices hitting the API at the same time.
|
|
60
|
+
const delay = this.hasReceivedData
|
|
61
|
+
? Math.floor(Math.random() * this.pollIntervalMs)
|
|
62
|
+
: Math.min(FAILED_FETCH_RETRY_MS, this.pollIntervalMs);
|
|
63
|
+
this.schedulePoll(delay);
|
|
57
64
|
}
|
|
58
65
|
resetPollTimer(delayMs = 3000) {
|
|
59
66
|
this.schedulePoll(delayMs);
|
|
@@ -168,10 +175,10 @@ class Device {
|
|
|
168
175
|
this.schedulePoll(this.pollIntervalMs);
|
|
169
176
|
return;
|
|
170
177
|
}
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
if (e instanceof winix_api_1.NoDataError) {
|
|
174
|
-
this.log.debug(
|
|
178
|
+
// Transient upstream conditions (Winix "no data", 5xx, DNS/connect failures,
|
|
179
|
+
// malformed bodies). Keep last-known state and don't count toward unreachable.
|
|
180
|
+
if (e instanceof winix_api_1.NoDataError || e instanceof winix_api_1.UpstreamUnavailableError) {
|
|
181
|
+
this.log.debug(`device:poll() ${e.constructor.name}, retaining last-known state`);
|
|
175
182
|
this.schedulePoll(this.pollIntervalMs);
|
|
176
183
|
return;
|
|
177
184
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "Winix Air Purifiers",
|
|
3
3
|
"name": "homebridge-winix-purifiers",
|
|
4
|
-
"version": "2.2.
|
|
4
|
+
"version": "2.2.6",
|
|
5
5
|
"description": "Homebridge plugin for Winix air purifiers",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
],
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@homebridge/plugin-ui-utils": "1.0.3",
|
|
69
|
-
"winix-api": "2.0.
|
|
69
|
+
"winix-api": "2.0.2"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/node": "20.11.0",
|