@switchbot/homebridge-switchbot 3.5.0-beta.9 → 3.5.1-beta.0
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/.vscode/settings.json +4 -1
- package/CHANGELOG.md +4 -1
- package/config.schema.json +164 -22
- package/dist/device/blindtilt.d.ts +21 -96
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +457 -866
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +27 -72
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +851 -913
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +15 -69
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +316 -742
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +15 -76
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +380 -833
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +14 -66
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +267 -602
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +18 -89
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +469 -897
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +76 -0
- package/dist/device/device.d.ts.map +1 -0
- package/dist/device/device.js +846 -0
- package/dist/device/device.js.map +1 -0
- package/dist/device/fan.d.ts +63 -0
- package/dist/device/fan.d.ts.map +1 -0
- package/dist/device/fan.js +645 -0
- package/dist/device/fan.js.map +1 -0
- package/dist/device/hub.d.ts +19 -58
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +304 -640
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +11 -66
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +300 -710
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +12 -64
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +225 -643
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +12 -70
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +371 -742
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +17 -63
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +309 -642
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +15 -64
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +223 -638
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +15 -65
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +216 -644
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +12 -69
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +209 -588
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +10 -57
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +141 -532
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +13 -63
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +252 -609
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +11 -63
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +179 -521
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +22 -16
- package/dist/homebridge-ui/server.js +1 -1
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts +10 -50
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +337 -482
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +8 -39
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +108 -333
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +7 -36
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +47 -299
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +7 -43
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +95 -364
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +46 -0
- package/dist/irdevice/irdevice.d.ts.map +1 -0
- package/dist/irdevice/irdevice.js +393 -0
- package/dist/irdevice/irdevice.js.map +1 -0
- package/dist/irdevice/light.d.ts +12 -45
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +121 -376
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +19 -48
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +441 -584
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +8 -40
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +94 -353
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +7 -36
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +48 -299
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +7 -36
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +50 -305
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +22 -8
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +342 -191
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +66 -18
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +16 -552
- package/dist/settings.js.map +1 -1
- package/dist/utils.d.ts +95 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +657 -1
- package/dist/utils.js.map +1 -1
- package/eslint.config.js +96 -0
- package/package.json +20 -16
- package/src/custom.d.ts +2 -1
- package/src/device/blindtilt.ts +488 -937
- package/src/device/bot.ts +907 -1016
- package/src/device/ceilinglight.ts +330 -798
- package/src/device/colorbulb.ts +394 -904
- package/src/device/contact.ts +298 -637
- package/src/device/curtain.ts +496 -954
- package/src/device/device.ts +872 -0
- package/src/device/fan.ts +692 -0
- package/src/device/hub.ts +338 -671
- package/src/device/humidifier.ts +330 -777
- package/src/device/iosensor.ts +258 -671
- package/src/device/lightstrip.ts +394 -809
- package/src/device/lock.ts +345 -700
- package/src/device/meter.ts +256 -666
- package/src/device/meterplus.ts +248 -672
- package/src/device/motion.ts +234 -622
- package/src/device/plug.ts +152 -572
- package/src/device/robotvacuumcleaner.ts +273 -653
- package/src/device/waterdetector.ts +198 -549
- package/src/homebridge-ui/public/index.html +22 -16
- package/src/homebridge-ui/server.ts +1 -1
- package/src/index.ts +4 -3
- package/src/irdevice/airconditioner.ts +368 -540
- package/src/irdevice/airpurifier.ts +134 -369
- package/src/irdevice/camera.ts +60 -324
- package/src/irdevice/fan.ts +111 -392
- package/src/irdevice/irdevice.ts +406 -0
- package/src/irdevice/light.ts +159 -425
- package/src/irdevice/other.ts +509 -661
- package/src/irdevice/tv.ts +123 -388
- package/src/irdevice/vacuumcleaner.ts +61 -324
- package/src/irdevice/waterheater.ts +63 -333
- package/src/platform.ts +395 -259
- package/src/settings.ts +120 -610
- package/src/utils.ts +661 -1
- package/src/device/waterdetector.json +0 -11
package/src/device/bot.ts
CHANGED
|
@@ -1,114 +1,153 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* bot.ts: @switchbot/homebridge-switchbot.
|
|
4
|
+
*/
|
|
5
|
+
import { deviceBase } from './device.js';
|
|
3
6
|
import { interval, Subject } from 'rxjs';
|
|
4
|
-
import { SwitchBotPlatform } from '../platform.js';
|
|
5
7
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
+
|
|
9
|
+
import type { SwitchBotPlatform } from '../platform.js';
|
|
10
|
+
import type { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
|
|
11
|
+
import type { device, devicesConfig, serviceData, deviceStatus } from '../settings.js';
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* Platform Accessory
|
|
11
15
|
* An instance of this class is created for each accessory your platform registers
|
|
12
16
|
* Each accessory may expose multiple services of different service types.
|
|
13
17
|
*/
|
|
14
|
-
export class Bot {
|
|
15
|
-
public readonly api: API;
|
|
16
|
-
public readonly log: Logging;
|
|
17
|
-
public readonly config!: SwitchBotPlatformConfig;
|
|
18
|
-
protected readonly hap: HAP;
|
|
18
|
+
export class Bot extends deviceBase {
|
|
19
19
|
// Services
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
20
|
+
private Battery: {
|
|
21
|
+
Name: CharacteristicValue;
|
|
22
|
+
Service: Service;
|
|
23
|
+
BatteryLevel: CharacteristicValue;
|
|
24
|
+
StatusLowBattery: CharacteristicValue;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
private Switch?: {
|
|
28
|
+
Name: CharacteristicValue;
|
|
29
|
+
Service: Service;
|
|
30
|
+
On: CharacteristicValue;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
private GarageDoor?: {
|
|
34
|
+
Name: CharacteristicValue;
|
|
35
|
+
Service: Service;
|
|
36
|
+
On: CharacteristicValue;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
private Door?: {
|
|
40
|
+
Name: CharacteristicValue;
|
|
41
|
+
Service: Service;
|
|
42
|
+
On: CharacteristicValue;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
private Window?: {
|
|
46
|
+
Name: CharacteristicValue;
|
|
47
|
+
Service: Service;
|
|
48
|
+
On: CharacteristicValue;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
private WindowCovering?: {
|
|
52
|
+
Name: CharacteristicValue;
|
|
53
|
+
Service: Service;
|
|
54
|
+
On: CharacteristicValue;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
private LockMechanism?: {
|
|
58
|
+
Name: CharacteristicValue;
|
|
59
|
+
Service: Service;
|
|
60
|
+
On: CharacteristicValue;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
private Faucet?: {
|
|
64
|
+
Name: CharacteristicValue;
|
|
65
|
+
Service: Service;
|
|
66
|
+
On: CharacteristicValue;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
private Fan?: {
|
|
70
|
+
Name: CharacteristicValue;
|
|
71
|
+
Service: Service;
|
|
72
|
+
On: CharacteristicValue;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
private StatefulProgrammableSwitch?: {
|
|
76
|
+
Name: CharacteristicValue;
|
|
77
|
+
Service: Service;
|
|
78
|
+
On: CharacteristicValue;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
private Outlet?: {
|
|
82
|
+
Name: CharacteristicValue;
|
|
83
|
+
Service: Service;
|
|
84
|
+
On: CharacteristicValue;
|
|
85
|
+
};
|
|
50
86
|
|
|
51
87
|
// Config
|
|
52
88
|
botMode!: string;
|
|
53
89
|
allowPush?: boolean;
|
|
54
90
|
doublePress!: number;
|
|
55
|
-
scanDuration!: number;
|
|
56
91
|
botDeviceType!: string;
|
|
57
92
|
pushRatePress!: number;
|
|
58
|
-
deviceLogging!: string;
|
|
59
93
|
multiPressCount!: number;
|
|
60
|
-
deviceRefreshRate!: number;
|
|
61
94
|
|
|
62
95
|
// Updates
|
|
63
96
|
botUpdateInProgress!: boolean;
|
|
64
97
|
doBotUpdate!: Subject<void>;
|
|
65
98
|
|
|
66
|
-
// Connection
|
|
67
|
-
private readonly OpenAPI: boolean;
|
|
68
|
-
private readonly BLE: boolean;
|
|
69
|
-
|
|
70
99
|
constructor(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
100
|
+
readonly platform: SwitchBotPlatform,
|
|
101
|
+
accessory: PlatformAccessory,
|
|
102
|
+
device: device & devicesConfig,
|
|
74
103
|
) {
|
|
75
|
-
|
|
76
|
-
this.log = this.platform.log;
|
|
77
|
-
this.config = this.platform.config;
|
|
78
|
-
this.hap = this.api.hap;
|
|
79
|
-
// Connection
|
|
80
|
-
this.BLE = this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI';
|
|
81
|
-
this.OpenAPI = this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI';
|
|
104
|
+
super(platform, accessory, device);
|
|
82
105
|
// default placeholders
|
|
83
|
-
this.
|
|
84
|
-
this.deviceType(device);
|
|
85
|
-
this.scan(device);
|
|
86
|
-
this.refreshRate(device);
|
|
87
|
-
this.PressOrSwitch(device);
|
|
88
|
-
this.allowPushChanges(device);
|
|
89
|
-
this.deviceContext();
|
|
90
|
-
this.DoublePress(device);
|
|
91
|
-
this.deviceConfig(device);
|
|
92
|
-
|
|
93
|
-
this.multiPressCount = 0;
|
|
106
|
+
this.getBotConfigSettings(device);
|
|
94
107
|
|
|
95
108
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
96
109
|
this.doBotUpdate = new Subject();
|
|
97
110
|
this.botUpdateInProgress = false;
|
|
98
111
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
.
|
|
105
|
-
.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
accessory.context.Battery = accessory.context.Battery ?? {};
|
|
113
|
+
// Initialize Battery property
|
|
114
|
+
this.Battery = {
|
|
115
|
+
Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
|
|
116
|
+
Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
|
|
117
|
+
BatteryLevel: accessory.context.BatteryLevel ?? 100,
|
|
118
|
+
StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
|
|
119
|
+
};
|
|
120
|
+
accessory.context.Battery = this.Battery as object;
|
|
121
|
+
|
|
122
|
+
// Initialize Battery Characteristics
|
|
123
|
+
this.Battery.Service
|
|
124
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
|
|
125
|
+
.setCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery)
|
|
126
|
+
.setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
|
|
109
127
|
|
|
110
128
|
// deviceType
|
|
111
129
|
if (this.botDeviceType === 'switch') {
|
|
130
|
+
// Initialize Switch Service
|
|
131
|
+
accessory.context.Switch = accessory.context.Switch ?? {};
|
|
132
|
+
this.Switch = {
|
|
133
|
+
Name: accessory.context.Switch.Name ?? accessory.displayName,
|
|
134
|
+
Service: accessory.getService(this.hap.Service.Switch) ?? accessory.addService(this.hap.Service.Switch) as Service,
|
|
135
|
+
On: accessory.context.On ?? false,
|
|
136
|
+
};
|
|
137
|
+
accessory.context.Switch = this.Switch as object;
|
|
138
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Switch`);
|
|
139
|
+
|
|
140
|
+
// Initialize Switch Characteristics
|
|
141
|
+
this.Switch.Service
|
|
142
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.Switch.Name)
|
|
143
|
+
.setCharacteristic(this.hap.Characteristic.On, this.Switch.On)
|
|
144
|
+
.getCharacteristic(this.hap.Characteristic.On)
|
|
145
|
+
.onGet(() => {
|
|
146
|
+
return this.Switch!.On;
|
|
147
|
+
})
|
|
148
|
+
.onSet(this.OnSet.bind(this));
|
|
149
|
+
|
|
150
|
+
// Remove other services
|
|
112
151
|
this.removeFanService(accessory);
|
|
113
152
|
this.removeLockService(accessory);
|
|
114
153
|
this.removeDoorService(accessory);
|
|
@@ -118,19 +157,33 @@ export class Bot {
|
|
|
118
157
|
this.removeGarageDoorService(accessory);
|
|
119
158
|
this.removeWindowCoveringService(accessory);
|
|
120
159
|
this.removeStatefulProgrammableSwitchService(accessory);
|
|
160
|
+
} else if (this.botDeviceType === 'garagedoor') {
|
|
161
|
+
// Initialize GarageDoor Service
|
|
162
|
+
accessory.context.GarageDoor = accessory.context.GarageDoor ?? {};
|
|
163
|
+
this.GarageDoor = {
|
|
164
|
+
Name: accessory.context.GarageDoor.Name ?? accessory.displayName,
|
|
165
|
+
Service: accessory.getService(this.hap.Service.GarageDoorOpener) ?? accessory.addService(this.hap.Service.GarageDoorOpener) as Service,
|
|
166
|
+
On: accessory.context.On ?? false,
|
|
167
|
+
};
|
|
168
|
+
accessory.context.GarageDoor = this.GarageDoor as object;
|
|
169
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Garage Door Opener`);
|
|
121
170
|
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
171
|
+
// Initialize GarageDoor Characteristics
|
|
172
|
+
this.GarageDoor.Service
|
|
173
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.GarageDoor.Name)
|
|
174
|
+
.setCharacteristic(this.hap.Characteristic.ObstructionDetected, false)
|
|
175
|
+
.getCharacteristic(this.hap.Characteristic.TargetDoorState).setProps({
|
|
176
|
+
validValues: [0, 100],
|
|
177
|
+
minValue: 0,
|
|
178
|
+
maxValue: 100,
|
|
179
|
+
minStep: 100,
|
|
180
|
+
})
|
|
181
|
+
.onGet(() => {
|
|
182
|
+
return this.GarageDoor!.On;
|
|
183
|
+
})
|
|
184
|
+
.onSet(this.OnSet.bind(this));
|
|
127
185
|
|
|
128
|
-
|
|
129
|
-
if (!this.switchService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
130
|
-
this.switchService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
131
|
-
}
|
|
132
|
-
this.switchService.getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
|
|
133
|
-
} else if (this.botDeviceType === 'garagedoor') {
|
|
186
|
+
// Remove other services
|
|
134
187
|
this.removeFanService(accessory);
|
|
135
188
|
this.removeLockService(accessory);
|
|
136
189
|
this.removeDoorService(accessory);
|
|
@@ -140,20 +193,33 @@ export class Bot {
|
|
|
140
193
|
this.removeWindowService(accessory);
|
|
141
194
|
this.removeWindowCoveringService(accessory);
|
|
142
195
|
this.removeStatefulProgrammableSwitchService(accessory);
|
|
196
|
+
} else if (this.botDeviceType === 'door') {
|
|
197
|
+
// Initialize Door Service
|
|
198
|
+
accessory.context.Door = accessory.context.Door ?? {};
|
|
199
|
+
this.Door = {
|
|
200
|
+
Name: accessory.context.Door.Name ?? accessory.displayName,
|
|
201
|
+
Service: accessory.getService(this.hap.Service.Door) ?? accessory.addService(this.hap.Service.Door) as Service,
|
|
202
|
+
On: accessory.context.On ?? false,
|
|
203
|
+
};
|
|
204
|
+
accessory.context.Door = this.Door as object;
|
|
205
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Door`);
|
|
143
206
|
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
207
|
+
// Initialize Door Characteristics
|
|
208
|
+
this.Door.Service
|
|
209
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.Door.Name)
|
|
210
|
+
.setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED)
|
|
211
|
+
.getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
|
|
212
|
+
validValues: [0, 100],
|
|
213
|
+
minValue: 0,
|
|
214
|
+
maxValue: 100,
|
|
215
|
+
minStep: 100,
|
|
216
|
+
})
|
|
217
|
+
.onGet(() => {
|
|
218
|
+
return this.Door!.On;
|
|
219
|
+
})
|
|
220
|
+
.onSet(this.OnSet.bind(this));
|
|
149
221
|
|
|
150
|
-
|
|
151
|
-
if (!this.garageDoorService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
152
|
-
this.garageDoorService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
153
|
-
}
|
|
154
|
-
this.garageDoorService.getCharacteristic(this.hap.Characteristic.TargetDoorState).onSet(this.OnSet.bind(this));
|
|
155
|
-
this.garageDoorService.setCharacteristic(this.hap.Characteristic.ObstructionDetected, false);
|
|
156
|
-
} else if (this.botDeviceType === 'door') {
|
|
222
|
+
// Remove other services
|
|
157
223
|
this.removeFanService(accessory);
|
|
158
224
|
this.removeLockService(accessory);
|
|
159
225
|
this.removeOutletService(accessory);
|
|
@@ -163,28 +229,33 @@ export class Bot {
|
|
|
163
229
|
this.removeGarageDoorService(accessory);
|
|
164
230
|
this.removeWindowCoveringService(accessory);
|
|
165
231
|
this.removeStatefulProgrammableSwitchService(accessory);
|
|
232
|
+
} else if (this.botDeviceType === 'window') {
|
|
233
|
+
// Initialize Window Service
|
|
234
|
+
accessory.context.Window = accessory.context.Window ?? {};
|
|
235
|
+
this.Window = {
|
|
236
|
+
Name: accessory.context.Window.Name ?? accessory.displayName,
|
|
237
|
+
Service: accessory.getService(this.hap.Service.Window) ?? accessory.addService(this.hap.Service.Window) as Service,
|
|
238
|
+
On: accessory.context.On ?? false,
|
|
239
|
+
};
|
|
240
|
+
accessory.context.Window = this.Window as object;
|
|
241
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Window`);
|
|
166
242
|
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
this.doorService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
|
|
174
|
-
if (!this.doorService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
175
|
-
this.doorService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
176
|
-
}
|
|
177
|
-
this.doorService
|
|
178
|
-
.getCharacteristic(this.hap.Characteristic.TargetPosition)
|
|
179
|
-
.setProps({
|
|
243
|
+
// Initialize Window Characteristics
|
|
244
|
+
this.Window.Service
|
|
245
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.Window.Name)
|
|
246
|
+
.setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED)
|
|
247
|
+
.getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
|
|
180
248
|
validValues: [0, 100],
|
|
181
249
|
minValue: 0,
|
|
182
250
|
maxValue: 100,
|
|
183
251
|
minStep: 100,
|
|
184
252
|
})
|
|
253
|
+
.onGet(() => {
|
|
254
|
+
return this.Window!.On;
|
|
255
|
+
})
|
|
185
256
|
.onSet(this.OnSet.bind(this));
|
|
186
|
-
|
|
187
|
-
|
|
257
|
+
|
|
258
|
+
// Remove other services
|
|
188
259
|
this.removeFanService(accessory);
|
|
189
260
|
this.removeLockService(accessory);
|
|
190
261
|
this.removeDoorService(accessory);
|
|
@@ -194,28 +265,33 @@ export class Bot {
|
|
|
194
265
|
this.removeGarageDoorService(accessory);
|
|
195
266
|
this.removeWindowCoveringService(accessory);
|
|
196
267
|
this.removeStatefulProgrammableSwitchService(accessory);
|
|
268
|
+
} else if (this.botDeviceType === 'windowcovering') {
|
|
269
|
+
// Initialize WindowCovering Service
|
|
270
|
+
accessory.context.WindowCovering = accessory.context.WindowCovering ?? {};
|
|
271
|
+
this.WindowCovering = {
|
|
272
|
+
Name: accessory.context.WindowCovering.Name ?? accessory.displayName,
|
|
273
|
+
Service: accessory.getService(this.hap.Service.WindowCovering) ?? accessory.addService(this.hap.Service.WindowCovering) as Service,
|
|
274
|
+
On: accessory.context.On ?? false,
|
|
275
|
+
};
|
|
276
|
+
accessory.context.WindowCovering = this.WindowCovering as object;
|
|
277
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Window Covering`);
|
|
197
278
|
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
this.windowService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
|
|
205
|
-
if (!this.windowService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
206
|
-
this.windowService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
207
|
-
}
|
|
208
|
-
this.windowService
|
|
209
|
-
.getCharacteristic(this.hap.Characteristic.TargetPosition)
|
|
210
|
-
.setProps({
|
|
279
|
+
// Initialize WindowCovering Characteristics
|
|
280
|
+
this.WindowCovering.Service
|
|
281
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name)
|
|
282
|
+
.setCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED)
|
|
283
|
+
.getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
|
|
211
284
|
validValues: [0, 100],
|
|
212
285
|
minValue: 0,
|
|
213
286
|
maxValue: 100,
|
|
214
287
|
minStep: 100,
|
|
215
288
|
})
|
|
289
|
+
.onGet(() => {
|
|
290
|
+
return this.WindowCovering!.On;
|
|
291
|
+
})
|
|
216
292
|
.onSet(this.OnSet.bind(this));
|
|
217
|
-
|
|
218
|
-
|
|
293
|
+
|
|
294
|
+
// Remove other services
|
|
219
295
|
this.removeFanService(accessory);
|
|
220
296
|
this.removeLockService(accessory);
|
|
221
297
|
this.removeDoorService(accessory);
|
|
@@ -225,28 +301,27 @@ export class Bot {
|
|
|
225
301
|
this.removeWindowService(accessory);
|
|
226
302
|
this.removeGarageDoorService(accessory);
|
|
227
303
|
this.removeStatefulProgrammableSwitchService(accessory);
|
|
304
|
+
} else if (this.botDeviceType === 'lock') {
|
|
305
|
+
// Initialize Lock Service
|
|
306
|
+
accessory.context.LockMechanism = accessory.context.LockMechanism ?? {};
|
|
307
|
+
this.LockMechanism = {
|
|
308
|
+
Name: accessory.context.LockMechanism.Name ?? accessory.displayName,
|
|
309
|
+
Service: accessory.getService(this.hap.Service.LockMechanism) ?? accessory.addService(this.hap.Service.LockMechanism) as Service,
|
|
310
|
+
On: accessory.context.On ?? false,
|
|
311
|
+
};
|
|
312
|
+
accessory.context.LockMechanism = this.LockMechanism as object;
|
|
313
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Lock`);
|
|
228
314
|
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
this.windowCoveringService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
|
|
236
|
-
if (!this.windowCoveringService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
237
|
-
this.windowCoveringService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
238
|
-
}
|
|
239
|
-
this.windowCoveringService
|
|
240
|
-
.getCharacteristic(this.hap.Characteristic.TargetPosition)
|
|
241
|
-
.setProps({
|
|
242
|
-
validValues: [0, 100],
|
|
243
|
-
minValue: 0,
|
|
244
|
-
maxValue: 100,
|
|
245
|
-
minStep: 100,
|
|
315
|
+
// Initialize Lock Characteristics
|
|
316
|
+
this.LockMechanism.Service
|
|
317
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.LockMechanism.Name)
|
|
318
|
+
.getCharacteristic(this.hap.Characteristic.LockTargetState)
|
|
319
|
+
.onGet(() => {
|
|
320
|
+
return this.LockMechanism!.On;
|
|
246
321
|
})
|
|
247
322
|
.onSet(this.OnSet.bind(this));
|
|
248
|
-
|
|
249
|
-
|
|
323
|
+
|
|
324
|
+
// Remove other services
|
|
250
325
|
this.removeFanService(accessory);
|
|
251
326
|
this.removeDoorService(accessory);
|
|
252
327
|
this.removeOutletService(accessory);
|
|
@@ -256,19 +331,27 @@ export class Bot {
|
|
|
256
331
|
this.removeGarageDoorService(accessory);
|
|
257
332
|
this.removeWindowCoveringService(accessory);
|
|
258
333
|
this.removeStatefulProgrammableSwitchService(accessory);
|
|
334
|
+
} else if (this.botDeviceType === 'faucet') {
|
|
335
|
+
// Initialize Faucet Service
|
|
336
|
+
accessory.context.Faucet = accessory.context.Faucet ?? {};
|
|
337
|
+
this.Faucet = {
|
|
338
|
+
Name: accessory.context.Faucet.Name ?? accessory.displayName,
|
|
339
|
+
Service: accessory.getService(this.hap.Service.Faucet) ?? accessory.addService(this.hap.Service.Faucet) as Service,
|
|
340
|
+
On: accessory.context.On ?? false,
|
|
341
|
+
};
|
|
342
|
+
accessory.context.Faucet = this.Faucet as object;
|
|
343
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Faucet`);
|
|
259
344
|
|
|
260
|
-
//
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
345
|
+
// Initialize Faucet Characteristics
|
|
346
|
+
this.Faucet.Service
|
|
347
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.Faucet.Name)
|
|
348
|
+
.getCharacteristic(this.hap.Characteristic.Active)
|
|
349
|
+
.onGet(() => {
|
|
350
|
+
return this.Faucet!.On;
|
|
351
|
+
})
|
|
352
|
+
.onSet(this.OnSet.bind(this));
|
|
265
353
|
|
|
266
|
-
|
|
267
|
-
if (!this.lockService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
268
|
-
this.lockService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
269
|
-
}
|
|
270
|
-
this.lockService.getCharacteristic(this.hap.Characteristic.LockTargetState).onSet(this.OnSet.bind(this));
|
|
271
|
-
} else if (this.botDeviceType === 'faucet') {
|
|
354
|
+
// Remove other services
|
|
272
355
|
this.removeFanService(accessory);
|
|
273
356
|
this.removeLockService(accessory);
|
|
274
357
|
this.removeDoorService(accessory);
|
|
@@ -278,19 +361,27 @@ export class Bot {
|
|
|
278
361
|
this.removeGarageDoorService(accessory);
|
|
279
362
|
this.removeWindowCoveringService(accessory);
|
|
280
363
|
this.removeStatefulProgrammableSwitchService(accessory);
|
|
364
|
+
} else if (this.botDeviceType === 'fan') {
|
|
365
|
+
// Initialize Fan Service
|
|
366
|
+
accessory.context.Fan = accessory.context.Fan ?? {};
|
|
367
|
+
this.Fan = {
|
|
368
|
+
Name: accessory.context.Fan.Name ?? accessory.displayName,
|
|
369
|
+
Service: accessory.getService(this.hap.Service.Fanv2) ?? accessory.addService(this.hap.Service.Fanv2) as Service,
|
|
370
|
+
On: accessory.context.On ?? false,
|
|
371
|
+
};
|
|
372
|
+
accessory.context.Fan = this.Fan as object;
|
|
373
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Fan`);
|
|
281
374
|
|
|
282
|
-
//
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
375
|
+
// Initialize Fan Characteristics
|
|
376
|
+
this.Fan.Service
|
|
377
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.Fan.Name)
|
|
378
|
+
.getCharacteristic(this.hap.Characteristic.On)
|
|
379
|
+
.onGet(() => {
|
|
380
|
+
return this.Fan!.On;
|
|
381
|
+
})
|
|
382
|
+
.onSet(this.OnSet.bind(this));
|
|
287
383
|
|
|
288
|
-
|
|
289
|
-
if (!this.faucetService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
290
|
-
this.faucetService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
291
|
-
}
|
|
292
|
-
this.faucetService.getCharacteristic(this.hap.Characteristic.Active).onSet(this.OnSet.bind(this));
|
|
293
|
-
} else if (this.botDeviceType === 'fan') {
|
|
384
|
+
// Remove other services
|
|
294
385
|
this.removeLockService(accessory);
|
|
295
386
|
this.removeDoorService(accessory);
|
|
296
387
|
this.removeFaucetService(accessory);
|
|
@@ -300,19 +391,28 @@ export class Bot {
|
|
|
300
391
|
this.removeGarageDoorService(accessory);
|
|
301
392
|
this.removeWindowCoveringService(accessory);
|
|
302
393
|
this.removeStatefulProgrammableSwitchService(accessory);
|
|
394
|
+
} else if (this.botDeviceType === 'stateful') {
|
|
395
|
+
// Initialize StatefulProgrammableSwitch Service
|
|
396
|
+
accessory.context.StatefulProgrammableSwitch = accessory.context.StatefulProgrammableSwitch ?? {};
|
|
397
|
+
this.StatefulProgrammableSwitch = {
|
|
398
|
+
Name: accessory.context.StatefulProgrammableSwitch.Name ?? accessory.displayName,
|
|
399
|
+
Service: accessory.getService(this.hap.Service.StatefulProgrammableSwitch)
|
|
400
|
+
?? accessory.addService(this.hap.Service.StatefulProgrammableSwitch) as Service,
|
|
401
|
+
On: accessory.context.On ?? false,
|
|
402
|
+
};
|
|
403
|
+
accessory.context.StatefulProgrammableSwitch = this.StatefulProgrammableSwitch as object;
|
|
404
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Stateful Programmable Switch`);
|
|
303
405
|
|
|
304
|
-
//
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
406
|
+
// Initialize StatefulProgrammableSwitch Characteristics
|
|
407
|
+
this.StatefulProgrammableSwitch.Service
|
|
408
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.StatefulProgrammableSwitch.Name)
|
|
409
|
+
.getCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState)
|
|
410
|
+
.onGet(() => {
|
|
411
|
+
return this.StatefulProgrammableSwitch!.On;
|
|
412
|
+
})
|
|
413
|
+
.onSet(this.OnSet.bind(this));
|
|
309
414
|
|
|
310
|
-
|
|
311
|
-
if (!this.fanService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
312
|
-
this.fanService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
313
|
-
}
|
|
314
|
-
this.fanService.getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
|
|
315
|
-
} else if (this.botDeviceType === 'stateful') {
|
|
415
|
+
// Remove other services
|
|
316
416
|
this.removeFanService(accessory);
|
|
317
417
|
this.removeLockService(accessory);
|
|
318
418
|
this.removeDoorService(accessory);
|
|
@@ -322,21 +422,27 @@ export class Bot {
|
|
|
322
422
|
this.removeWindowService(accessory);
|
|
323
423
|
this.removeGarageDoorService(accessory);
|
|
324
424
|
this.removeWindowCoveringService(accessory);
|
|
425
|
+
} else {
|
|
426
|
+
// Initialize Switch property
|
|
427
|
+
accessory.context.Outlet = accessory.context.Outlet ?? {};
|
|
428
|
+
this.Outlet = {
|
|
429
|
+
Name: accessory.context.Outlet.Name ?? accessory.displayName,
|
|
430
|
+
Service: accessory.getService(this.hap.Service.Outlet) ?? accessory.addService(this.hap.Service.Outlet) as Service,
|
|
431
|
+
On: accessory.context.On ?? false,
|
|
432
|
+
};
|
|
433
|
+
accessory.context.Outlet = this.Outlet as object;
|
|
434
|
+
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Outlet`);
|
|
325
435
|
|
|
326
|
-
//
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
if (!this.statefulProgrammableSwitchService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
334
|
-
this.statefulProgrammableSwitchService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
335
|
-
}
|
|
336
|
-
this.statefulProgrammableSwitchService
|
|
337
|
-
.getCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState)
|
|
436
|
+
// Initialize Outlet Characteristics
|
|
437
|
+
this.Outlet.Service
|
|
438
|
+
.setCharacteristic(this.hap.Characteristic.Name, this.Outlet.Name)
|
|
439
|
+
.getCharacteristic(this.hap.Characteristic.On)
|
|
440
|
+
.onGet(() => {
|
|
441
|
+
return this.Outlet!.On;
|
|
442
|
+
})
|
|
338
443
|
.onSet(this.OnSet.bind(this));
|
|
339
|
-
|
|
444
|
+
|
|
445
|
+
// Remove other services
|
|
340
446
|
this.removeFanService(accessory);
|
|
341
447
|
this.removeLockService(accessory);
|
|
342
448
|
this.removeDoorService(accessory);
|
|
@@ -346,30 +452,10 @@ export class Bot {
|
|
|
346
452
|
this.removeGarageDoorService(accessory);
|
|
347
453
|
this.removeWindowCoveringService(accessory);
|
|
348
454
|
this.removeStatefulProgrammableSwitchService(accessory);
|
|
349
|
-
|
|
350
|
-
// Add outletService
|
|
351
|
-
const outletService = `${accessory.displayName} Outlet`;
|
|
352
|
-
(this.outletService = accessory.getService(this.hap.Service.Outlet)
|
|
353
|
-
|| accessory.addService(this.hap.Service.Outlet)), outletService;
|
|
354
|
-
this.debugWarnLog(`${this.device.deviceType}: ${accessory.displayName} Displaying as Outlet`);
|
|
355
|
-
|
|
356
|
-
this.outletService.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
|
|
357
|
-
if (!this.outletService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
358
|
-
this.outletService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
359
|
-
}
|
|
360
|
-
this.outletService.getCharacteristic(this.hap.Characteristic.On).onSet(this.OnSet.bind(this));
|
|
361
455
|
}
|
|
362
456
|
|
|
363
|
-
//
|
|
364
|
-
|
|
365
|
-
(this.batteryService = this.accessory.getService(this.hap.Service.Battery)
|
|
366
|
-
|| accessory.addService(this.hap.Service.Battery)), batteryService;
|
|
367
|
-
|
|
368
|
-
this.batteryService.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
369
|
-
if (!this.batteryService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
370
|
-
this.batteryService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Battery`);
|
|
371
|
-
}
|
|
372
|
-
this.batteryService.setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
|
|
457
|
+
// Retrieve initial values and updateHomekit
|
|
458
|
+
this.refreshStatus();
|
|
373
459
|
|
|
374
460
|
// Retrieve initial values and updateHomekit
|
|
375
461
|
this.updateHomeKitCharacteristics();
|
|
@@ -381,28 +467,8 @@ export class Bot {
|
|
|
381
467
|
await this.refreshStatus();
|
|
382
468
|
});
|
|
383
469
|
|
|
384
|
-
//regisiter webhook event handler
|
|
385
|
-
|
|
386
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
|
|
387
|
-
this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
|
|
388
|
-
try {
|
|
389
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
|
|
390
|
-
const { power, battery, deviceMode } = context;
|
|
391
|
-
const { On, BatteryLevel, botMode } = this;
|
|
392
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
|
|
393
|
-
'(power, battery, deviceMode) = ' +
|
|
394
|
-
`Webhook:(${power}, ${battery}, ${deviceMode}), ` +
|
|
395
|
-
`current:(${On}, ${BatteryLevel}, ${botMode})`);
|
|
396
|
-
this.On = power;
|
|
397
|
-
this.BatteryLevel = battery;
|
|
398
|
-
this.botMode = deviceMode;
|
|
399
|
-
this.updateHomeKitCharacteristics();
|
|
400
|
-
} catch (e: any) {
|
|
401
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
402
|
-
+ `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
403
|
-
}
|
|
404
|
-
};
|
|
405
|
-
}
|
|
470
|
+
// regisiter webhook event handler
|
|
471
|
+
this.registerWebhook(accessory, device);
|
|
406
472
|
|
|
407
473
|
// Watch for Bot change events
|
|
408
474
|
// We put in a debounce of 1000ms so we don't make duplicate calls
|
|
@@ -411,7 +477,7 @@ export class Bot {
|
|
|
411
477
|
tap(() => {
|
|
412
478
|
this.botUpdateInProgress = true;
|
|
413
479
|
}),
|
|
414
|
-
debounceTime(this.
|
|
480
|
+
debounceTime(this.devicePushRate * 1000),
|
|
415
481
|
)
|
|
416
482
|
.subscribe(async () => {
|
|
417
483
|
try {
|
|
@@ -426,90 +492,90 @@ export class Bot {
|
|
|
426
492
|
}
|
|
427
493
|
} catch (e: any) {
|
|
428
494
|
this.apiError(e);
|
|
429
|
-
this.errorLog(
|
|
430
|
-
|
|
431
|
-
` Error Message: ${JSON.stringify(e.message)}`,
|
|
432
|
-
);
|
|
495
|
+
this.errorLog(`${device.deviceType}: ${accessory.displayName} failed pushChanges with ${device.connectionType} Connection,`
|
|
496
|
+
+ ` Error Message: ${JSON.stringify(e.message)}`);
|
|
433
497
|
}
|
|
434
498
|
this.botUpdateInProgress = false;
|
|
435
499
|
});
|
|
436
500
|
}
|
|
437
501
|
|
|
438
502
|
/**
|
|
439
|
-
* Parse the device status from the
|
|
503
|
+
* Parse the device status from the SwitchBotBLE API
|
|
440
504
|
*/
|
|
441
|
-
async
|
|
442
|
-
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
443
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} parseStatus enableCloudService: ${this.device.enableCloudService}`);
|
|
444
|
-
} else if (this.BLE) {
|
|
445
|
-
await this.BLEparseStatus();
|
|
446
|
-
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
447
|
-
await this.openAPIparseStatus();
|
|
448
|
-
} else {
|
|
449
|
-
await this.offlineOff();
|
|
450
|
-
this.debugWarnLog(
|
|
451
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`,
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
async BLEparseStatus(): Promise<void> {
|
|
505
|
+
async BLEparseStatus(serviceData: serviceData): Promise<void> {
|
|
457
506
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
458
507
|
// BLEmode (true if Switch Mode) | (false if Press Mode)
|
|
459
|
-
if (
|
|
460
|
-
this.accessory.context.On = this.
|
|
461
|
-
if (this.
|
|
462
|
-
this.
|
|
508
|
+
if (serviceData.mode) {
|
|
509
|
+
this.accessory.context.On = await this.getOn();
|
|
510
|
+
if (this.getOn() === undefined) {
|
|
511
|
+
this.setOn(Boolean(serviceData.state));
|
|
463
512
|
}
|
|
464
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode
|
|
513
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode,`
|
|
514
|
+
+ ` mode: ${serviceData.mode}, On: ${this.accessory.context.On}`);
|
|
465
515
|
} else {
|
|
466
|
-
this.
|
|
467
|
-
this.accessory.context.On = this.
|
|
468
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode
|
|
516
|
+
this.setOn(false);
|
|
517
|
+
this.accessory.context.On = await this.getOn();
|
|
518
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode,`
|
|
519
|
+
+ ` mode: ${serviceData.mode}, On: ${this.accessory.context.On}`);
|
|
469
520
|
}
|
|
470
521
|
|
|
471
|
-
this.BatteryLevel = Number(
|
|
472
|
-
if (this.BatteryLevel < 10) {
|
|
473
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
522
|
+
this.Battery.BatteryLevel = Number(serviceData.battery);
|
|
523
|
+
if (this.Battery.BatteryLevel < 10) {
|
|
524
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
474
525
|
} else {
|
|
475
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
526
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
476
527
|
}
|
|
477
|
-
if (Number.isNaN(this.BatteryLevel)) {
|
|
478
|
-
this.BatteryLevel = 100;
|
|
528
|
+
if (Number.isNaN(this.Battery.BatteryLevel)) {
|
|
529
|
+
this.Battery.BatteryLevel = 100;
|
|
479
530
|
}
|
|
480
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
|
|
481
|
-
+ ` StatusLowBattery: ${this.StatusLowBattery}`);
|
|
531
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
|
|
532
|
+
+ ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
482
533
|
}
|
|
483
534
|
|
|
484
|
-
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Parse the device status from the SwitchBot OpenAPI
|
|
538
|
+
*/
|
|
539
|
+
async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
|
|
485
540
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
486
541
|
if (this.botMode === 'press') {
|
|
487
|
-
this.
|
|
488
|
-
this.accessory.context.On = this.
|
|
542
|
+
this.setOn(false);
|
|
543
|
+
this.accessory.context.On = await this.getOn();
|
|
489
544
|
} else {
|
|
490
|
-
this.accessory.context.On = this.
|
|
491
|
-
if (this.
|
|
492
|
-
this.
|
|
545
|
+
this.accessory.context.On = await this.getOn();
|
|
546
|
+
if (this.getOn() === undefined) {
|
|
547
|
+
this.setOn(false);
|
|
493
548
|
}
|
|
494
549
|
}
|
|
495
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
550
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.accessory.context.On}`);
|
|
496
551
|
|
|
497
552
|
// Battery
|
|
498
|
-
this.BatteryLevel = Number(
|
|
499
|
-
if (this.BatteryLevel < 10) {
|
|
500
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
553
|
+
this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
|
|
554
|
+
if (this.Battery.BatteryLevel < 10) {
|
|
555
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
501
556
|
} else {
|
|
502
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
557
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
558
|
+
}
|
|
559
|
+
if (Number.isNaN(this.Battery.BatteryLevel)) {
|
|
560
|
+
this.Battery.BatteryLevel = 100;
|
|
561
|
+
}
|
|
562
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
|
|
563
|
+
+ ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
564
|
+
|
|
565
|
+
// Firmware Version
|
|
566
|
+
const version = deviceStatus.body.version?.toString();
|
|
567
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
|
|
568
|
+
if (deviceStatus.body.version) {
|
|
569
|
+
const deviceVersion = version?.replace(/^V|-.*$/g, '') ?? '0.0.0';
|
|
570
|
+
this.accessory
|
|
571
|
+
.getService(this.hap.Service.AccessoryInformation)!
|
|
572
|
+
.setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
|
|
573
|
+
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
|
|
574
|
+
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
575
|
+
.updateValue(deviceVersion);
|
|
576
|
+
this.accessory.context.deviceVersion = deviceVersion;
|
|
577
|
+
this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceVersion: ${this.accessory.context.deviceVersion}`);
|
|
503
578
|
}
|
|
504
|
-
if (Number.isNaN(this.BatteryLevel)) {
|
|
505
|
-
this.BatteryLevel = 100;
|
|
506
|
-
}
|
|
507
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
|
|
508
|
-
+ ` StatusLowBattery: ${this.StatusLowBattery}`);
|
|
509
|
-
|
|
510
|
-
// FirmwareRevision
|
|
511
|
-
this.FirmwareRevision = this.OpenAPI_FirmwareRevision!;
|
|
512
|
-
this.accessory.context.FirmwareRevision = this.FirmwareRevision;
|
|
513
579
|
}
|
|
514
580
|
|
|
515
581
|
/**
|
|
@@ -524,130 +590,76 @@ export class Bot {
|
|
|
524
590
|
await this.openAPIRefreshStatus();
|
|
525
591
|
} else {
|
|
526
592
|
await this.offlineOff();
|
|
527
|
-
this.debugWarnLog(
|
|
528
|
-
|
|
529
|
-
` ${this.device.connectionType}, refreshStatus will not happen.`,
|
|
530
|
-
);
|
|
593
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
594
|
+
+ ` ${this.device.connectionType}, refreshStatus will not happen.`);
|
|
531
595
|
}
|
|
532
596
|
}
|
|
533
597
|
|
|
534
598
|
async BLERefreshStatus(): Promise<void> {
|
|
535
599
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
|
|
536
|
-
const switchbot = await this.
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
.
|
|
540
|
-
|
|
541
|
-
.toLowerCase();
|
|
542
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
543
|
-
this.getCustomBLEAddress(switchbot);
|
|
600
|
+
const switchbot = await this.switchbotBLE();
|
|
601
|
+
|
|
602
|
+
if (switchbot === undefined) {
|
|
603
|
+
await this.BLERefreshConnection(switchbot);
|
|
604
|
+
} else {
|
|
544
605
|
// Start to monitor advertisement packets
|
|
545
|
-
|
|
606
|
+
(async () => {
|
|
546
607
|
// Start to monitor advertisement packets
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
switchbot.onadvertisement = (ad: any) => {
|
|
553
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
|
|
554
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
|
|
555
|
-
if (this.device.bleMac === ad.address && ad.model === 'H') {
|
|
556
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
557
|
-
this.BLE_Mode = ad.serviceData.mode;
|
|
558
|
-
this.BLE_On = ad.serviceData.state;
|
|
559
|
-
this.BLE_BatteryLevel = ad.serviceData.battery;
|
|
608
|
+
const serviceData: serviceData = await this.monitorAdvertisementPackets(switchbot);
|
|
609
|
+
// Update HomeKit
|
|
610
|
+
if (serviceData.model !== '' && serviceData.modelName !== '') {
|
|
611
|
+
await this.BLEparseStatus(serviceData);
|
|
612
|
+
await this.updateHomeKitCharacteristics();
|
|
560
613
|
} else {
|
|
561
|
-
this.
|
|
562
|
-
}
|
|
563
|
-
};
|
|
564
|
-
// Wait 1 seconds
|
|
565
|
-
await switchbot.wait(this.scanDuration * 1000);
|
|
566
|
-
// Stop to monitor
|
|
567
|
-
await switchbot.stopScan();
|
|
568
|
-
// Update HomeKit
|
|
569
|
-
await this.BLEparseStatus();
|
|
570
|
-
await this.updateHomeKitCharacteristics();
|
|
571
|
-
})();
|
|
572
|
-
/*if (switchbot !== false) {
|
|
573
|
-
switchbot
|
|
574
|
-
.startScan({
|
|
575
|
-
model: 'H',
|
|
576
|
-
id: this.device.bleMac,
|
|
577
|
-
})
|
|
578
|
-
.then(async () => {
|
|
579
|
-
// Set an event handler
|
|
580
|
-
switchbot.onadvertisement = async (ad: ad) => {
|
|
581
|
-
this.debugLog(
|
|
582
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
|
|
583
|
-
` BLE Address Found: ${ad.address}`,
|
|
584
|
-
);
|
|
585
|
-
this.BLE_Mode = ad.serviceData.mode;
|
|
586
|
-
this.BLE_On = ad.serviceData.state;
|
|
587
|
-
this.BLE_BatteryLevel = ad.serviceData.battery;
|
|
588
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
589
|
-
this.debugLog(
|
|
590
|
-
`${this.device.deviceType}: ${this.accessory.displayName}, model: ${ad.serviceData.model}, modelName: ` +
|
|
591
|
-
`${ad.serviceData.modelName}, mode: ${ad.serviceData.mode}, state: ${ad.serviceData.state}, battery: ${ad.serviceData.battery}`,
|
|
592
|
-
);
|
|
593
|
-
|
|
594
|
-
if (ad.serviceData) {
|
|
595
|
-
this.BLE_IsConnected = true;
|
|
596
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
|
|
597
|
-
await this.stopScanning(switchbot);
|
|
598
|
-
} else {
|
|
599
|
-
this.BLE_IsConnected = false;
|
|
600
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
|
|
601
|
-
}
|
|
602
|
-
};
|
|
603
|
-
// Wait
|
|
604
|
-
return await sleep(this.scanDuration * 1000);
|
|
605
|
-
})
|
|
606
|
-
.then(async () => {
|
|
607
|
-
// Stop to monitor
|
|
608
|
-
await this.stopScanning(switchbot);
|
|
609
|
-
})
|
|
610
|
-
.catch(async (e: any) => {
|
|
611
|
-
this.apiError(e);
|
|
612
|
-
this.errorLog(
|
|
613
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
|
|
614
|
-
` Connection, Error Message: ${JSON.stringify(e.message)}`,
|
|
615
|
-
);
|
|
614
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed to get serviceData, serviceData: ${serviceData}`);
|
|
616
615
|
await this.BLERefreshConnection(switchbot);
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
}*/
|
|
616
|
+
}
|
|
617
|
+
})();
|
|
618
|
+
}
|
|
621
619
|
}
|
|
622
620
|
|
|
623
621
|
async openAPIRefreshStatus(): Promise<void> {
|
|
624
622
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
625
623
|
try {
|
|
626
|
-
const { body, statusCode } = await
|
|
627
|
-
headers: this.platform.generateHeaders(),
|
|
628
|
-
});
|
|
629
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
|
|
624
|
+
const { body, statusCode } = await this.deviceRefreshStatus();
|
|
630
625
|
const deviceStatus: any = await body.json();
|
|
631
|
-
this.
|
|
632
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
|
|
626
|
+
await this.refreshStatusCodes(statusCode, deviceStatus);;
|
|
633
627
|
if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
|
|
634
|
-
this.
|
|
635
|
-
|
|
636
|
-
this.
|
|
637
|
-
this.OpenAPI_BatteryLevel = deviceStatus.body.battery;
|
|
638
|
-
this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
|
|
639
|
-
this.openAPIparseStatus();
|
|
640
|
-
this.updateHomeKitCharacteristics();
|
|
628
|
+
await this.successfulRefreshStatus(statusCode, deviceStatus);
|
|
629
|
+
await this.openAPIparseStatus(deviceStatus);
|
|
630
|
+
await this.updateHomeKitCharacteristics();
|
|
641
631
|
} else {
|
|
642
|
-
this.
|
|
643
|
-
this.statusCode(deviceStatus.statusCode);
|
|
632
|
+
await this.statusCodes(statusCode, deviceStatus);
|
|
644
633
|
}
|
|
645
634
|
} catch (e: any) {
|
|
646
635
|
this.apiError(e);
|
|
647
|
-
this.errorLog(
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
636
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}`
|
|
637
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
async registerWebhook(accessory: PlatformAccessory, device: device & devicesConfig) {
|
|
642
|
+
if (device.webhook) {
|
|
643
|
+
this.debugLog(`${device.deviceType}: ${accessory.displayName} is listening webhook.`);
|
|
644
|
+
this.platform.webhookEventHandler[device.deviceId] = async (context) => {
|
|
645
|
+
try {
|
|
646
|
+
this.debugLog(`${device.deviceType}: ${accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
|
|
647
|
+
const { power, battery, deviceMode } = context;
|
|
648
|
+
const { botMode } = this;
|
|
649
|
+
const On = await this.getOn();
|
|
650
|
+
const { BatteryLevel } = this.Battery;
|
|
651
|
+
this.debugLog(`${device.deviceType}: ${accessory.displayName} (power, battery, deviceMode) = Webhook:(${power}, ${battery}, ${deviceMode}),`
|
|
652
|
+
+ ` current:(${On}, ${BatteryLevel}, ${botMode})`);
|
|
653
|
+
await this.setOn(power);
|
|
654
|
+
this.Battery.BatteryLevel = battery;
|
|
655
|
+
this.botMode = deviceMode;
|
|
656
|
+
this.updateHomeKitCharacteristics();
|
|
657
|
+
} catch (e: any) {
|
|
658
|
+
this.errorLog(`${device.deviceType}: ${accessory.displayName} failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
} else {
|
|
662
|
+
this.debugLog(`${device.deviceType}: ${accessory.displayName} is not listening webhook.`);
|
|
651
663
|
}
|
|
652
664
|
}
|
|
653
665
|
|
|
@@ -663,13 +675,12 @@ export class Bot {
|
|
|
663
675
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
|
|
664
676
|
} else if (this.BLE) {
|
|
665
677
|
await this.BLEpushChanges();
|
|
666
|
-
} else if (this.OpenAPI) {
|
|
678
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
667
679
|
await this.openAPIpushChanges();
|
|
668
680
|
} else {
|
|
669
681
|
await this.offlineOff();
|
|
670
|
-
this.debugWarnLog(
|
|
671
|
-
|
|
672
|
-
);
|
|
682
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:`
|
|
683
|
+
+ ` ${this.device.connectionType}, pushChanges will not happen.`);
|
|
673
684
|
}
|
|
674
685
|
// Refresh the status from the API
|
|
675
686
|
interval(15000)
|
|
@@ -682,54 +693,51 @@ export class Bot {
|
|
|
682
693
|
|
|
683
694
|
async BLEpushChanges(): Promise<void> {
|
|
684
695
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
685
|
-
|
|
686
|
-
|
|
696
|
+
const On = await this.getOn();
|
|
697
|
+
if (On !== this.accessory.context.On || this.allowPush) {
|
|
698
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges On: ${On} OnCached: ${this.accessory.context.On}`);
|
|
687
699
|
const switchbot = await this.platform.connectBLE();
|
|
688
700
|
// Convert to BLE Address
|
|
689
|
-
|
|
690
|
-
.deviceId!.match(/.{1,2}/g)!
|
|
691
|
-
.join(':')
|
|
692
|
-
.toLowerCase();
|
|
693
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
701
|
+
await this.convertBLEAddress();
|
|
694
702
|
//if (switchbot !== false) {
|
|
695
703
|
if (this.botMode === 'press') {
|
|
696
704
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
|
|
697
705
|
switchbot
|
|
698
706
|
.discover({ model: 'H', quick: true, id: this.device.bleMac })
|
|
699
707
|
.then(async (device_list: { press: (arg0: { id: string | undefined }) => any }[]) => {
|
|
700
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${
|
|
708
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${On}`);
|
|
701
709
|
return await device_list[0].press({ id: this.device.bleMac });
|
|
702
710
|
})
|
|
703
711
|
.then(() => {
|
|
704
712
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
705
|
-
this.
|
|
713
|
+
this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
714
|
+
+ `On: ${On} sent over BLE, sent successfully`);
|
|
715
|
+
this.accessory.context.On = On;
|
|
706
716
|
setTimeout(() => {
|
|
707
717
|
if (this.botDeviceType === 'switch') {
|
|
708
|
-
this.
|
|
718
|
+
this.Switch?.Service.getCharacteristic(this.hap.Characteristic.On).updateValue(On);
|
|
709
719
|
} else {
|
|
710
|
-
this.
|
|
720
|
+
this.Outlet?.Service.getCharacteristic(this.hap.Characteristic.On).updateValue(On);
|
|
711
721
|
}
|
|
712
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${
|
|
722
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${On}, Switch Timeout`);
|
|
713
723
|
}, 500);
|
|
714
724
|
})
|
|
715
725
|
.catch(async (e: any) => {
|
|
716
726
|
this.apiError(e);
|
|
717
|
-
this.errorLog(
|
|
718
|
-
|
|
719
|
-
` Connection & botMode: ${this.botMode}, Error Message: ${JSON.stringify(e.message)}`,
|
|
720
|
-
);
|
|
727
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
728
|
+
+ ` Connection & botMode: ${this.botMode}, Error Message: ${JSON.stringify(e.message)}`);
|
|
721
729
|
await this.BLEPushConnection();
|
|
722
730
|
});
|
|
723
731
|
} else if (this.botMode === 'switch') {
|
|
724
732
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode: ${this.botMode}`);
|
|
725
733
|
switchbot
|
|
726
|
-
.discover({ model:
|
|
734
|
+
.discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
|
|
727
735
|
.then(async (device_list: any) => {
|
|
728
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${
|
|
729
|
-
return await this.
|
|
730
|
-
max: this.
|
|
736
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${On}`);
|
|
737
|
+
return await this.retryBLE({
|
|
738
|
+
max: await this.maxRetryBLE(),
|
|
731
739
|
fn: async () => {
|
|
732
|
-
if (
|
|
740
|
+
if (On) {
|
|
733
741
|
return await device_list[0].turnOn({ id: this.device.bleMac });
|
|
734
742
|
} else {
|
|
735
743
|
return await device_list[0].turnOff({ id: this.device.bleMac });
|
|
@@ -739,46 +747,43 @@ export class Bot {
|
|
|
739
747
|
})
|
|
740
748
|
.then(() => {
|
|
741
749
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
742
|
-
this.accessory.context.On =
|
|
750
|
+
this.accessory.context.On = On;
|
|
743
751
|
})
|
|
744
752
|
.catch(async (e: any) => {
|
|
745
753
|
this.apiError(e);
|
|
746
|
-
this.errorLog(
|
|
747
|
-
|
|
748
|
-
` Connection & botMode: ${this.botMode}, Error Message: ${JSON.stringify(e.message)}`,
|
|
749
|
-
);
|
|
754
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}`
|
|
755
|
+
+ ` Connection & botMode: ${this.botMode}, Error Message: ${JSON.stringify(e.message)}`);
|
|
750
756
|
await this.BLEPushConnection();
|
|
751
757
|
});
|
|
752
758
|
} else {
|
|
753
759
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
|
|
754
760
|
}
|
|
755
761
|
} else {
|
|
756
|
-
this.debugLog(
|
|
757
|
-
`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges.` + `On: ${this.On}, ` + `OnCached: ${this.accessory.context.On}`,
|
|
758
|
-
);
|
|
762
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, On: ${On}, OnCached: ${this.accessory.context.On}`);
|
|
759
763
|
}
|
|
760
764
|
}
|
|
761
765
|
|
|
762
766
|
async openAPIpushChanges(): Promise<void> {
|
|
763
767
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
768
|
+
let On = await this.getOn();
|
|
764
769
|
if (this.multiPressCount > 0) {
|
|
765
770
|
this.debugLog(`${this.device.deviceType}: ${this.multiPressCount} request(s) queued.`);
|
|
766
|
-
|
|
771
|
+
On = true;
|
|
767
772
|
}
|
|
768
|
-
if (
|
|
773
|
+
if (On !== this.accessory.context.On || this.allowPush || this.multiPressCount > 0) {
|
|
769
774
|
let command = '';
|
|
770
|
-
if (this.botMode === 'switch' &&
|
|
775
|
+
if (this.botMode === 'switch' && On) {
|
|
771
776
|
command = 'turnOn';
|
|
772
|
-
|
|
773
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${
|
|
774
|
-
} else if (this.botMode === 'switch' && !
|
|
777
|
+
On = true;
|
|
778
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${On}`);
|
|
779
|
+
} else if (this.botMode === 'switch' && !On) {
|
|
775
780
|
command = 'turnOff';
|
|
776
|
-
|
|
777
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${
|
|
781
|
+
On = false;
|
|
782
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Switch Mode, Turning ${On}`);
|
|
778
783
|
} else if (this.botMode === 'press' || this.botMode === 'multipress') {
|
|
779
784
|
command = 'press';
|
|
780
785
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Press Mode`);
|
|
781
|
-
|
|
786
|
+
On = false;
|
|
782
787
|
} else {
|
|
783
788
|
throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Device Parameters not set for this Bot.`);
|
|
784
789
|
}
|
|
@@ -789,44 +794,32 @@ export class Bot {
|
|
|
789
794
|
});
|
|
790
795
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
|
|
791
796
|
try {
|
|
792
|
-
const { body, statusCode } = await
|
|
793
|
-
body: bodyChange,
|
|
794
|
-
method: 'POST',
|
|
795
|
-
headers: this.platform.generateHeaders(),
|
|
796
|
-
});
|
|
797
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
|
|
797
|
+
const { body, statusCode } = await this.pushChangeRequest(bodyChange);
|
|
798
798
|
const deviceStatus: any = await body.json();
|
|
799
|
-
this.
|
|
800
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
|
|
801
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
|
|
799
|
+
await this.pushStatusCodes(statusCode, deviceStatus);
|
|
802
800
|
if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
|
|
803
|
-
this.
|
|
804
|
-
|
|
801
|
+
await this.successfulPushChange(statusCode, deviceStatus, bodyChange);
|
|
802
|
+
await this.updateHomeKitCharacteristics();
|
|
805
803
|
} else {
|
|
806
|
-
this.statusCode(statusCode);
|
|
807
|
-
this.statusCode(deviceStatus.statusCode);
|
|
804
|
+
await this.statusCode(statusCode);
|
|
805
|
+
await this.statusCode(deviceStatus.statusCode);
|
|
808
806
|
}
|
|
809
807
|
if (this.device.bot?.mode === 'multipress') {
|
|
810
808
|
this.multiPressCount--;
|
|
811
809
|
if (this.multiPressCount > 0) {
|
|
812
810
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Multi Press Count: ${this.multiPressCount}`);
|
|
813
|
-
|
|
811
|
+
On = true;
|
|
814
812
|
this.openAPIpushChanges();
|
|
815
813
|
}
|
|
816
814
|
}
|
|
817
815
|
} catch (e: any) {
|
|
818
816
|
this.apiError(e);
|
|
819
|
-
this.errorLog(
|
|
820
|
-
|
|
821
|
-
` Connection, Error Message: ${JSON.stringify(e.message)}`,
|
|
822
|
-
);
|
|
817
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
|
|
818
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
823
819
|
}
|
|
824
820
|
} else {
|
|
825
|
-
this.debugLog(
|
|
826
|
-
|
|
827
|
-
`On: ${this.On}, ` +
|
|
828
|
-
`OnCached: ${this.accessory.context.On}`,
|
|
829
|
-
);
|
|
821
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges,`
|
|
822
|
+
+ ` On: ${On}, OnCached: ${this.accessory.context.On}`);
|
|
830
823
|
}
|
|
831
824
|
}
|
|
832
825
|
|
|
@@ -835,53 +828,105 @@ export class Bot {
|
|
|
835
828
|
*/
|
|
836
829
|
async OnSet(value: CharacteristicValue): Promise<void> {
|
|
837
830
|
if (this.botDeviceType === 'garagedoor') {
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
this.
|
|
841
|
-
|
|
842
|
-
|
|
831
|
+
if (this.GarageDoor) {
|
|
832
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetDoorState: ${value}`);
|
|
833
|
+
if (value === this.hap.Characteristic.TargetDoorState.CLOSED) {
|
|
834
|
+
await this.setOn(false);
|
|
835
|
+
this.GarageDoor.On = false;
|
|
836
|
+
} else {
|
|
837
|
+
await this.setOn(true);
|
|
838
|
+
this.GarageDoor.On = true;
|
|
839
|
+
}
|
|
843
840
|
}
|
|
844
|
-
} else if (
|
|
845
|
-
this.
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
841
|
+
} else if (this.botDeviceType === 'door') {
|
|
842
|
+
if (this.Door) {
|
|
843
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
|
|
844
|
+
if (value === 0) {
|
|
845
|
+
await this.setOn(false);
|
|
846
|
+
this.Door.On = false;
|
|
847
|
+
} else {
|
|
848
|
+
await this.setOn(true);
|
|
849
|
+
this.Door.On = true;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
} else if (this.botDeviceType === 'window') {
|
|
853
|
+
if (this.Window) {
|
|
854
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
|
|
855
|
+
if (value === 0) {
|
|
856
|
+
await this.setOn(false);
|
|
857
|
+
this.Window.On = false;
|
|
858
|
+
} else {
|
|
859
|
+
await this.setOn(true);
|
|
860
|
+
this.Window.On = true;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
} else if (this.botDeviceType === 'windowcovering') {
|
|
864
|
+
if (this.WindowCovering) {
|
|
865
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
|
|
866
|
+
if (value === 0) {
|
|
867
|
+
await this.setOn(false);
|
|
868
|
+
this.WindowCovering.On = false;
|
|
869
|
+
} else {
|
|
870
|
+
await this.setOn(true);
|
|
871
|
+
this.WindowCovering.On = true;
|
|
872
|
+
}
|
|
854
873
|
}
|
|
855
874
|
} else if (this.botDeviceType === 'lock') {
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
this.
|
|
859
|
-
|
|
860
|
-
|
|
875
|
+
if (this.LockMechanism) {
|
|
876
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set LockTargetState: ${value}`);
|
|
877
|
+
if (value === this.hap.Characteristic.LockTargetState.SECURED) {
|
|
878
|
+
await this.setOn(false);
|
|
879
|
+
this.LockMechanism.On = false;
|
|
880
|
+
} else {
|
|
881
|
+
await this.setOn(true);
|
|
882
|
+
this.LockMechanism.On = true;
|
|
883
|
+
}
|
|
861
884
|
}
|
|
862
885
|
} else if (this.botDeviceType === 'faucet') {
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
this.
|
|
866
|
-
|
|
867
|
-
|
|
886
|
+
if (this.Faucet) {
|
|
887
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Active: ${value}`);
|
|
888
|
+
if (value === this.hap.Characteristic.Active.INACTIVE) {
|
|
889
|
+
await this.setOn(false);
|
|
890
|
+
this.Faucet.On = false;
|
|
891
|
+
} else {
|
|
892
|
+
await this.setOn(true);
|
|
893
|
+
this.Faucet.On = true;
|
|
894
|
+
}
|
|
868
895
|
}
|
|
869
896
|
} else if (this.botDeviceType === 'stateful') {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
897
|
+
if (this.StatefulProgrammableSwitch) {
|
|
898
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ProgrammableSwitchOutputState: ${value}`);
|
|
899
|
+
if (value === 0) {
|
|
900
|
+
await this.setOn(false);
|
|
901
|
+
this.StatefulProgrammableSwitch.On = false;
|
|
902
|
+
} else {
|
|
903
|
+
await this.setOn(true);
|
|
904
|
+
this.StatefulProgrammableSwitch.On = true;
|
|
905
|
+
}
|
|
875
906
|
}
|
|
876
|
-
} else {
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
if (value ===
|
|
880
|
-
this.
|
|
881
|
-
this.
|
|
907
|
+
} else if (this.botDeviceType === 'switch') {
|
|
908
|
+
if (this.Switch) {
|
|
909
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set ProgrammableSwitchOutputState: ${value}`);
|
|
910
|
+
if (value === 0) {
|
|
911
|
+
await this.setOn(false);
|
|
912
|
+
this.Switch.On = false;
|
|
913
|
+
} else {
|
|
914
|
+
await this.setOn(true);
|
|
915
|
+
this.Switch.On = true;
|
|
882
916
|
}
|
|
883
917
|
}
|
|
884
|
-
|
|
918
|
+
} else {
|
|
919
|
+
if (this.Outlet) {
|
|
920
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set On: ${value}`);
|
|
921
|
+
await this.setOn(Boolean(value));
|
|
922
|
+
this.Outlet.On = value;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
if (this.device.bot?.mode === 'multipress') {
|
|
926
|
+
if (value === true) {
|
|
927
|
+
this.multiPressCount++;
|
|
928
|
+
this.debugLog(`${this.device.deviceType} set to Multi-Press. Multi-Press count: ${this.multiPressCount}`);
|
|
929
|
+
}
|
|
885
930
|
}
|
|
886
931
|
this.doBotUpdate.next();
|
|
887
932
|
}
|
|
@@ -892,536 +937,352 @@ export class Bot {
|
|
|
892
937
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
893
938
|
// State
|
|
894
939
|
if (this.botDeviceType === 'garagedoor') {
|
|
895
|
-
if (this.On === undefined) {
|
|
896
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
940
|
+
if (this.GarageDoor?.On === undefined) {
|
|
941
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.GarageDoor?.On}`);
|
|
897
942
|
} else {
|
|
898
|
-
if (this.On) {
|
|
899
|
-
this.
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
this.garageDoorService?.updateCharacteristic(
|
|
904
|
-
this.hap.Characteristic.CurrentDoorState,
|
|
905
|
-
this.hap.Characteristic.CurrentDoorState.OPEN,
|
|
906
|
-
);
|
|
907
|
-
this.debugLog(
|
|
908
|
-
`${this.device.deviceType}: ` + `${this.accessory.displayName} updateCharacteristic TargetDoorState: Open, CurrentDoorState: Open`,
|
|
909
|
-
);
|
|
943
|
+
if (this.GarageDoor.On) {
|
|
944
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.OPEN);
|
|
945
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.OPEN);
|
|
946
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
947
|
+
+ ` TargetDoorState: Open, CurrentDoorState: Open (${this.GarageDoor.On})`);
|
|
910
948
|
} else {
|
|
911
|
-
this.
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
this.garageDoorService?.updateCharacteristic(
|
|
916
|
-
this.hap.Characteristic.CurrentDoorState,
|
|
917
|
-
this.hap.Characteristic.CurrentDoorState.CLOSED,
|
|
918
|
-
);
|
|
919
|
-
this.debugLog(
|
|
920
|
-
`${this.device.deviceType}: ` + `${this.accessory.displayName} updateCharacteristic TargetDoorState: Open, CurrentDoorState: Open`,
|
|
921
|
-
);
|
|
949
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.CLOSED);
|
|
950
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.CLOSED);
|
|
951
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
|
|
952
|
+
+ ` TargetDoorState: Open, CurrentDoorState: Open (${this.GarageDoor.On})`);
|
|
922
953
|
}
|
|
923
954
|
}
|
|
924
|
-
this.
|
|
955
|
+
await this.setOn(Boolean(this.GarageDoor?.On));
|
|
956
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Garage Door On: ${this.GarageDoor?.On}`);
|
|
925
957
|
} else if (this.botDeviceType === 'door') {
|
|
926
|
-
if (this.On === undefined) {
|
|
927
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
958
|
+
if (this.Door?.On === undefined) {
|
|
959
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Door?.On}`);
|
|
928
960
|
} else {
|
|
929
|
-
if (this.On) {
|
|
930
|
-
this.
|
|
931
|
-
this.
|
|
932
|
-
this.
|
|
933
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
961
|
+
if (this.Door.On) {
|
|
962
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
|
|
963
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
|
|
964
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
965
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
|
|
966
|
+
+ ` TargetPosition: 100, CurrentPosition: 100 (${this.Door.On})`);
|
|
934
967
|
} else {
|
|
935
|
-
this.
|
|
936
|
-
this.
|
|
937
|
-
this.
|
|
938
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
968
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
|
|
969
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
|
|
970
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
971
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
|
|
972
|
+
+ ` TargetPosition: 0, CurrentPosition: 0 (${this.Door.On})`);
|
|
939
973
|
}
|
|
940
974
|
}
|
|
941
|
-
this.
|
|
975
|
+
await this.setOn(Boolean(this.Door?.On));
|
|
976
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Door On: ${this.Door?.On}`);
|
|
942
977
|
} else if (this.botDeviceType === 'window') {
|
|
943
|
-
if (this.On === undefined) {
|
|
944
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
978
|
+
if (this.Window?.On === undefined) {
|
|
979
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Window?.On}`);
|
|
945
980
|
} else {
|
|
946
|
-
if (this.On) {
|
|
947
|
-
this.
|
|
948
|
-
this.
|
|
949
|
-
this.
|
|
950
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
981
|
+
if (this.Window.On) {
|
|
982
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
|
|
983
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
|
|
984
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
985
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
|
|
986
|
+
+ ` TargetPosition: 100, CurrentPosition: 100 (${this.Window.On})`);
|
|
951
987
|
} else {
|
|
952
|
-
this.
|
|
953
|
-
this.
|
|
954
|
-
this.
|
|
955
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
988
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
|
|
989
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
|
|
990
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
991
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
|
|
992
|
+
+ ` TargetPosition: 0, CurrentPosition: 0 (${this.Window.On})`);
|
|
956
993
|
}
|
|
957
994
|
}
|
|
958
|
-
this.
|
|
995
|
+
await this.setOn(Boolean(this.Window?.On));
|
|
996
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Window On: ${this.Window?.On}`);
|
|
959
997
|
} else if (this.botDeviceType === 'windowcovering') {
|
|
960
|
-
if (this.On === undefined) {
|
|
961
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
998
|
+
if (this.WindowCovering?.On === undefined) {
|
|
999
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.WindowCovering?.On}`);
|
|
962
1000
|
} else {
|
|
963
|
-
if (this.On) {
|
|
964
|
-
this.
|
|
965
|
-
this.
|
|
966
|
-
this.
|
|
967
|
-
|
|
968
|
-
this.
|
|
969
|
-
);
|
|
970
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 100, CurrentPosition: 100`);
|
|
1001
|
+
if (this.WindowCovering.On) {
|
|
1002
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
|
|
1003
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
|
|
1004
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
1005
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
|
|
1006
|
+
+ ` TargetPosition: 100, CurrentPosition: 100 (${this.WindowCovering.On})`);
|
|
971
1007
|
} else {
|
|
972
|
-
this.
|
|
973
|
-
this.
|
|
974
|
-
this.
|
|
975
|
-
|
|
976
|
-
this.
|
|
977
|
-
);
|
|
978
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic TargetPosition: 0, CurrentPosition: 0`);
|
|
1008
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
|
|
1009
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
|
|
1010
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
1011
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
|
|
1012
|
+
+ ` TargetPosition: 0, CurrentPosition: 0 (${this.WindowCovering.On})`);
|
|
979
1013
|
}
|
|
980
1014
|
}
|
|
981
|
-
this.
|
|
1015
|
+
await this.setOn(Boolean(this.WindowCovering?.On));
|
|
1016
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Window Covering On: ${this.WindowCovering?.On}`);
|
|
982
1017
|
} else if (this.botDeviceType === 'lock') {
|
|
983
|
-
if (this.On === undefined) {
|
|
984
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
1018
|
+
if (this.LockMechanism?.On === undefined) {
|
|
1019
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.LockMechanism?.On}`);
|
|
985
1020
|
} else {
|
|
986
|
-
if (this.On) {
|
|
987
|
-
this.
|
|
988
|
-
this.hap.Characteristic.LockTargetState
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
this.
|
|
992
|
-
this.
|
|
993
|
-
this.hap.Characteristic.LockCurrentState.UNSECURED,
|
|
994
|
-
);
|
|
995
|
-
this.debugLog(
|
|
996
|
-
`${this.device.deviceType}: ` +
|
|
997
|
-
`${this.accessory.displayName} updateCharacteristic LockTargetState: UNSECURED, LockCurrentState: UNSECURED`,
|
|
998
|
-
);
|
|
1021
|
+
if (this.LockMechanism.On) {
|
|
1022
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState,
|
|
1023
|
+
this.hap.Characteristic.LockTargetState.UNSECURED);
|
|
1024
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState,
|
|
1025
|
+
this.hap.Characteristic.LockCurrentState.UNSECURED);
|
|
1026
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristicc`
|
|
1027
|
+
+ ` LockTargetState: UNSECURED, LockCurrentState: UNSECURED (${this.LockMechanism.On})`);
|
|
999
1028
|
} else {
|
|
1000
|
-
this.
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
this.hap.Characteristic.LockCurrentState.SECURED
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
`${this.device.deviceType}: ` + `${this.accessory.displayName} updateCharacteristic LockTargetState: SECURED, LockCurrentState: SECURED`,
|
|
1007
|
-
);
|
|
1029
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState,
|
|
1030
|
+
this.hap.Characteristic.LockTargetState.SECURED);
|
|
1031
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState,
|
|
1032
|
+
this.hap.Characteristic.LockCurrentState.SECURED);
|
|
1033
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
1034
|
+
+ ` LockTargetState: SECURED, LockCurrentState: SECURED (${this.LockMechanism.On})`);
|
|
1008
1035
|
}
|
|
1009
1036
|
}
|
|
1010
|
-
this.
|
|
1037
|
+
await this.setOn(Boolean(this.LockMechanism?.On));
|
|
1038
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Lock On: ${this.LockMechanism?.On}`);
|
|
1011
1039
|
} else if (this.botDeviceType === 'faucet') {
|
|
1012
|
-
if (this.On === undefined) {
|
|
1013
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
1040
|
+
if (this.Faucet?.On === undefined) {
|
|
1041
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Faucet?.On}`);
|
|
1014
1042
|
} else {
|
|
1015
|
-
if (this.On) {
|
|
1016
|
-
this.
|
|
1017
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.On}`);
|
|
1043
|
+
if (this.Faucet.On) {
|
|
1044
|
+
this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.ACTIVE);
|
|
1045
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.Faucet.On}`);
|
|
1018
1046
|
} else {
|
|
1019
|
-
this.
|
|
1020
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.On}`);
|
|
1047
|
+
this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.INACTIVE);
|
|
1048
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.Faucet.On}`);
|
|
1021
1049
|
}
|
|
1022
1050
|
}
|
|
1023
|
-
this.
|
|
1051
|
+
await this.setOn(Boolean(this.Faucet?.On));
|
|
1052
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Faucet On: ${this.Faucet?.On}`);
|
|
1024
1053
|
} else if (this.botDeviceType === 'fan') {
|
|
1025
|
-
if (this.On === undefined) {
|
|
1026
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
1054
|
+
if (this.Fan?.On === undefined) {
|
|
1055
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Fan?.On}`);
|
|
1027
1056
|
} else {
|
|
1028
|
-
if (this.On) {
|
|
1029
|
-
this.
|
|
1030
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
1057
|
+
if (this.Fan.On) {
|
|
1058
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, this.Fan.On);
|
|
1059
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.Fan.On}`);
|
|
1031
1060
|
} else {
|
|
1032
|
-
this.
|
|
1033
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
1061
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, this.Fan.On);
|
|
1062
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.Fan.On}`);
|
|
1034
1063
|
}
|
|
1035
1064
|
}
|
|
1036
|
-
this.
|
|
1065
|
+
await this.setOn(Boolean(this.Fan?.On));
|
|
1066
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Fan On: ${this.Fan?.On}`);
|
|
1037
1067
|
} else if (this.botDeviceType === 'stateful') {
|
|
1038
|
-
if (this.On === undefined) {
|
|
1039
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
1068
|
+
if (this.StatefulProgrammableSwitch?.On === undefined) {
|
|
1069
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.StatefulProgrammableSwitch?.On}`);
|
|
1040
1070
|
} else {
|
|
1041
|
-
if (this.On) {
|
|
1042
|
-
this.
|
|
1043
|
-
this.hap.Characteristic.ProgrammableSwitchEvent
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
this.debugLog(
|
|
1048
|
-
`${this.device.deviceType}: ` +
|
|
1049
|
-
`${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 1`,
|
|
1050
|
-
);
|
|
1071
|
+
if (this.StatefulProgrammableSwitch.On) {
|
|
1072
|
+
this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent,
|
|
1073
|
+
this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
|
|
1074
|
+
this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 1);
|
|
1075
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
1076
|
+
+ ` ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 1 (${this.StatefulProgrammableSwitch.On})`);
|
|
1051
1077
|
} else {
|
|
1052
|
-
this.
|
|
1053
|
-
this.hap.Characteristic.ProgrammableSwitchEvent
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
this.debugLog(
|
|
1058
|
-
`${this.device.deviceType}: ` +
|
|
1059
|
-
`${this.accessory.displayName} updateCharacteristic ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 0`,
|
|
1060
|
-
);
|
|
1078
|
+
this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent,
|
|
1079
|
+
this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
|
|
1080
|
+
this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 0);
|
|
1081
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
1082
|
+
+ ` ProgrammableSwitchEvent: SINGLE, ProgrammableSwitchOutputState: 0 (${this.StatefulProgrammableSwitch.On})`);
|
|
1061
1083
|
}
|
|
1062
1084
|
}
|
|
1063
|
-
this.
|
|
1085
|
+
await this.setOn(Boolean(this.StatefulProgrammableSwitch?.On));
|
|
1086
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatefulProgrammableSwitch On: ${this.StatefulProgrammableSwitch?.On}`);
|
|
1064
1087
|
} else if (this.botDeviceType === 'switch') {
|
|
1065
|
-
if (this.On === undefined) {
|
|
1066
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
1088
|
+
if (this.Switch?.On === undefined) {
|
|
1089
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Switch?.On}`);
|
|
1067
1090
|
} else {
|
|
1068
|
-
this.
|
|
1069
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
1091
|
+
this.Switch.Service.updateCharacteristic(this.hap.Characteristic.On, this.Switch.On);
|
|
1092
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.Switch.On}`);
|
|
1070
1093
|
}
|
|
1094
|
+
await this.setOn(Boolean(this.Switch?.On));
|
|
1071
1095
|
} else {
|
|
1072
|
-
if (this.On === undefined) {
|
|
1073
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.On}`);
|
|
1096
|
+
if (this.Outlet?.On === undefined) {
|
|
1097
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Outlet?.On}`);
|
|
1074
1098
|
} else {
|
|
1075
|
-
this.
|
|
1076
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
|
|
1099
|
+
this.Outlet.Service.updateCharacteristic(this.hap.Characteristic.On, this.Outlet.On);
|
|
1100
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic On: ${this.Outlet.On}`);
|
|
1077
1101
|
}
|
|
1102
|
+
await this.setOn(Boolean(this.Outlet?.On));
|
|
1078
1103
|
}
|
|
1079
|
-
this.accessory.context.On = this.
|
|
1104
|
+
this.accessory.context.On = await this.getOn();
|
|
1080
1105
|
// BatteryLevel
|
|
1081
|
-
if (this.BatteryLevel === undefined) {
|
|
1082
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
1106
|
+
if (this.Battery.BatteryLevel === undefined) {
|
|
1107
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
1083
1108
|
} else {
|
|
1084
|
-
this.accessory.context.BatteryLevel = this.BatteryLevel;
|
|
1085
|
-
this.
|
|
1086
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
|
|
1109
|
+
this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
|
|
1110
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
|
|
1111
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
1087
1112
|
}
|
|
1088
1113
|
// StatusLowBattery
|
|
1089
|
-
if (this.StatusLowBattery === undefined) {
|
|
1090
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
1114
|
+
if (this.Battery.StatusLowBattery === undefined) {
|
|
1115
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
1091
1116
|
} else {
|
|
1092
|
-
this.accessory.context.StatusLowBattery = this.StatusLowBattery;
|
|
1093
|
-
this.
|
|
1094
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic
|
|
1117
|
+
this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
|
|
1118
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
|
|
1119
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
1120
|
+
+ ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
1095
1121
|
}
|
|
1096
1122
|
}
|
|
1097
1123
|
|
|
1098
1124
|
async removeOutletService(accessory: PlatformAccessory): Promise<void> {
|
|
1099
1125
|
// If outletService still present, then remove first
|
|
1100
|
-
|
|
1101
|
-
|
|
1126
|
+
if (this.Outlet?.Service) {
|
|
1127
|
+
this.Outlet.Service = this.accessory.getService(this.hap.Service.Outlet) as Service;
|
|
1102
1128
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Outlet Service`);
|
|
1129
|
+
accessory.removeService(this.Outlet.Service);
|
|
1103
1130
|
}
|
|
1104
|
-
accessory.removeService(this.outletService!);
|
|
1105
1131
|
}
|
|
1106
1132
|
|
|
1107
1133
|
async removeGarageDoorService(accessory: PlatformAccessory): Promise<void> {
|
|
1108
1134
|
// If garageDoorService still present, then remove first
|
|
1109
|
-
|
|
1110
|
-
|
|
1135
|
+
if (this.GarageDoor?.Service) {
|
|
1136
|
+
this.GarageDoor.Service = this.accessory.getService(this.hap.Service.GarageDoorOpener) as Service;
|
|
1111
1137
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Garage Door Service`);
|
|
1138
|
+
accessory.removeService(this.GarageDoor.Service);
|
|
1112
1139
|
}
|
|
1113
|
-
accessory.removeService(this.garageDoorService!);
|
|
1114
1140
|
}
|
|
1115
1141
|
|
|
1116
1142
|
async removeDoorService(accessory: PlatformAccessory): Promise<void> {
|
|
1117
1143
|
// If doorService still present, then remove first
|
|
1118
|
-
|
|
1119
|
-
|
|
1144
|
+
if (this.Door?.Service) {
|
|
1145
|
+
this.Door.Service = this.accessory.getService(this.hap.Service.Door) as Service;
|
|
1120
1146
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Door Service`);
|
|
1147
|
+
accessory.removeService(this.Door.Service);
|
|
1121
1148
|
}
|
|
1122
|
-
accessory.removeService(this.doorService!);
|
|
1123
1149
|
}
|
|
1124
1150
|
|
|
1125
1151
|
async removeLockService(accessory: PlatformAccessory): Promise<void> {
|
|
1126
1152
|
// If lockService still present, then remove first
|
|
1127
|
-
|
|
1128
|
-
|
|
1153
|
+
if (this.LockMechanism?.Service) {
|
|
1154
|
+
this.LockMechanism.Service = this.accessory.getService(this.hap.Service.LockMechanism) as Service;
|
|
1129
1155
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Lock Service`);
|
|
1156
|
+
accessory.removeService(this.LockMechanism.Service);
|
|
1130
1157
|
}
|
|
1131
|
-
accessory.removeService(this.lockService!);
|
|
1132
1158
|
}
|
|
1133
1159
|
|
|
1134
1160
|
async removeFaucetService(accessory: PlatformAccessory): Promise<void> {
|
|
1135
1161
|
// If faucetService still present, then remove first
|
|
1136
|
-
|
|
1137
|
-
|
|
1162
|
+
if (this.Faucet?.Service) {
|
|
1163
|
+
this.Faucet.Service = this.accessory.getService(this.hap.Service.Faucet) as Service;
|
|
1138
1164
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Faucet Service`);
|
|
1165
|
+
accessory.removeService(this.Faucet.Service);
|
|
1139
1166
|
}
|
|
1140
|
-
accessory.removeService(this.faucetService!);
|
|
1141
1167
|
}
|
|
1142
1168
|
|
|
1143
1169
|
async removeFanService(accessory: PlatformAccessory): Promise<void> {
|
|
1144
1170
|
// If fanService still present, then remove first
|
|
1145
|
-
|
|
1146
|
-
|
|
1171
|
+
if (this.Fan?.Service) {
|
|
1172
|
+
this.Fan.Service = this.accessory.getService(this.hap.Service.Fanv2) as Service;
|
|
1147
1173
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Fan Service`);
|
|
1174
|
+
accessory.removeService(this.Fan.Service);
|
|
1148
1175
|
}
|
|
1149
|
-
accessory.removeService(this.fanService!);
|
|
1150
1176
|
}
|
|
1151
1177
|
|
|
1152
1178
|
async removeWindowService(accessory: PlatformAccessory): Promise<void> {
|
|
1153
1179
|
// If windowService still present, then remove first
|
|
1154
|
-
|
|
1155
|
-
|
|
1180
|
+
if (this.Window?.Service) {
|
|
1181
|
+
this.Window.Service = this.accessory.getService(this.hap.Service.Window) as Service;
|
|
1156
1182
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Service`);
|
|
1183
|
+
accessory.removeService(this.Window.Service);
|
|
1157
1184
|
}
|
|
1158
|
-
accessory.removeService(this.windowService!);
|
|
1159
1185
|
}
|
|
1160
1186
|
|
|
1161
1187
|
async removeWindowCoveringService(accessory: PlatformAccessory): Promise<void> {
|
|
1162
1188
|
// If windowCoveringService still present, then remove first
|
|
1163
|
-
|
|
1164
|
-
|
|
1189
|
+
if (this.WindowCovering?.Service) {
|
|
1190
|
+
this.WindowCovering.Service = this.accessory.getService(this.hap.Service.WindowCovering) as Service;
|
|
1165
1191
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Window Covering Service`);
|
|
1192
|
+
accessory.removeService(this.WindowCovering.Service);
|
|
1166
1193
|
}
|
|
1167
|
-
accessory.removeService(this.windowCoveringService!);
|
|
1168
1194
|
}
|
|
1169
1195
|
|
|
1170
1196
|
async removeStatefulProgrammableSwitchService(accessory: PlatformAccessory): Promise<void> {
|
|
1171
1197
|
// If statefulProgrammableSwitchService still present, then remove first
|
|
1172
|
-
|
|
1173
|
-
|
|
1198
|
+
if (this.StatefulProgrammableSwitch?.Service) {
|
|
1199
|
+
this.StatefulProgrammableSwitch.Service = this.accessory.getService(this.hap.Service.StatefulProgrammableSwitch) as Service;
|
|
1174
1200
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Stateful Programmable Switch Service`);
|
|
1201
|
+
accessory.removeService(this.StatefulProgrammableSwitch.Service);
|
|
1175
1202
|
}
|
|
1176
|
-
accessory.removeService(this.statefulProgrammableSwitchService!);
|
|
1177
1203
|
}
|
|
1178
1204
|
|
|
1179
1205
|
async removeSwitchService(accessory: PlatformAccessory): Promise<void> {
|
|
1180
1206
|
// If switchService still present, then remove first
|
|
1181
|
-
|
|
1182
|
-
|
|
1207
|
+
if (this.Switch?.Service) {
|
|
1208
|
+
this.Switch.Service = this.accessory.getService(this.hap.Service.Switch) as Service;
|
|
1183
1209
|
this.warnLog(`${this.device.deviceType}: ${accessory.displayName} Removing Leftover Switch Service`);
|
|
1210
|
+
accessory.removeService(this.Switch.Service);
|
|
1184
1211
|
}
|
|
1185
|
-
accessory.removeService(this.switchService!);
|
|
1186
1212
|
}
|
|
1187
1213
|
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
} else {
|
|
1193
|
-
this.
|
|
1194
|
-
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
} else {
|
|
1203
|
-
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
1209
|
-
(async () => {
|
|
1210
|
-
// Start to monitor advertisement packets
|
|
1211
|
-
await switchbot.startScan({
|
|
1212
|
-
model: 'H',
|
|
1213
|
-
});
|
|
1214
|
-
// Set an event handler
|
|
1215
|
-
switchbot.onadvertisement = (ad: any) => {
|
|
1216
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
|
|
1217
|
-
};
|
|
1218
|
-
await sleep(10000);
|
|
1219
|
-
// Stop to monitor
|
|
1220
|
-
switchbot.stopScan();
|
|
1221
|
-
})();
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
async BLEPushConnection() {
|
|
1226
|
-
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
1227
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
|
|
1228
|
-
await this.openAPIpushChanges();
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
async BLERefreshConnection(switchbot: any): Promise<void> {
|
|
1233
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
|
|
1234
|
-
+ ` ${JSON.stringify(switchbot)}`);
|
|
1235
|
-
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
1236
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
|
|
1237
|
-
await this.openAPIRefreshStatus();
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
async retry({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
|
|
1242
|
-
return fn().catch(async (e: any) => {
|
|
1243
|
-
if (max === 0) {
|
|
1244
|
-
throw e;
|
|
1245
|
-
}
|
|
1246
|
-
this.infoLog(e);
|
|
1247
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Retrying`);
|
|
1248
|
-
await sleep(1000);
|
|
1249
|
-
return this.retry({ max: max - 1, fn });
|
|
1250
|
-
});
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
maxRetry(): number {
|
|
1254
|
-
if (this.device.maxRetry) {
|
|
1255
|
-
return this.device.maxRetry;
|
|
1256
|
-
} else {
|
|
1257
|
-
return 5;
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
async PressOrSwitch(device: device & devicesConfig): Promise<void> {
|
|
1262
|
-
if (!device.bot?.mode) {
|
|
1263
|
-
this.botMode = 'switch';
|
|
1264
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} does not have bot mode set in the Plugin's SwitchBot Device Settings,`);
|
|
1265
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} is defaulting to "${this.botMode}" mode, you may experience issues.`);
|
|
1266
|
-
} else if (device.bot?.mode === 'switch') {
|
|
1267
|
-
this.botMode = 'switch';
|
|
1268
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1269
|
-
} else if (device.bot?.mode === 'press') {
|
|
1270
|
-
this.botMode = 'press';
|
|
1271
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1272
|
-
} else if (device.bot?.mode === 'multipress') {
|
|
1273
|
-
this.botMode = 'multipress';
|
|
1274
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1275
|
-
} else {
|
|
1276
|
-
throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
|
-
async allowPushChanges(device: device & devicesConfig): Promise<void> {
|
|
1281
|
-
if (device.bot?.allowPush) {
|
|
1282
|
-
this.allowPush = true;
|
|
1283
|
-
} else {
|
|
1284
|
-
this.allowPush = false;
|
|
1285
|
-
}
|
|
1286
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Allowing Push Changes: ${this.allowPush}`);
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
async scan(device: device & devicesConfig): Promise<void> {
|
|
1290
|
-
if (device.scanDuration) {
|
|
1291
|
-
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
1292
|
-
if (this.BLE) {
|
|
1293
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
1294
|
-
}
|
|
1214
|
+
async getOn(): Promise<boolean> {
|
|
1215
|
+
let On: boolean;
|
|
1216
|
+
if (this.botDeviceType === 'garagedoor') {
|
|
1217
|
+
On = this.GarageDoor?.On ? true : false;
|
|
1218
|
+
} else if (this.botDeviceType === 'door') {
|
|
1219
|
+
On = this.Door?.On ? true : false;
|
|
1220
|
+
} else if (this.botDeviceType === 'window') {
|
|
1221
|
+
On = this.Window?.On ? true : false;
|
|
1222
|
+
} else if (this.botDeviceType === 'windowcovering') {
|
|
1223
|
+
On = this.WindowCovering?.On ? true : false;
|
|
1224
|
+
} else if (this.botDeviceType === 'lock') {
|
|
1225
|
+
On = this.LockMechanism?.On ? true : false;
|
|
1226
|
+
} else if (this.botDeviceType === 'faucet') {
|
|
1227
|
+
On = this.Faucet?.On ? true : false;
|
|
1228
|
+
} else if (this.botDeviceType === 'fan') {
|
|
1229
|
+
On = this.Fan?.On ? true : false;
|
|
1230
|
+
} else if (this.botDeviceType === 'stateful') {
|
|
1231
|
+
On = this.StatefulProgrammableSwitch?.On ? true : false;
|
|
1232
|
+
} else if (this.botDeviceType === 'switch') {
|
|
1233
|
+
On = this.Switch?.On ? true : false;
|
|
1295
1234
|
} else {
|
|
1296
|
-
|
|
1297
|
-
if (this.BLE) {
|
|
1298
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
async statusCode(statusCode: number): Promise<void> {
|
|
1304
|
-
switch (statusCode) {
|
|
1305
|
-
case 151:
|
|
1306
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
|
|
1307
|
-
break;
|
|
1308
|
-
case 152:
|
|
1309
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
|
|
1310
|
-
break;
|
|
1311
|
-
case 160:
|
|
1312
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
|
|
1313
|
-
break;
|
|
1314
|
-
case 161:
|
|
1315
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
|
|
1316
|
-
this.offlineOff();
|
|
1317
|
-
break;
|
|
1318
|
-
case 171:
|
|
1319
|
-
this.errorLog(
|
|
1320
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. ` +
|
|
1321
|
-
`Hub: ${this.device.hubDeviceId}`,
|
|
1322
|
-
);
|
|
1323
|
-
this.offlineOff();
|
|
1324
|
-
break;
|
|
1325
|
-
case 190:
|
|
1326
|
-
this.errorLog(
|
|
1327
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
1328
|
-
` Or command format is invalid, statusCode: ${statusCode}`,
|
|
1329
|
-
);
|
|
1330
|
-
break;
|
|
1331
|
-
case 100:
|
|
1332
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
|
|
1333
|
-
break;
|
|
1334
|
-
case 200:
|
|
1335
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
|
|
1336
|
-
break;
|
|
1337
|
-
case 400:
|
|
1338
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
|
|
1339
|
-
+ `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
|
|
1340
|
-
break;
|
|
1341
|
-
case 401:
|
|
1342
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
|
|
1343
|
-
+ `but the request has not been authenticated, statusCode: ${statusCode}`);
|
|
1344
|
-
break;
|
|
1345
|
-
case 403:
|
|
1346
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
|
|
1347
|
-
+ `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
|
|
1348
|
-
break;
|
|
1349
|
-
case 404:
|
|
1350
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
|
|
1351
|
-
+ `statusCode: ${statusCode}`);
|
|
1352
|
-
break;
|
|
1353
|
-
case 406:
|
|
1354
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
|
|
1355
|
-
+ `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
|
|
1356
|
-
break;
|
|
1357
|
-
case 415:
|
|
1358
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
|
|
1359
|
-
+ `header that is not supported by the server, statusCode: ${statusCode}`);
|
|
1360
|
-
break;
|
|
1361
|
-
case 422:
|
|
1362
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
|
|
1363
|
-
+ `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
|
|
1364
|
-
break;
|
|
1365
|
-
case 429:
|
|
1366
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
|
|
1367
|
-
+ `requests allowed for a given time window, statusCode: ${statusCode}`);
|
|
1368
|
-
break;
|
|
1369
|
-
case 500:
|
|
1370
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
|
|
1371
|
-
+ `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
|
|
1372
|
-
break;
|
|
1373
|
-
default:
|
|
1374
|
-
this.infoLog(
|
|
1375
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: ` +
|
|
1376
|
-
`${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`,
|
|
1377
|
-
);
|
|
1378
|
-
}
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
async offlineOff(): Promise<void> {
|
|
1382
|
-
if (this.device.offline) {
|
|
1383
|
-
await this.deviceContext();
|
|
1384
|
-
await this.updateHomeKitCharacteristics();
|
|
1235
|
+
On = this.Outlet?.On ? true : false;
|
|
1385
1236
|
}
|
|
1237
|
+
return On;
|
|
1386
1238
|
}
|
|
1387
1239
|
|
|
1388
|
-
async
|
|
1240
|
+
async setOn(On: boolean): Promise<void> {
|
|
1389
1241
|
if (this.botDeviceType === 'garagedoor') {
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1242
|
+
if (this.GarageDoor) {
|
|
1243
|
+
this.GarageDoor.On = On;
|
|
1244
|
+
}
|
|
1393
1245
|
} else if (this.botDeviceType === 'door') {
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1246
|
+
if (this.Door) {
|
|
1247
|
+
this.Door.On = On;
|
|
1248
|
+
}
|
|
1397
1249
|
} else if (this.botDeviceType === 'window') {
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1250
|
+
if (this.Window) {
|
|
1251
|
+
this.Window.On = On;
|
|
1252
|
+
}
|
|
1401
1253
|
} else if (this.botDeviceType === 'windowcovering') {
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1254
|
+
if (this.WindowCovering) {
|
|
1255
|
+
this.WindowCovering.On = On;
|
|
1256
|
+
}
|
|
1405
1257
|
} else if (this.botDeviceType === 'lock') {
|
|
1406
|
-
|
|
1407
|
-
|
|
1258
|
+
if (this.LockMechanism) {
|
|
1259
|
+
this.LockMechanism.On = On;
|
|
1260
|
+
}
|
|
1408
1261
|
} else if (this.botDeviceType === 'faucet') {
|
|
1409
|
-
|
|
1262
|
+
if (this.Faucet) {
|
|
1263
|
+
this.Faucet.On = On;
|
|
1264
|
+
}
|
|
1410
1265
|
} else if (this.botDeviceType === 'fan') {
|
|
1411
|
-
|
|
1266
|
+
if (this.Fan) {
|
|
1267
|
+
this.Fan.On = On;
|
|
1268
|
+
}
|
|
1412
1269
|
} else if (this.botDeviceType === 'stateful') {
|
|
1413
|
-
|
|
1414
|
-
|
|
1270
|
+
if (this.StatefulProgrammableSwitch) {
|
|
1271
|
+
this.StatefulProgrammableSwitch.On = On;
|
|
1272
|
+
}
|
|
1415
1273
|
} else if (this.botDeviceType === 'switch') {
|
|
1416
|
-
|
|
1274
|
+
if (this.Switch) {
|
|
1275
|
+
this.Switch.On = On;
|
|
1276
|
+
}
|
|
1417
1277
|
} else {
|
|
1418
|
-
|
|
1278
|
+
if (this.Outlet) {
|
|
1279
|
+
this.Outlet.On = On;
|
|
1280
|
+
}
|
|
1419
1281
|
}
|
|
1420
|
-
this.batteryService?.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
|
|
1421
|
-
this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
|
|
1422
1282
|
}
|
|
1423
1283
|
|
|
1424
|
-
async
|
|
1284
|
+
async getBotConfigSettings(device: device & devicesConfig) {
|
|
1285
|
+
//Bot Device Type
|
|
1425
1286
|
if (!device.bot?.deviceType && this.accessory.context.deviceType) {
|
|
1426
1287
|
this.botDeviceType = this.accessory.context.deviceType;
|
|
1427
1288
|
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Type: ${this.botDeviceType}, from Accessory Cache.`);
|
|
@@ -1435,41 +1296,33 @@ export class Bot {
|
|
|
1435
1296
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} No Device Type Set, deviceType: ${this.device.bot?.deviceType}`);
|
|
1436
1297
|
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using default deviceType: ${this.botDeviceType}`);
|
|
1437
1298
|
}
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
this.
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
this.
|
|
1446
|
-
}
|
|
1447
|
-
|
|
1448
|
-
this.
|
|
1299
|
+
// Bot Mode
|
|
1300
|
+
if (!device.bot?.mode) {
|
|
1301
|
+
this.botMode = 'switch';
|
|
1302
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} does not have bot mode set in the Plugin's SwitchBot Device Settings,`);
|
|
1303
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} is defaulting to "${this.botMode}" mode, you may experience issues.`);
|
|
1304
|
+
} else if (device.bot?.mode === 'switch') {
|
|
1305
|
+
this.botMode = 'switch';
|
|
1306
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1307
|
+
} else if (device.bot?.mode === 'press') {
|
|
1308
|
+
this.botMode = 'press';
|
|
1309
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1310
|
+
} else if (device.bot?.mode === 'multipress') {
|
|
1311
|
+
this.botMode = 'multipress';
|
|
1312
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Bot Mode: ${this.botMode}`);
|
|
1449
1313
|
} else {
|
|
1450
|
-
this.
|
|
1314
|
+
throw new Error(`${this.device.deviceType}: ${this.accessory.displayName} Bot Mode: ${this.botMode}`);
|
|
1451
1315
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1316
|
+
|
|
1317
|
+
// Bot Double Press
|
|
1318
|
+
if (device.bot?.doublePress) {
|
|
1319
|
+
this.doublePress = device.bot?.doublePress;
|
|
1320
|
+
this.accessory.context.doublePress = this.doublePress;
|
|
1455
1321
|
} else {
|
|
1456
|
-
this.
|
|
1457
|
-
}
|
|
1458
|
-
if (this.FirmwareRevision === undefined) {
|
|
1459
|
-
this.FirmwareRevision = this.platform.version;
|
|
1460
|
-
this.accessory.context.FirmwareRevision = this.FirmwareRevision;
|
|
1322
|
+
this.doublePress = 1;
|
|
1461
1323
|
}
|
|
1462
|
-
}
|
|
1463
1324
|
|
|
1464
|
-
|
|
1465
|
-
if (device.refreshRate) {
|
|
1466
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
1467
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1468
|
-
} else if (this.platform.config.options!.refreshRate) {
|
|
1469
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
1470
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1471
|
-
}
|
|
1472
|
-
// pushRatePress
|
|
1325
|
+
// Bot Press PushRate
|
|
1473
1326
|
if (device?.bot?.pushRatePress) {
|
|
1474
1327
|
this.pushRatePress = device?.bot?.pushRatePress;
|
|
1475
1328
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Bot pushRatePress: ${this.pushRatePress}`);
|
|
@@ -1477,106 +1330,144 @@ export class Bot {
|
|
|
1477
1330
|
this.pushRatePress = 15;
|
|
1478
1331
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default Bot pushRatePress: ${this.pushRatePress}`);
|
|
1479
1332
|
}
|
|
1480
|
-
}
|
|
1481
|
-
|
|
1482
|
-
async deviceConfig(device: device & devicesConfig): Promise<void> {
|
|
1483
|
-
let config = {};
|
|
1484
|
-
if (device.bot) {
|
|
1485
|
-
config = device.bot;
|
|
1486
|
-
}
|
|
1487
|
-
if (device.connectionType !== undefined) {
|
|
1488
|
-
config['connectionType'] = device.connectionType;
|
|
1489
|
-
}
|
|
1490
|
-
if (device.external !== undefined) {
|
|
1491
|
-
config['external'] = device.external;
|
|
1492
|
-
}
|
|
1493
|
-
if (device.logging !== undefined) {
|
|
1494
|
-
config['logging'] = device.logging;
|
|
1495
|
-
}
|
|
1496
|
-
if (device.refreshRate !== undefined) {
|
|
1497
|
-
config['refreshRate'] = device.refreshRate;
|
|
1498
|
-
}
|
|
1499
|
-
if (device.scanDuration !== undefined) {
|
|
1500
|
-
config['scanDuration'] = device.scanDuration;
|
|
1501
|
-
}
|
|
1502
|
-
if (device.offline !== undefined) {
|
|
1503
|
-
config['offline'] = device.offline;
|
|
1504
|
-
}
|
|
1505
|
-
if (device.maxRetry !== undefined) {
|
|
1506
|
-
config['maxRetry'] = device.maxRetry;
|
|
1507
|
-
}
|
|
1508
|
-
if (device.webhook !== undefined) {
|
|
1509
|
-
config['webhook'] = device.webhook;
|
|
1510
|
-
}
|
|
1511
|
-
if (Object.entries(config).length !== 0) {
|
|
1512
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
1333
|
|
|
1516
|
-
|
|
1517
|
-
if (
|
|
1518
|
-
this.
|
|
1519
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
1520
|
-
} else if (device.logging) {
|
|
1521
|
-
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
1522
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
1523
|
-
} else if (this.platform.config.options?.logging) {
|
|
1524
|
-
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
1525
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
1334
|
+
// Bot Allow Push
|
|
1335
|
+
if (device.bot?.allowPush) {
|
|
1336
|
+
this.allowPush = true;
|
|
1526
1337
|
} else {
|
|
1527
|
-
this.
|
|
1528
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
1338
|
+
this.allowPush = false;
|
|
1529
1339
|
}
|
|
1340
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Allowing Push Changes: ${this.allowPush}`);
|
|
1341
|
+
// Bot Multi Press Count
|
|
1342
|
+
this.multiPressCount = 0;
|
|
1530
1343
|
}
|
|
1531
1344
|
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
if (this.enablingDeviceLogging()) {
|
|
1537
|
-
this.platform.log.info(String(...log));
|
|
1345
|
+
async BLEPushConnection() {
|
|
1346
|
+
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
1347
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
|
|
1348
|
+
await this.openAPIpushChanges();
|
|
1538
1349
|
}
|
|
1539
1350
|
}
|
|
1540
1351
|
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1352
|
+
async BLERefreshConnection(switchbot: any): Promise<void> {
|
|
1353
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
|
|
1354
|
+
+ ` ${JSON.stringify(switchbot)}`);
|
|
1355
|
+
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
1356
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
|
|
1357
|
+
await this.openAPIRefreshStatus();
|
|
1544
1358
|
}
|
|
1545
1359
|
}
|
|
1546
1360
|
|
|
1547
|
-
|
|
1548
|
-
if (this.
|
|
1549
|
-
if (this.
|
|
1550
|
-
this.
|
|
1361
|
+
async offlineOff(): Promise<void> {
|
|
1362
|
+
if (this.device.offline) {
|
|
1363
|
+
if (this.botDeviceType === 'garagedoor') {
|
|
1364
|
+
if (this.GarageDoor) {
|
|
1365
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, this.hap.Characteristic.TargetDoorState.CLOSED);
|
|
1366
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, this.hap.Characteristic.CurrentDoorState.CLOSED);
|
|
1367
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.ObstructionDetected, false);
|
|
1368
|
+
}
|
|
1369
|
+
} else if (this.botDeviceType === 'door') {
|
|
1370
|
+
if (this.Door) {
|
|
1371
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
|
|
1372
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
|
|
1373
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
1374
|
+
}
|
|
1375
|
+
} else if (this.botDeviceType === 'window') {
|
|
1376
|
+
if (this.Window) {
|
|
1377
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
|
|
1378
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
|
|
1379
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
1380
|
+
}
|
|
1381
|
+
} else if (this.botDeviceType === 'windowcovering') {
|
|
1382
|
+
if (this.WindowCovering) {
|
|
1383
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 0);
|
|
1384
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 0);
|
|
1385
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
1386
|
+
}
|
|
1387
|
+
} else if (this.botDeviceType === 'lock') {
|
|
1388
|
+
if (this.LockMechanism) {
|
|
1389
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, this.hap.Characteristic.LockTargetState.SECURED);
|
|
1390
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, this.hap.Characteristic.LockCurrentState.SECURED);
|
|
1391
|
+
}
|
|
1392
|
+
} else if (this.botDeviceType === 'faucet') {
|
|
1393
|
+
if (this.Faucet) {
|
|
1394
|
+
this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.INACTIVE);
|
|
1395
|
+
}
|
|
1396
|
+
} else if (this.botDeviceType === 'fan') {
|
|
1397
|
+
if (this.Fan) {
|
|
1398
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, false);
|
|
1399
|
+
}
|
|
1400
|
+
} else if (this.botDeviceType === 'stateful') {
|
|
1401
|
+
if (this.StatefulProgrammableSwitch) {
|
|
1402
|
+
this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent,
|
|
1403
|
+
this.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
|
|
1404
|
+
this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, 0);
|
|
1405
|
+
}
|
|
1406
|
+
} else if (this.botDeviceType === 'switch') {
|
|
1407
|
+
if (this.Switch) {
|
|
1408
|
+
this.Switch.Service.updateCharacteristic(this.hap.Characteristic.On, false);
|
|
1409
|
+
}
|
|
1410
|
+
} else {
|
|
1411
|
+
if (this.Outlet) {
|
|
1412
|
+
this.Outlet.Service.updateCharacteristic(this.hap.Characteristic.On, false);
|
|
1413
|
+
}
|
|
1551
1414
|
}
|
|
1552
1415
|
}
|
|
1553
1416
|
}
|
|
1554
1417
|
|
|
1555
|
-
|
|
1556
|
-
if (this.
|
|
1557
|
-
this.
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
debugErrorLog(...log: any[]): void {
|
|
1562
|
-
if (this.enablingDeviceLogging()) {
|
|
1563
|
-
if (this.deviceLogging?.includes('debug')) {
|
|
1564
|
-
this.platform.log.error('[DEBUG]', String(...log));
|
|
1418
|
+
async apiError(e: any): Promise<void> {
|
|
1419
|
+
if (this.botDeviceType === 'garagedoor') {
|
|
1420
|
+
if (this.GarageDoor) {
|
|
1421
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.TargetDoorState, e);
|
|
1422
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.CurrentDoorState, e);
|
|
1423
|
+
this.GarageDoor.Service.updateCharacteristic(this.hap.Characteristic.ObstructionDetected, e);
|
|
1565
1424
|
}
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
this.
|
|
1425
|
+
} else if (this.botDeviceType === 'door') {
|
|
1426
|
+
if (this.Door) {
|
|
1427
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
|
|
1428
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
|
|
1429
|
+
this.Door.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
|
|
1430
|
+
}
|
|
1431
|
+
} else if (this.botDeviceType === 'window') {
|
|
1432
|
+
if (this.Window) {
|
|
1433
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
|
|
1434
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
|
|
1435
|
+
this.Window.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
|
|
1436
|
+
}
|
|
1437
|
+
} else if (this.botDeviceType === 'windowcovering') {
|
|
1438
|
+
if (this.WindowCovering) {
|
|
1439
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
|
|
1440
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
|
|
1441
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
|
|
1442
|
+
}
|
|
1443
|
+
} else if (this.botDeviceType === 'lock') {
|
|
1444
|
+
if (this.LockMechanism) {
|
|
1445
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockTargetState, e);
|
|
1446
|
+
this.LockMechanism.Service.updateCharacteristic(this.hap.Characteristic.LockCurrentState, e);
|
|
1447
|
+
}
|
|
1448
|
+
} else if (this.botDeviceType === 'faucet') {
|
|
1449
|
+
if (this.Faucet) {
|
|
1450
|
+
this.Faucet.Service.updateCharacteristic(this.hap.Characteristic.Active, e);
|
|
1451
|
+
}
|
|
1452
|
+
} else if (this.botDeviceType === 'fan') {
|
|
1453
|
+
if (this.Fan) {
|
|
1454
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.On, e);
|
|
1455
|
+
}
|
|
1456
|
+
} else if (this.botDeviceType === 'stateful') {
|
|
1457
|
+
if (this.StatefulProgrammableSwitch) {
|
|
1458
|
+
this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchEvent, e);
|
|
1459
|
+
this.StatefulProgrammableSwitch.Service.updateCharacteristic(this.hap.Characteristic.ProgrammableSwitchOutputState, e);
|
|
1460
|
+
}
|
|
1461
|
+
} else if (this.botDeviceType === 'switch') {
|
|
1462
|
+
if (this.Switch) {
|
|
1463
|
+
this.Switch.Service.updateCharacteristic(this.hap.Characteristic.On, e);
|
|
1464
|
+
}
|
|
1465
|
+
} else {
|
|
1466
|
+
if (this.Outlet) {
|
|
1467
|
+
this.Outlet.Service.updateCharacteristic(this.hap.Characteristic.On, e);
|
|
1575
1468
|
}
|
|
1576
1469
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
enablingDeviceLogging(): boolean {
|
|
1580
|
-
return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
|
|
1470
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
|
|
1471
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
|
|
1581
1472
|
}
|
|
1582
1473
|
}
|