iobroker.smartfriends 1.2.0 → 1.3.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 CHANGED
@@ -33,6 +33,11 @@ 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.3.0 (2026-01-11)
37
+
38
+ - (Black-Thunder) Support for further device types was added
39
+ - (Black-Thunder) Umlauts in device names are now correctly parsed
40
+
36
41
  ### 1.2.0 (2026-01-09)
37
42
 
38
43
  - (Black-Thunder) Timeout for initial device request was increased
package/io-package.json CHANGED
@@ -1,11 +1,24 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "smartfriends",
4
- "version": "1.2.0",
4
+ "version": "1.3.0",
5
5
  "news": {
6
+ "1.3.0": {
7
+ "en": "Support for further device types was added\nUmlauts in device names are now correctly parsed",
8
+ "de": "Unterstützung für weitere Gerätetypen wurde hinzugefügt\nUmlaute in Gerätenamen werden nun korrekt dargestellt",
9
+ "ru": "Добавлена поддержка дополнительных типов устройств\nУмлауты в названиях устройств теперь правильно разобраны",
10
+ "pt": "Foi adicionado suporte para outros tipos de dispositivos\nUmlauts em nomes de dispositivos agora são corretamente analisados",
11
+ "nl": "Ondersteuning voor andere apparaattypes is toegevoegd\nUmlauts in apparaatnamen zijn nu correct ontleed",
12
+ "fr": "Un soutien pour d'autres types d'appareils a été ajouté\nUmlauts dans les noms de périphériques sont maintenant correctement analysés",
13
+ "it": "È stato aggiunto il supporto per ulteriori tipi di dispositivo\nI nomi dei dispositivi sono ora correttamente analizzati",
14
+ "es": "Se agregó soporte para nuevos tipos de dispositivos\nUmlauts en los nombres de los dispositivos ahora se analizan correctamente",
15
+ "pl": "Dodano wsparcie dla innych typów urządzeń\nKlauty w nazwach urządzeń są teraz poprawnie przefiltrowane",
16
+ "uk": "Додана підтримка подальших типів пристроїв\nУмлаути в назвах пристроїв тепер правильно припаровані",
17
+ "zh-cn": "添加了对更多设备类型的支持\n设备名称中的 Umlaut 现已正确解析"
18
+ },
6
19
  "1.2.0": {
7
20
  "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",
21
+ "de": "Timeout für erste Geräteanfrage wurde erhöht\nGeräte ohne definierten Gerätetyp werden ignoriert\nVerarbeitung der Geräte wurde überarbeitet und Unterstützung für weitere Gerätetypen hinzugefügt",
9
22
  "ru": "Время ожидания первоначального запроса устройства было увеличено\nУстройства без определенного типа устройства игнорируются\nРефакторированная обработка устройств и дополнительная поддержка для других типов устройств",
10
23
  "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
24
  "nl": "Tijdslimiet voor het eerste apparaatverzoek werd verhoogd\nApparaten zonder gedefinieerd apparaattype worden genegeerd\nRefactored device handling en toegevoegde ondersteuning voor andere apparaattypes",
@@ -16,48 +29,9 @@
16
29
  "uk": "Підвищено запит на початковий пристрій\nПристрої без визначеного типу пристрою ігноруються\nРефакторний пристрій обробки та додано підтримку для подальших типів пристроїв",
17
30
  "zh-cn": "初始设备请求的超时增加\n没有定义设备类型的设备会被忽略\n对设备类型进行重构处理并添加支持"
18
31
  },
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
- },
32
- "1.2.0-alpha.0": {
33
- "en": "Refactored device handling and added support for further device types",
34
- "de": "Refactored Device Handling und zusätzliche Unterstützung für weitere Gerätetypen",
35
- "ru": "Рефакторированная обработка устройств и дополнительная поддержка для других типов устройств",
36
- "pt": "Manipulação do dispositivo refatorizado e suporte adicional para outros tipos de dispositivo",
37
- "nl": "Refactored device handling en toegevoegde ondersteuning voor andere apparaattypes",
38
- "fr": "Manipulation de l'appareil refactoré et support supplémentaire pour d'autres types d'appareil",
39
- "it": "Gestione del dispositivo e supporto aggiunto per ulteriori tipi di dispositivo",
40
- "es": "Manejo de dispositivo refactorizado y soporte añadido para nuevos tipos de dispositivos",
41
- "pl": "Zmieniona obsługa urządzenia i dodana obsługa dla innych typów urządzeń",
42
- "uk": "Рефакторний пристрій обробки та додано підтримку для подальших типів пристроїв",
43
- "zh-cn": "对设备类型进行重构处理并添加支持"
44
- },
45
32
  "1.1.0": {
46
33
  "en": "Refactored device handling: dynamic states, removed type whitelist, grouped devices under master ID\nHandle device value updates now correctly",
47
- "de": "Refactored Device Handling: dynamische Zustände, entfernte Typ Whitelist, gruppierte Geräte unter Master ID\nGerätewert-Updates jetzt korrekt ausschalten",
48
- "ru": "Рефакторированная обработка устройств: динамические состояния, удаленный белый список типов, сгруппированные устройства под идентификатором Master ID\nОбновления стоимости устройства теперь правильно",
49
- "pt": "Manipulação do dispositivo refatorado: estados dinâmicos, lista branca do tipo removido, dispositivos agrupados sob ID mestre\nGerenciar as atualizações de valor do dispositivo agora corretamente",
50
- "nl": "Refactored device handling: dynamische toestanden, verwijderd type whitelist, gegroepeerde apparaten onder master ID\nHandle apparaat waarde updates nu correct",
51
- "fr": "Manipulation de l'appareil refacturé : états dynamiques, liste blanche de type enlevé, dispositifs groupés sous Master ID\nGérer les mises à jour de la valeur du périphérique maintenant correctement",
52
- "it": "Movimentazione del dispositivo refattore: stati dinamici, tipo rimosso whitelist, dispositivi raggruppati sotto master ID\nMantenere gli aggiornamenti del valore del dispositivo ora correttamente",
53
- "es": "Manejo de dispositivo refactorizado: estados dinámicos, lista blanca de tipo eliminado, dispositivos agrupados bajo ID maestro\nActualizaciones de valor del dispositivo manual ahora correctamente",
54
- "pl": "Przekształcona obsługa urządzenia: stany dynamiczne, usunięty biały typ, zgrupowane urządzenia pod master ID\nUchwyt aktualizacji wartości urządzenia teraz poprawnie",
55
- "uk": "Рефакторний пристрій обробки: динамічні стани, видалений тип білий список, вбудовані пристрої під магістр ID\nОновлення значення ручного пристрою тепер правильно",
56
- "zh-cn": "重构设备处理: 动态状态, 删除类型白名单, 主 ID 下分组设备\n现在正确处理设备值更新"
57
- },
58
- "1.1.0-alpha.1": {
59
- "en": "Refactored device handling: dynamic states, removed type whitelist, grouped devices under master ID\nHandle device value updates now correctly",
60
- "de": "Refactored Device Handling: dynamische Zustände, entfernte Typ Whitelist, gruppierte Geräte unter Master ID\nGerätewert-Updates jetzt korrekt ausschalten",
34
+ "de": "Verarbeitung der Geräte wurde überarbeitet: dynamische Zustände, Whitelist von Gerätetypen entfernt, Geräte werden nun unter Master ID gruppiert\nGerätewert-Updates werden jetzt korrekt behandelt",
61
35
  "ru": "Рефакторированная обработка устройств: динамические состояния, удаленный белый список типов, сгруппированные устройства под идентификатором Master ID\nОбновления стоимости устройства теперь правильно",
62
36
  "pt": "Manipulação do dispositivo refatorado: estados dinâmicos, lista branca do tipo removido, dispositivos agrupados sob ID mestre\nGerenciar as atualizações de valor do dispositivo agora corretamente",
63
37
  "nl": "Refactored device handling: dynamische toestanden, verwijderd type whitelist, gegroepeerde apparaten onder master ID\nHandle apparaat waarde updates nu correct",
@@ -68,22 +42,9 @@
68
42
  "uk": "Рефакторний пристрій обробки: динамічні стани, видалений тип білий список, вбудовані пристрої під магістр ID\nОновлення значення ручного пристрою тепер правильно",
69
43
  "zh-cn": "重构设备处理: 动态状态, 删除类型白名单, 主 ID 下分组设备\n现在正确处理设备值更新"
70
44
  },
71
- "1.1.0-alpha.0": {
72
- "en": "Refactored device handling: dynamic states, removed type whitelist, grouped devices under master ID",
73
- "de": "Überarbeitete Geräteverwaltung: dynamische Zustände, entfernte Typ-Whitelist, gruppierte Geräte unter Master-ID",
74
- "ru": "Рефакторированная обработка устройств: динамические состояния, удаленный белый список типов, сгруппированные устройства под идентификатором Master ID",
75
- "pt": "Manipulação do dispositivo refatorado: estados dinâmicos, lista branca do tipo removido, dispositivos agrupados sob ID mestre",
76
- "nl": "Refactored device handling: dynamische toestanden, verwijderd type whitelist, gegroepeerde apparaten onder master ID",
77
- "fr": "Manipulation de l'appareil refacturé : états dynamiques, liste blanche de type enlevé, dispositifs groupés sous Master ID",
78
- "it": "Movimentazione del dispositivo refattore: stati dinamici, tipo rimosso whitelist, dispositivi raggruppati sotto master ID",
79
- "es": "Manejo de dispositivo refactorizado: estados dinámicos, lista blanca de tipo eliminado, dispositivos agrupados bajo ID maestro",
80
- "pl": "Przekształcona obsługa urządzenia: stany dynamiczne, usunięty biały typ, zgrupowane urządzenia pod master ID",
81
- "uk": "Рефакторний пристрій обробки: динамічні стани, видалений тип білий список, вбудовані пристрої під магістр ID",
82
- "zh-cn": "重构设备处理: 动态状态, 删除类型白名单, 主 ID 下分组设备"
83
- },
84
- "1.0.1": {
45
+ "1.0.1": {
85
46
  "en": "Increased robustness when communicating with the gateway\nAdded new option to ignore certificate errors",
86
- "de": "Erhöhte Robustheit bei der Kommunikation mit dem Gateway\nNeue Option hinzugefügt, um Zertifikatsfehler zu ignorieren",
47
+ "de": "Robustheit der Kommunikation mit dem Gateway erhöht\nNeue Option hinzugefügt, um Zertifikatsfehler zu ignorieren",
87
48
  "ru": "Повышенная надежность при общении с шлюзом\nДобавлена новая возможность игнорировать ошибки сертификата",
88
49
  "pt": "Maior robustez ao se comunicar com o gateway\nAdicionada nova opção para ignorar erros de certificado",
89
50
  "nl": "Verhoogde robuustheid bij het communiceren met de gateway\nNieuwe optie toegevoegd om certificaatfouten te negeren",
@@ -93,6 +54,19 @@
93
54
  "pl": "Większa odporność podczas komunikacji z bramą\nDodano nową opcję do ignorowania błędów certyfikatu",
94
55
  "uk": "Підвищена надійність при спілкуванні з шлюзом\nДодано новий варіант ігнорувати помилки сертифіката",
95
56
  "zh-cn": "与网关沟通时的强度提高\n添加新选项以忽略证书错误"
57
+ },
58
+ "1.0.0": {
59
+ "en": "initial release",
60
+ "de": "Erstveröffentlichung",
61
+ "ru": "Начальная версия",
62
+ "pt": "lançamento inicial",
63
+ "nl": "Eerste uitgave",
64
+ "fr": "Première version",
65
+ "it": "Versione iniziale",
66
+ "es": "Versión inicial",
67
+ "pl": "Pierwsze wydanie",
68
+ "zh-cn": "首次出版",
69
+ "uk": "початковий випуск"
96
70
  }
97
71
  },
98
72
  "titleLang": {
@@ -29,13 +29,21 @@ const LevelKinds = {
29
29
  */
30
30
  const SensorKinds = {
31
31
  thermometer: {
32
- role: "level.temperature",
32
+ role: "value.temperature",
33
33
  desc: "Measured temperature",
34
34
  unit: "°C",
35
35
  defaultMin: -90,
36
36
  defaultMax: 60,
37
37
  defaultStep: 0.5,
38
38
  },
39
+ luminanceDetector: {
40
+ role: "value.brightness ",
41
+ desc: "Measured brightness",
42
+ unit: "lux",
43
+ defaultMin: 0,
44
+ defaultMax: 150000,
45
+ defaultStep: 1,
46
+ },
39
47
  volume: {
40
48
  role: "value.rain",
41
49
  desc: "Measured rain volume",
@@ -44,8 +52,18 @@ const SensorKinds = {
44
52
  defaultMax: 350,
45
53
  defaultStep: 1,
46
54
  },
47
- // generic sensor kind for different types of weather sensors (e.g. atmospheric pressure, wind speed, etc.)
48
- weather: {
55
+ batteryLevel: {
56
+ role: "value.battery",
57
+ desc: "Battery level",
58
+ unit: "%",
59
+ defaultMin: 0,
60
+ defaultMax: 100,
61
+ defaultStep: 1,
62
+ },
63
+ // some devices are defined as "kind": "default", so this is a fallback
64
+ // generic sensor kind for different types of sensors (e.g. atmospheric pressure, wind speed, etc.)
65
+ genericSensor: {
66
+ kind: "measuredValue",
49
67
  role: "value",
50
68
  desc: "Measured value",
51
69
  unit: "",
@@ -54,17 +72,50 @@ const SensorKinds = {
54
72
 
55
73
  /**
56
74
  * Declarative registry for device kinds that provide
57
- * an alarm information
75
+ * an enumerated information
58
76
  */
59
- const AlarmKinds = {
77
+ const EnumStateKinds = {
60
78
  failureStatus: {
61
79
  role: "value",
62
80
  desc: "Error code of the device",
63
81
  },
82
+ smokeDetector: {
83
+ role: "sensor.alarm.fire",
84
+ desc: "Smoke detector state",
85
+ },
86
+ signal: {
87
+ kind: "rssi", // rename to make the purpose of the state clearer
88
+ role: "value",
89
+ desc: "Signal strength (RSSI)",
90
+ },
91
+ floodDetector: {
92
+ role: "sensor.alarm.flood",
93
+ desc: "Flood detector state",
94
+ },
95
+ genericEnum: {
96
+ role: "value",
97
+ desc: "Enumerated state",
98
+ },
99
+ };
100
+
101
+ /**
102
+ * Declarative registry for device kinds that provide thermostat controls
103
+ */
104
+ const ThermostatKinds = {
105
+ thermostat: {
106
+ kind: "targetTemperature", // rename to make the purpose of the state clearer
107
+ role: "level.temperature",
108
+ desc: "Target temperature",
109
+ unit: "°C",
110
+ defaultMin: 5,
111
+ defaultMax: 28,
112
+ defaultStep: 0.5,
113
+ },
64
114
  };
65
115
 
66
116
  module.exports = {
67
- AlarmKinds,
68
117
  LevelKinds,
69
118
  SensorKinds,
119
+ EnumStateKinds,
120
+ ThermostatKinds,
70
121
  };
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
- const { LevelKinds, SensorKinds, AlarmKinds } = require("./DeviceCapabilityRegistry");
3
+ const { resolveEnumKind } = require("./EnumKindResolver");
4
+ const { LevelKinds, SensorKinds, EnumStateKinds, ThermostatKinds } = require("./DeviceCapabilityRegistry");
4
5
 
5
6
  /**
6
7
  * Resolves capabilities from a SmartFriends device definition
@@ -10,76 +11,104 @@ function getDeviceCapabilities(definition) {
10
11
  return {
11
12
  shouldBeCreated: false,
12
13
  hasWritableStates: false,
13
- hasSwitchingValues: false,
14
- hasLevel: false,
15
- hasSensor: false,
16
- hasAlarm: false,
17
14
  configObj: null,
18
15
  };
19
16
  }
20
17
 
21
- const deviceType = definition?.deviceType ?? {};
18
+ const deviceType = definition.deviceType;
22
19
  const kind = deviceType.kind ?? "unknown";
23
- const deviceDesignation = definition?.deviceDesignation?.replace(/\${|}/g, "") ?? kind;
24
20
  const model = deviceType.model ?? "unknown";
21
+ const type = deviceType.type;
22
+ const name = (definition.deviceDesignation ?? kind).replace(/\${|}/g, "");
23
+ const configObj = { kind, name };
25
24
 
25
+ // SwitchingValues → always win
26
26
  const switchingValues = Array.isArray(deviceType.switchingValues) ? deviceType.switchingValues : [];
27
-
28
27
  const hasSwitchingValues = switchingValues.length > 0;
29
- let configObj = {
30
- kind,
31
- name: deviceDesignation,
32
- };
33
28
 
29
+ // Level actuators
34
30
  const levelConfig = LevelKinds[kind] ?? null;
35
- const sensorConfig = (SensorKinds[kind] && model == "analog") ?? null; // only sensor type "analog" contains measurable values
36
- const alarmConfig = AlarmKinds[kind] ?? null;
31
+
32
+ // Thermostat
33
+ const thermostatConfig = type === "actuator" && model === "analog" ? (ThermostatKinds[kind] ?? null) : null;
34
+
35
+ // Analog sensors
36
+ let sensorConfig = null;
37
+ if (type === "sensor" && model === "analog") {
38
+ if (SensorKinds[kind]) {
39
+ // Known sensor kind
40
+ sensorConfig = SensorKinds[kind];
41
+ } else if (kind === "default") {
42
+ // Generic fallback fo default kind
43
+ sensorConfig = SensorKinds.genericSensor;
44
+ }
45
+ }
46
+
47
+ // Enum sensors (textOptions)
48
+ let enumStateConfig = null;
49
+ if (
50
+ type === "sensor" &&
51
+ model === "text" &&
52
+ Array.isArray(deviceType.textOptions) &&
53
+ deviceType.textOptions.some(opt => opt && typeof opt === "object" && "name" in opt)
54
+ ) {
55
+ const enumKind = resolveEnumKind(definition, deviceType);
56
+ enumStateConfig = EnumStateKinds[enumKind] ?? EnumStateKinds.genericEnum;
57
+ }
37
58
 
38
59
  if (levelConfig) {
39
- configObj = {
40
- ...configObj,
60
+ Object.assign(configObj, {
61
+ kind: levelConfig.kind ?? configObj.kind,
41
62
  role: levelConfig.role,
42
63
  desc: levelConfig.desc,
43
64
  unit: levelConfig.unit,
44
65
  min: deviceType.min ?? levelConfig.defaultMin,
45
66
  max: deviceType.max ?? levelConfig.defaultMax,
46
67
  step: deviceType.step ?? levelConfig.defaultStep,
47
- };
68
+ });
69
+ } else if (thermostatConfig) {
70
+ Object.assign(configObj, {
71
+ kind: thermostatConfig.kind ?? configObj.kind,
72
+ role: thermostatConfig.role,
73
+ desc: thermostatConfig.desc,
74
+ unit: thermostatConfig.unit,
75
+ min: deviceType.min ?? thermostatConfig.defaultMin,
76
+ max: deviceType.max ?? thermostatConfig.defaultMax,
77
+ step: deviceType.step ?? thermostatConfig.defaultStep,
78
+ });
48
79
  } else if (sensorConfig) {
49
- configObj = {
50
- ...configObj,
80
+ Object.assign(configObj, {
81
+ kind: sensorConfig.kind ?? configObj.kind,
51
82
  role: sensorConfig.role,
52
83
  desc: sensorConfig.desc,
53
84
  unit: sensorConfig.unit,
54
85
  min: deviceType.min ?? sensorConfig.defaultMin,
55
86
  max: deviceType.max ?? sensorConfig.defaultMax,
56
87
  step: deviceType.step ?? sensorConfig.defaultStep,
57
- };
58
- } else if (alarmConfig) {
59
- configObj = {
60
- ...configObj,
61
- role: alarmConfig.role,
62
- desc: alarmConfig.desc,
63
- };
64
-
65
- // map "textOptions" (if present) into configObj as enumerated states
66
- if (deviceType.textOptions && Array.isArray(deviceType.textOptions) && deviceType.textOptions.length > 0) {
67
- configObj.states = deviceType.textOptions.reduce((acc, opt) => {
68
- acc[opt.value] = `${opt.state} (${opt.name.replace(/\${|}/g, "")})`;
88
+ });
89
+ } else if (enumStateConfig) {
90
+ Object.assign(configObj, {
91
+ kind: enumStateConfig.kind ?? configObj.kind,
92
+ role: enumStateConfig.role,
93
+ desc: enumStateConfig.desc,
94
+ states: deviceType.textOptions.reduce((acc, opt) => {
95
+ acc[opt.value] = opt.name.replace(/\${|}/g, "");
69
96
  return acc;
70
- }, {});
71
- }
97
+ }, {}),
98
+ });
72
99
  }
73
100
 
74
101
  return {
75
102
  // state creation decision
76
- shouldBeCreated: hasSwitchingValues || !!levelConfig || !!sensorConfig || !!alarmConfig,
77
- hasWritableStates: hasSwitchingValues || !!levelConfig,
103
+ shouldBeCreated:
104
+ hasSwitchingValues || !!levelConfig || !!thermostatConfig || !!sensorConfig || !!enumStateConfig,
105
+ hasWritableStates: hasSwitchingValues || !!levelConfig || !!thermostatConfig,
78
106
  // metadata for builders
79
107
  hasSwitchingValues,
80
108
  hasLevel: !!levelConfig,
109
+ hasThermostat: !!thermostatConfig,
81
110
  hasSensor: !!sensorConfig,
82
- hasAlarm: !!alarmConfig,
111
+ hasEnumState: !!enumStateConfig,
83
112
  // config object for state creation
84
113
  configObj: configObj,
85
114
  };
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Resolves semantic enum type for devices with
5
+ * model=text + textOptions
6
+ */
7
+ function resolveEnumKind(definition, deviceType) {
8
+ const designation = definition.deviceDesignation ?? "";
9
+ const kind = definition.kind ?? "";
10
+ const options = deviceType.textOptions ?? [];
11
+
12
+ // RSSI / signal strength
13
+ if (designation.includes("Rssi")) {
14
+ return "signal";
15
+ }
16
+
17
+ // Failure status
18
+ if (kind.includes("failureStatus")) {
19
+ return "failureStatus";
20
+ }
21
+
22
+ // Smoke detector
23
+ if (options.some(o => /smoke/i.test(o.valueState ?? ""))) {
24
+ return "smokeDetector";
25
+ }
26
+
27
+ // Flood / water
28
+ if (options.some(o => /water|flood/i.test(o.valueState ?? ""))) {
29
+ return "floodDetector";
30
+ }
31
+
32
+ return "genericEnum";
33
+ }
34
+
35
+ module.exports = {
36
+ resolveEnumKind,
37
+ };
@@ -26,10 +26,12 @@ class SchellenbergDevice {
26
26
 
27
27
  devicePrefix = devicePrefix.replace(this.adapter.FORBIDDEN_CHARS, "");
28
28
 
29
+ // Umlauts are Unicode-escaped and need to be parsed here
30
+ const rawName = this.name.replace(/\${|}/g, "");
29
31
  await this.adapter.setObjectNotExistsAsync(devicePrefix, {
30
32
  type: "channel",
31
33
  common: {
32
- name: this.name,
34
+ name: JSON.parse(`"${rawName.replace(/\\\\/g, "\\")}"`),
33
35
  },
34
36
  native: {},
35
37
  });
@@ -92,8 +94,8 @@ class SchellenbergDevice {
92
94
  await this.createSensorState(infoPrefix, capabilities.configObj);
93
95
  }
94
96
 
95
- if (capabilities.hasAlarm) {
96
- await this.createAlarmState(infoPrefix, capabilities.configObj);
97
+ if (capabilities.hasEnumState) {
98
+ await this.createEnumState(infoPrefix, capabilities.configObj);
97
99
  }
98
100
  //#endregion
99
101
 
@@ -118,6 +120,10 @@ class SchellenbergDevice {
118
120
  if (capabilities.hasLevel) {
119
121
  await this.createLevelState(controlPrefix, capabilities.configObj);
120
122
  }
123
+
124
+ if (capabilities.hasThermostat) {
125
+ await this.createThermostatState(controlPrefix, capabilities.configObj);
126
+ }
121
127
  }
122
128
  //#endregion
123
129
 
@@ -168,6 +174,25 @@ class SchellenbergDevice {
168
174
  });
169
175
  }
170
176
 
177
+ async createThermostatState(statePrefix, thermostatConfigObj) {
178
+ await this.adapter.setObjectNotExistsAsync(`${statePrefix}${thermostatConfigObj.kind}`, {
179
+ type: "state",
180
+ common: {
181
+ name: thermostatConfigObj.kind,
182
+ desc: thermostatConfigObj.desc,
183
+ type: "number",
184
+ role: thermostatConfigObj.role,
185
+ read: true,
186
+ write: true,
187
+ min: thermostatConfigObj.min,
188
+ max: thermostatConfigObj.max,
189
+ step: thermostatConfigObj.step,
190
+ unit: thermostatConfigObj.unit,
191
+ },
192
+ native: {},
193
+ });
194
+ }
195
+
171
196
  async createSensorState(statePrefix, sensorConfigObj) {
172
197
  await this.adapter.setObjectNotExistsAsync(`${statePrefix}${sensorConfigObj.kind}`, {
173
198
  type: "state",
@@ -188,17 +213,17 @@ class SchellenbergDevice {
188
213
  });
189
214
  }
190
215
 
191
- async createAlarmState(statePrefix, alarmConfigObj) {
192
- await this.adapter.setObjectNotExistsAsync(`${statePrefix}${alarmConfigObj.kind}`, {
216
+ async createEnumState(statePrefix, enumConfigObj) {
217
+ await this.adapter.setObjectNotExistsAsync(`${statePrefix}${enumConfigObj.kind}`, {
193
218
  type: "state",
194
219
  common: {
195
- name: alarmConfigObj.kind,
196
- desc: alarmConfigObj.desc,
220
+ name: enumConfigObj.kind,
221
+ desc: enumConfigObj.desc,
197
222
  type: "number",
198
- role: alarmConfigObj.role,
223
+ role: enumConfigObj.role,
199
224
  read: true,
200
225
  write: false,
201
- states: alarmConfigObj.states,
226
+ states: enumConfigObj.states,
202
227
  },
203
228
  native: {},
204
229
  });
@@ -253,15 +278,11 @@ class SchellenbergDevice {
253
278
  return;
254
279
  }
255
280
 
256
- if (capabilities.hasLevel) {
281
+ if (capabilities.hasLevel || capabilities.hasThermostat) {
257
282
  await this.setDeviceStateValue(controlPrefix, capabilities.configObj, value);
258
283
  }
259
284
 
260
- if (capabilities.hasSensor) {
261
- await this.setDeviceStateValue(infoPrefix, capabilities.configObj, value);
262
- }
263
-
264
- if (capabilities.hasAlarm) {
285
+ if (capabilities.hasSensor || capabilities.hasEnumState) {
265
286
  await this.setDeviceStateValue(infoPrefix, capabilities.configObj, value);
266
287
  }
267
288
  }
@@ -10,9 +10,12 @@ class SchellenbergMasterDevice {
10
10
 
11
11
  async createMasterFolder() {
12
12
  const masterPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id.replace(this.adapter.FORBIDDEN_CHARS, "")}`;
13
+
14
+ // Umlauts are Unicode-escaped and need to be parsed here
15
+ const rawName = this.name.replace(/\${|}/g, "");
13
16
  await this.adapter.setObjectNotExistsAsync(masterPrefix, {
14
17
  type: "channel",
15
- common: { name: this.name },
18
+ common: { name: JSON.parse(`"${rawName.replace(/\\\\/g, "\\")}"`) },
16
19
  native: {},
17
20
  });
18
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.smartfriends",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "smartfriends",
5
5
  "author": {
6
6
  "name": "Black-Thunder",