@switchbot/homebridge-switchbot 3.5.0-beta.5 → 3.5.0-beta.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/config.schema.json +120 -17
- package/dist/device/blindtilt.d.ts +21 -94
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +352 -757
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts +25 -71
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +588 -761
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts +13 -67
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +214 -588
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts +13 -74
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +256 -634
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts +14 -65
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +209 -532
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts +17 -86
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +340 -787
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts +59 -0
- package/dist/device/device.d.ts.map +1 -0
- package/dist/device/device.js +682 -0
- package/dist/device/device.js.map +1 -0
- package/dist/device/fan.d.ts +51 -0
- package/dist/device/fan.d.ts.map +1 -0
- package/dist/device/fan.js +505 -0
- package/dist/device/fan.js.map +1 -0
- package/dist/device/hub.d.ts +15 -59
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +247 -597
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts +10 -65
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +218 -579
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts +11 -64
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +179 -585
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts +10 -68
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +257 -569
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts +15 -62
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +215 -543
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +13 -63
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +175 -578
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +13 -64
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +164 -578
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts +13 -69
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +142 -520
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts +9 -57
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +87 -453
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts +11 -62
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +145 -452
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts +9 -70
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +126 -665
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +2 -2
- package/dist/index.js +1 -1
- package/dist/irdevice/airconditioner.d.ts +8 -48
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +309 -419
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts +7 -38
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +72 -304
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts +6 -35
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +34 -278
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +6 -39
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +67 -311
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +40 -0
- package/dist/irdevice/irdevice.d.ts.map +1 -0
- package/dist/irdevice/irdevice.js +512 -0
- package/dist/irdevice/irdevice.js.map +1 -0
- package/dist/irdevice/light.d.ts +6 -34
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +23 -272
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts +18 -47
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +352 -546
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts +7 -39
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +82 -321
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts +6 -35
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +41 -284
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts +6 -35
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +42 -287
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +14 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +291 -147
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +41 -11
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +0 -552
- package/dist/settings.js.map +1 -1
- package/dist/utils.d.ts +77 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +638 -1
- package/dist/utils.js.map +1 -1
- package/eslint.config.js +87 -0
- package/package.json +16 -15
- package/src/custom.d.ts +2 -1
- package/src/device/blindtilt.ts +378 -783
- package/src/device/bot.ts +621 -845
- package/src/device/ceilinglight.ts +227 -608
- package/src/device/colorbulb.ts +269 -657
- package/src/device/contact.ts +235 -555
- package/src/device/curtain.ts +360 -811
- package/src/device/device.ts +710 -0
- package/src/device/fan.ts +554 -0
- package/src/device/hub.ts +274 -625
- package/src/device/humidifier.ts +246 -624
- package/src/device/iosensor.ts +205 -611
- package/src/device/lightstrip.ts +278 -597
- package/src/device/lock.ts +252 -583
- package/src/device/meter.ts +200 -601
- package/src/device/meterplus.ts +189 -603
- package/src/device/motion.ts +161 -542
- package/src/device/plug.ts +97 -481
- package/src/device/robotvacuumcleaner.ts +166 -478
- package/src/device/waterdetector.ts +143 -689
- package/src/homebridge-ui/public/index.html +2 -2
- package/src/index.ts +1 -1
- package/src/irdevice/airconditioner.ts +330 -446
- package/src/irdevice/airpurifier.ts +89 -321
- package/src/irdevice/camera.ts +42 -293
- package/src/irdevice/fan.ts +78 -327
- package/src/irdevice/irdevice.ts +528 -0
- package/src/irdevice/light.ts +32 -287
- package/src/irdevice/other.ts +396 -615
- package/src/irdevice/tv.ts +100 -339
- package/src/irdevice/vacuumcleaner.ts +49 -305
- package/src/irdevice/waterheater.ts +50 -310
- package/src/platform.ts +301 -155
- package/src/settings.ts +57 -566
- package/src/utils.ts +642 -1
package/src/device/curtain.ts
CHANGED
|
@@ -1,139 +1,100 @@
|
|
|
1
|
+
/* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* curtain.ts: @switchbot/homebridge-switchbot.
|
|
4
|
+
*/
|
|
5
|
+
import { hostname } from 'os';
|
|
1
6
|
import { request } from 'undici';
|
|
2
|
-
import { sleep } from '../utils.js';
|
|
3
|
-
import { MqttClient } from 'mqtt';
|
|
4
7
|
import { interval, Subject } from 'rxjs';
|
|
5
|
-
import
|
|
8
|
+
import { deviceBase } from './device.js';
|
|
6
9
|
import { SwitchBotPlatform } from '../platform.js';
|
|
7
10
|
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
|
|
8
|
-
import { Service, PlatformAccessory, CharacteristicValue, CharacteristicChange
|
|
9
|
-
import { device, devicesConfig, serviceData, deviceStatus, Devices
|
|
10
|
-
import { hostname } from 'os';
|
|
11
|
+
import { Service, PlatformAccessory, CharacteristicValue, CharacteristicChange } from 'homebridge';
|
|
12
|
+
import { device, devicesConfig, serviceData, deviceStatus, Devices } from '../settings.js';
|
|
11
13
|
|
|
12
|
-
export class Curtain {
|
|
13
|
-
public readonly api: API;
|
|
14
|
-
public readonly log: Logging;
|
|
15
|
-
public readonly config!: SwitchBotPlatformConfig;
|
|
16
|
-
protected readonly hap: HAP;
|
|
14
|
+
export class Curtain extends deviceBase {
|
|
17
15
|
// Services
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
OpenAPI_CurrentPosition: deviceStatus['slidePosition'];
|
|
37
|
-
OpenAPI_CurrentAmbientLightLevel: deviceStatus['brightness'];
|
|
38
|
-
|
|
39
|
-
// Others
|
|
40
|
-
Mode!: string;
|
|
41
|
-
setPositionMode?: string;
|
|
42
|
-
|
|
43
|
-
// BLE Status
|
|
44
|
-
BLE_InMotion: serviceData['inMotion'];
|
|
45
|
-
BLE_BatteryLevel: serviceData['battery'];
|
|
46
|
-
BLE_Calibration: serviceData['calibration'];
|
|
47
|
-
BLE_CurrentPosition: serviceData['position'];
|
|
48
|
-
BLE_CurrentAmbientLightLevel: serviceData['lightLevel'];
|
|
49
|
-
|
|
50
|
-
// BLE Others
|
|
51
|
-
BLE_IsConnected?: boolean;
|
|
52
|
-
spaceBetweenLevels!: number;
|
|
16
|
+
private WindowCovering!: {
|
|
17
|
+
Service: Service;
|
|
18
|
+
PositionState: CharacteristicValue;
|
|
19
|
+
TargetPosition: CharacteristicValue;
|
|
20
|
+
CurrentPosition: CharacteristicValue;
|
|
21
|
+
HoldPosition: CharacteristicValue;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
private Battery!: {
|
|
25
|
+
Service: Service;
|
|
26
|
+
BatteryLevel: CharacteristicValue;
|
|
27
|
+
StatusLowBattery: CharacteristicValue;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
private LightSensor?: {
|
|
31
|
+
Service: Service;
|
|
32
|
+
CurrentAmbientLightLevel?: CharacteristicValue;
|
|
33
|
+
};
|
|
53
34
|
|
|
54
35
|
// Target
|
|
55
36
|
setNewTarget!: boolean;
|
|
56
37
|
setNewTargetTimer!: NodeJS.Timeout;
|
|
57
38
|
|
|
58
|
-
//MQTT stuff
|
|
59
|
-
mqttClient: MqttClient | null = null;
|
|
60
|
-
|
|
61
|
-
// Config
|
|
62
|
-
updateRate!: number;
|
|
63
|
-
set_minLux!: number;
|
|
64
|
-
set_maxLux!: number;
|
|
65
|
-
set_minStep!: number;
|
|
66
|
-
setOpenMode!: string;
|
|
67
|
-
setCloseMode!: string;
|
|
68
|
-
scanDuration!: number;
|
|
69
|
-
deviceLogging!: string;
|
|
70
|
-
deviceRefreshRate!: number;
|
|
71
|
-
|
|
72
39
|
// Updates
|
|
73
40
|
curtainUpdateInProgress!: boolean;
|
|
74
41
|
doCurtainUpdate!: Subject<void>;
|
|
75
42
|
|
|
76
|
-
// Connection
|
|
77
|
-
private readonly OpenAPI: boolean;
|
|
78
|
-
private readonly BLE: boolean;
|
|
79
|
-
|
|
80
|
-
// EVE history service handler
|
|
81
|
-
historyService: any = null;
|
|
82
|
-
|
|
83
43
|
constructor(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
44
|
+
readonly platform: SwitchBotPlatform,
|
|
45
|
+
accessory: PlatformAccessory,
|
|
46
|
+
device: device & devicesConfig,
|
|
87
47
|
) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this.
|
|
91
|
-
this.hap = this.api.hap;
|
|
92
|
-
// Connection
|
|
93
|
-
this.BLE = this.device.connectionType === 'BLE' || this.device.connectionType === 'BLE/OpenAPI';
|
|
94
|
-
this.OpenAPI = this.device.connectionType === 'OpenAPI' || this.device.connectionType === 'BLE/OpenAPI';
|
|
95
|
-
// default placeholders
|
|
96
|
-
this.deviceLogs(device);
|
|
97
|
-
this.refreshRate(device);
|
|
98
|
-
this.scan(device);
|
|
99
|
-
this.setupMqtt(device);
|
|
100
|
-
this.deviceContext();
|
|
101
|
-
this.deviceConfig(device);
|
|
102
|
-
|
|
48
|
+
super(platform, accessory, device);
|
|
49
|
+
// default placeholder
|
|
50
|
+
this.history(device);
|
|
103
51
|
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
104
52
|
this.doCurtainUpdate = new Subject();
|
|
105
53
|
this.curtainUpdateInProgress = false;
|
|
106
54
|
this.setNewTarget = false;
|
|
107
55
|
|
|
56
|
+
// Initialize LightBulb property
|
|
57
|
+
this.WindowCovering = {
|
|
58
|
+
Service: accessory.getService(this.hap.Service.WindowCovering)!,
|
|
59
|
+
PositionState: accessory.context.PositionState || this.hap.Characteristic.PositionState.STOPPED,
|
|
60
|
+
TargetPosition: accessory.context.TargetPosition || 100,
|
|
61
|
+
CurrentPosition: accessory.context.CurrentPosition || 100,
|
|
62
|
+
HoldPosition: accessory.context.HoldPosition || false,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Initialize Battery property
|
|
66
|
+
this.Battery = {
|
|
67
|
+
Service: accessory.getService(this.hap.Service.Battery)!,
|
|
68
|
+
BatteryLevel: accessory.context.BatteryLevel || 100,
|
|
69
|
+
StatusLowBattery: accessory.context.StatusLowBattery || this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// Initialize LightSensor property
|
|
73
|
+
if (!this.device.curtain?.hide_lightsensor) {
|
|
74
|
+
this.LightSensor = {
|
|
75
|
+
Service: accessory.getService(this.hap.Service.LightSensor)!,
|
|
76
|
+
CurrentAmbientLightLevel: accessory.context.CurrentAmbientLightLevel || 0.0001,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
108
80
|
// Retrieve initial values and updateHomekit
|
|
109
81
|
this.refreshStatus();
|
|
110
82
|
|
|
111
|
-
// set accessory information
|
|
112
|
-
accessory
|
|
113
|
-
.getService(this.hap.Service.AccessoryInformation)!
|
|
114
|
-
.setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
|
|
115
|
-
.setCharacteristic(this.hap.Characteristic.Model, 'W0701600')
|
|
116
|
-
.setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId)
|
|
117
|
-
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, accessory.context.FirmwareRevision);
|
|
118
|
-
|
|
119
83
|
// get the WindowCovering service if it exists, otherwise create a new WindowCovering service
|
|
120
84
|
// you can create multiple services for each accessory
|
|
121
|
-
const
|
|
122
|
-
(this.
|
|
123
|
-
|| accessory.addService(this.hap.Service.WindowCovering)),
|
|
85
|
+
const WindowCoveringService = `${accessory.displayName} ${device.deviceType}`;
|
|
86
|
+
(this.WindowCovering.Service = accessory.getService(this.hap.Service.WindowCovering)
|
|
87
|
+
|| accessory.addService(this.hap.Service.WindowCovering)), WindowCoveringService;
|
|
124
88
|
|
|
125
|
-
this.
|
|
126
|
-
if (!this.windowCoveringService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
127
|
-
this.windowCoveringService.addCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName);
|
|
128
|
-
}
|
|
89
|
+
this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
|
|
129
90
|
|
|
130
91
|
// each service must implement at-minimum the "required characteristics" for the given service type
|
|
131
92
|
// see https://developers.homebridge.io/#/service/WindowCovering
|
|
132
93
|
|
|
133
94
|
// create handlers for required characteristics
|
|
134
|
-
this.
|
|
95
|
+
this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
|
|
135
96
|
|
|
136
|
-
this.
|
|
97
|
+
this.WindowCovering.Service
|
|
137
98
|
.getCharacteristic(this.hap.Characteristic.CurrentPosition)
|
|
138
99
|
.setProps({
|
|
139
100
|
minStep: this.minStep(device),
|
|
@@ -142,10 +103,10 @@ export class Curtain {
|
|
|
142
103
|
validValueRanges: [0, 100],
|
|
143
104
|
})
|
|
144
105
|
.onGet(() => {
|
|
145
|
-
return this.CurrentPosition;
|
|
106
|
+
return this.WindowCovering.CurrentPosition;
|
|
146
107
|
});
|
|
147
108
|
|
|
148
|
-
this.
|
|
109
|
+
this.WindowCovering.Service
|
|
149
110
|
.getCharacteristic(this.hap.Characteristic.TargetPosition)
|
|
150
111
|
.setProps({
|
|
151
112
|
minStep: this.minStep(device),
|
|
@@ -155,38 +116,32 @@ export class Curtain {
|
|
|
155
116
|
})
|
|
156
117
|
.onSet(this.TargetPositionSet.bind(this));
|
|
157
118
|
|
|
158
|
-
this.
|
|
119
|
+
this.WindowCovering.Service
|
|
159
120
|
.getCharacteristic(this.hap.Characteristic.HoldPosition)
|
|
160
121
|
.onSet(this.HoldPositionSet.bind(this));
|
|
161
122
|
|
|
162
123
|
// Light Sensor Service
|
|
163
124
|
if (device.curtain?.hide_lightsensor) {
|
|
164
125
|
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Light Sensor Service`);
|
|
165
|
-
this.
|
|
166
|
-
accessory.removeService(this.
|
|
167
|
-
} else if (!this.
|
|
126
|
+
this.LightSensor!.Service = this.accessory.getService(this.hap.Service.LightSensor) as Service;
|
|
127
|
+
accessory.removeService(this.LightSensor!.Service);
|
|
128
|
+
} else if (!this.LightSensor?.Service) {
|
|
168
129
|
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Light Sensor Service`);
|
|
169
|
-
const
|
|
170
|
-
(this.
|
|
171
|
-
|| this.accessory.addService(this.hap.Service.LightSensor)),
|
|
130
|
+
const LightSensorService = `${accessory.displayName} Light Sensor`;
|
|
131
|
+
(this.LightSensor!.Service = this.accessory.getService(this.hap.Service.LightSensor)
|
|
132
|
+
|| this.accessory.addService(this.hap.Service.LightSensor)), LightSensorService;
|
|
172
133
|
|
|
173
|
-
this.
|
|
174
|
-
if (!this.lightSensorService?.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
175
|
-
this.lightSensorService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Light Sensor`);
|
|
176
|
-
}
|
|
134
|
+
this.LightSensor!.Service.setCharacteristic(this.hap.Characteristic.Name, LightSensorService);
|
|
177
135
|
} else {
|
|
178
136
|
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Light Sensor Service Not Added`);
|
|
179
137
|
}
|
|
180
138
|
|
|
181
139
|
// Battery Service
|
|
182
140
|
const batteryService = `${accessory.displayName} Battery`;
|
|
183
|
-
(this.
|
|
141
|
+
(this.Battery.Service = this.accessory.getService(this.hap.Service.Battery)
|
|
184
142
|
|| accessory.addService(this.hap.Service.Battery)), batteryService;
|
|
185
143
|
|
|
186
|
-
this.
|
|
187
|
-
if (!this.batteryService.testCharacteristic(this.hap.Characteristic.ConfiguredName)) {
|
|
188
|
-
this.batteryService.addCharacteristic(this.hap.Characteristic.ConfiguredName, `${accessory.displayName} Battery`);
|
|
189
|
-
}
|
|
144
|
+
this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
190
145
|
|
|
191
146
|
// Update Homekit
|
|
192
147
|
this.updateHomeKitCharacteristics();
|
|
@@ -199,19 +154,18 @@ export class Curtain {
|
|
|
199
154
|
});
|
|
200
155
|
|
|
201
156
|
//regisiter webhook event handler
|
|
202
|
-
if (
|
|
203
|
-
this.
|
|
157
|
+
if (device.webhook) {
|
|
158
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
|
|
204
159
|
this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
|
|
205
160
|
try {
|
|
206
161
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
|
|
207
162
|
const { slidePosition, battery } = context;
|
|
208
|
-
const { CurrentPosition, BatteryLevel } = this;
|
|
209
163
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
|
|
210
164
|
'(slidePosition, battery) = ' +
|
|
211
165
|
`Webhook:(${slidePosition}, ${battery}), ` +
|
|
212
|
-
`current:(${CurrentPosition}, ${BatteryLevel})`);
|
|
213
|
-
this.CurrentPosition = slidePosition;
|
|
214
|
-
this.BatteryLevel = battery;
|
|
166
|
+
`current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
|
|
167
|
+
this.WindowCovering.CurrentPosition = slidePosition;
|
|
168
|
+
this.Battery.BatteryLevel = battery;
|
|
215
169
|
this.updateHomeKitCharacteristics();
|
|
216
170
|
} catch (e: any) {
|
|
217
171
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
@@ -221,13 +175,14 @@ export class Curtain {
|
|
|
221
175
|
}
|
|
222
176
|
|
|
223
177
|
// update slide progress
|
|
224
|
-
interval(this.
|
|
178
|
+
interval(this.deviceUpdateRate * 1000)
|
|
225
179
|
//.pipe(skipWhile(() => this.curtainUpdateInProgress))
|
|
226
180
|
.subscribe(async () => {
|
|
227
|
-
if (this.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
|
|
181
|
+
if (this.WindowCovering.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
|
|
228
182
|
return;
|
|
229
183
|
}
|
|
230
|
-
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Refresh Status When Moving
|
|
184
|
+
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Refresh Status When Moving,`
|
|
185
|
+
+ ` PositionState: ${this.WindowCovering.PositionState}`);
|
|
231
186
|
await this.refreshStatus();
|
|
232
187
|
});
|
|
233
188
|
|
|
@@ -257,6 +212,16 @@ export class Curtain {
|
|
|
257
212
|
this.setupHistoryService(device);
|
|
258
213
|
}
|
|
259
214
|
|
|
215
|
+
private history(device: device & devicesConfig) {
|
|
216
|
+
if (device.history === true) {
|
|
217
|
+
// initialize when this accessory is newly created.
|
|
218
|
+
this.accessory.context.lastActivation = this.accessory.context.lastActivation ?? 0;
|
|
219
|
+
} else {
|
|
220
|
+
// removes cached values if history is turned off
|
|
221
|
+
delete this.accessory.context.lastActivation;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
260
225
|
/*
|
|
261
226
|
* Setup EVE history features for curtain devices.
|
|
262
227
|
*/
|
|
@@ -304,7 +269,7 @@ export class Curtain {
|
|
|
304
269
|
}
|
|
305
270
|
|
|
306
271
|
async updateHistory(): Promise<void> {
|
|
307
|
-
const motion = Number(this.CurrentPosition) > 0 ? 1 : 0;
|
|
272
|
+
const motion = Number(this.WindowCovering.CurrentPosition) > 0 ? 1 : 0;
|
|
308
273
|
this.historyService.addEntry({
|
|
309
274
|
time: Math.round(new Date().valueOf() / 1000),
|
|
310
275
|
motion: motion,
|
|
@@ -317,198 +282,198 @@ export class Curtain {
|
|
|
317
282
|
);
|
|
318
283
|
}
|
|
319
284
|
|
|
320
|
-
|
|
321
|
-
* Parse the device status from the SwitchBot api
|
|
322
|
-
*/
|
|
323
|
-
async parseStatus(): Promise<void> {
|
|
324
|
-
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
325
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} parseStatus enableCloudService: ${this.device.enableCloudService}`);
|
|
326
|
-
} else if (this.BLE) {
|
|
327
|
-
await this.BLEparseStatus();
|
|
328
|
-
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
329
|
-
await this.openAPIparseStatus();
|
|
330
|
-
} else {
|
|
331
|
-
await this.offlineOff();
|
|
332
|
-
this.debugWarnLog(
|
|
333
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, parseStatus will not happen.`,
|
|
334
|
-
);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
async BLEparseStatus(): Promise<void> {
|
|
285
|
+
async BLEparseStatus(serviceData: serviceData): Promise<void> {
|
|
339
286
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
340
287
|
// CurrentPosition
|
|
341
|
-
this.CurrentPosition = 100 - Number(
|
|
288
|
+
this.WindowCovering.CurrentPosition = 100 - Number(serviceData.position);
|
|
342
289
|
await this.setMinMax();
|
|
343
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.CurrentPosition}`);
|
|
290
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition ${this.WindowCovering.CurrentPosition}`);
|
|
344
291
|
if (this.setNewTarget) {
|
|
345
292
|
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
|
|
346
293
|
await this.setMinMax();
|
|
347
|
-
if (Number(this.TargetPosition) > this.CurrentPosition) {
|
|
348
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.CurrentPosition}`);
|
|
349
|
-
this.PositionState = this.hap.Characteristic.PositionState.INCREASING;
|
|
350
|
-
this.
|
|
351
|
-
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} INCREASING
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
this.
|
|
355
|
-
this.
|
|
356
|
-
this.
|
|
294
|
+
if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
|
|
295
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
296
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
|
|
297
|
+
this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
|
|
298
|
+
this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
|
|
299
|
+
+ ` PositionState: ${this.WindowCovering.PositionState}`);
|
|
300
|
+
} else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
|
|
301
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
302
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
|
|
303
|
+
this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
|
|
304
|
+
this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
|
|
305
|
+
+ ` PositionState: ${this.WindowCovering.PositionState}`);
|
|
357
306
|
} else {
|
|
358
|
-
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} Standby
|
|
359
|
-
|
|
360
|
-
this.
|
|
361
|
-
this.
|
|
307
|
+
this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby,`
|
|
308
|
+
+ ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
309
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
|
|
310
|
+
this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
|
|
311
|
+
this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
|
|
312
|
+
+ ` PositionState: ${this.WindowCovering.PositionState}`);
|
|
362
313
|
}
|
|
363
314
|
} else {
|
|
364
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.CurrentPosition}`);
|
|
365
|
-
this.TargetPosition = this.CurrentPosition;
|
|
366
|
-
this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
|
|
315
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
316
|
+
this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
|
|
317
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
|
|
367
318
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
|
|
368
319
|
}
|
|
369
320
|
this.debugLog(
|
|
370
|
-
`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
|
|
371
|
-
` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`,
|
|
321
|
+
`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},` +
|
|
322
|
+
` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`,
|
|
372
323
|
);
|
|
373
324
|
|
|
374
325
|
if (!this.device.curtain?.hide_lightsensor) {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
326
|
+
const set_minLux = await this.minLux();
|
|
327
|
+
const set_maxLux = await this.maxLux();
|
|
328
|
+
const spaceBetweenLevels = 9;
|
|
378
329
|
|
|
379
330
|
// Brightness
|
|
380
|
-
switch (
|
|
331
|
+
switch (serviceData.lightLevel) {
|
|
381
332
|
case 1:
|
|
382
|
-
this.CurrentAmbientLightLevel =
|
|
383
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
333
|
+
this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
|
|
334
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
|
|
384
335
|
break;
|
|
385
336
|
case 2:
|
|
386
|
-
this.CurrentAmbientLightLevel = (
|
|
337
|
+
this.LightSensor!.CurrentAmbientLightLevel = (set_maxLux - set_minLux) / spaceBetweenLevels;
|
|
387
338
|
this.debugLog(
|
|
388
|
-
`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
389
|
-
` Calculation: ${(
|
|
339
|
+
`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},` +
|
|
340
|
+
` Calculation: ${(set_maxLux - set_minLux) / spaceBetweenLevels}`,
|
|
390
341
|
);
|
|
391
342
|
break;
|
|
392
343
|
case 3:
|
|
393
|
-
this.CurrentAmbientLightLevel = ((
|
|
394
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
344
|
+
this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 2;
|
|
345
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
|
|
395
346
|
break;
|
|
396
347
|
case 4:
|
|
397
|
-
this.CurrentAmbientLightLevel = ((
|
|
398
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
348
|
+
this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 3;
|
|
349
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
|
|
399
350
|
break;
|
|
400
351
|
case 5:
|
|
401
|
-
this.CurrentAmbientLightLevel = ((
|
|
402
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
352
|
+
this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 4;
|
|
353
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
|
|
403
354
|
break;
|
|
404
355
|
case 6:
|
|
405
|
-
this.CurrentAmbientLightLevel = ((
|
|
406
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
356
|
+
this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 5;
|
|
357
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
|
|
407
358
|
break;
|
|
408
359
|
case 7:
|
|
409
|
-
this.CurrentAmbientLightLevel = ((
|
|
410
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
360
|
+
this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 6;
|
|
361
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
|
|
411
362
|
break;
|
|
412
363
|
case 8:
|
|
413
|
-
this.CurrentAmbientLightLevel = ((
|
|
414
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
364
|
+
this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 7;
|
|
365
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
|
|
415
366
|
break;
|
|
416
367
|
case 9:
|
|
417
|
-
this.CurrentAmbientLightLevel = ((
|
|
418
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
368
|
+
this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 8;
|
|
369
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
|
|
419
370
|
break;
|
|
420
371
|
case 10:
|
|
421
372
|
default:
|
|
422
|
-
this.CurrentAmbientLightLevel =
|
|
373
|
+
this.LightSensor!.CurrentAmbientLightLevel = set_maxLux;
|
|
423
374
|
this.debugLog();
|
|
424
375
|
}
|
|
425
376
|
this.debugLog(
|
|
426
|
-
`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${
|
|
427
|
-
` CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`,
|
|
377
|
+
`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel},` +
|
|
378
|
+
` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`,
|
|
428
379
|
);
|
|
429
380
|
}
|
|
430
381
|
// Battery
|
|
431
|
-
this.BatteryLevel = Number(
|
|
432
|
-
if (this.BatteryLevel < 10) {
|
|
433
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
382
|
+
this.Battery.BatteryLevel = Number(serviceData.battery);
|
|
383
|
+
if (this.Battery.BatteryLevel < 10) {
|
|
384
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
434
385
|
} else {
|
|
435
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
386
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
436
387
|
}
|
|
437
388
|
this.debugLog(
|
|
438
|
-
`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
|
|
389
|
+
`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
|
|
390
|
+
+ ` StatusLowBattery: ${this.Battery.StatusLowBattery}`,
|
|
439
391
|
);
|
|
440
392
|
}
|
|
441
393
|
|
|
442
|
-
async openAPIparseStatus(): Promise<void> {
|
|
394
|
+
async openAPIparseStatus(deviceStatus: deviceStatus): Promise<void> {
|
|
443
395
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
444
396
|
// CurrentPosition
|
|
445
|
-
this.CurrentPosition = 100 - Number(
|
|
397
|
+
this.WindowCovering!.CurrentPosition = 100 - Number(deviceStatus.body.slidePosition);
|
|
446
398
|
await this.setMinMax();
|
|
447
|
-
this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
|
|
399
|
+
this.debugLog(`Curtain ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
448
400
|
if (this.setNewTarget) {
|
|
449
401
|
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Checking Status ...`);
|
|
450
402
|
}
|
|
451
403
|
|
|
452
|
-
if (this.setNewTarget &&
|
|
404
|
+
if (this.setNewTarget && deviceStatus.body.moving) {
|
|
453
405
|
await this.setMinMax();
|
|
454
|
-
if (Number(this.TargetPosition) > this.CurrentPosition) {
|
|
455
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.CurrentPosition} `);
|
|
456
|
-
this.PositionState = this.hap.Characteristic.PositionState.INCREASING;
|
|
457
|
-
this.
|
|
458
|
-
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} INCREASING
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
this.
|
|
462
|
-
this.
|
|
463
|
-
this.
|
|
406
|
+
if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
|
|
407
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
|
|
408
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
|
|
409
|
+
this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
|
|
410
|
+
this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} INCREASING`
|
|
411
|
+
+ ` PositionState: ${this.WindowCovering.PositionState}`);
|
|
412
|
+
} else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
|
|
413
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition} `);
|
|
414
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
|
|
415
|
+
this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
|
|
416
|
+
this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} DECREASING`
|
|
417
|
+
+ ` PositionState: ${this.WindowCovering.PositionState}`);
|
|
464
418
|
} else {
|
|
465
|
-
this.debugLog(`${this.device.deviceType}: ${this.CurrentPosition} Standby
|
|
466
|
-
|
|
467
|
-
this.
|
|
468
|
-
this.
|
|
419
|
+
this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} Standby,`
|
|
420
|
+
+ ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
421
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
|
|
422
|
+
this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
|
|
423
|
+
this.debugLog(`${this.device.deviceType}: ${this.WindowCovering.CurrentPosition} STOPPED`
|
|
424
|
+
+ ` PositionState: ${this.WindowCovering.PositionState}`);
|
|
469
425
|
}
|
|
470
426
|
} else {
|
|
471
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.CurrentPosition}`);
|
|
472
|
-
this.TargetPosition = this.CurrentPosition;
|
|
473
|
-
this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
|
|
427
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
428
|
+
this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
|
|
429
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
|
|
474
430
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Stopped`);
|
|
475
431
|
}
|
|
476
432
|
this.debugLog(
|
|
477
|
-
`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition},` +
|
|
478
|
-
` TargetPosition: ${this.TargetPosition}, PositionState: ${this.PositionState},`,
|
|
433
|
+
`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition},` +
|
|
434
|
+
` TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`,
|
|
479
435
|
);
|
|
480
436
|
|
|
481
437
|
// Brightness
|
|
482
438
|
if (!this.device.curtain?.hide_lightsensor) {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
switch (
|
|
439
|
+
const set_minLux = await this.minLux();
|
|
440
|
+
const set_maxLux = await this.maxLux();
|
|
441
|
+
switch (deviceStatus.body.brightness) {
|
|
486
442
|
case 'dim':
|
|
487
|
-
this.CurrentAmbientLightLevel =
|
|
443
|
+
this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
|
|
488
444
|
break;
|
|
489
445
|
case 'bright':
|
|
490
446
|
default:
|
|
491
|
-
this.CurrentAmbientLightLevel =
|
|
447
|
+
this.LightSensor!.CurrentAmbientLightLevel = set_maxLux;
|
|
492
448
|
}
|
|
493
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
449
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
450
|
+
+ ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
|
|
494
451
|
}
|
|
495
452
|
|
|
496
453
|
// BatteryLevel
|
|
497
|
-
this.BatteryLevel = Number(
|
|
498
|
-
if (this.BatteryLevel < 10) {
|
|
499
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
454
|
+
this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
|
|
455
|
+
if (this.Battery.BatteryLevel < 10) {
|
|
456
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
500
457
|
} else {
|
|
501
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
458
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
502
459
|
}
|
|
503
|
-
if (Number.isNaN(this.BatteryLevel)) {
|
|
504
|
-
this.BatteryLevel = 100;
|
|
460
|
+
if (Number.isNaN(this.Battery.BatteryLevel)) {
|
|
461
|
+
this.Battery.BatteryLevel = 100;
|
|
505
462
|
}
|
|
506
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel},`
|
|
507
|
-
+ ` StatusLowBattery: ${this.StatusLowBattery}`);
|
|
463
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
|
|
464
|
+
+ ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
508
465
|
|
|
509
|
-
//
|
|
510
|
-
|
|
511
|
-
this.
|
|
466
|
+
// Firmware Version
|
|
467
|
+
const version = deviceStatus.body.version?.toString();
|
|
468
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Firmware Version: ${version?.replace(/^V|-.*$/g, '')}`);
|
|
469
|
+
if (deviceStatus.body.version) {
|
|
470
|
+
this.accessory.context.version = version?.replace(/^V|-.*$/g, '');
|
|
471
|
+
this.accessory
|
|
472
|
+
.getService(this.hap.Service.AccessoryInformation)!
|
|
473
|
+
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, this.accessory.context.version)
|
|
474
|
+
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
475
|
+
.updateValue(this.accessory.context.version);
|
|
476
|
+
}
|
|
512
477
|
}
|
|
513
478
|
|
|
514
479
|
async refreshStatus(): Promise<void> {
|
|
@@ -538,118 +503,45 @@ export class Curtain {
|
|
|
538
503
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
539
504
|
this.getCustomBLEAddress(switchbot);
|
|
540
505
|
// Start to monitor advertisement packets
|
|
541
|
-
let model: string;
|
|
542
|
-
switch (this.device.configDeviceType) {
|
|
543
|
-
case 'Curtain3':
|
|
544
|
-
model = '{';
|
|
545
|
-
break;
|
|
546
|
-
default:
|
|
547
|
-
model = 'c';
|
|
548
|
-
}
|
|
549
506
|
(async () => {
|
|
550
507
|
// Start to monitor advertisement packets
|
|
551
|
-
await switchbot.startScan({
|
|
552
|
-
model: model,
|
|
553
|
-
id: this.device.bleMac,
|
|
554
|
-
});
|
|
508
|
+
await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
|
|
555
509
|
// Set an event handler
|
|
556
510
|
switchbot.onadvertisement = (ad: any) => {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
511
|
+
if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
|
|
512
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
|
|
513
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
|
|
560
514
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
561
|
-
this.BLE_Calibration = ad.serviceData.calibration;
|
|
562
|
-
this.BLE_BatteryLevel = ad.serviceData.battery;
|
|
563
|
-
this.BLE_InMotion = ad.serviceData.inMotion;
|
|
564
|
-
this.BLE_CurrentPosition = ad.serviceData.position;
|
|
565
|
-
this.BLE_CurrentAmbientLightLevel = ad.serviceData.lightLevel;
|
|
566
515
|
} else {
|
|
567
516
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
568
517
|
}
|
|
569
518
|
};
|
|
570
|
-
// Wait
|
|
519
|
+
// Wait 10 seconds
|
|
571
520
|
await switchbot.wait(this.scanDuration * 1000);
|
|
572
521
|
// Stop to monitor
|
|
573
522
|
await switchbot.stopScan();
|
|
574
523
|
// Update HomeKit
|
|
575
|
-
await this.BLEparseStatus();
|
|
524
|
+
await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
|
|
576
525
|
await this.updateHomeKitCharacteristics();
|
|
577
526
|
})();
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
/*if (switchbot !== false) {
|
|
581
|
-
switchbot
|
|
582
|
-
.startScan({
|
|
583
|
-
model: model,
|
|
584
|
-
id: this.device.bleMac,
|
|
585
|
-
})
|
|
586
|
-
.then(async () => {
|
|
587
|
-
// Set an event handler
|
|
588
|
-
switchbot.onadvertisement = async (ad: ad) => {
|
|
589
|
-
this.debugLog(
|
|
590
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac},` +
|
|
591
|
-
` BLE Address Found: ${ad.address}`,
|
|
592
|
-
);
|
|
593
|
-
this.BLE_Calibration = ad.serviceData.calibration;
|
|
594
|
-
this.BLE_BatteryLevel = ad.serviceData.battery;
|
|
595
|
-
this.BLE_InMotion = ad.serviceData.inMotion;
|
|
596
|
-
this.BLE_CurrentPosition = ad.serviceData.position;
|
|
597
|
-
this.BLE_CurrentAmbientLightLevel = ad.serviceData.lightLevel;
|
|
598
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
599
|
-
this.debugLog(
|
|
600
|
-
`${this.device.deviceType}: ${this.accessory.displayName} calibration: ${ad.serviceData.calibration}, ` +
|
|
601
|
-
`position: ${ad.serviceData.position}, lightLevel: ${ad.serviceData.lightLevel}, battery: ${ad.serviceData.battery}, ` +
|
|
602
|
-
`inMotion: ${ad.serviceData.inMotion}`,
|
|
603
|
-
);
|
|
604
|
-
|
|
605
|
-
if (ad.serviceData) {
|
|
606
|
-
this.BLE_IsConnected = true;
|
|
607
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
|
|
608
|
-
await this.stopScanning(switchbot);
|
|
609
|
-
} else {
|
|
610
|
-
this.BLE_IsConnected = false;
|
|
611
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} connected: ${this.BLE_IsConnected}`);
|
|
612
|
-
}
|
|
613
|
-
};
|
|
614
|
-
// Wait
|
|
615
|
-
return await sleep(this.scanDuration * 1000);
|
|
616
|
-
})
|
|
617
|
-
.then(async () => {
|
|
618
|
-
// Stop to monitor
|
|
619
|
-
await this.stopScanning(switchbot);
|
|
620
|
-
})
|
|
621
|
-
.catch(async (e: any) => {
|
|
622
|
-
this.apiError(e);
|
|
623
|
-
this.errorLog(
|
|
624
|
-
`${this.device.deviceType}: ${this.accessory.displayName} failed BLERefreshStatus with ${this.device.connectionType}` +
|
|
625
|
-
` Connection, Error Message: ${JSON.stringify(e.message)}`,
|
|
626
|
-
);
|
|
627
|
-
await this.BLERefreshConnection(switchbot);
|
|
628
|
-
});
|
|
629
|
-
} else {
|
|
527
|
+
if (switchbot === undefined) {
|
|
630
528
|
await this.BLERefreshConnection(switchbot);
|
|
631
|
-
}
|
|
529
|
+
}
|
|
632
530
|
}
|
|
633
531
|
|
|
634
532
|
async openAPIRefreshStatus(): Promise<void> {
|
|
635
533
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
636
534
|
try {
|
|
637
|
-
const { body, statusCode } = await
|
|
638
|
-
headers: this.platform.generateHeaders()
|
|
639
|
-
});
|
|
535
|
+
const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
|
|
536
|
+
`${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
|
|
640
537
|
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
|
|
641
538
|
const deviceStatus: any = await body.json();
|
|
642
539
|
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
|
|
643
540
|
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
|
|
644
541
|
if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
|
|
645
|
-
this.
|
|
542
|
+
this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
646
543
|
+ `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
|
|
647
|
-
this.
|
|
648
|
-
this.OpenAPI_InMotion = deviceStatus.body.moving;
|
|
649
|
-
this.OpenAPI_CurrentAmbientLightLevel = deviceStatus.body.brightness;
|
|
650
|
-
this.OpenAPI_BatteryLevel = deviceStatus.body.battery;
|
|
651
|
-
this.OpenAPI_FirmwareRevision = deviceStatus.body.version;
|
|
652
|
-
this.openAPIparseStatus();
|
|
544
|
+
this.openAPIparseStatus(deviceStatus);
|
|
653
545
|
this.updateHomeKitCharacteristics();
|
|
654
546
|
} else {
|
|
655
547
|
this.statusCode(statusCode);
|
|
@@ -688,7 +580,7 @@ export class Curtain {
|
|
|
688
580
|
|
|
689
581
|
async BLEpushChanges(): Promise<void> {
|
|
690
582
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
691
|
-
if (this.TargetPosition !== this.CurrentPosition) {
|
|
583
|
+
if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
|
|
692
584
|
const switchbot = await this.platform.connectBLE();
|
|
693
585
|
// Convert to BLE Address
|
|
694
586
|
this.device.bleMac = this.device
|
|
@@ -696,27 +588,29 @@ export class Curtain {
|
|
|
696
588
|
.join(':')
|
|
697
589
|
.toLowerCase();
|
|
698
590
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
699
|
-
this.
|
|
700
|
-
const adjustedMode =
|
|
701
|
-
this.debugLog(`${this.accessory.displayName} Mode: ${
|
|
591
|
+
const { setPositionMode, Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
|
|
592
|
+
const adjustedMode = setPositionMode === 1 ? 0x01 : 0xff;
|
|
593
|
+
this.debugLog(`${this.accessory.displayName} Mode: ${Mode}`);
|
|
702
594
|
if (switchbot !== false) {
|
|
703
595
|
try {
|
|
704
596
|
const device_list = await switchbot.discover({ model: 'c', quick: true, id: this.device.bleMac });
|
|
705
|
-
this.infoLog(`${this.accessory.displayName} Target Position: ${this.TargetPosition}`);
|
|
597
|
+
this.infoLog(`${this.accessory.displayName} Target Position: ${this.WindowCovering.TargetPosition}`);
|
|
706
598
|
|
|
707
|
-
await this.
|
|
708
|
-
max: this.
|
|
599
|
+
await this.retryBLE({
|
|
600
|
+
max: await this.maxRetryBLE(),
|
|
709
601
|
fn: async () => {
|
|
710
|
-
await device_list[0].runToPos(100 - Number(this.TargetPosition), adjustedMode);
|
|
602
|
+
await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode);
|
|
711
603
|
},
|
|
712
604
|
});
|
|
713
605
|
|
|
714
606
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
607
|
+
this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
608
|
+
+ `TargetPosition: ${this.WindowCovering.TargetPosition} sent over BLE, sent successfully`);
|
|
715
609
|
} catch (e) {
|
|
716
610
|
this.apiError(e);
|
|
717
611
|
this.errorLog(
|
|
718
612
|
`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}` +
|
|
719
|
-
|
|
613
|
+
` Connection, Error Message: ${JSON.stringify((e as Error).message)}`,
|
|
720
614
|
);
|
|
721
615
|
await this.BLEPushConnection();
|
|
722
616
|
throw new Error('Connection error');
|
|
@@ -728,54 +622,23 @@ export class Curtain {
|
|
|
728
622
|
} else {
|
|
729
623
|
this.debugLog(
|
|
730
624
|
`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges, CurrentPosition & TargetPosition Are the Same.` +
|
|
731
|
-
` CurrentPosition: ${this.CurrentPosition}, TargetPosition ${this.TargetPosition}`,
|
|
625
|
+
` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`,
|
|
732
626
|
);
|
|
733
627
|
}
|
|
734
628
|
}
|
|
735
629
|
|
|
736
|
-
async retry({ max, fn }: { max: number; fn: { (): any; (): Promise<any> } }): Promise<null> {
|
|
737
|
-
return fn().catch(async (e: any) => {
|
|
738
|
-
if (max === 0) {
|
|
739
|
-
throw e;
|
|
740
|
-
}
|
|
741
|
-
this.infoLog(e);
|
|
742
|
-
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Retrying`);
|
|
743
|
-
await sleep(1000);
|
|
744
|
-
return this.retry({ max: max - 1, fn });
|
|
745
|
-
});
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
maxRetry(): number {
|
|
749
|
-
if (this.device.maxRetry) {
|
|
750
|
-
return this.device.maxRetry;
|
|
751
|
-
} else {
|
|
752
|
-
return 5;
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
630
|
async openAPIpushChanges(): Promise<void> {
|
|
757
631
|
let command: string;
|
|
758
632
|
let parameter: string;
|
|
759
633
|
let commandType: string;
|
|
760
634
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
761
|
-
if (this.TargetPosition !== this.CurrentPosition || this.device.disableCaching) {
|
|
762
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Pushing ${this.TargetPosition}`);
|
|
763
|
-
const adjustedTargetPosition = 100 - Number(this.TargetPosition);
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
}
|
|
769
|
-
if (this.setPositionMode === '1') {
|
|
770
|
-
this.Mode = 'Silent Mode';
|
|
771
|
-
} else if (this.setPositionMode === '0') {
|
|
772
|
-
this.Mode = 'Performance Mode';
|
|
773
|
-
} else {
|
|
774
|
-
this.Mode = 'Default Mode';
|
|
775
|
-
}
|
|
776
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Mode: ${this.Mode}`);
|
|
777
|
-
const adjustedMode = this.setPositionMode || 'ff';
|
|
778
|
-
if (this.HoldPosition) {
|
|
635
|
+
if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition || this.device.disableCaching) {
|
|
636
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Pushing ${this.WindowCovering.TargetPosition}`);
|
|
637
|
+
const adjustedTargetPosition = 100 - Number(this.WindowCovering.TargetPosition);
|
|
638
|
+
const { setPositionMode, Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
|
|
639
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Mode: ${Mode}`);
|
|
640
|
+
const adjustedMode = setPositionMode || 'ff';
|
|
641
|
+
if (this.WindowCovering.HoldPosition) {
|
|
779
642
|
command = 'pause';
|
|
780
643
|
parameter = 'default';
|
|
781
644
|
commandType = 'command';
|
|
@@ -804,6 +667,8 @@ export class Curtain {
|
|
|
804
667
|
if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
|
|
805
668
|
this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
806
669
|
+ `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
|
|
670
|
+
this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
671
|
+
+ `request to SwitchBot API, body: ${JSON.stringify(deviceStatus)} sent successfully`);
|
|
807
672
|
} else {
|
|
808
673
|
this.statusCode(statusCode);
|
|
809
674
|
this.statusCode(deviceStatus.statusCode);
|
|
@@ -818,7 +683,7 @@ export class Curtain {
|
|
|
818
683
|
} else {
|
|
819
684
|
this.debugLog(
|
|
820
685
|
`${this.device.deviceType}: ${this.accessory.displayName} No OpenAPI Changes, CurrentPosition & TargetPosition Are the Same.` +
|
|
821
|
-
` CurrentPosition: ${this.CurrentPosition}, TargetPosition ${this.TargetPosition}`,
|
|
686
|
+
` CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition ${this.WindowCovering.TargetPosition}`,
|
|
822
687
|
);
|
|
823
688
|
}
|
|
824
689
|
}
|
|
@@ -827,50 +692,53 @@ export class Curtain {
|
|
|
827
692
|
* Handle requests to set the value of the "Target Position" characteristic
|
|
828
693
|
*/
|
|
829
694
|
async TargetPositionSet(value: CharacteristicValue): Promise<void> {
|
|
830
|
-
if (this.TargetPosition === this.accessory.context.TargetPosition) {
|
|
695
|
+
if (this.WindowCovering.TargetPosition === this.accessory.context.TargetPosition) {
|
|
831
696
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set TargetPosition: ${value}`);
|
|
832
697
|
} else {
|
|
833
698
|
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set TargetPosition: ${value}`);
|
|
834
699
|
}
|
|
835
700
|
|
|
836
701
|
// Set HoldPosition to false when TargetPosition is changed
|
|
837
|
-
this.HoldPosition = false;
|
|
838
|
-
this.
|
|
702
|
+
this.WindowCovering.HoldPosition = false;
|
|
703
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition);
|
|
839
704
|
|
|
840
|
-
this.TargetPosition = value;
|
|
705
|
+
this.WindowCovering.TargetPosition = value;
|
|
841
706
|
if (this.device.mqttURL) {
|
|
842
|
-
this.mqttPublish('TargetPosition', this.TargetPosition);
|
|
843
|
-
this.mqttPublish('HoldPosition', this.HoldPosition);
|
|
707
|
+
this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
|
|
708
|
+
this.mqttPublish('HoldPosition', this.WindowCovering.HoldPosition.toString()); // Convert boolean to string
|
|
844
709
|
}
|
|
845
710
|
|
|
846
711
|
await this.setMinMax();
|
|
847
|
-
if (value > this.CurrentPosition) {
|
|
848
|
-
this.PositionState = this.hap.Characteristic.PositionState.INCREASING;
|
|
712
|
+
if (value > this.WindowCovering.CurrentPosition) {
|
|
713
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
|
|
849
714
|
this.setNewTarget = true;
|
|
850
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value}
|
|
851
|
-
|
|
852
|
-
|
|
715
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value},`
|
|
716
|
+
+ ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
717
|
+
} else if (value < this.WindowCovering.CurrentPosition) {
|
|
718
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
|
|
853
719
|
this.setNewTarget = true;
|
|
854
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value}
|
|
720
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value},`
|
|
721
|
+
+ ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
855
722
|
} else {
|
|
856
|
-
this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
|
|
723
|
+
this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
|
|
857
724
|
this.setNewTarget = false;
|
|
858
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value}
|
|
725
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} value: ${value},`
|
|
726
|
+
+ ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
859
727
|
}
|
|
860
|
-
this.
|
|
861
|
-
this.
|
|
728
|
+
this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
|
|
729
|
+
this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
|
|
862
730
|
|
|
863
731
|
/**
|
|
864
732
|
* If Curtain movement time is short, the moving flag from backend is always false.
|
|
865
733
|
* The minimum time depends on the network control latency.
|
|
866
734
|
*/
|
|
867
735
|
clearTimeout(this.setNewTargetTimer);
|
|
868
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.
|
|
736
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateRate: ${this.deviceUpdateRate}`);
|
|
869
737
|
if (this.setNewTarget) {
|
|
870
738
|
this.setNewTargetTimer = setTimeout(() => {
|
|
871
739
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} setNewTarget ${this.setNewTarget} timeout`);
|
|
872
740
|
this.setNewTarget = false;
|
|
873
|
-
}, this.
|
|
741
|
+
}, this.deviceUpdateRate * 1000);
|
|
874
742
|
}
|
|
875
743
|
this.doCurtainUpdate.next();
|
|
876
744
|
}
|
|
@@ -880,153 +748,98 @@ export class Curtain {
|
|
|
880
748
|
*/
|
|
881
749
|
async HoldPositionSet(value: CharacteristicValue): Promise<void> {
|
|
882
750
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} HoldPosition: ${value}`);
|
|
883
|
-
this.HoldPosition = value;
|
|
751
|
+
this.WindowCovering.HoldPosition = value;
|
|
884
752
|
this.doCurtainUpdate.next();
|
|
885
753
|
}
|
|
886
754
|
|
|
887
755
|
async updateHomeKitCharacteristics(): Promise<void> {
|
|
888
756
|
await this.setMinMax();
|
|
889
|
-
if (this.CurrentPosition === undefined || Number.isNaN(this.CurrentPosition)) {
|
|
890
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.CurrentPosition}`);
|
|
757
|
+
if (this.WindowCovering.CurrentPosition === undefined || Number.isNaN(this.WindowCovering.CurrentPosition)) {
|
|
758
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
891
759
|
} else {
|
|
760
|
+
this.accessory.context.CurrentPosition = this.WindowCovering.CurrentPosition;
|
|
761
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, Number(this.WindowCovering.CurrentPosition));
|
|
762
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
763
|
+
+ ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
|
|
892
764
|
if (this.device.mqttURL) {
|
|
893
|
-
this.mqttPublish('CurrentPosition', this.CurrentPosition);
|
|
765
|
+
this.mqttPublish('CurrentPosition', this.WindowCovering.CurrentPosition.toString()); // Convert to string
|
|
894
766
|
}
|
|
895
|
-
this.accessory.context.CurrentPosition = this.CurrentPosition;
|
|
896
|
-
this.windowCoveringService.updateCharacteristic(this.hap.Characteristic.CurrentPosition, Number(this.CurrentPosition));
|
|
897
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic CurrentPosition: ${this.CurrentPosition}`);
|
|
898
767
|
}
|
|
899
|
-
if (this.PositionState === undefined) {
|
|
900
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.PositionState}`);
|
|
768
|
+
if (this.WindowCovering.PositionState === undefined) {
|
|
769
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} PositionState: ${this.WindowCovering.PositionState}`);
|
|
901
770
|
} else {
|
|
902
771
|
if (this.device.mqttURL) {
|
|
903
|
-
this.mqttPublish('PositionState', this.PositionState);
|
|
772
|
+
this.mqttPublish('PositionState', this.WindowCovering.PositionState.toString());
|
|
904
773
|
}
|
|
905
|
-
this.accessory.context.PositionState = this.PositionState;
|
|
906
|
-
this.
|
|
907
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic
|
|
774
|
+
this.accessory.context.PositionState = this.WindowCovering.PositionState;
|
|
775
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, Number(this.WindowCovering.PositionState));
|
|
776
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
777
|
+
+ ` PositionState: ${this.WindowCovering.PositionState}`);
|
|
908
778
|
}
|
|
909
|
-
if (this.TargetPosition === undefined || Number.isNaN(this.TargetPosition)) {
|
|
910
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.TargetPosition}`);
|
|
779
|
+
if (this.WindowCovering.TargetPosition === undefined || Number.isNaN(this.WindowCovering.TargetPosition)) {
|
|
780
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} TargetPosition: ${this.WindowCovering.TargetPosition}`);
|
|
911
781
|
} else {
|
|
912
782
|
if (this.device.mqttURL) {
|
|
913
|
-
this.mqttPublish('TargetPosition', this.TargetPosition);
|
|
783
|
+
this.mqttPublish('TargetPosition', this.WindowCovering.TargetPosition.toString());
|
|
914
784
|
}
|
|
915
|
-
this.accessory.context.TargetPosition = this.TargetPosition;
|
|
916
|
-
this.
|
|
917
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic
|
|
785
|
+
this.accessory.context.TargetPosition = this.WindowCovering.TargetPosition;
|
|
786
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, Number(this.WindowCovering.TargetPosition));
|
|
787
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
788
|
+
+ ` TargetPosition: ${this.WindowCovering.TargetPosition}`);
|
|
918
789
|
}
|
|
919
|
-
if (this.HoldPosition === undefined) {
|
|
920
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} HoldPosition: ${this.HoldPosition}`);
|
|
790
|
+
if (this.WindowCovering.HoldPosition === undefined) {
|
|
791
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} HoldPosition: ${this.WindowCovering.HoldPosition}`);
|
|
921
792
|
} else {
|
|
922
793
|
if (this.device.mqttURL) {
|
|
923
|
-
this.mqttPublish('HoldPosition', this.HoldPosition);
|
|
794
|
+
this.mqttPublish('HoldPosition', this.WindowCovering.HoldPosition.toString());
|
|
924
795
|
}
|
|
925
|
-
this.accessory.context.HoldPosition = this.HoldPosition;
|
|
926
|
-
this.
|
|
927
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic
|
|
796
|
+
this.accessory.context.HoldPosition = this.WindowCovering.HoldPosition;
|
|
797
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition);
|
|
798
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
799
|
+
+ ` HoldPosition: ${this.WindowCovering.HoldPosition}`);
|
|
928
800
|
}
|
|
929
801
|
if (!this.device.curtain?.hide_lightsensor) {
|
|
930
|
-
if (this.CurrentAmbientLightLevel === undefined || Number.isNaN(this.CurrentAmbientLightLevel)) {
|
|
931
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}
|
|
802
|
+
if (this.LightSensor!.CurrentAmbientLightLevel === undefined || Number.isNaN(this.LightSensor!.CurrentAmbientLightLevel)) {
|
|
803
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
|
|
804
|
+
+ ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
|
|
932
805
|
} else {
|
|
933
806
|
if (this.device.mqttURL) {
|
|
934
|
-
this.mqttPublish('CurrentAmbientLightLevel', this.CurrentAmbientLightLevel);
|
|
807
|
+
this.mqttPublish('CurrentAmbientLightLevel', this.LightSensor!.CurrentAmbientLightLevel.toString());
|
|
935
808
|
}
|
|
936
|
-
this.accessory.context.CurrentAmbientLightLevel = this.CurrentAmbientLightLevel;
|
|
937
|
-
this.
|
|
809
|
+
this.accessory.context.CurrentAmbientLightLevel = this.LightSensor!.CurrentAmbientLightLevel;
|
|
810
|
+
this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor!.CurrentAmbientLightLevel);
|
|
938
811
|
this.debugLog(
|
|
939
812
|
`${this.device.deviceType}: ${this.accessory.displayName}` +
|
|
940
|
-
` updateCharacteristic CurrentAmbientLightLevel: ${this.CurrentAmbientLightLevel}`,
|
|
813
|
+
` updateCharacteristic CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`,
|
|
941
814
|
);
|
|
942
815
|
if (this.device.history) {
|
|
943
816
|
this.historyService?.addEntry({
|
|
944
817
|
time: Math.round(new Date().valueOf() / 1000),
|
|
945
|
-
lux: this.CurrentAmbientLightLevel,
|
|
818
|
+
lux: this.LightSensor!.CurrentAmbientLightLevel,
|
|
946
819
|
});
|
|
947
820
|
}
|
|
948
821
|
}
|
|
949
822
|
}
|
|
950
|
-
if (this.BatteryLevel === undefined) {
|
|
951
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
823
|
+
if (this.Battery.BatteryLevel === undefined) {
|
|
824
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
952
825
|
} else {
|
|
953
826
|
if (this.device.mqttURL) {
|
|
954
|
-
this.mqttPublish('BatteryLevel', this.BatteryLevel);
|
|
827
|
+
this.mqttPublish('BatteryLevel', this.Battery.BatteryLevel.toString());
|
|
955
828
|
}
|
|
956
|
-
this.accessory.context.BatteryLevel = this.BatteryLevel;
|
|
957
|
-
this.
|
|
958
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
|
|
829
|
+
this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
|
|
830
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
|
|
831
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
959
832
|
}
|
|
960
|
-
if (this.StatusLowBattery === undefined) {
|
|
961
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
833
|
+
if (this.Battery.StatusLowBattery === undefined) {
|
|
834
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
962
835
|
} else {
|
|
963
836
|
if (this.device.mqttURL) {
|
|
964
|
-
this.mqttPublish('StatusLowBattery', this.StatusLowBattery);
|
|
965
|
-
}
|
|
966
|
-
this.accessory.context.StatusLowBattery = this.StatusLowBattery;
|
|
967
|
-
this.batteryService?.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.StatusLowBattery);
|
|
968
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
/*
|
|
973
|
-
* Publish MQTT message for topics of
|
|
974
|
-
* 'homebridge-switchbot/curtain/xx:xx:xx:xx:xx:xx'
|
|
975
|
-
*/
|
|
976
|
-
mqttPublish(topic: string, message: any) {
|
|
977
|
-
const mac = this.device.deviceId
|
|
978
|
-
?.toLowerCase()
|
|
979
|
-
.match(/[\s\S]{1,2}/g)
|
|
980
|
-
?.join(':');
|
|
981
|
-
const options = this.device.mqttPubOptions || {};
|
|
982
|
-
this.mqttClient?.publish(`homebridge-switchbot/curtain/${mac}/${topic}`, `${message}`, options);
|
|
983
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT message: ${topic}/${message} options:${JSON.stringify(options)}`);
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
/*
|
|
987
|
-
* Setup MQTT hadler if URL is specified.
|
|
988
|
-
*/
|
|
989
|
-
async setupMqtt(device: device & devicesConfig): Promise<void> {
|
|
990
|
-
if (device.mqttURL) {
|
|
991
|
-
try {
|
|
992
|
-
const { connectAsync } = asyncmqtt;
|
|
993
|
-
this.mqttClient = await connectAsync(device.mqttURL, device.mqttOptions || {});
|
|
994
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} MQTT connection has been established successfully.`);
|
|
995
|
-
this.mqttClient.on('error', (e: Error) => {
|
|
996
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to publish MQTT messages. ${e}`);
|
|
997
|
-
});
|
|
998
|
-
} catch (e) {
|
|
999
|
-
this.mqttClient = null;
|
|
1000
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Failed to establish MQTT connection. ${e}`);
|
|
837
|
+
this.mqttPublish('StatusLowBattery', this.Battery.StatusLowBattery.toString());
|
|
1001
838
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
switchbot.stopScan();
|
|
1007
|
-
if (this.BLE_IsConnected) {
|
|
1008
|
-
await this.BLEparseStatus();
|
|
1009
|
-
await this.updateHomeKitCharacteristics();
|
|
1010
|
-
} else {
|
|
1011
|
-
await this.BLERefreshConnection(switchbot);
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
async getCustomBLEAddress(switchbot: any) {
|
|
1016
|
-
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
1017
|
-
(async () => {
|
|
1018
|
-
// Start to monitor advertisement packets
|
|
1019
|
-
await switchbot.startScan({
|
|
1020
|
-
model: 'c',
|
|
1021
|
-
});
|
|
1022
|
-
// Set an event handler
|
|
1023
|
-
switchbot.onadvertisement = (ad: any) => {
|
|
1024
|
-
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} ad: ${JSON.stringify(ad, null, ' ')}`);
|
|
1025
|
-
};
|
|
1026
|
-
await sleep(10000);
|
|
1027
|
-
// Stop to monitor
|
|
1028
|
-
switchbot.stopScan();
|
|
1029
|
-
})();
|
|
839
|
+
this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
|
|
840
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
|
|
841
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
842
|
+
+ ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
1030
843
|
}
|
|
1031
844
|
}
|
|
1032
845
|
|
|
@@ -1046,364 +859,100 @@ export class Curtain {
|
|
|
1046
859
|
}
|
|
1047
860
|
}
|
|
1048
861
|
|
|
1049
|
-
async
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
862
|
+
async setPerformance() {
|
|
863
|
+
let setPositionMode: number;
|
|
864
|
+
let Mode: string;
|
|
865
|
+
if (Number(this.WindowCovering.TargetPosition) > 50) {
|
|
866
|
+
if (this.device.blindTilt?.setOpenMode === '1') {
|
|
867
|
+
setPositionMode = 1;
|
|
868
|
+
Mode = 'Silent Mode';
|
|
869
|
+
} else if (this.device.blindTilt?.setOpenMode === '0') {
|
|
870
|
+
setPositionMode = 0;
|
|
871
|
+
Mode = 'Performance Mode';
|
|
1054
872
|
} else {
|
|
1055
|
-
|
|
1056
|
-
|
|
873
|
+
setPositionMode = 0;
|
|
874
|
+
Mode = 'Default Mode';
|
|
1057
875
|
}
|
|
1058
876
|
} else {
|
|
1059
|
-
if (this.device.
|
|
1060
|
-
|
|
1061
|
-
|
|
877
|
+
if (this.device.blindTilt?.setCloseMode === '1') {
|
|
878
|
+
setPositionMode = 1;
|
|
879
|
+
Mode = 'Silent Mode';
|
|
880
|
+
} else if (this.device.blindTilt?.setOpenMode === '0') {
|
|
881
|
+
setPositionMode = 0;
|
|
882
|
+
Mode = 'Performance Mode';
|
|
1062
883
|
} else {
|
|
1063
|
-
|
|
1064
|
-
|
|
884
|
+
setPositionMode = 0;
|
|
885
|
+
Mode = 'Default Mode';
|
|
1065
886
|
}
|
|
1066
887
|
}
|
|
888
|
+
return { setPositionMode, Mode };
|
|
1067
889
|
}
|
|
1068
890
|
|
|
1069
891
|
async setMinMax(): Promise<void> {
|
|
1070
892
|
if (this.device.curtain?.set_min) {
|
|
1071
|
-
if (Number(this.CurrentPosition) <= this.device.curtain?.set_min) {
|
|
1072
|
-
this.CurrentPosition = 0;
|
|
893
|
+
if (Number(this.WindowCovering.CurrentPosition) <= this.device.curtain?.set_min) {
|
|
894
|
+
this.WindowCovering.CurrentPosition = 0;
|
|
1073
895
|
}
|
|
1074
896
|
}
|
|
1075
897
|
if (this.device.curtain?.set_max) {
|
|
1076
|
-
if (Number(this.CurrentPosition) >= this.device.curtain?.set_max) {
|
|
1077
|
-
this.CurrentPosition = 100;
|
|
898
|
+
if (Number(this.WindowCovering.CurrentPosition) >= this.device.curtain?.set_max) {
|
|
899
|
+
this.WindowCovering.CurrentPosition = 100;
|
|
1078
900
|
}
|
|
1079
901
|
}
|
|
1080
902
|
if (this.device.history) {
|
|
1081
903
|
const motion = this.accessory.getService(this.hap.Service.MotionSensor);
|
|
1082
|
-
const state = Number(this.CurrentPosition) > 0 ? 1 : 0;
|
|
904
|
+
const state = Number(this.WindowCovering.CurrentPosition) > 0 ? 1 : 0;
|
|
1083
905
|
motion?.updateCharacteristic(this.hap.Characteristic.MotionDetected, state);
|
|
1084
906
|
}
|
|
1085
907
|
}
|
|
1086
908
|
|
|
1087
909
|
minStep(device: device & devicesConfig): number {
|
|
910
|
+
let set_minStep: number;
|
|
1088
911
|
if (device.curtain?.set_minStep) {
|
|
1089
|
-
|
|
912
|
+
set_minStep = device.curtain?.set_minStep;
|
|
1090
913
|
} else {
|
|
1091
|
-
|
|
914
|
+
set_minStep = 1;
|
|
1092
915
|
}
|
|
1093
|
-
return
|
|
916
|
+
return set_minStep;
|
|
1094
917
|
}
|
|
1095
918
|
|
|
1096
|
-
minLux(): number {
|
|
919
|
+
async minLux(): Promise<number> {
|
|
920
|
+
let set_minLux: number;
|
|
1097
921
|
if (this.device.curtain?.set_minLux) {
|
|
1098
|
-
|
|
922
|
+
set_minLux = this.device.curtain?.set_minLux;
|
|
1099
923
|
} else {
|
|
1100
|
-
|
|
924
|
+
set_minLux = 1;
|
|
1101
925
|
}
|
|
1102
|
-
return
|
|
926
|
+
return set_minLux;
|
|
1103
927
|
}
|
|
1104
928
|
|
|
1105
|
-
maxLux(): number {
|
|
929
|
+
async maxLux(): Promise<number> {
|
|
930
|
+
let set_maxLux: number;
|
|
1106
931
|
if (this.device.curtain?.set_maxLux) {
|
|
1107
|
-
|
|
1108
|
-
} else {
|
|
1109
|
-
this.set_maxLux = 6001;
|
|
1110
|
-
}
|
|
1111
|
-
return this.set_maxLux;
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
async scan(device: device & devicesConfig): Promise<void> {
|
|
1115
|
-
if (device.scanDuration) {
|
|
1116
|
-
if (this.updateRate > device.scanDuration) {
|
|
1117
|
-
this.scanDuration = this.updateRate;
|
|
1118
|
-
if (this.BLE) {
|
|
1119
|
-
this.warnLog(
|
|
1120
|
-
`${this.device.deviceType}: ` +
|
|
1121
|
-
`${this.accessory.displayName} scanDuration is less than updateRate, overriding scanDuration with updateRate`,
|
|
1122
|
-
);
|
|
1123
|
-
}
|
|
1124
|
-
} else {
|
|
1125
|
-
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
1126
|
-
}
|
|
1127
|
-
if (this.BLE) {
|
|
1128
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
1129
|
-
}
|
|
932
|
+
set_maxLux = this.device.curtain?.set_maxLux;
|
|
1130
933
|
} else {
|
|
1131
|
-
|
|
1132
|
-
this.scanDuration = this.updateRate;
|
|
1133
|
-
} else {
|
|
1134
|
-
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
1135
|
-
}
|
|
1136
|
-
if (this.BLE) {
|
|
1137
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
async statusCode(statusCode: number): Promise<void> {
|
|
1143
|
-
switch (statusCode) {
|
|
1144
|
-
case 151:
|
|
1145
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command not supported by this deviceType, statusCode: ${statusCode}`);
|
|
1146
|
-
break;
|
|
1147
|
-
case 152:
|
|
1148
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device not found, statusCode: ${statusCode}`);
|
|
1149
|
-
break;
|
|
1150
|
-
case 160:
|
|
1151
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Command is not supported, statusCode: ${statusCode}`);
|
|
1152
|
-
break;
|
|
1153
|
-
case 161:
|
|
1154
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Device is offline, statusCode: ${statusCode}`);
|
|
1155
|
-
this.offlineOff();
|
|
1156
|
-
break;
|
|
1157
|
-
case 171:
|
|
1158
|
-
this.errorLog(
|
|
1159
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Hub Device is offline, statusCode: ${statusCode}. ` +
|
|
1160
|
-
`Hub: ${this.device.hubDeviceId}`,
|
|
1161
|
-
);
|
|
1162
|
-
this.offlineOff();
|
|
1163
|
-
break;
|
|
1164
|
-
case 190:
|
|
1165
|
-
this.errorLog(
|
|
1166
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,` +
|
|
1167
|
-
` Or command format is invalid, statusCode: ${statusCode}`,
|
|
1168
|
-
);
|
|
1169
|
-
break;
|
|
1170
|
-
case 100:
|
|
1171
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Command successfully sent, statusCode: ${statusCode}`);
|
|
1172
|
-
break;
|
|
1173
|
-
case 200:
|
|
1174
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Request successful, statusCode: ${statusCode}`);
|
|
1175
|
-
break;
|
|
1176
|
-
case 400:
|
|
1177
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Bad Request, The client has issued an invalid request. `
|
|
1178
|
-
+ `This is commonly used to specify validation errors in a request payload, statusCode: ${statusCode}`);
|
|
1179
|
-
break;
|
|
1180
|
-
case 401:
|
|
1181
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unauthorized, Authorization for the API is required, `
|
|
1182
|
-
+ `but the request has not been authenticated, statusCode: ${statusCode}`);
|
|
1183
|
-
break;
|
|
1184
|
-
case 403:
|
|
1185
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not `
|
|
1186
|
-
+ `have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
|
|
1187
|
-
break;
|
|
1188
|
-
case 404:
|
|
1189
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Found, Specifies the requested path does not exist, `
|
|
1190
|
-
+ `statusCode: ${statusCode}`);
|
|
1191
|
-
break;
|
|
1192
|
-
case 406:
|
|
1193
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Not Acceptable, The client has requested a MIME type via `
|
|
1194
|
-
+ `the Accept header for a value not supported by the server, statusCode: ${statusCode}`);
|
|
1195
|
-
break;
|
|
1196
|
-
case 415:
|
|
1197
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unsupported Media Type, The client has defined a contentType `
|
|
1198
|
-
+ `header that is not supported by the server, statusCode: ${statusCode}`);
|
|
1199
|
-
break;
|
|
1200
|
-
case 422:
|
|
1201
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Unprocessable Entity, The client has made a valid request, `
|
|
1202
|
-
+ `but the server cannot process it. This is often used for APIs for which certain limits have been exceeded, statusCode: ${statusCode}`);
|
|
1203
|
-
break;
|
|
1204
|
-
case 429:
|
|
1205
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Too Many Requests, The client has exceeded the number of `
|
|
1206
|
-
+ `requests allowed for a given time window, statusCode: ${statusCode}`);
|
|
1207
|
-
break;
|
|
1208
|
-
case 500:
|
|
1209
|
-
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} Internal Server Error, An unexpected error on the SmartThings `
|
|
1210
|
-
+ `servers has occurred. These errors should be rare, statusCode: ${statusCode}`);
|
|
1211
|
-
break;
|
|
1212
|
-
default:
|
|
1213
|
-
this.infoLog(
|
|
1214
|
-
`${this.device.deviceType}: ${this.accessory.displayName} Unknown statusCode: ` +
|
|
1215
|
-
`${statusCode}, Submit Bugs Here: ' + 'https://tinyurl.com/SwitchBotBug`,
|
|
1216
|
-
);
|
|
934
|
+
set_maxLux = 6001;
|
|
1217
935
|
}
|
|
936
|
+
return set_maxLux;
|
|
1218
937
|
}
|
|
1219
938
|
|
|
1220
939
|
async offlineOff(): Promise<void> {
|
|
1221
940
|
if (this.device.offline) {
|
|
1222
|
-
|
|
1223
|
-
|
|
941
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
|
|
942
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
|
|
943
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
|
|
1224
944
|
}
|
|
1225
945
|
}
|
|
1226
946
|
|
|
1227
947
|
async apiError(e: any): Promise<void> {
|
|
1228
|
-
this.
|
|
1229
|
-
this.
|
|
1230
|
-
this.
|
|
948
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
|
|
949
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
|
|
950
|
+
this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
|
|
1231
951
|
if (!this.device.curtain?.hide_lightsensor) {
|
|
1232
|
-
this.
|
|
952
|
+
this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
|
|
1233
953
|
}
|
|
1234
|
-
this.
|
|
1235
|
-
this.
|
|
954
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
|
|
955
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
|
|
1236
956
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
1237
957
|
}
|
|
1238
|
-
|
|
1239
|
-
async deviceContext() {
|
|
1240
|
-
if (this.accessory.context.CurrentPosition === undefined) {
|
|
1241
|
-
this.CurrentPosition = 0;
|
|
1242
|
-
} else {
|
|
1243
|
-
this.CurrentPosition = this.accessory.context.CurrentPosition;
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
if (this.accessory.context.TargetPosition === undefined) {
|
|
1247
|
-
this.TargetPosition = 0;
|
|
1248
|
-
} else {
|
|
1249
|
-
this.TargetPosition = this.accessory.context.TargetPosition;
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
if (this.accessory.context.PositionState === undefined) {
|
|
1253
|
-
this.PositionState = this.hap.Characteristic.PositionState.STOPPED;
|
|
1254
|
-
} else {
|
|
1255
|
-
this.PositionState = this.accessory.context.PositionState;
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
if (!this.device.curtain?.hide_lightsensor) {
|
|
1259
|
-
if (this.accessory.context.CurrentAmbientLightLevel !== undefined) {
|
|
1260
|
-
this.CurrentAmbientLightLevel = this.accessory.context.CurrentAmbientLightLevel;
|
|
1261
|
-
}
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
if (this.BLE) {
|
|
1265
|
-
if (this.accessory.context.BatteryLevel === undefined) {
|
|
1266
|
-
this.BatteryLevel = 100;
|
|
1267
|
-
} else {
|
|
1268
|
-
this.BatteryLevel = this.accessory.context.BatteryLevel;
|
|
1269
|
-
}
|
|
1270
|
-
if (this.accessory.context.StatusLowBattery === undefined) {
|
|
1271
|
-
this.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
1272
|
-
} else {
|
|
1273
|
-
this.StatusLowBattery = this.accessory.context.StatusLowBattery;
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
if (this.device.history === true) {
|
|
1278
|
-
// initialize when this accessory is newly created.
|
|
1279
|
-
this.accessory.context.lastActivation = this.accessory.context.lastActivation ?? 0;
|
|
1280
|
-
} else {
|
|
1281
|
-
// removes cached values if history is turned off
|
|
1282
|
-
delete this.accessory.context.lastActivation;
|
|
1283
|
-
}
|
|
1284
|
-
if (this.FirmwareRevision === undefined) {
|
|
1285
|
-
this.FirmwareRevision = this.platform.version;
|
|
1286
|
-
this.accessory.context.FirmwareRevision = this.FirmwareRevision;
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
1291
|
-
// refreshRate
|
|
1292
|
-
if (device.refreshRate) {
|
|
1293
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
1294
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1295
|
-
} else if (this.platform.config.options!.refreshRate) {
|
|
1296
|
-
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
1297
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
1298
|
-
}
|
|
1299
|
-
// updateRate
|
|
1300
|
-
if (device?.curtain?.updateRate) {
|
|
1301
|
-
this.updateRate = device?.curtain?.updateRate;
|
|
1302
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Curtain updateRate: ${this.updateRate}`);
|
|
1303
|
-
} else {
|
|
1304
|
-
this.updateRate = 7;
|
|
1305
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Default Curtain updateRate: ${this.updateRate}`);
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
async deviceConfig(device: device & devicesConfig): Promise<void> {
|
|
1310
|
-
let config = {};
|
|
1311
|
-
if (device.curtain) {
|
|
1312
|
-
config = device.curtain;
|
|
1313
|
-
}
|
|
1314
|
-
if (device.connectionType !== undefined) {
|
|
1315
|
-
config['connectionType'] = device.connectionType;
|
|
1316
|
-
}
|
|
1317
|
-
if (device.external !== undefined) {
|
|
1318
|
-
config['external'] = device.external;
|
|
1319
|
-
}
|
|
1320
|
-
if (device.mqttURL !== undefined) {
|
|
1321
|
-
config['mqttURL'] = device.mqttURL;
|
|
1322
|
-
}
|
|
1323
|
-
if (device.logging !== undefined) {
|
|
1324
|
-
config['logging'] = device.logging;
|
|
1325
|
-
}
|
|
1326
|
-
if (device.refreshRate !== undefined) {
|
|
1327
|
-
config['refreshRate'] = device.refreshRate;
|
|
1328
|
-
}
|
|
1329
|
-
if (device.scanDuration !== undefined) {
|
|
1330
|
-
config['scanDuration'] = device.scanDuration;
|
|
1331
|
-
}
|
|
1332
|
-
if (device.maxRetry !== undefined) {
|
|
1333
|
-
config['maxRetry'] = device.maxRetry;
|
|
1334
|
-
}
|
|
1335
|
-
if (device.webhook !== undefined) {
|
|
1336
|
-
config['webhook'] = device.webhook;
|
|
1337
|
-
}
|
|
1338
|
-
if (Object.entries(config).length !== 0) {
|
|
1339
|
-
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
1340
|
-
}
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
async deviceLogs(device: device & devicesConfig): Promise<void> {
|
|
1344
|
-
if (this.platform.debugMode) {
|
|
1345
|
-
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
1346
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
1347
|
-
} else if (device.logging) {
|
|
1348
|
-
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
1349
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
1350
|
-
} else if (this.platform.config.options?.logging) {
|
|
1351
|
-
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
1352
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
1353
|
-
} else {
|
|
1354
|
-
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
1355
|
-
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
/**
|
|
1360
|
-
* Logging for Device
|
|
1361
|
-
*/
|
|
1362
|
-
infoLog(...log: any[]): void {
|
|
1363
|
-
if (this.enablingDeviceLogging()) {
|
|
1364
|
-
this.platform.log.info(String(...log));
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
warnLog(...log: any[]): void {
|
|
1369
|
-
if (this.enablingDeviceLogging()) {
|
|
1370
|
-
this.platform.log.warn(String(...log));
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
debugWarnLog(...log: any[]): void {
|
|
1375
|
-
if (this.enablingDeviceLogging()) {
|
|
1376
|
-
if (this.deviceLogging?.includes('debug')) {
|
|
1377
|
-
this.platform.log.warn('[DEBUG]', String(...log));
|
|
1378
|
-
}
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
errorLog(...log: any[]): void {
|
|
1383
|
-
if (this.enablingDeviceLogging()) {
|
|
1384
|
-
this.platform.log.error(String(...log));
|
|
1385
|
-
}
|
|
1386
|
-
}
|
|
1387
|
-
|
|
1388
|
-
debugErrorLog(...log: any[]): void {
|
|
1389
|
-
if (this.enablingDeviceLogging()) {
|
|
1390
|
-
if (this.deviceLogging?.includes('debug')) {
|
|
1391
|
-
this.platform.log.error('[DEBUG]', String(...log));
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
debugLog(...log: any[]): void {
|
|
1397
|
-
if (this.enablingDeviceLogging()) {
|
|
1398
|
-
if (this.deviceLogging === 'debug') {
|
|
1399
|
-
this.platform.log.info('[DEBUG]', String(...log));
|
|
1400
|
-
} else {
|
|
1401
|
-
this.platform.log.debug(String(...log));
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
enablingDeviceLogging(): boolean {
|
|
1407
|
-
return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
|
|
1408
|
-
}
|
|
1409
958
|
}
|