UNPKG

tsvesync

Version:

A TypeScript library for interacting with VeSync smart home devices

480 lines (479 loc) 20.8 kB
"use strict"; /** * VeSync Bulb Implementations */ Object.defineProperty(exports, "__esModule", { value: true }); exports.bulbModules = exports.VeSyncBulbESL100MC = exports.VeSyncBulbXYD0001 = exports.VeSyncBulbESL100CW = exports.VeSyncBulbESL100 = void 0; const vesyncBulb_1 = require("./vesyncBulb"); const helpers_1 = require("./helpers"); const logger_1 = require("./logger"); /** * ESL100 Bulb Implementation */ class VeSyncBulbESL100 extends vesyncBulb_1.VeSyncBulb { constructor(details, manager) { super(details, manager); } async getDetails() { logger_1.logger.debug(`[${this.deviceName}] Fetching ESL100 details`); const body = { ...helpers_1.Helpers.reqBody(this.manager, 'devicedetail'), uuid: this.uuid }; const [response, statusCode] = await this.callApi('/SmartBulb/v1/device/devicedetail', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); const success = this.checkResponse([response, statusCode], 'getDetails'); if (success && (response === null || response === void 0 ? void 0 : response.result)) { const result = response.result; if (result.deviceStatus) { this.deviceStatus = result.deviceStatus; } if (result.connectionStatus) { this.connectionStatus = result.connectionStatus; } if (result.brightNess !== undefined) { this.brightness = Number(result.brightNess); } else if (result.brightness !== undefined) { this.brightness = Number(result.brightness); } logger_1.logger.debug(`[${this.deviceName}] Updated details: status=${this.deviceStatus}, brightness=${this.brightness}`); } return success; } async turnOn() { const body = { ...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'), uuid: this.uuid, status: 'on' }; const [response] = await this.callApi('/SmartBulb/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.deviceStatus = 'on'; this.connectionStatus = 'online'; logger_1.logger.info(`[${this.deviceName}] Turned on successfully`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to turn on: ${JSON.stringify(response)}`); return false; } async turnOff() { const body = { ...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'), uuid: this.uuid, status: 'off' }; const [response] = await this.callApi('/SmartBulb/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.deviceStatus = 'off'; logger_1.logger.info(`[${this.deviceName}] Turned off successfully`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to turn off: ${JSON.stringify(response)}`); return false; } async setBrightness(brightness) { if (!this.features.includes('dimmable')) { logger_1.logger.error(`[${this.deviceName}] Dimming not supported`); return false; } const brightnessUpdate = vesyncBulb_1.VeSyncBulb.clamp(Math.round(brightness), 0, 100); const body = { ...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'), uuid: this.uuid, status: 'on', brightNess: String(brightnessUpdate) }; const [response] = await this.callApi('/SmartBulb/v1/device/updateBrightness', 'put', body, helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.brightness = brightnessUpdate; this.deviceStatus = 'on'; this.connectionStatus = 'online'; logger_1.logger.info(`[${this.deviceName}] Brightness set to ${brightnessUpdate}`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to set brightness: ${JSON.stringify(response)}`); return false; } async setColorTemp(colorTemp) { logger_1.logger.error(`[${this.deviceName}] Color temperature control not supported`); return false; } } exports.VeSyncBulbESL100 = VeSyncBulbESL100; /** * ESL100CW Bulb Implementation */ class VeSyncBulbESL100CW extends vesyncBulb_1.VeSyncBulb { constructor(details, manager) { super(details, manager); } buildBypassBody(lightPayload) { return { ...helpers_1.Helpers.reqBody(this.manager, 'bypass'), cid: this.cid, configModule: this.configModule, jsonCmd: { light: lightPayload } }; } async getDetails() { var _a; logger_1.logger.debug(`[${this.deviceName}] Fetching ESL100CW status`); const body = { ...helpers_1.Helpers.reqBody(this.manager, 'bypass'), cid: this.cid, configModule: this.configModule, jsonCmd: { getLightStatus: 'get' } }; const [response, statusCode] = await this.callApi('/cloud/v1/deviceManaged/bypass', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); const success = this.checkResponse([response, statusCode], 'getDetails'); if (success) { const inner = ((_a = response === null || response === void 0 ? void 0 : response.result) === null || _a === void 0 ? void 0 : _a.result) || (response === null || response === void 0 ? void 0 : response.result); const light = inner === null || inner === void 0 ? void 0 : inner.light; if (light) { this.deviceStatus = light.action === 'on' ? 'on' : 'off'; if (light.brightness !== undefined) { this.brightness = Number(light.brightness); } if (light.colorTempe !== undefined) { this.colorTemp = Number(light.colorTempe); } } } return success; } async turnOn() { const [response] = await this.callApi('/cloud/v1/deviceManaged/bypass', 'post', this.buildBypassBody({ action: 'on' }), helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.deviceStatus = 'on'; this.connectionStatus = 'online'; logger_1.logger.info(`[${this.deviceName}] Turned on successfully`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to turn on: ${JSON.stringify(response)}`); return false; } async turnOff() { const [response] = await this.callApi('/cloud/v1/deviceManaged/bypass', 'post', this.buildBypassBody({ action: 'off' }), helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.deviceStatus = 'off'; logger_1.logger.info(`[${this.deviceName}] Turned off successfully`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to turn off: ${JSON.stringify(response)}`); return false; } async setBrightness(brightness) { if (!this.features.includes('dimmable')) { logger_1.logger.error(`[${this.deviceName}] Dimming not supported`); return false; } const brightnessUpdate = vesyncBulb_1.VeSyncBulb.clamp(Math.round(brightness), 0, 100); const light = { action: 'on', brightness: brightnessUpdate }; if (this.features.includes('color_temp')) { light.colorTempe = this.colorTemp; } const [response] = await this.callApi('/cloud/v1/deviceManaged/bypass', 'post', this.buildBypassBody(light), helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.brightness = brightnessUpdate; this.deviceStatus = 'on'; this.connectionStatus = 'online'; logger_1.logger.info(`[${this.deviceName}] Brightness set to ${brightnessUpdate}`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to set brightness: ${JSON.stringify(response)}`); return false; } async setColorTemp(colorTemp) { if (!this.features.includes('color_temp')) { logger_1.logger.error(`[${this.deviceName}] Color temperature control not supported`); return false; } const colorTempUpdate = vesyncBulb_1.VeSyncBulb.clamp(Math.round(colorTemp), 0, 100); const light = { action: 'on', brightness: this.brightness, colorTempe: colorTempUpdate }; const [response] = await this.callApi('/cloud/v1/deviceManaged/bypass', 'post', this.buildBypassBody(light), helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.colorTemp = colorTempUpdate; this.deviceStatus = 'on'; this.connectionStatus = 'online'; logger_1.logger.info(`[${this.deviceName}] Color temperature set to ${colorTempUpdate}`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to set color temperature: ${JSON.stringify(response)}`); return false; } } exports.VeSyncBulbESL100CW = VeSyncBulbESL100CW; /** * XYD0001 Bulb Implementation */ class VeSyncBulbXYD0001 extends vesyncBulb_1.VeSyncBulb { constructor(details, manager) { super(details, manager); } async setColorTemp(colorTemp) { if (!this.features.includes('color_temp')) { logger_1.logger.error(`[${this.deviceName}] Color temperature control not supported`); return false; } logger_1.logger.debug(`[${this.deviceName}] Setting color temperature to ${colorTemp}`); const body = { ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'), cid: this.cid, configModule: this.configModule, payload: { data: { brightness: '', colorMode: 'white', colorTemp: colorTemp, force: 1, hue: '', saturation: '', value: '' }, method: 'setLightStatusV2', source: 'APP' } }; const [response] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.colorTemp = colorTemp; logger_1.logger.info(`[${this.deviceName}] Successfully set color temperature to ${colorTemp}`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to set color temperature: ${JSON.stringify(response)}`); return false; } async setHsv(hue, saturation, value) { if (!this.features.includes('rgb_shift')) { logger_1.logger.error(`[${this.deviceName}] Color control not supported`); return false; } logger_1.logger.debug(`[${this.deviceName}] Setting HSV color to H:${hue} S:${saturation} V:${value}`); const body = { ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'), cid: this.cid, configModule: this.configModule, payload: { data: { brightness: value, colorMode: 'hsv', colorTemp: '', force: 1, hue: hue, saturation: saturation, value: value }, method: 'setLightStatusV2', source: 'APP' } }; const [response] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.colorHue = hue; this.colorSaturation = saturation; this.colorValue = value; logger_1.logger.info(`[${this.deviceName}] Successfully set HSV color`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to set HSV color: ${JSON.stringify(response)}`); return false; } async enableWhiteMode() { logger_1.logger.debug(`[${this.deviceName}] Enabling white mode`); const body = { ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'), cid: this.cid, configModule: this.configModule, payload: { data: { brightness: '', colorMode: 'white', colorTemp: '', force: 1, red: '', green: '', blue: '' }, method: 'setLightStatusV2', source: 'APP' } }; const [response] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); if ((response === null || response === void 0 ? void 0 : response.code) === 0) { this.colorMode = 'white'; logger_1.logger.info(`[${this.deviceName}] Successfully enabled white mode`); return true; } logger_1.logger.error(`[${this.deviceName}] Failed to enable white mode: ${JSON.stringify(response)}`); return false; } } exports.VeSyncBulbXYD0001 = VeSyncBulbXYD0001; /** * ESL100MC Bulb Implementation */ class VeSyncBulbESL100MC extends vesyncBulb_1.VeSyncBulb { constructor(details, manager) { super(details, manager); } buildBypassV2Payload(method, data) { return { ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'), cid: this.cid, configModule: this.configModule, payload: { method, source: 'APP', data } }; } handleBypassV2Response(response, context) { if (!response) { logger_1.logger.error(`[${this.deviceName}] ${context} returned empty response`); return false; } if (response.code !== 0) { logger_1.logger.error(`[${this.deviceName}] ${context} failed: ${JSON.stringify(response)}`); return false; } const inner = response.result; if ((inner === null || inner === void 0 ? void 0 : inner.code) !== undefined && inner.code !== 0) { logger_1.logger.error(`[${this.deviceName}] ${context} inner error: ${JSON.stringify(response)}`); return false; } return true; } async getDetails() { var _a, _b, _c, _d; logger_1.logger.debug(`[${this.deviceName}] Fetching ESL100MC status`); const body = this.buildBypassV2Payload('getLightStatus', {}); const [response, statusCode] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); const success = this.checkResponse([response, statusCode], 'getDetails'); if (!success) { return false; } const inner = ((_a = response === null || response === void 0 ? void 0 : response.result) === null || _a === void 0 ? void 0 : _a.result) || (response === null || response === void 0 ? void 0 : response.result); if (inner) { if (inner.action) { this.deviceStatus = inner.action === 'on' ? 'on' : 'off'; } if (inner.brightness !== undefined) { this.brightness = Number(inner.brightness); } this.rgbValues = { red: Number((_b = inner.red) !== null && _b !== void 0 ? _b : this.rgbValues.red), green: Number((_c = inner.green) !== null && _c !== void 0 ? _c : this.rgbValues.green), blue: Number((_d = inner.blue) !== null && _d !== void 0 ? _d : this.rgbValues.blue) }; this.colorMode = inner.colorMode || this.colorMode; } return true; } async turnOn() { const body = this.buildBypassV2Payload('setSwitch', { id: 0, enabled: true }); const [response] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); if (this.handleBypassV2Response(response, 'turn on')) { this.deviceStatus = 'on'; this.connectionStatus = 'online'; return true; } return false; } async turnOff() { const body = this.buildBypassV2Payload('setSwitch', { id: 0, enabled: false }); const [response] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); if (this.handleBypassV2Response(response, 'turn off')) { this.deviceStatus = 'off'; return true; } return false; } async setBrightness(brightness) { const brightnessUpdate = vesyncBulb_1.VeSyncBulb.clamp(Math.round(brightness), 0, 100); const body = this.buildBypassV2Payload('setLightStatus', { action: 'on', speed: 0, brightness: brightnessUpdate, red: 0, green: 0, blue: 0, colorMode: 'white' }); const [response] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); if (this.handleBypassV2Response(response, 'set brightness')) { this.brightness = brightnessUpdate; this.deviceStatus = 'on'; this.colorMode = 'white'; this.connectionStatus = 'online'; return true; } return false; } async setRgb(red, green, blue) { if (!this.features.includes('rgb_shift')) { logger_1.logger.error(`[${this.deviceName}] Color control not supported`); return false; } const body = this.buildBypassV2Payload('setLightStatus', { action: 'on', speed: 0, brightness: 100, red: vesyncBulb_1.VeSyncBulb.clamp(Math.round(red), 0, 255), green: vesyncBulb_1.VeSyncBulb.clamp(Math.round(green), 0, 255), blue: vesyncBulb_1.VeSyncBulb.clamp(Math.round(blue), 0, 255), colorMode: 'color' }); const [response] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager)); if (this.handleBypassV2Response(response, 'set RGB color')) { this.rgbValues = { red: vesyncBulb_1.VeSyncBulb.clamp(Math.round(red), 0, 255), green: vesyncBulb_1.VeSyncBulb.clamp(Math.round(green), 0, 255), blue: vesyncBulb_1.VeSyncBulb.clamp(Math.round(blue), 0, 255) }; this.brightness = 100; this.deviceStatus = 'on'; this.colorMode = 'color'; this.connectionStatus = 'online'; return true; } return false; } async enableWhiteMode() { const targetBrightness = this.brightness > 0 ? this.brightness : 100; const success = await this.setBrightness(targetBrightness); if (success) { this.colorMode = 'white'; } return success; } async setColorTemp(colorTemp) { logger_1.logger.error(`[${this.deviceName}] Color temperature control not supported`); return false; } } exports.VeSyncBulbESL100MC = VeSyncBulbESL100MC; // Export the bulb modules dictionary exports.bulbModules = { 'ESL100': VeSyncBulbESL100, 'ESL100CW': VeSyncBulbESL100CW, 'XYD0001': VeSyncBulbXYD0001, 'ESL100MC': VeSyncBulbESL100MC };