tsvesync
Version:
A TypeScript library for interacting with VeSync smart home devices
337 lines (336 loc) • 13.9 kB
JavaScript
"use strict";
/**
* VeSync Outlets
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.VeSyncOutlet = exports.outletConfig = void 0;
const vesyncBaseDevice_1 = require("./vesyncBaseDevice");
const helpers_1 = require("./helpers");
const logger_1 = require("./logger");
// Outlet configuration
exports.outletConfig = {
'wifi-switch-1.3': {
module: 'VeSyncOutlet7A',
features: ['energy']
},
'ESW03-USA': {
module: 'VeSyncOutlet10A',
features: ['energy']
},
'ESW01-EU': {
module: 'VeSyncOutlet10A',
features: ['energy']
},
'ESW10-USA': {
module: 'VeSyncOutlet10A',
features: ['energy']
},
'ESW15-USA': {
module: 'VeSyncOutlet15A',
features: ['energy', 'nightlight']
},
'ESO15-TB': {
module: 'VeSyncOutdoorPlug',
features: ['energy']
}
};
/**
* VeSync Outlet Base Class
*/
class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
constructor(details, manager) {
var _a;
super(details, manager);
this.energy = {};
this.details = details;
this.features = ((_a = exports.outletConfig[this.deviceType]) === null || _a === void 0 ? void 0 : _a.features) || [];
}
/**
* Get outlet details
*/
async getDetails() {
logger_1.logger.debug(`[${this.deviceName}] Getting outlet details`);
const body = {
...helpers_1.Helpers.reqBody(this.manager, 'devicedetail'),
uuid: this.uuid
};
let url;
if (this.deviceType === 'wifi-switch-1.3') {
url = '/v1/device/' + this.cid + '/detail';
}
else if (this.deviceType.startsWith('ESO15')) {
url = '/outdoorsocket15a/v1/device/devicedetail';
}
else if (this.deviceType.startsWith('ESW15')) {
url = '/15a/v1/device/devicedetail';
}
else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01') || this.deviceType.startsWith('ESW10')) {
url = '/10a/v1/device/devicedetail';
}
else {
url = '/v1/device/devicedetail';
}
const [response, statusCode] = await this.callApi(url, this.deviceType === 'wifi-switch-1.3' ? 'get' : 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
if (!response) {
logger_1.logger.debug(`[${this.deviceName}] No response received from API`);
return false;
}
// Handle error responses
if (response.error) {
logger_1.logger.error(`[${this.deviceName}] Failed to get outlet details for ${url}: ${JSON.stringify(response)}`);
return false;
}
// Handle successful responses
if (response.code === 0) {
this.details = response;
// Handle outdoor plugs with subdevices
if (response.subDevices) {
const subDevice = response.subDevices.find((dev) => {
// Match by name (primary identifier)
if (dev.subDeviceName === this.deviceName) {
return true;
}
// Match by subDeviceNo if available
if ('subDeviceNo' in this && this.subDeviceNo === dev.subDeviceNo) {
return true;
}
// Match by cid/uuid if available (cid might be in format parentCid_subDeviceNo)
if (this.cid && this.cid.includes('_')) {
const [_, subId] = this.cid.split('_');
if (subId && dev.subDeviceNo === parseInt(subId)) {
return true;
}
}
return false;
});
if (subDevice) {
this.deviceStatus = subDevice.subDeviceStatus;
logger_1.logger.debug(`[${this.deviceName}] Successfully retrieved sub-device status: ${this.deviceStatus}`);
return true;
}
}
// Handle regular devices
if (response.deviceStatus !== undefined) {
this.deviceStatus = response.deviceStatus;
}
else if (response.status !== undefined) {
this.deviceStatus = response.status;
}
else if (response.power !== undefined) {
this.deviceStatus = response.power === 'on' ? 'on' : 'off';
}
else {
logger_1.logger.debug(`[${this.deviceName}] Device status not found in response: ${JSON.stringify(response)}`);
return false;
}
logger_1.logger.debug(`[${this.deviceName}] Successfully retrieved outlet details`);
return true;
}
else {
logger_1.logger.debug(`[${this.deviceName}] Failed to get outlet details: ${JSON.stringify(response)}`);
return false;
}
}
/**
* Update outlet energy data
*/
async updateEnergy() {
if (!this.features.includes('energy')) {
logger_1.logger.debug(`[${this.deviceName}] Energy monitoring not supported`);
return;
}
logger_1.logger.debug(`[${this.deviceName}] Updating energy data`);
// Different endpoints for different device types
let url;
if (this.deviceType === 'wifi-switch-1.3') {
url = `/v1/device/${this.deviceType}-${this.cid}/energy/detail`;
}
else if (this.deviceType.startsWith('ESO15')) {
url = '/outdoorsocket15a/v1/device/energy';
}
else if (this.deviceType.startsWith('ESW15')) {
url = '/15a/v1/device/energy';
}
else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01') || this.deviceType.startsWith('ESW10')) {
url = '/10a/v1/device/energy';
}
else {
url = '/v1/device/energy';
}
const body = this.deviceType === 'wifi-switch-1.3' ? null : {
...helpers_1.Helpers.reqBody(this.manager, 'energy'),
uuid: this.uuid
};
const [response] = await this.callApi(url, this.deviceType === 'wifi-switch-1.3' ? 'get' : 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
// Handle different response formats
if ((response === null || response === void 0 ? void 0 : response.code) === 0 && response.result) {
this.energy = response.result;
logger_1.logger.info(`[${this.deviceName}] Successfully updated energy data`);
}
else if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
// Some devices return data directly in response
this.energy = {
power: response.power || '0',
voltage: response.voltage || '0',
energy: response.energy || '0',
energyToday: response.energy || '0',
energyWeek: response.energy || '0',
energyMonth: response.energy || '0',
energyYear: response.energy || '0'
};
logger_1.logger.info(`[${this.deviceName}] Successfully updated energy data`);
}
else {
// For error responses, set defaults but don't log as error
this.energy = {
power: '0',
voltage: '0',
energy: '0',
energyToday: '0',
energyWeek: '0',
energyMonth: '0',
energyYear: '0'
};
logger_1.logger.debug(`[${this.deviceName}] Failed to update energy data: ${JSON.stringify(response)}`);
}
}
/**
* Get outlet energy usage
*/
async getEnergyUsage() {
if (!this.features.includes('energy')) {
logger_1.logger.debug(`[${this.deviceName}] Energy monitoring not supported`);
return {
power: 'Not supported',
voltage: 'Not supported',
energy_today: 'Not supported',
energy_week: 'Not supported',
energy_month: 'Not supported',
energy_year: 'Not supported'
};
}
await this.updateEnergy();
return {
power: this.energy.power || '0',
voltage: this.energy.voltage || '0',
energy_today: this.energy.energyToday || '0',
energy_week: this.energy.energyWeek || '0',
energy_month: this.energy.energyMonth || '0',
energy_year: this.energy.energyYear || '0'
};
}
/**
* Get outlet status
*/
async getStatus() {
logger_1.logger.debug(`[${this.deviceName}] Getting outlet status`);
await this.getDetails();
return this.deviceStatus;
}
/**
* Get API prefix based on device type
*/
getApiPrefix() {
if (this.deviceType === 'wifi-switch-1.3') {
return `v1/device/${this.deviceType}-${this.cid}`;
}
else if (this.deviceType.startsWith('ESW15') || this.deviceType.startsWith('ESO15')) {
return '15a/v1/device';
}
else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01') || this.deviceType.startsWith('ESW10')) {
return '10a/v1/device';
}
return 'v1/device';
}
/**
* Get weekly energy data
*/
async getWeeklyEnergy() {
if (!this.features.includes('energy')) {
logger_1.logger.debug(`[${this.deviceName}] Energy monitoring not supported`);
return;
}
logger_1.logger.debug(`[${this.deviceName}] Getting weekly energy data`);
const isLegacyDevice = this.deviceType === 'wifi-switch-1.3';
const body = isLegacyDevice ? null : {
...helpers_1.Helpers.reqBody(this.manager, 'energyweek'),
uuid: this.uuid
};
const [response] = await this.callApi(isLegacyDevice ? `/${this.getApiPrefix()}/energy/week` : `/${this.getApiPrefix()}/energyweek`, isLegacyDevice ? 'get' : 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
this.energy.week = response.result || response.energyWeek || '0';
logger_1.logger.debug(`[${this.deviceName}] Successfully retrieved weekly energy data`);
}
else {
this.energy.week = '0';
logger_1.logger.debug(`[${this.deviceName}] Failed to get weekly energy data: ${JSON.stringify(response)}`);
}
}
/**
* Get monthly energy data
*/
async getMonthlyEnergy() {
if (!this.features.includes('energy')) {
logger_1.logger.debug(`[${this.deviceName}] Energy monitoring not supported`);
return;
}
logger_1.logger.debug(`[${this.deviceName}] Getting monthly energy data`);
const isLegacyDevice = this.deviceType === 'wifi-switch-1.3';
const body = isLegacyDevice ? null : {
...helpers_1.Helpers.reqBody(this.manager, 'energymonth'),
uuid: this.uuid
};
const [response] = await this.callApi(isLegacyDevice ? `/${this.getApiPrefix()}/energy/month` : `/${this.getApiPrefix()}/energymonth`, isLegacyDevice ? 'get' : 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
this.energy.month = response.result || response.energyMonth || '0';
logger_1.logger.debug(`[${this.deviceName}] Successfully retrieved monthly energy data`);
}
else {
this.energy.month = '0';
logger_1.logger.debug(`[${this.deviceName}] Failed to get monthly energy data: ${JSON.stringify(response)}`);
}
}
/**
* Get yearly energy data
*/
async getYearlyEnergy() {
if (!this.features.includes('energy')) {
logger_1.logger.debug(`[${this.deviceName}] Energy monitoring not supported`);
return;
}
logger_1.logger.debug(`[${this.deviceName}] Getting yearly energy data`);
const isLegacyDevice = this.deviceType === 'wifi-switch-1.3';
const body = isLegacyDevice ? null : {
...helpers_1.Helpers.reqBody(this.manager, 'energyyear'),
uuid: this.uuid
};
const [response] = await this.callApi(isLegacyDevice ? `/${this.getApiPrefix()}/energy/year` : `/${this.getApiPrefix()}/energyyear`, isLegacyDevice ? 'get' : 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
this.energy.year = response.result || response.energyYear || '0';
logger_1.logger.debug(`[${this.deviceName}] Successfully retrieved yearly energy data`);
}
else {
this.energy.year = '0';
logger_1.logger.debug(`[${this.deviceName}] Failed to get yearly energy data: ${JSON.stringify(response)}`);
}
}
/**
* Update outlet details and energy info
*/
async update() {
logger_1.logger.debug(`[${this.deviceName}] Updating outlet information`);
const success = await this.getDetails();
if (success && this.features.includes('energy')) {
await this.updateEnergy();
}
logger_1.logger.info(`[${this.deviceName}] Successfully updated outlet information`);
return success;
}
/**
* Check if outlet has nightlight feature
*/
hasNightlight() {
return this.features.includes('nightlight');
}
}
exports.VeSyncOutlet = VeSyncOutlet;