homebridge-tasmota-control 0.4.2 → 0.4.5-beta.6
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 +11 -0
- package/README.md +13 -9
- package/config.schema.json +1 -1
- package/index.js +42 -37
- package/package.json +2 -2
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
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
# Homebridge Tasmota Control
|
|
8
8
|
[](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
|
|
9
|
-
[](https://www.npmjs.com/package/homebridge-tasmota-control)
|
|
9
|
+
[](https://www.npmjs.com/package/homebridge-tasmota-control)
|
|
10
|
+
[](https://www.npmjs.com/package/homebridge-tasmota-control)
|
|
11
|
+
[](https://www.npmjs.com/package/homebridge-tasmota-control)
|
|
10
12
|
[](https://github.com/grzegorz914/homebridge-tasmota-control/pulls)
|
|
11
13
|
[](https://github.com/grzegorz914/homebridge-tasmota-control/issues)
|
|
12
14
|
|
|
@@ -23,7 +25,7 @@ Homebridge plugin for Tasmota flashed devices.
|
|
|
23
25
|
|
|
24
26
|
## Note
|
|
25
27
|
* Right now only switch/outlets devices are supported.
|
|
26
|
-
* Tested with
|
|
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:
|
|
@@ -32,8 +34,10 @@ Homebridge plugin for Tasmota flashed devices.
|
|
|
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
|
-
|
|
36
|
-
|
|
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,13 +71,13 @@ Install and use [Homebridge Config UI X](https://github.com/oznu/homebridge-conf
|
|
|
67
71
|
}
|
|
68
72
|
```
|
|
69
73
|
|
|
70
|
-
|
|
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
|
|
75
|
-
4. Select Your accessory.
|
|
76
|
-
5. Enter the
|
|
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
83
|
## [What's New](https://github.com/grzegorz914/homebridge-tasmota-control/blob/master/CHANGELOG.md).
|
package/config.schema.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"pluginAlias": "tasmotaControl",
|
|
3
3
|
"pluginType": "platform",
|
|
4
4
|
"singular": true,
|
|
5
|
-
"headerDisplay": "This plugin works with
|
|
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 %s.', 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
|
|
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,18 +105,23 @@ class tasmotaDevice {
|
|
|
106
105
|
fs.mkdirSync(this.prefDir);
|
|
107
106
|
}
|
|
108
107
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
|
124
|
+
this.log.debug('Device: %s %s, requesting info.', this.host, this.name);
|
|
121
125
|
try {
|
|
122
126
|
const response = await this.axiosInstance(API_COMMANDS.Status);
|
|
123
127
|
const debug = this.enableDebugMode ? this.log('Device: %s %s, debug response: %s', this.host, this.name, JSON.stringify(response.data, null, 2)) : false;
|
|
@@ -141,38 +145,42 @@ class tasmotaDevice {
|
|
|
141
145
|
this.firmwareRevision = firmwareRevision;
|
|
142
146
|
this.channelsCount = channelsCount;
|
|
143
147
|
|
|
144
|
-
this.
|
|
148
|
+
this.checkDeviceState();
|
|
145
149
|
} catch (error) {
|
|
146
|
-
this.log.error('Device: %s %s,
|
|
150
|
+
this.log.error('Device: %s %s, check info error: %s, trying to reconnect in 15s.', this.host, this.name, error);
|
|
151
|
+
this.reconnect();
|
|
147
152
|
}
|
|
148
153
|
}
|
|
149
154
|
|
|
150
|
-
async
|
|
151
|
-
this.log.debug('Device: %s %s, requesting
|
|
155
|
+
async checkDeviceState() {
|
|
156
|
+
this.log.debug('Device: %s %s, requesting state.', this.host, this.name);
|
|
152
157
|
try {
|
|
153
|
-
const
|
|
154
|
-
const
|
|
158
|
+
const channelsCount = this.channelsCount;
|
|
159
|
+
const deviceState = await this.axiosInstance(API_COMMANDS.PowerStatus);
|
|
160
|
+
const debug = this.enableDebugMode ? this.log('Device: %s %s, debug deviceState: %s', this.host, this.name, JSON.stringify(deviceState.data, null, 2)) : false;
|
|
155
161
|
|
|
156
162
|
this.powerState = new Array();
|
|
157
|
-
for (let i = 0; i <
|
|
158
|
-
const channel =
|
|
159
|
-
const powerState = (
|
|
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
|
-
|
|
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,
|
|
174
|
-
this.
|
|
175
|
-
this.checkDeviceInfo = true;
|
|
182
|
+
this.log.error('Device: %s %s, check state error: %s, trying again.', this.host, this.name, error);
|
|
183
|
+
this.updateDeviceState();
|
|
176
184
|
}
|
|
177
185
|
}
|
|
178
186
|
|
|
@@ -191,20 +199,17 @@ class tasmotaDevice {
|
|
|
191
199
|
const serialNumber = this.serialNumber;
|
|
192
200
|
const firmwareRevision = this.firmwareRevision;
|
|
193
201
|
|
|
194
|
-
accessory.
|
|
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
|
-
|
|
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 () => {
|
|
@@ -213,14 +218,14 @@ class tasmotaDevice {
|
|
|
213
218
|
return state;
|
|
214
219
|
})
|
|
215
220
|
.onSet(async (state) => {
|
|
216
|
-
const powerOn =
|
|
217
|
-
const powerOff =
|
|
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
226
|
const logInfo = this.disableLogInfo ? false : this.log('Device: %s %s, set state: %s', this.host, accessoryName, 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: %s %s, set state error: %s', this.host, this.name, error);
|
|
224
229
|
}
|
|
225
230
|
});
|
|
226
231
|
this.tasmotaServices.push(tasmotaService);
|
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.
|
|
4
|
+
"version": "0.4.5-beta.6",
|
|
5
5
|
"description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Tasmota flashed devices.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"homebridge": ">=1.3.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"axios": "^0.27.
|
|
34
|
+
"axios": "^0.27.2"
|
|
35
35
|
},
|
|
36
36
|
"keywords": [
|
|
37
37
|
"homebridge",
|