iobroker.smartfriends 1.1.0-alpha.1 → 1.2.0-alpha.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Black-Thunder <glwars@aol.de>
3
+ Copyright (c) 2025-2026 Black-Thunder <glwars@aol.de>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -20,8 +20,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
22
 
23
-
24
- -------------------------------------------------------------------------------
23
+ ---
25
24
 
26
25
  LoPablo/SchellenbergApi (https://github.com/LoPablo/SchellenbergApi)
27
26
 
package/README.md CHANGED
@@ -33,7 +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.1.0-alpha.1 (2025-12-28)
36
+ ### 1.2.0-alpha.0 (2026-01-02)
37
+
38
+ - (Black-Thunder) Refactored device handling and added support for further device types
39
+
40
+ ### 1.1.0 (2025-12-28)
37
41
 
38
42
  - (Black-Thunder) Refactored device handling: dynamic states, removed type whitelist, grouped devices under master ID
39
43
  - (Black-Thunder) Handle device value updates now correctly
@@ -55,7 +59,7 @@ Special thanks und credits to [LoPablo](https://github.com/LoPablo/SchellenbergA
55
59
 
56
60
  MIT License
57
61
 
58
- Copyright (c) 2025 Black-Thunder <glwars@aol.de>
62
+ Copyright (c) 2025-2026 Black-Thunder <glwars@aol.de>
59
63
 
60
64
  Permission is hereby granted, free of charge, to any person obtaining a copy
61
65
  of this software and associated documentation files (the "Software"), to deal
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "smartfriends",
4
- "version": "1.1.0-alpha.1",
4
+ "version": "1.2.0-alpha.0",
5
5
  "news": {
6
+ "1.2.0-alpha.0": {
7
+ "en": "Refactored device handling and added support for further device types",
8
+ "de": "Refactored Device Handling und zusätzliche Unterstützung für weitere Gerätetypen",
9
+ "ru": "Рефакторированная обработка устройств и дополнительная поддержка для других типов устройств",
10
+ "pt": "Manipulação do dispositivo refatorizado e suporte adicional para outros tipos de dispositivo",
11
+ "nl": "Refactored device handling en toegevoegde ondersteuning voor andere apparaattypes",
12
+ "fr": "Manipulation de l'appareil refactoré et support supplémentaire pour d'autres types d'appareil",
13
+ "it": "Gestione del dispositivo e supporto aggiunto per ulteriori tipi di dispositivo",
14
+ "es": "Manejo de dispositivo refactorizado y soporte añadido para nuevos tipos de dispositivos",
15
+ "pl": "Zmieniona obsługa urządzenia i dodana obsługa dla innych typów urządzeń",
16
+ "uk": "Рефакторний пристрій обробки та додано підтримку для подальших типів пристроїв",
17
+ "zh-cn": "对设备类型进行重构处理并添加支持"
18
+ },
19
+ "1.1.0": {
20
+ "en": "Refactored device handling: dynamic states, removed type whitelist, grouped devices under master ID\nHandle device value updates now correctly",
21
+ "de": "Refactored Device Handling: dynamische Zustände, entfernte Typ Whitelist, gruppierte Geräte unter Master ID\nGerätewert-Updates jetzt korrekt ausschalten",
22
+ "ru": "Рефакторированная обработка устройств: динамические состояния, удаленный белый список типов, сгруппированные устройства под идентификатором Master ID\nОбновления стоимости устройства теперь правильно",
23
+ "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",
24
+ "nl": "Refactored device handling: dynamische toestanden, verwijderd type whitelist, gegroepeerde apparaten onder master ID\nHandle apparaat waarde updates nu correct",
25
+ "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",
26
+ "it": "Movimentazione del dispositivo refattore: stati dinamici, tipo rimosso whitelist, dispositivi raggruppati sotto master ID\nMantenere gli aggiornamenti del valore del dispositivo ora correttamente",
27
+ "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",
28
+ "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",
29
+ "uk": "Рефакторний пристрій обробки: динамічні стани, видалений тип білий список, вбудовані пристрої під магістр ID\nОновлення значення ручного пристрою тепер правильно",
30
+ "zh-cn": "重构设备处理: 动态状态, 删除类型白名单, 主 ID 下分组设备\n现在正确处理设备值更新"
31
+ },
6
32
  "1.1.0-alpha.1": {
7
33
  "en": "Refactored device handling: dynamic states, removed type whitelist, grouped devices under master ID\nHandle device value updates now correctly",
8
34
  "de": "Refactored Device Handling: dynamische Zustände, entfernte Typ Whitelist, gruppierte Geräte unter Master ID\nGerätewert-Updates jetzt korrekt ausschalten",
@@ -12,6 +12,7 @@ const SmartSocketFactory = require("./comunication/SmartSocketFactory");
12
12
  const CommonDefines = require("./helpers/CommonDefines");
13
13
  const DeviceManager = require("./devices/DeviceManager");
14
14
  const { SchellenbergMasterDevice } = require("./devices/SchellenbergMasterDevice");
15
+ const { getDeviceCapabilities } = require("./devices/DeviceKindCapabilities");
15
16
 
16
17
  class SchellenbergBridge {
17
18
  constructor(adapter) {
@@ -170,25 +171,30 @@ class SchellenbergBridge {
170
171
 
171
172
  // 2️⃣ MasterDevices anlegen
172
173
  for (const [masterId, childDevices] of Object.entries(devicesByMaster)) {
173
- const masterName = childDevices[0].masterDeviceName || childDevices[0].deviceName;
174
+ const masterName = (childDevices[0].masterDeviceName || childDevices[0].deviceName).replace(
175
+ /\${|}/g,
176
+ "",
177
+ );
174
178
  const masterDevice = new SchellenbergMasterDevice(this.adapter, masterId, masterName, []);
175
179
 
176
180
  // 3️⃣ Child-Devices unter Master anlegen
177
181
  for (const child of childDevices) {
178
- // Nur Devices mit definierbaren Control-States
179
- const hasSwitching = child.definition.deviceType?.switchingValues?.length;
180
- const isPosition = child.definition.deviceType?.kind === commonDefines.AdapterStateIDs.Position;
182
+ // Nur Devices mit definierbaren States
183
+ const capabilities = getDeviceCapabilities(child.definition);
184
+ this.adapter.log.debug(
185
+ `Device ${child.deviceID}: kind=${child.definition.deviceType.kind}, capabilities=${JSON.stringify(capabilities)}`,
186
+ );
181
187
 
182
- if (!hasSwitching && !isPosition) {
188
+ if (!capabilities.shouldBeCreated) {
183
189
  this.adapter.log.debug(
184
- `Skipping device ${child.deviceName} (${child.deviceDesignation}) – no definable control states found`,
190
+ `Skipping device ${child.deviceName} (${child.deviceDesignation}) – no definable states found`,
185
191
  );
186
192
  continue;
187
193
  }
188
194
 
189
195
  const schellenbergDevice = await this.deviceManager.createDevice({
190
196
  id: child.deviceID,
191
- name: child.deviceName,
197
+ name: child.deviceName.replace(/\${|}/g, ""),
192
198
  deviceType: child.deviceTypClient ?? child.definition.deviceType?.kind ?? "unknown",
193
199
  designation: child.deviceDesignation,
194
200
  definition: child.definition,
@@ -258,11 +264,6 @@ class SchellenbergBridge {
258
264
  `Message received: ${parsedResponse.responseMessage} (code: ${parsedResponse.responseCode})`,
259
265
  );
260
266
 
261
- if (parsedResponse.currentTimestamp) {
262
- this.adapter.log.debug(`Updated timestamp to ${parsedResponse.currentTimestamp}`);
263
- this.lastTimestamp = parsedResponse.currentTimestamp;
264
- }
265
-
266
267
  this.handleResponseCode(parsedResponse);
267
268
  }
268
269
 
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Declarative registry for device kinds that provide
5
+ * a level-like control (position, brightness, etc.)
6
+ */
7
+ const LevelKinds = {
8
+ position: {
9
+ role: "level.blind",
10
+ desc: "Position of the device",
11
+ unit: "%",
12
+ defaultMin: 0,
13
+ defaultMax: 100,
14
+ defaultStep: 1,
15
+ },
16
+ brightness: {
17
+ role: "level.dimmer",
18
+ desc: "Brightness of the device",
19
+ unit: "%",
20
+ defaultMin: 0,
21
+ defaultMax: 100,
22
+ defaultStep: 1,
23
+ },
24
+ };
25
+
26
+ /**
27
+ * Declarative registry for device kinds that provide
28
+ * a sensor state information (temperature, rain, etc.)
29
+ */
30
+ const SensorKinds = {
31
+ thermometer: {
32
+ role: "level.temperature",
33
+ desc: "Measured temperature",
34
+ unit: "°C",
35
+ defaultMin: -90,
36
+ defaultMax: 60,
37
+ defaultStep: 0.5,
38
+ },
39
+ volume: {
40
+ role: "value.rain",
41
+ desc: "Measured rain volume",
42
+ unit: "mm",
43
+ defaultMin: 0,
44
+ defaultMax: 350,
45
+ defaultStep: 1,
46
+ },
47
+ // generic sensor kind for different types of weather sensors (e.g. atmospheric pressure, wind speed, etc.)
48
+ weather: {
49
+ role: "value",
50
+ desc: "Measured value",
51
+ unit: "",
52
+ },
53
+ };
54
+
55
+ /**
56
+ * Declarative registry for device kinds that provide
57
+ * an alarm information
58
+ */
59
+ const AlarmKinds = {
60
+ failureStatus: {
61
+ role: "value",
62
+ desc: "Error code of the device",
63
+ },
64
+ };
65
+
66
+ module.exports = {
67
+ AlarmKinds,
68
+ LevelKinds,
69
+ SensorKinds,
70
+ };
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ const { LevelKinds, SensorKinds, AlarmKinds } = require("./DeviceCapabilityRegistry");
4
+
5
+ /**
6
+ * Resolves capabilities from a SmartFriends device definition
7
+ */
8
+ function getDeviceCapabilities(definition) {
9
+ const deviceType = definition?.deviceType ?? {};
10
+ const kind = deviceType.kind ?? "unknown";
11
+ const deviceDesignation = definition?.deviceDesignation?.replace(/\${|}/g, "") ?? kind;
12
+ const model = deviceType.model ?? "unknown";
13
+
14
+ const switchingValues = Array.isArray(deviceType.switchingValues) ? deviceType.switchingValues : [];
15
+
16
+ const hasSwitchingValues = switchingValues.length > 0;
17
+ let configObj = {
18
+ kind,
19
+ name: deviceDesignation,
20
+ };
21
+
22
+ const levelConfig = LevelKinds[kind] ?? null;
23
+ const sensorConfig = (SensorKinds[kind] && model == "analog") ?? null; // only sensor type "analog" contains measurable values
24
+ const alarmConfig = AlarmKinds[kind] ?? null;
25
+
26
+ if (levelConfig) {
27
+ configObj = {
28
+ ...configObj,
29
+ role: levelConfig.role,
30
+ desc: levelConfig.desc,
31
+ unit: levelConfig.unit,
32
+ min: deviceType.min ?? levelConfig.defaultMin,
33
+ max: deviceType.max ?? levelConfig.defaultMax,
34
+ step: deviceType.step ?? levelConfig.defaultStep,
35
+ };
36
+ } else if (sensorConfig) {
37
+ configObj = {
38
+ ...configObj,
39
+ role: sensorConfig.role,
40
+ desc: sensorConfig.desc,
41
+ unit: sensorConfig.unit,
42
+ min: deviceType.min ?? sensorConfig.defaultMin,
43
+ max: deviceType.max ?? sensorConfig.defaultMax,
44
+ step: deviceType.step ?? sensorConfig.defaultStep,
45
+ };
46
+ } else if (alarmConfig) {
47
+ configObj = {
48
+ ...configObj,
49
+ role: alarmConfig.role,
50
+ desc: alarmConfig.desc,
51
+ };
52
+
53
+ // map "textOptions" (if present) into configObj as enumerated states
54
+ if (deviceType.textOptions && Array.isArray(deviceType.textOptions) && deviceType.textOptions.length > 0) {
55
+ configObj.states = deviceType.textOptions.reduce((acc, opt) => {
56
+ acc[opt.value] = `${opt.state} (${opt.name.replace(/\${|}/g, "")})`;
57
+ return acc;
58
+ }, {});
59
+ }
60
+ }
61
+
62
+ return {
63
+ // state creation decision
64
+ shouldBeCreated: hasSwitchingValues || !!levelConfig || !!sensorConfig || !!alarmConfig,
65
+ hasWritableStates: hasSwitchingValues || !!levelConfig,
66
+ // metadata for builders
67
+ hasSwitchingValues,
68
+ hasLevel: !!levelConfig,
69
+ hasSensor: !!sensorConfig,
70
+ hasAlarm: !!alarmConfig,
71
+ // config object for state creation
72
+ configObj: configObj,
73
+ };
74
+ }
75
+
76
+ module.exports = {
77
+ getDeviceCapabilities,
78
+ };
@@ -1,4 +1,4 @@
1
- const { SchellenbergDevice } = require("./SchellenbergDevice");
1
+ const SchellenbergDevice = require("./SchellenbergDevice");
2
2
  const commonDefines = require("../helpers/CommonDefines");
3
3
  const commandFactory = require("../comunication/CommandFactory");
4
4
 
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ const { getDeviceCapabilities } = require("./DeviceKindCapabilities");
3
4
  const commonDefines = require("../helpers/CommonDefines");
4
5
 
5
6
  class SchellenbergDevice {
@@ -16,6 +17,9 @@ class SchellenbergDevice {
16
17
 
17
18
  // Creates all necessery states and channels and writes the values into the DB
18
19
  async CreateAndSave(masterPrefix) {
20
+ // Dynamisch aus device.definition
21
+ const capabilities = getDeviceCapabilities(this.definition);
22
+
19
23
  let devicePrefix = masterPrefix
20
24
  ? `${masterPrefix}.${this.id}`
21
25
  : `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}`;
@@ -83,65 +87,121 @@ class SchellenbergDevice {
83
87
  },
84
88
  native: {},
85
89
  });
90
+
91
+ if (capabilities.hasSensor) {
92
+ await this.createSensorState(infoPrefix, capabilities.configObj);
93
+ }
94
+
95
+ if (capabilities.hasAlarm) {
96
+ await this.createAlarmState(infoPrefix, capabilities.configObj);
97
+ }
86
98
  //#endregion
87
99
 
88
100
  //#region CONTROL
89
- let controlPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Control}`;
101
+ if (capabilities.hasWritableStates) {
102
+ let controlPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Control}`;
90
103
 
91
- await this.adapter.setObjectNotExistsAsync(controlPrefix, {
92
- type: "channel",
93
- common: {
94
- name: "Device control",
95
- },
96
- native: {},
97
- });
104
+ await this.adapter.setObjectNotExistsAsync(controlPrefix, {
105
+ type: "channel",
106
+ common: {
107
+ name: "Device control",
108
+ },
109
+ native: {},
110
+ });
98
111
 
99
- controlPrefix += ".";
112
+ controlPrefix += ".";
100
113
 
101
- // Dynamisch aus device.definition
102
- if (this.definition?.deviceType?.switchingValues) {
103
- for (const stateDef of this.definition.deviceType.switchingValues) {
104
- const stateId = stateDef.name
105
- .replace(/\${|}/g, "") // ${On} → On
106
- .replace(this.adapter.FORBIDDEN_CHARS, "")
107
- .toLowerCase();
108
-
109
- await this.adapter.setObjectNotExistsAsync(`${controlPrefix}${stateId}`, {
110
- type: "state",
111
- common: {
112
- name: stateId,
113
- type: "boolean",
114
- role: "button",
115
- read: false,
116
- write: true,
117
- def: false,
118
- },
119
- native: {
120
- commandValue: stateDef.value,
121
- },
122
- });
114
+ if (capabilities.hasSwitchingValues) {
115
+ await this.createSwitchStates(controlPrefix);
123
116
  }
124
- } else if (this.definition.deviceType.kind === commonDefines.AdapterStateIDs.Position) {
125
- await this.adapter.setObjectNotExistsAsync(`${controlPrefix}${commonDefines.AdapterStateIDs.Position}`, {
117
+
118
+ if (capabilities.hasLevel) {
119
+ await this.createLevelState(controlPrefix, capabilities.configObj);
120
+ }
121
+ }
122
+ //#endregion
123
+
124
+ this.adapter.log.debug(`Created and saved device ${this.id} (${this.name})`);
125
+ }
126
+
127
+ async createSwitchStates(statePrefix) {
128
+ for (const stateDef of this.definition.deviceType.switchingValues) {
129
+ const stateId = stateDef.name
130
+ .replace(/\${|}/g, "") // ${On} → On
131
+ .replace(this.adapter.FORBIDDEN_CHARS, "")
132
+ .toLowerCase();
133
+
134
+ await this.adapter.setObjectNotExistsAsync(`${statePrefix}${stateId}`, {
126
135
  type: "state",
127
136
  common: {
128
- name: commonDefines.AdapterStateIDs.Position,
129
- type: "number",
130
- role: "level.blind",
131
- read: true,
137
+ name: stateId,
138
+ type: "boolean",
139
+ role: "button",
140
+ read: false,
132
141
  write: true,
133
- min: this.definition.deviceType.min ?? 0,
134
- max: this.definition.deviceType.max ?? 100,
135
- step: this.definition.deviceType.step ?? 1,
136
- unit: "%",
137
- def: 0,
142
+ def: false,
143
+ },
144
+ native: {
145
+ commandValue: stateDef.value,
138
146
  },
139
- native: {},
140
147
  });
141
148
  }
142
- //#endregion
149
+ }
143
150
 
144
- this.adapter.log.debug(`Created and saved device ${this.id} (${this.name})`);
151
+ async createLevelState(statePrefix, levelConfigObj) {
152
+ await this.adapter.setObjectNotExistsAsync(`${statePrefix}${levelConfigObj.kind}`, {
153
+ type: "state",
154
+ common: {
155
+ name: levelConfigObj.kind,
156
+ desc: levelConfigObj.desc,
157
+ type: "number",
158
+ role: levelConfigObj.role,
159
+ read: true,
160
+ write: true,
161
+ min: levelConfigObj.min,
162
+ max: levelConfigObj.max,
163
+ step: levelConfigObj.step,
164
+ unit: levelConfigObj.unit,
165
+ def: 0,
166
+ },
167
+ native: {},
168
+ });
169
+ }
170
+
171
+ async createSensorState(statePrefix, sensorConfigObj) {
172
+ await this.adapter.setObjectNotExistsAsync(`${statePrefix}${sensorConfigObj.kind}`, {
173
+ type: "state",
174
+ common: {
175
+ name: sensorConfigObj.kind,
176
+ desc: sensorConfigObj.desc,
177
+ type: "number",
178
+ role: sensorConfigObj.role,
179
+ read: true,
180
+ write: false,
181
+ min: sensorConfigObj.min,
182
+ max: sensorConfigObj.max,
183
+ step: sensorConfigObj.step,
184
+ unit: sensorConfigObj.unit,
185
+ def: 0,
186
+ },
187
+ native: {},
188
+ });
189
+ }
190
+
191
+ async createAlarmState(statePrefix, alarmConfigObj) {
192
+ await this.adapter.setObjectNotExistsAsync(`${statePrefix}${alarmConfigObj.kind}`, {
193
+ type: "state",
194
+ common: {
195
+ name: alarmConfigObj.kind,
196
+ desc: alarmConfigObj.desc,
197
+ type: "number",
198
+ role: alarmConfigObj.role,
199
+ read: true,
200
+ write: false,
201
+ states: alarmConfigObj.states,
202
+ },
203
+ native: {},
204
+ });
145
205
  }
146
206
 
147
207
  // Only writes changed data into the DB
@@ -173,23 +233,44 @@ class SchellenbergDevice {
173
233
  }
174
234
 
175
235
  let controlPrefix = "";
236
+ let infoPrefix = "";
176
237
  if (value.masterDeviceID != this.id) {
177
238
  // Child-Device unter einem Master-Device
178
239
  controlPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${value.masterDeviceID}.${this.id}.${commonDefines.AdapterDatapointIDs.Control}.`;
240
+ infoPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${value.masterDeviceID}.${this.id}.${commonDefines.AdapterDatapointIDs.Info}.`;
179
241
  } else {
180
242
  // Einzelnes Device
181
243
  controlPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Control}.`;
244
+ infoPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Info}.`;
182
245
  }
183
246
 
184
- if (this.definition?.deviceType?.switchingValues) {
247
+ // Dynamisch aus device.definition
248
+ const capabilities = getDeviceCapabilities(this.definition);
249
+
250
+ if (capabilities.hasSwitchingValues) {
185
251
  // SwitchingValues ignorieren, liefern keine Updates zurück
186
- } else if (this.definition?.deviceType?.kind === commonDefines.AdapterStateIDs.Position) {
187
- // Für Position → direkt setzen
188
- const stateId = `${controlPrefix}${commonDefines.AdapterStateIDs.Position}`;
189
- await this.adapter.setStateAsync(stateId, value.value, true);
190
- this.adapter.log.debug(`Device ${this.id}: Updated position = ${value.value}`);
252
+ this.adapter.log.debug(`Device ${this.id}: switchingValue update ignored (value=${value.value})`);
253
+ return;
191
254
  }
255
+
256
+ if (capabilities.hasLevel) {
257
+ await this.setDeviceStateValue(controlPrefix, capabilities.configObj, value);
258
+ }
259
+
260
+ if (capabilities.hasSensor) {
261
+ await this.setDeviceStateValue(infoPrefix, capabilities.configObj, value);
262
+ }
263
+
264
+ if (capabilities.hasAlarm) {
265
+ await this.setDeviceStateValue(infoPrefix, capabilities.configObj, value);
266
+ }
267
+ }
268
+
269
+ async setDeviceStateValue(statePrefix, configObj, value) {
270
+ const stateId = `${statePrefix}${configObj.kind}`;
271
+ await this.adapter.setStateAsync(stateId, value.value, true);
272
+ this.adapter.log.debug(`Device ${this.id}: Updated ${configObj.kind} = ${value.value}`);
192
273
  }
193
274
  }
194
275
 
195
- exports.SchellenbergDevice = SchellenbergDevice;
276
+ module.exports = SchellenbergDevice;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.smartfriends",
3
- "version": "1.1.0-alpha.1",
3
+ "version": "1.2.0-alpha.0",
4
4
  "description": "smartfriends",
5
5
  "author": {
6
6
  "name": "Black-Thunder",