homebridge-tasmota-control 0.4.4 → 0.4.5
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 +7 -0
- package/README.md +16 -12
- package/config.schema.json +1 -1
- package/index.js +52 -43
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@ 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] - (10.08.2022)
|
|
8
|
+
## Changes
|
|
9
|
+
- fix report wrong device state [#4](https://github.com/grzegorz914/homebridge-tasmota-control/issues/4)
|
|
10
|
+
- code and logs refactor
|
|
11
|
+
- add additional check configured host in config
|
|
12
|
+
- update config schema
|
|
13
|
+
|
|
7
14
|
## [0.4.4] - (23.07.2022)
|
|
8
15
|
## Changes
|
|
9
16
|
- refactor information service
|
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/
|
|
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
|
[](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,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
|
|
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
|
-
|
|
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,16 +71,16 @@ 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
|
-
## [What's New](https://github.com/grzegorz914/homebridge-tasmota-control/
|
|
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.
|
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(
|
|
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
|
|
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
|
-
|
|
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(
|
|
124
|
+
this.log.debug(`Device: ${this.host} ${this.name}, requesting info.`);
|
|
121
125
|
try {
|
|
122
|
-
const
|
|
123
|
-
const debug = this.enableDebugMode ? this.log(
|
|
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 =
|
|
126
|
-
const modelName =
|
|
127
|
-
const addressMac =
|
|
128
|
-
const firmwareRevision =
|
|
129
|
-
const channelsCount =
|
|
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.
|
|
148
|
+
this.checkDeviceState();
|
|
145
149
|
} catch (error) {
|
|
146
|
-
this.log.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
|
|
151
|
-
this.log.debug(
|
|
155
|
+
async checkDeviceState() {
|
|
156
|
+
this.log.debug(`Device: ${this.host} ${this.name}, 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: ${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 <
|
|
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(
|
|
174
|
-
this.
|
|
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
|
|
|
@@ -200,23 +208,24 @@ class tasmotaDevice {
|
|
|
200
208
|
//Prepare service
|
|
201
209
|
this.log.debug('prepareTasmotaService');
|
|
202
210
|
this.tasmotaServices = new Array();
|
|
203
|
-
|
|
211
|
+
const channelsCount = this.channelsCount;
|
|
212
|
+
for (let i = 0; i < channelsCount; i++) {
|
|
204
213
|
const tasmotaService = new Service.Outlet(accessoryName, `tasmotaService${[i]}`);
|
|
205
214
|
tasmotaService.getCharacteristic(Characteristic.On)
|
|
206
215
|
.onGet(async () => {
|
|
207
216
|
const state = this.powerState[i];
|
|
208
|
-
const logInfo = this.disableLogInfo ? false : this.log(
|
|
217
|
+
const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${accessoryName}, state: ${state ? 'ON' : 'OFF'}`);
|
|
209
218
|
return state;
|
|
210
219
|
})
|
|
211
220
|
.onSet(async (state) => {
|
|
212
|
-
const powerOn =
|
|
213
|
-
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;
|
|
214
223
|
state = state ? powerOn : powerOff;
|
|
215
224
|
try {
|
|
216
225
|
await this.axiosInstance(state);
|
|
217
|
-
const logInfo = this.disableLogInfo ? false : this.log(
|
|
226
|
+
const logInfo = this.disableLogInfo ? false : this.log(`Device: ${this.host} ${accessoryName}, set state: ${state ? 'ON' : 'OFF'}`);
|
|
218
227
|
} catch (error) {
|
|
219
|
-
this.log.error(
|
|
228
|
+
this.log.error(`Device: ${this.host} ${accessoryName}, set state error: ${error}`);
|
|
220
229
|
}
|
|
221
230
|
});
|
|
222
231
|
this.tasmotaServices.push(tasmotaService);
|
|
@@ -224,7 +233,7 @@ class tasmotaDevice {
|
|
|
224
233
|
}
|
|
225
234
|
|
|
226
235
|
this.startPrepareAccessory = false;
|
|
227
|
-
this.log.debug(
|
|
236
|
+
this.log.debug(`Device: ${this.host} ${accessoryName}, publish as external accessory.`);
|
|
228
237
|
this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]);
|
|
229
238
|
}
|
|
230
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.
|
|
4
|
+
"version": "0.4.5",
|
|
5
5
|
"description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Tasmota flashed devices.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|