homebridge-tsvesync
Version:
Homebridge plugin for VeSync devices including Levoit air purifiers, humidifiers, and Etekcity smart outlets
195 lines (158 loc) • 6.23 kB
text/typescript
import { Categories, PlatformAccessory } from 'homebridge';
import { TSVESyncPlatform } from '../platform';
import { VeSyncBaseDevice } from 'tsvesync';
import { AirPurifierAccessory } from '../accessories/air-purifier.accessory';
import { HumidifierAccessory } from '../accessories/humidifier.accessory';
import { FanAccessory } from '../accessories/fan.accessory';
import { LightAccessory } from '../accessories/light.accessory';
import { OutletAccessory } from '../accessories/outlet.accessory';
import { SwitchAccessory } from '../accessories/switch.accessory';
import { BaseAccessory } from '../accessories/base.accessory';
import { AirQualitySensorAccessory } from '../accessories/air-quality-sensor.accessory';
import {
VeSyncAirPurifier,
VeSyncHumidifier,
VeSyncFan,
VeSyncBulb,
VeSyncDimmerSwitch,
VeSyncOutlet,
VeSyncSwitch
} from '../types/device.types';
// Device model constants
const AIR_PURIFIER_MODELS = [
'Core200S', 'Core300S', 'Core400S', 'Core600S',
'Vital100S', 'Vital200S', 'LV-PUR131S', 'LV-RH131S',
'EverestAir'
];
const HUMIDIFIER_MODELS = [
'Classic200S', 'Classic300S', 'Dual200S', 'LV600S',
'OasisMist', 'OasisMist600S', 'Superior6000S',
'OasisMist1000S'
];
const FAN_MODELS = ['LTF-F422'];
const OUTLET_MODELS = [
'ESO15-TB', 'ESW15-USA', 'ESW03-USA', 'ESW01-EU',
'ESW10-USA', 'wifi-switch-1.3'
];
const SWITCH_MODELS = ['ESWL01', 'ESWL03'];
const DIMMER_MODELS = ['ESWD16'];
export class DeviceFactory {
private static modelMatches(deviceType: string, models: string[]): boolean {
const upperDeviceType = deviceType.toUpperCase();
return models.some(model => upperDeviceType.includes(model.toUpperCase()));
}
static isAirPurifier(deviceType: string): boolean {
return deviceType.startsWith('LAP-') ||
this.modelMatches(deviceType, AIR_PURIFIER_MODELS);
}
private static isHumidifier(deviceType: string): boolean {
return deviceType.startsWith('LUH-') ||
deviceType.startsWith('LEH-') ||
this.modelMatches(deviceType, HUMIDIFIER_MODELS);
}
private static isFan(deviceType: string): boolean {
return deviceType.startsWith('LTF-') ||
this.modelMatches(deviceType, FAN_MODELS);
}
private static isBulb(deviceType: string): boolean {
return deviceType.startsWith('ESL') || deviceType === 'XYD0001';
}
private static isDimmer(deviceType: string): boolean {
return this.modelMatches(deviceType, DIMMER_MODELS);
}
private static isOutlet(deviceType: string): boolean {
return this.modelMatches(deviceType, OUTLET_MODELS);
}
private static isSwitch(deviceType: string): boolean {
return this.modelMatches(deviceType, SWITCH_MODELS);
}
static createAccessory(
platform: TSVESyncPlatform,
accessory: PlatformAccessory,
device: VeSyncBaseDevice
): BaseAccessory {
const deviceType = device.deviceType.toUpperCase();
// Air Purifiers
if (this.isAirPurifier(deviceType)) {
return new AirPurifierAccessory(platform, accessory, device as VeSyncAirPurifier);
}
// Humidifiers
if (this.isHumidifier(deviceType)) {
return new HumidifierAccessory(platform, accessory, device as VeSyncHumidifier);
}
// Fans
if (this.isFan(deviceType)) {
return new FanAccessory(platform, accessory, device as VeSyncFan);
}
// Dimmers
if (this.isDimmer(deviceType)) {
return new LightAccessory(platform, accessory, device as VeSyncDimmerSwitch);
}
// Bulbs
if (this.isBulb(deviceType)) {
return new LightAccessory(platform, accessory, device as VeSyncBulb);
}
// Outlets
if (this.isOutlet(deviceType)) {
return new OutletAccessory(platform, accessory, device as VeSyncOutlet);
}
// Switches
if (this.isSwitch(deviceType)) {
return new SwitchAccessory(platform, accessory, device as VeSyncSwitch);
}
// Default to outlet for unknown devices
platform.log.warn(`Unknown device type: ${deviceType}, defaulting to outlet`);
return new OutletAccessory(platform, accessory, device as VeSyncOutlet);
}
static getAccessoryCategory(deviceType: string): Categories {
const type = deviceType.toUpperCase();
if (this.isAirPurifier(type)) {
return Categories.AIR_PURIFIER;
}
if (this.isHumidifier(type)) {
return Categories.AIR_HUMIDIFIER;
}
if (this.isFan(type)) {
return Categories.FAN;
}
if (this.isDimmer(type) || this.isBulb(type)) {
return Categories.LIGHTBULB;
}
if (this.isSwitch(type)) {
return Categories.SWITCH;
}
if (this.isOutlet(type)) {
return Categories.OUTLET;
}
// Default to outlet for unknown devices
return Categories.OUTLET;
}
static createAQSensorAccessory(
platform: TSVESyncPlatform,
accessory: PlatformAccessory,
device: VeSyncBaseDevice
): BaseAccessory | null {
const deviceType = device.deviceType.toUpperCase();
// Only create AQ sensor for air purifier devices with AQ support
if (this.isAirPurifier(deviceType)) {
// Check if device has the air_quality feature
const extendedDevice = device as any;
// Use the device's native feature detection if available
if (typeof extendedDevice.hasFeature === 'function' && extendedDevice.hasFeature('air_quality')) {
platform.log.debug(`Creating AQ sensor for ${device.deviceName} - device has air_quality feature`);
return new AirQualitySensorAccessory(platform, accessory, device);
}
// Fallback to device type checking for older devices
if (deviceType.includes('CORE300S') ||
deviceType.includes('CORE400S') ||
deviceType.includes('CORE600S') ||
(deviceType.includes('LAP-') && !deviceType.includes('LAP-EL')) ||
deviceType.includes('LV-PUR131S')) {
platform.log.debug(`Creating AQ sensor for ${device.deviceName} - device type ${deviceType} supports AQ`);
return new AirQualitySensorAccessory(platform, accessory, device);
}
}
platform.log.debug(`Not creating AQ sensor for ${device.deviceName} - no air quality support detected`);
return null;
}
}