@switchbot/homebridge-switchbot 1.12.7-beta.5 → 1.12.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/config.schema.json +6 -6
- package/dist/device/bot.js +2 -2
- package/dist/device/bot.js.map +1 -1
- package/dist/device/colorbulb.d.ts +0 -6
- package/dist/device/colorbulb.d.ts.map +1 -1
- package/dist/device/colorbulb.js +74 -89
- package/dist/device/colorbulb.js.map +1 -1
- package/dist/device/curtain.js +1 -1
- package/dist/device/curtain.js.map +1 -1
- package/dist/device/humidifier.js +2 -2
- package/dist/device/humidifier.js.map +1 -1
- package/dist/device/lock.d.ts.map +1 -1
- package/dist/device/lock.js +1 -21
- package/dist/device/lock.js.map +1 -1
- package/dist/device/meter.d.ts +0 -1
- package/dist/device/meter.d.ts.map +1 -1
- package/dist/device/meter.js +1 -14
- package/dist/device/meter.js.map +1 -1
- package/dist/device/meterplus.d.ts +76 -0
- package/dist/device/meterplus.d.ts.map +1 -0
- package/dist/device/meterplus.js +464 -0
- package/dist/device/meterplus.js.map +1 -0
- package/dist/device/plug.js +1 -1
- package/dist/device/plug.js.map +1 -1
- package/dist/device/striplight.d.ts +90 -0
- package/dist/device/striplight.d.ts.map +1 -0
- package/dist/device/striplight.js +487 -0
- package/dist/device/striplight.js.map +1 -0
- package/dist/platform.d.ts +2 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +119 -9
- package/dist/platform.js.map +1 -1
- package/package.json +76 -76
- package/src/device/bot.ts +2 -2
- package/src/device/colorbulb.ts +74 -89
- package/src/device/curtain.ts +1 -1
- package/src/device/humidifier.ts +2 -2
- package/src/device/lock.ts +1 -21
- package/src/device/meter.ts +1 -13
- package/src/device/meterplus.ts +518 -0
- package/src/device/plug.ts +1 -1
- package/src/device/striplight.ts +583 -0
- package/src/platform.ts +127 -9
package/src/device/curtain.ts
CHANGED
|
@@ -87,7 +87,7 @@ export class Curtain {
|
|
|
87
87
|
|
|
88
88
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
89
89
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
90
|
-
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.
|
|
90
|
+
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.WindowCovering, 'NAME', 'USER_DEFINED_SUBTYPE');
|
|
91
91
|
|
|
92
92
|
// set the service name, this is what is displayed as the default name on the Home app
|
|
93
93
|
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|
package/src/device/humidifier.ts
CHANGED
|
@@ -79,7 +79,7 @@ export class Humidifier {
|
|
|
79
79
|
.setCharacteristic(this.platform.Characteristic.Model, 'W0801800')
|
|
80
80
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!);
|
|
81
81
|
|
|
82
|
-
// get the
|
|
82
|
+
// get the service if it exists, otherwise create a new service
|
|
83
83
|
// you can create multiple services for each accessory
|
|
84
84
|
(this.humidifierService =
|
|
85
85
|
accessory.getService(this.platform.Service.HumidifierDehumidifier) || accessory.addService(this.platform.Service.HumidifierDehumidifier)),
|
|
@@ -87,7 +87,7 @@ export class Humidifier {
|
|
|
87
87
|
|
|
88
88
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
89
89
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
90
|
-
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.
|
|
90
|
+
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.HumidifierDehumidifier, 'NAME', 'USER_DEFINED_SUBTYPE');
|
|
91
91
|
|
|
92
92
|
// set the service name, this is what is displayed as the default name on the Home app
|
|
93
93
|
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|
package/src/device/lock.ts
CHANGED
|
@@ -62,7 +62,7 @@ export class Lock {
|
|
|
62
62
|
|
|
63
63
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
64
64
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
65
|
-
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.
|
|
65
|
+
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.LockMechanism, 'NAME', 'USER_DEFINED_SUBTYPE');
|
|
66
66
|
|
|
67
67
|
// set the service name, this is what is displayed as the default name on the Home app
|
|
68
68
|
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|
|
@@ -119,26 +119,6 @@ export class Lock {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
async refreshStatus(): Promise<void> {
|
|
122
|
-
const switchbot = await this.platform.connectBLE();
|
|
123
|
-
// Convert to BLE Address
|
|
124
|
-
this.device.bleMac = this.device
|
|
125
|
-
.deviceId!.match(/.{1,2}/g)!
|
|
126
|
-
.join(':')
|
|
127
|
-
.toLowerCase();
|
|
128
|
-
this.debugLog(`Curtain: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
129
|
-
(async () => {
|
|
130
|
-
// Start to monitor advertisement packets
|
|
131
|
-
await switchbot.startScan({
|
|
132
|
-
model: 'o',
|
|
133
|
-
});
|
|
134
|
-
// Set an event handler
|
|
135
|
-
switchbot.onadvertisement = (ad: any) => {
|
|
136
|
-
this.warnLog(JSON.stringify(ad, null, ' '));
|
|
137
|
-
};
|
|
138
|
-
await switchbot.wait(10000);
|
|
139
|
-
// Stop to monitor
|
|
140
|
-
switchbot.stopScan();
|
|
141
|
-
})();
|
|
142
122
|
try {
|
|
143
123
|
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
144
124
|
this.debugLog(`Lock: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
package/src/device/meter.ts
CHANGED
|
@@ -78,7 +78,7 @@ export class Meter {
|
|
|
78
78
|
accessory
|
|
79
79
|
.getService(this.platform.Service.AccessoryInformation)!
|
|
80
80
|
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'SwitchBot')
|
|
81
|
-
.setCharacteristic(this.platform.Characteristic.Model,
|
|
81
|
+
.setCharacteristic(this.platform.Characteristic.Model, 'METERTH-S1')
|
|
82
82
|
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!);
|
|
83
83
|
|
|
84
84
|
// Temperature Sensor Service
|
|
@@ -408,18 +408,6 @@ export class Meter {
|
|
|
408
408
|
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
-
model(device: device & devicesConfig): CharacteristicValue {
|
|
412
|
-
let model: string;
|
|
413
|
-
if (device.deviceType === 'Meter Plus (US)') {
|
|
414
|
-
model = 'W2301500';
|
|
415
|
-
} else if (device.deviceType === 'Meter Plus (JP)') {
|
|
416
|
-
model = 'W2201500';
|
|
417
|
-
} else {
|
|
418
|
-
model = 'S1';
|
|
419
|
-
}
|
|
420
|
-
return model;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
411
|
async config(device: device & devicesConfig): Promise<void> {
|
|
424
412
|
let config = {};
|
|
425
413
|
if (device.meter) {
|
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import { interval, Subject } from 'rxjs';
|
|
2
|
+
import { skipWhile } from 'rxjs/operators';
|
|
3
|
+
import { SwitchBotPlatform } from '../platform';
|
|
4
|
+
import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
|
|
5
|
+
import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, temperature, deviceStatus } from '../settings';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Platform Accessory
|
|
9
|
+
* An instance of this class is created for each accessory your platform registers
|
|
10
|
+
* Each accessory may expose multiple services of different service types.
|
|
11
|
+
*/
|
|
12
|
+
export class MeterPlus {
|
|
13
|
+
// Services
|
|
14
|
+
batteryService?: Service;
|
|
15
|
+
temperatureservice?: Service;
|
|
16
|
+
humidityservice?: Service;
|
|
17
|
+
|
|
18
|
+
// Characteristic Values
|
|
19
|
+
CurrentRelativeHumidity!: CharacteristicValue;
|
|
20
|
+
CurrentRelativeHumidityCached!: CharacteristicValue;
|
|
21
|
+
CurrentTemperature?: CharacteristicValue;
|
|
22
|
+
CurrentTemperatureCached?: CharacteristicValue;
|
|
23
|
+
BatteryLevel?: CharacteristicValue;
|
|
24
|
+
ChargingState?: CharacteristicValue;
|
|
25
|
+
StatusLowBattery?: CharacteristicValue;
|
|
26
|
+
Active!: CharacteristicValue;
|
|
27
|
+
WaterLevel!: CharacteristicValue;
|
|
28
|
+
|
|
29
|
+
// OpenAPI Others
|
|
30
|
+
Temperature: deviceStatus['temperature'];
|
|
31
|
+
Humidity: deviceStatus['humidity'];
|
|
32
|
+
deviceStatus!: deviceStatusResponse;
|
|
33
|
+
|
|
34
|
+
// BLE Others
|
|
35
|
+
connected?: boolean;
|
|
36
|
+
switchbot!: switchbot;
|
|
37
|
+
SwitchToOpenAPI?: boolean;
|
|
38
|
+
serviceData!: serviceData;
|
|
39
|
+
address!: ad['address'];
|
|
40
|
+
temperature!: temperature['c'];
|
|
41
|
+
battery!: serviceData['battery'];
|
|
42
|
+
humidity!: serviceData['humidity'];
|
|
43
|
+
|
|
44
|
+
// Config
|
|
45
|
+
scanDuration!: number;
|
|
46
|
+
deviceLogging!: string;
|
|
47
|
+
deviceRefreshRate!: number;
|
|
48
|
+
|
|
49
|
+
// Updates
|
|
50
|
+
meterUpdateInProgress!: boolean;
|
|
51
|
+
doMeterUpdate: Subject<void>;
|
|
52
|
+
|
|
53
|
+
constructor(private readonly platform: SwitchBotPlatform, private accessory: PlatformAccessory, public device: device & devicesConfig) {
|
|
54
|
+
// default placeholders
|
|
55
|
+
this.logs(device);
|
|
56
|
+
this.scan(device);
|
|
57
|
+
this.refreshRate(device);
|
|
58
|
+
this.config(device);
|
|
59
|
+
if (this.CurrentRelativeHumidity === undefined) {
|
|
60
|
+
this.CurrentRelativeHumidity = 0;
|
|
61
|
+
} else {
|
|
62
|
+
this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
|
|
63
|
+
}
|
|
64
|
+
if (this.CurrentTemperature === undefined) {
|
|
65
|
+
this.CurrentTemperature = 0;
|
|
66
|
+
} else {
|
|
67
|
+
this.CurrentTemperature = this.accessory.context.CurrentTemperature;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
71
|
+
this.doMeterUpdate = new Subject();
|
|
72
|
+
this.meterUpdateInProgress = false;
|
|
73
|
+
|
|
74
|
+
// Retrieve initial values and updateHomekit
|
|
75
|
+
this.refreshStatus();
|
|
76
|
+
|
|
77
|
+
// set accessory information
|
|
78
|
+
accessory
|
|
79
|
+
.getService(this.platform.Service.AccessoryInformation)!
|
|
80
|
+
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'SwitchBot')
|
|
81
|
+
.setCharacteristic(this.platform.Characteristic.Model, this.model(device))
|
|
82
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, device.deviceId!);
|
|
83
|
+
|
|
84
|
+
// Temperature Sensor Service
|
|
85
|
+
if (device.meter?.hide_temperature) {
|
|
86
|
+
this.debugLog(`Meter Plus: ${accessory.displayName} Removing Temperature Sensor Service`);
|
|
87
|
+
this.temperatureservice = this.accessory.getService(this.platform.Service.TemperatureSensor);
|
|
88
|
+
accessory.removeService(this.temperatureservice!);
|
|
89
|
+
} else if (!this.temperatureservice) {
|
|
90
|
+
this.debugLog(`Meter Plus: ${accessory.displayName} Add Temperature Sensor Service`);
|
|
91
|
+
(this.temperatureservice =
|
|
92
|
+
this.accessory.getService(this.platform.Service.TemperatureSensor) || this.accessory.addService(this.platform.Service.TemperatureSensor)),
|
|
93
|
+
`${accessory.displayName} Temperature Sensor`;
|
|
94
|
+
|
|
95
|
+
this.temperatureservice.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Temperature Sensor`);
|
|
96
|
+
|
|
97
|
+
this.temperatureservice
|
|
98
|
+
.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
|
|
99
|
+
.setProps({
|
|
100
|
+
unit: Units['CELSIUS'],
|
|
101
|
+
validValueRanges: [-273.15, 100],
|
|
102
|
+
minValue: -273.15,
|
|
103
|
+
maxValue: 100,
|
|
104
|
+
minStep: 0.1,
|
|
105
|
+
})
|
|
106
|
+
.onGet(() => {
|
|
107
|
+
return this.CurrentTemperature!;
|
|
108
|
+
});
|
|
109
|
+
} else {
|
|
110
|
+
this.debugLog(`Meter Plus: ${accessory.displayName} Temperature Sensor Service Not Added`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Humidity Sensor Service
|
|
114
|
+
if (device.meter?.hide_humidity) {
|
|
115
|
+
this.debugLog(`Meter Plus: ${accessory.displayName} Removing Humidity Sensor Service`);
|
|
116
|
+
this.humidityservice = this.accessory.getService(this.platform.Service.HumiditySensor);
|
|
117
|
+
accessory.removeService(this.humidityservice!);
|
|
118
|
+
} else if (!this.humidityservice) {
|
|
119
|
+
this.debugLog(`Meter Plus: ${accessory.displayName} Add Humidity Sensor Service`);
|
|
120
|
+
(this.humidityservice =
|
|
121
|
+
this.accessory.getService(this.platform.Service.HumiditySensor) || this.accessory.addService(this.platform.Service.HumiditySensor)),
|
|
122
|
+
`${accessory.displayName} Humidity Sensor`;
|
|
123
|
+
|
|
124
|
+
this.humidityservice.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Humidity Sensor`);
|
|
125
|
+
|
|
126
|
+
this.humidityservice
|
|
127
|
+
.getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity)
|
|
128
|
+
.setProps({
|
|
129
|
+
minStep: 0.1,
|
|
130
|
+
})
|
|
131
|
+
.onGet(() => {
|
|
132
|
+
return this.CurrentRelativeHumidity;
|
|
133
|
+
});
|
|
134
|
+
} else {
|
|
135
|
+
this.debugLog(`Meter Plus: ${accessory.displayName} Humidity Sensor Service Not Added`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Battery Service
|
|
139
|
+
if (!device.ble) {
|
|
140
|
+
this.debugLog(`Meter Plus: ${accessory.displayName} Removing Battery Service`);
|
|
141
|
+
this.batteryService = this.accessory.getService(this.platform.Service.Battery);
|
|
142
|
+
accessory.removeService(this.batteryService!);
|
|
143
|
+
} else if (device.ble && !this.batteryService) {
|
|
144
|
+
this.debugLog(`Meter Plus: ${accessory.displayName} Add Battery Service`);
|
|
145
|
+
(this.batteryService = this.accessory.getService(this.platform.Service.Battery) || this.accessory.addService(this.platform.Service.Battery)),
|
|
146
|
+
`${accessory.displayName} Battery`;
|
|
147
|
+
|
|
148
|
+
this.batteryService.setCharacteristic(this.platform.Characteristic.Name, `${accessory.displayName} Battery`);
|
|
149
|
+
|
|
150
|
+
this.batteryService.setCharacteristic(this.platform.Characteristic.ChargingState, this.platform.Characteristic.ChargingState.NOT_CHARGEABLE);
|
|
151
|
+
} else {
|
|
152
|
+
this.debugLog(`Meter Plus: ${accessory.displayName} Battery Service Not Added`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Retrieve initial values and updateHomekit
|
|
156
|
+
this.updateHomeKitCharacteristics();
|
|
157
|
+
|
|
158
|
+
// Start an update interval
|
|
159
|
+
interval(this.deviceRefreshRate * 1000)
|
|
160
|
+
.pipe(skipWhile(() => this.meterUpdateInProgress))
|
|
161
|
+
.subscribe(async () => {
|
|
162
|
+
await this.refreshStatus();
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Parse the device status from the SwitchBot api
|
|
168
|
+
*/
|
|
169
|
+
async parseStatus(): Promise<void> {
|
|
170
|
+
if (this.SwitchToOpenAPI || !this.device.ble) {
|
|
171
|
+
await this.openAPIparseStatus();
|
|
172
|
+
} else {
|
|
173
|
+
await this.BLEparseStatus();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async BLEparseStatus(): Promise<void> {
|
|
178
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} BLE parseStatus`);
|
|
179
|
+
|
|
180
|
+
// Battery
|
|
181
|
+
this.BatteryLevel = Number(this.battery);
|
|
182
|
+
if (this.BatteryLevel < 15) {
|
|
183
|
+
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
|
|
184
|
+
} else {
|
|
185
|
+
this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
|
|
186
|
+
}
|
|
187
|
+
this.debugLog(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
|
|
188
|
+
|
|
189
|
+
// Humidity
|
|
190
|
+
if (!this.device.meter?.hide_humidity) {
|
|
191
|
+
this.CurrentRelativeHumidity = this.humidity!;
|
|
192
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Current Temperature
|
|
196
|
+
if (!this.device.meter?.hide_temperature) {
|
|
197
|
+
this.temperature < 0 ? 0 : this.temperature > 100 ? 100 : this.temperature;
|
|
198
|
+
this.CurrentTemperature = this.temperature;
|
|
199
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async openAPIparseStatus(): Promise<void> {
|
|
204
|
+
if (this.device.ble) {
|
|
205
|
+
this.SwitchToOpenAPI = false;
|
|
206
|
+
}
|
|
207
|
+
if (this.platform.config.credentials?.openToken) {
|
|
208
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} OpenAPI parseStatus`);
|
|
209
|
+
// Current Relative Humidity
|
|
210
|
+
if (!this.device.meter?.hide_humidity) {
|
|
211
|
+
this.CurrentRelativeHumidity = this.Humidity!;
|
|
212
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Humidity: ${this.CurrentRelativeHumidity}%`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Current Temperature
|
|
216
|
+
if (!this.device.meter?.hide_temperature) {
|
|
217
|
+
this.CurrentTemperature = this.Temperature!;
|
|
218
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Asks the SwitchBot API for the latest device information
|
|
225
|
+
*/
|
|
226
|
+
async refreshStatus(): Promise<void> {
|
|
227
|
+
if (this.device.ble) {
|
|
228
|
+
this.BLErefreshStatus();
|
|
229
|
+
} else {
|
|
230
|
+
this.openAPIRefreshStatus();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async BLErefreshStatus(): Promise<void> {
|
|
235
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} BLE RefreshStatus`);
|
|
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(`Meter Plus: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
|
|
243
|
+
this.getCustomBLEAddress(switchbot);
|
|
244
|
+
// Start to monitor advertisement packets
|
|
245
|
+
if (switchbot !== false) {
|
|
246
|
+
switchbot
|
|
247
|
+
.startScan({
|
|
248
|
+
model: 'i',
|
|
249
|
+
id: this.device.bleMac,
|
|
250
|
+
})
|
|
251
|
+
.then(() => {
|
|
252
|
+
// Set an event hander
|
|
253
|
+
switchbot.onadvertisement = (ad: ad) => {
|
|
254
|
+
this.address = ad.address;
|
|
255
|
+
if (this.deviceLogging.includes('debug')) {
|
|
256
|
+
this.infoLog(this.address);
|
|
257
|
+
this.infoLog(this.device.bleMac);
|
|
258
|
+
this.infoLog(`Meter Plus: ${this.accessory.displayName} BLE Address Found: ${this.address}`);
|
|
259
|
+
this.infoLog(`Meter Plus: ${this.accessory.displayName} Config BLE Address: ${this.device.bleMac}`);
|
|
260
|
+
}
|
|
261
|
+
this.serviceData = ad.serviceData;
|
|
262
|
+
this.temperature = ad.serviceData.temperature!.c;
|
|
263
|
+
this.humidity = ad.serviceData.humidity;
|
|
264
|
+
this.battery = ad.serviceData.battery;
|
|
265
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
|
|
266
|
+
this.debugLog(
|
|
267
|
+
`Meter Plus: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, ` +
|
|
268
|
+
`temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, ` +
|
|
269
|
+
`battery: ${ad.serviceData.battery}`,
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
if (this.serviceData) {
|
|
273
|
+
this.connected = true;
|
|
274
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
275
|
+
} else {
|
|
276
|
+
this.connected = false;
|
|
277
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} connected: ${this.connected}`);
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
// Wait 10 seconds
|
|
281
|
+
return switchbot.wait(this.scanDuration * 1000);
|
|
282
|
+
})
|
|
283
|
+
.then(async () => {
|
|
284
|
+
// Stop to monitor
|
|
285
|
+
switchbot.stopScan();
|
|
286
|
+
if (this.connected) {
|
|
287
|
+
this.parseStatus();
|
|
288
|
+
this.updateHomeKitCharacteristics();
|
|
289
|
+
} else {
|
|
290
|
+
await this.BLEconnection(switchbot);
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
.catch(async (e: any) => {
|
|
294
|
+
this.errorLog(`Meter Plus: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
|
|
295
|
+
if (this.deviceLogging.includes('debug')) {
|
|
296
|
+
this.errorLog(
|
|
297
|
+
`Meter Plus: ${this.accessory.displayName} failed refreshStatus with BLE Connection,` + ` Error Message: ${JSON.stringify(e.message)}`,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
if (this.platform.config.credentials?.openToken) {
|
|
301
|
+
this.warnLog(`Meter Plus: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
302
|
+
this.SwitchToOpenAPI = true;
|
|
303
|
+
this.openAPIRefreshStatus();
|
|
304
|
+
}
|
|
305
|
+
this.apiError(e);
|
|
306
|
+
});
|
|
307
|
+
} else {
|
|
308
|
+
await this.BLEconnection(switchbot);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async getCustomBLEAddress(switchbot: any) {
|
|
313
|
+
if (this.device.customBLEaddress && this.deviceLogging.includes('debug')) {
|
|
314
|
+
(async () => {
|
|
315
|
+
// Start to monitor advertisement packets
|
|
316
|
+
await switchbot.startScan({
|
|
317
|
+
model: 'i',
|
|
318
|
+
});
|
|
319
|
+
// Set an event handler
|
|
320
|
+
switchbot.onadvertisement = (ad: any) => {
|
|
321
|
+
this.warnLog(JSON.stringify(ad, null, ' '));
|
|
322
|
+
};
|
|
323
|
+
await switchbot.wait(10000);
|
|
324
|
+
// Stop to monitor
|
|
325
|
+
switchbot.stopScan();
|
|
326
|
+
})();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async BLEconnection(switchbot: any): Promise<void> {
|
|
331
|
+
this.errorLog(`Meter Plus: ${this.accessory.displayName} wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
|
|
332
|
+
if (this.platform.config.credentials?.openToken) {
|
|
333
|
+
this.warnLog(`Meter Plus: ${this.accessory.displayName} Using OpenAPI Connection`);
|
|
334
|
+
this.SwitchToOpenAPI = true;
|
|
335
|
+
await this.openAPIRefreshStatus();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async openAPIRefreshStatus(): Promise<void> {
|
|
340
|
+
if (this.platform.config.credentials?.openToken) {
|
|
341
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} OpenAPI RefreshStatus`);
|
|
342
|
+
try {
|
|
343
|
+
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
|
|
344
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} openAPIRefreshStatus: ${JSON.stringify(this.deviceStatus)}`);
|
|
345
|
+
this.Humidity = this.deviceStatus.body.humidity!;
|
|
346
|
+
this.Temperature = this.deviceStatus.body.temperature!;
|
|
347
|
+
this.parseStatus();
|
|
348
|
+
this.updateHomeKitCharacteristics();
|
|
349
|
+
} catch (e: any) {
|
|
350
|
+
this.errorLog(`Meter Plus: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
|
|
351
|
+
if (this.deviceLogging.includes('debug')) {
|
|
352
|
+
this.errorLog(
|
|
353
|
+
`Meter Plus: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,` +
|
|
354
|
+
` Error Message: ${JSON.stringify(e.message)}`,
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
this.apiError(e);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Updates the status for each of the HomeKit Characteristics
|
|
364
|
+
*/
|
|
365
|
+
async updateHomeKitCharacteristics(): Promise<void> {
|
|
366
|
+
if (!this.device.meter?.hide_humidity) {
|
|
367
|
+
if (this.CurrentRelativeHumidity === undefined) {
|
|
368
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
|
|
369
|
+
} else {
|
|
370
|
+
this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
|
|
371
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (!this.device.meter?.hide_temperature) {
|
|
375
|
+
if (this.CurrentTemperature === undefined) {
|
|
376
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
|
|
377
|
+
} else {
|
|
378
|
+
this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature);
|
|
379
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (this.device.ble) {
|
|
383
|
+
if (this.BatteryLevel === undefined) {
|
|
384
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}`);
|
|
385
|
+
} else {
|
|
386
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.BatteryLevel);
|
|
387
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.BatteryLevel}`);
|
|
388
|
+
}
|
|
389
|
+
if (this.StatusLowBattery === undefined) {
|
|
390
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} StatusLowBattery: ${this.StatusLowBattery}`);
|
|
391
|
+
} else {
|
|
392
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.StatusLowBattery);
|
|
393
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.StatusLowBattery}`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
async apiError(e: any): Promise<void> {
|
|
399
|
+
if (!this.device.meter?.hide_humidity) {
|
|
400
|
+
this.humidityservice?.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, e);
|
|
401
|
+
}
|
|
402
|
+
if (!this.device.meter?.hide_temperature) {
|
|
403
|
+
this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
|
|
404
|
+
}
|
|
405
|
+
if (this.device.ble) {
|
|
406
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.BatteryLevel, e);
|
|
407
|
+
this.batteryService?.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, e);
|
|
408
|
+
}
|
|
409
|
+
//throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
model(device: device & devicesConfig): CharacteristicValue {
|
|
413
|
+
let model: string;
|
|
414
|
+
if (device.deviceType === 'Meter Plus (JP)') {
|
|
415
|
+
model = 'W2201500';
|
|
416
|
+
} else {
|
|
417
|
+
model = 'W2301500';
|
|
418
|
+
}
|
|
419
|
+
return model;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
async config(device: device & devicesConfig): Promise<void> {
|
|
423
|
+
let config = {};
|
|
424
|
+
if (device.meter) {
|
|
425
|
+
config = device.meter;
|
|
426
|
+
}
|
|
427
|
+
if (device.ble !== undefined) {
|
|
428
|
+
config['ble'] = device.ble;
|
|
429
|
+
}
|
|
430
|
+
if (device.logging !== undefined) {
|
|
431
|
+
config['logging'] = device.logging;
|
|
432
|
+
}
|
|
433
|
+
if (device.refreshRate !== undefined) {
|
|
434
|
+
config['refreshRate'] = device.refreshRate;
|
|
435
|
+
}
|
|
436
|
+
if (device.scanDuration !== undefined) {
|
|
437
|
+
config['scanDuration'] = device.scanDuration;
|
|
438
|
+
}
|
|
439
|
+
if (Object.entries(config).length !== 0) {
|
|
440
|
+
this.infoLog(`Meter Plus: ${this.accessory.displayName} Config: ${JSON.stringify(config)}`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
async refreshRate(device: device & devicesConfig): Promise<void> {
|
|
445
|
+
if (device.refreshRate) {
|
|
446
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = device.refreshRate;
|
|
447
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Device Config refreshRate: ${this.deviceRefreshRate}`);
|
|
448
|
+
} else if (this.platform.config.options!.refreshRate) {
|
|
449
|
+
this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
|
|
450
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
async scan(device: device & devicesConfig): Promise<void> {
|
|
455
|
+
if (device.scanDuration) {
|
|
456
|
+
this.scanDuration = this.accessory.context.scanDuration = device.scanDuration;
|
|
457
|
+
if (device.ble) {
|
|
458
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Device Config scanDuration: ${this.scanDuration}`);
|
|
459
|
+
}
|
|
460
|
+
} else {
|
|
461
|
+
this.scanDuration = this.accessory.context.scanDuration = 1;
|
|
462
|
+
if (this.device.ble) {
|
|
463
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Default scanDuration: ${this.scanDuration}`);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async logs(device: device & devicesConfig): Promise<void> {
|
|
469
|
+
if (this.platform.debugMode) {
|
|
470
|
+
this.deviceLogging = this.accessory.context.logging = 'debugMode';
|
|
471
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Debug Mode Logging: ${this.deviceLogging}`);
|
|
472
|
+
} else if (device.logging) {
|
|
473
|
+
this.deviceLogging = this.accessory.context.logging = device.logging;
|
|
474
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Device Config Logging: ${this.deviceLogging}`);
|
|
475
|
+
} else if (this.platform.config.options?.logging) {
|
|
476
|
+
this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
|
|
477
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Using Platform Config Logging: ${this.deviceLogging}`);
|
|
478
|
+
} else {
|
|
479
|
+
this.deviceLogging = this.accessory.context.logging = 'standard';
|
|
480
|
+
this.debugLog(`Meter Plus: ${this.accessory.displayName} Logging Not Set, Using: ${this.deviceLogging}`);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Logging for Device
|
|
486
|
+
*/
|
|
487
|
+
infoLog(...log: any[]): void {
|
|
488
|
+
if (this.enablingDeviceLogging()) {
|
|
489
|
+
this.platform.log.info(String(...log));
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
warnLog(...log: any[]): void {
|
|
494
|
+
if (this.enablingDeviceLogging()) {
|
|
495
|
+
this.platform.log.warn(String(...log));
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
errorLog(...log: any[]): void {
|
|
500
|
+
if (this.enablingDeviceLogging()) {
|
|
501
|
+
this.platform.log.error(String(...log));
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
debugLog(...log: any[]): void {
|
|
506
|
+
if (this.enablingDeviceLogging()) {
|
|
507
|
+
if (this.deviceLogging === 'debug') {
|
|
508
|
+
this.platform.log.info('[DEBUG]', String(...log));
|
|
509
|
+
} else {
|
|
510
|
+
this.platform.log.debug(String(...log));
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
enablingDeviceLogging(): boolean {
|
|
516
|
+
return this.deviceLogging.includes('debug') || this.deviceLogging === 'standard';
|
|
517
|
+
}
|
|
518
|
+
}
|
package/src/device/plug.ts
CHANGED
|
@@ -59,7 +59,7 @@ export class Plug {
|
|
|
59
59
|
|
|
60
60
|
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
|
|
61
61
|
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
|
|
62
|
-
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.
|
|
62
|
+
// accessory.getService('NAME') ?? accessory.addService(this.platform.Service.Outlet, 'NAME', 'USER_DEFINED_SUBTYPE');
|
|
63
63
|
|
|
64
64
|
// set the service name, this is what is displayed as the default name on the Home app
|
|
65
65
|
// in this example we are using the name we stored in the `accessory.context` in the `discoverDevices` method.
|