tsvesync
Version:
A TypeScript library for interacting with VeSync smart home devices
480 lines (479 loc) • 20.8 kB
JavaScript
"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
};