@homebridge-plugins/homebridge-wemo 7.7.1-beta.0 → 7.7.1-beta.2
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 +4 -0
- package/config.schema.json +9 -3
- package/lib/platform.js +35 -6
- package/lib/utils/constants.js +14 -0
- package/lib/utils/lang-en.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,10 @@ All notable changes to `@homebridge-plugins/homebridge-wemo` will be documented
|
|
|
12
12
|
- fix: send a colour change when only the saturation moves, and mend the al cleanup
|
|
13
13
|
- fix: explain a port clash on the notification listener instead of crashing the bridge
|
|
14
14
|
- fix: stop gating a few log lines on a debug setting that was never readable
|
|
15
|
+
- fix: keep an accessory when a device answers without its service list
|
|
16
|
+
- fix: cancel a garage door's settle timer when homebridge shuts down
|
|
17
|
+
- fix: wait for the manually configured devices before reporting which ones failed to connect
|
|
18
|
+
- fix: reject an interval so large it would make the plugin poll every millisecond
|
|
15
19
|
|
|
16
20
|
## v7.7.0 (2026-08-02)
|
|
17
21
|
|
package/config.schema.json
CHANGED
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"title": "Discovery Interval",
|
|
43
43
|
"description": "An interval (in seconds) in which the plugin will broadcast on your network to initally find devices and repair connection errors. Must be 15 or more.",
|
|
44
44
|
"placeholder": 30,
|
|
45
|
-
"minimum": 15
|
|
45
|
+
"minimum": 15,
|
|
46
|
+
"maximum": 2073600
|
|
46
47
|
},
|
|
47
48
|
"wemoClient": {
|
|
48
49
|
"title": "Discovery Settings",
|
|
@@ -87,14 +88,16 @@
|
|
|
87
88
|
"title": "HTTP Polling Interval",
|
|
88
89
|
"description": "An interval (in seconds) in which the plugin will request status updates for devices that don't support UPnP or have it manually disabled. Must be 15 or more.",
|
|
89
90
|
"placeholder": 30,
|
|
90
|
-
"minimum": 15
|
|
91
|
+
"minimum": 15,
|
|
92
|
+
"maximum": 2073600
|
|
91
93
|
},
|
|
92
94
|
"upnpInterval": {
|
|
93
95
|
"type": "integer",
|
|
94
96
|
"title": "UPnP Subscription Interval",
|
|
95
97
|
"description": "An interval (in seconds) in which the plugin will resubscribe to UPnP notifications. Must be 60 or more.",
|
|
96
98
|
"placeholder": 300,
|
|
97
|
-
"minimum": 60
|
|
99
|
+
"minimum": 60,
|
|
100
|
+
"maximum": 2073600
|
|
98
101
|
},
|
|
99
102
|
"disableUPNP": {
|
|
100
103
|
"type": "boolean",
|
|
@@ -162,6 +165,7 @@
|
|
|
162
165
|
"description": "The time in seconds for how long it takes the garage door to open/close. Must be 1 or more.",
|
|
163
166
|
"placeholder": 20,
|
|
164
167
|
"minimum": 1,
|
|
168
|
+
"maximum": 2073600,
|
|
165
169
|
"condition": {
|
|
166
170
|
"functionBody": "return (model.makerTypes && model.makerTypes[arrayIndices] && model.makerTypes[arrayIndices].makerType === 'garageDoor' && !model.makerTypes[arrayIndices].ignoreDevice);"
|
|
167
171
|
}
|
|
@@ -252,6 +256,7 @@
|
|
|
252
256
|
"description": "The plugin will not log device wattage if the time difference (in seconds) from the previous value is less than this number. Must be 1 or more.",
|
|
253
257
|
"placeholder": 1,
|
|
254
258
|
"minimum": 1,
|
|
259
|
+
"maximum": 2073600,
|
|
255
260
|
"condition": {
|
|
256
261
|
"functionBody": "return (model.wemoInsights && model.wemoInsights[arrayIndices] && model.wemoInsights[arrayIndices].serialNumber && model.wemoInsights[arrayIndices].serialNumber.length > 0 && !model.wemoInsights[arrayIndices].ignoreDevice);"
|
|
257
262
|
}
|
|
@@ -492,6 +497,7 @@
|
|
|
492
497
|
"description": "A timer (in seconds) for how long after motion is not detected that the state is changed.",
|
|
493
498
|
"placeholder": 60,
|
|
494
499
|
"minimum": 0,
|
|
500
|
+
"maximum": 2073600,
|
|
495
501
|
"condition": {
|
|
496
502
|
"functionBody": "return (model.wemoMotions && model.wemoMotions[arrayIndices] && model.wemoMotions[arrayIndices].serialNumber && model.wemoMotions[arrayIndices].serialNumber.length > 0 && !model.wemoMotions[arrayIndices].ignoreDevice);"
|
|
497
503
|
}
|
package/lib/platform.js
CHANGED
|
@@ -100,6 +100,9 @@ export default class {
|
|
|
100
100
|
const logIncrease = (k, min) => {
|
|
101
101
|
this.log.warn('%s [%s] %s %s.', platformLang.cfgItem, k, platformLang.cfgLow, min)
|
|
102
102
|
}
|
|
103
|
+
const logDecrease = (k, max) => {
|
|
104
|
+
this.log.warn('%s [%s] %s %s.', platformLang.cfgItem, k, platformLang.cfgHigh, max)
|
|
105
|
+
}
|
|
103
106
|
const logQuotes = (k) => {
|
|
104
107
|
this.log.warn('%s [%s] %s.', platformLang.cfgItem, k, platformLang.cfgQts)
|
|
105
108
|
}
|
|
@@ -133,6 +136,9 @@ export default class {
|
|
|
133
136
|
} else if (intVal < platformConsts.minValues[key]) {
|
|
134
137
|
logIncrease(key, platformConsts.minValues[key])
|
|
135
138
|
this.config[key] = platformConsts.minValues[key]
|
|
139
|
+
} else if (platformConsts.maxValues[key] !== undefined && intVal > platformConsts.maxValues[key]) {
|
|
140
|
+
logDecrease(key, platformConsts.maxValues[key])
|
|
141
|
+
this.config[key] = platformConsts.maxValues[key]
|
|
136
142
|
} else {
|
|
137
143
|
this.config[key] = intVal
|
|
138
144
|
}
|
|
@@ -187,6 +193,9 @@ export default class {
|
|
|
187
193
|
} else if (intVal < platformConsts.minValues[k]) {
|
|
188
194
|
logIncrease(`${key}.${id}.${k}`, platformConsts.minValues[k])
|
|
189
195
|
this.deviceConf[id][k] = platformConsts.minValues[k]
|
|
196
|
+
} else if (platformConsts.maxValues[k] !== undefined && intVal > platformConsts.maxValues[k]) {
|
|
197
|
+
logDecrease(`${key}.${id}.${k}`, platformConsts.maxValues[k])
|
|
198
|
+
this.deviceConf[id][k] = platformConsts.maxValues[k]
|
|
190
199
|
} else {
|
|
191
200
|
this.deviceConf[id][k] = intVal
|
|
192
201
|
}
|
|
@@ -531,6 +540,13 @@ export default class {
|
|
|
531
540
|
if (accessory.control?.pollingInterval) {
|
|
532
541
|
clearInterval(accessory.control.pollingInterval)
|
|
533
542
|
}
|
|
543
|
+
// A garage door part-way through opening or closing has a timer waiting to
|
|
544
|
+
// write its settled state. That was left running, so it fired against a
|
|
545
|
+
// torn-down accessory and held the process open until it did.
|
|
546
|
+
if (accessory.control?.movingTimer) {
|
|
547
|
+
clearTimeout(accessory.control.movingTimer)
|
|
548
|
+
accessory.control.movingTimer = false
|
|
549
|
+
}
|
|
534
550
|
if (accessory.client) {
|
|
535
551
|
accessory.client.stopSubscriptions()
|
|
536
552
|
}
|
|
@@ -648,7 +664,15 @@ export default class {
|
|
|
648
664
|
// *************************** \\
|
|
649
665
|
// Manually Configured Devices \\
|
|
650
666
|
// *************************** \\
|
|
651
|
-
|
|
667
|
+
// Awaited, unlike the `forEach(async ...)` this used to be, which threw the
|
|
668
|
+
// promises away. The "still awaiting" warning further down then ran before
|
|
669
|
+
// these probes had finished, so a manually configured device that was about
|
|
670
|
+
// to connect could be reported as one that had not.
|
|
671
|
+
// Still concurrent rather than a for..of loop, because each entry is an
|
|
672
|
+
// independent port scan and running them one after another would drag out
|
|
673
|
+
// discovery. Each callback keeps its own try/catch, so one failure cannot
|
|
674
|
+
// reject the whole batch.
|
|
675
|
+
await Promise.all(this.manualDevices.map(async (device) => {
|
|
652
676
|
try {
|
|
653
677
|
// Check to see if the entry is a full address or an IP
|
|
654
678
|
let deviceIP
|
|
@@ -703,7 +727,7 @@ export default class {
|
|
|
703
727
|
this.log.warn('[%s] %s: %s.', device, platformLang.connError, eText)
|
|
704
728
|
}
|
|
705
729
|
}
|
|
706
|
-
})
|
|
730
|
+
}))
|
|
707
731
|
|
|
708
732
|
// ************************ \\
|
|
709
733
|
// Erroneous Device Logging \\
|
|
@@ -842,10 +866,15 @@ export default class {
|
|
|
842
866
|
}
|
|
843
867
|
})
|
|
844
868
|
} else {
|
|
845
|
-
// Device has no services so
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
869
|
+
// Device has no services so cannot be set up on this run.
|
|
870
|
+
//
|
|
871
|
+
// The cached accessory used to be unregistered here. A setup document
|
|
872
|
+
// that arrives truncated, or from a device part-way through a reboot,
|
|
873
|
+
// parses fine but has no serviceList - and one of those was enough to
|
|
874
|
+
// take the accessory out of HomeKit along with its room, its scenes and
|
|
875
|
+
// any automations using it. A later restart brings it back as a brand new
|
|
876
|
+
// accessory, so none of that comes back with it. Leave it alone: it shows
|
|
877
|
+
// as No Response until the device answers properly again.
|
|
849
878
|
throw new Error(platformLang.noServices)
|
|
850
879
|
}
|
|
851
880
|
|
package/lib/utils/constants.js
CHANGED
|
@@ -44,6 +44,20 @@ export default {
|
|
|
44
44
|
wattDiff: 1,
|
|
45
45
|
},
|
|
46
46
|
|
|
47
|
+
// A Node timer holds its delay in a signed 32-bit integer. Over 2147483647 ms
|
|
48
|
+
// it does not throw - it quietly becomes 1 ms, so any of these set past that
|
|
49
|
+
// point would fire a thousand times a second rather than slowly. 2073600
|
|
50
|
+
// seconds is 24 days, comfortably inside the limit once multiplied up.
|
|
51
|
+
maxValues: {
|
|
52
|
+
discoveryInterval: 2073600,
|
|
53
|
+
doorOpenTimer: 2073600,
|
|
54
|
+
makerTimer: 2073600,
|
|
55
|
+
noMotionTimer: 2073600,
|
|
56
|
+
pollingInterval: 2073600,
|
|
57
|
+
timeDiff: 2073600,
|
|
58
|
+
upnpInterval: 2073600,
|
|
59
|
+
},
|
|
60
|
+
|
|
47
61
|
minValues: {
|
|
48
62
|
adaptiveLightingShift: -1,
|
|
49
63
|
discoveryInterval: 15,
|
package/lib/utils/lang-en.js
CHANGED
|
@@ -12,6 +12,7 @@ export default {
|
|
|
12
12
|
cfgIgn: 'is not configured correctly so ignoring',
|
|
13
13
|
cfgIgnItem: 'has an invalid entry which will be ignored',
|
|
14
14
|
cfgItem: 'Config entry',
|
|
15
|
+
cfgHigh: 'is set too high so reducing to',
|
|
15
16
|
cfgLow: 'is set too low so increasing to',
|
|
16
17
|
cfgRmv: 'is unused and can be removed',
|
|
17
18
|
cfgQts: 'should not have quotes around its entry',
|
package/package.json
CHANGED