node-switchbot 3.6.0-beta.1 → 3.6.0-beta.3
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 +19 -0
- package/dist/device.d.ts +110 -5
- package/dist/device.d.ts.map +1 -1
- package/dist/device.js +297 -78
- package/dist/device.js.map +1 -1
- package/dist/device.test.d.ts +2 -0
- package/dist/device.test.d.ts.map +1 -0
- package/dist/device.test.js +152 -0
- package/dist/device.test.js.map +1 -0
- package/dist/index.d.ts +4 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -7
- package/dist/index.js.map +1 -1
- package/dist/parameter-checker.d.ts +1 -0
- package/dist/parameter-checker.d.ts.map +1 -1
- package/dist/parameter-checker.js +19 -11
- package/dist/parameter-checker.js.map +1 -1
- package/dist/parameter-checker.test.d.ts +2 -0
- package/dist/parameter-checker.test.d.ts.map +1 -0
- package/dist/parameter-checker.test.js +56 -0
- package/dist/parameter-checker.test.js.map +1 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +21 -16
- package/dist/settings.js.map +1 -1
- package/dist/settings.test.js +13 -1
- package/dist/settings.test.js.map +1 -1
- package/dist/switchbot-ble.d.ts +7 -4
- package/dist/switchbot-ble.d.ts.map +1 -1
- package/dist/switchbot-ble.js +77 -37
- package/dist/switchbot-ble.js.map +1 -1
- package/dist/switchbot-ble.test.d.ts +2 -0
- package/dist/switchbot-ble.test.d.ts.map +1 -0
- package/dist/switchbot-ble.test.js +32 -0
- package/dist/switchbot-ble.test.js.map +1 -0
- package/dist/switchbot-openapi.d.ts +4 -7
- package/dist/switchbot-openapi.d.ts.map +1 -1
- package/dist/switchbot-openapi.js +19 -10
- package/dist/switchbot-openapi.js.map +1 -1
- package/dist/switchbot-openapi.test.d.ts +2 -0
- package/dist/switchbot-openapi.test.d.ts.map +1 -0
- package/dist/switchbot-openapi.test.js +36 -0
- package/dist/switchbot-openapi.test.js.map +1 -0
- package/dist/types/ble-guards.d.ts +12 -0
- package/dist/types/ble-guards.d.ts.map +1 -0
- package/dist/types/ble-guards.js +10 -0
- package/dist/types/ble-guards.js.map +1 -0
- package/dist/types/ble-guards.test.d.ts +2 -0
- package/dist/types/ble-guards.test.d.ts.map +1 -0
- package/dist/types/ble-guards.test.js +62 -0
- package/dist/types/ble-guards.test.js.map +1 -0
- package/dist/types/{bledevicestatus.d.ts → ble.d.ts} +97 -116
- package/dist/types/ble.d.ts.map +1 -0
- package/dist/types/ble.js +2 -0
- package/dist/types/ble.js.map +1 -0
- package/dist/types/openapi.d.ts +560 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +3 -0
- package/dist/types/openapi.js.map +1 -0
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/Advertising.html +4 -4
- package/docs/classes/ErrorUtils.html +25 -0
- package/docs/classes/ParameterChecker.html +69 -0
- package/docs/classes/SwitchBotBLE.html +8 -10
- package/docs/classes/SwitchBotOpenAPI.html +9 -9
- package/docs/classes/SwitchbotDevice.html +12 -12
- package/docs/classes/ValidationUtils.html +51 -0
- package/docs/classes/WoBlindTilt.html +21 -21
- package/docs/classes/WoBulb.html +19 -19
- package/docs/classes/WoCeilingLight.html +22 -22
- package/docs/classes/WoContact.html +13 -13
- package/docs/classes/WoCurtain.html +18 -18
- package/docs/classes/WoHand.html +18 -18
- package/docs/classes/WoHub2.html +13 -13
- package/docs/classes/WoHumi.html +20 -20
- package/docs/classes/WoHumi2.html +20 -20
- package/docs/classes/WoIOSensorTH.html +13 -13
- package/docs/classes/WoKeypad.html +13 -13
- package/docs/classes/WoLeak.html +13 -13
- package/docs/classes/WoPlugMiniJP.html +18 -18
- package/docs/classes/WoPlugMiniUS.html +18 -18
- package/docs/classes/WoPresence.html +13 -13
- package/docs/classes/WoRelaySwitch1.html +15 -15
- package/docs/classes/WoRelaySwitch1PM.html +15 -15
- package/docs/classes/WoRemote.html +13 -13
- package/docs/classes/WoSensorTH.html +12 -12
- package/docs/classes/WoSensorTHPlus.html +12 -12
- package/docs/classes/WoSensorTHPro.html +12 -12
- package/docs/classes/WoSensorTHProCO2.html +12 -12
- package/docs/classes/WoSmartLock.html +23 -23
- package/docs/classes/WoSmartLockPro.html +23 -23
- package/docs/classes/WoStrip.html +20 -20
- package/docs/enums/LogLevel.html +2 -2
- package/docs/enums/SwitchBotBLEModel.html +2 -2
- package/docs/enums/SwitchBotBLEModelFriendlyName.html +2 -2
- package/docs/enums/SwitchBotBLEModelName.html +2 -2
- package/docs/enums/SwitchBotModel.html +2 -2
- package/docs/functions/updateBaseURL.html +3 -0
- package/docs/hierarchy.html +1 -1
- package/docs/interfaces/AdvertisementData.html +2 -2
- package/docs/interfaces/Chars.html +2 -2
- package/docs/interfaces/ColorLightServiceDataBase.html +17 -0
- package/docs/interfaces/ErrorObject.html +2 -2
- package/docs/interfaces/LockBaseServiceData.html +15 -0
- package/docs/interfaces/NobleTypes.html +2 -2
- package/docs/interfaces/Params.html +2 -2
- package/docs/interfaces/PlugMiniServiceDataBase.html +12 -0
- package/docs/interfaces/{pushResponse.html → PushResponse.html} +3 -2
- package/docs/interfaces/Rule.html +2 -2
- package/docs/interfaces/ServiceData.html +2 -2
- package/docs/interfaces/SwitchBotBLEDevice.html +2 -2
- package/docs/interfaces/SwitchBotScanner.html +6 -0
- package/docs/interfaces/TemperatureServiceDataBase.html +10 -0
- package/docs/interfaces/WebhookDetail.html +2 -2
- package/docs/interfaces/ad.html +2 -2
- package/docs/interfaces/body.html +2 -2
- package/docs/interfaces/deleteWebhookResponse.html +2 -2
- package/docs/interfaces/device.html +2 -2
- package/docs/interfaces/deviceList.html +2 -2
- package/docs/interfaces/deviceStatus.html +2 -2
- package/docs/interfaces/deviceStatusRequest.html +2 -2
- package/docs/interfaces/deviceWebhook.html +2 -2
- package/docs/interfaces/deviceWebhookContext.html +2 -2
- package/docs/interfaces/devices.html +2 -2
- package/docs/interfaces/infraredRemoteList.html +2 -2
- package/docs/interfaces/irdevice.html +2 -2
- package/docs/interfaces/pushRequest.html +5 -0
- package/docs/interfaces/pushResponseBody.html +3 -0
- package/docs/interfaces/queryWebhookResponse.html +2 -2
- package/docs/interfaces/setupWebhookResponse.html +2 -2
- package/docs/interfaces/updateWebhookResponse.html +2 -2
- package/docs/interfaces/webhookRequest.html +2 -2
- package/docs/modules.html +1 -1
- package/docs/types/BLEDeviceServiceData.html +1 -0
- package/docs/types/{indoorCam.html → IndoorCam.html} +1 -1
- package/docs/types/MacAddress.html +1 -1
- package/docs/types/batteryCirculatorFan.html +1 -1
- package/docs/types/batteryCirculatorFanServiceData.html +1 -1
- package/docs/types/batteryCirculatorFanStatus.html +1 -1
- package/docs/types/batteryCirculatorFanWebhookContext.html +1 -1
- package/docs/types/blindTilt.html +1 -1
- package/docs/types/blindTiltServiceData.html +1 -1
- package/docs/types/blindTiltStatus.html +1 -1
- package/docs/types/blindTiltWebhookContext.html +1 -1
- package/docs/types/bot.html +1 -1
- package/docs/types/botServiceData.html +1 -1
- package/docs/types/botStatus.html +1 -1
- package/docs/types/botWebhookContext.html +1 -1
- package/docs/types/ceilingLight.html +1 -1
- package/docs/types/ceilingLightPro.html +1 -1
- package/docs/types/ceilingLightProServiceData.html +1 -1
- package/docs/types/ceilingLightProStatus.html +1 -1
- package/docs/types/ceilingLightProWebhookContext.html +1 -1
- package/docs/types/ceilingLightServiceData.html +1 -1
- package/docs/types/ceilingLightStatus.html +1 -1
- package/docs/types/ceilingLightWebhookContext.html +1 -1
- package/docs/types/circulatorFanStatus.html +1 -1
- package/docs/types/circulatorFanWebhookContext.html +1 -1
- package/docs/types/colorBulb.html +1 -1
- package/docs/types/colorBulbServiceData.html +1 -1
- package/docs/types/colorBulbStatus.html +1 -1
- package/docs/types/colorBulbWebhookContext.html +1 -1
- package/docs/types/commandType.html +2 -0
- package/docs/types/contactSensor.html +1 -1
- package/docs/types/contactSensorServiceData.html +1 -1
- package/docs/types/contactSensorStatus.html +1 -1
- package/docs/types/contactSensorWebhookContext.html +1 -1
- package/docs/types/curtain.html +1 -1
- package/docs/types/curtain3.html +1 -1
- package/docs/types/curtain3ServiceData.html +1 -1
- package/docs/types/curtain3WebhookContext.html +1 -1
- package/docs/types/curtainServiceData.html +1 -1
- package/docs/types/curtainStatus.html +1 -1
- package/docs/types/curtainWebhookContext.html +1 -1
- package/docs/types/floorCleaningRobotS10.html +1 -1
- package/docs/types/floorCleaningRobotS10Status.html +1 -1
- package/docs/types/floorCleaningRobotS10WebhookContext.html +1 -1
- package/docs/types/hub2.html +1 -1
- package/docs/types/hub2ServiceData.html +1 -1
- package/docs/types/hub2Status.html +1 -1
- package/docs/types/hub2WebhookContext.html +1 -1
- package/docs/types/humidifier.html +1 -1
- package/docs/types/humidifier2ServiceData.html +1 -1
- package/docs/types/humidifier2Status.html +1 -1
- package/docs/types/humidifier2WebhookContext.html +1 -1
- package/docs/types/humidifierServiceData.html +1 -1
- package/docs/types/humidifierStatus.html +1 -1
- package/docs/types/humidifierWebhookContext.html +1 -1
- package/docs/types/indoorCameraWebhookContext.html +1 -1
- package/docs/types/keypad.html +1 -1
- package/docs/types/keypadDetectorServiceData.html +1 -1
- package/docs/types/keypadTouch.html +1 -1
- package/docs/types/keypadTouchWebhookContext.html +1 -1
- package/docs/types/keypadWebhookContext.html +1 -1
- package/docs/types/lock.html +1 -1
- package/docs/types/lockPro.html +1 -1
- package/docs/types/lockProServiceData.html +1 -1
- package/docs/types/lockProStatus.html +1 -1
- package/docs/types/lockProWebhookContext.html +1 -1
- package/docs/types/lockServiceData.html +1 -1
- package/docs/types/lockStatus.html +1 -1
- package/docs/types/lockWebhookContext.html +1 -1
- package/docs/types/meter.html +1 -1
- package/docs/types/meterPlus.html +1 -1
- package/docs/types/meterPlusServiceData.html +1 -1
- package/docs/types/meterPlusStatus.html +1 -1
- package/docs/types/meterPlusWebhookContext.html +1 -1
- package/docs/types/meterPro.html +1 -1
- package/docs/types/meterProCO2ServiceData.html +1 -1
- package/docs/types/meterProCO2Status.html +1 -1
- package/docs/types/meterProCO2WebhookContext.html +1 -1
- package/docs/types/meterProServiceData.html +1 -1
- package/docs/types/meterProStatus.html +1 -1
- package/docs/types/meterProWebhookContext.html +1 -1
- package/docs/types/meterServiceData.html +1 -1
- package/docs/types/meterStatus.html +1 -1
- package/docs/types/meterWebhookContext.html +1 -1
- package/docs/types/motionSensor.html +1 -1
- package/docs/types/motionSensorServiceData.html +1 -1
- package/docs/types/motionSensorStatus.html +1 -1
- package/docs/types/motionSensorWebhookContext.html +1 -1
- package/docs/types/onadvertisement.html +1 -1
- package/docs/types/ondiscover.html +1 -1
- package/docs/types/outdoorMeter.html +1 -1
- package/docs/types/outdoorMeterServiceData.html +1 -1
- package/docs/types/outdoorMeterStatus.html +1 -1
- package/docs/types/outdoorMeterWebhookContext.html +1 -1
- package/docs/types/panTiltCamWebhookContext.html +1 -1
- package/docs/types/pantiltCam.html +1 -1
- package/docs/types/pantiltCam2k.html +1 -1
- package/docs/types/plug.html +1 -1
- package/docs/types/plugMini.html +1 -1
- package/docs/types/plugMiniJPServiceData.html +1 -1
- package/docs/types/plugMiniJPWebhookContext.html +1 -1
- package/docs/types/plugMiniStatus.html +1 -1
- package/docs/types/plugMiniUSServiceData.html +1 -1
- package/docs/types/plugMiniUSWebhookContext.html +1 -1
- package/docs/types/plugStatus.html +1 -1
- package/docs/types/plugWebhookContext.html +1 -1
- package/docs/types/relaySwitch1Context.html +1 -1
- package/docs/types/relaySwitch1PMContext.html +1 -1
- package/docs/types/relaySwitch1PMServiceData.html +1 -1
- package/docs/types/relaySwitch1PMStatus.html +1 -1
- package/docs/types/relaySwitch1ServiceData.html +1 -1
- package/docs/types/relaySwitch1Status.html +1 -1
- package/docs/types/remote.html +1 -1
- package/docs/types/remoteServiceData.html +1 -1
- package/docs/types/robotVacuumCleanerS1.html +1 -1
- package/docs/types/robotVacuumCleanerS1Plus.html +1 -1
- package/docs/types/robotVacuumCleanerS1PlusStatus.html +1 -1
- package/docs/types/robotVacuumCleanerS1PlusWebhookContext.html +1 -1
- package/docs/types/robotVacuumCleanerS1Status.html +1 -1
- package/docs/types/robotVacuumCleanerS1WebhookContext.html +1 -1
- package/docs/types/robotVacuumCleanerServiceData.html +1 -1
- package/docs/types/stripLight.html +1 -1
- package/docs/types/stripLightServiceData.html +1 -1
- package/docs/types/stripLightStatus.html +1 -1
- package/docs/types/stripLightWebhookContext.html +1 -1
- package/docs/types/waterLeakDetector.html +1 -1
- package/docs/types/waterLeakDetectorServiceData.html +1 -1
- package/docs/types/waterLeakDetectorStatus.html +1 -1
- package/docs/types/waterLeakDetectorWebhookContext.html +1 -1
- package/docs/variables/parameterChecker.html +1 -0
- package/docs/variables/urls.html +1 -0
- package/package.json +6 -6
- package/dist/types/bledevicestatus.d.ts.map +0 -1
- package/dist/types/bledevicestatus.js +0 -2
- package/dist/types/bledevicestatus.js.map +0 -1
- package/dist/types/devicelist.d.ts +0 -90
- package/dist/types/devicelist.d.ts.map +0 -1
- package/dist/types/devicelist.js +0 -2
- package/dist/types/devicelist.js.map +0 -1
- package/dist/types/devicepush.d.ts +0 -13
- package/dist/types/devicepush.d.ts.map +0 -1
- package/dist/types/devicepush.js +0 -2
- package/dist/types/devicepush.js.map +0 -1
- package/dist/types/deviceresponse.d.ts +0 -12
- package/dist/types/deviceresponse.d.ts.map +0 -1
- package/dist/types/deviceresponse.js +0 -2
- package/dist/types/deviceresponse.js.map +0 -1
- package/dist/types/devicestatus.d.ts +0 -194
- package/dist/types/devicestatus.d.ts.map +0 -1
- package/dist/types/devicestatus.js +0 -3
- package/dist/types/devicestatus.js.map +0 -1
- package/dist/types/devicewebhookstatus.d.ts +0 -236
- package/dist/types/devicewebhookstatus.d.ts.map +0 -1
- package/dist/types/devicewebhookstatus.js +0 -2
- package/dist/types/devicewebhookstatus.js.map +0 -1
- package/dist/types/irdevicelist.d.ts +0 -10
- package/dist/types/irdevicelist.d.ts.map +0 -1
- package/dist/types/irdevicelist.js +0 -2
- package/dist/types/irdevicelist.js.map +0 -1
- package/docs/interfaces/bodyChange.html +0 -4
- package/docs/interfaces/switchbot.html +0 -3
- package/jest.config.js +0 -3
package/dist/device.js
CHANGED
|
@@ -1,15 +1,52 @@
|
|
|
1
1
|
import { Buffer } from 'node:buffer';
|
|
2
2
|
import * as Crypto from 'node:crypto';
|
|
3
3
|
import { EventEmitter } from 'node:events';
|
|
4
|
-
import { parameterChecker } from './parameter-checker.js';
|
|
5
4
|
import { CHAR_UUID_DEVICE, CHAR_UUID_NOTIFY, CHAR_UUID_WRITE, READ_TIMEOUT_MSEC, SERV_UUID_PRIMARY, WoSmartLockCommands, WoSmartLockProCommands, WRITE_TIMEOUT_MSEC } from './settings.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Command constants for various SwitchBot devices.
|
|
7
|
+
* Using readonly arrays to ensure immutability and better type safety.
|
|
8
|
+
*/
|
|
9
|
+
const DEVICE_COMMANDS = {
|
|
10
|
+
BLIND_TILT: {
|
|
11
|
+
OPEN: [0x57, 0x0F, 0x45, 0x01, 0x05, 0xFF, 0x32],
|
|
12
|
+
CLOSE_UP: [0x57, 0x0F, 0x45, 0x01, 0x05, 0xFF, 0x64],
|
|
13
|
+
CLOSE_DOWN: [0x57, 0x0F, 0x45, 0x01, 0x05, 0xFF, 0x00],
|
|
14
|
+
PAUSE: [0x57, 0x0F, 0x45, 0x01, 0x00, 0xFF],
|
|
15
|
+
},
|
|
16
|
+
BULB: {
|
|
17
|
+
BASE: [0x57, 0x0F, 0x47, 0x01],
|
|
18
|
+
READ_STATE: [0x57, 0x0F, 0x48, 0x01],
|
|
19
|
+
TURN_ON: [0x01, 0x01],
|
|
20
|
+
TURN_OFF: [0x01, 0x02],
|
|
21
|
+
SET_BRIGHTNESS: [0x02, 0x14],
|
|
22
|
+
SET_COLOR_TEMP: [0x02, 0x17],
|
|
23
|
+
SET_RGB: [0x02, 0x12],
|
|
24
|
+
},
|
|
25
|
+
HUMIDIFIER: {
|
|
26
|
+
HEADER: '5701',
|
|
27
|
+
TURN_ON: '570101',
|
|
28
|
+
TURN_OFF: '570102',
|
|
29
|
+
INCREASE: '570103',
|
|
30
|
+
DECREASE: '570104',
|
|
31
|
+
SET_AUTO_MODE: '570105',
|
|
32
|
+
SET_MANUAL_MODE: '570106',
|
|
33
|
+
},
|
|
34
|
+
// Common commands used across multiple devices
|
|
35
|
+
COMMON: {
|
|
36
|
+
POWER_ON: [0x57, 0x01, 0x01],
|
|
37
|
+
POWER_OFF: [0x57, 0x01, 0x02],
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
// Legacy constants for backward compatibility
|
|
41
|
+
const BLIND_TILT_COMMANDS = DEVICE_COMMANDS.BLIND_TILT;
|
|
42
|
+
const BULB_COMMANDS = DEVICE_COMMANDS.BULB;
|
|
43
|
+
const HUMIDIFIER_COMMAND_HEADER = DEVICE_COMMANDS.HUMIDIFIER.HEADER;
|
|
44
|
+
const TURN_ON_KEY = DEVICE_COMMANDS.HUMIDIFIER.TURN_ON;
|
|
45
|
+
const TURN_OFF_KEY = DEVICE_COMMANDS.HUMIDIFIER.TURN_OFF;
|
|
46
|
+
const INCREASE_KEY = DEVICE_COMMANDS.HUMIDIFIER.INCREASE;
|
|
47
|
+
const DECREASE_KEY = DEVICE_COMMANDS.HUMIDIFIER.DECREASE;
|
|
48
|
+
const SET_AUTO_MODE_KEY = DEVICE_COMMANDS.HUMIDIFIER.SET_AUTO_MODE;
|
|
49
|
+
const SET_MANUAL_MODE_KEY = DEVICE_COMMANDS.HUMIDIFIER.SET_MANUAL_MODE;
|
|
13
50
|
export var SwitchBotModel;
|
|
14
51
|
(function (SwitchBotModel) {
|
|
15
52
|
SwitchBotModel["HubMini"] = "W0202200";
|
|
@@ -166,6 +203,176 @@ export var LogLevel;
|
|
|
166
203
|
LogLevel["DEBUG"] = "debug";
|
|
167
204
|
LogLevel["INFO"] = "info";
|
|
168
205
|
})(LogLevel || (LogLevel = {}));
|
|
206
|
+
/**
|
|
207
|
+
* Utility class for comprehensive input validation with improved error messages.
|
|
208
|
+
*/
|
|
209
|
+
export class ValidationUtils {
|
|
210
|
+
/**
|
|
211
|
+
* Validates percentage value (0-100).
|
|
212
|
+
* @param value - The value to validate
|
|
213
|
+
* @param paramName - The parameter name for error reporting
|
|
214
|
+
* @throws {RangeError} When value is not within valid range
|
|
215
|
+
* @throws {TypeError} When value is not a number
|
|
216
|
+
*/
|
|
217
|
+
static validatePercentage(value, paramName = 'value') {
|
|
218
|
+
if (typeof value !== 'number' || Number.isNaN(value)) {
|
|
219
|
+
throw new TypeError(`${paramName} must be a valid number, got: ${value}`);
|
|
220
|
+
}
|
|
221
|
+
if (value < 0 || value > 100) {
|
|
222
|
+
throw new RangeError(`${paramName} must be between 0 and 100 inclusive, got: ${value}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Validates RGB color value (0-255).
|
|
227
|
+
* @param value - The color value to validate
|
|
228
|
+
* @param colorName - The color name for error reporting
|
|
229
|
+
* @throws {RangeError} When value is not within valid range
|
|
230
|
+
* @throws {TypeError} When value is not a number
|
|
231
|
+
*/
|
|
232
|
+
static validateRGB(value, colorName = 'color') {
|
|
233
|
+
if (typeof value !== 'number' || Number.isNaN(value)) {
|
|
234
|
+
throw new TypeError(`${colorName} must be a valid number, got: ${value}`);
|
|
235
|
+
}
|
|
236
|
+
if (!Number.isInteger(value) || value < 0 || value > 255) {
|
|
237
|
+
throw new RangeError(`${colorName} must be an integer between 0 and 255 inclusive, got: ${value}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Validates buffer and throws descriptive error.
|
|
242
|
+
* @param buffer - The buffer to validate
|
|
243
|
+
* @param expectedLength - Optional expected length
|
|
244
|
+
* @param paramName - The parameter name for error reporting
|
|
245
|
+
* @throws {TypeError} When buffer is not a Buffer
|
|
246
|
+
* @throws {RangeError} When buffer length doesn't match expected
|
|
247
|
+
*/
|
|
248
|
+
static validateBuffer(buffer, expectedLength, paramName = 'buffer') {
|
|
249
|
+
if (!Buffer.isBuffer(buffer)) {
|
|
250
|
+
throw new TypeError(`${paramName} must be a Buffer instance, got: ${typeof buffer}`);
|
|
251
|
+
}
|
|
252
|
+
if (expectedLength !== undefined && buffer.length !== expectedLength) {
|
|
253
|
+
throw new RangeError(`${paramName} must have exactly ${expectedLength} bytes, got: ${buffer.length} bytes`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Validates string input with comprehensive checks.
|
|
258
|
+
* @param value - The value to validate
|
|
259
|
+
* @param paramName - The parameter name for error reporting
|
|
260
|
+
* @param minLength - Minimum required length
|
|
261
|
+
* @param maxLength - Optional maximum length
|
|
262
|
+
* @throws {TypeError} When value is not a string
|
|
263
|
+
* @throws {RangeError} When string length is invalid
|
|
264
|
+
*/
|
|
265
|
+
static validateString(value, paramName = 'value', minLength = 1, maxLength) {
|
|
266
|
+
if (typeof value !== 'string') {
|
|
267
|
+
throw new TypeError(`${paramName} must be a string, got: ${typeof value}`);
|
|
268
|
+
}
|
|
269
|
+
if (value.length < minLength) {
|
|
270
|
+
throw new RangeError(`${paramName} must have at least ${minLength} character(s), got: ${value.length}`);
|
|
271
|
+
}
|
|
272
|
+
if (maxLength !== undefined && value.length > maxLength) {
|
|
273
|
+
throw new RangeError(`${paramName} must have at most ${maxLength} character(s), got: ${value.length}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Validates numeric range with enhanced checks.
|
|
278
|
+
* @param value - The value to validate
|
|
279
|
+
* @param min - Minimum allowed value
|
|
280
|
+
* @param max - Maximum allowed value
|
|
281
|
+
* @param paramName - The parameter name for error reporting
|
|
282
|
+
* @param mustBeInteger - Whether the value must be an integer
|
|
283
|
+
* @throws {TypeError} When value is not a number
|
|
284
|
+
* @throws {RangeError} When value is outside valid range
|
|
285
|
+
*/
|
|
286
|
+
static validateRange(value, min, max, paramName = 'value', mustBeInteger = false) {
|
|
287
|
+
if (typeof value !== 'number' || Number.isNaN(value)) {
|
|
288
|
+
throw new TypeError(`${paramName} must be a valid number, got: ${value}`);
|
|
289
|
+
}
|
|
290
|
+
if (mustBeInteger && !Number.isInteger(value)) {
|
|
291
|
+
throw new TypeError(`${paramName} must be an integer, got: ${value}`);
|
|
292
|
+
}
|
|
293
|
+
if (value < min || value > max) {
|
|
294
|
+
throw new RangeError(`${paramName} must be between ${min} and ${max} inclusive, got: ${value}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Validates MAC address format.
|
|
299
|
+
* @param address - The MAC address to validate
|
|
300
|
+
* @param paramName - The parameter name for error reporting
|
|
301
|
+
* @throws {TypeError} When address is not a string
|
|
302
|
+
* @throws {Error} When address format is invalid
|
|
303
|
+
*/
|
|
304
|
+
static validateMacAddress(address, paramName = 'address') {
|
|
305
|
+
if (typeof address !== 'string') {
|
|
306
|
+
throw new TypeError(`${paramName} must be a string`);
|
|
307
|
+
}
|
|
308
|
+
const macRegex = /^(?:[0-9A-F]{2}[:-]){5}[0-9A-F]{2}$|^[0-9A-F]{12}$/i;
|
|
309
|
+
if (!macRegex.test(address)) {
|
|
310
|
+
throw new Error(`${paramName} must be a valid MAC address format, got: ${address}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Validates that a value is one of the allowed enum values.
|
|
315
|
+
* @param value - The value to validate
|
|
316
|
+
* @param allowedValues - Array of allowed values
|
|
317
|
+
* @param paramName - The parameter name for error reporting
|
|
318
|
+
* @throws {Error} When value is not in allowed values
|
|
319
|
+
*/
|
|
320
|
+
static validateEnum(value, allowedValues, paramName = 'value') {
|
|
321
|
+
if (!allowedValues.includes(value)) {
|
|
322
|
+
throw new Error(`${paramName} must be one of: ${allowedValues.join(', ')}, got: ${value}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Enhanced error handling utilities.
|
|
328
|
+
*/
|
|
329
|
+
export class ErrorUtils {
|
|
330
|
+
/**
|
|
331
|
+
* Creates a timeout error with context.
|
|
332
|
+
* @param operation - The operation that timed out
|
|
333
|
+
* @param timeoutMs - The timeout duration in milliseconds
|
|
334
|
+
* @returns A descriptive timeout error
|
|
335
|
+
*/
|
|
336
|
+
static createTimeoutError(operation, timeoutMs) {
|
|
337
|
+
return new Error(`Operation '${operation}' timed out after ${timeoutMs}ms`);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Creates a connection error with context.
|
|
341
|
+
* @param deviceId - The device ID that failed to connect
|
|
342
|
+
* @param cause - The underlying cause of the connection failure
|
|
343
|
+
* @returns A descriptive connection error
|
|
344
|
+
*/
|
|
345
|
+
static createConnectionError(deviceId, cause) {
|
|
346
|
+
const message = `Failed to connect to device ${deviceId}`;
|
|
347
|
+
return cause ? new Error(`${message}: ${cause.message}`) : new Error(message);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Creates a command error with context.
|
|
351
|
+
* @param command - The command that failed
|
|
352
|
+
* @param deviceId - The device ID
|
|
353
|
+
* @param cause - The underlying cause
|
|
354
|
+
* @returns A descriptive command error
|
|
355
|
+
*/
|
|
356
|
+
static createCommandError(command, deviceId, cause) {
|
|
357
|
+
const message = `Command '${command}' failed for device ${deviceId}`;
|
|
358
|
+
return cause ? new Error(`${message}: ${cause.message}`) : new Error(message);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Wraps an async operation with timeout and enhanced error handling.
|
|
362
|
+
* @param operation - The async operation to wrap
|
|
363
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
364
|
+
* @param operationName - Name of the operation for error messages
|
|
365
|
+
* @returns Promise that resolves with the operation result or rejects with timeout
|
|
366
|
+
*/
|
|
367
|
+
static async withTimeout(operation, timeoutMs, operationName) {
|
|
368
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
369
|
+
setTimeout(() => {
|
|
370
|
+
reject(this.createTimeoutError(operationName, timeoutMs));
|
|
371
|
+
}, timeoutMs);
|
|
372
|
+
});
|
|
373
|
+
return Promise.race([operation, timeoutPromise]);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
169
376
|
/**
|
|
170
377
|
* Represents a Switchbot Device.
|
|
171
378
|
*/
|
|
@@ -345,8 +552,9 @@ export class SwitchbotDevice extends EventEmitter {
|
|
|
345
552
|
* @param service The service to discover characteristics for.
|
|
346
553
|
* @returns A Promise that resolves with the list of characteristics.
|
|
347
554
|
*/
|
|
348
|
-
|
|
349
|
-
|
|
555
|
+
// Discover characteristics without extra async/await
|
|
556
|
+
discoverCharacteristics(service) {
|
|
557
|
+
return service.discoverCharacteristicsAsync([]);
|
|
350
558
|
}
|
|
351
559
|
/**
|
|
352
560
|
* Subscribes to the notify characteristic.
|
|
@@ -404,12 +612,20 @@ export class SwitchbotDevice extends EventEmitter {
|
|
|
404
612
|
*/
|
|
405
613
|
async getDeviceName() {
|
|
406
614
|
await this.internalConnect();
|
|
407
|
-
|
|
408
|
-
|
|
615
|
+
try {
|
|
616
|
+
if (!this.characteristics?.device) {
|
|
617
|
+
throw new Error(`Characteristic ${CHAR_UUID_DEVICE} not supported`);
|
|
618
|
+
}
|
|
619
|
+
const buf = await this.readCharacteristic(this.characteristics.device);
|
|
620
|
+
return buf.toString('utf8');
|
|
621
|
+
}
|
|
622
|
+
catch (error) {
|
|
623
|
+
const deviceContext = `device ${this.deviceId || 'unknown'}`;
|
|
624
|
+
throw ErrorUtils.createCommandError('getDeviceName', deviceContext, error);
|
|
625
|
+
}
|
|
626
|
+
finally {
|
|
627
|
+
await this.internalDisconnect();
|
|
409
628
|
}
|
|
410
|
-
const buf = await this.readCharacteristic(this.characteristics.device);
|
|
411
|
-
await this.internalDisconnect();
|
|
412
|
-
return buf.toString('utf8');
|
|
413
629
|
}
|
|
414
630
|
/**
|
|
415
631
|
* Sets the device name.
|
|
@@ -417,17 +633,26 @@ export class SwitchbotDevice extends EventEmitter {
|
|
|
417
633
|
* @returns A Promise that resolves when the name is set.
|
|
418
634
|
*/
|
|
419
635
|
async setDeviceName(name) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
636
|
+
ValidationUtils.validateString(name, 'name', 1);
|
|
637
|
+
// Additional validation for device name length
|
|
638
|
+
const nameBuffer = Buffer.from(name, 'utf8');
|
|
639
|
+
if (nameBuffer.length > 100) {
|
|
640
|
+
throw new RangeError('Device name cannot exceed 100 bytes when encoded as UTF-8');
|
|
423
641
|
}
|
|
424
|
-
const buf = Buffer.from(name, 'utf8');
|
|
425
642
|
await this.internalConnect();
|
|
426
|
-
|
|
427
|
-
|
|
643
|
+
try {
|
|
644
|
+
if (!this.characteristics?.device) {
|
|
645
|
+
throw new Error(`Characteristic ${CHAR_UUID_DEVICE} not supported`);
|
|
646
|
+
}
|
|
647
|
+
await this.writeCharacteristic(this.characteristics.device, nameBuffer);
|
|
648
|
+
}
|
|
649
|
+
catch (error) {
|
|
650
|
+
const deviceContext = `device ${this.deviceId || 'unknown'}`;
|
|
651
|
+
throw ErrorUtils.createCommandError('setDeviceName', deviceContext, error);
|
|
652
|
+
}
|
|
653
|
+
finally {
|
|
654
|
+
await this.internalDisconnect();
|
|
428
655
|
}
|
|
429
|
-
await this.writeCharacteristic(this.characteristics.device, buf);
|
|
430
|
-
await this.internalDisconnect();
|
|
431
656
|
}
|
|
432
657
|
/**
|
|
433
658
|
* Sends a command to the device and awaits a response.
|
|
@@ -435,17 +660,24 @@ export class SwitchbotDevice extends EventEmitter {
|
|
|
435
660
|
* @returns A Promise that resolves with the response buffer.
|
|
436
661
|
*/
|
|
437
662
|
async command(reqBuf) {
|
|
438
|
-
|
|
439
|
-
throw new TypeError('The specified data is not acceptable for writing.');
|
|
440
|
-
}
|
|
663
|
+
ValidationUtils.validateBuffer(reqBuf, undefined, 'reqBuf');
|
|
441
664
|
await this.internalConnect();
|
|
442
665
|
if (!this.characteristics?.write) {
|
|
443
|
-
throw new Error('No
|
|
666
|
+
throw new Error('No write characteristic available for command execution');
|
|
667
|
+
}
|
|
668
|
+
try {
|
|
669
|
+
await this.writeCharacteristic(this.characteristics.write, reqBuf);
|
|
670
|
+
const resBuf = await this.waitForCommandResponse();
|
|
671
|
+
return resBuf;
|
|
672
|
+
}
|
|
673
|
+
catch (error) {
|
|
674
|
+
const deviceContext = `device ${this.deviceId || 'unknown'}`;
|
|
675
|
+
// Use ErrorUtils for enriched error context
|
|
676
|
+
throw ErrorUtils.createCommandError('execute command', deviceContext, error);
|
|
677
|
+
}
|
|
678
|
+
finally {
|
|
679
|
+
await this.internalDisconnect();
|
|
444
680
|
}
|
|
445
|
-
await this.writeCharacteristic(this.characteristics.write, reqBuf);
|
|
446
|
-
const resBuf = await this.waitForCommandResponse();
|
|
447
|
-
await this.internalDisconnect();
|
|
448
|
-
return resBuf;
|
|
449
681
|
}
|
|
450
682
|
/**
|
|
451
683
|
* Waits for a response from the device after sending a command.
|
|
@@ -468,41 +700,33 @@ export class SwitchbotDevice extends EventEmitter {
|
|
|
468
700
|
return await Promise.race([readPromise, timeoutPromise]);
|
|
469
701
|
}
|
|
470
702
|
/**
|
|
471
|
-
* Reads data from a characteristic with
|
|
703
|
+
* Reads data from a characteristic with enhanced timeout and error handling.
|
|
472
704
|
* @param char The characteristic to read from.
|
|
473
705
|
* @returns A Promise that resolves with the data buffer.
|
|
474
706
|
*/
|
|
475
707
|
async readCharacteristic(char) {
|
|
476
|
-
const timer = setTimeout(() => {
|
|
477
|
-
throw new Error('READ_TIMEOUT');
|
|
478
|
-
}, READ_TIMEOUT_MSEC);
|
|
479
708
|
try {
|
|
480
|
-
|
|
481
|
-
clearTimeout(timer);
|
|
482
|
-
return result;
|
|
709
|
+
return await ErrorUtils.withTimeout(char.readAsync(), READ_TIMEOUT_MSEC, `read characteristic ${char.uuid}`);
|
|
483
710
|
}
|
|
484
711
|
catch (error) {
|
|
485
|
-
|
|
486
|
-
throw error;
|
|
712
|
+
const deviceContext = `device ${this.deviceId || 'unknown'}`;
|
|
713
|
+
throw ErrorUtils.createCommandError(`read characteristic ${char.uuid}`, deviceContext, error);
|
|
487
714
|
}
|
|
488
715
|
}
|
|
489
716
|
/**
|
|
490
|
-
* Writes data to a characteristic with
|
|
717
|
+
* Writes data to a characteristic with enhanced timeout and error handling.
|
|
491
718
|
* @param char The characteristic to write to.
|
|
492
719
|
* @param buf The data buffer.
|
|
493
720
|
* @returns A Promise that resolves when the write is complete.
|
|
494
721
|
*/
|
|
495
722
|
async writeCharacteristic(char, buf) {
|
|
496
|
-
|
|
497
|
-
throw new Error('WRITE_TIMEOUT');
|
|
498
|
-
}, WRITE_TIMEOUT_MSEC);
|
|
723
|
+
ValidationUtils.validateBuffer(buf, undefined, 'write buffer');
|
|
499
724
|
try {
|
|
500
|
-
await char.writeAsync(buf, false);
|
|
501
|
-
clearTimeout(timer);
|
|
725
|
+
return await ErrorUtils.withTimeout(char.writeAsync(buf, false), WRITE_TIMEOUT_MSEC, `write to characteristic ${char.uuid}`);
|
|
502
726
|
}
|
|
503
727
|
catch (error) {
|
|
504
|
-
|
|
505
|
-
throw error;
|
|
728
|
+
const deviceContext = `device ${this.deviceId || 'unknown'}`;
|
|
729
|
+
throw ErrorUtils.createCommandError(`write to characteristic ${char.uuid}`, deviceContext, error);
|
|
506
730
|
}
|
|
507
731
|
}
|
|
508
732
|
}
|
|
@@ -556,10 +780,11 @@ export class Advertising {
|
|
|
556
780
|
* Validates if the buffer is a valid Buffer object with a minimum length.
|
|
557
781
|
*
|
|
558
782
|
* @param {any} buffer - The buffer to validate.
|
|
783
|
+
* @param {number} minLength - The minimum required length.
|
|
559
784
|
* @returns {boolean} - True if the buffer is valid, false otherwise.
|
|
560
785
|
*/
|
|
561
|
-
static validateBuffer(buffer) {
|
|
562
|
-
return buffer && Buffer.isBuffer(buffer) && buffer.length >=
|
|
786
|
+
static validateBuffer(buffer, minLength = 3) {
|
|
787
|
+
return buffer && Buffer.isBuffer(buffer) && buffer.length >= minLength;
|
|
563
788
|
}
|
|
564
789
|
/**
|
|
565
790
|
* Parses the service data based on the device model.
|
|
@@ -696,21 +921,21 @@ export class WoBlindTilt extends SwitchbotDevice {
|
|
|
696
921
|
* @returns {Promise<void>}
|
|
697
922
|
*/
|
|
698
923
|
async open() {
|
|
699
|
-
await this.operateBlindTilt([
|
|
924
|
+
await this.operateBlindTilt([...BLIND_TILT_COMMANDS.OPEN]);
|
|
700
925
|
}
|
|
701
926
|
/**
|
|
702
927
|
* Closes the blind tilt up to the nearest endpoint.
|
|
703
928
|
* @returns {Promise<void>}
|
|
704
929
|
*/
|
|
705
930
|
async closeUp() {
|
|
706
|
-
await this.operateBlindTilt([
|
|
931
|
+
await this.operateBlindTilt([...BLIND_TILT_COMMANDS.CLOSE_UP]);
|
|
707
932
|
}
|
|
708
933
|
/**
|
|
709
934
|
* Closes the blind tilt down to the nearest endpoint.
|
|
710
935
|
* @returns {Promise<void>}
|
|
711
936
|
*/
|
|
712
937
|
async closeDown() {
|
|
713
|
-
await this.operateBlindTilt([
|
|
938
|
+
await this.operateBlindTilt([...BLIND_TILT_COMMANDS.CLOSE_DOWN]);
|
|
714
939
|
}
|
|
715
940
|
/**
|
|
716
941
|
* Closes the blind tilt to the nearest endpoint.
|
|
@@ -794,7 +1019,7 @@ export class WoBlindTilt extends SwitchbotDevice {
|
|
|
794
1019
|
* @returns {Promise<void>}
|
|
795
1020
|
*/
|
|
796
1021
|
async pause() {
|
|
797
|
-
await this.operateBlindTilt([
|
|
1022
|
+
await this.operateBlindTilt([...BLIND_TILT_COMMANDS.PAUSE]);
|
|
798
1023
|
}
|
|
799
1024
|
/**
|
|
800
1025
|
* Runs the blind tilt to the specified position.
|
|
@@ -803,13 +1028,10 @@ export class WoBlindTilt extends SwitchbotDevice {
|
|
|
803
1028
|
* @returns {Promise<void>}
|
|
804
1029
|
*/
|
|
805
1030
|
async runToPos(percent, mode) {
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
throw new RangeError('Mode must be a number between 0 and 1');
|
|
811
|
-
}
|
|
812
|
-
await this.operateBlindTilt([0x57, 0x0F, 0x45, 0x01, 0x05, mode, percent]);
|
|
1031
|
+
ValidationUtils.validatePercentage(percent, 'percent');
|
|
1032
|
+
ValidationUtils.validateRange(mode, 0, 1, 'mode', true);
|
|
1033
|
+
const adjustedPercent = this.reverse ? 100 - percent : percent;
|
|
1034
|
+
await this.operateBlindTilt([0x57, 0x0F, 0x45, 0x01, 0x05, mode, adjustedPercent]);
|
|
813
1035
|
}
|
|
814
1036
|
/**
|
|
815
1037
|
* Sends a command to operate the blind tilt and handles the response.
|
|
@@ -876,7 +1098,7 @@ export class WoBulb extends SwitchbotDevice {
|
|
|
876
1098
|
* @returns {Promise<boolean>} - Resolves with a boolean indicating whether the bulb is ON (true) or OFF (false).
|
|
877
1099
|
*/
|
|
878
1100
|
async readState() {
|
|
879
|
-
return this.operateBulb([
|
|
1101
|
+
return this.operateBulb([...BULB_COMMANDS.READ_STATE]);
|
|
880
1102
|
}
|
|
881
1103
|
/**
|
|
882
1104
|
* Sets the state of the bulb.
|
|
@@ -885,22 +1107,21 @@ export class WoBulb extends SwitchbotDevice {
|
|
|
885
1107
|
* @private
|
|
886
1108
|
*/
|
|
887
1109
|
async setState(reqByteArray) {
|
|
888
|
-
|
|
889
|
-
return this.operateBulb(base.concat(reqByteArray));
|
|
1110
|
+
return this.operateBulb([...BULB_COMMANDS.BASE, ...reqByteArray]);
|
|
890
1111
|
}
|
|
891
1112
|
/**
|
|
892
1113
|
* Turns on the bulb.
|
|
893
1114
|
* @returns {Promise<boolean>} - Resolves with a boolean indicating whether the bulb is ON (true).
|
|
894
1115
|
*/
|
|
895
1116
|
async turnOn() {
|
|
896
|
-
return this.setState([
|
|
1117
|
+
return this.setState([...BULB_COMMANDS.TURN_ON]);
|
|
897
1118
|
}
|
|
898
1119
|
/**
|
|
899
1120
|
* Turns off the bulb.
|
|
900
1121
|
* @returns {Promise<boolean>} - Resolves with a boolean indicating whether the bulb is OFF (false).
|
|
901
1122
|
*/
|
|
902
1123
|
async turnOff() {
|
|
903
|
-
return this.setState([
|
|
1124
|
+
return this.setState([...BULB_COMMANDS.TURN_OFF]);
|
|
904
1125
|
}
|
|
905
1126
|
/**
|
|
906
1127
|
* Sets the brightness of the bulb.
|
|
@@ -908,10 +1129,8 @@ export class WoBulb extends SwitchbotDevice {
|
|
|
908
1129
|
* @returns {Promise<boolean>} - Resolves with a boolean indicating whether the operation was successful.
|
|
909
1130
|
*/
|
|
910
1131
|
async setBrightness(brightness) {
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
}
|
|
914
|
-
return this.setState([0x02, 0x14, brightness]);
|
|
1132
|
+
ValidationUtils.validatePercentage(brightness, 'brightness');
|
|
1133
|
+
return this.setState([...BULB_COMMANDS.SET_BRIGHTNESS, brightness]);
|
|
915
1134
|
}
|
|
916
1135
|
/**
|
|
917
1136
|
* Sets the color temperature of the bulb.
|
|
@@ -919,10 +1138,8 @@ export class WoBulb extends SwitchbotDevice {
|
|
|
919
1138
|
* @returns {Promise<boolean>} - Resolves with a boolean indicating whether the operation was successful.
|
|
920
1139
|
*/
|
|
921
1140
|
async setColorTemperature(color_temperature) {
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
}
|
|
925
|
-
return this.setState([0x02, 0x17, color_temperature]);
|
|
1141
|
+
ValidationUtils.validatePercentage(color_temperature, 'color_temperature');
|
|
1142
|
+
return this.setState([...BULB_COMMANDS.SET_COLOR_TEMP, color_temperature]);
|
|
926
1143
|
}
|
|
927
1144
|
/**
|
|
928
1145
|
* Sets the RGB color of the bulb.
|
|
@@ -933,10 +1150,11 @@ export class WoBulb extends SwitchbotDevice {
|
|
|
933
1150
|
* @returns {Promise<boolean>} - Resolves with a boolean indicating whether the operation was successful.
|
|
934
1151
|
*/
|
|
935
1152
|
async setRGB(brightness, red, green, blue) {
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1153
|
+
ValidationUtils.validatePercentage(brightness, 'brightness');
|
|
1154
|
+
ValidationUtils.validateRGB(red, 'red');
|
|
1155
|
+
ValidationUtils.validateRGB(green, 'green');
|
|
1156
|
+
ValidationUtils.validateRGB(blue, 'blue');
|
|
1157
|
+
return this.setState([...BULB_COMMANDS.SET_RGB, brightness, red, green, blue]);
|
|
940
1158
|
}
|
|
941
1159
|
/**
|
|
942
1160
|
* Sends a command to the bulb.
|
|
@@ -2750,6 +2968,7 @@ export class WoStrip extends SwitchbotDevice {
|
|
|
2750
2968
|
red: byte3,
|
|
2751
2969
|
green: byte4,
|
|
2752
2970
|
blue: byte5,
|
|
2971
|
+
color_temperature: 0, // Add a default value or extract from serviceData if available
|
|
2753
2972
|
delay: byte8 & 0b10000000,
|
|
2754
2973
|
preset: byte8 & 0b00001000,
|
|
2755
2974
|
color_mode: byte8 & 0b00000111,
|