homebridge-tasmota-control 0.4.3 → 0.4.5-beta.7

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,17 @@ 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.4.5] - (08.08.2022)
8
+ ## Changes
9
+ - fix report wrong device state [#4](https://github.com/grzegorz914/homebridge-tasmota-control/issues/4)
10
+ - code refactor and logs cleanup
11
+ - add additional check correct configured host in config
12
+ - update config schema
13
+
14
+ ## [0.4.4] - (23.07.2022)
15
+ ## Changes
16
+ - refactor information service
17
+
7
18
  ## [0.4.2] - (25.04.2022)
8
19
  ## Changes
9
20
  - update dependencies
package/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
  <p align="center">
2
- <a href="https://github.com/grzegorz914/homebridge-tasmota-control"><img src="https://raw.githubusercontent.com/grzegorz914/homebridge-tasmota-control/master/homebridge-tasmota-control.png" width="640"></a>
2
+ <a href="https://github.com/grzegorz914/homebridge-tasmota-control"><img src="https://raw.githubusercontent.com/grzegorz914/homebridge-tasmota-control/main/homebridge-tasmota-control.png" width="640"></a>
3
3
  </p>
4
4
 
5
5
  <span align="center">
6
6
 
7
7
  # Homebridge Tasmota Control
8
8
  [![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) [![npm](https://badgen.net/npm/v/homebridge-tasmota-control?color=purple)](https://www.npmjs.com/package/homebridge-tasmota-control)
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/v/homebridge-tasmota-control?color=purple)](https://www.npmjs.com/package/homebridge-tasmota-control)
11
+ [![npm](https://img.shields.io/npm/v/homebridge-tasmota-control/beta.svg?style=flat-square)](https://www.npmjs.com/package/homebridge-tasmota-control)
10
12
  [![GitHub pull requests](https://img.shields.io/github/issues-pr/grzegorz914/homebridge-tasmota-control.svg)](https://github.com/grzegorz914/homebridge-tasmota-control/pulls)
11
13
  [![GitHub issues](https://img.shields.io/github/issues/grzegorz914/homebridge-tasmota-control.svg)](https://github.com/grzegorz914/homebridge-tasmota-control/issues)
12
14
 
@@ -23,17 +25,19 @@ Homebridge plugin for Tasmota flashed devices.
23
25
 
24
26
  ## Note
25
27
  * Right now only switch/outlets devices are supported.
26
- * Tested with latest Tasmota 10.1.0
28
+ * Tested with Tasmota 10.1.0 and above
27
29
 
28
30
  ## Troubleshooting
29
31
  * If for some reason the device is not displayed in HomeKit app try this procedure:
30
- * Go to `./homebridge/persist`.
32
+ * Go to `./homebridge/persist` or `/var/lib/homebridge/persist` for RPI.
31
33
  * Remove `AccessoryInfo.xxx` file which contain Your device data: `{"displayName":"Tasmota"}`.
32
34
  * Next remove `IdentifierCashe.xxx` file with same name as `AccessoryInfo.xxx`.
33
35
  * Restart Homebridge and try add it to the Home app again.
34
36
 
35
- ## Configuration
36
- Install and use [Homebridge Config UI X](https://github.com/oznu/homebridge-config-ui-x/wiki) plugin to configure this plugin (Highly Recommended). The sample configuration can be edited and used manually as an alternative. See the `sample-config.json` file in this repository for an example or copy the example below into your config.json file, making the apporpriate changes before saving it. Be sure to always make a backup copy of your config.json file before making any changes to it.
37
+ ### Configuration
38
+ * Run this plugin as a child bridge (Highly Recommended).
39
+ * Install and use [Homebridge Config UI X](https://github.com/oznu/homebridge-config-ui-x/wiki) to configure this plugin (Highly Recommended).
40
+ * The sample configuration can be edited and used manually as an alternative. See the `sample-config.json` file in this repository for an example or copy the example below into your config.json file, making the apporpriate changes before saving it. Be sure to always make a backup copy of your config.json file before making any changes to it.
37
41
 
38
42
  <p align="left">
39
43
  <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>
@@ -67,16 +71,16 @@ Install and use [Homebridge Config UI X](https://github.com/oznu/homebridge-conf
67
71
  }
68
72
  ```
69
73
 
70
- ## Adding to HomeKit
74
+ ### Adding to HomeKit
71
75
  Each accessory needs to be manually paired.
72
76
  1. Open the Home <img src='https://user-images.githubusercontent.com/3979615/78010622-4ea1d380-738e-11ea-8a17-e6a465eeec35.png' width='16.42px'> app on your device.
73
- 2. Tap the <img src='https://user-images.githubusercontent.com/3979615/78010869-9aed1380-738e-11ea-9644-9f46b3633026.png' width='16.42px'>.
74
- 3. Tap *Add Accessory*, and select *I Don't Have a Code or Cannot Scan* or *More Options*.
75
- 4. Select Your accessory.
76
- 5. Enter the Homebridge PIN or scan the QR code, this can be found in Homebridge UI or Homebridge logs.
77
+ 2. Tap the Home tab, then tap <img src='https://user-images.githubusercontent.com/3979615/78010869-9aed1380-738e-11ea-9644-9f46b3633026.png' width='16.42px'>.
78
+ 3. Tap *Add Accessory*, and select *I Don't Have a Code, Cannot Scan* or *More options*.
79
+ 4. Select Your accessory and press add anyway.
80
+ 5. Enter the PIN or scan the QR code, this can be found in Homebridge UI or Homebridge logs.
77
81
  6. Complete the accessory setup.
78
82
 
79
- ## [What's New](https://github.com/grzegorz914/homebridge-tasmota-control/blob/master/CHANGELOG.md).
83
+ ## [What's New](https://github.com/grzegorz914/homebridge-tasmota-control/main/master/CHANGELOG.md).
80
84
 
81
85
  ## Development
82
86
  * Pull request and help in development highly appreciated.
@@ -2,7 +2,7 @@
2
2
  "pluginAlias": "tasmotaControl",
3
3
  "pluginType": "platform",
4
4
  "singular": true,
5
- "headerDisplay": "This plugin works with Tasmota flashed devices and are exposed to HomeKit as separate accessories and each needs to be manually paired.\n\n1. Open the Home <img src='https://user-images.githubusercontent.com/3979615/78010622-4ea1d380-738e-11ea-8a17-e6a465eeec35.png' height='16.42px'> app on your device.\n2. Tap the <img src='https://user-images.githubusercontent.com/3979615/78010869-9aed1380-738e-11ea-9644-9f46b3633026.png' height='16.42px'>.\n3. Tap *Add Accessory*, and select *I Don't Have a Code or Cannot Scan* or *More Options*.\n4. Select Your accessory.\n5. Enter the Homebridge PIN or scan the QR code, this can be found in Homebridge UI or Homebridge logs.\n6. Complete the accessory setup.",
5
+ "headerDisplay": "This plugin works with deevices flashed with Tasmota firmware. Devices are exposed to HomeKit as separate accessories and each needs to be manually paired.\n\n1. Open the Home <img src='https://user-images.githubusercontent.com/3979615/78010622-4ea1d380-738e-11ea-8a17-e6a465eeec35.png' height='16.42px'> app on your device.\n2. Tap the <img src='https://user-images.githubusercontent.com/3979615/78010869-9aed1380-738e-11ea-9644-9f46b3633026.png' height='16.42px'>.\n3. Tap *Add Accessory*, and select *I Don't Have a Code or Cannot Scan* or *More Options*.\n4. Select Your accessory and press add anyway.\n5. Enter the PIN or scan the QR code, this can be found in Homebridge UI or Homebridge logs.\n6. Complete the accessory setup.",
6
6
  "footerDisplay": "For documentation please see [GitHub repository](https://github.com/grzegorz914/homebridge-tasmota-control).",
7
7
  "schema": {
8
8
  "type": "object",
package/index.js CHANGED
@@ -33,9 +33,10 @@ class tasmotaPlatform {
33
33
  constructor(log, config, api) {
34
34
  // only load if configured
35
35
  if (!config || !Array.isArray(config.devices)) {
36
- log('No configuration found for %s', PLUGIN_NAME);
36
+ log(`No configuration found for ${deviceName}.`, PLUGIN_NAME);
37
37
  return;
38
38
  }
39
+
39
40
  this.log = log;
40
41
  this.api = api;
41
42
  this.devices = config.devices || [];
@@ -45,8 +46,8 @@ class tasmotaPlatform {
45
46
  this.log.debug('didFinishLaunching');
46
47
  for (let i = 0; i < this.devices.length; i++) {
47
48
  const device = this.devices[i];
48
- if (!device.name) {
49
- this.log.warn('Device Name Missing');
49
+ if (!device.name || !device.host) {
50
+ this.log.warn('Device name or host missing!');
50
51
  } else {
51
52
  new tasmotaDevice(this.log, device, this.api);
52
53
  }
@@ -88,8 +89,6 @@ class tasmotaDevice {
88
89
 
89
90
  //setup variables
90
91
  this.channelsCount = 0;
91
- this.checkDeviceInfo = true;
92
- this.checkDeviceState = false;
93
92
  this.startPrepareAccessory = true;
94
93
 
95
94
  this.prefDir = path.join(api.user.storagePath(), 'tasmota');
@@ -106,27 +105,32 @@ class tasmotaDevice {
106
105
  fs.mkdirSync(this.prefDir);
107
106
  }
108
107
 
109
- //Check device state
110
- setInterval(function () {
111
- if (this.checkDeviceInfo) {
112
- this.getDeviceInfo();
113
- } else {
114
- this.updateDeviceState();
115
- }
116
- }.bind(this), this.refreshInterval * 1000);
108
+ this.getDeviceInfo();
109
+ }
110
+
111
+ reconnect() {
112
+ setTimeout(() => {
113
+ this.getDeviceInfo();
114
+ }, 15000);
115
+ }
116
+
117
+ updateDeviceState() {
118
+ setTimeout(() => {
119
+ this.checkDeviceState();
120
+ }, this.refreshInterval * 1000);
117
121
  }
118
122
 
119
123
  async getDeviceInfo() {
120
- this.log.debug('Device: %s %s, requesting Device Info.', this.host, this.name);
124
+ this.log.debug(`Device: ${this.host} ${this.name}, requesting info.`);
121
125
  try {
122
- const response = await this.axiosInstance(API_COMMANDS.Status);
123
- const debug = this.enableDebugMode ? this.log('Device: %s %s, debug response: %s', this.host, this.name, JSON.stringify(response.data, null, 2)) : false;
126
+ const deviceInfo = await this.axiosInstance(API_COMMANDS.Status);
127
+ const debug = this.enableDebugMode ? this.log(`Device: ${this.host} ${this.name}, debug device info: ${JSON.stringify(deviceInfo.data, null, 2)}`) : false;
124
128
 
125
- const deviceName = response.data.Status.DeviceName;
126
- const modelName = response.data.StatusFWR.Hardware;
127
- const addressMac = response.data.StatusNET.Mac;
128
- const firmwareRevision = response.data.StatusFWR.Version;
129
- const channelsCount = response.data.Status.FriendlyName.length;
129
+ const deviceName = deviceInfo.data.Status.DeviceName;
130
+ const modelName = deviceInfo.data.StatusFWR.Hardware;
131
+ const addressMac = deviceInfo.data.StatusNET.Mac;
132
+ const firmwareRevision = deviceInfo.data.StatusFWR.Version;
133
+ const channelsCount = deviceInfo.data.Status.FriendlyName.length;
130
134
 
131
135
  this.log(`----- ${deviceName} -----`);
132
136
  this.log(`Manufacturer: ${this.manufacturer}`);
@@ -134,45 +138,49 @@ class tasmotaDevice {
134
138
  this.log(`Serialnr: ${addressMac}`);
135
139
  this.log(`Firmware: ${firmwareRevision}`);
136
140
  this.log(`Channels: ${channelsCount}`);
137
- this.log('----------------------------------');
141
+ this.log(`----------------------------------`);
138
142
 
139
143
  this.modelName = modelName;
140
144
  this.serialNumber = addressMac;
141
145
  this.firmwareRevision = firmwareRevision;
142
146
  this.channelsCount = channelsCount;
143
147
 
144
- this.checkDeviceInfo = (channelsCount == 0);
148
+ this.checkDeviceState();
145
149
  } catch (error) {
146
- this.log.error('Device: %s %s, Device Info eror: %s, state: Offline, trying to reconnect', this.host, this.name, error);
150
+ this.log.error(`Device: ${this.host} ${this.name}, check info error: ${error}, trying to reconnect in 15s.`);
151
+ this.reconnect();
147
152
  }
148
153
  }
149
154
 
150
- async updateDeviceState() {
151
- this.log.debug('Device: %s %s, requesting Device state.', this.host, this.name);
155
+ async checkDeviceState() {
156
+ this.log.debug(`Device: ${this.host} ${this.name}, requesting state.`, this.host, this.name);
152
157
  try {
153
- const response = await this.axiosInstance(API_COMMANDS.PowerStatus);
154
- const debug = this.enableDebugMode ? this.log('Device: %s %s, debug response: %s', this.host, this.name, JSON.stringify(response.data, null, 2)) : false;
158
+ const channelsCount = this.channelsCount;
159
+ const deviceState = await this.axiosInstance(API_COMMANDS.PowerStatus);
160
+ const debug = this.enableDebugMode ? this.log(`Device: ${this.host} ${this.name}, debug state: ${JSON.stringify(deviceState.data, null, 2)}`) : false;
155
161
 
156
162
  this.powerState = new Array();
157
- for (let i = 0; i < this.channelsCount; i++) {
158
- const channel = this.channelsCount == 1 ? 'POWER' : 'POWER' + (i + 1);
159
- const powerState = (response.data[channel] == 'ON');
163
+ for (let i = 0; i < channelsCount; i++) {
164
+ const channel = channelsCount == 1 ? 'POWER' || 'POWER1' : 'POWER' + (i + 1);
165
+ const powerState = (deviceState.data[channel] == 'ON');
166
+
160
167
  if (this.tasmotaServices) {
161
168
  this.tasmotaServices[i]
162
169
  .updateCharacteristic(Characteristic.On, powerState)
163
170
  }
171
+
164
172
  this.powerState.push(powerState);
165
173
  }
166
- this.checkDeviceState = true;
174
+
175
+ this.updateDeviceState();
167
176
 
168
177
  //start prepare accessory
169
- if (this.startPrepareAccessory) {
178
+ if (this.startPrepareAccessory && this.serialNumber) {
170
179
  this.prepareAccessory();
171
180
  }
172
181
  } catch (error) {
173
- this.log.error('Device: %s %s, update Device state error: %s, state: Offline', this.host, this.name, error);
174
- this.checkDeviceState = false;
175
- this.checkDeviceInfo = true;
182
+ this.log.error(`Device: ${this.host} ${this.name}, check state error: ${error}, trying again.`);
183
+ this.updateDeviceState();
176
184
  }
177
185
  }
178
186
 
@@ -191,36 +199,33 @@ class tasmotaDevice {
191
199
  const serialNumber = this.serialNumber;
192
200
  const firmwareRevision = this.firmwareRevision;
193
201
 
194
- accessory.removeService(accessory.getService(Service.AccessoryInformation));
195
- const informationService = new Service.AccessoryInformation();
196
- informationService
197
- .setCharacteristic(Characteristic.Name, accessoryName)
202
+ accessory.getService(Service.AccessoryInformation)
198
203
  .setCharacteristic(Characteristic.Manufacturer, manufacturer)
199
204
  .setCharacteristic(Characteristic.Model, modelName)
200
205
  .setCharacteristic(Characteristic.SerialNumber, serialNumber)
201
206
  .setCharacteristic(Characteristic.FirmwareRevision, firmwareRevision);
202
- accessory.addService(informationService);
203
207
 
204
208
  //Prepare service
205
209
  this.log.debug('prepareTasmotaService');
206
210
  this.tasmotaServices = new Array();
207
- for (let i = 0; i < this.channelsCount; i++) {
211
+ const channelsCount = this.channelsCount;
212
+ for (let i = 0; i < channelsCount; i++) {
208
213
  const tasmotaService = new Service.Outlet(accessoryName, `tasmotaService${[i]}`);
209
214
  tasmotaService.getCharacteristic(Characteristic.On)
210
215
  .onGet(async () => {
211
216
  const state = this.powerState[i];
212
- const logInfo = this.disableLogInfo ? false : this.log('Device: %s %s, get state: %s', this.host, accessoryName, state ? 'ON' : 'OFF');
217
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${accessoryName}, state: ${state ? 'ON' : 'OFF'}`);
213
218
  return state;
214
219
  })
215
220
  .onSet(async (state) => {
216
- const powerOn = this.channelsCount == 1 ? API_COMMANDS.Power + API_COMMANDS.On : API_COMMANDS.Power + (i + 1) + API_COMMANDS.On;
217
- const powerOff = this.channelsCount == 1 ? API_COMMANDS.Power + API_COMMANDS.Off : API_COMMANDS.Power + (i + 1) + API_COMMANDS.Off;
221
+ const powerOn = (channelsCount == 1) ? API_COMMANDS.Power + API_COMMANDS.On : API_COMMANDS.Power + (i + 1) + API_COMMANDS.On;
222
+ const powerOff = (channelsCount == 1) ? API_COMMANDS.Power + API_COMMANDS.Off : API_COMMANDS.Power + (i + 1) + API_COMMANDS.Off;
218
223
  state = state ? powerOn : powerOff;
219
224
  try {
220
225
  await this.axiosInstance(state);
221
- const logInfo = this.disableLogInfo ? false : this.log('Device: %s %s, set state: %s', this.host, accessoryName, state ? 'ON' : 'OFF');
226
+ const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${accessoryName}, set state: ${state ? 'ON' : 'OFF'}`);
222
227
  } catch (error) {
223
- this.log.error('Device: %s %s, set state: %s', this.host, this.name, error);
228
+ this.log.error(`Device: ${this.host} ${accessoryName}, set state error: ${error}`);
224
229
  }
225
230
  });
226
231
  this.tasmotaServices.push(tasmotaService);
@@ -228,7 +233,7 @@ class tasmotaDevice {
228
233
  }
229
234
 
230
235
  this.startPrepareAccessory = false;
231
- this.log.debug('Device: %s %s, publishExternalAccessories.', this.host, accessoryName);
236
+ this.log.debug(`Device: ${this.host} ${accessoryName}, publish as external accessory.`);
232
237
  this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
233
238
  }
234
239
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Tasmota Control",
3
3
  "name": "homebridge-tasmota-control",
4
- "version": "0.4.3",
4
+ "version": "0.4.5-beta.7",
5
5
  "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Tasmota flashed devices.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",