@switchbot/homebridge-switchbot 3.5.0-beta.28 → 3.5.0-beta.29
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 +1 -0
- package/config.schema.json +67 -1
- package/dist/device/blindtilt.d.ts.map +1 -1
- package/dist/device/blindtilt.js +8 -3
- package/dist/device/blindtilt.js.map +1 -1
- package/dist/device/bot.d.ts.map +1 -1
- package/dist/device/bot.js +8 -3
- package/dist/device/bot.js.map +1 -1
- package/dist/device/ceilinglight.d.ts.map +1 -1
- package/dist/device/ceilinglight.js +31 -5
- package/dist/device/ceilinglight.js.map +1 -1
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +23 -4
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/contact.d.ts.map +1 -1
- package/dist/device/contact.js +7 -2
- package/dist/device/contact.js.map +1 -1
- package/dist/device/curtain.d.ts.map +1 -1
- package/dist/device/curtain.js +7 -2
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/device.d.ts.map +1 -1
- package/dist/device/device.js +13 -3
- package/dist/device/device.js.map +1 -1
- package/dist/device/fan.d.ts +51 -0
- package/dist/device/fan.d.ts.map +1 -0
- package/dist/device/fan.js +499 -0
- package/dist/device/fan.js.map +1 -0
- package/dist/device/hub.d.ts.map +1 -1
- package/dist/device/hub.js +32 -24
- package/dist/device/hub.js.map +1 -1
- package/dist/device/humidifier.d.ts.map +1 -1
- package/dist/device/humidifier.js +7 -2
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/iosensor.d.ts.map +1 -1
- package/dist/device/iosensor.js +25 -17
- package/dist/device/iosensor.js.map +1 -1
- package/dist/device/lightstrip.d.ts.map +1 -1
- package/dist/device/lightstrip.js +41 -4
- package/dist/device/lightstrip.js.map +1 -1
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +7 -2
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +25 -17
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts.map +1 -1
- package/dist/device/meterplus.js +7 -2
- package/dist/device/meterplus.js.map +1 -1
- package/dist/device/motion.d.ts.map +1 -1
- package/dist/device/motion.js +7 -2
- package/dist/device/motion.js.map +1 -1
- package/dist/device/plug.d.ts.map +1 -1
- package/dist/device/plug.js +7 -2
- package/dist/device/plug.js.map +1 -1
- package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/device/robotvacuumcleaner.js +8 -3
- package/dist/device/robotvacuumcleaner.js.map +1 -1
- package/dist/device/waterdetector.d.ts.map +1 -1
- package/dist/device/waterdetector.js +14 -7
- package/dist/device/waterdetector.js.map +1 -1
- package/dist/irdevice/airconditioner.d.ts.map +1 -1
- package/dist/irdevice/airconditioner.js +2 -1
- package/dist/irdevice/airconditioner.js.map +1 -1
- package/dist/irdevice/airpurifier.d.ts.map +1 -1
- package/dist/irdevice/airpurifier.js +2 -1
- package/dist/irdevice/airpurifier.js.map +1 -1
- package/dist/irdevice/camera.d.ts.map +1 -1
- package/dist/irdevice/camera.js +2 -1
- package/dist/irdevice/camera.js.map +1 -1
- package/dist/irdevice/fan.d.ts +1 -1
- package/dist/irdevice/fan.d.ts.map +1 -1
- package/dist/irdevice/fan.js +3 -2
- package/dist/irdevice/fan.js.map +1 -1
- package/dist/irdevice/irdevice.js.map +1 -1
- package/dist/irdevice/light.d.ts.map +1 -1
- package/dist/irdevice/light.js +2 -1
- package/dist/irdevice/light.js.map +1 -1
- package/dist/irdevice/other.d.ts.map +1 -1
- package/dist/irdevice/other.js +2 -1
- package/dist/irdevice/other.js.map +1 -1
- package/dist/irdevice/tv.d.ts.map +1 -1
- package/dist/irdevice/tv.js +2 -1
- package/dist/irdevice/tv.js.map +1 -1
- package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
- package/dist/irdevice/vacuumcleaner.js +2 -1
- package/dist/irdevice/vacuumcleaner.js.map +1 -1
- package/dist/irdevice/waterheater.d.ts.map +1 -1
- package/dist/irdevice/waterheater.js +2 -1
- package/dist/irdevice/waterheater.js.map +1 -1
- package/dist/platform.d.ts +2 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +68 -5
- package/dist/platform.js.map +1 -1
- package/dist/settings.d.ts +22 -4
- package/dist/settings.d.ts.map +1 -1
- package/dist/utils.d.ts +10 -5
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +23 -9
- package/dist/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/device/blindtilt.ts +8 -3
- package/src/device/bot.ts +8 -3
- package/src/device/ceilinglight.ts +31 -5
- package/src/device/colorbulb.ts +25 -6
- package/src/device/contact.ts +9 -4
- package/src/device/curtain.ts +21 -16
- package/src/device/device.ts +13 -3
- package/src/device/fan.ts +548 -0
- package/src/device/hub.ts +30 -22
- package/src/device/humidifier.ts +8 -3
- package/src/device/iosensor.ts +27 -19
- package/src/device/lightstrip.ts +40 -6
- package/src/device/lock.ts +12 -7
- package/src/device/meter.ts +29 -21
- package/src/device/meterplus.ts +11 -6
- package/src/device/motion.ts +8 -3
- package/src/device/plug.ts +8 -3
- package/src/device/robotvacuumcleaner.ts +13 -8
- package/src/device/waterdetector.ts +14 -7
- package/src/irdevice/airconditioner.ts +4 -3
- package/src/irdevice/airpurifier.ts +4 -3
- package/src/irdevice/camera.ts +3 -2
- package/src/irdevice/fan.ts +3 -2
- package/src/irdevice/irdevice.ts +1 -1
- package/src/irdevice/light.ts +2 -1
- package/src/irdevice/other.ts +46 -45
- package/src/irdevice/tv.ts +2 -1
- package/src/irdevice/vacuumcleaner.ts +2 -1
- package/src/irdevice/waterheater.ts +2 -1
- package/src/platform.ts +71 -5
- package/src/settings.ts +34 -9
- package/src/utils.ts +24 -9
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
2
|
+
/* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* plug.ts: @switchbot/homebridge-switchbot.
|
|
5
|
+
*/
|
|
6
|
+
import { request } from 'undici';
|
|
7
|
+
import { deviceBase } from './device.js';
|
|
8
|
+
import { SwitchBotPlatform } from '../platform.js';
|
|
9
|
+
import { Subject, debounceTime, interval, skipWhile, take, tap } from 'rxjs';
|
|
10
|
+
import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
|
|
11
|
+
import { device, devicesConfig, serviceData, deviceStatus, Devices } from '../settings.js';
|
|
12
|
+
|
|
13
|
+
export class Fan extends deviceBase {
|
|
14
|
+
// Services
|
|
15
|
+
private Fan: {
|
|
16
|
+
Service: Service;
|
|
17
|
+
Active: CharacteristicValue;
|
|
18
|
+
SwingMode: CharacteristicValue;
|
|
19
|
+
RotationSpeed: CharacteristicValue;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
private Battery: {
|
|
23
|
+
Service: Service;
|
|
24
|
+
BatteryLevel: CharacteristicValue;
|
|
25
|
+
StatusLowBattery: CharacteristicValue;
|
|
26
|
+
ChargingState: CharacteristicValue;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Updates
|
|
30
|
+
plugUpdateInProgress!: boolean;
|
|
31
|
+
doPlugUpdate!: Subject<void>;
|
|
32
|
+
|
|
33
|
+
constructor(
|
|
34
|
+
readonly platform: SwitchBotPlatform,
|
|
35
|
+
accessory: PlatformAccessory,
|
|
36
|
+
device: device & devicesConfig,
|
|
37
|
+
) {
|
|
38
|
+
super(platform, accessory, device);
|
|
39
|
+
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
40
|
+
this.doPlugUpdate = new Subject();
|
|
41
|
+
this.plugUpdateInProgress = false;
|
|
42
|
+
|
|
43
|
+
// Initialize Fan property
|
|
44
|
+
this.Fan = {
|
|
45
|
+
Service: accessory.getService(this.hap.Service.Fanv2)!,
|
|
46
|
+
Active: accessory.context.Active || this.hap.Characteristic.Active.INACTIVE,
|
|
47
|
+
SwingMode: accessory.context.SwingMode || this.hap.Characteristic.SwingMode.SWING_DISABLED,
|
|
48
|
+
RotationSpeed: accessory.context.RotationSpeed || 0,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Initialize Battery property
|
|
52
|
+
this.Battery = {
|
|
53
|
+
Service: accessory.getService(this.hap.Service.Battery)!,
|
|
54
|
+
BatteryLevel: accessory.context.BatteryLevel || 100,
|
|
55
|
+
StatusLowBattery: accessory.context.StatusLowBattery || this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
|
|
56
|
+
ChargingState: accessory.context.ChargingState || this.hap.Characteristic.ChargingState.NOT_CHARGING,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Retrieve initial values and updateHomekit
|
|
60
|
+
this.refreshStatus();
|
|
61
|
+
|
|
62
|
+
// get the Fan service if it exists, otherwise create a new Fanv2 service
|
|
63
|
+
// you can create multiple services for each accessory
|
|
64
|
+
const FanService = `${accessory.displayName} ${device.deviceType}`;
|
|
65
|
+
(this.Fan.Service = accessory.getService(this.hap.Service.Fanv2)
|
|
66
|
+
|| accessory.addService(this.hap.Service.Fanv2)), FanService;
|
|
67
|
+
|
|
68
|
+
this.Fan.Service.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
|
|
69
|
+
// each service must implement at-minimum the "required characteristics" for the given service type
|
|
70
|
+
// see https://developers.homebridge.io/#/service/Fanv2
|
|
71
|
+
|
|
72
|
+
// create handlers for required characteristics
|
|
73
|
+
this.Fan.Service.getCharacteristic(this.hap.Characteristic.Active).onSet(this.ActiveSet.bind(this));
|
|
74
|
+
// create handlers for required characteristics
|
|
75
|
+
this.Fan.Service.getCharacteristic(this.hap.Characteristic.RotationSpeed).onSet(this.RotationSpeedSet.bind(this));
|
|
76
|
+
// create handlers for required characteristics
|
|
77
|
+
this.Fan.Service.getCharacteristic(this.hap.Characteristic.SwingMode).onSet(this.SwingModeSet.bind(this));
|
|
78
|
+
|
|
79
|
+
// Update Homekit
|
|
80
|
+
this.updateHomeKitCharacteristics();
|
|
81
|
+
|
|
82
|
+
// Start an update interval
|
|
83
|
+
interval(this.deviceRefreshRate * 1000)
|
|
84
|
+
.pipe(skipWhile(() => this.plugUpdateInProgress))
|
|
85
|
+
.subscribe(async () => {
|
|
86
|
+
await this.refreshStatus();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
//regisiter webhook event handler
|
|
90
|
+
if (device.webhook) {
|
|
91
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
|
|
92
|
+
this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
|
|
93
|
+
try {
|
|
94
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
|
|
95
|
+
const { version, battery, powerState, oscillation, chargingStatus, fanSpeed } = context;
|
|
96
|
+
const { Active, SwingMode, RotationSpeed } = this.Fan;
|
|
97
|
+
const { BatteryLevel, ChargingState } = this.Battery;
|
|
98
|
+
const { FirmwareRevision } = this.accessory.context;
|
|
99
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
|
|
100
|
+
'(version, battery, powerState, oscillation, chargingStatus, fanSpeed) = '
|
|
101
|
+
+ `Webhook:(${version}, ${battery}, ${powerState}, ${oscillation}, ${chargingStatus}, ${fanSpeed}), `
|
|
102
|
+
+ `current:(${FirmwareRevision}, ${BatteryLevel}, ${Active}, ${SwingMode}, ${ChargingState}, ${RotationSpeed})`);
|
|
103
|
+
|
|
104
|
+
// Active
|
|
105
|
+
this.Fan.Active = powerState === 'ON' ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE;
|
|
106
|
+
|
|
107
|
+
// SwingMode
|
|
108
|
+
this.Fan.SwingMode = oscillation === 'on' ?
|
|
109
|
+
this.hap.Characteristic.SwingMode.SWING_ENABLED : this.hap.Characteristic.SwingMode.SWING_DISABLED;
|
|
110
|
+
|
|
111
|
+
// RotationSpeed
|
|
112
|
+
this.Fan.RotationSpeed = fanSpeed;
|
|
113
|
+
|
|
114
|
+
// ChargingState
|
|
115
|
+
this.Battery.ChargingState = chargingStatus === 'charging' ?
|
|
116
|
+
this.hap.Characteristic.ChargingState.CHARGING : this.hap.Characteristic.ChargingState.NOT_CHARGING;
|
|
117
|
+
|
|
118
|
+
// BatteryLevel
|
|
119
|
+
this.Battery.BatteryLevel = battery;
|
|
120
|
+
|
|
121
|
+
// FirmwareRevision
|
|
122
|
+
this.accessory.context.FirmwareRevision = version;
|
|
123
|
+
this.accessory
|
|
124
|
+
.getService(this.hap.Service.AccessoryInformation)!
|
|
125
|
+
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, this.accessory.context.FirmwareRevision)
|
|
126
|
+
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
127
|
+
.updateValue(this.accessory.context.FirmwareRevision);
|
|
128
|
+
this.updateHomeKitCharacteristics();
|
|
129
|
+
} catch (e: any) {
|
|
130
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
131
|
+
+ `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Watch for Plug change events
|
|
137
|
+
// We put in a debounce of 100ms so we don't make duplicate calls
|
|
138
|
+
this.doPlugUpdate
|
|
139
|
+
.pipe(
|
|
140
|
+
tap(() => {
|
|
141
|
+
this.plugUpdateInProgress = true;
|
|
142
|
+
}),
|
|
143
|
+
debounceTime(this.platform.config.options!.pushRate! * 1000),
|
|
144
|
+
)
|
|
145
|
+
.subscribe(async () => {
|
|
146
|
+
try {
|
|
147
|
+
await this.pushChanges();
|
|
148
|
+
} catch (e: any) {
|
|
149
|
+
this.apiError(e);
|
|
150
|
+
this.errorLog(
|
|
151
|
+
`${this.device.deviceType}: ${this.accessory.displayName} failed pushChanges with ${this.device.connectionType} Connection,` +
|
|
152
|
+
` Error Message: ${JSON.stringify(e.message)}`,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
this.plugUpdateInProgress = false;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async BLEparseStatus(serviceData: serviceData): Promise<void> {
|
|
160
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEparseStatus`);
|
|
161
|
+
|
|
162
|
+
// State
|
|
163
|
+
switch (serviceData.state) {
|
|
164
|
+
case 'on':
|
|
165
|
+
this.Fan.Active = true;
|
|
166
|
+
break;
|
|
167
|
+
default:
|
|
168
|
+
this.Fan.Active = false;
|
|
169
|
+
}
|
|
170
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Fan.Active}`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async openAPIparseStatus(deviceStatus: deviceStatus) {
|
|
174
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIparseStatus`);
|
|
175
|
+
|
|
176
|
+
// Active
|
|
177
|
+
this.Fan.Active = deviceStatus.body.power === 'on' ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE;
|
|
178
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Active: ${this.Fan.Active}`);
|
|
179
|
+
|
|
180
|
+
// SwingMode
|
|
181
|
+
this.Fan.SwingMode = deviceStatus.body.oscillation === 'on' ?
|
|
182
|
+
this.hap.Characteristic.SwingMode.SWING_ENABLED : this.hap.Characteristic.SwingMode.SWING_DISABLED;
|
|
183
|
+
|
|
184
|
+
// RotationSpeed
|
|
185
|
+
this.Fan.RotationSpeed = deviceStatus.body.fanSpeed;
|
|
186
|
+
|
|
187
|
+
// ChargingState
|
|
188
|
+
this.Battery.ChargingState = deviceStatus.body.chargingStatus === 'charging' ?
|
|
189
|
+
this.hap.Characteristic.ChargingState.CHARGING : this.hap.Characteristic.ChargingState.NOT_CHARGING;
|
|
190
|
+
|
|
191
|
+
// BatteryLevel
|
|
192
|
+
this.Battery.BatteryLevel = Number(deviceStatus.body.battery);
|
|
193
|
+
if (this.Battery.BatteryLevel < 10) {
|
|
194
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
195
|
+
} else {
|
|
196
|
+
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
197
|
+
}
|
|
198
|
+
if (Number.isNaN(this.Battery.BatteryLevel)) {
|
|
199
|
+
this.Battery.BatteryLevel = 100;
|
|
200
|
+
}
|
|
201
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel},`
|
|
202
|
+
+ ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
203
|
+
|
|
204
|
+
// FirmwareRevision
|
|
205
|
+
this.accessory.context.FirmwareRevision = deviceStatus.body.version;
|
|
206
|
+
this.accessory
|
|
207
|
+
.getService(this.hap.Service.AccessoryInformation)!
|
|
208
|
+
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, this.accessory.context.FirmwareRevision)
|
|
209
|
+
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
210
|
+
.updateValue(this.accessory.context.FirmwareRevision);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Asks the SwitchBot API for the latest device information
|
|
217
|
+
*/
|
|
218
|
+
async refreshStatus(): Promise<void> {
|
|
219
|
+
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
220
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} refreshStatus enableCloudService: ${this.device.enableCloudService}`);
|
|
221
|
+
} else if (this.BLE) {
|
|
222
|
+
await this.BLERefreshStatus();
|
|
223
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
224
|
+
await this.openAPIRefreshStatus();
|
|
225
|
+
} else {
|
|
226
|
+
await this.offlineOff();
|
|
227
|
+
this.debugWarnLog(
|
|
228
|
+
`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` +
|
|
229
|
+
` ${this.device.connectionType}, refreshStatus will not happen.`,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async BLERefreshStatus(): Promise<void> {
|
|
235
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLERefreshStatus`);
|
|
236
|
+
const switchbot = await this.platform.connectBLE();
|
|
237
|
+
// Convert to BLE Address
|
|
238
|
+
this.device.bleMac = this.device
|
|
239
|
+
.deviceId!.match(/.{1,2}/g)!
|
|
240
|
+
.join(':')
|
|
241
|
+
.toLowerCase();
|
|
242
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
243
|
+
this.getCustomBLEAddress(switchbot);
|
|
244
|
+
// Start to monitor advertisement packets
|
|
245
|
+
(async () => {
|
|
246
|
+
// Start to monitor advertisement packets
|
|
247
|
+
await switchbot.startScan({ model: this.device.bleModel, id: this.device.bleMac });
|
|
248
|
+
// Set an event handler
|
|
249
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
250
|
+
if (this.device.bleMac === ad.address && ad.model === this.device.bleModel) {
|
|
251
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ${JSON.stringify(ad, null, ' ')}`);
|
|
252
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} address: ${ad.address}, model: ${ad.model}`);
|
|
253
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
254
|
+
} else {
|
|
255
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
// Wait 10 seconds
|
|
259
|
+
await switchbot.wait(this.scanDuration * 1000);
|
|
260
|
+
// Stop to monitor
|
|
261
|
+
await switchbot.stopScan();
|
|
262
|
+
// Update HomeKit
|
|
263
|
+
await this.BLEparseStatus(switchbot.onadvertisement.serviceData);
|
|
264
|
+
await this.updateHomeKitCharacteristics();
|
|
265
|
+
})();
|
|
266
|
+
if (switchbot === undefined) {
|
|
267
|
+
await this.BLERefreshConnection(switchbot);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async openAPIRefreshStatus(): Promise<void> {
|
|
272
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIRefreshStatus`);
|
|
273
|
+
try {
|
|
274
|
+
const { body, statusCode } = await this.platform.retryRequest(this.deviceMaxRetries, this.deviceDelayBetweenRetries,
|
|
275
|
+
`${Devices}/${this.device.deviceId}/status`, { headers: this.platform.generateHeaders() });
|
|
276
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
|
|
277
|
+
const deviceStatus: any = await body.json();
|
|
278
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
|
|
279
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
|
|
280
|
+
if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
|
|
281
|
+
this.debugSuccessLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
282
|
+
+ `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
|
|
283
|
+
this.openAPIparseStatus(deviceStatus);
|
|
284
|
+
this.updateHomeKitCharacteristics();
|
|
285
|
+
} else {
|
|
286
|
+
this.statusCode(statusCode);
|
|
287
|
+
this.statusCode(deviceStatus.statusCode);
|
|
288
|
+
}
|
|
289
|
+
} catch (e: any) {
|
|
290
|
+
this.apiError(e);
|
|
291
|
+
this.errorLog(
|
|
292
|
+
`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIRefreshStatus with ${this.device.connectionType}` +
|
|
293
|
+
` Connection, Error Message: ${JSON.stringify(e.message)}`,
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Pushes the requested changes to the SwitchBot API
|
|
300
|
+
* deviceType commandType Command command parameter Description
|
|
301
|
+
* Battery Circulator Fan - "command" "turnOff" "default" = set to OFF state
|
|
302
|
+
* Battery Circulator Fan - "command" "turnOn" "default" = set to ON state
|
|
303
|
+
* Battery Circulator Fan - "command" "setNightLightMode" "off, 1, or 2" = off, turn off nightlight, (1, bright) (2, dim)
|
|
304
|
+
* Battery Circulator Fan - "command" "setWindMode" "direct, natural, sleep, or baby" = Set fan mode. direct: direct mode. natural: natural mode. sleep: sleep mode. baby: ultra quiet mode
|
|
305
|
+
* Battery Circulator Fan - "command" "setWindSpeed" "{1-100} e.g. 10" = Set fan speed.1~100
|
|
306
|
+
*/
|
|
307
|
+
|
|
308
|
+
async pushChanges(): Promise<void> {
|
|
309
|
+
if (!this.device.enableCloudService && this.OpenAPI) {
|
|
310
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} pushChanges enableCloudService: ${this.device.enableCloudService}`);
|
|
311
|
+
} else if (this.BLE) {
|
|
312
|
+
await this.BLEpushChanges();
|
|
313
|
+
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
314
|
+
await this.openAPIpushChanges();
|
|
315
|
+
} else {
|
|
316
|
+
await this.offlineOff();
|
|
317
|
+
this.debugWarnLog(
|
|
318
|
+
`${this.device.deviceType}: ${this.accessory.displayName} Connection Type:` + ` ${this.device.connectionType}, pushChanges will not happen.`,
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
// Refresh the status from the API
|
|
322
|
+
interval(15000)
|
|
323
|
+
.pipe(skipWhile(() => this.plugUpdateInProgress))
|
|
324
|
+
.pipe(take(1))
|
|
325
|
+
.subscribe(async () => {
|
|
326
|
+
await this.refreshStatus();
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async BLEpushChanges(): Promise<void> {
|
|
331
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`);
|
|
332
|
+
if (this.Fan.Active !== this.accessory.context.Active) {
|
|
333
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLEpushChanges`
|
|
334
|
+
+ ` On: ${this.Fan.Active} OnCached: ${this.accessory.context.Active}`);
|
|
335
|
+
const switchbot = await this.platform.connectBLE();
|
|
336
|
+
// Convert to BLE Address
|
|
337
|
+
this.device.bleMac = this.device
|
|
338
|
+
.deviceId!.match(/.{1,2}/g)!
|
|
339
|
+
.join(':')
|
|
340
|
+
.toLowerCase();
|
|
341
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
342
|
+
switchbot
|
|
343
|
+
.discover({
|
|
344
|
+
model: this.device.bleModel,
|
|
345
|
+
id: this.device.bleMac,
|
|
346
|
+
})
|
|
347
|
+
.then(async (device_list: any) => {
|
|
348
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} On: ${this.Fan.Active}`);
|
|
349
|
+
return await this.retryBLE({
|
|
350
|
+
max: await this.maxRetryBLE(),
|
|
351
|
+
fn: async () => {
|
|
352
|
+
if (this.Fan.Active) {
|
|
353
|
+
return await device_list[0].turnOn({ id: this.device.bleMac });
|
|
354
|
+
} else {
|
|
355
|
+
return await device_list[0].turnOff({ id: this.device.bleMac });
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
});
|
|
359
|
+
})
|
|
360
|
+
.then(() => {
|
|
361
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Done.`);
|
|
362
|
+
this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
363
|
+
+ `Active: ${this.Fan.Active} sent over BLE, sent successfully`);
|
|
364
|
+
this.Fan.Active = false;
|
|
365
|
+
})
|
|
366
|
+
.catch(async (e: any) => {
|
|
367
|
+
this.apiError(e);
|
|
368
|
+
this.errorLog(
|
|
369
|
+
`${this.device.deviceType}: ${this.accessory.displayName} failed BLEpushChanges with ${this.device.connectionType}` +
|
|
370
|
+
` Connection, Error Message: ${JSON.stringify(e.message)}`,
|
|
371
|
+
);
|
|
372
|
+
await this.BLEPushConnection();
|
|
373
|
+
});
|
|
374
|
+
} else {
|
|
375
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No BLEpushChanges,`
|
|
376
|
+
+ ` Active: ${this.Fan.Active}, ActiveCached: ${this.accessory.context.Active}`);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async openAPIpushChanges() {
|
|
381
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} openAPIpushChanges`);
|
|
382
|
+
if (this.Fan.Active !== this.accessory.context.Active) {
|
|
383
|
+
let command = '';
|
|
384
|
+
if (this.Fan.Active) {
|
|
385
|
+
command = 'turnOn';
|
|
386
|
+
} else {
|
|
387
|
+
command = 'turnOff';
|
|
388
|
+
}
|
|
389
|
+
const bodyChange = JSON.stringify({
|
|
390
|
+
command: `${command}`,
|
|
391
|
+
parameter: 'default',
|
|
392
|
+
commandType: 'command',
|
|
393
|
+
});
|
|
394
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Sending request to SwitchBot API, body: ${bodyChange},`);
|
|
395
|
+
try {
|
|
396
|
+
const { body, statusCode } = await request(`${Devices}/${this.device.deviceId}/commands`, {
|
|
397
|
+
body: bodyChange,
|
|
398
|
+
method: 'POST',
|
|
399
|
+
headers: this.platform.generateHeaders(),
|
|
400
|
+
});
|
|
401
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} statusCode: ${statusCode}`);
|
|
402
|
+
const deviceStatus: any = await body.json();
|
|
403
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus: ${JSON.stringify(deviceStatus)}`);
|
|
404
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus body: ${JSON.stringify(deviceStatus.body)}`);
|
|
405
|
+
this.debugWarnLog(`${this.device.deviceType}: ${this.accessory.displayName} deviceStatus statusCode: ${deviceStatus.statusCode}`);
|
|
406
|
+
if ((statusCode === 200 || statusCode === 100) && (deviceStatus.statusCode === 200 || deviceStatus.statusCode === 100)) {
|
|
407
|
+
this.debugErrorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
408
|
+
+ `statusCode: ${statusCode} & deviceStatus StatusCode: ${deviceStatus.statusCode}`);
|
|
409
|
+
this.successLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
410
|
+
+ `request to SwitchBot API, body: ${deviceStatus} sent successfully`);
|
|
411
|
+
} else {
|
|
412
|
+
this.statusCode(statusCode);
|
|
413
|
+
this.statusCode(deviceStatus.statusCode);
|
|
414
|
+
}
|
|
415
|
+
} catch (e: any) {
|
|
416
|
+
this.apiError(e);
|
|
417
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} failed openAPIpushChanges with ${this.device.connectionType}`
|
|
418
|
+
+ ` Connection, Error Message: ${JSON.stringify(e.message)}`);
|
|
419
|
+
}
|
|
420
|
+
} else {
|
|
421
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No openAPIpushChanges.`
|
|
422
|
+
+ `On: ${this.Fan.Active}, ActiveCached: ${this.accessory.context.Active}`);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Handle requests to set the value of the "On" characteristic
|
|
428
|
+
*/
|
|
429
|
+
async ActiveSet(value: CharacteristicValue): Promise<void> {
|
|
430
|
+
if (this.Fan.Active === this.accessory.context.Active) {
|
|
431
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set Active: ${value}`);
|
|
432
|
+
} else {
|
|
433
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set Active: ${value}`);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
this.Fan.Active = value;
|
|
437
|
+
this.doPlugUpdate.next();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Handle requests to set the value of the "On" characteristic
|
|
442
|
+
*/
|
|
443
|
+
async RotationSpeedSet(value: CharacteristicValue): Promise<void> {
|
|
444
|
+
if (this.Fan.RotationSpeed === this.accessory.context.RotationSpeed) {
|
|
445
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set RotationSpeed: ${value}`);
|
|
446
|
+
} else {
|
|
447
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set RotationSpeed: ${value}`);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
this.Fan.RotationSpeed = value;
|
|
451
|
+
this.doPlugUpdate.next();
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Handle requests to set the value of the "On" characteristic
|
|
456
|
+
*/
|
|
457
|
+
async SwingModeSet(value: CharacteristicValue): Promise<void> {
|
|
458
|
+
if (this.Fan.SwingMode === this.accessory.context.SwingMode) {
|
|
459
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} No Changes, Set SwingMode: ${value}`);
|
|
460
|
+
} else {
|
|
461
|
+
this.infoLog(`${this.device.deviceType}: ${this.accessory.displayName} Set SwingMode: ${value}`);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
this.Fan.SwingMode = value;
|
|
465
|
+
this.doPlugUpdate.next();
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async updateHomeKitCharacteristics(): Promise<void> {
|
|
469
|
+
// Active
|
|
470
|
+
if (this.Fan.Active === undefined) {
|
|
471
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} Active: ${this.Fan.Active}`);
|
|
472
|
+
} else {
|
|
473
|
+
this.accessory.context.Active = this.Fan.Active;
|
|
474
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.Active, this.Fan.Active);
|
|
475
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic Active: ${this.Fan.Active}`);
|
|
476
|
+
}
|
|
477
|
+
// RotationSpeed
|
|
478
|
+
if(this.Fan.RotationSpeed === undefined) {
|
|
479
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} RotationSpeed: ${this.Fan.RotationSpeed}`);
|
|
480
|
+
} else {
|
|
481
|
+
this.accessory.context.RotationSpeed = this.Fan.RotationSpeed;
|
|
482
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.RotationSpeed, this.Fan.RotationSpeed);
|
|
483
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic RotationSpeed: ${this.Fan.RotationSpeed}`);
|
|
484
|
+
}
|
|
485
|
+
// SwingMode
|
|
486
|
+
if(this.Fan.SwingMode === undefined) {
|
|
487
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} SwingMode: ${this.Fan.SwingMode}`);
|
|
488
|
+
} else {
|
|
489
|
+
this.accessory.context.SwingMode = this.Fan.SwingMode;
|
|
490
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.SwingMode, this.Fan.SwingMode);
|
|
491
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic SwingMode: ${this.Fan.SwingMode}`);
|
|
492
|
+
}
|
|
493
|
+
// BateryLevel
|
|
494
|
+
if(this.Battery.BatteryLevel === undefined) {
|
|
495
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
496
|
+
} else {
|
|
497
|
+
this.accessory.context.BatteryLevel = this.Battery.BatteryLevel;
|
|
498
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
|
|
499
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
|
|
500
|
+
}
|
|
501
|
+
// ChargingState
|
|
502
|
+
if(this.Battery.ChargingState === undefined) {
|
|
503
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
|
|
504
|
+
} else {
|
|
505
|
+
this.accessory.context.ChargingState = this.Battery.ChargingState;
|
|
506
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
|
|
507
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic ChargingState: ${this.Battery.ChargingState}`);
|
|
508
|
+
}
|
|
509
|
+
// StatusLowBattery
|
|
510
|
+
if(this.Battery.StatusLowBattery === undefined) {
|
|
511
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
512
|
+
} else {
|
|
513
|
+
this.accessory.context.StatusLowBattery = this.Battery.StatusLowBattery;
|
|
514
|
+
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
|
|
515
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.Battery.StatusLowBattery}`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
async BLEPushConnection() {
|
|
520
|
+
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
521
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Push Changes`);
|
|
522
|
+
await this.openAPIpushChanges();
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
async BLERefreshConnection(switchbot: any): Promise<void> {
|
|
527
|
+
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot:`
|
|
528
|
+
+ ` ${JSON.stringify(switchbot)}`);
|
|
529
|
+
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
530
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} Using OpenAPI Connection to Refresh Status`);
|
|
531
|
+
await this.openAPIRefreshStatus();
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
async offlineOff(): Promise<void> {
|
|
536
|
+
if (this.device.offline) {
|
|
537
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.Active, this.hap.Characteristic.Active.INACTIVE);
|
|
538
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.RotationSpeed, 0);
|
|
539
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.SwingMode, this.hap.Characteristic.SwingMode.SWING_DISABLED);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
async apiError(e: any): Promise<void> {
|
|
544
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.Active, e);
|
|
545
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.RotationSpeed, e);
|
|
546
|
+
this.Fan.Service.updateCharacteristic(this.hap.Characteristic.SwingMode, e);
|
|
547
|
+
}
|
|
548
|
+
}
|
package/src/device/hub.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { deviceBase } from './device.js';
|
|
|
7
7
|
import { SwitchBotPlatform } from '../platform.js';
|
|
8
8
|
import { Devices, device, deviceStatus, devicesConfig } from '../settings.js';
|
|
9
9
|
import { CharacteristicValue, PlatformAccessory, Service, Units } from 'homebridge';
|
|
10
|
+
import { convertUnits } from '../utils.js';
|
|
10
11
|
|
|
11
12
|
export class Hub extends deviceBase {
|
|
12
13
|
// Services
|
|
@@ -145,34 +146,36 @@ export class Hub extends deviceBase {
|
|
|
145
146
|
});
|
|
146
147
|
|
|
147
148
|
//regisiter webhook event handler
|
|
148
|
-
if (
|
|
149
|
-
this.
|
|
149
|
+
if (device.webhook) {
|
|
150
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
|
|
150
151
|
this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
|
|
151
152
|
try {
|
|
152
153
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.
|
|
159
|
-
|
|
160
|
-
|
|
154
|
+
const { temperature, humidity, lightLevel } = context;
|
|
155
|
+
const { CurrentTemperature } = this.TemperatureSensor || { CurrentTemperature: undefined };
|
|
156
|
+
const { CurrentAmbientLightLevel } = this.LightSensor || { CurrentAmbientLightLevel: undefined };
|
|
157
|
+
const { CurrentRelativeHumidity } = this.HumiditySensor || { CurrentRelativeHumidity: undefined };
|
|
158
|
+
if (context.scale !== 'CELCIUS' && device.hub?.convertUnitTo === undefined) {
|
|
159
|
+
this.warnLog(`${this.device.deviceType}: ${this.accessory.displayName} received a non-CELCIUS Webhook scale: `
|
|
160
|
+
+ `${context.scale}, Use the *convertUnitsTo* config under Hub settings, if displaying incorrectly in HomeKit.`);
|
|
161
|
+
}
|
|
162
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ` +
|
|
163
|
+
'(scale, temperature, humidity, lightLevel) = ' +
|
|
164
|
+
`Webhook:(${context.scale}, ${convertUnits(temperature, context.scale, device.hub?.convertUnitTo)}, ${humidity}, ${lightLevel}), ` +
|
|
161
165
|
`current:(${CurrentTemperature}, ${CurrentRelativeHumidity}, ${CurrentAmbientLightLevel})`);
|
|
162
|
-
|
|
166
|
+
if (!this.device.hub?.hide_humidity) {
|
|
163
167
|
this.HumiditySensor!.CurrentRelativeHumidity = humidity;
|
|
164
|
-
}
|
|
165
|
-
if (!this.device.hub?.hide_temperature) {
|
|
166
|
-
this.TemperatureSensor!.CurrentTemperature = temperature;
|
|
167
|
-
}
|
|
168
|
-
if (!this.device.hub?.hide_lightsensor) {
|
|
169
|
-
const set_minLux = await this.minLux();
|
|
170
|
-
const set_maxLux = await this.maxLux();
|
|
171
|
-
const spaceBetweenLevels = 19;
|
|
172
|
-
await this.getLightLevel(lightLevel, set_minLux, set_maxLux, spaceBetweenLevels);
|
|
173
|
-
}
|
|
174
|
-
this.updateHomeKitCharacteristics();
|
|
175
168
|
}
|
|
169
|
+
if (!this.device.hub?.hide_temperature) {
|
|
170
|
+
this.TemperatureSensor!.CurrentTemperature = convertUnits(temperature, context.scale, device.hub?.convertUnitTo);
|
|
171
|
+
}
|
|
172
|
+
if (!this.device.hub?.hide_lightsensor) {
|
|
173
|
+
const set_minLux = await this.minLux();
|
|
174
|
+
const set_maxLux = await this.maxLux();
|
|
175
|
+
const spaceBetweenLevels = 19;
|
|
176
|
+
await this.getLightLevel(lightLevel, set_minLux, set_maxLux, spaceBetweenLevels);
|
|
177
|
+
}
|
|
178
|
+
this.updateHomeKitCharacteristics();
|
|
176
179
|
} catch (e: any) {
|
|
177
180
|
this.errorLog(`${this.device.deviceType}: ${this.accessory.displayName} `
|
|
178
181
|
+ `failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
|
|
@@ -215,6 +218,11 @@ export class Hub extends deviceBase {
|
|
|
215
218
|
|
|
216
219
|
// FirmwareRevision
|
|
217
220
|
this.accessory.context.FirmwareRevision = deviceStatus.body.version;
|
|
221
|
+
this.accessory
|
|
222
|
+
.getService(this.hap.Service.AccessoryInformation)!
|
|
223
|
+
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, this.accessory.context.FirmwareRevision)
|
|
224
|
+
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
225
|
+
.updateValue(this.accessory.context.FirmwareRevision);
|
|
218
226
|
}
|
|
219
227
|
|
|
220
228
|
async refreshStatus(): Promise<void> {
|
package/src/device/humidifier.ts
CHANGED
|
@@ -143,8 +143,8 @@ export class Humidifier extends deviceBase {
|
|
|
143
143
|
});
|
|
144
144
|
|
|
145
145
|
//regisiter webhook event handler
|
|
146
|
-
if (
|
|
147
|
-
this.
|
|
146
|
+
if (device.webhook) {
|
|
147
|
+
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} is listening webhook.`);
|
|
148
148
|
this.platform.webhookEventHandler[this.device.deviceId] = async (context) => {
|
|
149
149
|
try {
|
|
150
150
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} received Webhook: ${JSON.stringify(context)}`);
|
|
@@ -270,6 +270,11 @@ export class Humidifier extends deviceBase {
|
|
|
270
270
|
|
|
271
271
|
// FirmwareRevision
|
|
272
272
|
this.accessory.context.FirmwareRevision = deviceStatus.body.version;
|
|
273
|
+
this.accessory
|
|
274
|
+
.getService(this.hap.Service.AccessoryInformation)!
|
|
275
|
+
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, this.accessory.context.FirmwareRevision)
|
|
276
|
+
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
277
|
+
.updateValue(this.accessory.context.FirmwareRevision);
|
|
273
278
|
}
|
|
274
279
|
|
|
275
280
|
async refreshStatus(): Promise<void> {
|
|
@@ -670,7 +675,7 @@ export class Humidifier extends deviceBase {
|
|
|
670
675
|
} else {
|
|
671
676
|
this.TemperatureSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, this.TemperatureSensor!.CurrentTemperature);
|
|
672
677
|
this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
|
|
673
|
-
|
|
678
|
+
+ ` CurrentTemperature: ${this.TemperatureSensor!.CurrentTemperature}`);
|
|
674
679
|
this.accessory.context.CurrentTemperature = this.TemperatureSensor!.CurrentTemperature;
|
|
675
680
|
}
|
|
676
681
|
}
|