@switchbot/homebridge-switchbot 1.10.2-beta.2 → 1.10.2-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 +6 -0
- package/README.md +10 -0
- package/dist/{devices/bots.d.ts → device/bot.d.ts} +3 -3
- package/dist/device/bot.d.ts.map +1 -0
- package/dist/{devices/bots.js → device/bot.js} +4 -1
- package/dist/device/bot.js.map +1 -0
- package/dist/{devices → device}/colorbulb.d.ts +7 -1
- package/dist/device/colorbulb.d.ts.map +1 -0
- package/dist/{devices → device}/colorbulb.js +9 -0
- package/dist/device/colorbulb.js.map +1 -0
- package/dist/{devices → device}/contact.d.ts +0 -0
- package/dist/device/contact.d.ts.map +1 -0
- package/dist/{devices → device}/contact.js +0 -0
- package/dist/device/contact.js.map +1 -0
- package/dist/{devices/curtains.d.ts → device/curtain.d.ts} +1 -1
- package/dist/device/curtain.d.ts.map +1 -0
- package/dist/{devices/curtains.js → device/curtain.js} +3 -3
- package/dist/device/curtain.js.map +1 -0
- package/dist/{devices/humidifiers.d.ts → device/humidifier.d.ts} +5 -5
- package/dist/device/humidifier.d.ts.map +1 -0
- package/dist/{devices/humidifiers.js → device/humidifier.js} +4 -4
- package/dist/device/humidifier.js.map +1 -0
- package/dist/{devices/plugs.d.ts → device/lock.d.ts} +14 -12
- package/dist/device/lock.d.ts.map +1 -0
- package/dist/device/lock.js +298 -0
- package/dist/device/lock.js.map +1 -0
- package/dist/{devices/meters.d.ts → device/meter.d.ts} +2 -1
- package/dist/device/meter.d.ts.map +1 -0
- package/dist/{devices/meters.js → device/meter.js} +15 -5
- package/dist/device/meter.js.map +1 -0
- package/dist/{devices → device}/motion.d.ts +2 -2
- package/dist/device/motion.d.ts.map +1 -0
- package/dist/{devices → device}/motion.js +3 -4
- package/dist/device/motion.js.map +1 -0
- package/dist/device/plug.d.ts +54 -0
- package/dist/device/plug.d.ts.map +1 -0
- package/dist/{devices/plugs.js → device/plug.js} +29 -12
- package/dist/device/plug.js.map +1 -0
- package/dist/{irdevices/airconditioners.d.ts → irdevice/airconditioner.d.ts} +1 -1
- package/dist/irdevice/airconditioner.d.ts.map +1 -0
- package/dist/{irdevices/airconditioners.js → irdevice/airconditioner.js} +1 -1
- package/dist/irdevice/airconditioner.js.map +1 -0
- package/dist/{irdevices/airpurifiers.d.ts → irdevice/airpurifier.d.ts} +1 -1
- package/dist/irdevice/airpurifier.d.ts.map +1 -0
- package/dist/{irdevices/airpurifiers.js → irdevice/airpurifier.js} +1 -1
- package/dist/irdevice/airpurifier.js.map +1 -0
- package/dist/{irdevices/cameras.d.ts → irdevice/camera.d.ts} +1 -1
- package/dist/irdevice/camera.d.ts.map +1 -0
- package/dist/{irdevices/cameras.js → irdevice/camera.js} +1 -1
- package/dist/irdevice/camera.js.map +1 -0
- package/dist/{irdevices/fans.d.ts → irdevice/fan.d.ts} +1 -1
- package/dist/irdevice/fan.d.ts.map +1 -0
- package/dist/{irdevices/fans.js → irdevice/fan.js} +1 -1
- package/dist/irdevice/fan.js.map +1 -0
- package/dist/{irdevices/lights.d.ts → irdevice/light.d.ts} +1 -1
- package/dist/irdevice/light.d.ts.map +1 -0
- package/dist/{irdevices/lights.js → irdevice/light.js} +1 -1
- package/dist/irdevice/light.js.map +1 -0
- package/dist/{irdevices/others.d.ts → irdevice/other.d.ts} +1 -1
- package/dist/irdevice/other.d.ts.map +1 -0
- package/dist/{irdevices/others.js → irdevice/other.js} +1 -1
- package/dist/irdevice/other.js.map +1 -0
- package/dist/{irdevices/tvs.d.ts → irdevice/tv.d.ts} +1 -1
- package/dist/irdevice/tv.d.ts.map +1 -0
- package/dist/{irdevices/tvs.js → irdevice/tv.js} +1 -1
- package/dist/irdevice/tv.js.map +1 -0
- package/dist/{irdevices/vacuumcleaners.d.ts → irdevice/vacuumcleaner.d.ts} +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -0
- package/dist/{irdevices/vacuumcleaners.js → irdevice/vacuumcleaner.js} +1 -1
- package/dist/irdevice/vacuumcleaner.js.map +1 -0
- package/dist/{irdevices/waterheaters.d.ts → irdevice/waterheater.d.ts} +1 -1
- package/dist/irdevice/waterheater.d.ts.map +1 -0
- package/dist/{irdevices/waterheaters.js → irdevice/waterheater.js} +1 -1
- package/dist/irdevice/waterheater.js.map +1 -0
- package/dist/platform.d.ts +1 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +106 -45
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +7 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/package.json +1 -1
- package/src/{devices/bots.ts → device/bot.ts} +5 -2
- package/src/{devices → device}/colorbulb.ts +10 -1
- package/src/{devices → device}/contact.ts +0 -0
- package/src/{devices/curtains.ts → device/curtain.ts} +2 -2
- package/src/{devices/humidifiers.ts → device/humidifier.ts} +7 -10
- package/src/device/lock.ts +345 -0
- package/src/{devices/meters.ts → device/meter.ts} +13 -7
- package/src/{devices → device}/motion.ts +5 -9
- package/src/{devices/plugs.ts → device/plug.ts} +31 -16
- package/src/{irdevices/airconditioners.ts → irdevice/airconditioner.ts} +0 -0
- package/src/{irdevices/airpurifiers.ts → irdevice/airpurifier.ts} +0 -0
- package/src/{irdevices/cameras.ts → irdevice/camera.ts} +0 -0
- package/src/{irdevices/fans.ts → irdevice/fan.ts} +0 -0
- package/src/{irdevices/lights.ts → irdevice/light.ts} +0 -0
- package/src/{irdevices/others.ts → irdevice/other.ts} +0 -0
- package/src/{irdevices/tvs.ts → irdevice/tv.ts} +0 -0
- package/src/{irdevices/vacuumcleaners.ts → irdevice/vacuumcleaner.ts} +0 -0
- package/src/{irdevices/waterheaters.ts → irdevice/waterheater.ts} +0 -0
- package/src/platform.ts +82 -17
- package/src/settings.ts +24 -11
- package/dist/devices/bots.d.ts.map +0 -1
- package/dist/devices/bots.js.map +0 -1
- package/dist/devices/colorbulb.d.ts.map +0 -1
- package/dist/devices/colorbulb.js.map +0 -1
- package/dist/devices/contact.d.ts.map +0 -1
- package/dist/devices/contact.js.map +0 -1
- package/dist/devices/curtains.d.ts.map +0 -1
- package/dist/devices/curtains.js.map +0 -1
- package/dist/devices/humidifiers.d.ts.map +0 -1
- package/dist/devices/humidifiers.js.map +0 -1
- package/dist/devices/meters.d.ts.map +0 -1
- package/dist/devices/meters.js.map +0 -1
- package/dist/devices/motion.d.ts.map +0 -1
- package/dist/devices/motion.js.map +0 -1
- package/dist/devices/plugs.d.ts.map +0 -1
- package/dist/devices/plugs.js.map +0 -1
- package/dist/irdevices/airconditioners.d.ts.map +0 -1
- package/dist/irdevices/airconditioners.js.map +0 -1
- package/dist/irdevices/airpurifiers.d.ts.map +0 -1
- package/dist/irdevices/airpurifiers.js.map +0 -1
- package/dist/irdevices/cameras.d.ts.map +0 -1
- package/dist/irdevices/cameras.js.map +0 -1
- package/dist/irdevices/fans.d.ts.map +0 -1
- package/dist/irdevices/fans.js.map +0 -1
- package/dist/irdevices/lights.d.ts.map +0 -1
- package/dist/irdevices/lights.js.map +0 -1
- package/dist/irdevices/others.d.ts.map +0 -1
- package/dist/irdevices/others.js.map +0 -1
- package/dist/irdevices/tvs.d.ts.map +0 -1
- package/dist/irdevices/tvs.js.map +0 -1
- package/dist/irdevices/vacuumcleaners.d.ts.map +0 -1
- package/dist/irdevices/vacuumcleaners.js.map +0 -1
- package/dist/irdevices/waterheaters.d.ts.map +0 -1
- package/dist/irdevices/waterheaters.js.map +0 -1
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { AxiosResponse } from 'axios';
|
|
2
|
+
import { interval, Subject } from 'rxjs';
|
|
3
|
+
import { SwitchBotPlatform } from '../platform';
|
|
4
|
+
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
5
|
+
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
6
|
+
import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload, deviceStatus } from '../settings';
|
|
7
|
+
|
|
8
|
+
export class Lock {
|
|
9
|
+
// Services
|
|
10
|
+
private lockService: Service;
|
|
11
|
+
private doorService?: Service;
|
|
12
|
+
|
|
13
|
+
// Characteristic Values
|
|
14
|
+
LockCurrentState!: CharacteristicValue;
|
|
15
|
+
LockTargetState!: CharacteristicValue;
|
|
16
|
+
LockTargetStateCached!: CharacteristicValue;
|
|
17
|
+
|
|
18
|
+
// OpenAPI Others
|
|
19
|
+
doorState!: deviceStatus['doorState'];
|
|
20
|
+
lockState!: deviceStatus['lockState'];
|
|
21
|
+
deviceStatus!: deviceStatusResponse;
|
|
22
|
+
|
|
23
|
+
// Config
|
|
24
|
+
scanDuration!: number;
|
|
25
|
+
deviceLogging!: string;
|
|
26
|
+
deviceRefreshRate!: number;
|
|
27
|
+
|
|
28
|
+
// Updates
|
|
29
|
+
lockUpdateInProgress!: boolean;
|
|
30
|
+
doLockUpdate!: Subject<void>;
|
|
31
|
+
|
|
32
|
+
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
|
|
33
|
+
// default placeholders
|
|
34
|
+
this.logs(device);
|
|
35
|
+
this.scan(device);
|
|
36
|
+
this.refreshRate(device);
|
|
37
|
+
this.config(device);
|
|
38
|
+
if (this.LockTargetState === undefined) {
|
|
39
|
+
this.LockTargetState = false;
|
|
40
|
+
} else {
|
|
41
|
+
this.LockTargetState = this.accessory.context.On;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
45
|
+
this.doLockUpdate = new Subject();
|
|
46
|
+
this.lockUpdateInProgress = false;
|
|
47
|
+
|
|
48
|
+
// Retrieve initial values and updateHomekit
|
|
49
|
+
this.refreshStatus();
|
|
50
|
+
|
|
51
|
+
// set accessory information
|
|
52
|
+
accessory
|
|
53
|
+
.getService(this.platform.Service.AccessoryInformation)!
|
|
54
|
+
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'SwitchBot')
|
|
55
|
+
.setCharacteristic(this.platform.Characteristic.Model, 'SWITCHBOT-LOCK-W1601700')
|
|
56
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!);
|
|
57
|
+
|
|
58
|
+
// get the WindowCovering service if it exists, otherwise create a new WindowCovering service
|
|
59
|
+
// you can create multiple services for each accessory
|
|
60
|
+
(this.lockService = accessory.getService(this.platform.Service.Outlet) || accessory.addService(this.platform.Service.Outlet)),
|
|
61
|
+
`${device.deviceName} ${device.deviceType}`;
|
|
62
|
+
|
|
63
|
+
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
64
|
+
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
65
|
+
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.Lightbulb, 'NAME', 'USER_DEFINED_SUBTYPE');
|
|
66
|
+
|
|
67
|
+
// set the service name, this is what is displayed as the default name on the Home app
|
|
68
|
+
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|
|
69
|
+
this.lockService.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName);
|
|
70
|
+
|
|
71
|
+
// each service must implement at-minimum the "required characteristics" for the given service type
|
|
72
|
+
// see https://developers.homebridge.io/#/service/WindowCovering
|
|
73
|
+
|
|
74
|
+
// create handlers for required characteristics
|
|
75
|
+
this.lockService.getCharacteristic(this.platform.Characteristic.LockCurrentState).onSet(this.LockTargetStateSet.bind(this));
|
|
76
|
+
|
|
77
|
+
// Update Homekit
|
|
78
|
+
this.updateHomeKitCharacteristics();
|
|
79
|
+
|
|
80
|
+
// Start an update interval
|
|
81
|
+
interval(this.deviceRefreshRate * 1000)
|
|
82
|
+
.pipe(skipWhile(() => this.lockUpdateInProgress))
|
|
83
|
+
.subscribe(() => {
|
|
84
|
+
this.refreshStatus();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Watch for Lock change events
|
|
88
|
+
// We put in a debounce of 100ms so we don't make duplicate calls
|
|
89
|
+
this.doLockUpdate
|
|
90
|
+
.pipe(
|
|
91
|
+
tap(() => {
|
|
92
|
+
this.lockUpdateInProgress = true;
|
|
93
|
+
}),
|
|
94
|
+
debounceTime(this.platform.config.options!.pushRate! * 1000),
|
|
95
|
+
)
|
|
96
|
+
.subscribe(async () => {
|
|
97
|
+
try {
|
|
98
|
+
await this.pushChanges();
|
|
99
|
+
} catch (e: any) {
|
|
100
|
+
this.errorLog(`Lock: ${this.accessory.displayName} failed pushChanges`);
|
|
101
|
+
if (this.deviceLogging === 'debug') {
|
|
102
|
+
this.errorLog(`Lock: ${this.accessory.displayName} failed pushChanges,` + ` Error Message: ${JSON.stringify(e.message)}`);
|
|
103
|
+
}
|
|
104
|
+
if (this.platform.debugMode) {
|
|
105
|
+
this.errorLog(`Lock: ${this.accessory.displayName} failed pushChanges,` + ` Error: ${JSON.stringify(e)}`);
|
|
106
|
+
}
|
|
107
|
+
this.apiError(e);
|
|
108
|
+
}
|
|
109
|
+
this.lockUpdateInProgress = false;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
parseStatus() {
|
|
114
|
+
switch (this.lockState) {
|
|
115
|
+
case 'on':
|
|
116
|
+
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.UNSECURED;
|
|
117
|
+
break;
|
|
118
|
+
default:
|
|
119
|
+
this.LockCurrentState = this.platform.Characteristic.LockCurrentState.SECURED;
|
|
120
|
+
}
|
|
121
|
+
this.debugLog(`Lock: ${this.accessory.displayName} On: ${this.LockTargetState}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private async refreshStatus() {
|
|
125
|
+
try {
|
|
126
|
+
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
127
|
+
this.debugLog(`Lock: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
128
|
+
this.lockState = this.deviceStatus.body.lockState;
|
|
129
|
+
this.warnLog(this.lockState);
|
|
130
|
+
this.doorState = this.deviceStatus.body.doorState;
|
|
131
|
+
this.warnLog(this.doorState);
|
|
132
|
+
this.parseStatus();
|
|
133
|
+
this.updateHomeKitCharacteristics();
|
|
134
|
+
} catch (e: any) {
|
|
135
|
+
this.errorLog(`Lock: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
136
|
+
if (this.deviceLogging === 'debug') {
|
|
137
|
+
this.errorLog(
|
|
138
|
+
`Lock: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
if (this.platform.debugMode) {
|
|
142
|
+
this.errorLog(`Lock: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` + ` Error: ${JSON.stringify(e)}`);
|
|
143
|
+
}
|
|
144
|
+
this.apiError(e);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Pushes the requested changes to the SwitchBot API
|
|
150
|
+
* deviceType commandType Command command parameter Description
|
|
151
|
+
* Lock - "command" "????" "????" = set to ???? state
|
|
152
|
+
* Lock - "command" "????" "????" = set to ???? state - LockCurrentState
|
|
153
|
+
*/
|
|
154
|
+
async pushChanges() {
|
|
155
|
+
if (this.LockTargetState !== this.LockTargetStateCached) {
|
|
156
|
+
const payload = {
|
|
157
|
+
commandType: 'command',
|
|
158
|
+
parameter: 'default',
|
|
159
|
+
} as payload;
|
|
160
|
+
|
|
161
|
+
if (this.LockTargetState) {
|
|
162
|
+
payload.command = 'turnOn';
|
|
163
|
+
} else {
|
|
164
|
+
payload.command = 'turnOff';
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this.infoLog(
|
|
168
|
+
`Lock: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},` +
|
|
169
|
+
` parameter: ${payload.parameter}, commandType: ${payload.commandType}`,
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// Make the API request
|
|
173
|
+
const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
|
|
174
|
+
this.debugLog(`Lock: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
|
|
175
|
+
this.statusCode(push);
|
|
176
|
+
this.LockTargetStateCached = this.LockTargetState;
|
|
177
|
+
this.accessory.context.On = this.LockTargetStateCached;
|
|
178
|
+
}
|
|
179
|
+
interval(5000)
|
|
180
|
+
.pipe(skipWhile(() => this.lockUpdateInProgress))
|
|
181
|
+
.pipe(take(1))
|
|
182
|
+
.subscribe(() => {
|
|
183
|
+
this.refreshStatus();
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
updateHomeKitCharacteristics() {
|
|
188
|
+
if (this.LockTargetState === undefined) {
|
|
189
|
+
this.debugLog(`Lock: ${this.accessory.displayName} LockTargetState: ${this.LockTargetState}`);
|
|
190
|
+
} else {
|
|
191
|
+
this.lockService.updateCharacteristic(this.platform.Characteristic.LockTargetState, this.LockTargetState);
|
|
192
|
+
this.debugLog(`Lock: ${this.accessory.displayName} updateCharacteristic LockTargetState: ${this.LockTargetState}`);
|
|
193
|
+
}
|
|
194
|
+
if (this.LockCurrentState === undefined) {
|
|
195
|
+
this.debugLog(`Lock: ${this.accessory.displayName} LockCurrentState: ${this.LockCurrentState}`);
|
|
196
|
+
} else {
|
|
197
|
+
this.lockService.updateCharacteristic(this.platform.Characteristic.LockCurrentState, this.LockCurrentState);
|
|
198
|
+
this.debugLog(`Lock: ${this.accessory.displayName} updateCharacteristic LockTargetState: ${this.LockCurrentState}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public apiError(e: any) {
|
|
203
|
+
this.lockService.updateCharacteristic(this.platform.Characteristic.LockTargetState, e);
|
|
204
|
+
this.lockService.updateCharacteristic(this.platform.Characteristic.LockCurrentState, e);
|
|
205
|
+
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private statusCode(push: AxiosResponse<{ statusCode: number }>) {
|
|
209
|
+
switch (push.data.statusCode) {
|
|
210
|
+
case 151:
|
|
211
|
+
this.errorLog(`Lock: ${this.accessory.displayName} Command not supported by this device type.`);
|
|
212
|
+
break;
|
|
213
|
+
case 152:
|
|
214
|
+
this.errorLog(`Lock: ${this.accessory.displayName} Device not found.`);
|
|
215
|
+
break;
|
|
216
|
+
case 160:
|
|
217
|
+
this.errorLog(`Lock: ${this.accessory.displayName} Command is not supported.`);
|
|
218
|
+
break;
|
|
219
|
+
case 161:
|
|
220
|
+
this.errorLog(`Lock: ${this.accessory.displayName} Device is offline.`);
|
|
221
|
+
break;
|
|
222
|
+
case 171:
|
|
223
|
+
this.errorLog(`Lock: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
|
|
224
|
+
break;
|
|
225
|
+
case 190:
|
|
226
|
+
this.errorLog(
|
|
227
|
+
`Lock: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
228
|
+
` Or command: ${JSON.stringify(push.data)} format is invalid`,
|
|
229
|
+
);
|
|
230
|
+
break;
|
|
231
|
+
case 100:
|
|
232
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Command successfully sent.`);
|
|
233
|
+
break;
|
|
234
|
+
default:
|
|
235
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Unknown statusCode.`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Handle requests to set the value of the "On" characteristic
|
|
241
|
+
*/
|
|
242
|
+
LockTargetStateSet(value: CharacteristicValue) {
|
|
243
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Set LockTargetState: ${value}`);
|
|
244
|
+
|
|
245
|
+
this.LockTargetState = value;
|
|
246
|
+
this.doLockUpdate.next();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
config(device: device & devicesConfig) {
|
|
250
|
+
let config = {};
|
|
251
|
+
if (device.lock) {
|
|
252
|
+
config = device.lock;
|
|
253
|
+
}
|
|
254
|
+
if (device.ble !== undefined) {
|
|
255
|
+
config['ble'] = device.ble;
|
|
256
|
+
}
|
|
257
|
+
if (device.logging !== undefined) {
|
|
258
|
+
config['logging'] = device.logging;
|
|
259
|
+
}
|
|
260
|
+
if (device.refreshRate !== undefined) {
|
|
261
|
+
config['refreshRate'] = device.refreshRate;
|
|
262
|
+
}
|
|
263
|
+
if (device.scanDuration !== undefined) {
|
|
264
|
+
config['scanDuration'] = device.scanDuration;
|
|
265
|
+
}
|
|
266
|
+
if (Object.entries(config).length !== 0) {
|
|
267
|
+
this.warnLog(`Lock: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
refreshRate(device: device & devicesConfig) {
|
|
272
|
+
if (device.refreshRate) {
|
|
273
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
274
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
275
|
+
} else if (this.platform.config.options!.refreshRate) {
|
|
276
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
277
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
scan(device: device & devicesConfig) {
|
|
282
|
+
if (device.scanDuration) {
|
|
283
|
+
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
284
|
+
if (device.ble) {
|
|
285
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
289
|
+
if (this.device.ble) {
|
|
290
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
logs(device: device & devicesConfig) {
|
|
296
|
+
if (this.platform.debugMode) {
|
|
297
|
+
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
298
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
299
|
+
} else if (device.logging) {
|
|
300
|
+
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
301
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
302
|
+
} else if (this.platform.config.options?.logging) {
|
|
303
|
+
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
304
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
305
|
+
} else {
|
|
306
|
+
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
307
|
+
this.debugLog(`Lock: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Logging for Device
|
|
313
|
+
*/
|
|
314
|
+
infoLog(...log: any[]) {
|
|
315
|
+
if (this.enablingDeviceLogging()) {
|
|
316
|
+
this.platform.log.info(String(...log));
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
warnLog(...log: any[]) {
|
|
321
|
+
if (this.enablingDeviceLogging()) {
|
|
322
|
+
this.platform.log.warn(String(...log));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
errorLog(...log: any[]) {
|
|
327
|
+
if (this.enablingDeviceLogging()) {
|
|
328
|
+
this.platform.log.error(String(...log));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
debugLog(...log: any[]) {
|
|
333
|
+
if (this.enablingDeviceLogging()) {
|
|
334
|
+
if (this.deviceLogging === 'debug') {
|
|
335
|
+
this.platform.log.info('[DEBUG]', String(...log));
|
|
336
|
+
} else {
|
|
337
|
+
this.platform.log.debug(String(...log));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
enablingDeviceLogging(): boolean {
|
|
343
|
+
return this.deviceLogging === 'debug' || this.deviceLogging === 'standard';
|
|
344
|
+
}
|
|
345
|
+
}
|
|
@@ -66,12 +66,6 @@ export class Meter {
|
|
|
66
66
|
this.CurrentTemperature = this.accessory.context.CurrentTemperature;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
// Meter Config
|
|
70
|
-
this.debugLog(
|
|
71
|
-
`Meter: ${this.accessory.displayName} Config: (ble: ${device.ble}, hide_temperature: ${device.meter?.hide_temperature},` +
|
|
72
|
-
` hide_humidity: ${device.meter?.hide_humidity})`,
|
|
73
|
-
);
|
|
74
|
-
|
|
75
69
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
76
70
|
this.doMeterUpdate = new Subject();
|
|
77
71
|
this.meterUpdateInProgress = false;
|
|
@@ -83,7 +77,7 @@ export class Meter {
|
|
|
83
77
|
accessory
|
|
84
78
|
.getService(this.platform.Service.AccessoryInformation)!
|
|
85
79
|
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'SwitchBot')
|
|
86
|
-
.setCharacteristic(this.platform.Characteristic.Model,
|
|
80
|
+
.setCharacteristic(this.platform.Characteristic.Model, this.model(device))
|
|
87
81
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!);
|
|
88
82
|
|
|
89
83
|
// Temperature Sensor Service
|
|
@@ -393,6 +387,18 @@ export class Meter {
|
|
|
393
387
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
394
388
|
}
|
|
395
389
|
|
|
390
|
+
model(device: device & devicesConfig): CharacteristicValue {
|
|
391
|
+
let model: string;
|
|
392
|
+
if (device.deviceType === 'Meter Plus (US)') {
|
|
393
|
+
model = 'SWITCHBOT-METERTH-W2301500';
|
|
394
|
+
} else if (device.deviceType === 'Meter Plus (JP)') {
|
|
395
|
+
model = 'SWITCHBOT-METERTH-W2201500';
|
|
396
|
+
} else {
|
|
397
|
+
model = 'SWITCHBOT-METERTH-S1';
|
|
398
|
+
}
|
|
399
|
+
return model;
|
|
400
|
+
}
|
|
401
|
+
|
|
396
402
|
config(device: device & devicesConfig) {
|
|
397
403
|
let config = {};
|
|
398
404
|
if (device.meter) {
|
|
@@ -54,13 +54,6 @@ export class Motion {
|
|
|
54
54
|
this.config(device);
|
|
55
55
|
this.MotionDetected = false;
|
|
56
56
|
|
|
57
|
-
// Motion Config
|
|
58
|
-
this.debugLog(
|
|
59
|
-
`Motion Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline},` +
|
|
60
|
-
` hide_lightsensor: ${device.motion?.hide_lightsensor},` +
|
|
61
|
-
` set_minLux: ${this.device.motion?.set_minLux}, set_maxLux: ${this.device.motion?.set_maxLux})`,
|
|
62
|
-
);
|
|
63
|
-
|
|
64
57
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
65
58
|
this.doMotionUpdate = new Subject();
|
|
66
59
|
this.motionUbpdateInProgress = false;
|
|
@@ -390,6 +383,9 @@ export class Motion {
|
|
|
390
383
|
if (device.scanDuration !== undefined) {
|
|
391
384
|
config['scanDuration'] = device.scanDuration;
|
|
392
385
|
}
|
|
386
|
+
if (device.offline !== undefined) {
|
|
387
|
+
config['offline'] = device.offline;
|
|
388
|
+
}
|
|
393
389
|
if (Object.entries(config).length !== 0) {
|
|
394
390
|
this.warnLog(`Motion Sensor: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
395
391
|
}
|
|
@@ -435,7 +431,7 @@ export class Motion {
|
|
|
435
431
|
}
|
|
436
432
|
}
|
|
437
433
|
|
|
438
|
-
|
|
434
|
+
minLux(): number {
|
|
439
435
|
if (this.device.motion?.set_minLux) {
|
|
440
436
|
this.set_minLux = this.device.motion!.set_minLux!;
|
|
441
437
|
} else {
|
|
@@ -444,7 +440,7 @@ export class Motion {
|
|
|
444
440
|
return this.set_minLux;
|
|
445
441
|
}
|
|
446
442
|
|
|
447
|
-
|
|
443
|
+
maxLux(): number {
|
|
448
444
|
if (this.device.motion?.set_maxLux) {
|
|
449
445
|
this.set_maxLux = this.device.motion!.set_maxLux!;
|
|
450
446
|
} else {
|
|
@@ -38,9 +38,6 @@ export class Plug {
|
|
|
38
38
|
this.On = this.accessory.context.On;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
// Plug Config
|
|
42
|
-
this.debugLog(`Plug: ${this.accessory.displayName} Config: (offline: ${device.offline})`);
|
|
43
|
-
|
|
44
41
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
45
42
|
this.doPlugUpdate = new Subject();
|
|
46
43
|
this.plugUpdateInProgress = false;
|
|
@@ -52,7 +49,7 @@ export class Plug {
|
|
|
52
49
|
accessory
|
|
53
50
|
.getService(this.platform.Service.AccessoryInformation)!
|
|
54
51
|
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'SwitchBot')
|
|
55
|
-
.setCharacteristic(this.platform.Characteristic.Model,
|
|
52
|
+
.setCharacteristic(this.platform.Characteristic.Model, this.model(device))
|
|
56
53
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!);
|
|
57
54
|
|
|
58
55
|
// get the WindowCovering service if it exists, otherwise create a new WindowCovering service
|
|
@@ -145,8 +142,11 @@ export class Plug {
|
|
|
145
142
|
/**
|
|
146
143
|
* Pushes the requested changes to the SwitchBot API
|
|
147
144
|
* deviceType commandType Command command parameter Description
|
|
148
|
-
* Plug
|
|
149
|
-
* Plug
|
|
145
|
+
* Plug - "command" "turnOff" "default" = set to OFF state
|
|
146
|
+
* Plug - "command" "turnOn" "default" = set to ON state
|
|
147
|
+
* Plug Mini (US/JP) - "command" turnOn default = set to ON state
|
|
148
|
+
* Plug Mini (US/JP) - "command" turnOff default = set to OFF state
|
|
149
|
+
* Plug Mini (US/JP) - "command" toggle default = toggle state
|
|
150
150
|
*/
|
|
151
151
|
async pushChanges() {
|
|
152
152
|
if (this.On !== this.OnCached) {
|
|
@@ -228,7 +228,7 @@ export class Plug {
|
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
async offlineOff(): Promise<void> {
|
|
232
232
|
if (this.device.offline) {
|
|
233
233
|
this.On = false;
|
|
234
234
|
this.service.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
|
|
@@ -238,14 +238,26 @@ export class Plug {
|
|
|
238
238
|
/**
|
|
239
239
|
* Handle requests to set the value of the "On" characteristic
|
|
240
240
|
*/
|
|
241
|
-
OnSet(value: CharacteristicValue) {
|
|
241
|
+
async OnSet(value: CharacteristicValue): Promise<void> {
|
|
242
242
|
this.debugLog(`Plug: ${this.accessory.displayName} - Set On: ${value}`);
|
|
243
243
|
|
|
244
244
|
this.On = value;
|
|
245
245
|
this.doPlugUpdate.next();
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
|
|
248
|
+
model(device: device & devicesConfig): string {
|
|
249
|
+
let model: string;
|
|
250
|
+
if (device.deviceType === 'Plug Mini (US)') {
|
|
251
|
+
model = 'SWITCHBOT-PLUG-W1901400';
|
|
252
|
+
} else if (device.deviceType === 'Plug Mini (JP)') {
|
|
253
|
+
model = 'SWITCHBOT-PLUG-W2001400';
|
|
254
|
+
} else {
|
|
255
|
+
model = 'SWITCHBOT-PLUG-SP11';
|
|
256
|
+
}
|
|
257
|
+
return model;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async config(device: device & devicesConfig): Promise<void> {
|
|
249
261
|
let config = {};
|
|
250
262
|
if (device.plug) {
|
|
251
263
|
config = device.plug;
|
|
@@ -262,12 +274,15 @@ export class Plug {
|
|
|
262
274
|
if (device.scanDuration !== undefined) {
|
|
263
275
|
config['scanDuration'] = device.scanDuration;
|
|
264
276
|
}
|
|
277
|
+
if (device.offline !== undefined) {
|
|
278
|
+
config['offline'] = device.offline;
|
|
279
|
+
}
|
|
265
280
|
if (Object.entries(config).length !== 0) {
|
|
266
281
|
this.warnLog(`Plug: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
267
282
|
}
|
|
268
283
|
}
|
|
269
284
|
|
|
270
|
-
refreshRate(device: device & devicesConfig) {
|
|
285
|
+
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
271
286
|
if (device.refreshRate) {
|
|
272
287
|
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
273
288
|
this.debugLog(`Plug: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
@@ -277,7 +292,7 @@ export class Plug {
|
|
|
277
292
|
}
|
|
278
293
|
}
|
|
279
294
|
|
|
280
|
-
scan(device: device & devicesConfig) {
|
|
295
|
+
async scan(device: device & devicesConfig): Promise<void> {
|
|
281
296
|
if (device.scanDuration) {
|
|
282
297
|
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
283
298
|
if (device.ble) {
|
|
@@ -291,7 +306,7 @@ export class Plug {
|
|
|
291
306
|
}
|
|
292
307
|
}
|
|
293
308
|
|
|
294
|
-
logs(device: device & devicesConfig) {
|
|
309
|
+
async logs(device: device & devicesConfig): Promise<void> {
|
|
295
310
|
if (this.platform.debugMode) {
|
|
296
311
|
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
297
312
|
this.debugLog(`Plug: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
@@ -310,25 +325,25 @@ export class Plug {
|
|
|
310
325
|
/**
|
|
311
326
|
* Logging for Device
|
|
312
327
|
*/
|
|
313
|
-
infoLog(...log: any[]) {
|
|
328
|
+
infoLog(...log: any[]): void {
|
|
314
329
|
if (this.enablingDeviceLogging()) {
|
|
315
330
|
this.platform.log.info(String(...log));
|
|
316
331
|
}
|
|
317
332
|
}
|
|
318
333
|
|
|
319
|
-
warnLog(...log: any[]) {
|
|
334
|
+
warnLog(...log: any[]): void {
|
|
320
335
|
if (this.enablingDeviceLogging()) {
|
|
321
336
|
this.platform.log.warn(String(...log));
|
|
322
337
|
}
|
|
323
338
|
}
|
|
324
339
|
|
|
325
|
-
errorLog(...log: any[]) {
|
|
340
|
+
errorLog(...log: any[]): void {
|
|
326
341
|
if (this.enablingDeviceLogging()) {
|
|
327
342
|
this.platform.log.error(String(...log));
|
|
328
343
|
}
|
|
329
344
|
}
|
|
330
345
|
|
|
331
|
-
debugLog(...log: any[]) {
|
|
346
|
+
debugLog(...log: any[]): void {
|
|
332
347
|
if (this.enablingDeviceLogging()) {
|
|
333
348
|
if (this.deviceLogging === 'debug') {
|
|
334
349
|
this.platform.log.info('[DEBUG]', String(...log));
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|