homebridge-tasmota-control
Version:
Homebridge plugin to control Tasmota flashed devices.
846 lines (787 loc) • 166 kB
JavaScript
import { promises as fsPromises } from 'fs';
import axios from 'axios';
import EventEmitter from 'events';
import ImpulseGenerator from './impulsegenerator.js';
import { ApiCommands, MiElHVAC, LightKeys, SensorKeys, TemperatureDisplayUnits } from './constants.js';
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
class TasmotaDevice extends EventEmitter {
constructor(api, config, miElHvac, defaultHeatingSetTemperatureFile, defaultCoolingSetTemperatureFile) {
super();
Accessory = api.platformAccessory;
Characteristic = api.hap.Characteristic;
Service = api.hap.Service;
Categories = api.hap.Categories;
AccessoryUUID = api.hap.uuid;
//device configuration
this.name = config.name;
const host = config.host;
const auth = config.auth || false;
const url = `http://${host}/cm?cmnd=`;
const user = config.user || '';
const passwd = config.passwd || '';
//mitsubishi ac
this.heatDryFanMode = miElHvac.heatDryFanMode || 1; //NONE, HEAT, DRY, FAN
this.coolDryFanMode = miElHvac.coolDryFanMode || 1; //NONE, COOL, DRY, FAN
this.autoDryFanMode = miElHvac.autoDryFanMode || 1; //NONE, COOL, DRY, FAN
//external sensor
const remoteTemperatureSensor = miElHvac.remoteTemperatureSensor ?? {};
const remoteTemperatureSensorEnable = remoteTemperatureSensor.enable || false;
const remoteTemperatureSensorPath = remoteTemperatureSensor.path;
const remoteTemperatureSensorRefreshInterval = remoteTemperatureSensor.refreshInterval * 1000 || 5000;
const remoteTemperatureSensorAuth = remoteTemperatureSensor.auth || false;
const remoteTemperatureSensorUser = remoteTemperatureSensor.user;
const remoteTemperatureSensorPasswd = remoteTemperatureSensor.passwd;
this.remoteTemperatureSensorEnable = remoteTemperatureSensorEnable;
this.remoteTemperatureSensorRefreshInterval = remoteTemperatureSensorRefreshInterval;
//presets
const presets = miElHvac.presets || [];
this.presetsConfigured = [];
for (const preset of presets) {
const presetName = preset.name ?? false;
const presetDisplayType = preset.displayType ?? 0;
const presetNamePrefix = preset.namePrefix ?? false;
if (presetName && presetDisplayType > 0) {
const presetyServiceType = ['', Service.Outlet, Service.Switch, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][presetDisplayType];
const presetCharacteristicType = ['', Characteristic.On, Characteristic.On, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][presetDisplayType];
preset.namePrefix = presetNamePrefix;
preset.serviceType = presetyServiceType;
preset.characteristicType = presetCharacteristicType;
preset.state = false;
preset.previousSettings = {};
this.presetsConfigured.push(preset);
} else {
const log = presetDisplayType === 0 ? false : this.emit('warn', `Preset Name: ${preset ? preset : 'Missing'}`);
};
}
this.presetsConfiguredCount = this.presetsConfigured.length || 0;
//buttons
const buttons = miElHvac.buttons || [];
this.buttonsConfigured = [];
for (const button of buttons) {
const buttonName = button.name ?? false;
const buttonMode = button.mode ?? -1;
const buttonDisplayType = button.displayType ?? 0;
const buttonNamePrefix = button.namePrefix ?? false;
if (buttonName && buttonMode >= 0 && buttonDisplayType > 0) {
const buttonServiceType = ['', Service.Outlet, Service.Switch][buttonDisplayType];
const buttonCharacteristicType = ['', Characteristic.On, Characteristic.On][buttonDisplayType];
button.namePrefix = buttonNamePrefix;
button.serviceType = buttonServiceType;
button.characteristicType = buttonCharacteristicType;
button.state = false;
button.previousValue = null;
this.buttonsConfigured.push(button);
} else {
const log = buttonDisplayType === 0 ? false : this.emit('warn', `Button Name: ${buttonName ? buttonName : 'Missing'}, Mode: ${buttonMode ? buttonMode : 'Missing'}`);
};
}
this.buttonsConfiguredCount = this.buttonsConfigured.length || 0;
//sensors
const sensors = miElHvac.sensors || [];
this.sensorsConfigured = [];
for (const sensor of sensors) {
const sensorName = sensor.name ?? false;
const sensorMode = sensor.mode ?? -1;
const sensorDisplayType = sensor.displayType ?? 0;
const sensorNamePrefix = sensor.namePrefix ?? false;
if (sensorName && sensorMode >= 0 && sensorDisplayType > 0) {
const sensorServiceType = ['', Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor][sensorDisplayType];
const sensorCharacteristicType = ['', Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState][sensorDisplayType];
sensor.namePrefix = sensorNamePrefix;
sensor.serviceType = sensorServiceType;
sensor.characteristicType = sensorCharacteristicType;
sensor.state = false;
sensor.previousValue = null;
this.sensorsConfigured.push(sensor);
} else {
const log = sensorDisplayType === 0 ? false : this.emit('warn', `Sensor Name: ${sensorName ? sensorName : 'Missing'}, Mode: ${sensorMode ? sensorMode : 'Missing'}`);
};
}
this.sensorsConfiguredCount = this.sensorsConfigured.length || 0;
//frost protect
const frostProtect = miElHvac.frostProtect ?? {};
this.frostProtectEnable = frostProtect.enable || false;
this.frostProtectLowTemp = frostProtect.lowTemp || 14;
this.frostProtectHighTemp = frostProtect.highTemp || 16;
this.frostProtectActive = false;
//extra sensors
this.temperatureSensor = miElHvac.temperatureSensor || false;
this.temperatureSensorOutdoor = miElHvac.temperatureSensorOutdoor || false;
//other config
this.relaysDisplayType = config.relaysDisplayType || 0;
this.relaysNamePrefix = config.relaysNamePrefix || false;
this.lightsNamePrefix = config.lightsNamePrefix || false;
this.sensorsNamePrefix = config.sensorsNamePrefix || false;
this.enableDebugMode = config.enableDebugMode || false;
this.disableLogInfo = config.disableLogInfo || false;
this.disableLogDeviceInfo = config.disableLogDeviceInfo || false;
this.loadNameFromDevice = config.loadNameFromDevice || false;
const refreshInterval = config.refreshInterval * 1000 || 5000;
this.refreshInterval = refreshInterval;
//files
this.defaultHeatingSetTemperatureFile = defaultHeatingSetTemperatureFile;
this.defaultCoolingSetTemperatureFile = defaultCoolingSetTemperatureFile;
//switches, outlets, lights
this.relaysCount = 0;
//sensors
this.sensorsCount = 0;
this.sensorsTemperatureCount = 0;
this.sensorsReferenceTemperatureCount = 0;
this.sensorsObjTemperatureCount = 0;
this.sensorsAmbTemperatureCount = 0;
this.sensorsHumidityCount = 0;
this.sensorsDewPointTemperatureCount = 0;
this.sensorsPressureCount = 0;
this.sensorsGasCount = 0;
this.sensorsCarbonDioxydeCount = 0;
this.sensorsAmbientLightCount = 0;
this.sensorsMotionCount = 0;
//variable
this.startPrepareAccessory = true;
//mielhvac
this.accessory = {};
this.device = 0; //0 - mielhvac, 1 - switch/outlet, 2 - light
this.previousStateSwingV = 'auto';
this.previousStateSwingH = 'center';
//axios instance
this.axiosInstance = axios.create({
method: 'GET',
baseURL: url,
timeout: refreshInterval > 10000 ? 10000 : refreshInterval,
withCredentials: auth,
auth: {
username: user,
password: passwd
}
});
//axios instance remote temp
if (remoteTemperatureSensorEnable) {
const path = remoteTemperatureSensorPath;
this.axiosInstanceRemoteTemp = axios.create({
method: 'GET',
baseURL: path,
timeout: remoteTemperatureSensorRefreshInterval > 10000 ? 10000 : remoteTemperatureSensorRefreshInterval,
withCredentials: remoteTemperatureSensorAuth,
auth: {
username: remoteTemperatureSensorUser,
password: remoteTemperatureSensorPasswd
}
});
};
//impulse generator
this.impulseGenerator = new ImpulseGenerator();
this.impulseGenerator.on('checkDeviceState', async () => {
try {
await this.checkDeviceState();
} catch (error) {
this.emit('error', `Impulse generator error: ${error}`);
};
}).on('updateRemoteTemp', async () => {
try {
await this.updateRemoteTemp();
} catch (error) {
this.emit('error', `Impulse generator error: ${error}`);
};
}).on('state', (state) => {
const emitState = state ? this.emit('success', `Impulse generator started`) : this.emit('warn', `Impulse generator stopped`);
});
};
async getDeviceInfo() {
const debug = this.enableDebugMode ? this.emit('debug', `Requesting info`) : false;
try {
const deviceInfoData = await this.axiosInstance(ApiCommands.Status);
const deviceInfo = deviceInfoData.data ?? {};
const debug = this.enableDebugMode ? this.emit('debug', `Info: ${JSON.stringify(deviceInfo, null, 2)}`) : false;
await new Promise(resolve => setTimeout(resolve, 250));
//status
const friendlyNames = [];
const status = deviceInfo.Status ?? {};
const deviceName = this.loadNameFromDevice ? status.DeviceName ?? 'Unknown' : this.name;
const friendlyName = status.FriendlyName ?? [];
const relaysName = Array.isArray(friendlyName) ? friendlyName : [friendlyName];
for (const relayName of relaysName) {
const name = relayName ?? 'Unknown'
friendlyNames.push(name);
};
//status FWR
const statusFwr = deviceInfo.StatusFWR ?? {};
const firmwareRevision = statusFwr.Version ?? 'Unknown';
const modelName = statusFwr.Hardware ?? 'Unknown';
//status NET
const statusNet = deviceInfo.StatusNET ?? {};
const addressMac = statusNet.Mac ?? false;
//status SNS
const statusSns = deviceInfo.StatusSNS ?? {};
const statusSnsKeys = Object.keys(statusSns);
//status STS
const statusSts = deviceInfo.StatusSTS ?? {};
const statusStsKeys = Object.keys(statusSts);
this.device = statusSnsKeys.includes('MiElHVAC') ? 0 : statusStsKeys.some(key => LightKeys.includes(key)) ? 2 : 1;
this.deviceName = deviceName;
this.friendlyNames = friendlyNames;
this.modelName = modelName;
this.serialNumber = addressMac;
this.firmwareRevision = firmwareRevision;
this.relaysCount = friendlyNames.length;
return addressMac;
} catch (error) {
throw new Error(`Check info error: ${error}`);
};
};
async checkDeviceState() {
const debug = this.enableDebugMode ? this.emit('debug', `Requesting status`) : false;
try {
//power status
const powerStatusData = await this.axiosInstance(ApiCommands.PowerStatus);
const powerStatus = powerStatusData.data ?? {};
const debug = this.enableDebugMode ? this.emit('debug', `Power status: ${JSON.stringify(powerStatus, null, 2)}`) : false;
//power status keys
const powerStatusKeys = Object.keys(powerStatus);
//sensor status
const sensorStatusData = await this.axiosInstance(ApiCommands.Status);
const sensorStatus = sensorStatusData.data ?? {};
const debug1 = this.enableDebugMode ? this.emit('debug', `Sensors status: ${JSON.stringify(sensorStatus, null, 2)}`) : false;
//sensor status keys
const sensorStatusKeys = Object.keys(sensorStatus);
//status SNS
const statusSnsSupported = sensorStatusKeys.includes('StatusSNS');
const statusSns = statusSnsSupported ? sensorStatus.StatusSNS : {};
const statusSnsKeys = Object.keys(statusSns);
//status STS
const statusStsSupported = sensorStatusKeys.includes('StatusSTS');
const statusSts = statusStsSupported ? sensorStatus.StatusSTS : {};
const statusStsKeys = Object.keys(statusSts);
//relays
const relaysCount = this.relaysCount;
//device
switch (this.device) {
case 0: //mielhvac
//power
const power1 = powerStatus.POWER == 'ON' ? 1 : 0;
//status SNS
const time = statusSns.Time ?? '';
const temperatureUnit = statusSns.TempUnit === 'C' ? '°C' : 'F';
//mielhvac
const miElHvac = statusSns.MiElHVAC ?? {};
const power = miElHvac.Power === 'on' ? 1 : 0;
const roomTemperature = miElHvac.Temperature ?? null;
const outdoorTemperature = miElHvac.OutdoorTemperature ?? null;
const setTemperature = miElHvac.SetTemperature;
const operationMode = miElHvac.Mode ?? 'Unknown';
const operationModeStage = miElHvac.ModeStage ?? 'Unknown';
const fanSpeed = miElHvac.FanSpeed ?? 'Unknown';
const fanSpeedStage = miElHvac.FanStage ?? 'Unknown';
const vaneVerticalDirection = miElHvac.SwingV ?? 'Unknown';
const vaneHorizontalDirection = miElHvac.SwingH ?? 'Unknown';
const prohibit = miElHvac.Prohibit ?? 'Unknown';
const airDirection = miElHvac.AirDirection ?? 'Unknown';
const compressor = miElHvac.Compressor ?? 'Unknown';
const compressorFrequency = miElHvac.CompressorFrequency ?? 0;
const operationPower = miElHvac.OperationPower ?? 0;
const operationEnergy = miElHvac.OperationEnergy ?? 0;
const operationStage = miElHvac.OperationStage ?? 'Unknown';
const swingMode = vaneVerticalDirection === 'swing' && vaneHorizontalDirection === 'swing' ? 1 : 0;
const defaultCoolingSetTemperature = parseFloat(await this.readData(this.defaultCoolingSetTemperatureFile));
const defaultHeatingSetTemperature = parseFloat(await this.readData(this.defaultHeatingSetTemperatureFile));
const remoteTemperatureSensorState = miElHvac.RemoteTemperatureSensorState ?? false; //ON, OFF
const remoteTemperatureSensorAutoClearTime = miElHvac.RemoteTemperatureSensorAutoClearTime ?? 0; //time in ms
const modelSupportsHeat = true;
const modelSupportsDry = true;
const modelSupportsCool = true;
const modelSupportsAuto = true;
const modelSupportsFanSpeed = true;
const hasAutomaticFanSpeed = true;
const numberOfFanSpeeds = 5;
const lockPhysicalControl = prohibit === 'all' ?? false;
const useFahrenheit = temperatureUnit === 'F' ?? false;
const temperatureIncrement = useFahrenheit ? 1 : 0.5;
const hideDryModeControl = false;
const hideVaneControls = false;
this.accessory = {
time: time,
power: power,
roomTemperature: roomTemperature,
outdoorTemperature: outdoorTemperature,
setTemperature: setTemperature,
operationMode: operationMode,
operationModeStage: operationModeStage,
vaneVerticalDirection: vaneVerticalDirection,
vaneHorizontalDirection: vaneHorizontalDirection,
prohibit: prohibit,
airDirection: airDirection,
swingMode: swingMode,
compressor: compressor,
compressorFrequency: compressorFrequency,
operationPower: operationPower,
operationEnergy: operationEnergy,
operationStage: operationStage,
defaultCoolingSetTemperature: defaultCoolingSetTemperature,
defaultHeatingSetTemperature: defaultHeatingSetTemperature,
remoteTemperatureSensorState: remoteTemperatureSensorState,
remoteTemperatureSensorAutoClearTime: remoteTemperatureSensorAutoClearTime,
modelSupportsHeat: modelSupportsHeat,
modelSupportsDry: modelSupportsDry,
modelSupportsCool: modelSupportsCool,
modelSupportsAuto: modelSupportsAuto,
modelSupportsFanSpeed: modelSupportsFanSpeed,
hasAutomaticFanSpeed: hasAutomaticFanSpeed,
numberOfFanSpeeds: numberOfFanSpeeds,
lockPhysicalControl: prohibit === 'all' ? 1 : 0,
temperatureUnit: temperatureUnit,
useFahrenheit: useFahrenheit,
temperatureIncrement: temperatureIncrement,
hideDryModeControl: hideDryModeControl,
hideVaneControls: hideVaneControls
};
//operation mode
const operationModeStageMap = {
'manual': 0,
'heat': 2,
'dry': 1,
'cool': 3,
'fan': 1,
'heat_isee': 2,
'dry_isee': 1,
'cool_isee': 3,
'auto_fan': 1,
'auto_heat': 2,
'auto_cool': 3,
'auto_leader': 4
};
switch (operationMode) {
case 'heat':
this.accessory.currentOperationMode = [2, 1, 2, 3, 0][operationModeStageMap[operationModeStage]]; //INACTIVE, IDLE, HEATING, COOLING
this.accessory.targetOperationMode = 1; //AUTO, HEAT, COOL
break;
case 'dry':
this.accessory.currentOperationMode = [1, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
break;
case 'cool':
this.accessory.currentOperationMode = [3, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
this.accessory.targetOperationMode = 2;
break;
case 'fan':
this.accessory.currentOperationMode = [1, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
this.accessory.targetOperationMode = this.autoDryFanMode === 3 ? 0 : this.heatDryFanMode === 3 ? 1 : this.coolDryFanMode === 3 ? 2 : this.accessory.targetOperationMode ?? 0;
break;
case 'auto':
this.accessory.currentOperationMode = [2, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
this.accessory.targetOperationMode = 0;
break;
case 'heat_isee':
this.accessory.currentOperationMode = [2, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
this.accessory.targetOperationMode = 1;
break;
case 'dry_isee':
this.accessory.currentOperationMode = [1, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
this.accessory.targetOperationMode = this.autoDryFanMode === 2 ? 0 : this.heatDryFanMode === 2 ? 1 : this.coolDryFanMode === 2 ? 2 : this.accessory.targetOperationMode ?? 0;
break;
case 'cool_isee':
this.accessory.currentOperationMode = [3, 1, 2, 3, 0][operationModeStageMap[operationModeStage]];
this.accessory.targetOperationMode = 2;
break;
default:
this.emit('warn', `Unknown operating mode: ${operationMode}`);
return
};
this.accessory.currentOperationMode = !power ? 0 : this.accessory.currentOperationMode;
this.accessory.operationModeSetPropsMinValue = modelSupportsAuto && modelSupportsHeat ? 0 : !modelSupportsAuto && modelSupportsHeat ? 1 : modelSupportsAuto && !modelSupportsHeat ? 0 : 2;
this.accessory.operationModeSetPropsMaxValue = 2
this.accessory.operationModeSetPropsValidValues = modelSupportsAuto && modelSupportsHeat ? [0, 1, 2] : !modelSupportsAuto && modelSupportsHeat ? [1, 2] : modelSupportsAuto && !modelSupportsHeat ? [0, 2] : [2];
if (modelSupportsFanSpeed) {
//fan speed mode
const fanSpeedMap = {
'auto': 0,
'quiet': 1,
'1': 2,
'2': 3,
'3': 4,
'4': 5
};
switch (numberOfFanSpeeds) {
case 2: //Fan speed mode 2
this.accessory.fanSpeed = hasAutomaticFanSpeed ? [3, 1, 2][fanSpeedMap[fanSpeed]] : [0, 1, 2][fanSpeedMap[fanSpeed]];
this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 3 : 2;
break;
case 3: //Fan speed mode 3
this.accessory.fanSpeed = hasAutomaticFanSpeed ? [4, 1, 2, 3][fanSpeedMap[fanSpeed]] : [0, 1, 2, 3][fanSpeedMap[fanSpeed]];
this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 4 : 3;
break;
case 4: //Fan speed mode 4
this.accessory.fanSpeed = hasAutomaticFanSpeed ? [5, 1, 2, 3, 4][fanSpeedMap[fanSpeed]] : [0, 1, 2, 3, 4][fanSpeedMap[fanSpeed]];
this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 5 : 4;
break;
case 5: //Fan speed mode 5
this.accessory.fanSpeed = hasAutomaticFanSpeed ? [6, 1, 2, 3, 4, 5][fanSpeedMap[fanSpeed]] : [0, 1, 2, 3, 4, 5][fanSpeedMap[fanSpeed]];
this.accessory.fanSpeedSetPropsMaxValue = hasAutomaticFanSpeed ? 6 : 5;
break;
};
};
//update characteristics
if (this.miElHvacService) {
this.miElHvacService
.updateCharacteristic(Characteristic.Active, power)
.updateCharacteristic(Characteristic.CurrentHeaterCoolerState, this.accessory.currentOperationMode)
.updateCharacteristic(Characteristic.TargetHeaterCoolerState, this.accessory.targetOperationMode)
.updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature)
.updateCharacteristic(Characteristic.LockPhysicalControls, lockPhysicalControl)
.updateCharacteristic(Characteristic.TemperatureDisplayUnits, useFahrenheit)
.updateCharacteristic(Characteristic.SwingMode, swingMode);
const updateDefCool = operationMode === 'auto' || operationMode === 'cool' ? this.miElHvacService.updateCharacteristic(Characteristic.CoolingThresholdTemperature, operationMode === 'auto' ? defaultCoolingSetTemperature : setTemperature) : false;
const updateDefHeat = operationMode === 'auto' || operationMode === 'heat' ? this.miElHvacService.updateCharacteristic(Characteristic.HeatingThresholdTemperature, operationMode === 'auto' ? defaultHeatingSetTemperature : setTemperature) : false;
const updateRS = modelSupportsFanSpeed ? this.miElHvacService.updateCharacteristic(Characteristic.RotationSpeed, this.accessory.fanSpeed) : false;
if (this.frostProtectEnable) {
if (roomTemperature <= this.frostProtectLowTemp && !power) {
this.miElHvacService
.setCharacteristic(Characteristic.Active, true)
.setCharacteristic(Characteristic.TargetHeaterCoolerState, 1)
.setCharacteristic(Characteristic.HeatingThresholdTemperature, this.frostProtectHighTemp);
this.frostProtectActive = true;
};
if (roomTemperature >= this.frostProtectHighTemp && this.frostProtectActive) {
this.miElHvacService.setCharacteristic(Characteristic.Active, false);
this.frostProtectActive = false;
};
};
};
//update presets state
if (this.presetsConfigured.length > 0) {
for (let i = 0; i < this.presetsConfigured.length; i++) {
const preset = this.presetsConfigured[i];
let iseeMode = operationMode;
iseeMode = (operationMode === 'heat' || operationMode === 'heat_isee') ? 'heat' : iseeMode;
iseeMode = (operationMode === 'dry' || operationMode === 'dry_isee') ? 'dry' : iseeMode;
iseeMode = (operationMode === 'cool' || operationMode === 'cool_isee') ? 'cool' : iseeMode;
preset.state = power ? (preset.mode === iseeMode
&& (preset.setTemp).toFixed(1) === parseFloat(setTemperature).toFixed(1)
&& preset.fanSpeed === fanSpeed
&& preset.swingV === vaneVerticalDirection
&& preset.swingH === vaneHorizontalDirection) : false;
if (this.presetsServices) {
const characteristicType = preset.characteristicType;
this.presetsServices[i]
.updateCharacteristic(characteristicType, preset.state)
};
};
};
//update buttons state
if (this.buttonsConfiguredCount > 0) {
for (let i = 0; i < this.buttonsConfiguredCount; i++) {
const button = this.buttonsConfigured[i];
const mode = button.mode;
switch (mode) {
case 0: //POWER ON,OFF
button.state = power === 1;
break;
case 1: //OPERATING MODE HEAT
button.state = power ? (operationMode === 'heat' || operationMode === 'heat_isee') : false;
break;
case 2: //OPERATING MODE DRY
button.state = power ? (operationMode === 'dry' || operationMode === 'dry_isee') : false;
break
case 3: //OPERATING MODE COOL
button.state = power ? (operationMode === 'cool' || operationMode === 'cool_isee') : false;
break;
case 4: //OPERATING MODE FAN
button.state = power ? (operationMode === 'fan') : false;
break;
case 5: //OPERATING MODE AUTO
button.state = power ? (operationMode === 'auto') : false;
break;
case 6: //OPERATING MODE PURIFY
button.state = power ? (operationMode === 'purify') : false;
break;
case 10: //VANE H AUTO
button.state = power ? (vaneHorizontalDirection === 'auto') : false;
break;
case 11: //VANE H LEFT
button.state = power ? (vaneHorizontalDirection === 'left') : false;
break;
case 12: //VANE H LEFT MIDDLE
button.state = power ? (vaneHorizontalDirection === 'left_middle') : false;
break;
case 13: //VANE H CENTER
button.state = power ? (vaneHorizontalDirection === 'center') : false;
break;
case 14: //VANE H RIGHT MIDDLE
button.state = power ? (vaneHorizontalDirection === 'right_middle') : false;
break;
case 15: //VANE H RIGHT
button.state = power ? (vaneHorizontalDirection === 'right') : false;
break;
case 16: //VANE H SPLIT
button.state = power ? (vaneHorizontalDirection === 'split') : false;
break;
case 17: //VANE H SWING
button.state = power ? (vaneHorizontalDirection === 'swing') : false;
break;
case 20: //VANE V AUTO
button.state = power ? (vaneVerticalDirection === 'auto') : false;
break;
case 21: //VANE V UP
button.state = power ? (vaneVerticalDirection === 'up') : false;
break;
case 22: //VANE V UP MIDDLE
button.state = power ? (vaneVerticalDirection === 'up_middle') : false;
break;
case 23: //VANE V CENTER
button.state = power ? (vaneVerticalDirection === 'center') : false;
break;
case 24: //VANE V DOWN MIDDLE
button.state = power ? (vaneVerticalDirection === 'down_middle') : false;
break;
case 25: //VANE V DOWN
button.state = power ? (vaneVerticalDirection === 'down') : false;
break;
case 26: //VANE V SWING
button.state = power ? (vaneVerticalDirection === 'swing') : false;
break;
case 30: //FAN SPEED MODE AUTO
button.state = power ? (fanSpeed === 'auto') : false;
break;
case 31: //FAN SPEED MODE 1
button.state = power ? (fanSpeed === 'quiet') : false;
break;
case 32: //FAN SPEED MODE 2
button.state = power ? (fanSpeed === '1') : false;
break;
case 33: //FAN SPEED MODE 3
button.state = power ? (fanSpeed === '2') : false;
break;
case 34: //FAN SPEED MODE 4
button.state = power ? (fanSpeed === '3') : false;
break;
case 35: //FAN SPEED MODE 5
button.state = power ? (fanSpeed === '4') : false;
break;
case 40: //AIR DIRECTION EVEN
button.state = power ? (airDirection === 'even') : false;
break;
case 41: //AIR DIRECTION INDIRECT
button.state = power ? (airDirection === 'indirect') : false;
break;
case 42: //AIR DIRECTION DIRECT
button.state = power ? (airDirection === 'direct') : false;
break;
case 50: //PHYSICAL LOCK CONTROLS ALL
button.state = prohibit === 'all';
break;
case 51: //PHYSICAL LOCK CONTROLS POWER
button.state = prohibit === 'power';
break;
case 52: //PHYSICAL LOCK CONTROLS MODE
button.state = prohibit === 'mode';
break;
case 53: //PHYSICAL LOCK CONTROLS TEMP
button.state = prohibit === 'temp';
break;
default: //Unknown button
this.emit('message', `Unknown button mode: ${mode} detected`);
break;
};
//update services
if (this.buttonsServices) {
const characteristicType = button.characteristicType;
this.buttonsServices[i]
.updateCharacteristic(characteristicType, button.state)
};
};
};
//update sensors state
if (this.sensorsConfiguredCount > 0) {
for (let i = 0; i < this.sensorsConfiguredCount; i++) {
const sensor = this.sensorsConfigured[i];
const mode = sensor.mode;
switch (mode) {
case 0: //POWER ON,OFF
sensor.state = power === 1;
break;
case 1: //OPERATING MODE HEAT
sensor.state = power ? (operationMode === 'heat' || operationMode === 'heat_isee') : false;
break;
case 2: //OPERATING MODE DRY
sensor.state = power ? (operationMode === 'dry' || operationMode === 'dry_isee') : false;
break
case 3: //OPERATING MODE COOL
sensor.state = power ? (operationMode === 'cool' || operationMode === 'cool_isee') : false;
break;
case 4: //OPERATING MODE FAN
sensor.state = power ? (operationMode === 'fan') : false;
break;
case 5: //OPERATING MODE AUTO
sensor.state = power ? (operationMode === 'auto') : false;
break;
case 6: //OPERATING MODE PURIFY
sensor.state = power ? (operationMode === 'purify') : false;
break;
case 10: //VANE H AUTO
sensor.state = power ? (vaneHorizontalDirection === 'auto') : false;
break;
case 11: //VANE H LEFT
sensor.state = power ? (vaneHorizontalDirection === 'left') : false;
break;
case 12: //VANE H LEFT MIDDLE
sensor.state = power ? (vaneHorizontalDirection === 'left_middle') : false;
break;
case 13: //VANE H CENTER
sensor.state = power ? (vaneHorizontalDirection === 'center') : false;
break;
case 14: //VANE H RIGHT MIDDLE
sensor.state = power ? (vaneHorizontalDirection === 'right_middle') : false;
break;
case 15: //VANE H RIGHT
sensor.state = power ? (vaneHorizontalDirection === 'right') : false;
break;
case 16: //VANE H SPLIT
sensor.state = power ? (vaneHorizontalDirection === 'split') : false;
break;
case 17: //VANE H SWING
sensor.state = power ? (vaneHorizontalDirection === 'swing') : false;
break;
case 20: //VANE V AUTO
sensor.state = power ? (vaneVerticalDirection === 'auto') : false;
break;
case 21: //VANE V UP
sensor.state = power ? (vaneVerticalDirection === 'up') : false;
break;
case 22: //VANE V UP MIDDLE
sensor.state = power ? (vaneVerticalDirection === 'up_middle') : false;
break;
case 23: //VANE V CENTER
sensor.state = power ? (vaneVerticalDirection === 'center') : false;
break;
case 24: //VANE V DOWN MIDDLE
sensor.state = power ? (vaneVerticalDirection === 'down_middle') : false;
break;
case 25: //VANE V DOWN
sensor.state = power ? (vaneVerticalDirection === 'down') : false;
break;
case 26: //VANE V SWING
sensor.state = power ? (vaneVerticalDirection === 'swing') : false;
break;
case 27: //VANE H/V CONTROLS HIDE
sensor.state = power ? (hideVaneControls === true) : false;
break;
case 30: //FAN SPEED MODE AUTO
sensor.state = power ? (fanSpeed === 'auto') : false;
break;
case 31: //FAN SPEED MODE 1
sensor.state = power ? (fanSpeed === 'quiet') : false;
break;
case 32: //FAN SPEED MODE 2
sensor.state = power ? (fanSpeed === '1') : false;
break;
case 33: //FAN SPEED MODE 3
sensor.state = power ? (fanSpeed === '2') : false;
break;
case 34: //FAN SPEED MODE 4
sensor.state = power ? (fanSpeed === '3') : false;
break;
case 35: //FAN SPEED MODE 5
sensor.state = power ? (fanSpeed === '4') : false;
break;
case 40: //AIR DIRECTION EVEN
sensor.state = power ? (airDirection === 'even') : false;
break;
case 41: //AIR DIRECTION INDIRECT
sensor.state = power ? (airDirection === 'indirect') : false;
break;
case 42: //AIR DIRECTION DIRECT
sensor.state = power ? (airDirection === 'direct') : false;
break;
case 50: //PHYSICAL LOCK CONTROLS ALL
sensor.state = prohibit === 'all';
break;
case 51: //PHYSICAL LOCK CONTROLS POWER
sensor.state = prohibit === 'power';
break;
case 52: //PHYSICAL LOCK CONTROLS MODE
sensor.state = prohibit === 'mode';
break;
case 53: //PHYSICAL LOCK CONTROLS TEMP
sensor.state = prohibit === 'temp';
break;
case 60: //REMOTE TEMPERATURE STATE
sensor.state = remoteTemperatureSensorState;
break;
case 70: //OPERATION STAGE NORMAL
sensor.state = operationStage === 'normal';
break;
case 71: //OPERATION STAGE DEFROST
sensor.state = operationStage === 'defrost';
break;
case 72: //OPERATION STAGE PREHEAT
sensor.state = operationStage === 'preheat';
break;
case 73: //OPERATION STAGE STANDBY
sensor.state = operationStage === 'standby';
break;
case 80: //FAN STAGE OFF
sensor.state = fanSpeedStage === 'off';
break;
case 81: //FAN STAGE QUIET
sensor.state = fanSpeedStage === 'quiet';;
break;
case 82: //FAN STAGE 1
sensor.state = fanSpeedStage === '1';;
break;
case 83: //FAN STAGE 2
sensor.state = fanSpeedStage === '2';;
break;
case 84: //FAN STAGE 3
sensor.state = fanSpeedStage === '3';;
break;
case 85: //FAN STAGE 4
sensor.state = fanSpeedStage === '4';;
break;
case 86: //FAN STAGE 5
sensor.state = fanSpeedStage === '5';;
break;
case 90: //MODE STAGE AUTO OFF
sensor.state = operationMode !== 'auto';
break;
case 91: //MODE STAGE AUTO FAN
sensor.state = operationModeStage === 'auto_fan';
break;
case 92: //MODE STAGE AUTO HEAT
sensor.state = operationModeStage === 'auto_heat';
break;
case 93: //MODE STAGE AUTO COOL
sensor.state = operationModeStage === 'auto_cool';;
break;
case 94: //MODE STAGE AUTO LEADER
sensor.state = operationModeStage === 'auto_leader';;
break;
default: //Unknown sensor
this.emit('message', `Unknown sensor mode: ${mode} detected`);
break;
};
//update services
if (this.sensorsServices) {
const characteristicType = sensor.characteristicType;
this.sensorsServices[i]
.updateCharacteristic(characteristicType, sensor.state)
};
};
};
//update room temperature sensor
if (this.roomTemperatureSensorService) {
this.roomTemperatureSensorService
.updateCharacteristic(Characteristic.CurrentTemperature, roomTemperature)
};
//update outdoor temperature sensor
if (this.outdoorTemperatureSensorService) {
this.outdoorTemperatureSensorService
.updateCharacteristic(Characteristic.CurrentTemperature, outdoorTemperature)
};
//log current state
if (!this.disableLogInfo) {
this.emit('message', `Power: ${power ? 'ON' : 'OFF'}`);
const info = power ? this.emit('message', `Target operation mode: ${operationMode.toUpperCase()}`) : false;
const info1 = power ? this.emit('message', `Current operation mode: ${operationModeStage.toUpperCase()}`) : false;
const info2 = power ? this.emit('message', `Target temperature: ${setTemperature}${temperatureUnit}`) : false;
const info3 = power ? this.emit('message', `Current temperature: ${roomTemperature}${temperatureUnit}`) : false;
const info4 = power && outdoorTemperature !== null ? this.emit('message', `Outdoor temperature: ${outdoorTemperature}${temperatureUnit}`) : false;
const info5 = power && modelSupportsFanSpeed ? this.emit('message', `Target Fan speed: ${fanSpeed.toUpperCase()}`) : false;
const info6 = power && modelSupportsFanSpeed ? this.emit('messa