@switchbot/homebridge-switchbot 1.3.0 → 1.3.1-beta.11
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 +12 -1
- package/config.schema.json +12 -25
- package/dist/devices/bots.d.ts +2 -0
- package/dist/devices/bots.d.ts.map +1 -1
- package/dist/devices/bots.js +137 -96
- package/dist/devices/bots.js.map +1 -1
- package/dist/devices/colorbulb.d.ts +1 -0
- package/dist/devices/colorbulb.d.ts.map +1 -1
- package/dist/devices/colorbulb.js +18 -4
- package/dist/devices/colorbulb.js.map +1 -1
- package/dist/devices/contact.js +1 -1
- package/dist/devices/contact.js.map +1 -1
- package/dist/devices/curtains.d.ts.map +1 -1
- package/dist/devices/curtains.js +7 -2
- package/dist/devices/curtains.js.map +1 -1
- package/dist/devices/humidifiers.d.ts +1 -0
- package/dist/devices/humidifiers.d.ts.map +1 -1
- package/dist/devices/humidifiers.js +16 -3
- package/dist/devices/humidifiers.js.map +1 -1
- package/dist/devices/indoorcam.d.ts +32 -3
- package/dist/devices/indoorcam.d.ts.map +1 -1
- package/dist/devices/indoorcam.js +103 -45
- package/dist/devices/indoorcam.js.map +1 -1
- package/dist/devices/meters.d.ts +2 -11
- package/dist/devices/meters.d.ts.map +1 -1
- package/dist/devices/meters.js +8 -38
- package/dist/devices/meters.js.map +1 -1
- package/dist/devices/plugs.d.ts +2 -0
- package/dist/devices/plugs.d.ts.map +1 -1
- package/dist/devices/plugs.js +42 -17
- package/dist/devices/plugs.js.map +1 -1
- package/dist/irdevices/airconditioners.d.ts +2 -0
- package/dist/irdevices/airconditioners.d.ts.map +1 -1
- package/dist/irdevices/airconditioners.js +18 -2
- package/dist/irdevices/airconditioners.js.map +1 -1
- package/dist/irdevices/airpurifiers.d.ts +2 -0
- package/dist/irdevices/airpurifiers.d.ts.map +1 -1
- package/dist/irdevices/airpurifiers.js +18 -1
- package/dist/irdevices/airpurifiers.js.map +1 -1
- package/dist/irdevices/cameras.d.ts +1 -0
- package/dist/irdevices/cameras.d.ts.map +1 -1
- package/dist/irdevices/cameras.js +10 -1
- package/dist/irdevices/cameras.js.map +1 -1
- package/dist/irdevices/fans.d.ts +1 -0
- package/dist/irdevices/fans.d.ts.map +1 -1
- package/dist/irdevices/fans.js +10 -1
- package/dist/irdevices/fans.js.map +1 -1
- package/dist/irdevices/lights.d.ts +1 -0
- package/dist/irdevices/lights.d.ts.map +1 -1
- package/dist/irdevices/lights.js +10 -1
- package/dist/irdevices/lights.js.map +1 -1
- package/dist/irdevices/others.d.ts +1 -0
- package/dist/irdevices/others.d.ts.map +1 -1
- package/dist/irdevices/others.js +10 -1
- package/dist/irdevices/others.js.map +1 -1
- package/dist/irdevices/tvs.d.ts +1 -0
- package/dist/irdevices/tvs.d.ts.map +1 -1
- package/dist/irdevices/tvs.js +10 -1
- package/dist/irdevices/tvs.js.map +1 -1
- package/dist/irdevices/vacuumcleaners.d.ts +1 -0
- package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
- package/dist/irdevices/vacuumcleaners.js +10 -1
- package/dist/irdevices/vacuumcleaners.js.map +1 -1
- package/dist/irdevices/waterheaters.d.ts +1 -0
- package/dist/irdevices/waterheaters.d.ts.map +1 -1
- package/dist/irdevices/waterheaters.js +10 -1
- package/dist/irdevices/waterheaters.js.map +1 -1
- package/dist/platform.d.ts +2 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +109 -23
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +6 -5
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/homebridge-ui/public/index.html +5 -1
- package/package.json +66 -66
- package/src/devices/bots.ts +125 -86
- package/src/devices/colorbulb.ts +18 -4
- package/src/devices/contact.ts +1 -1
- package/src/devices/curtains.ts +8 -3
- package/src/devices/humidifiers.ts +18 -4
- package/src/devices/indoorcam.ts +129 -50
- package/src/devices/meters.ts +10 -39
- package/src/devices/plugs.ts +46 -19
- package/src/irdevices/airconditioners.ts +18 -2
- package/src/irdevices/airpurifiers.ts +19 -1
- package/src/irdevices/cameras.ts +11 -1
- package/src/irdevices/fans.ts +11 -1
- package/src/irdevices/lights.ts +11 -1
- package/src/irdevices/others.ts +11 -1
- package/src/irdevices/tvs.ts +11 -1
- package/src/irdevices/vacuumcleaners.ts +11 -1
- package/src/irdevices/waterheaters.ts +11 -1
- package/src/platform.ts +109 -23
- package/src/settings.ts +7 -5
package/src/devices/indoorcam.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AxiosResponse } from 'axios';
|
|
2
2
|
import { interval, Subject } from 'rxjs';
|
|
3
3
|
import { SwitchBotPlatform } from '../platform';
|
|
4
|
-
import { debounceTime, skipWhile, tap } from 'rxjs/operators';
|
|
4
|
+
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
5
5
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
6
6
|
import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
|
|
7
7
|
|
|
@@ -10,8 +10,13 @@ export class IndoorCam {
|
|
|
10
10
|
private service: Service;
|
|
11
11
|
|
|
12
12
|
// Characteristic Values
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
Active!: CharacteristicValue;
|
|
14
|
+
SetupEndpoints!: CharacteristicValue;
|
|
15
|
+
StreamingStatus!: CharacteristicValue;
|
|
16
|
+
SupportedRTPConfiguration!: CharacteristicValue;
|
|
17
|
+
SelectedRTPStreamConfiguration!: CharacteristicValue;
|
|
18
|
+
SupportedVideoStreamConfiguration!: CharacteristicValue;
|
|
19
|
+
SupportedAudioStreamConfiguration!: CharacteristicValue;
|
|
15
20
|
|
|
16
21
|
// OpenAPI Others
|
|
17
22
|
deviceStatus!: deviceStatusResponse;
|
|
@@ -29,9 +34,12 @@ export class IndoorCam {
|
|
|
29
34
|
private accessory: PlatformAccessory,
|
|
30
35
|
public device: device & devicesConfig,
|
|
31
36
|
) {
|
|
37
|
+
// Indoor Cam Config
|
|
38
|
+
this.platform.device(`Indoor Cam: ${this.accessory.displayName} Config: (hide_device: ${device.hide_device})`);
|
|
39
|
+
|
|
40
|
+
this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} was added but will not work as OpenAPI doesn't support it yet.`);
|
|
32
41
|
// default placeholders
|
|
33
|
-
this.
|
|
34
|
-
this.OutletInUse = true;
|
|
42
|
+
this.SelectedRTPStreamConfiguration;
|
|
35
43
|
|
|
36
44
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
37
45
|
this.doCameraUpdate = new Subject();
|
|
@@ -50,8 +58,8 @@ export class IndoorCam {
|
|
|
50
58
|
// get the WindowCovering service if it exists, otherwise create a new WindowCovering service
|
|
51
59
|
// you can create multiple services for each accessory
|
|
52
60
|
(this.service =
|
|
53
|
-
accessory.getService(this.platform.Service.
|
|
54
|
-
accessory.addService(this.platform.Service.
|
|
61
|
+
accessory.getService(this.platform.Service.CameraRTPStreamManagement) ||
|
|
62
|
+
accessory.addService(this.platform.Service.CameraRTPStreamManagement)), `${accessory.displayName} Indoor Camera`;
|
|
55
63
|
|
|
56
64
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
57
65
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
@@ -65,9 +73,26 @@ export class IndoorCam {
|
|
|
65
73
|
// see https://developers.homebridge.io/#/service/WindowCovering
|
|
66
74
|
|
|
67
75
|
// create handlers for required characteristics
|
|
68
|
-
this.service.getCharacteristic(this.platform.Characteristic.
|
|
76
|
+
this.service.getCharacteristic(this.platform.Characteristic.Active)
|
|
77
|
+
.onSet(this.ActiveSet.bind(this));
|
|
78
|
+
|
|
79
|
+
this.service.getCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration)
|
|
80
|
+
.onSet(this.SelectedRTPStreamConfigurationSet.bind(this));
|
|
81
|
+
|
|
82
|
+
this.service.getCharacteristic(this.platform.Characteristic.SetupEndpoints)
|
|
83
|
+
.onSet(this.SetupEndpointsSet.bind(this));
|
|
84
|
+
|
|
85
|
+
this.service.getCharacteristic(this.platform.Characteristic.StreamingStatus)
|
|
86
|
+
.onSet(this.StreamingStatusSet.bind(this));
|
|
69
87
|
|
|
70
|
-
this.service.
|
|
88
|
+
this.service.getCharacteristic(this.platform.Characteristic.SupportedAudioStreamConfiguration)
|
|
89
|
+
.onSet(this.SupportedAudioStreamConfigurationSet.bind(this));
|
|
90
|
+
|
|
91
|
+
this.service.getCharacteristic(this.platform.Characteristic.SupportedRTPConfiguration)
|
|
92
|
+
.onSet(this.SupportedRTPConfigurationSet.bind(this));
|
|
93
|
+
|
|
94
|
+
this.service.getCharacteristic(this.platform.Characteristic.SupportedVideoStreamConfiguration)
|
|
95
|
+
.onSet(this.SupportedVideoStreamConfigurationSet.bind(this));
|
|
71
96
|
|
|
72
97
|
// Update Homekit
|
|
73
98
|
this.updateHomeKitCharacteristics();
|
|
@@ -108,14 +133,7 @@ export class IndoorCam {
|
|
|
108
133
|
}
|
|
109
134
|
|
|
110
135
|
parseStatus() {
|
|
111
|
-
|
|
112
|
-
case 'on':
|
|
113
|
-
this.On = true;
|
|
114
|
-
break;
|
|
115
|
-
default:
|
|
116
|
-
this.On = false;
|
|
117
|
-
}
|
|
118
|
-
this.platform.debug(`Indoor Cam ${this.accessory.displayName} On: ${this.On}`);
|
|
136
|
+
this.platform.debug(`Indoor Cam ${this.accessory.displayName} SelectedRTPStreamConfiguration: ${this.SelectedRTPStreamConfiguration}`);
|
|
119
137
|
}
|
|
120
138
|
|
|
121
139
|
|
|
@@ -146,45 +164,42 @@ export class IndoorCam {
|
|
|
146
164
|
* Camera - "command" "turnOn" "default" = set to ON state
|
|
147
165
|
*/
|
|
148
166
|
async pushChanges() {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
167
|
+
if (!this.Active) {
|
|
168
|
+
const payload = {
|
|
169
|
+
commandType: 'command',
|
|
170
|
+
parameter: 'default',
|
|
171
|
+
command: 'turnOn',
|
|
172
|
+
} as payload;
|
|
173
|
+
|
|
174
|
+
this.platform.log.info(`Indoor Cam: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
|
|
175
|
+
+ ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
|
|
176
|
+
|
|
177
|
+
// Make the API request
|
|
178
|
+
const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
|
|
179
|
+
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
|
|
180
|
+
this.statusCode(push);
|
|
181
|
+
interval(5000)
|
|
182
|
+
.pipe(skipWhile(() => this.cameraUpdateInProgress))
|
|
183
|
+
.pipe(take(1))
|
|
184
|
+
.subscribe(() => {
|
|
185
|
+
this.refreshStatus();
|
|
186
|
+
});
|
|
156
187
|
} else {
|
|
157
|
-
|
|
188
|
+
this.platform.device(`Indoor Cam: ${this.accessory.displayName} No pushChanges. Active: ${this.Active}`);
|
|
158
189
|
}
|
|
159
|
-
|
|
160
|
-
this.platform.log.info(`Indoor Cam: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
|
|
161
|
-
+ ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
|
|
162
|
-
|
|
163
|
-
// Make the API request
|
|
164
|
-
const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
|
|
165
|
-
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
|
|
166
|
-
this.statusCode(push);
|
|
167
|
-
this.refreshStatus();
|
|
168
190
|
}
|
|
169
191
|
|
|
170
192
|
updateHomeKitCharacteristics() {
|
|
171
|
-
if (this.
|
|
172
|
-
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} On: ${this.
|
|
173
|
-
} else {
|
|
174
|
-
this.service.updateCharacteristic(this.platform.Characteristic.On, this.On);
|
|
175
|
-
this.platform.device(`Indoor Cam: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
176
|
-
}
|
|
177
|
-
if (this.OutletInUse === undefined) {
|
|
178
|
-
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} OutletInUse: ${this.OutletInUse}`);
|
|
193
|
+
if (this.SelectedRTPStreamConfiguration === undefined) {
|
|
194
|
+
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} On: ${this.SelectedRTPStreamConfiguration}`);
|
|
179
195
|
} else {
|
|
180
|
-
this.service.updateCharacteristic(this.platform.Characteristic.
|
|
181
|
-
this.platform.device(`Indoor Cam: ${this.accessory.displayName} updateCharacteristic
|
|
196
|
+
this.service.updateCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration, this.SelectedRTPStreamConfiguration);
|
|
197
|
+
this.platform.device(`Indoor Cam: ${this.accessory.displayName} updateCharacteristic On: ${this.SelectedRTPStreamConfiguration}`);
|
|
182
198
|
}
|
|
183
199
|
}
|
|
184
200
|
|
|
185
201
|
public apiError(e: any) {
|
|
186
|
-
this.service.updateCharacteristic(this.platform.Characteristic.
|
|
187
|
-
this.service.updateCharacteristic(this.platform.Characteristic.OutletInUse, e);
|
|
202
|
+
this.service.updateCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration, e);
|
|
188
203
|
}
|
|
189
204
|
|
|
190
205
|
private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
|
|
@@ -200,9 +215,15 @@ export class IndoorCam {
|
|
|
200
215
|
break;
|
|
201
216
|
case 161:
|
|
202
217
|
this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device is offline.`);
|
|
218
|
+
if (this.device.offline) {
|
|
219
|
+
this.Active = false;
|
|
220
|
+
}
|
|
203
221
|
break;
|
|
204
222
|
case 171:
|
|
205
|
-
this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Hub Device is offline
|
|
223
|
+
this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
224
|
+
if (this.device.offline) {
|
|
225
|
+
this.Active = false;
|
|
226
|
+
}
|
|
206
227
|
break;
|
|
207
228
|
case 190:
|
|
208
229
|
this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
|
|
@@ -216,15 +237,73 @@ export class IndoorCam {
|
|
|
216
237
|
}
|
|
217
238
|
}
|
|
218
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Handle requests to set the value of the "Active" characteristic
|
|
242
|
+
*/
|
|
243
|
+
ActiveSet(value: CharacteristicValue) {
|
|
244
|
+
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} Active: ${value}`);
|
|
245
|
+
|
|
246
|
+
this.Active = value;
|
|
247
|
+
this.doCameraUpdate.next();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Handle requests to set the value of the "SelectedRTPStreamConfiguration" characteristic
|
|
252
|
+
*/
|
|
253
|
+
SelectedRTPStreamConfigurationSet(value: CharacteristicValue) {
|
|
254
|
+
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SelectedRTPStreamConfiguration: ${value}`);
|
|
255
|
+
|
|
256
|
+
this.SelectedRTPStreamConfiguration = value;
|
|
257
|
+
this.doCameraUpdate.next();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Handle requests to set the value of the "On" characteristic
|
|
262
|
+
*/
|
|
263
|
+
SetupEndpointsSet(value: CharacteristicValue) {
|
|
264
|
+
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SetupEndpoints: ${value}`);
|
|
265
|
+
|
|
266
|
+
this.SetupEndpoints = value;
|
|
267
|
+
this.doCameraUpdate.next();
|
|
268
|
+
}
|
|
269
|
+
|
|
219
270
|
/**
|
|
220
271
|
* Handle requests to set the value of the "On" characteristic
|
|
221
272
|
*/
|
|
222
|
-
|
|
223
|
-
this.platform.debug(`Indoor Cam: ${this.accessory.displayName}
|
|
273
|
+
SupportedAudioStreamConfigurationSet(value: CharacteristicValue) {
|
|
274
|
+
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SupportedAudioStreamConfiguration: ${value}`);
|
|
224
275
|
|
|
225
|
-
this.
|
|
276
|
+
this.SupportedAudioStreamConfiguration = value;
|
|
226
277
|
this.doCameraUpdate.next();
|
|
227
278
|
}
|
|
228
279
|
|
|
280
|
+
/**
|
|
281
|
+
* Handle requests to set the value of the "On" characteristic
|
|
282
|
+
*/
|
|
283
|
+
SupportedRTPConfigurationSet(value: CharacteristicValue) {
|
|
284
|
+
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SupportedRTPConfiguration: ${value}`);
|
|
285
|
+
|
|
286
|
+
this.SupportedRTPConfiguration = value;
|
|
287
|
+
this.doCameraUpdate.next();
|
|
288
|
+
}
|
|
229
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Handle requests to set the value of the "On" characteristic
|
|
292
|
+
*/
|
|
293
|
+
StreamingStatusSet(value: CharacteristicValue) {
|
|
294
|
+
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} StreamingStatus: ${value}`);
|
|
295
|
+
|
|
296
|
+
this.StreamingStatus = value;
|
|
297
|
+
this.doCameraUpdate.next();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Handle requests to set the value of the "On" characteristic
|
|
302
|
+
*/
|
|
303
|
+
SupportedVideoStreamConfigurationSet(value: CharacteristicValue) {
|
|
304
|
+
this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SupportedVideoStreamConfiguration: ${value}`);
|
|
305
|
+
|
|
306
|
+
this.SupportedVideoStreamConfiguration = value;
|
|
307
|
+
this.doCameraUpdate.next();
|
|
308
|
+
}
|
|
230
309
|
}
|
package/src/devices/meters.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { interval, Subject } from 'rxjs';
|
|
|
3
3
|
import { skipWhile } from 'rxjs/operators';
|
|
4
4
|
import { SwitchBotPlatform } from '../platform';
|
|
5
5
|
import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
|
|
6
|
-
import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse } from '../settings';
|
|
6
|
+
import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, temperature } from '../settings';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Platform Accessory
|
|
@@ -32,10 +32,9 @@ export class Meter {
|
|
|
32
32
|
connected?: boolean;
|
|
33
33
|
switchbot!: switchbot;
|
|
34
34
|
serviceData!: serviceData;
|
|
35
|
+
temperature!: temperature['c'];
|
|
35
36
|
battery!: serviceData['battery'];
|
|
36
37
|
humidity!: serviceData['humidity'];
|
|
37
|
-
fahrenheit!: serviceData['fahrenheit'];
|
|
38
|
-
temperature!: serviceData['temperature'];
|
|
39
38
|
|
|
40
39
|
// Config
|
|
41
40
|
private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
|
|
@@ -51,8 +50,8 @@ export class Meter {
|
|
|
51
50
|
public device: device & devicesConfig,
|
|
52
51
|
) {
|
|
53
52
|
// Meter Config
|
|
54
|
-
this.platform.device(`Meter: ${this.accessory.displayName} Config: (ble: ${device.ble},
|
|
55
|
-
+ `
|
|
53
|
+
this.platform.device(`Meter: ${this.accessory.displayName} Config: (ble: ${device.ble}, hide_temperature: ${device.meter?.hide_temperature},`
|
|
54
|
+
+ ` hide_humidity: ${device.meter?.hide_humidity})`);
|
|
56
55
|
|
|
57
56
|
// default placeholders
|
|
58
57
|
this.BatteryLevel = 0;
|
|
@@ -191,13 +190,8 @@ export class Meter {
|
|
|
191
190
|
|
|
192
191
|
// Current Temperature
|
|
193
192
|
if (!this.device.meter?.hide_temperature) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
} else if (this.device.meter?.unit === 0) {
|
|
197
|
-
this.CurrentTemperature = this.toCelsius(this.temperature!.c);
|
|
198
|
-
} else {
|
|
199
|
-
this.CurrentTemperature = Number(this.temperature?.c);
|
|
200
|
-
}
|
|
193
|
+
this.temperature < 0 ? 0 : this.temperature > 100 ? 100 : this.temperature;
|
|
194
|
+
this.CurrentTemperature = this.temperature;
|
|
201
195
|
this.platform.debug(`Meter: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
|
|
202
196
|
}
|
|
203
197
|
}
|
|
@@ -223,13 +217,7 @@ export class Meter {
|
|
|
223
217
|
|
|
224
218
|
// Current Temperature
|
|
225
219
|
if (!this.device.meter?.hide_temperature) {
|
|
226
|
-
|
|
227
|
-
this.CurrentTemperature = this.toFahrenheit(this.deviceStatus.body.temperature!);
|
|
228
|
-
} else if (this.device.meter?.unit === 0) {
|
|
229
|
-
this.CurrentTemperature = this.toCelsius(this.deviceStatus.body.temperature!);
|
|
230
|
-
} else {
|
|
231
|
-
this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
|
|
232
|
-
}
|
|
220
|
+
this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
|
|
233
221
|
this.platform.debug(`Meter: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
|
|
234
222
|
}
|
|
235
223
|
}
|
|
@@ -259,20 +247,18 @@ export class Meter {
|
|
|
259
247
|
const switchbot = this.connectBLE();
|
|
260
248
|
// Start to monitor advertisement packets
|
|
261
249
|
switchbot.startScan({
|
|
262
|
-
model: 'T',
|
|
263
250
|
id: this.device.bleMac,
|
|
264
251
|
}).then(() => {
|
|
265
252
|
// Set an event hander
|
|
266
253
|
switchbot.onadvertisement = (ad: ad) => {
|
|
267
254
|
this.serviceData = ad.serviceData;
|
|
268
|
-
this.temperature = ad.serviceData.temperature;
|
|
269
|
-
this.fahrenheit = ad.serviceData.fahrenheit;
|
|
255
|
+
this.temperature = Number(ad.serviceData.temperature?.c);
|
|
270
256
|
this.humidity = ad.serviceData.humidity;
|
|
271
257
|
this.battery = ad.serviceData.battery;
|
|
272
258
|
this.platform.device(`Meter: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
273
259
|
this.platform.device(`Meter: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, `
|
|
274
|
-
+ `temperature: ${JSON.stringify(ad.serviceData.temperature)},
|
|
275
|
-
+ `
|
|
260
|
+
+ `temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, `
|
|
261
|
+
+ `battery: ${ad.serviceData.battery}`);
|
|
276
262
|
|
|
277
263
|
if (this.serviceData) {
|
|
278
264
|
this.connected = true;
|
|
@@ -382,19 +368,4 @@ export class Meter {
|
|
|
382
368
|
this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
|
|
383
369
|
}
|
|
384
370
|
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Converts the value to celsius if the temperature units are in Fahrenheit
|
|
388
|
-
*/
|
|
389
|
-
toCelsius(value: number) {
|
|
390
|
-
// celsius should be to the nearest 0.5 degree
|
|
391
|
-
return Math.round((5 / 9) * (value - 32) * 2) / 2;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/**
|
|
395
|
-
* Converts the value to fahrenheit if the temperature units are in Fahrenheit
|
|
396
|
-
*/
|
|
397
|
-
toFahrenheit(value: number) {
|
|
398
|
-
return Math.round((value * 9) / 5 + 32);
|
|
399
|
-
}
|
|
400
371
|
}
|
package/src/devices/plugs.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { AxiosResponse } from 'axios';
|
|
3
3
|
import { interval, Subject } from 'rxjs';
|
|
4
4
|
import { SwitchBotPlatform } from '../platform';
|
|
5
|
-
import { debounceTime, skipWhile, tap } from 'rxjs/operators';
|
|
5
|
+
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
6
6
|
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
7
7
|
import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
|
|
8
8
|
|
|
@@ -12,6 +12,7 @@ export class Plug {
|
|
|
12
12
|
|
|
13
13
|
// Characteristic Values
|
|
14
14
|
On!: CharacteristicValue;
|
|
15
|
+
OnCached!: CharacteristicValue;
|
|
15
16
|
|
|
16
17
|
// OpenAPI Others
|
|
17
18
|
deviceStatus!: deviceStatusResponse;
|
|
@@ -29,8 +30,15 @@ export class Plug {
|
|
|
29
30
|
private accessory: PlatformAccessory,
|
|
30
31
|
public device: device & devicesConfig,
|
|
31
32
|
) {
|
|
33
|
+
// Bot Config
|
|
34
|
+
this.platform.device(`Plug: ${this.accessory.displayName} Config: (offline: ${device.offline})`);
|
|
35
|
+
|
|
32
36
|
// default placeholders
|
|
33
|
-
this.On
|
|
37
|
+
if (this.On === undefined) {
|
|
38
|
+
this.On = false;
|
|
39
|
+
} else {
|
|
40
|
+
this.On = this.accessory.context.On;
|
|
41
|
+
}
|
|
34
42
|
|
|
35
43
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
36
44
|
this.doPlugUpdate = new Subject();
|
|
@@ -142,24 +150,34 @@ export class Plug {
|
|
|
142
150
|
* Plug - "command" "turnOn" "default" = set to ON state
|
|
143
151
|
*/
|
|
144
152
|
async pushChanges() {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
if (this.On !== this.OnCached) {
|
|
154
|
+
const payload = {
|
|
155
|
+
commandType: 'command',
|
|
156
|
+
parameter: 'default',
|
|
157
|
+
} as payload;
|
|
158
|
+
|
|
159
|
+
if (this.On) {
|
|
160
|
+
payload.command = 'turnOn';
|
|
161
|
+
} else {
|
|
162
|
+
payload.command = 'turnOff';
|
|
163
|
+
}
|
|
155
164
|
|
|
156
|
-
|
|
157
|
-
|
|
165
|
+
this.platform.log.info(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
|
|
166
|
+
+ ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
|
|
158
167
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
// Make the API request
|
|
169
|
+
const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
|
|
170
|
+
this.platform.debug(`Plug: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
|
|
171
|
+
this.statusCode(push);
|
|
172
|
+
this.OnCached = this.On;
|
|
173
|
+
this.accessory.context.On = this.OnCached;
|
|
174
|
+
}
|
|
175
|
+
interval(5000)
|
|
176
|
+
.pipe(skipWhile(() => this.plugUpdateInProgress))
|
|
177
|
+
.pipe(take(1))
|
|
178
|
+
.subscribe(() => {
|
|
179
|
+
this.refreshStatus();
|
|
180
|
+
});
|
|
163
181
|
}
|
|
164
182
|
|
|
165
183
|
updateHomeKitCharacteristics() {
|
|
@@ -188,9 +206,11 @@ export class Plug {
|
|
|
188
206
|
break;
|
|
189
207
|
case 161:
|
|
190
208
|
this.platform.log.error(`Plug: ${this.accessory.displayName} Device is offline.`);
|
|
209
|
+
this.offlineOff();
|
|
191
210
|
break;
|
|
192
211
|
case 171:
|
|
193
|
-
this.platform.log.error(`Plug: ${this.accessory.displayName} Hub Device is offline
|
|
212
|
+
this.platform.log.error(`Plug: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
213
|
+
this.offlineOff();
|
|
194
214
|
break;
|
|
195
215
|
case 190:
|
|
196
216
|
this.platform.log.error(`Plug: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
|
|
@@ -204,6 +224,13 @@ export class Plug {
|
|
|
204
224
|
}
|
|
205
225
|
}
|
|
206
226
|
|
|
227
|
+
private offlineOff() {
|
|
228
|
+
if (this.device.offline) {
|
|
229
|
+
this.On = false;
|
|
230
|
+
this.service.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
207
234
|
/**
|
|
208
235
|
* Handle requests to set the value of the "On" characteristic
|
|
209
236
|
*/
|
|
@@ -14,9 +14,11 @@ export class AirConditioner {
|
|
|
14
14
|
|
|
15
15
|
// Characteristic Values
|
|
16
16
|
Active!: CharacteristicValue;
|
|
17
|
+
ActiveCached!: CharacteristicValue;
|
|
17
18
|
RotationSpeed!: CharacteristicValue;
|
|
18
19
|
LastTemperature!: CharacteristicValue;
|
|
19
20
|
CurrentTemperature!: CharacteristicValue;
|
|
21
|
+
CurrentTemperatureCached!: CharacteristicValue;
|
|
20
22
|
TargetHeaterCoolerState?: CharacteristicValue;
|
|
21
23
|
CurrentHeaterCoolerState!: CharacteristicValue;
|
|
22
24
|
HeatingThresholdTemperature?: CharacteristicValue;
|
|
@@ -41,7 +43,17 @@ export class AirConditioner {
|
|
|
41
43
|
private accessory: PlatformAccessory,
|
|
42
44
|
public device: irdevice & irDevicesConfig,
|
|
43
45
|
) {
|
|
44
|
-
|
|
46
|
+
// default placeholders
|
|
47
|
+
if (this.Active === undefined) {
|
|
48
|
+
this.Active = this.platform.Characteristic.Active.INACTIVE;
|
|
49
|
+
} else {
|
|
50
|
+
this.Active = this.accessory.context.Active;
|
|
51
|
+
}
|
|
52
|
+
if (this.CurrentTemperature === undefined) {
|
|
53
|
+
this.CurrentTemperature = 24;
|
|
54
|
+
} else {
|
|
55
|
+
this.CurrentTemperature = this.accessory.context.CurrentTemperature;
|
|
56
|
+
}
|
|
45
57
|
|
|
46
58
|
// set accessory information
|
|
47
59
|
accessory
|
|
@@ -161,6 +173,8 @@ export class AirConditioner {
|
|
|
161
173
|
this.platform.device(`Air Conditioner: ${this.accessory.displayName} pushAirConditionerOffChanges, Active: ${this.Active}`);
|
|
162
174
|
}
|
|
163
175
|
this.Active = value;
|
|
176
|
+
this.ActiveCached = this.Active;
|
|
177
|
+
this.accessory.context.Active = this.ActiveCached;
|
|
164
178
|
}
|
|
165
179
|
|
|
166
180
|
private updateHomeKitCharacteristics() {
|
|
@@ -349,6 +363,8 @@ export class AirConditioner {
|
|
|
349
363
|
const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
|
|
350
364
|
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
|
|
351
365
|
this.statusCode(push);
|
|
366
|
+
this.CurrentTemperatureCached = this.CurrentTemperature;
|
|
367
|
+
this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
|
|
352
368
|
this.updateHomeKitCharacteristics();
|
|
353
369
|
} catch (e: any) {
|
|
354
370
|
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} failed pushChanges`);
|
|
@@ -379,7 +395,7 @@ export class AirConditioner {
|
|
|
379
395
|
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Device is offline.`);
|
|
380
396
|
break;
|
|
381
397
|
case 171:
|
|
382
|
-
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Hub Device is offline
|
|
398
|
+
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
383
399
|
break;
|
|
384
400
|
case 190:
|
|
385
401
|
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Device internal error due to device states not synchronized`
|
|
@@ -15,11 +15,13 @@ export class AirPurifier {
|
|
|
15
15
|
// Characteristic Values
|
|
16
16
|
Active!: CharacteristicValue;
|
|
17
17
|
APActive!: CharacteristicValue;
|
|
18
|
+
ActiveCached!: CharacteristicValue;
|
|
18
19
|
CurrentAPTemp!: CharacteristicValue;
|
|
19
20
|
CurrentAPMode!: CharacteristicValue;
|
|
20
21
|
RotationSpeed!: CharacteristicValue;
|
|
21
22
|
CurrentAPFanSpeed!: CharacteristicValue;
|
|
22
23
|
CurrentTemperature!: CharacteristicValue;
|
|
24
|
+
CurrentTemperatureCached!: CharacteristicValue;
|
|
23
25
|
CurrentAirPurifierState!: CharacteristicValue;
|
|
24
26
|
CurrentHeaterCoolerState!: CharacteristicValue;
|
|
25
27
|
|
|
@@ -42,6 +44,18 @@ export class AirPurifier {
|
|
|
42
44
|
private accessory: PlatformAccessory,
|
|
43
45
|
public device: irdevice & irDevicesConfig,
|
|
44
46
|
) {
|
|
47
|
+
// default placeholders
|
|
48
|
+
if (this.Active === undefined) {
|
|
49
|
+
this.Active = this.platform.Characteristic.Active.INACTIVE;
|
|
50
|
+
} else {
|
|
51
|
+
this.Active = this.accessory.context.Active;
|
|
52
|
+
}
|
|
53
|
+
if (this.CurrentTemperature === undefined) {
|
|
54
|
+
this.CurrentTemperature = 24;
|
|
55
|
+
} else {
|
|
56
|
+
this.CurrentTemperature = this.accessory.context.CurrentTemperature;
|
|
57
|
+
}
|
|
58
|
+
|
|
45
59
|
// set accessory information
|
|
46
60
|
accessory
|
|
47
61
|
.getService(this.platform.Service.AccessoryInformation)!
|
|
@@ -81,6 +95,8 @@ export class AirPurifier {
|
|
|
81
95
|
this.pushAirConditionerOnChanges();
|
|
82
96
|
}
|
|
83
97
|
this.Active = value;
|
|
98
|
+
this.ActiveCached = this.Active;
|
|
99
|
+
this.accessory.context.Active = this.ActiveCached;
|
|
84
100
|
}
|
|
85
101
|
|
|
86
102
|
private updateHomeKitCharacteristics() {
|
|
@@ -210,6 +226,8 @@ export class AirPurifier {
|
|
|
210
226
|
this.platform.debug(`Air Purifier: ${this.accessory.displayName} pushChanges: ${push.data}`);
|
|
211
227
|
this.statusCode(push);
|
|
212
228
|
this.updateHomeKitCharacteristics();
|
|
229
|
+
this.CurrentTemperatureCached = this.CurrentTemperature;
|
|
230
|
+
this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
|
|
213
231
|
} catch (e: any) {
|
|
214
232
|
this.platform.log.error(`Air Purifier: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
215
233
|
if (this.deviceDebug) {
|
|
@@ -239,7 +257,7 @@ export class AirPurifier {
|
|
|
239
257
|
this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Device is offline.`);
|
|
240
258
|
break;
|
|
241
259
|
case 171:
|
|
242
|
-
this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Hub Device is offline
|
|
260
|
+
this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
243
261
|
break;
|
|
244
262
|
case 190:
|
|
245
263
|
this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Device internal error due to device states not synchronized`
|
package/src/irdevices/cameras.ts
CHANGED
|
@@ -14,6 +14,7 @@ export class Camera {
|
|
|
14
14
|
|
|
15
15
|
// Characteristic Values
|
|
16
16
|
On!: CharacteristicValue;
|
|
17
|
+
OnCached!: CharacteristicValue;
|
|
17
18
|
|
|
18
19
|
// Config
|
|
19
20
|
private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
|
|
@@ -24,6 +25,13 @@ export class Camera {
|
|
|
24
25
|
private accessory: PlatformAccessory,
|
|
25
26
|
public device: irdevice & irDevicesConfig,
|
|
26
27
|
) {
|
|
28
|
+
// default placeholders
|
|
29
|
+
if (this.On === undefined) {
|
|
30
|
+
this.On = false;
|
|
31
|
+
} else {
|
|
32
|
+
this.On = this.accessory.context.On;
|
|
33
|
+
}
|
|
34
|
+
|
|
27
35
|
// set accessory information
|
|
28
36
|
accessory
|
|
29
37
|
.getService(this.platform.Service.AccessoryInformation)!
|
|
@@ -110,6 +118,8 @@ export class Camera {
|
|
|
110
118
|
this.platform.debug(`Camera: ${this.accessory.displayName} pushChanges: ${push.data}`);
|
|
111
119
|
this.statusCode(push);
|
|
112
120
|
this.updateHomeKitCharacteristics();
|
|
121
|
+
this.OnCached = this.On;
|
|
122
|
+
this.accessory.context.On = this.OnCached;
|
|
113
123
|
} catch (e: any) {
|
|
114
124
|
this.platform.log.error(`Camera: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
|
|
115
125
|
if (this.deviceDebug) {
|
|
@@ -139,7 +149,7 @@ export class Camera {
|
|
|
139
149
|
this.platform.log.error(`Camera: ${this.accessory.displayName} Device is offline.`);
|
|
140
150
|
break;
|
|
141
151
|
case 171:
|
|
142
|
-
this.platform.log.error(`Camera: ${this.accessory.displayName} Hub Device is offline
|
|
152
|
+
this.platform.log.error(`Camera: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
143
153
|
break;
|
|
144
154
|
case 190:
|
|
145
155
|
this.platform.log.error(`Camera: ${this.accessory.displayName} Device internal error due to device states not synchronized`
|
package/src/irdevices/fans.ts
CHANGED
|
@@ -14,6 +14,7 @@ export class Fan {
|
|
|
14
14
|
|
|
15
15
|
// Characteristic Values
|
|
16
16
|
Active!: CharacteristicValue;
|
|
17
|
+
ActiveCached!: CharacteristicValue;
|
|
17
18
|
ActiveIdentifier!: CharacteristicValue;
|
|
18
19
|
RotationSpeed!: CharacteristicValue;
|
|
19
20
|
SwingMode!: CharacteristicValue;
|
|
@@ -34,6 +35,13 @@ export class Fan {
|
|
|
34
35
|
private accessory: PlatformAccessory,
|
|
35
36
|
public device: irdevice & irDevicesConfig,
|
|
36
37
|
) {
|
|
38
|
+
// default placeholders
|
|
39
|
+
if (this.Active === undefined) {
|
|
40
|
+
this.Active = this.platform.Characteristic.Active.INACTIVE;
|
|
41
|
+
} else {
|
|
42
|
+
this.Active = this.accessory.context.Active;
|
|
43
|
+
}
|
|
44
|
+
|
|
37
45
|
// set accessory information
|
|
38
46
|
accessory
|
|
39
47
|
.getService(this.platform.Service.AccessoryInformation)!
|
|
@@ -164,6 +172,8 @@ export class Fan {
|
|
|
164
172
|
this.pushFanOnChanges();
|
|
165
173
|
}
|
|
166
174
|
this.Active = value;
|
|
175
|
+
this.ActiveCached = this.Active;
|
|
176
|
+
this.accessory.context.Active = this.ActiveCached;
|
|
167
177
|
}
|
|
168
178
|
|
|
169
179
|
/**
|
|
@@ -261,7 +271,7 @@ export class Fan {
|
|
|
261
271
|
this.platform.log.error(`Fan: ${this.accessory.displayName} Device is offline.`);
|
|
262
272
|
break;
|
|
263
273
|
case 171:
|
|
264
|
-
this.platform.log.error(`Fan: ${this.accessory.displayName} Hub Device is offline
|
|
274
|
+
this.platform.log.error(`Fan: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
265
275
|
break;
|
|
266
276
|
case 190:
|
|
267
277
|
this.platform.log.error(`Fan: ${this.accessory.displayName} Device internal error due to device states not synchronized`
|