homebridge-tasmota-control 1.6.15-beta.30 → 1.6.15-beta.32

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Tasmota Control",
3
3
  "name": "homebridge-tasmota-control",
4
- "version": "1.6.15-beta.30",
4
+ "version": "1.6.15-beta.32",
5
5
  "description": "Homebridge plugin to control Tasmota flashed devices.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
package/src/fans.js CHANGED
@@ -2,6 +2,7 @@ import { promises as fsPromises } from 'fs';
2
2
  import axios from 'axios';
3
3
  import EventEmitter from 'events';
4
4
  import ImpulseGenerator from './impulsegenerator.js';
5
+ import Functions from './functions.js';
5
6
  import { ApiCommands } from './constants.js';
6
7
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
8
 
@@ -27,12 +28,13 @@ class Fans extends EventEmitter {
27
28
  this.disableLogInfo = config.disableLogInfo || false;
28
29
  this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
29
30
  this.refreshInterval = refreshInterval;
31
+ this.functions = new Functions();
30
32
 
31
33
  //axios instance
32
34
  const url = `http://${config.host}/cm?cmnd=`;
33
35
  this.axiosInstance = axios.create({
34
36
  baseURL: url,
35
- timeout: 10000,
37
+ timeout: 15000,
36
38
  withCredentials: config.auth,
37
39
  auth: {
38
40
  username: config.user,
@@ -40,27 +42,33 @@ class Fans extends EventEmitter {
40
42
  }
41
43
  });
42
44
 
43
- //impulse generator
44
- this.call = false;
45
+ //lock flags
46
+ this.locks = {
47
+ checkState: false,
48
+ };
45
49
  this.impulseGenerator = new ImpulseGenerator()
46
- .on('checkDeviceState', async () => {
47
- if (this.call) return;
48
-
49
- try {
50
- this.call = true;
51
- await this.checkDeviceState();
52
- this.call = false;
53
- } catch (error) {
54
- this.call = false;
55
- this.emit('error', `Inpulse generator error: ${error}`);
56
- };
57
- })
50
+ .on('checkState', () => this.handleWithLock('checkState', async () => {
51
+ await this.checkState();
52
+ }))
58
53
  .on('state', (state) => {
59
54
  this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
60
55
  });
61
56
  }
62
57
 
63
- async checkDeviceState() {
58
+ async handleWithLock(lockKey, fn) {
59
+ if (this.locks[lockKey]) return;
60
+
61
+ this.locks[lockKey] = true;
62
+ try {
63
+ await fn();
64
+ } catch (error) {
65
+ this.emit('error', `Inpulse generator error: ${error}`);
66
+ } finally {
67
+ this.locks[lockKey] = false;
68
+ }
69
+ }
70
+
71
+ async checkState() {
64
72
  if (this.enableDebugMode) this.emit('debug', `Requesting status`);
65
73
  try {
66
74
  //power status
@@ -151,30 +159,10 @@ class Fans extends EventEmitter {
151
159
  }
152
160
  }
153
161
 
154
- async saveData(path, data) {
155
- try {
156
- data = JSON.stringify(data, null, 2);
157
- await fsPromises.writeFile(path, data);
158
- if (this.enableDebugMode) this.emit('debug', `Saved data: ${data}`);
159
- return true;
160
- } catch (error) {
161
- throw new Error(`Save data error: ${error}`);
162
- }
163
- }
164
-
165
- async readData(path) {
166
- try {
167
- const data = await fsPromises.readFile(path);
168
- return data;
169
- } catch (error) {
170
- throw new Error(`Read data error: ${error}`);
171
- }
172
- }
173
-
174
162
  async startImpulseGenerator() {
175
163
  try {
176
164
  //start impulse generator
177
- const timers = [{ name: 'checkDeviceState', sampling: this.refreshInterval }];
165
+ const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
178
166
  await this.impulseGenerator.start(timers);
179
167
  return true;
180
168
  } catch (error) {
@@ -528,7 +516,7 @@ class Fans extends EventEmitter {
528
516
  async start() {
529
517
  try {
530
518
  //check device state
531
- await this.checkDeviceState();
519
+ await this.checkState();
532
520
 
533
521
  //connect to deice success
534
522
  this.emit('success', `Connect Success`)
@@ -0,0 +1,31 @@
1
+ import { promises as fsPromises } from 'fs';
2
+
3
+ class Functions {
4
+ constructor(config) {
5
+ }
6
+
7
+ async saveData(path, data) {
8
+ try {
9
+ data = JSON.stringify(data, null, 2);
10
+ await fsPromises.writeFile(path, data);
11
+ return true;
12
+ } catch (error) {
13
+ throw new Error(`Save data error: ${error}`);
14
+ }
15
+ }
16
+
17
+ async readData(path) {
18
+ try {
19
+ const data = await fsPromises.readFile(path);
20
+ return data;
21
+ } catch (error) {
22
+ throw new Error(`Read data error: ${error}`);
23
+ }
24
+ }
25
+
26
+ async scaleValue(value, inMin, inMax, outMin, outMax) {
27
+ const scaledValue = parseFloat((((Math.max(inMin, Math.min(inMax, value)) - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin).toFixed(0));
28
+ return scaledValue;
29
+ }
30
+ }
31
+ export default Functions
package/src/lights.js CHANGED
@@ -2,6 +2,7 @@ import { promises as fsPromises } from 'fs';
2
2
  import axios from 'axios';
3
3
  import EventEmitter from 'events';
4
4
  import ImpulseGenerator from './impulsegenerator.js';
5
+ import Functions from './functions.js';
5
6
  import { ApiCommands } from './constants.js';
6
7
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
8
 
@@ -26,12 +27,13 @@ class Lights extends EventEmitter {
26
27
  this.disableLogInfo = config.disableLogInfo || false;
27
28
  this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
28
29
  this.refreshInterval = refreshInterval;
30
+ this.functions = new Functions();
29
31
 
30
32
  //axios instance
31
33
  const url = `http://${config.host}/cm?cmnd=`;
32
34
  this.axiosInstance = axios.create({
33
35
  baseURL: url,
34
- timeout: 10000,
36
+ timeout: 15000,
35
37
  withCredentials: config.auth,
36
38
  auth: {
37
39
  username: config.user,
@@ -39,26 +41,33 @@ class Lights extends EventEmitter {
39
41
  }
40
42
  });
41
43
 
42
- this.call = false;
44
+ //lock flags
45
+ this.locks = {
46
+ checkState: false,
47
+ };
43
48
  this.impulseGenerator = new ImpulseGenerator()
44
- .on('checkDeviceState', async () => {
45
- if (this.call) return;
46
-
47
- try {
48
- this.call = true;
49
- await this.checkDeviceState();
50
- this.call = false;
51
- } catch (error) {
52
- this.call = false;
53
- this.emit('error', `Inpulse generator error: ${error}`);
54
- };
55
- })
49
+ .on('checkState', () => this.handleWithLock('checkState', async () => {
50
+ await this.checkState();
51
+ }))
56
52
  .on('state', (state) => {
57
53
  this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
58
54
  });
59
55
  }
60
56
 
61
- async checkDeviceState() {
57
+ async handleWithLock(lockKey, fn) {
58
+ if (this.locks[lockKey]) return;
59
+
60
+ this.locks[lockKey] = true;
61
+ try {
62
+ await fn();
63
+ } catch (error) {
64
+ this.emit('error', `Inpulse generator error: ${error}`);
65
+ } finally {
66
+ this.locks[lockKey] = false;
67
+ }
68
+ }
69
+
70
+ async checkState() {
62
71
  if (this.enableDebugMode) this.emit('debug', `Requesting status`);
63
72
  try {
64
73
  //power status
@@ -95,7 +104,7 @@ class Lights extends EventEmitter {
95
104
 
96
105
  //color temperature scale tasmota 153..500 to homekit 140..500
97
106
  const colorTemp = statusSts.CT ?? false;
98
- const colorTemperature = colorTemp !== false ? await this.scaleValue(colorTemp, 153, 500, 140, 500) : false;
107
+ const colorTemperature = colorTemp !== false ? await this.functions.scaleValue(colorTemp, 153, 500, 140, 500) : false;
99
108
 
100
109
  //hasb color map to array number
101
110
  const hsbColor = statusSts.HSBColor ? statusSts.HSBColor.split(',').map((value) => Number(value.trim())) : false;
@@ -158,35 +167,10 @@ class Lights extends EventEmitter {
158
167
  }
159
168
  }
160
169
 
161
- async scaleValue(value, inMin, inMax, outMin, outMax) {
162
- const scaledValue = parseFloat((((Math.max(inMin, Math.min(inMax, value)) - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin).toFixed(0));
163
- return scaledValue;
164
- }
165
-
166
- async saveData(path, data) {
167
- try {
168
- data = JSON.stringify(data, null, 2);
169
- await fsPromises.writeFile(path, data);
170
- if (this.enableDebugMode) this.emit('debug', `Saved data: ${data}`);
171
- return true;
172
- } catch (error) {
173
- throw new Error(`Save data error: ${error}`);
174
- }
175
- }
176
-
177
- async readData(path) {
178
- try {
179
- const data = await fsPromises.readFile(path);
180
- return data;
181
- } catch (error) {
182
- throw new Error(`Read data error: ${error}`);
183
- }
184
- }
185
-
186
170
  async startImpulseGenerator() {
187
171
  try {
188
172
  //start impulse generator
189
- const timers = [{ name: 'checkDeviceState', sampling: this.refreshInterval }];
173
+ const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
190
174
  await this.impulseGenerator.start(timers);
191
175
  return true;
192
176
  } catch (error) {
@@ -280,7 +264,7 @@ class Lights extends EventEmitter {
280
264
  })
281
265
  .onSet(async (value) => {
282
266
  try {
283
- value = await this.scaleValue(value, 140, 500, 153, 500);
267
+ value = await this.functions.scaleValue(value, 140, 500, 153, 500);
284
268
  const colorTemperature = `${ApiCommands.ColorTemperature}${value}`; //153..500
285
269
  await this.axiosInstance.get(colorTemperature);
286
270
  if (!this.disableLogInfo) this.emit('info', `${friendlyName}, set color temperatur: ${value}`);
@@ -335,7 +319,7 @@ class Lights extends EventEmitter {
335
319
  async start() {
336
320
  try {
337
321
  //check device state
338
- await this.checkDeviceState();
322
+ await this.checkState();
339
323
 
340
324
  //connect to deice success
341
325
  this.emit('success', `Connect Success`)
package/src/mielhvac.js CHANGED
@@ -2,6 +2,7 @@ import { promises as fsPromises } from 'fs';
2
2
  import axios from 'axios';
3
3
  import EventEmitter from 'events';
4
4
  import ImpulseGenerator from './impulsegenerator.js';
5
+ import Functions from './functions.js';
5
6
  import { ApiCommands, MiElHVAC, TemperatureDisplayUnits } from './constants.js';
6
7
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
8
 
@@ -40,8 +41,8 @@ class MiElHvac extends EventEmitter {
40
41
  const presets = miElHvac.presets || [];
41
42
  this.presetsConfigured = [];
42
43
  for (const preset of presets) {
43
- const displayType = preset.displayType ?? 0;
44
- if (displayType === 0) {
44
+ const displayType = preset.displayType;
45
+ if (!displayType) {
45
46
  continue;
46
47
  }
47
48
 
@@ -60,8 +61,8 @@ class MiElHvac extends EventEmitter {
60
61
  const buttons = miElHvac.buttons || [];
61
62
  this.buttonsConfigured = [];
62
63
  for (const button of buttons) {
63
- const displayType = button.displayType ?? 0;
64
- if (displayType === 0) {
64
+ const displayType = button.displayType;
65
+ if (!displayType) {
65
66
  continue;
66
67
  }
67
68
 
@@ -80,8 +81,8 @@ class MiElHvac extends EventEmitter {
80
81
  const sensors = miElHvac.sensors || [];
81
82
  this.sensorsConfigured = [];
82
83
  for (const sensor of sensors) {
83
- const displayType = sensor.displayType ?? 0;
84
- if (displayType === 0) {
84
+ const displayType = sensor.displayType;
85
+ if (!displayType) {
85
86
  continue;
86
87
  }
87
88
 
@@ -118,12 +119,13 @@ class MiElHvac extends EventEmitter {
118
119
  this.mielHvac = {};
119
120
  this.previousStateSwingV = 'auto';
120
121
  this.previousStateSwingH = 'center';
122
+ this.functions = new Functions();
121
123
 
122
124
  //axios instance
123
125
  const url = `http://${config.host}/cm?cmnd=`;
124
126
  this.axiosInstance = axios.create({
125
127
  baseURL: url,
126
- timeout: 10000,
128
+ timeout: 15000,
127
129
  withCredentials: config.auth,
128
130
  auth: {
129
131
  username: config.user,
@@ -144,39 +146,37 @@ class MiElHvac extends EventEmitter {
144
146
  });
145
147
  }
146
148
 
147
- //impulse generator
148
- this.call = false;
149
- this.call1 = false;
149
+ //lock flags
150
+ this.locks = {
151
+ checkState: false,
152
+ updateRemoteTemp: false,
153
+ };
150
154
  this.impulseGenerator = new ImpulseGenerator()
151
- .on('checkDeviceState', async () => {
152
- if (this.call) return;
153
-
154
- try {
155
- this.call = true;
156
- await this.checkDeviceState();
157
- this.call = false;
158
- } catch (error) {
159
- this.call = false;
160
- this.emit('error', `Inpulse generator error: ${error}`);
161
- };
162
- })
163
- .on('updateRemoteTemp', async () => {
164
- if (this.call1) return;
165
-
166
- try {
167
- this.call1 = true;
168
- await this.updateRemoteTemp();
169
- } catch (error) {
170
- this.call1 = false;
171
- this.emit('error', `Impulse generator error: ${error}`);
172
- }
173
- })
155
+ .on('checkState', () => this.handleWithLock('checkState', async () => {
156
+ await this.checkState();
157
+ }))
158
+ .on('updateRemoteTemp', () => this.handleWithLock('updateRemoteTemp', async () => {
159
+ await this.checkState();
160
+ }))
174
161
  .on('state', (state) => {
175
162
  this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
176
163
  });
177
164
  }
178
165
 
179
- async checkDeviceState() {
166
+ async handleWithLock(lockKey, fn) {
167
+ if (this.locks[lockKey]) return;
168
+
169
+ this.locks[lockKey] = true;
170
+ try {
171
+ await fn();
172
+ } catch (error) {
173
+ this.emit('error', `Inpulse generator error: ${error}`);
174
+ } finally {
175
+ this.locks[lockKey] = false;
176
+ }
177
+ }
178
+
179
+ async checkState() {
180
180
  if (this.enableDebugMode) this.emit('debug', `Requesting status`);
181
181
  try {
182
182
  //power status
@@ -232,8 +232,8 @@ class MiElHvac extends EventEmitter {
232
232
  const operationEnergy = miElHvac.OperationEnergy ?? 0;
233
233
  const operationStatus = miElHvac.OperationStatus ?? 'Unknown';
234
234
  const swingMode = vaneVerticalDirection === 'swing' && vaneHorizontalDirection === 'swing' ? 1 : 0;
235
- const defaultCoolingSetTemperature = parseFloat(await this.readData(this.info.defaultCoolingSetTemperatureFile));
236
- const defaultHeatingSetTemperature = parseFloat(await this.readData(this.info.defaultHeatingSetTemperatureFile));
235
+ const defaultCoolingSetTemperature = parseFloat(await this.functions.readData(this.info.defaultCoolingSetTemperatureFile));
236
+ const defaultHeatingSetTemperature = parseFloat(await this.functions.readData(this.info.defaultHeatingSetTemperatureFile));
237
237
  const remoteTemperatureSensorState = miElHvac.RemoteTemperatureSensorState ?? false; //ON, OFF
238
238
  const remoteTemperatureSensorAutoClearTime = miElHvac.RemoteTemperatureSensorAutoClearTime ?? 0; //time in ms
239
239
 
@@ -721,30 +721,10 @@ class MiElHvac extends EventEmitter {
721
721
  }
722
722
  }
723
723
 
724
- async saveData(path, data) {
725
- try {
726
- data = JSON.stringify(data, null, 2);
727
- await fsPromises.writeFile(path, data);
728
- if (this.enableDebugMode) this.emit('debug', `Saved data: ${data}`);
729
- return true;
730
- } catch (error) {
731
- throw new Error(`Save data error: ${error}`);
732
- }
733
- }
734
-
735
- async readData(path) {
736
- try {
737
- const data = await fsPromises.readFile(path);
738
- return data;
739
- } catch (error) {
740
- throw new Error(`Read data error: ${error}`);
741
- }
742
- }
743
-
744
724
  async startImpulseGenerator() {
745
725
  try {
746
726
  //start impulse generator
747
- const timers = [{ name: 'checkDeviceState', sampling: this.refreshInterval }];
727
+ const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
748
728
  if (this.remoteTemperatureSensorEnable) timers.push({ name: 'updateRemoteTemp', sampling: this.remoteTemperatureSensorRefreshInterval });
749
729
  await this.impulseGenerator.start(timers);
750
730
  return true;
@@ -934,7 +914,7 @@ class MiElHvac extends EventEmitter {
934
914
  .onSet(async (value) => {
935
915
  try {
936
916
  if (this.mielHvac.targetOperationMode === 0) {
937
- await this.saveData(this.info.defaultCoolingSetTemperatureFile, value);
917
+ await this.functions.saveData(this.info.defaultCoolingSetTemperatureFile, value);
938
918
  value = (value + this.info.mielHvac.defaultHeatingSetTemperature) / 2;
939
919
  }
940
920
 
@@ -959,7 +939,7 @@ class MiElHvac extends EventEmitter {
959
939
  .onSet(async (value) => {
960
940
  try {
961
941
  if (this.mielHvac.targetOperationMode === 0) {
962
- await this.saveData(this.info.defaultHeatingSetTemperatureFile, value);
942
+ await this.functions.saveData(this.info.defaultHeatingSetTemperatureFile, value);
963
943
  value = (value + this.info.mielHvac.defaultCoolingSetTemperature) / 2;
964
944
  }
965
945
 
@@ -1254,7 +1234,7 @@ class MiElHvac extends EventEmitter {
1254
1234
  async start() {
1255
1235
  try {
1256
1236
  //check device state
1257
- const checkState = await this.checkDeviceState();
1237
+ const checkState = await this.checkState();
1258
1238
  if (!checkState) return null;
1259
1239
 
1260
1240
  //connect to deice success
package/src/sensors.js CHANGED
@@ -2,6 +2,7 @@ import { promises as fsPromises } from 'fs';
2
2
  import axios from 'axios';
3
3
  import EventEmitter from 'events';
4
4
  import ImpulseGenerator from './impulsegenerator.js';
5
+ import Functions from './functions.js';
5
6
  import { ApiCommands, SensorKeys } from './constants.js';
6
7
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
8
 
@@ -25,6 +26,7 @@ class Sensors extends EventEmitter {
25
26
  this.disableLogInfo = config.disableLogInfo || false;
26
27
  this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
27
28
  this.refreshInterval = refreshInterval;
29
+ this.functions = new Functions();
28
30
 
29
31
  //sensors
30
32
  this.sensorsCount = 0;
@@ -33,7 +35,7 @@ class Sensors extends EventEmitter {
33
35
  const url = `http://${config.host}/cm?cmnd=`;
34
36
  this.axiosInstance = axios.create({
35
37
  baseURL: url,
36
- timeout: 10000,
38
+ timeout: 15000,
37
39
  withCredentials: config.auth,
38
40
  auth: {
39
41
  username: config.user,
@@ -41,27 +43,33 @@ class Sensors extends EventEmitter {
41
43
  }
42
44
  });
43
45
 
44
- //impulse generator
45
- this.call = false;
46
+ //lock flags
47
+ this.locks = {
48
+ checkState: false,
49
+ };
46
50
  this.impulseGenerator = new ImpulseGenerator()
47
- .on('checkDeviceState', async () => {
48
- if (this.call) return;
49
-
50
- try {
51
- this.call = true;
52
- await this.checkDeviceState();
53
- this.call = false;
54
- } catch (error) {
55
- this.call = false;
56
- this.emit('error', `Inpulse generator error: ${error}`);
57
- };
58
- })
51
+ .on('checkState', () => this.handleWithLock('checkState', async () => {
52
+ await this.checkState();
53
+ }))
59
54
  .on('state', (state) => {
60
55
  this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
61
56
  });
62
57
  }
63
58
 
64
- async checkDeviceState() {
59
+ async handleWithLock(lockKey, fn) {
60
+ if (this.locks[lockKey]) return;
61
+
62
+ this.locks[lockKey] = true;
63
+ try {
64
+ await fn();
65
+ } catch (error) {
66
+ this.emit('error', `Inpulse generator error: ${error}`);
67
+ } finally {
68
+ this.locks[lockKey] = false;
69
+ }
70
+ }
71
+
72
+ async checkState() {
65
73
  if (this.enableDebugMode) this.emit('debug', `Requesting status`);
66
74
  try {
67
75
  //sensor status
@@ -189,30 +197,10 @@ class Sensors extends EventEmitter {
189
197
  }
190
198
  }
191
199
 
192
- async saveData(path, data) {
193
- try {
194
- data = JSON.stringify(data, null, 2);
195
- await fsPromises.writeFile(path, data);
196
- if (this.enableDebugMode) this.emit('debug', `Saved data: ${data}`);
197
- return true;
198
- } catch (error) {
199
- throw new Error(`Save data error: ${error}`);
200
- }
201
- }
202
-
203
- async readData(path) {
204
- try {
205
- const data = await fsPromises.readFile(path);
206
- return data;
207
- } catch (error) {
208
- throw new Error(`Read data error: ${error}`);
209
- }
210
- }
211
-
212
200
  async startImpulseGenerator() {
213
201
  try {
214
202
  //start impulse generator
215
- const timers = [{ name: 'checkDeviceState', sampling: this.refreshInterval }];
203
+ const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
216
204
  await this.impulseGenerator.start(timers);
217
205
  return true;
218
206
  } catch (error) {
@@ -538,7 +526,7 @@ class Sensors extends EventEmitter {
538
526
  async start() {
539
527
  try {
540
528
  //check device state
541
- await this.checkDeviceState();
529
+ await this.checkState();
542
530
 
543
531
  //connect to deice success
544
532
  this.emit('success', `Connect Success`)
package/src/switches.js CHANGED
@@ -2,6 +2,7 @@ import { promises as fsPromises } from 'fs';
2
2
  import axios from 'axios';
3
3
  import EventEmitter from 'events';
4
4
  import ImpulseGenerator from './impulsegenerator.js';
5
+ import Functions from './functions.js';
5
6
  import { ApiCommands } from './constants.js';
6
7
  let Accessory, Characteristic, Service, Categories, AccessoryUUID;
7
8
 
@@ -27,12 +28,13 @@ class Switches extends EventEmitter {
27
28
  this.disableLogInfo = config.disableLogInfo || false;
28
29
  this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
29
30
  this.refreshInterval = refreshInterval;
31
+ this.functions = new Functions();
30
32
 
31
33
  //axios instance
32
34
  const url = `http://${config.host}/cm?cmnd=`;
33
35
  this.axiosInstance = axios.create({
34
36
  baseURL: url,
35
- timeout: 10000,
37
+ timeout: 15000,
36
38
  withCredentials: config.auth,
37
39
  auth: {
38
40
  username: config.user,
@@ -40,27 +42,33 @@ class Switches extends EventEmitter {
40
42
  }
41
43
  });
42
44
 
43
- //impulse generator
44
- this.call = false;
45
+ //lock flags
46
+ this.locks = {
47
+ checkState: false,
48
+ };
45
49
  this.impulseGenerator = new ImpulseGenerator()
46
- .on('checkDeviceState', async () => {
47
- if (this.call) return;
48
-
49
- try {
50
- this.call = true;
51
- await this.checkDeviceState();
52
- this.call = false;
53
- } catch (error) {
54
- this.call = false;
55
- this.emit('error', `Inpulse generator error: ${error}`);
56
- };
57
- })
50
+ .on('checkState', () => this.handleWithLock('checkState', async () => {
51
+ await this.checkState();
52
+ }))
58
53
  .on('state', (state) => {
59
54
  this.emit('success', `Impulse generator ${state ? 'started' : 'stopped'}.`);
60
55
  });
61
56
  }
62
57
 
63
- async checkDeviceState() {
58
+ async handleWithLock(lockKey, fn) {
59
+ if (this.locks[lockKey]) return;
60
+
61
+ this.locks[lockKey] = true;
62
+ try {
63
+ await fn();
64
+ } catch (error) {
65
+ this.emit('error', `Inpulse generator error: ${error}`);
66
+ } finally {
67
+ this.locks[lockKey] = false;
68
+ }
69
+ }
70
+
71
+ async checkState() {
64
72
  if (this.enableDebugMode) this.emit('debug', `Requesting status`);
65
73
  try {
66
74
  //power status
@@ -107,30 +115,10 @@ class Switches extends EventEmitter {
107
115
  }
108
116
  }
109
117
 
110
- async saveData(path, data) {
111
- try {
112
- data = JSON.stringify(data, null, 2);
113
- await fsPromises.writeFile(path, data);
114
- if (this.enableDebugMode) this.emit('debug', `Saved data: ${data}`);
115
- return true;
116
- } catch (error) {
117
- throw new Error(`Save data error: ${error}`);
118
- }
119
- }
120
-
121
- async readData(path) {
122
- try {
123
- const data = await fsPromises.readFile(path);
124
- return data;
125
- } catch (error) {
126
- throw new Error(`Read data error: ${error}`);
127
- }
128
- }
129
-
130
118
  async startImpulseGenerator() {
131
119
  try {
132
120
  //start impulse generator
133
- const timers = [{ name: 'checkDeviceState', sampling: this.refreshInterval }];
121
+ const timers = [{ name: 'checkState', sampling: this.refreshInterval }];
134
122
  await this.impulseGenerator.start(timers);
135
123
  return true;
136
124
  } catch (error) {
@@ -215,7 +203,7 @@ class Switches extends EventEmitter {
215
203
  async start() {
216
204
  try {
217
205
  //check device state
218
- await this.checkDeviceState();
206
+ await this.checkState();
219
207
 
220
208
  //connect to deice success
221
209
  this.emit('success', `Connect Success`)