homebridge-tasmota-control 1.5.1-beta.2 → 1.5.1-beta.21

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
@@ -8,6 +8,7 @@ import Fans from './src/fans.js';
8
8
  import Sensors from './src/sensors.js';
9
9
  import ImpulseGenerator from './src/impulsegenerator.js';
10
10
  import { PluginName, PlatformName } from './src/constants.js';
11
+ import CustomCharacteristics from './src/customcharacteristics.js';
11
12
 
12
13
  class tasmotaPlatform {
13
14
  constructor(log, config, api) {
@@ -56,7 +57,7 @@ class tasmotaPlatform {
56
57
  const disableLogSuccess = device.disableLogSuccess || false;
57
58
  const disableLogWarn = device.disableLogWarn || false;
58
59
  const disableLogError = device.disableLogError || false;
59
- const debug = enableDebugMode ? log.info(`Device: ${host} ${deviceName}, debug: Did finish launching.`) : false;
60
+ const debug = !enableDebugMode ? false : log.info(`Device: ${host} ${deviceName}, debug: Did finish launching.`);
60
61
  const newConfig = {
61
62
  ...device,
62
63
  user: 'removed',
@@ -70,6 +71,9 @@ class tasmotaPlatform {
70
71
  deviceInfo.on('debug', (debug) => {
71
72
  const emitLog = !enableDebugMode ? false : log.info(`Device: ${host} ${deviceName}, debug: ${debug}.`);
72
73
  })
74
+ .on('debug', (debug) => {
75
+ const emitLog = !enableDebugMode ? false : log.info(`Device: ${host} ${deviceName}, debug: ${debug}.`);
76
+ })
73
77
  .on('warn', (warn) => {
74
78
  const emitLog = disableLogWarn ? false : log.warn(`Device: ${host} ${deviceName}, ${warn}.`);
75
79
  })
@@ -144,7 +148,7 @@ class tasmotaPlatform {
144
148
  const emitLog = disableLogInfo ? false : log.info(`Device: ${host} ${deviceName}, ${info}.`);
145
149
  })
146
150
  .on('debug', (debug) => {
147
- const emitLog = enableDebugMode ? false : log.info(`Device: ${host} ${deviceName}, debug: ${debug}.`);
151
+ const emitLog = !enableDebugMode ? false : log.info(`Device: ${host} ${deviceName}, debug: ${debug}.`);
148
152
  })
149
153
  .on('warn', (warn) => {
150
154
  const emitLog = disableLogWarn ? false : log.warn(`Device: ${host} ${deviceName}, ${warn}.`);
@@ -186,5 +190,6 @@ class tasmotaPlatform {
186
190
  }
187
191
 
188
192
  export default (api) => {
193
+ CustomCharacteristics(api);
189
194
  api.registerPlatform(PluginName, PlatformName, tasmotaPlatform);
190
195
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Tasmota Control",
3
3
  "name": "homebridge-tasmota-control",
4
- "version": "1.5.1-beta.2",
4
+ "version": "1.5.1-beta.21",
5
5
  "description": "Homebridge plugin to control Tasmota flashed devices.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",
@@ -0,0 +1,198 @@
1
+ export default (api) => {
2
+ const { Service, Characteristic, Units, Formats, Perms } = api.hap;
3
+
4
+ //Envoy production/consumption characteristics
5
+ class Power extends Characteristic {
6
+ constructor() {
7
+ super('Power', '00000071-000B-1000-8000-0026BB765291');
8
+ this.setProps({
9
+ format: Formats.FLOAT,
10
+ unit: 'W',
11
+ maxValue: 10000,
12
+ minValue: -10000,
13
+ minStep: 0.001,
14
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
15
+ });
16
+ this.value = this.getDefaultValue();
17
+ }
18
+ }
19
+ Characteristic.Power = Power;
20
+
21
+ class ApparentPower extends Characteristic {
22
+ constructor() {
23
+ super('Apparent power', '00000072-000B-1000-8000-0026BB765291');
24
+ this.setProps({
25
+ format: Formats.FLOAT,
26
+ unit: 'VA',
27
+ maxValue: 10000,
28
+ minValue: -10000,
29
+ minStep: 0.001,
30
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
31
+ });
32
+ this.value = this.getDefaultValue();
33
+ }
34
+ }
35
+ Characteristic.ApparentPower = ApparentPower;
36
+
37
+ class ReactivePower extends Characteristic {
38
+ constructor() {
39
+ super('Reactive power', '00000073-000B-1000-8000-0026BB765291');
40
+ this.setProps({
41
+ format: Formats.FLOAT,
42
+ unit: 'VAr',
43
+ maxValue: 10000,
44
+ minValue: -10000,
45
+ minStep: 0.001,
46
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
47
+ });
48
+ this.value = this.getDefaultValue();
49
+ }
50
+ }
51
+ Characteristic.ReactivePower = ReactivePower;
52
+
53
+ class EnergyToday extends Characteristic {
54
+ constructor() {
55
+ super('Energy today', '00000074-000B-1000-8000-0026BB765291');
56
+ this.setProps({
57
+ format: Formats.FLOAT,
58
+ unit: 'kWh',
59
+ maxValue: 1000,
60
+ minValue: -1000,
61
+ minStep: 0.001,
62
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
63
+ });
64
+ this.value = this.getDefaultValue();
65
+ }
66
+ }
67
+ Characteristic.EnergyToday = EnergyToday;
68
+
69
+ class EnergyLastDay extends Characteristic {
70
+ constructor() {
71
+ super('Energy last day', '00000075-000B-1000-8000-0026BB765291');
72
+ this.setProps({
73
+ format: Formats.FLOAT,
74
+ unit: 'kWh',
75
+ maxValue: 1000,
76
+ minValue: -1000,
77
+ minStep: 0.001,
78
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
79
+ });
80
+ this.value = this.getDefaultValue();
81
+ }
82
+ }
83
+ Characteristic.EnergyLastDay = EnergyLastDay;
84
+
85
+ class EnergyLifetime extends Characteristic {
86
+ constructor() {
87
+ super('Energy lifetime', '00000076-000B-1000-8000-0026BB765291');
88
+ this.setProps({
89
+ format: Formats.FLOAT,
90
+ unit: 'kWh',
91
+ maxValue: 100000000,
92
+ minValue: -100000000,
93
+ minStep: 0.001,
94
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
95
+ });
96
+ this.value = this.getDefaultValue();
97
+ }
98
+ }
99
+ Characteristic.EnergyLifetime = EnergyLifetime;
100
+
101
+ class Current extends Characteristic {
102
+ constructor() {
103
+ super('Current', '00000077-000B-1000-8000-0026BB765291');
104
+ this.setProps({
105
+ format: Formats.FLOAT,
106
+ unit: 'A',
107
+ maxValue: 1000,
108
+ minValue: -1000,
109
+ minStep: 0.001,
110
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
111
+ });
112
+ this.value = this.getDefaultValue();
113
+ }
114
+ }
115
+ Characteristic.Current = Current;
116
+
117
+ class Voltage extends Characteristic {
118
+ constructor() {
119
+ super('Voltage', '00000078-000B-1000-8000-0026BB765291');
120
+ this.setProps({
121
+ format: Formats.FLOAT,
122
+ unit: 'V',
123
+ maxValue: 1000,
124
+ minValue: 0,
125
+ minStep: 0.1,
126
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
127
+ });
128
+ this.value = this.getDefaultValue();
129
+ }
130
+ }
131
+ Characteristic.Voltage = Voltage;
132
+
133
+ class Factor extends Characteristic {
134
+ constructor() {
135
+ super('Power factor', '00000079-000B-1000-8000-0026BB765291');
136
+ this.setProps({
137
+ format: Formats.FLOAT,
138
+ unit: 'cos φ',
139
+ maxValue: 1,
140
+ minValue: -1,
141
+ minStep: 0.01,
142
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
143
+ });
144
+ this.value = this.getDefaultValue();
145
+ }
146
+ }
147
+ Characteristic.Factor = Factor;
148
+
149
+ class Freqency extends Characteristic {
150
+ constructor() {
151
+ super('Frequency', '00000080-000B-1000-8000-0026BB765291');
152
+ this.setProps({
153
+ format: Formats.FLOAT,
154
+ unit: 'Hz',
155
+ maxValue: 100,
156
+ minValue: 0,
157
+ minStep: 0.01,
158
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
159
+ });
160
+ this.value = this.getDefaultValue();
161
+ }
162
+ }
163
+ Characteristic.Freqency = Freqency;
164
+
165
+ class ReadingTime extends Characteristic {
166
+ constructor() {
167
+ super('Reading time', '00000081-000B-1000-8000-0026BB765291');
168
+ this.setProps({
169
+ format: Formats.STRING,
170
+ perms: [Perms.PAIRED_READ, Perms.NOTIFY]
171
+ });
172
+ this.value = this.getDefaultValue();
173
+ }
174
+ }
175
+ Characteristic.ReadingTime = ReadingTime;
176
+
177
+ //power production service
178
+ class PowerAndEnergyService extends Service {
179
+ constructor(displayName, subtype) {
180
+ super(displayName, '00000004-000A-1000-8000-0026BB765291', subtype);
181
+ // Mandatory Characteristics
182
+ this.addCharacteristic(Characteristic.Power)
183
+ // Optional Characteristics
184
+ this.addOptionalCharacteristic(Characteristic.ApparentPower);
185
+ this.addOptionalCharacteristic(Characteristic.ReactivePower);
186
+ this.addOptionalCharacteristic(Characteristic.EnergyToday);
187
+ this.addOptionalCharacteristic(Characteristic.EnergyLastDay);
188
+ this.addOptionalCharacteristic(Characteristic.EnergyLifetime);
189
+ this.addOptionalCharacteristic(Characteristic.Current);
190
+ this.addOptionalCharacteristic(Characteristic.Voltage);
191
+ this.addOptionalCharacteristic(Characteristic.Factor);
192
+ this.addOptionalCharacteristic(Characteristic.Freqency);
193
+ this.addOptionalCharacteristic(Characteristic.ReadingTime);
194
+ this.addOptionalCharacteristic(Characteristic.ConfiguredName);
195
+ }
196
+ }
197
+ Service.PowerAndEnergyService = PowerAndEnergyService;
198
+ };
package/src/deviceinfo.js CHANGED
@@ -54,13 +54,6 @@ class DeviceInfo extends EventEmitter {
54
54
  //status SNS
55
55
  const statusSns = deviceInfo.StatusSNS ?? {};
56
56
  const statusSnsKeys = Object.keys(statusSns);
57
- const sensor = Object.entries(statusSns)
58
- .filter(([key]) => SensorKeys.some(type => key.includes(type)))
59
- .reduce((obj, [key, value]) => {
60
- obj[key] = value;
61
- return obj;
62
- }, {});
63
- this.emit('debug', `Sensor: ${JSON.stringify(sensor, null, 2)}`)
64
57
 
65
58
  //status STS
66
59
  const statusSts = deviceInfo.StatusSTS ?? {};
@@ -73,14 +66,17 @@ class DeviceInfo extends EventEmitter {
73
66
  const fans = statusStsKeys.includes('FanSpeed') ? types.push(3) : false;
74
67
  const switches = !mielhvac && !lights && !fans ? types.push(1) : false
75
68
  const sensors = statusSnsKeys.some(key => SensorKeys.includes(key)) ? types.push(4) : false;
69
+ const sensorName = Object.entries(statusSns).filter(([key]) => SensorKeys.some(type => key.includes(type))).reduce((obj, [key, value]) => { return key; }, {});
76
70
  const obj = {
77
71
  deviceTypes: types,
78
72
  deviceName: deviceName,
73
+ sensorName: sensorName,
79
74
  friendlyNames: friendlyNames,
80
75
  modelName: modelName,
81
76
  serialNumber: addressMac,
82
77
  firmwareRevision: firmwareRevision
83
78
  };
79
+ this.emit('debug', `Sensor: ${JSON.stringify(obj, null, 2)}`)
84
80
  return obj;
85
81
  } catch (error) {
86
82
  throw new Error(`Check info error: ${error}`);
package/src/mielhvac.js CHANGED
@@ -814,7 +814,7 @@ class MiElHvac extends EventEmitter {
814
814
  this.emit('devInfo', `Hardware: ${this.info.modelName}`);
815
815
  this.emit('devInfo', `Serialnr: ${this.serialNumber}`)
816
816
  this.emit('devInfo', `Firmware: ${this.info.firmwareRevision}`);
817
- this.emit('devInfo', `Sensor: MiELHVAC`);
817
+ this.emit('devInfo', `Device: MiELHVAC`);
818
818
  this.emit('devInfo', `----------------------------------`);
819
819
  return;
820
820
  }
package/src/sensors.js CHANGED
@@ -100,10 +100,9 @@ class Sensors extends EventEmitter {
100
100
  //sensor
101
101
  const obj = {
102
102
  name: key,
103
- time: sensorStatus.Time,
104
- tempUnit: sensorStatus.TempUnit === 'C' ? '°C' : 'F',
105
- pressureUnit: sensorStatus.PressureUnit ?? 'hPa',
106
-
103
+ time: statusSns.Time,
104
+ tempUnit: statusSns.TempUnit,
105
+ pressureUnit: statusSns.PressureUnit,
107
106
  temperature: sensorData.Temperature,
108
107
  referenceTemperature: sensorData.ReferenceTemperature,
109
108
  objTemperature: sensorData.OBJTMP,
@@ -114,26 +113,30 @@ class Sensors extends EventEmitter {
114
113
  gas: sensorData.Gas,
115
114
  carbonDioxyde: sensorData.CarbonDioxyde,
116
115
  ambientLight: sensorData.Ambient,
117
- motion: sensorData.Motion ? sensorData.Motion === 'ON' : null
116
+ motion: sensorData.Motion
117
+ }
118
+ if (obj.tempUnit === 'C') {
119
+ obj.tempUnit = '°C';
118
120
  }
119
121
 
120
122
  //energy
121
123
  const obj1 = {
122
- energyTotalStartTime: sensorData.TotalStartTime,
123
- energyTotal: sensorData.Total,
124
- energyPeriod: sensorData.Period,
125
- energyYesterday: sensorData.Yesterday,
126
- energyToday: sensorData.Today,
127
124
  power: sensorData.Power,
128
125
  apparentPower: sensorData.ApparentPower,
129
126
  reactivePower: sensorData.ReactivePower,
130
- factor: sensorData.Factor,
131
- voltage: sensorData.Voltage,
127
+ energyToday: sensorData.Today,
128
+ energyLastDay: sensorData.Yesterday,
129
+ energyLifetime: sensorData.Total,
130
+ energyLifeTimeStartTime: sensorData.TotalStartTime,
131
+ energyPeriod: sensorData.Period,
132
132
  current: sensorData.Current,
133
+ voltage: sensorData.Voltage,
134
+ factor: sensorData.Factor,
135
+ frequency: sensorData.Frequency,
133
136
  load: sensorData.Load,
134
137
  }
135
138
  const sensor = key === 'ENERGY' ? { ...obj, ...obj1 } : obj;
136
- this.emit('debug', `Sensors status: ${JSON.stringify(sensor, null, 2)}`)
139
+ const debug1 = this.enableDebugMode ? this.emit('debug', `Sensor: ${JSON.stringify(sensor, null, 2)}`) : false;
137
140
 
138
141
  //push to array
139
142
  this.sensors.push(sensor);
@@ -144,18 +147,33 @@ class Sensors extends EventEmitter {
144
147
  if (this.sensorsCount > 0) {
145
148
  for (let i = 0; i < this.sensorsCount; i++) {
146
149
  const sensor = this.sensors[i];
150
+
147
151
  this.sensorTemperatureServices?.[i]?.updateCharacteristic(Characteristic.CurrentTemperature, sensor.temperature);
148
152
  this.sensorReferenceTemperatureServices?.[i]?.updateCharacteristic(Characteristic.CurrentTemperature, sensor.referenceTemperature);
149
153
  this.sensorObjTemperatureServices?.[i]?.updateCharacteristic(Characteristic.CurrentTemperature, sensor.objTemperature);
150
154
  this.sensorAmbTemperatureServices?.[i]?.updateCharacteristic(Characteristic.CurrentTemperature, sensor.ambTemperature);
151
155
  this.sensorDewPointTemperatureServices?.[i]?.updateCharacteristic(Characteristic.CurrentTemperature, sensor.dewPointTemperature);
152
156
  this.sensorHumidityServices?.[i]?.updateCharacteristic(Characteristic.CurrentRelativeHumidity, sensor.humidity);
153
- this.sensorCarbonDioxydeServices?.[i]
154
- ?.updateCharacteristic(Characteristic.CarbonDioxideDetected, sensor.carbonDioxyde > 1000)
155
- .updateCharacteristic(Characteristic.CarbonDioxideLevel, sensor.carbonDioxyde)
156
- .updateCharacteristic(Characteristic.CarbonDioxidePeakLevel, sensor.carbonDioxyde);
157
+
158
+ const co2Service = this.sensorCarbonDioxydeServices?.[i];
159
+ co2Service?.updateCharacteristic(Characteristic.CarbonDioxideDetected, sensor.carbonDioxyde > 1000);
160
+ co2Service?.updateCharacteristic(Characteristic.CarbonDioxideLevel, sensor.carbonDioxyde);
161
+ co2Service?.updateCharacteristic(Characteristic.CarbonDioxidePeakLevel, sensor.carbonDioxyde);
162
+
157
163
  this.sensorAmbientLightServices?.[i]?.updateCharacteristic(Characteristic.CurrentAmbientLightLevel, sensor.ambientLight);
158
164
  this.sensorMotionServices?.[i]?.updateCharacteristic(Characteristic.MotionDetected, sensor.motion);
165
+
166
+
167
+ //energy
168
+ const fields = [
169
+ 'Power', 'ApparentPower', 'ReactivePower', 'EnergyToday', 'EnergyLastDay',
170
+ 'EnergyLifetime', 'Current', 'Voltage', 'Factor', 'Frequency', 'ReadingTime'
171
+ ];
172
+ const characteristic = this.sensorEnergyServices?.[i]?.Characteristic;
173
+ for (const key of fields) {
174
+ characteristic?.[key]?.updateCharacteristic(Characteristic[key], sensor[key.toLowerCase()]);
175
+ }
176
+
159
177
  }
160
178
  }
161
179
  }
@@ -203,7 +221,7 @@ class Sensors extends EventEmitter {
203
221
  this.emit('devInfo', `Hardware: ${this.info.modelName}`);
204
222
  this.emit('devInfo', `Serialnr: ${this.serialNumber}`)
205
223
  this.emit('devInfo', `Firmware: ${this.info.firmwareRevision}`);
206
- this.emit('devInfo', `Sensors: ${this.sensorsCount}`);
224
+ this.emit('devInfo', `Sensor: ${this.info.sensorName}`);
207
225
  this.emit('devInfo', `----------------------------------`);
208
226
  return;
209
227
  }
@@ -403,6 +421,104 @@ class Sensors extends EventEmitter {
403
421
  });
404
422
  this.sensorMotionServices.push(sensorMotionService);
405
423
  }
424
+
425
+ //energy
426
+ if (sensor.name === 'ENERGY') {
427
+ const debug4 = this.enableDebugMode ? this.emit('debug', `Prepare Power And Energy Service`) : false;
428
+ this.sensorEnergyServices = [];
429
+ const serviceName = this.sensorsNamePrefix ? `${accessoryName} ${sensorName} Power And Energy` : `${sensorName} Power And Energy`;
430
+ const energyService = accessory.addService(Service.PowerAndEnergyService, serviceName, 'energyService');
431
+ energyService.setCharacteristic(Characteristic.ConfiguredName, serviceName);
432
+ if (sensor.power) {
433
+ energyService.getCharacteristic(Characteristic.Power)
434
+ .onGet(async () => {
435
+ const value = sensor.power;
436
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} power: ${value} W`);
437
+ return value;
438
+ });
439
+ }
440
+ if (sensor.apparentPower) {
441
+ energyService.getCharacteristic(Characteristic.ApparentPower)
442
+ .onGet(async () => {
443
+ const value = sensor.apparentPower;
444
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} apparent power: ${value} VA`);
445
+ return value;
446
+ });
447
+ }
448
+ if (sensor.reactivePower) {
449
+ energyService.getCharacteristic(Characteristic.ReactivePower)
450
+ .onGet(async () => {
451
+ const value = sensor.reactivePower;
452
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} reactive power: ${value} VAr`);
453
+ return value;
454
+ });
455
+ }
456
+ if (sensor.energyToday) {
457
+ energyService.getCharacteristic(Characteristic.EnergyToday)
458
+ .onGet(async () => {
459
+ const value = sensor.energyToday;
460
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} energy today: ${value} kWh`);
461
+ return value;
462
+ });
463
+ }
464
+ if (sensor.energyLastDay) {
465
+ energyService.getCharacteristic(Characteristic.EnergyLastDay)
466
+ .onGet(async () => {
467
+ const value = sensor.energyLastDay;
468
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} energy last day: ${value} kWh`);
469
+ return value;
470
+ });
471
+ }
472
+ if (sensor.energyLifetime) {
473
+ energyService.getCharacteristic(Characteristic.EnergyLifetime)
474
+ .onGet(async () => {
475
+ const value = sensor.energyLifetime;
476
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} energy lifetime: ${value} kWh`);
477
+ return value;
478
+ });
479
+ }
480
+ if (sensor.current) {
481
+ energyService.getCharacteristic(Characteristic.Current)
482
+ .onGet(async () => {
483
+ const value = sensor.current;
484
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} current: ${value} A`);
485
+ return value;
486
+ });
487
+ }
488
+ if (sensor.voltage) {
489
+ energyService.getCharacteristic(Characteristic.Voltage)
490
+ .onGet(async () => {
491
+ const value = sensor.voltage;
492
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} voltage: ${value} V`);
493
+ return value;
494
+ });
495
+ }
496
+ if (sensor.factor) {
497
+ energyService.getCharacteristic(Characteristic.Factor)
498
+ .onGet(async () => {
499
+ const value = sensor.factor;
500
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} power factor: ${value} cos φ`);
501
+ return value;
502
+ });
503
+ }
504
+ if (sensor.frequency) {
505
+ energyService.getCharacteristic(Characteristic.Freqency)
506
+ .onGet(async () => {
507
+ const value = sensor.frequency;
508
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} frequency: ${value} Hz`);
509
+ return value;
510
+ });
511
+ }
512
+ if (sensor.time) {
513
+ energyService.getCharacteristic(Characteristic.ReadingTime)
514
+ .onGet(async () => {
515
+ const value = sensor.time;
516
+ const info = this.disableLogInfo ? false : this.emit('info', `sensor: ${sensorName} last report: ${value}`);
517
+ return value;
518
+ });
519
+ }
520
+ this.sensorEnergyServices.push(energyService);
521
+ }
406
522
  i++;
407
523
  }
408
524
  }