UNPKG

homebridge-lg-airco

Version:

Homebridge plugin to control a Smart Thinq enabled LG airco unit. Makes use of WideQ => https://github.com/sampsyo/wideq

303 lines (271 loc) 10.4 kB
import {PythonUtils} from "../utils/python-utils"; const {resolve} = require('path'); export class WideqAdapter { private static readonly wideqFolder: string = resolve(__dirname + '../../../resources/wideq/'); private static readonly wideqScriptFile: string = 'example.py'; private readonly country: string; private readonly language: string; private readonly storagePath: string; private readonly debug: boolean; private readonly logDebug: Function; constructor(country: string, language: string, storagePath: string, debug: boolean, debugLogger: Function) { this.country = country; this.language = language; this.storagePath = storagePath; this.logDebug = debugLogger; } public static async listAirCoolers(country: string, language: string, storagePath: string): Promise<Array<AirCooler>> { console.log(storagePath); const data: string = await PythonUtils.executePython3(this.wideqFolder, this.wideqScriptFile, ['-c', country, '-l', language, '-p', storagePath, '-v', 'ls']); const devices = data.split('\n'); const processedDevices: AirCooler[] = []; for (const device of devices) { const deviceInfoValues = device.split(':'); if (deviceInfoValues.length > 1) { const modelInfoValues = deviceInfoValues[1].split('('); const deviceId: string = deviceInfoValues[0].trim(); const deviceType: string = modelInfoValues[0].trim(); const modelName: string = modelInfoValues[1].replace(')', '').trim(); processedDevices.push({ deviceId, deviceType, modelName, country, language }); } } return processedDevices; } public async getStatus(deviceId: string): Promise<AirCoolerStatus> { try { const data: string = await PythonUtils.executePython3(WideqAdapter.wideqFolder, WideqAdapter.wideqScriptFile, ['-c', this.country, '-l', this.language, '-p', this.storagePath, this.debug ? '-v' : null, 'ac-mon', deviceId]); this.logDebug(data); const dataPieces: string[] = data.split(';').map(s => s.trim()); this.logDebug(dataPieces); return { isOn: dataPieces[0].toLowerCase() === 'on', mode: (<any>Mode)[dataPieces[1]], currentTempInCelsius: parseFloat(dataPieces[2].substring(4)), targetTempInCelsius: parseFloat(dataPieces[3].substring(4)), fanSpeed: (<any>FanSpeed)[dataPieces[4].substring(10)] }; } catch (error) { this.logDebug(error); return null; } } public async getCurrentPowerUsage(deviceId: string): Promise<number> { try { const data: string = await PythonUtils.executePython3(WideqAdapter.wideqFolder, WideqAdapter.wideqScriptFile, ['-c', this.country, '-l', this.language, '-p', this.storagePath, this.debug ? '-v' : null, 'get-power-draw', deviceId]); this.logDebug(data); return parseInt(data); } catch (error) { this.logDebug(error); return null; } } public async setPowerOnOff(deviceId: string, poweredOn: boolean): Promise<boolean> { try { const data: string = await PythonUtils.executePython3(WideqAdapter.wideqFolder, WideqAdapter.wideqScriptFile, ['-c', this.country, '-l', this.language, '-p', this.storagePath, this.debug ? '-v' : null, 'turn', deviceId, (poweredOn ? 'on': 'off')]); this.logDebug(data); return true; } catch (error) { this.logDebug(error); return false; } } public async setTargetTemperature(deviceId: string, temperatureInCelsius: number): Promise<boolean> { try { const data: string = await PythonUtils.executePython3(WideqAdapter.wideqFolder, WideqAdapter.wideqScriptFile, ['-c', this.country, '-l', this.language, '-p', this.storagePath, this.debug ? '-v' : null, 'set-temp', deviceId, (temperatureInCelsius + '')]); this.logDebug(data); return true; } catch (error) { this.logDebug(error); return false; } } public async setMode(deviceId: string, mode: Mode): Promise<boolean> { try { const data: string = await PythonUtils.executePython3(WideqAdapter.wideqFolder, WideqAdapter.wideqScriptFile, ['-c', this.country, '-l', this.language, '-p', this.storagePath, this.debug ? '-v' : null, 'set-mode', deviceId, mode]); this.logDebug(data); return true; } catch (error) { this.logDebug(error); return false; } } public async setFanSpeed(deviceId: string, fanSpeed: FanSpeed): Promise<boolean> { try { const data: string = await PythonUtils.executePython3(WideqAdapter.wideqFolder, WideqAdapter.wideqScriptFile, ['-c', this.country, '-l', this.language, '-p', this.storagePath, this.debug ? '-v' : null, 'set-speed', deviceId, fanSpeed]); this.logDebug(data); return true; } catch (error) { this.logDebug(error); return false; } } public async setSwingModeV(deviceId: string, swingModeV: VSwingMode): Promise<boolean> { try { const data: string = await PythonUtils.executePython3(WideqAdapter.wideqFolder, WideqAdapter.wideqScriptFile, ['-c', this.country, '-l', this.language, '-p', this.storagePath, this.debug ? '-v' : null, 'set-swing-v', deviceId, swingModeV]); this.logDebug(data); return true; } catch (error) { this.logDebug(error); return false; } } public async setSwingModeH(deviceId: string, swingModeH: HSwingMode): Promise<boolean> { try { const data: string = await PythonUtils.executePython3(WideqAdapter.wideqFolder, WideqAdapter.wideqScriptFile, ['-c', this.country, '-l', this.language, '-p', this.storagePath, this.debug ? '-v' : null, 'set-swing-h', deviceId, swingModeH]); this.logDebug(data); return true; } catch (error) { this.logDebug(error); return false; } } public static fanSpeedToPercentage(fanSpeed: FanSpeed): number { switch (fanSpeed) { case FanSpeed.SLOW: return 12.5; case FanSpeed.SLOW_LOW: return 25; case FanSpeed.LOW: return 37.5; case FanSpeed.LOW_MID: return 50; case FanSpeed.MID: return 62.5; case FanSpeed.MID_HIGH: return 75; case FanSpeed.HIGH: return 87.5; case FanSpeed.POWER: return 100; case FanSpeed.AUTO: case FanSpeed.NATURE: case FanSpeed.R_LOW: case FanSpeed.R_MID: case FanSpeed.R_HIGH: case FanSpeed.L_LOW: case FanSpeed.L_MID: case FanSpeed.L_HIGH: case FanSpeed.L_LOWR_LOW: case FanSpeed.L_LOWR_MID: case FanSpeed.L_LOWR_HIGH: case FanSpeed.L_MIDR_LOW: case FanSpeed.L_MIDR_MID: case FanSpeed.L_MIDR_HIGH: case FanSpeed.L_HIGHR_LOW: case FanSpeed.L_HIGHR_MID: case FanSpeed.L_HIGHR_HIGH: case FanSpeed.AUTO_2: case FanSpeed.POWER_2: case FanSpeed.LONGPOWER: return 0; } } public static percentageToFanSpeed(percentage: number): FanSpeed { if (percentage <= 12.5) { return FanSpeed.SLOW; } else if (percentage <= 25) { return FanSpeed.SLOW_LOW; } else if (percentage <= 37.5) { return FanSpeed.LOW; } else if (percentage <= 50) { return FanSpeed.LOW_MID; } else if (percentage <= 62.5) { return FanSpeed.MID; } else if (percentage <= 75) { return FanSpeed.MID_HIGH; } else if (percentage <= 87.5) { return FanSpeed.HIGH; } else if (percentage <= 100) { return FanSpeed.POWER; } } } export interface AirCooler { deviceId: string; deviceType: string; modelName: string; country: string; language: string; } export interface AirCoolerStatus { isOn: boolean mode: Mode, currentTempInCelsius: number, targetTempInCelsius: number, fanSpeed: FanSpeed } /* * WIDEQ AC related enums * Please check ac.py for updated values & documentation **/ export enum HSwingMode { OFF = "OFF", ONE = "ONE", TWO = "TWO", THREE = "THREE", FOUR = "FOUR", FIVE = "FIVE", LEFT_HALF = "LEFT_HALF", RIGHT_HALF = "RIGHT_HALF", ALL = "ALL", } export enum VSwingMode { OFF = "OFF", ONE = "ONE", TWO = "TWO", THREE = "THREE", FOUR = "FOUR", FIVE = "FIVE", SIX = "SIX", ALL = "ALL" } export enum Mode { COOL = "COOL", DRY = "DRY", FAN = "FAN", AI = "AI", HEAT = "HEAT", //TODO: Figure out which mode settings actually work! AIRCLEAN = "AIRCLEAN", ACO = "ACO", AROMA = "AROMA", ENERGY_SAVING = "ENERGY_SAVING", ENERGY_SAVER = "ENERGY_SAVER", } export enum FanSpeed { SLOW = 'SLOW', SLOW_LOW = 'SLOW_LOW', LOW = 'LOW', LOW_MID = 'LOW_MID', MID = 'MID', MID_HIGH = 'MID_HIGH', HIGH = 'HIGH', //TODO: Figure out which fan speed settings actually work! POWER = 'POWER', AUTO = 'AUTO', NATURE = 'NATURE', R_LOW = 'R_LOW', R_MID = 'R_MID', R_HIGH = 'R_HIGH', L_LOW = 'L_LOW', L_MID = 'L_MID', L_HIGH = 'L_HIGH', L_LOWR_LOW = 'L_LOWR_LOW', L_LOWR_MID = 'L_LOWR_MID', L_LOWR_HIGH = 'L_LOWR_HIGH', L_MIDR_LOW = 'L_MIDR_LOW', L_MIDR_MID = 'L_MIDR_MID', L_MIDR_HIGH = 'L_MIDR_HIGH', L_HIGHR_LOW = 'L_HIGHR_LOW', L_HIGHR_MID = 'L_HIGHR_MID', L_HIGHR_HIGH = 'L_HIGHR_HIGH', AUTO_2 = 'AUTO_2', POWER_2 = 'POWER_2', LONGPOWER = 'LONGPOWER' }