iobroker.smartfriends 1.2.0-alpha.0 → 1.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 +3 -1
- package/io-package.json +27 -14
- package/lib/SchellenbergBridge.js +8 -4
- package/lib/comunication/CommandFactory.js +1 -1
- package/lib/comunication/SmartSocket.js +18 -10
- package/lib/comunication/SmartSocketFactory.js +2 -2
- package/lib/comunication/comModel/JSONCommand.js +4 -1
- package/lib/devices/DeviceKindCapabilities.js +12 -0
- package/lib/helpers/Deferred.js +10 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,8 +33,10 @@ The adapter establishes a direct connection to the gateway to control and query
|
|
|
33
33
|
Placeholder for the next version (at the beginning of the line):
|
|
34
34
|
### __WORK IN PROGRESS__
|
|
35
35
|
-->
|
|
36
|
-
### 1.2.0
|
|
36
|
+
### 1.2.0 (2026-01-09)
|
|
37
37
|
|
|
38
|
+
- (Black-Thunder) Timeout for initial device request was increased
|
|
39
|
+
- (Black-Thunder) Devices without defined device type are ignored
|
|
38
40
|
- (Black-Thunder) Refactored device handling and added support for further device types
|
|
39
41
|
|
|
40
42
|
### 1.1.0 (2025-12-28)
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "smartfriends",
|
|
4
|
-
"version": "1.2.0
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.2.0": {
|
|
7
|
+
"en": "Timeout for initial device request was increased\nDevices without defined device type are ignored\nRefactored device handling and added support for further device types",
|
|
8
|
+
"de": "Timeout für erste Geräteanfrage wurde erhöht\nGeräte ohne definierten Gerätetyp werden ignoriert\nRefactored Device Handling und zusätzliche Unterstützung für weitere Gerätetypen",
|
|
9
|
+
"ru": "Время ожидания первоначального запроса устройства было увеличено\nУстройства без определенного типа устройства игнорируются\nРефакторированная обработка устройств и дополнительная поддержка для других типов устройств",
|
|
10
|
+
"pt": "O tempo limite para a solicitação inicial do dispositivo foi aumentado\nOs dispositivos sem tipo de dispositivo definido são ignorados\nManipulação do dispositivo refatorizado e suporte adicional para outros tipos de dispositivo",
|
|
11
|
+
"nl": "Tijdslimiet voor het eerste apparaatverzoek werd verhoogd\nApparaten zonder gedefinieerd apparaattype worden genegeerd\nRefactored device handling en toegevoegde ondersteuning voor andere apparaattypes",
|
|
12
|
+
"fr": "Le délai pour la demande initiale d'appareil a été augmenté\nLes dispositifs sans type défini sont ignorés\nManipulation de l'appareil refactoré et support supplémentaire pour d'autres types d'appareil",
|
|
13
|
+
"it": "Timeout per la richiesta iniziale del dispositivo è stato aumentato\nI dispositivi senza tipo di dispositivo definito vengono ignorati\nGestione del dispositivo e supporto aggiunto per ulteriori tipi di dispositivo",
|
|
14
|
+
"es": "Se aumentó el tiempo para la solicitud inicial del dispositivo\nLos dispositivos sin tipo de dispositivo definido son ignorados\nManejo de dispositivo refactorizado y soporte añadido para nuevos tipos de dispositivos",
|
|
15
|
+
"pl": "Zwiększono czas na początkowe żądanie urządzenia\nUrządzenia bez określonego typu urządzenia są ignorowane\nZmieniona obsługa urządzenia i dodana obsługa dla innych typów urządzeń",
|
|
16
|
+
"uk": "Підвищено запит на початковий пристрій\nПристрої без визначеного типу пристрою ігноруються\nРефакторний пристрій обробки та додано підтримку для подальших типів пристроїв",
|
|
17
|
+
"zh-cn": "初始设备请求的超时增加\n没有定义设备类型的设备会被忽略\n对设备类型进行重构处理并添加支持"
|
|
18
|
+
},
|
|
19
|
+
"1.2.0-alpha.1": {
|
|
20
|
+
"en": "Timeout for initial device request was increased\nDevices without defined device type are ignored",
|
|
21
|
+
"de": "Timeout für erste Geräteanfrage wurde erhöht\nGeräte ohne definierten Gerätetyp werden ignoriert",
|
|
22
|
+
"ru": "Время ожидания первоначального запроса устройства было увеличено\nУстройства без определенного типа устройства игнорируются",
|
|
23
|
+
"pt": "O tempo limite para a solicitação inicial do dispositivo foi aumentado\nOs dispositivos sem tipo de dispositivo definido são ignorados",
|
|
24
|
+
"nl": "Tijdslimiet voor het eerste apparaatverzoek werd verhoogd\nApparaten zonder gedefinieerd apparaattype worden genegeerd",
|
|
25
|
+
"fr": "Le délai pour la demande initiale d'appareil a été augmenté\nLes dispositifs sans type défini sont ignorés",
|
|
26
|
+
"it": "Timeout per la richiesta iniziale del dispositivo è stato aumentato\nI dispositivi senza tipo di dispositivo definito vengono ignorati",
|
|
27
|
+
"es": "Se aumentó el tiempo para la solicitud inicial del dispositivo\nLos dispositivos sin tipo de dispositivo definido son ignorados",
|
|
28
|
+
"pl": "Zwiększono czas na początkowe żądanie urządzenia\nUrządzenia bez określonego typu urządzenia są ignorowane",
|
|
29
|
+
"uk": "Підвищено запит на початковий пристрій\nПристрої без визначеного типу пристрою ігноруються",
|
|
30
|
+
"zh-cn": "初始设备请求的超时增加\n没有定义设备类型的设备会被忽略"
|
|
31
|
+
},
|
|
6
32
|
"1.2.0-alpha.0": {
|
|
7
33
|
"en": "Refactored device handling and added support for further device types",
|
|
8
34
|
"de": "Refactored Device Handling und zusätzliche Unterstützung für weitere Gerätetypen",
|
|
@@ -67,19 +93,6 @@
|
|
|
67
93
|
"pl": "Większa odporność podczas komunikacji z bramą\nDodano nową opcję do ignorowania błędów certyfikatu",
|
|
68
94
|
"uk": "Підвищена надійність при спілкуванні з шлюзом\nДодано новий варіант ігнорувати помилки сертифіката",
|
|
69
95
|
"zh-cn": "与网关沟通时的强度提高\n添加新选项以忽略证书错误"
|
|
70
|
-
},
|
|
71
|
-
"1.0.0": {
|
|
72
|
-
"en": "initial release",
|
|
73
|
-
"de": "Erstveröffentlichung",
|
|
74
|
-
"ru": "Начальная версия",
|
|
75
|
-
"pt": "lançamento inicial",
|
|
76
|
-
"nl": "Eerste uitgave",
|
|
77
|
-
"fr": "Première version",
|
|
78
|
-
"it": "Versione iniziale",
|
|
79
|
-
"es": "Versión inicial",
|
|
80
|
-
"pl": "Pierwsze wydanie",
|
|
81
|
-
"zh-cn": "首次出版",
|
|
82
|
-
"uk": "початковий випуск"
|
|
83
96
|
}
|
|
84
97
|
},
|
|
85
98
|
"titleLang": {
|
|
@@ -64,7 +64,7 @@ class SchellenbergBridge {
|
|
|
64
64
|
this.compatibilityConfigurationVersion,
|
|
65
65
|
this.languageTranslationVersion,
|
|
66
66
|
);
|
|
67
|
-
const response = await this.socket.
|
|
67
|
+
const response = await this.socket.sendAndReceiveCommand(command, this.loginResponse.sessionID);
|
|
68
68
|
|
|
69
69
|
if (!response?.response) {
|
|
70
70
|
return;
|
|
@@ -180,16 +180,20 @@ class SchellenbergBridge {
|
|
|
180
180
|
// 3️⃣ Child-Devices unter Master anlegen
|
|
181
181
|
for (const child of childDevices) {
|
|
182
182
|
// Nur Devices mit definierbaren States
|
|
183
|
-
const capabilities = getDeviceCapabilities(child.definition);
|
|
184
183
|
this.adapter.log.debug(
|
|
185
|
-
`
|
|
184
|
+
`Getting device capabilites from definition: ${JSON.stringify(child.definition)}`,
|
|
186
185
|
);
|
|
186
|
+
const capabilities = getDeviceCapabilities(child.definition);
|
|
187
187
|
|
|
188
188
|
if (!capabilities.shouldBeCreated) {
|
|
189
189
|
this.adapter.log.debug(
|
|
190
190
|
`Skipping device ${child.deviceName} (${child.deviceDesignation}) – no definable states found`,
|
|
191
191
|
);
|
|
192
192
|
continue;
|
|
193
|
+
} else {
|
|
194
|
+
this.adapter.log.debug(
|
|
195
|
+
`Device ${child.deviceID}: kind=${child.definition.deviceType.kind}, capabilities=${JSON.stringify(capabilities)}`,
|
|
196
|
+
);
|
|
193
197
|
}
|
|
194
198
|
|
|
195
199
|
const schellenbergDevice = await this.deviceManager.createDevice({
|
|
@@ -397,7 +401,7 @@ class SchellenbergBridge {
|
|
|
397
401
|
|
|
398
402
|
sendAndReceiveCommand(command) {
|
|
399
403
|
if (this.socket && this.loginResponse && this.loginResponse.sessionID) {
|
|
400
|
-
return this.socket.
|
|
404
|
+
return this.socket.sendAndReceiveCommand(command, this.loginResponse.sessionID);
|
|
401
405
|
}
|
|
402
406
|
|
|
403
407
|
this.adapter.log.error("Login to the gateway was not successful yet. Ignoring command.");
|
|
@@ -70,7 +70,7 @@ exports.LoginCommand = LoginCommand;
|
|
|
70
70
|
|
|
71
71
|
class allNewInfoCommand extends JSONCommand.default {
|
|
72
72
|
constructor(timestamp, compatibilityConfigurationVersion, languageTranslationVersion) {
|
|
73
|
-
super("getAllNewInfos");
|
|
73
|
+
super("getAllNewInfos", 15000); // higher timeout as this command might take longer to receive a response
|
|
74
74
|
this.timestamp = timestamp;
|
|
75
75
|
this.compatibilityConfigurationVersion = compatibilityConfigurationVersion;
|
|
76
76
|
this.languageTranslationVersion = languageTranslationVersion;
|
|
@@ -169,16 +169,24 @@ class SmartSocket {
|
|
|
169
169
|
//sends command and waits for receive in the promise queue of the message handler
|
|
170
170
|
//don't know if the output socket of the gateway is in-order, so maybe there needs
|
|
171
171
|
//to be some checking
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
172
|
+
sendAndReceiveCommand(command, sessionkey) {
|
|
173
|
+
const timeout = command.timeout ?? 5000; // default timeout is 5 sec
|
|
174
|
+
|
|
175
|
+
const localPromise = new Deferred.default(
|
|
176
|
+
this.adapter,
|
|
177
|
+
(resolve, reject) => {
|
|
178
|
+
if (this.internalSocket && command) {
|
|
179
|
+
this.adapter.log.debug(
|
|
180
|
+
`Send and receive JSON (timeout: ${timeout}ms): ${command.toString(sessionkey)}`,
|
|
181
|
+
);
|
|
182
|
+
this.internalSocket.write(command.toString(sessionkey));
|
|
183
|
+
this.internalSocket.write("\n");
|
|
184
|
+
} else {
|
|
185
|
+
reject();
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
timeout,
|
|
189
|
+
);
|
|
182
190
|
if (this.dataDelegate) {
|
|
183
191
|
this.dataDelegate.queueUpPromise(localPromise);
|
|
184
192
|
}
|
|
@@ -35,7 +35,7 @@ class SmartSocketFactory {
|
|
|
35
35
|
.then(socket => {
|
|
36
36
|
if (socket) {
|
|
37
37
|
socket
|
|
38
|
-
.
|
|
38
|
+
.sendAndReceiveCommand(CommandFactory.default.createHeloCmd(username))
|
|
39
39
|
.then(responseHelo => {
|
|
40
40
|
if (responseHelo.response) {
|
|
41
41
|
const parsedResponseHelo = HeloResponse.default.fromObject(
|
|
@@ -52,7 +52,7 @@ class SmartSocketFactory {
|
|
|
52
52
|
parsedResponseHelo.sessionSalt,
|
|
53
53
|
);
|
|
54
54
|
socket
|
|
55
|
-
.
|
|
55
|
+
.sendAndReceiveCommand(
|
|
56
56
|
CommandFactory.default.createLoginCommand(
|
|
57
57
|
username,
|
|
58
58
|
digest,
|
|
@@ -8,13 +8,16 @@
|
|
|
8
8
|
//--------------------------------------------------
|
|
9
9
|
|
|
10
10
|
class JSONCommand {
|
|
11
|
-
constructor(method) {
|
|
11
|
+
constructor(method, timeoutMs = 5000) {
|
|
12
12
|
this.command = method;
|
|
13
|
+
this.timeout = timeoutMs;
|
|
13
14
|
}
|
|
15
|
+
|
|
14
16
|
toString(sessionID) {
|
|
15
17
|
if (sessionID) {
|
|
16
18
|
this.sessionID = sessionID;
|
|
17
19
|
}
|
|
20
|
+
|
|
18
21
|
return JSON.stringify(this);
|
|
19
22
|
}
|
|
20
23
|
}
|
|
@@ -6,6 +6,18 @@ const { LevelKinds, SensorKinds, AlarmKinds } = require("./DeviceCapabilityRegis
|
|
|
6
6
|
* Resolves capabilities from a SmartFriends device definition
|
|
7
7
|
*/
|
|
8
8
|
function getDeviceCapabilities(definition) {
|
|
9
|
+
if (!definition?.deviceType) {
|
|
10
|
+
return {
|
|
11
|
+
shouldBeCreated: false,
|
|
12
|
+
hasWritableStates: false,
|
|
13
|
+
hasSwitchingValues: false,
|
|
14
|
+
hasLevel: false,
|
|
15
|
+
hasSensor: false,
|
|
16
|
+
hasAlarm: false,
|
|
17
|
+
configObj: null,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
9
21
|
const deviceType = definition?.deviceType ?? {};
|
|
10
22
|
const kind = deviceType.kind ?? "unknown";
|
|
11
23
|
const deviceDesignation = definition?.deviceDesignation?.replace(/\${|}/g, "") ?? kind;
|
package/lib/helpers/Deferred.js
CHANGED
|
@@ -10,30 +10,38 @@
|
|
|
10
10
|
//--------------------------------------------------
|
|
11
11
|
|
|
12
12
|
class Deferred {
|
|
13
|
-
constructor(adapter, executor) {
|
|
13
|
+
constructor(adapter, executor, timeoutMs = 5000) {
|
|
14
14
|
this.adapter = adapter;
|
|
15
|
+
|
|
15
16
|
this.timeout = this.adapter.setTimeout(() => {
|
|
16
17
|
this.reject("timeout");
|
|
17
|
-
},
|
|
18
|
+
}, timeoutMs);
|
|
19
|
+
|
|
18
20
|
this.promise = new Promise((resolve, reject) => {
|
|
19
21
|
this._resolveSelf = resolve;
|
|
20
22
|
this._rejectSelf = reject;
|
|
21
23
|
});
|
|
24
|
+
|
|
22
25
|
executor.call(this, this._resolveSelf, this._rejectSelf);
|
|
23
26
|
}
|
|
27
|
+
|
|
24
28
|
then(onfulfilled, onrejected) {
|
|
25
29
|
return this.promise.then(onfulfilled, onrejected);
|
|
26
30
|
}
|
|
31
|
+
|
|
27
32
|
catch(onrejected) {
|
|
28
33
|
return this.promise.then(onrejected);
|
|
29
34
|
}
|
|
35
|
+
|
|
30
36
|
finally(onfinally) {
|
|
31
37
|
return this.promise.finally(onfinally);
|
|
32
38
|
}
|
|
39
|
+
|
|
33
40
|
resolve(val) {
|
|
34
41
|
this.adapter.clearTimeout(this.timeout);
|
|
35
42
|
this._resolveSelf(val);
|
|
36
43
|
}
|
|
44
|
+
|
|
37
45
|
reject(reason) {
|
|
38
46
|
this.adapter.clearTimeout(this.timeout);
|
|
39
47
|
this._rejectSelf(reason);
|