homebridge-tasmota-control 0.7.2 → 0.9.0-beta.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/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.9.0] - (xx.02.2024)
8
+ ## Changes
9
+ - add support for Light Bulb (On/Off, Brightness, Color Temperature, Hue, Saturation)
10
+ - add possibility to disable/enable name prefix for relays, sensors
11
+ - config schema updated
12
+ - cleanu
13
+
7
14
  ## [0.8.0] - (03.02.2024)
8
15
  ## Changes
9
16
  - add support for Ambient Light and Carbon Dioxyde Sensors
package/README.md CHANGED
@@ -5,8 +5,9 @@
5
5
  <span align="center">
6
6
 
7
7
  # Homebridge Tasmota Control
8
+
8
9
  [![verified-by-homebridge](https://badgen.net/badge/homebridge/verified/purple)](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
9
- [![npm](https://badgen.net/npm/dt/homebridge-tasmota-control?color=purple)](https://www.npmjs.com/package/homebridge-tasmota-control)
10
+ [![npm](https://badgen.net/npm/dt/homebridge-tasmota-control?color=purple)](https://www.npmjs.com/package/homebridge-tasmota-control)
10
11
  [![npm](https://badgen.net/npm/v/homebridge-tasmota-control?color=purple)](https://www.npmjs.com/package/homebridge-tasmota-control)
11
12
  [![npm](https://img.shields.io/npm/v/homebridge-tasmota-control/beta.svg?style=flat-square)](https://www.npmjs.com/package/homebridge-tasmota-control)
12
13
  [![GitHub pull requests](https://img.shields.io/github/issues-pr/grzegorz914/homebridge-tasmota-control.svg)](https://github.com/grzegorz914/homebridge-tasmota-control/pulls)
@@ -26,32 +27,39 @@ Homebridge plugin for Tasmota flashed devices.
26
27
 
27
28
  ## About The Plugin
28
29
 
29
- * Plugin work witch Tasmota falshed devices, communicate over web requests.
30
- * Control devices:
31
- * Switches, Relays
30
+ * Plugin work witch Tasmota falshed devices.
31
+ * Control relay devices:
32
+ * Light - `Power ON/OFF`, `Dimmer`, `Color Temperature`, `Hue`, `Saturation`
33
+ * Outlet - `Power ON/OFF`
34
+ * Switch - `Power ON/OFF`
32
35
  * Read Sensors:
33
36
  * Temperature
34
37
  * Humidity
35
38
  * Dew Point
39
+ * Carbon Dioxyde
40
+ * Ambient Light
36
41
 
37
42
  ### Configuration
38
43
 
39
44
  * Run this plugin as a [Child Bridge](https://github.com/homebridge/homebridge/wiki/Child-Bridges) (Highly Recommended), this prevent crash Homebridge if plugin crashes.
40
- * Install and use [Homebridge Config UI X](https://github.com/homebridge/homebridge-config-ui-x/wiki) to configure this plugin (Highly Recommended).
41
- * The `sample-config.json` can be edited and used as an alternative.
45
+ * Install and use [Homebridge Config UI X](https://github.com/homebridge/homebridge-config-ui-x/wiki) to configure this plugin (Highly Recommended).
46
+ * The `sample-config.json` can be edited and used as an alternative.
42
47
  * Be sure to always make a backup copy of your config.json file before making any changes to it.
43
48
 
44
49
  <p align="center">
45
50
  <a href="https://github.com/grzegorz914/homebridge-tasmota-control"><img src="https://raw.githubusercontent.com/grzegorz914/homebridge-tasmota-control/master/graphics/ustawienia.png" width="840"></a>
46
51
  </p>
47
52
 
48
- | Key | Description |
53
+ | Key | Description |
49
54
  | --- | --- |
50
55
  | `name` | Here set the accessory *Name* to be displayed in *Homebridge/HomeKit*. |
51
56
  | `host` | Here set the *Hsostname or Address IP* of the Device.|
52
57
  | `auth` | If enabled, authorizatins credentials will be used for login. |
53
58
  | `user` | Here set the authorization *Username*. |
54
59
  | `passwd` | Here set the authorization *Password*. |
60
+ | `relaysNamePrefix` | Here enable/disable the accessory name as a prefix for relays name. |
61
+ | `relaysDisplayType` | Here select characteristic display type for relays which are exposed in the HomeKit app. |
62
+ | `sensorsNamePrefix` | Here enable/disable the accessory name as a prefix for sensors name. |
55
63
  | `enableDebugMode` | This enable debug log in homebridge console. |
56
64
  | `disableLogInfo` | This disable log info, all values and state will not be displayed in Homebridge log console. |
57
65
  | `disableLogDeviceInfo` | If enabled, add ability to disable log device info by every connections device to the network. |
@@ -51,6 +51,41 @@
51
51
  "functionBody": "return model.devices[arrayIndices].auth === true;"
52
52
  }
53
53
  },
54
+ "relaysNamePrefix": {
55
+ "title": "Name Prefix",
56
+ "type": "boolean",
57
+ "description": "Here enable/disable the accessory name as a prefix for relays name.",
58
+ "required": true
59
+ },
60
+ "relaysDisplayType": {
61
+ "title": "Display Type",
62
+ "type": "integer",
63
+ "minimum": 0,
64
+ "maximum": 1,
65
+ "default": 0,
66
+ "oneOf": [
67
+ {
68
+ "title": "Outlet",
69
+ "enum": [
70
+ 0
71
+ ]
72
+ },
73
+ {
74
+ "title": "Switch",
75
+ "enum": [
76
+ 1
77
+ ]
78
+ }
79
+ ],
80
+ "description": "Here select characteristic display type for relays which are exposed in the HomeKit app.",
81
+ "required": true
82
+ },
83
+ "sensorsNamePrefix": {
84
+ "title": "Name Prefix",
85
+ "type": "boolean",
86
+ "description": "Here enable/disable the accessory name as a prefix for sensors name.",
87
+ "required": true
88
+ },
54
89
  "refreshInterval": {
55
90
  "title": "Refresh Interval (sec)",
56
91
  "type": "integer",
@@ -106,6 +141,21 @@
106
141
  "type": "tabarray",
107
142
  "title": "{{ value.title }}",
108
143
  "items": [
144
+ {
145
+ "key": "devices[]",
146
+ "title": "Relays",
147
+ "items": [
148
+ "devices[].relaysDisplayType",
149
+ "devices[].relaysNamePrefix"
150
+ ]
151
+ },
152
+ {
153
+ "key": "devices[]",
154
+ "title": "Sensors",
155
+ "items": [
156
+ "devices[].sensorsNamePrefix"
157
+ ]
158
+ },
109
159
  {
110
160
  "key": "devices[]",
111
161
  "title": "Authorization",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Tasmota Control",
3
3
  "name": "homebridge-tasmota-control",
4
- "version": "0.7.2",
4
+ "version": "0.9.0-beta.0",
5
5
  "description": "Homebridge plugin to control Tasmota flashed devices.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
package/src/constans.json CHANGED
@@ -5,11 +5,22 @@
5
5
  "Status": "Status 0",
6
6
  "PowerStatus": "Power0",
7
7
  "Power": "Power",
8
+ "PowerOn": "Power%20on",
9
+ "PowerOff": "Power%20off",
8
10
  "Off": "%20off",
9
11
  "On": "%20on",
10
12
  "Toggle": "%20toggle",
11
13
  "Blink": "%20blink",
12
- "BlinkOff": "%20blinkoff"
14
+ "BlinkOff": "%20blinkoff",
15
+ "Dimmer": "Dimmer",
16
+ "DimmerAllChannels": "Dimmer1",
17
+ "DimmerForRgbChannels": "Dimmer2",
18
+ "DimmerForWhiteChannels": "Dimmer3",
19
+ "ColorTemperature": "CT",
20
+ "HSBColor": "HSBColor",
21
+ "HSBHue": "HSBColor1",
22
+ "HSBSaturation": "HSBColor2",
23
+ "HSBBrightness": "HSBColor3"
13
24
  },
14
25
  "StatusSNS": [
15
26
  "AZ7798",
@@ -31,8 +42,11 @@
31
42
  "SCD30",
32
43
  "SCD40",
33
44
  "SCD41",
45
+ "SHT1X",
34
46
  "SHT10",
47
+ "SHT3X",
35
48
  "SHT30",
49
+ "SHT4X",
36
50
  "SHT40"
37
51
  ],
38
52
  "StatusSNSProperties": [
@@ -21,6 +21,10 @@ class TasmotaDevice {
21
21
  this.user = config.user;
22
22
  this.passwd = config.passwd;
23
23
  this.auth = config.auth || false;
24
+ this.relaysNamePrefix = config.relaysNamePrefix || false;
25
+ this.relaysDisplayType = config.relaysDisplayType || 0;
26
+ this.lightsNamePrefix = config.lightsNamePrefix || false;
27
+ this.sensorsNamePrefix = config.sensorsNamePrefix || false;
24
28
  this.refreshInterval = config.refreshInterval || 5;
25
29
  this.enableDebugMode = config.enableDebugMode || false;
26
30
  this.disableLogInfo = config.disableLogInfo || false;
@@ -36,6 +40,10 @@ class TasmotaDevice {
36
40
  this.relaysFriendlyNames = [];
37
41
  this.relaysCount = 0;
38
42
 
43
+ //lights
44
+ this.lightsFriendlyNames = [];
45
+ this.lightsCount = 0;
46
+
39
47
  //sensors
40
48
  this.sensors = [];
41
49
  this.sensorsCount = 0;
@@ -44,6 +52,8 @@ class TasmotaDevice {
44
52
  this.sensorsDewPointCount = 0;
45
53
  this.sensorsPressureCount = 0;
46
54
  this.sensorsGasCount = 0;
55
+ this.sensorsCarbonDioxydeCount = 0;
56
+ this.sensorsAmbientLightCount = 0;
47
57
 
48
58
  //variable
49
59
  this.startPrepareAccessory = true;
@@ -107,12 +117,14 @@ class TasmotaDevice {
107
117
  //keys
108
118
  const deviceInfoKeys = Object.keys(deviceInfo);
109
119
 
110
- //status
120
+ //relays
121
+ const deviceType = deviceInfo.Status.Module ?? 'Tasmota';
111
122
  const deviceName = deviceInfo.Status.DeviceName ?? 'Tasmota';
112
- const relaysCount = deviceInfo.Status.FriendlyName.length ?? 0;
123
+ const friendlyNames = Array.isArray(deviceInfo.Status.FriendlyName) ? deviceInfo.Status.FriendlyName : [deviceInfo.Status.FriendlyName];
124
+ const relaysCount = friendlyNames.length ?? 0;
113
125
  for (let i = 0; i < relaysCount; i++) {
114
- const friendlyName = deviceInfo.Status.FriendlyName[i] ?? false;
115
- const push = friendlyName ? this.relaysFriendlyNames.push(friendlyName) : false;
126
+ const friendlyName = friendlyNames[i] ?? `Unknown Nmae ${i}`;
127
+ this.relaysFriendlyNames.push(friendlyName);
116
128
  };
117
129
 
118
130
  //status fwr
@@ -160,6 +172,7 @@ class TasmotaDevice {
160
172
  this.serialNumber = addressMac;
161
173
  this.firmwareRevision = firmwareRevision;
162
174
  this.relaysCount = relaysCount;
175
+ this.lightsCount = relaysCount;
163
176
  this.sensorsCount = sensorsCount;
164
177
 
165
178
  resolve(addressMac)
@@ -196,6 +209,69 @@ class TasmotaDevice {
196
209
  };
197
210
  };
198
211
 
212
+ //lights
213
+ const lightsCount = this.lightsCount;
214
+ if (lightsCount > 0) {
215
+ this.lightsStete = [];
216
+ this.lightsBrightnessSupported = [];
217
+ this.lightsBrightness = [];
218
+ this.lightsColorTemperatueSupported = [];
219
+ this.lightsColorTemperatue = [];
220
+ this.lightsHueSupported = [];
221
+ this.lightsHue = [];
222
+ this.lightsSaturationSupported = [];
223
+ this.lightsSaturation = [];
224
+
225
+ const lightsStatusData = await this.axiosInstance(CONSTANS.ApiCommands.PowerStatus);
226
+ const lightsStatus = lightsStatusData.data;
227
+ const debug = this.enableDebugMode ? this.log(`Device: ${this.host} ${this.name}, debug ${lightsCount === 1 ? 'light' : 'lights'} status: ${JSON.stringify(lightsStatus, null, 2)}`) : false;
228
+
229
+ for (let i = 0; i < lightsCount; i++) {
230
+ const powerStatusKey = lightsCount === 1 ? 'POWER' : 'POWER' + (i + 1);
231
+ const status = lightsStatus[powerStatusKey] === 'ON' ?? false;
232
+
233
+ const statusKeys = Object.keys(lightsStatus);
234
+ const brightnessSupported = statusKeys.includes('Dimmer');
235
+ const brightness = lightsStatus.Dimmer ?? false;
236
+ const colorTemperatureSupported = statusKeys.includes('CT');
237
+ const colorTemperature = lightsStatus.CT ?? false;
238
+ const hueSupported = statusKeys.includes('HSBColor1');
239
+ const hue = lightsStatus.HSBColor1 ?? false;
240
+ const saturationSupported = statusKeys.includes('HSBColor2');
241
+ const saturation = lightsStatus.HSBColor2 ?? false;
242
+
243
+ this.lightsStete.push(status);
244
+ this.lightsBrightnessSupported.push(brightnessSupported)
245
+ const push = brightnessSupported ? this.lightsBrightness.push(brightness) : false;
246
+ this.lightsColorTemperatueSupported.push(colorTemperatureSupported)
247
+ const push1 = colorTemperatureSupported ? this.lightsColorTemperatue.push(colorTemperature) : false;
248
+ this.lightsHueSupported.push(hueSupported)
249
+ const push2 = hueSupported ? this.lightsHue.push(hue) : false;
250
+ this.lightsSaturationSupported.push(saturationSupported)
251
+ const push3 = saturationSupported ? this.lightsHue.push(saturation) : false;
252
+
253
+
254
+ //update characteristics
255
+ if (this.lightServices) {
256
+ this.lightServices[i].updateCharacteristic(Characteristic.On, status);
257
+
258
+ if (brightnessSupported) {
259
+ this.lightServices[i].updateCharacteristic(Characteristic.Brightness, brightness);
260
+ };
261
+ if (colorTemperatureSupported) {
262
+ const value = colorTemperature > 153 ? colorTemperature : 140;
263
+ this.lightServices[i].updateCharacteristic(Characteristic.ColorTemperature, value);
264
+ };
265
+ if (hueSupported) {
266
+ this.lightServices[i].updateCharacteristic(Characteristic.Hue, hue);
267
+ };
268
+ if (saturationSupported) {
269
+ this.lightServices[i].updateCharacteristic(Characteristic.Saturation, saturation);
270
+ };
271
+ };
272
+ };
273
+ };
274
+
199
275
  //sensors
200
276
  const sensorsCount = this.sensorsCount;
201
277
  if (sensorsCount > 0) {
@@ -205,6 +281,8 @@ class TasmotaDevice {
205
281
  this.sensorsDewPoint = [];
206
282
  this.sensorsPressure = [];
207
283
  this.sensorsGas = [];
284
+ this.sensorsCarbonDioxyde = [];
285
+ this.sensorsAmbientLight = [];
208
286
 
209
287
  const sensorsStatusData = await this.axiosInstance(CONSTANS.ApiCommands.Status);
210
288
  const sensorsStatus = sensorsStatusData.data.StatusSNS;
@@ -227,6 +305,8 @@ class TasmotaDevice {
227
305
  const push3 = dewPoint !== false && dewPoint !== undefined && dewPoint !== null ? this.sensorsDewPoint.push(dewPoint) : false;
228
306
  const push4 = pressure !== false && pressure !== undefined && pressure !== null ? this.sensorsPressure.push(pressure) : false;
229
307
  const push5 = gas !== false && gas !== undefined && gas !== null ? this.sensorsGas.push(gas) : false;
308
+ const push6 = carbonDioxyde !== false && carbonDioxyde !== undefined && carbonDioxyde !== null ? this.sensorsCarbonDioxyde.push(carbonDioxyde) : false;
309
+ const push7 = ambientLight !== false && ambientLight !== undefined && ambientLight !== null ? this.sensorsAmbientLight.push(ambientLight) : false;
230
310
  };
231
311
 
232
312
  this.sensorsTemperatureCount = this.sensorsTemperature.length;
@@ -234,6 +314,8 @@ class TasmotaDevice {
234
314
  this.sensorsDewPointCount = this.sensorsDewPoint.length;
235
315
  this.sensorsPressureCount = this.sensorsPressure.length;
236
316
  this.sensorsGasCount = this.sensorsGas.length;
317
+ this.sensorsCarbonDioxydeCount = this.sensorsCarbonDioxyde.length;
318
+ this.sensorsAmbientLightCount = this.sensorsAmbientLight.length;
237
319
  this.tempUnit = sensorsStatus.TempUnit ?? 'C';
238
320
  this.pressureUnit = sensorsStatus.PressureUnit ?? 'hPa';
239
321
 
@@ -262,6 +344,25 @@ class TasmotaDevice {
262
344
  .updateCharacteristic(Characteristic.CurrentTemperature, dewPoint);
263
345
  };
264
346
  };
347
+
348
+ if (this.sensorCarbonDioxydeServices && this.sensorsCarbonDioxydeCount > 0) {
349
+ for (let i = 0; i < this.sensorsCarbonDioxydeCount; i++) {
350
+ const carbonDioxydeDetected = this.sensorsCarbonDioxyde[i] > 1000;
351
+ const carbonDioxydeLevel = this.sensorsCarbonDioxyde[i];
352
+ this.sensorCarbonDioxydeServices[i]
353
+ .updateCharacteristic(Characteristic.CarbonDioxideDetected, carbonDioxydeDetected)
354
+ .updateCharacteristic(Characteristic.CarbonDioxideLevel, carbonDioxydeLevel)
355
+ .updateCharacteristic(Characteristic.CarbonDioxidePeakLevel, carbonDioxydeLevel);
356
+ };
357
+ };
358
+
359
+ if (this.sensorAmbientLightServices && this.sensorsAmbientLightCount > 0) {
360
+ for (let i = 0; i < this.sensorsAmbientLightCount; i++) {
361
+ const ambientLight = this.sensorsAmbientLight[i];
362
+ this.sensorAmbientLightServices[i]
363
+ .updateCharacteristic(Characteristic.CurrentAmbientLightLevel, ambientLight);
364
+ };
365
+ };
265
366
  };
266
367
 
267
368
  resolve();
@@ -293,33 +394,36 @@ class TasmotaDevice {
293
394
  //Prepare services
294
395
  const debug2 = this.enableDebugMode ? this.log('Prepare Services') : false;
295
396
 
296
- //relays
397
+ //switches, outlets
297
398
  const relaysCount = this.relaysCount;
298
399
  if (relaysCount > 0) {
299
400
  const debug = this.enableDebugMode ? this.log('Prepare Relay Services') : false;
300
401
  this.relayServices = [];
301
402
  for (let i = 0; i < relaysCount; i++) {
302
- const relaysName = this.relaysFriendlyNames[i];
303
- const serviceName = relaysCount > 1 ? `${accessoryName} ${relaysName}` : accessoryName;
304
- const logName = relaysCount > 1 ? `${accessoryName}, relay: ${relaysName}` : `${accessoryName}`
305
- const relayService = new Service.Outlet(serviceName, `Relay${[i]}`);
403
+ const relayName = this.relaysFriendlyNames[i];
404
+ const relayLogName = relaysCount > 1 ? `${accessoryName}, relay: ${relayName}` : relayName
405
+ const serviceName = this.relaysNamePrefix ? `${accessoryName} ${relayName}` : relayName;
406
+ const serviceType = [Service.Outlet, Service.Switch][this.relaysDisplayType];
407
+ const relayService = new serviceType(serviceName, `Relay ${[i]}`);
306
408
  relayService.addOptionalCharacteristic(Characteristic.ConfiguredName);
307
409
  relayService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
308
410
  relayService.getCharacteristic(Characteristic.On)
309
411
  .onGet(async () => {
310
412
  const state = this.relaysStete[i] ?? false;
311
- const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${logName}, state: ${state ? 'ON' : 'OFF'}`);
413
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${relayLogName}, state: ${state ? 'ON' : 'OFF'}`);
312
414
  return state;
313
415
  })
314
416
  .onSet(async (state) => {
315
- const powerOn = relaysCount === 1 ? CONSTANS.ApiCommands.Power + CONSTANS.ApiCommands.On : CONSTANS.ApiCommands.Power + (i + 1) + CONSTANS.ApiCommands.On;
316
- const powerOff = relaysCount === 1 ? CONSTANS.ApiCommands.Power + CONSTANS.ApiCommands.Off : CONSTANS.ApiCommands.Power + (i + 1) + CONSTANS.ApiCommands.Off;
317
- state = state ? powerOn : powerOff;
318
417
  try {
418
+ const relayNr = i + 1;
419
+ const relayOn = relaysCount === 1 ? CONSTANS.ApiCommands.PowerOn : `${CONSTANS.ApiCommands.Power}${relayNr}${CONSTANS.ApiCommands.On}`;
420
+ const relayOff = relaysCount === 1 ? CONSTANS.ApiCommands.PowerOff : `${CONSTANS.ApiCommands.Power}${relayNr}${CONSTANS.ApiCommands.Off}`;
421
+ state = state ? relayOn : relayOff;
422
+
319
423
  await this.axiosInstance(state);
320
- const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${logName}, set state: ${state ? 'ON' : 'OFF'}`);
424
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${relayLogName}, set state: ${state ? 'ON' : 'OFF'}`);
321
425
  } catch (error) {
322
- this.log.error(`Device: ${this.host} ${logName}, set state error: ${error}`);
426
+ this.log.error(`Device: ${this.host} ${relayLogName}, set state error: ${error}`);
323
427
  }
324
428
  });
325
429
  this.relayServices.push(relayService);
@@ -327,6 +431,111 @@ class TasmotaDevice {
327
431
  };
328
432
  }
329
433
 
434
+ //lights
435
+ const lightsCount = this.lightsCount;
436
+ if (lightsCount > 0) {
437
+ const debug = this.enableDebugMode ? this.log('Prepare Light Services') : false;
438
+ this.lightServices = [];
439
+ for (let i = 0; i < lightsCount; i++) {
440
+ const lightName = this.lightsFriendlyNames[i];
441
+ const lightLogName = lightsCount > 1 ? `${accessoryName}, light: ${lightName}` : lightName
442
+ const serviceName = this.lightsNamePrefix ? `${accessoryName} ${lightName}` : lightName;
443
+ const lightService = new Service.Lightbulb(serviceName, `Light ${[i]}`);
444
+ lightService.addOptionalCharacteristic(Characteristic.ConfiguredName);
445
+ lightService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
446
+ lightService.getCharacteristic(Characteristic.On)
447
+ .onGet(async () => {
448
+ const state = this.lightsStete[i] ?? false;
449
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, state: ${state ? 'ON' : 'OFF'}`);
450
+ return state;
451
+ })
452
+ .onSet(async (state) => {
453
+ try {
454
+ const lightNr = i + 1;
455
+ const lightOn = lightsCount === 1 ? CONSTANS.ApiCommands.PowerOn : `${CONSTANS.ApiCommands.Power}${lightNr}${CONSTANS.ApiCommands.On}`;
456
+ const lightOff = lightsCount === 1 ? CONSTANS.ApiCommands.PowerOff : `${CONSTANS.ApiCommands.Power}${lightNr}${CONSTANS.ApiCommands.Off}`
457
+ state = state ? lightOn : lightOff;
458
+
459
+ await this.axiosInstance(state);
460
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, set state: ${state ? 'ON' : 'OFF'}`);
461
+ } catch (error) {
462
+ this.log.error(`Device: ${this.host} ${lightLogName}, set state error: ${error}`);
463
+ }
464
+ });
465
+ if (this.lightsBrightnessSupported[i]) {
466
+ lightService.getCharacteristic(Characteristic.Brightness)
467
+ .onGet(async () => {
468
+ const value = this.lightsBrightness[i] ?? 0;
469
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, brightness: ${value} %`);
470
+ return value;
471
+ })
472
+ .onSet(async (value) => {
473
+ try {
474
+ const brightness = `${CONSTANS.ApiCommands.Dimmer}${value}`; //0..100
475
+ await this.axiosInstance(brightness);
476
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, set brightness: ${value} %`);
477
+ } catch (error) {
478
+ this.log.error(`Device: ${this.host} ${lightLogName}, set brightness error: ${error}`);
479
+ }
480
+ });
481
+ };
482
+ if (this.lightsColorTemperatueSupported[i]) {
483
+ lightService.getCharacteristic(Characteristic.ColorTemperature)
484
+ .onGet(async () => {
485
+ const value = this.lightsColorTemperature[i] > 153 ? this.lightsColorTemperature[i] : 140;
486
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, color temperatur: ${value}`);
487
+ return value;
488
+ })
489
+ .onSet(async (value) => {
490
+ try {
491
+ value = value < 153 ? 153 : value;
492
+ const colorTemperature = `${CONSTANS.ApiCommands.ColorTemperature}${value}`; //140..500
493
+ await this.axiosInstance(colorTemperature);
494
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, set brightness: ${value} °`);
495
+ } catch (error) {
496
+ this.log.error(`Device: ${this.host} ${lightLogName}, set color temperatur error: ${error}`);
497
+ }
498
+ });
499
+ };
500
+ if (this.lightsHueSupported[i]) {
501
+ lightService.getCharacteristic(Characteristic.Hue)
502
+ .onGet(async () => {
503
+ const value = this.lightsHue[i] ?? 0;
504
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, hue: ${value} %`);
505
+ return value;
506
+ })
507
+ .onSet(async (value) => {
508
+ try {
509
+ const hue = `${CONSTANS.ApiCommands.HSBHue}${value}`; //0..360
510
+ await this.axiosInstance(hue);
511
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, set hue: ${value} °`);
512
+ } catch (error) {
513
+ this.log.error(`Device: ${this.host} ${lightLogName}, set hue error: ${error}`);
514
+ }
515
+ });
516
+ };
517
+ if (this.lightsSaturationSupported[i]) {
518
+ lightService.getCharacteristic(Characteristic.Saturation)
519
+ .onGet(async () => {
520
+ const value = this.lightsSaturation[i] ?? 0;
521
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, saturation: ${value} %`);
522
+ return value;
523
+ })
524
+ .onSet(async (value) => {
525
+ try {
526
+ const saturation = `${CONSTANS.ApiCommands.HSBSaturation}${value}`; //0..100
527
+ await this.axiosInstance(saturation);
528
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${lightLogName}, set saturation: ${value} °`);
529
+ } catch (error) {
530
+ this.log.error(`Device: ${this.host} ${lightLogName}, set saturation error: ${error}`);
531
+ }
532
+ });
533
+ };
534
+ this.lightServices.push(lightService);
535
+ accessory.addService(lightService);
536
+ };
537
+ }
538
+
330
539
  //sensors
331
540
  const sensorsCount = this.sensorsCount;
332
541
  if (sensorsCount > 0) {
@@ -339,8 +548,8 @@ class TasmotaDevice {
339
548
  this.sensorTemperatureServices = [];
340
549
  for (let i = 0; i < sensorsTemperatureCount; i++) {
341
550
  const sensorName = this.sensorsName[i];
342
- const serviceName = `${accessoryName} ${sensorName} Temperature`;
343
- const sensorTemperatureService = new Service.TemperatureSensor(serviceName, `Temperature Sensor${i}`);
551
+ const serviceName = this.sensorsNamePrefix ? `${accessoryName} ${sensorName} Temperature` : `${sensorName} Temperature`;
552
+ const sensorTemperatureService = new Service.TemperatureSensor(serviceName, `Temperature Sensor ${i}`);
344
553
  sensorTemperatureService.addOptionalCharacteristic(Characteristic.ConfiguredName);
345
554
  sensorTemperatureService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
346
555
  sensorTemperatureService.getCharacteristic(Characteristic.CurrentTemperature)
@@ -361,8 +570,8 @@ class TasmotaDevice {
361
570
  this.sensorHumidityServices = [];
362
571
  for (let i = 0; i < sensorsHumidityCount; i++) {
363
572
  const sensorName = this.sensorsName[i];
364
- const serviceName = `${accessoryName} ${sensorName} Humidity`;
365
- const sensorHumidityService = new Service.HumiditySensor(serviceName, `Humidity Sensor${i}`);
573
+ const serviceName = this.sensorsNamePrefix ? `${accessoryName} ${sensorName} Humidity` : `${sensorName} Humidity`;
574
+ const sensorHumidityService = new Service.HumiditySensor(serviceName, `Humidity Sensor ${i}`);
366
575
  sensorHumidityService.addOptionalCharacteristic(Characteristic.ConfiguredName);
367
576
  sensorHumidityService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
368
577
  sensorHumidityService.getCharacteristic(Characteristic.CurrentRelativeHumidity)
@@ -383,8 +592,8 @@ class TasmotaDevice {
383
592
  this.sensorDewPointServices = [];
384
593
  for (let i = 0; i < sensorsDewPointCount; i++) {
385
594
  const sensorName = this.sensorsName[i];
386
- const serviceName = `${accessoryName} ${sensorName} Dew Point`;
387
- const sensorDewPointService = new Service.TemperatureSensor(serviceName, `Dew Point Sensor${i}`);
595
+ const serviceName = this.sensorsNamePrefix ? `${accessoryName} ${sensorName} Dew Point` : `${sensorName} Dew Point`;
596
+ const sensorDewPointService = new Service.TemperatureSensor(serviceName, `Dew Point Sensor ${i}`);
388
597
  sensorDewPointService.addOptionalCharacteristic(Characteristic.ConfiguredName);
389
598
  sensorDewPointService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
390
599
  sensorDewPointService.getCharacteristic(Characteristic.CurrentTemperature)
@@ -403,7 +612,60 @@ class TasmotaDevice {
403
612
  //gas
404
613
 
405
614
  //carbon dioxyde
615
+ const sensorsCarbonDioxydeCount = this.sensorsCarbonDioxydeCount;
616
+ if (sensorsCarbonDioxydeCount > 0) {
617
+ const debug = this.enableDebugMode ? this.log('Prepare Carbon Dioxyde Sensor Services') : false;
618
+ this.sensorCarbonDioxydeServices = [];
619
+ for (let i = 0; i < sensorsCarbonDioxydeCount; i++) {
620
+ const sensorName = this.sensorsName[i];
621
+ const serviceName = this.sensorsNamePrefix ? `${accessoryName} ${sensorName} Carbon Dioxyde` : `${sensorName} Carbon Dioxyde`;
622
+ const sensorCarbonDioxydeService = new Service.CarbonDioxideSensor(serviceName, `Carbon Dioxyde Sensor ${i}`);
623
+ sensorCarbonDioxydeService.addOptionalCharacteristic(Characteristic.ConfiguredName);
624
+ sensorCarbonDioxydeService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
625
+ sensorCarbonDioxydeService.getCharacteristic(Characteristic.CarbonDioxideDetected)
626
+ .onGet(async () => {
627
+ const state = this.sensorsCarbonDioxyde[i] > 1000;
628
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host}, ${accessoryName}, sensor: ${sensorName} carbon dioxyde detected: ${state ? 'Yes' : 'No'}`);
629
+ return state;
630
+ });
631
+ sensorCarbonDioxydeService.getCharacteristic(Characteristic.CarbonDioxideLevel)
632
+ .onGet(async () => {
633
+ const value = this.sensorsCarbonDioxyde[i];
634
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host}, ${accessoryName}, sensor: ${sensorName} carbon dioxyde level: ${value} ppm`);
635
+ return value;
636
+ });
637
+ sensorCarbonDioxydeService.getCharacteristic(Characteristic.CarbonDioxidePeakLevel)
638
+ .onGet(async () => {
639
+ const value = this.sensorsCarbonDioxyde[i];
640
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host}, ${accessoryName}, sensor: ${sensorName} carbon dioxyde peak level: ${value} ppm`);
641
+ return value;
642
+ });
643
+ this.sensorCarbonDioxydeServices.push(sensorCarbonDioxydeService);
644
+ accessory.addService(sensorCarbonDioxydeService);
645
+ };
646
+ }
406
647
 
648
+ //ambient light
649
+ const sensorsAmbientLightCount = this.sensorsAmbientLightCount;
650
+ if (sensorsAmbientLightCount > 0) {
651
+ const debug = this.enableDebugMode ? this.log('Prepare Ambient Light Sensor Services') : false;
652
+ this.sensorAmbientLightServices = [];
653
+ for (let i = 0; i < sensorsAmbientLightCount; i++) {
654
+ const sensorName = this.sensorsName[i];
655
+ const serviceName = this.sensorsNamePrefix ? `${accessoryName} ${sensorName} Ambient Light` : `${sensorName} Ambient Light`;
656
+ const sensorAmbientLightService = new Service.LightSensor(serviceName, `Ambient Light Sensor ${i}`);
657
+ sensorAmbientLightService.addOptionalCharacteristic(Characteristic.ConfiguredName);
658
+ sensorAmbientLightService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
659
+ sensorAmbientLightService.getCharacteristic(Characteristic.CurrentAmbientLightLevel)
660
+ .onGet(async () => {
661
+ const value = this.sensorsAmbientLight[i];
662
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host}, ${accessoryName}, sensor: ${sensorName} ambient light: ${value} lx`);
663
+ return value;
664
+ });
665
+ this.sensorAmbientLightServices.push(sensorAmbientLightService);
666
+ accessory.addService(sensorAmbientLightService);
667
+ };
668
+ }
407
669
  };
408
670
 
409
671
  resolve(accessory);