homebridge-tasmota-control 1.7.9 → 1.7.10-beta.1

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/index.js CHANGED
@@ -115,19 +115,19 @@ class tasmotaPlatform {
115
115
  let deviceType;
116
116
  switch (type) {
117
117
  case 0: //mielhvac
118
- deviceType = new MiElHvac(api, device, info, serialNumber, refreshInterval);
118
+ deviceType = new MiElHvac(api, device, info, serialNumber);
119
119
  break;
120
120
  case 1: //switches
121
- deviceType = new Switches(api, device, info, serialNumber, refreshInterval);
121
+ deviceType = new Switches(api, device, info, serialNumber);
122
122
  break;
123
123
  case 2: //lights
124
- deviceType = new Lights(api, device, info, serialNumber, refreshInterval);
124
+ deviceType = new Lights(api, device, info, serialNumber);
125
125
  break;
126
126
  case 3: //fans
127
- deviceType = new Fans(api, device, info, serialNumber, refreshInterval);
127
+ deviceType = new Fans(api, device, info, serialNumber);
128
128
  break;
129
129
  case 4: //sensors
130
- deviceType = new Sensors(api, device, info, serialNumber, refreshInterval);
130
+ deviceType = new Sensors(api, device, info, serialNumber);
131
131
  break;
132
132
  default:
133
133
  if (logLevel.warn) log.warn(`Device: ${host} ${deviceName}, unknown device: ${info.deviceTypes}.`);
@@ -146,8 +146,11 @@ class tasmotaPlatform {
146
146
  api.publishExternalAccessories(PluginName, [accessory]);
147
147
  if (logLevel.success) log.success(`Device: ${host} ${deviceName}, Published as external accessory.`);
148
148
 
149
- await impulseGenerator.stop();
150
- await deviceType.startImpulseGenerator();
149
+ //start impulse generator
150
+ await deviceType.startStopImpulseGenerator(true, [{ name: 'checkState', sampling: refreshInterval }]);
151
+
152
+ //stop impulse generator
153
+ await impulseGenerator.state(false);
151
154
  }
152
155
 
153
156
  i++;
@@ -160,7 +163,7 @@ class tasmotaPlatform {
160
163
  });
161
164
 
162
165
  //start impulse generator
163
- await impulseGenerator.start([{ name: 'start', sampling: 60000 }]);
166
+ await impulseGenerator.state(true, [{ name: 'start', sampling: 120000 }]);
164
167
  } catch (error) {
165
168
  if (logLevel.error) log.error(`Device: ${host} ${deviceName}, Did finish launching error: ${error.message ?? error}.`);
166
169
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Tasmota Control",
3
3
  "name": "homebridge-tasmota-control",
4
- "version": "1.7.9",
4
+ "version": "1.7.10-beta.1",
5
5
  "description": "Homebridge plugin to control Tasmota flashed devices.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -31,10 +31,10 @@
31
31
  ],
32
32
  "engines": {
33
33
  "homebridge": "^1.9.0 || ^2.0.0 || ^2.0.0-beta.30 || ^2.0.0-alpha.40",
34
- "node": "^20 || ^22 || ^24"
34
+ "node": "^20 || ^22 || ^24 || ^25"
35
35
  },
36
36
  "dependencies": {
37
- "axios": "^1.13.1"
37
+ "axios": "^1.13.2"
38
38
  },
39
39
  "keywords": [
40
40
  "homebridge",
package/src/fans.js CHANGED
@@ -6,7 +6,7 @@ import { ApiCommands } from './constants.js';
6
6
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
7
 
8
8
  class Fans extends EventEmitter {
9
- constructor(api, config, info, serialNumber, refreshInterval) {
9
+ constructor(api, config, info, serialNumber) {
10
10
  super();
11
11
 
12
12
  Accessory = api.platformAccessory;
@@ -26,7 +26,6 @@ class Fans extends EventEmitter {
26
26
  this.enableDebugMode = config.enableDebugMode || false;
27
27
  this.disableLogInfo = config.disableLogInfo || false;
28
28
  this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
29
- this.refreshInterval = refreshInterval;
30
29
  this.functions = new Functions();
31
30
 
32
31
  //axios instance
@@ -50,7 +49,7 @@ class Fans extends EventEmitter {
50
49
  await this.checkState();
51
50
  }))
52
51
  .on('state', (state) => {
53
- this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
52
+ this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
54
53
  });
55
54
  }
56
55
 
@@ -156,11 +155,10 @@ class Fans extends EventEmitter {
156
155
  }
157
156
  }
158
157
 
159
- async startImpulseGenerator() {
158
+ async startStopImpulseGenerator(state, timers = []) {
160
159
  try {
161
160
  //start impulse generator
162
- const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
163
- await this.impulseGenerator.start(timers);
161
+ await this.melCloudAta.impulseGenerator.state(state, timers)
164
162
  return true;
165
163
  } catch (error) {
166
164
  throw new Error(`Impulse generator start error: ${error}`);
@@ -7,46 +7,34 @@ class ImpulseGenerator extends EventEmitter {
7
7
  this.timers = [];
8
8
  }
9
9
 
10
- async start(timers) {
11
- if (this.timersState) {
12
- this.state(true);
13
- return true;
10
+ async state(state, timers = []) {
11
+ // Stop current timers before new start
12
+ if (this.timersState && state) {
13
+ await this.state(false);
14
14
  }
15
15
 
16
- this.timers = [];
17
-
18
- for (const timer of timers) {
19
- this.emit(timer.name);
20
-
21
- const interval = setInterval(() => {
22
- this.emit(timer.name);
23
- }, timer.sampling);
16
+ if (state) {
17
+ if (!Array.isArray(timers)) throw new Error('Timers must be an array');
24
18
 
25
- this.timers.push(interval);
26
- }
19
+ for (const { name, sampling } of timers) {
20
+ if (!name || !sampling) continue;
27
21
 
28
- this.state(true);
29
- return true;
30
- }
22
+ this.emit(name);
31
23
 
32
- async stop() {
33
- if (!this.timersState) {
34
- this.state(false);
35
- return true;
36
- }
24
+ const interval = setInterval(() => {
25
+ this.emit(name);
26
+ }, sampling);
37
27
 
38
- for (const timer of this.timers) {
39
- clearInterval(timer);
28
+ this.timers.push(interval);
29
+ }
30
+ } else {
31
+ this.timers.forEach(clearInterval);
32
+ this.timers = [];
40
33
  }
41
34
 
42
- this.timers = [];
43
- this.state(false);
44
- return true;
45
- }
46
-
47
- state(state) {
48
35
  this.timersState = state;
49
36
  this.emit('state', state);
37
+ return true;
50
38
  }
51
39
  }
52
40
 
package/src/lights.js CHANGED
@@ -6,7 +6,7 @@ import { ApiCommands } from './constants.js';
6
6
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
7
 
8
8
  class Lights extends EventEmitter {
9
- constructor(api, config, info, serialNumber, refreshInterval) {
9
+ constructor(api, config, info, serialNumber) {
10
10
  super();
11
11
 
12
12
  Accessory = api.platformAccessory;
@@ -25,7 +25,6 @@ class Lights extends EventEmitter {
25
25
  this.enableDebugMode = config.enableDebugMode || false;
26
26
  this.disableLogInfo = config.disableLogInfo || false;
27
27
  this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
28
- this.refreshInterval = refreshInterval;
29
28
  this.functions = new Functions();
30
29
 
31
30
  //axios instance
@@ -47,7 +46,7 @@ class Lights extends EventEmitter {
47
46
  await this.checkState();
48
47
  }))
49
48
  .on('state', (state) => {
50
- this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
49
+ this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
51
50
  });
52
51
  }
53
52
 
@@ -153,11 +152,10 @@ class Lights extends EventEmitter {
153
152
  }
154
153
  }
155
154
 
156
- async startImpulseGenerator() {
155
+ async startStopImpulseGenerator(state, timers = []) {
157
156
  try {
158
157
  //start impulse generator
159
- const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
160
- await this.impulseGenerator.start(timers);
158
+ await this.melCloudAta.impulseGenerator.state(state, timers)
161
159
  return true;
162
160
  } catch (error) {
163
161
  throw new Error(`Impulse generator start error: ${error}`);
package/src/mielhvac.js CHANGED
@@ -6,7 +6,7 @@ import { ApiCommands, MiElHVAC, TemperatureDisplayUnits } from './constants.js';
6
6
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
7
 
8
8
  class MiElHvac extends EventEmitter {
9
- constructor(api, config, info, serialNumber, refreshInterval) {
9
+ constructor(api, config, info, serialNumber) {
10
10
  super();
11
11
 
12
12
  Accessory = api.platformAccessory;
@@ -37,64 +37,34 @@ class MiElHvac extends EventEmitter {
37
37
  this.remoteTemperatureSensorRefreshInterval = remoteTemperatureSensorRefreshInterval;
38
38
 
39
39
  //presets
40
- const presets = miElHvac.presets || [];
41
- this.presetsConfigured = [];
42
- for (const preset of presets) {
43
- const displayType = preset.displayType;
44
- if (!displayType) {
45
- continue;
46
- }
47
-
48
- const presetyServiceType = ['', Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType];
49
- const presetCharacteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType];
50
- preset.serviceType = presetyServiceType;
51
- preset.characteristicType = presetCharacteristicType;
40
+ this.presets = (miElHvac.presets || []).filter(preset => (preset.displayType ?? 0) > 0);
41
+ for (const preset of this.presets) {
42
+ preset.serviceType = [null, Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][preset.displayType];
43
+ preset.characteristicType = [null, Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][preset.displayType];
52
44
  preset.name = preset.name || 'Preset';
53
45
  preset.state = false;
54
46
  preset.previousSettings = {};
55
- this.presetsConfigured.push(preset);
56
47
  }
57
- this.presetsConfiguredCount = this.presetsConfigured.length || 0;
58
48
 
59
49
  //buttons
60
- const buttons = miElHvac.buttons || [];
61
- this.buttonsConfigured = [];
62
- for (const button of buttons) {
63
- const displayType = button.displayType;
64
- if (!displayType) {
65
- continue;
66
- }
67
-
68
- const buttonServiceType = ['', Service.Outlet, Service.Switch][displayType];
69
- const buttonCharacteristicType = ['', Characteristic.On, Characteristic.On][displayType];
70
- button.serviceType = buttonServiceType;
71
- button.characteristicType = buttonCharacteristicType;
50
+ this.buttons = (miElHvac.buttons || []).filter(button => (button.displayType ?? 0) > 0);
51
+ for (const button of this.buttons) {
52
+ button.serviceType = [null, Service.Outlet, Service.Switch][button.displayType];
53
+ button.characteristicType = [null, Characteristic.On, Characteristic.On][button.displayType];
72
54
  button.name = button.name || 'Button';
73
55
  button.state = false;
74
56
  button.previousValue = null;
75
- this.buttonsConfigured.push(button);
76
57
  }
77
- this.buttonsConfiguredCount = this.buttonsConfigured.length || 0;
78
58
 
79
59
  //sensors
80
- const sensors = miElHvac.sensors || [];
81
- this.sensorsConfigured = [];
82
- for (const sensor of sensors) {
83
- const displayType = sensor.displayType;
84
- if (!displayType) {
85
- continue;
86
- }
87
-
88
- const sensorServiceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][displayType];
89
- const sensorCharacteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][displayType];
90
- sensor.serviceType = sensorServiceType;
91
- sensor.characteristicType = sensorCharacteristicType;
60
+ this.sensors = (miElHvac.sensors || []).filter(sensor => (sensor.displayType ?? 0) > 0);
61
+ for (const sensor of this.sensors) {
62
+ sensor.serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][sensor.displayType];
63
+ sensor.characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][sensor.displayType];
92
64
  sensor.name = sensor.name || 'Sensor';
93
65
  sensor.state = false;
94
66
  sensor.previousValue = null;
95
- this.sensorsConfigured.push(sensor);
96
67
  }
97
- this.sensorsConfiguredCount = this.sensorsConfigured.length || 0;
98
68
 
99
69
  //frost protect
100
70
  const frostProtect = miElHvac.frostProtect ?? {};
@@ -112,7 +82,6 @@ class MiElHvac extends EventEmitter {
112
82
  this.enableDebugMode = config.enableDebugMode || false;
113
83
  this.disableLogInfo = config.disableLogInfo || false;
114
84
  this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
115
- this.refreshInterval = refreshInterval;
116
85
 
117
86
  //mielhvac
118
87
  this.mielHvac = {};
@@ -158,7 +127,7 @@ class MiElHvac extends EventEmitter {
158
127
  await this.checkState();
159
128
  }))
160
129
  .on('state', (state) => {
161
- this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
130
+ this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
162
131
  });
163
132
  }
164
133
 
@@ -434,8 +403,8 @@ class MiElHvac extends EventEmitter {
434
403
  }
435
404
 
436
405
  // Update presets state
437
- if (this.presetsConfiguredCount > 0) {
438
- this.presetsConfigured.forEach((preset, index) => {
406
+ if (this.presets.length > 0) {
407
+ this.presets.forEach((preset, index) => {
439
408
  let iseeMode = operationMode;
440
409
  if (iseeMode === 'heat_isee') iseeMode = 'heat';
441
410
  else if (iseeMode === 'dry_isee') iseeMode = 'dry';
@@ -452,7 +421,7 @@ class MiElHvac extends EventEmitter {
452
421
  });
453
422
  }
454
423
 
455
- if (this.buttonsConfiguredCount > 0) {
424
+ if (this.buttons.length > 0) {
456
425
  const modeMap = {
457
426
  0: () => power === 1,
458
427
  1: () => power && ['heat', 'heat_isee'].includes(operationMode),
@@ -521,7 +490,7 @@ class MiElHvac extends EventEmitter {
521
490
  63: 'on', //nightmode
522
491
  };
523
492
 
524
- this.buttonsConfigured.forEach((button, index) => {
493
+ this.buttons.forEach((button, index) => {
525
494
  const mode = button.mode;
526
495
  let state = false;
527
496
 
@@ -550,14 +519,14 @@ class MiElHvac extends EventEmitter {
550
519
  });
551
520
  }
552
521
 
553
- if (this.sensorsConfiguredCount > 0) {
522
+ if (this.sensors.length > 0) {
554
523
  const powerOn = power === 1;
555
524
 
556
525
  // Helper: match by value with power check
557
526
  const is = (val, match) => powerOn && val === match;
558
527
  const isOneOf = (val, matches) => powerOn && matches.includes(val);
559
528
 
560
- this.sensorsConfigured.forEach((sensor, index) => {
529
+ this.sensors.forEach((sensor, index) => {
561
530
  const mode = sensor.mode;
562
531
 
563
532
  const sensorStates = {
@@ -691,12 +660,12 @@ class MiElHvac extends EventEmitter {
691
660
  }
692
661
  }
693
662
 
694
- async startImpulseGenerator() {
663
+ async startStopImpulseGenerator(state, timers = []) {
695
664
  try {
696
- //start impulse generator
697
- const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
698
665
  if (this.remoteTemperatureSensorEnable) timers.push({ name: 'updateRemoteTemp', sampling: this.remoteTemperatureSensorRefreshInterval });
699
- await this.impulseGenerator.start(timers);
666
+
667
+ //start impulse generator
668
+ await this.melCloudAta.impulseGenerator.state(state, timers)
700
669
  return true;
701
670
  } catch (error) {
702
671
  throw new Error(`Impulse generator start error: ${error}`);
@@ -952,11 +921,11 @@ class MiElHvac extends EventEmitter {
952
921
  accessory.addService(this.miElHvacService);
953
922
 
954
923
  //presets services
955
- if (this.presetsConfiguredCount > 0) {
924
+ if (this.presets.length > 0) {
956
925
  if (this.enableDebugMode) this.emit('debug', 'Prepare presets services');
957
926
  this.presetsServices = [];
958
927
 
959
- this.presetsConfigured.forEach((preset, index) => {
928
+ this.presets.forEach((preset, index) => {
960
929
  const { name: presetName, namePrefix, serviceType, characteristicType, mode, setTemp, fanSpeed, swingV, swingH } = preset;
961
930
  const serviceName = namePrefix ? `${accessoryName} ${presetName}` : presetName;
962
931
 
@@ -1004,11 +973,11 @@ class MiElHvac extends EventEmitter {
1004
973
  }
1005
974
 
1006
975
 
1007
- if (this.buttonsConfiguredCount > 0) {
976
+ if (this.buttons.length > 0) {
1008
977
  if (this.enableDebugMode) this.emit('debug', 'Prepare buttons services');
1009
978
  this.buttonsServices = [];
1010
979
 
1011
- this.buttonsConfigured.forEach((button, index) => {
980
+ this.buttons.forEach((button, index) => {
1012
981
  const { mode, name: buttonName, namePrefix, serviceType, characteristicType } = button;
1013
982
  const serviceName = namePrefix ? `${accessoryName} ${buttonName}` : buttonName;
1014
983
 
@@ -1127,13 +1096,12 @@ class MiElHvac extends EventEmitter {
1127
1096
  });
1128
1097
  }
1129
1098
 
1130
-
1131
1099
  //sensors services
1132
- if (this.sensorsConfiguredCount > 0) {
1100
+ if (this.sensors.length > 0) {
1133
1101
  if (this.enableDebugMode) this.emit('debug', `Prepare sensors services`);
1134
1102
  this.sensorsServices = [];
1135
1103
 
1136
- this.sensorsConfigured.forEach((sensor, index) => {
1104
+ this.sensors.forEach((sensor, index) => {
1137
1105
  //get sensor name
1138
1106
  const sensorName = sensor.name;
1139
1107
 
package/src/sensors.js CHANGED
@@ -6,7 +6,7 @@ import { ApiCommands, SensorKeys } from './constants.js';
6
6
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
7
 
8
8
  class Sensors extends EventEmitter {
9
- constructor(api, config, info, serialNumber, refreshInterval) {
9
+ constructor(api, config, info, serialNumber) {
10
10
  super();
11
11
 
12
12
  Accessory = api.platformAccessory;
@@ -24,7 +24,6 @@ class Sensors extends EventEmitter {
24
24
  this.enableDebugMode = config.enableDebugMode || false;
25
25
  this.disableLogInfo = config.disableLogInfo || false;
26
26
  this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
27
- this.refreshInterval = refreshInterval;
28
27
  this.functions = new Functions();
29
28
 
30
29
  //sensors
@@ -49,7 +48,7 @@ class Sensors extends EventEmitter {
49
48
  await this.checkState();
50
49
  }))
51
50
  .on('state', (state) => {
52
- this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
51
+ this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
53
52
  });
54
53
  }
55
54
 
@@ -192,11 +191,10 @@ class Sensors extends EventEmitter {
192
191
  }
193
192
  }
194
193
 
195
- async startImpulseGenerator() {
194
+ async startStopImpulseGenerator(state, timers = []) {
196
195
  try {
197
196
  //start impulse generator
198
- const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
199
- await this.impulseGenerator.start(timers);
197
+ await this.melCloudAta.impulseGenerator.state(state, timers)
200
198
  return true;
201
199
  } catch (error) {
202
200
  throw new Error(`Impulse generator start error: ${error}`);
package/src/switches.js CHANGED
@@ -6,7 +6,7 @@ import { ApiCommands } from './constants.js';
6
6
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
7
 
8
8
  class Switches extends EventEmitter {
9
- constructor(api, config, info, serialNumber, refreshInterval) {
9
+ constructor(api, config, info, serialNumber) {
10
10
  super();
11
11
 
12
12
  Accessory = api.platformAccessory;
@@ -26,7 +26,6 @@ class Switches extends EventEmitter {
26
26
  this.enableDebugMode = config.enableDebugMode || false;
27
27
  this.disableLogInfo = config.disableLogInfo || false;
28
28
  this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
29
- this.refreshInterval = refreshInterval;
30
29
  this.functions = new Functions();
31
30
 
32
31
  //axios instance
@@ -48,7 +47,7 @@ class Switches extends EventEmitter {
48
47
  await this.checkState();
49
48
  }))
50
49
  .on('state', (state) => {
51
- this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
50
+ this.emit(state ? 'success' : 'warn', `Impulse generator ${state ? 'started' : 'stopped'}`);
52
51
  });
53
52
  }
54
53
 
@@ -108,11 +107,10 @@ class Switches extends EventEmitter {
108
107
  }
109
108
  }
110
109
 
111
- async startImpulseGenerator() {
110
+ async startStopImpulseGenerator(state, timers = []) {
112
111
  try {
113
112
  //start impulse generator
114
- const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
115
- await this.impulseGenerator.start(timers);
113
+ await this.melCloudAta.impulseGenerator.state(state, timers)
116
114
  return true;
117
115
  } catch (error) {
118
116
  throw new Error(`Impulse generator start error: ${error}`);