iobroker.zigbee2mqtt 2.1.0 → 2.2.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.
- package/README.md +12 -1
- package/io-package.json +27 -13
- package/lib/check.js +30 -30
- package/lib/colors.js +442 -443
- package/lib/deviceController.js +235 -222
- package/lib/exposes.js +867 -859
- package/lib/messages.js +31 -31
- package/lib/mqttServerController.js +30 -30
- package/lib/nonGenericDevicesExtension.js +47 -0
- package/lib/rgb.js +227 -203
- package/lib/states.js +6374 -6374
- package/lib/statesController.js +129 -129
- package/lib/utils.js +82 -82
- package/lib/websocketController.js +58 -58
- package/lib/z2mController.js +69 -64
- package/main.js +202 -194
- package/package.json +3 -3
package/lib/statesController.js
CHANGED
|
@@ -3,136 +3,136 @@ const incStatsQueue = [];
|
|
|
3
3
|
const timeOutCache = {};
|
|
4
4
|
|
|
5
5
|
class StatesController {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
6
|
+
constructor(adapter, deviceCache, groupCache, logCustomizations) {
|
|
7
|
+
this.adapter = adapter;
|
|
8
|
+
this.groupCache = groupCache;
|
|
9
|
+
this.deviceCache = deviceCache;
|
|
10
|
+
this.logCustomizations = logCustomizations;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
processDeviceMessage(messageObj) {
|
|
14
|
+
// Is payload present?
|
|
15
|
+
if (messageObj.payload == '') {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const device = this.groupCache.concat(this.deviceCache).find(x => x.id == messageObj.topic);
|
|
20
|
+
if (device) {
|
|
21
|
+
try {
|
|
22
|
+
this.setDeviceStateSafely(messageObj, device);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
this.adapter.log.error(error);
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
incStatsQueue[incStatsQueue.length] = messageObj;
|
|
28
|
+
this.adapter.log.debug(`Device: ${messageObj.topic} not found, queue state in incStatsQueue!`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async setDeviceStateSafely(messageObj, device) {
|
|
33
|
+
if (this.logCustomizations.debugDevices.includes(device.ieee_address)) {
|
|
34
|
+
this.adapter.log.warn(`--->>> fromZ2M -> ${device.ieee_address} states: ${JSON.stringify(messageObj)}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const [key, value] of Object.entries(messageObj.payload)) {
|
|
38
|
+
let states;
|
|
39
|
+
if (key == 'action') {
|
|
40
|
+
states = device.states.filter(x => (x.prop && x.prop == key));
|
|
41
|
+
} else {
|
|
42
|
+
states = device.states.filter(x => (x.prop && x.prop == key) || x.id == key);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (const state of states) {
|
|
46
|
+
if (!state) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const stateName = `${device.ieee_address}.${state.id}`;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
if (state.isEvent) {
|
|
54
|
+
if (state.getter) {
|
|
55
|
+
await this.setStateWithTimeoutAsync(stateName, state.getter(messageObj.payload), 300);
|
|
56
|
+
} else {
|
|
57
|
+
await this.setStateWithTimeoutAsync(stateName, value, 300);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
if (state.getter) {
|
|
61
|
+
await this.setStateChangedSafelyAsync(stateName, state.getter(messageObj.payload));
|
|
62
|
+
} else {
|
|
63
|
+
await this.setStateChangedSafelyAsync(stateName, value);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch (err) {
|
|
67
|
+
incStatsQueue[incStatsQueue.length] = messageObj;
|
|
68
|
+
this.adapter.log.debug(`Can not set ${stateName}, queue state in incStatsQueue!`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async setStateSafelyAsync(stateName, value) {
|
|
75
|
+
if (value !== undefined) {
|
|
76
|
+
await this.adapter.setStateAsync(stateName, value, true);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async setStateChangedSafelyAsync(stateName, value) {
|
|
81
|
+
if (value !== undefined) {
|
|
82
|
+
await this.adapter.setStateChangedAsync(stateName, value, true);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async setStateWithTimeoutAsync(stateName, value, timeout) {
|
|
87
|
+
if (value !== undefined) {
|
|
88
|
+
await this.adapter.setStateAsync(stateName, value, true);
|
|
89
|
+
if (timeOutCache[stateName]) {
|
|
90
|
+
clearTimeout(timeOutCache[stateName]);
|
|
91
|
+
}
|
|
92
|
+
timeOutCache[stateName] = setTimeout(() => {
|
|
93
|
+
this.adapter.setStateAsync(stateName, !value, true);
|
|
94
|
+
}, timeout);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
processQueue() {
|
|
99
|
+
const oldIncStatsQueue = [];
|
|
100
|
+
utils.moveArray(incStatsQueue, oldIncStatsQueue);
|
|
101
|
+
while (oldIncStatsQueue.length > 0) {
|
|
102
|
+
this.processDeviceMessage(oldIncStatsQueue.shift());
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async subscribeWritableStates() {
|
|
107
|
+
await this.adapter.unsubscribeObjectsAsync('*');
|
|
108
|
+
for (const device of this.groupCache.concat(this.deviceCache)) {
|
|
109
|
+
for (const state of device.states) {
|
|
110
|
+
if (state.write == true) {
|
|
111
|
+
this.adapter.subscribeStatesAsync(`${device.ieee_address}.${state.id}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
this.adapter.subscribeStatesAsync('info.debugmessages');
|
|
116
|
+
this.adapter.subscribeStatesAsync('info.logfilter');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async setAllAvailableToFalse() {
|
|
120
|
+
for (const device of this.deviceCache) {
|
|
121
|
+
for (const state of device.states) {
|
|
122
|
+
if (state.id == 'available') {
|
|
123
|
+
await this.adapter.setStateChangedAsync(`${device.ieee_address}.${state.id}`, false, true);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async allTimerClear() {
|
|
130
|
+
for (const timer in timeOutCache) {
|
|
131
|
+
clearTimeout(timeOutCache[timer]);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
module.exports = {
|
|
137
|
-
|
|
137
|
+
StatesController
|
|
138
138
|
};
|
package/lib/utils.js
CHANGED
|
@@ -2,132 +2,132 @@
|
|
|
2
2
|
* Converts a bulb level of range [0...254] to an adapter level of range [0...100]
|
|
3
3
|
*/
|
|
4
4
|
function bulbLevelToAdapterLevel(bulbLevel) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
5
|
+
// Convert from bulb levels [0...254] to adapter levels [0...100]:
|
|
6
|
+
// - Bulb level 0 is a forbidden value according to the ZigBee spec "ZigBee Cluster Library
|
|
7
|
+
// (for ZigBee 3.0) User Guide", but some bulbs (HUE) accept this value and interpret this
|
|
8
|
+
// value as "switch the bulb off".
|
|
9
|
+
// - A bulb level of "1" is the "minimum possible level" which should mean "bulb off",
|
|
10
|
+
// but there are bulbs that do not switch off (they need "0", some IKEA bulbs are affected).
|
|
11
|
+
// - No visible difference was seen between bulb level 1 and 2 on HUE LCT012 bulbs.
|
|
12
|
+
//
|
|
13
|
+
// Conclusion:
|
|
14
|
+
// - We map adapter level "0" to the (forbidden) bulb level "0" that seems to switch all
|
|
15
|
+
// known bulbs.
|
|
16
|
+
// - Bulb level "1" is not used, but if received nevertheless, it is converted to
|
|
17
|
+
// adapter level "0" (off).
|
|
18
|
+
// - Bulb level range [2...254] is linearly mapped to adapter level range [1...100].
|
|
19
|
+
if (bulbLevel >= 2) {
|
|
20
|
+
// Perform linear mapping of range [2...254] to [1...100]
|
|
21
|
+
return (Math.round((bulbLevel - 2) * 99 / 252) + 1);
|
|
22
|
+
} else {
|
|
23
|
+
// The bulb is considered off. Even a bulb level of "1" is considered as off.
|
|
24
|
+
return 0;
|
|
25
|
+
} // else
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Converts an adapter level of range [0...100] to a bulb level of range [0...254]
|
|
30
30
|
*/
|
|
31
31
|
function adapterLevelToBulbLevel(adapterLevel) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
32
|
+
// Convert from adapter levels [0...100] to bulb levels [0...254].
|
|
33
|
+
// This is the inverse of function bulbLevelToAdapterLevel().
|
|
34
|
+
// Please read the comments there regarding the rules applied here for mapping the values.
|
|
35
|
+
if (adapterLevel) {
|
|
36
|
+
// Perform linear mapping of range [1...100] to [2...254]
|
|
37
|
+
return (Math.round((adapterLevel - 1) * 252 / 99) + 2);
|
|
38
|
+
} else {
|
|
39
|
+
// Switch the bulb off. Some bulbs need "0" (IKEA), others "1" (HUE), and according to the
|
|
40
|
+
// ZigBee docs "1" is the "minimum possible level"... we choose "0" here which seems to work.
|
|
41
|
+
return 0;
|
|
42
|
+
} // else
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
function bytesArrayToWordArray(ba) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
const wa = [];
|
|
47
|
+
for (let i = 0; i < ba.length; i++) {
|
|
48
|
+
wa[(i / 2) | 0] |= ba[i] << (8 * (i % 2));
|
|
49
|
+
}
|
|
50
|
+
return wa;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// If the value is greater than 1000, kelvin is assumed.
|
|
54
54
|
// If smaller, it is assumed to be mired.
|
|
55
55
|
function toMired(t) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
let miredValue = t;
|
|
57
|
+
if (t > 1000) {
|
|
58
|
+
miredValue = miredKelvinConversion(t);
|
|
59
|
+
}
|
|
60
|
+
return miredValue;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
function miredKelvinConversion(t) {
|
|
64
|
-
|
|
64
|
+
return Math.round(1000000 / t);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
68
|
* Converts a decimal number to a hex string with zero-padding
|
|
69
69
|
*/
|
|
70
70
|
function decimalToHex(decimal, padding) {
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
let hex = Number(decimal).toString(16);
|
|
72
|
+
padding = typeof (padding) === 'undefined' || padding === null ? padding = 2 : padding;
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
while (hex.length < padding) {
|
|
75
|
+
hex = `0${hex}`;
|
|
76
|
+
}
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
return hex;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
function getZbId(adapterDevId) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
const idx = adapterDevId.indexOf('group');
|
|
83
|
+
if (idx > 0) return adapterDevId.substr(idx + 6);
|
|
84
|
+
return '0x' + adapterDevId.split('.')[2];
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
function getAdId(adapter, id) {
|
|
88
|
-
|
|
88
|
+
return adapter.namespace + '.' + id.split('.')[2]; // iobroker device id
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
function sanitizeImageParameter(parameter) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
const replaceByDash = [/\?/g, /&/g, /[^a-z\d\-_./:]/gi, /[/]/gi];
|
|
93
|
+
let sanitized = parameter;
|
|
94
|
+
replaceByDash.forEach((r) => sanitized = sanitized.replace(r, '-'));
|
|
95
|
+
return sanitized;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
function getDeviceIcon(definition) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
let icon = definition.icon;
|
|
100
|
+
if (icon) {
|
|
101
|
+
icon = icon.replace('${model}', sanitizeImageParameter(definition.model));
|
|
102
|
+
}
|
|
103
|
+
if (!icon) {
|
|
104
|
+
icon = `https://www.zigbee2mqtt.io/images/devices/${sanitizeImageParameter(definition.model)}.jpg`;
|
|
105
|
+
}
|
|
106
|
+
return icon;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
function clearArray(array) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
while (array.length > 0) {
|
|
111
|
+
array.pop();
|
|
112
|
+
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
function moveArray(source, target) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
while (source.length > 0) {
|
|
117
|
+
target.push(source.shift());
|
|
118
|
+
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
module.exports = {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
122
|
+
bulbLevelToAdapterLevel,
|
|
123
|
+
adapterLevelToBulbLevel,
|
|
124
|
+
bytesArrayToWordArray,
|
|
125
|
+
toMired,
|
|
126
|
+
miredKelvinConversion,
|
|
127
|
+
decimalToHex,
|
|
128
|
+
getZbId,
|
|
129
|
+
getAdId,
|
|
130
|
+
getDeviceIcon,
|
|
131
|
+
clearArray,
|
|
132
|
+
moveArray,
|
|
133
133
|
};
|
|
@@ -7,78 +7,78 @@ let pingTimeout;
|
|
|
7
7
|
let autoRestartTimeout;
|
|
8
8
|
|
|
9
9
|
class WebsocketController {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
constructor(adapter) {
|
|
11
|
+
this.adapter = adapter;
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
initWsClient() {
|
|
15
|
+
try {
|
|
16
|
+
wsClient = new WebSocket(`ws://${this.adapter.config.wsServerIP}:${this.adapter.config.wsServerPort}/api`);
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
wsClient.on('open', () => {
|
|
19
|
+
// Send ping to server
|
|
20
|
+
this.sendPingToServer();
|
|
21
|
+
// Start Heartbeat
|
|
22
|
+
this.wsHeartbeat();
|
|
23
|
+
});
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
wsClient.on('pong', () => {
|
|
26
|
+
this.wsHeartbeat();
|
|
27
|
+
});
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
wsClient.on('close', async () => {
|
|
30
|
+
clearTimeout(pingTimeout);
|
|
31
|
+
clearTimeout(ping);
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
if (wsClient.readyState === WebSocket.CLOSED) {
|
|
34
|
+
this.autoRestart();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
wsClient.on('message', () => { });
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
wsClient.on('error', (err) => { this.adapter.log.debug(err); });
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
return wsClient;
|
|
43
|
+
} catch (err) {
|
|
44
|
+
this.adapter.log.error(err);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
send(message) {
|
|
49
|
+
wsClient.send(message);
|
|
50
|
+
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
sendPingToServer() {
|
|
53
|
+
//this.logDebug('Send ping to server');
|
|
54
|
+
wsClient.ping();
|
|
55
|
+
ping = setTimeout(() => {
|
|
56
|
+
this.sendPingToServer();
|
|
57
|
+
}, wsHeartbeatIntervall);
|
|
58
|
+
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
wsHeartbeat() {
|
|
61
|
+
clearTimeout(pingTimeout);
|
|
62
|
+
pingTimeout = setTimeout(() => {
|
|
63
|
+
this.adapter.log.warn('Websocked connection timed out');
|
|
64
|
+
wsClient.terminate();
|
|
65
|
+
}, wsHeartbeatIntervall + 1000);
|
|
66
|
+
}
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
async autoRestart() {
|
|
69
|
+
this.adapter.log.warn(`Start try again in ${restartTimeout / 1000} seconds...`);
|
|
70
|
+
autoRestartTimeout = setTimeout(() => {
|
|
71
|
+
this.adapter.startWebsocket();
|
|
72
|
+
}, restartTimeout);
|
|
73
|
+
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
async allTimerClear() {
|
|
76
|
+
clearTimeout(pingTimeout);
|
|
77
|
+
clearTimeout(ping);
|
|
78
|
+
clearTimeout(autoRestartTimeout);
|
|
79
|
+
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
module.exports = {
|
|
83
|
-
|
|
83
|
+
WebsocketController
|
|
84
84
|
};
|