homebridge-melcloud-control
Version:
Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.
763 lines (731 loc) • 187 kB
JavaScript
import EventEmitter from 'events';
import MelCloudAtw from './melcloudatw.js';
import RestFul from './restful.js';
import Mqtt from './mqtt.js';
import Functions from './functions.js';
import { TemperatureDisplayUnits, HeatPump, DeviceType } from './constants.js';
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
class DeviceAtw extends EventEmitter {
constructor(api, account, device, presets, schedules, scenes, buttons, defaultTempsFile, melCloudClass, melCloudAccountData, melCloudDeviceData) {
super();
Accessory = api.platformAccessory;
Characteristic = api.hap.Characteristic;
Service = api.hap.Service;
Categories = api.hap.Categories;
AccessoryUUID = api.hap.uuid;
//account config
this.account = account;
this.accountType = account.type;
this.accountName = account.name;
this.accountTypeMelCloud = account.type === 'melcloud';
this.logDeviceInfo = account.log?.deviceInfo || false;
this.logInfo = account.log?.info || false;
this.logWarn = account.log?.warn || false;
this.logDebug = account.log?.debug || false;
this.logError = account.log?.error || false;
//device config
this.device = device;
this.deviceId = device.id;
this.deviceName = device.name;
this.deviceTypeString = DeviceType[device.type];
this.displayType = device.displayType;
this.hideZone = device.hideZone;
this.temperatureOutdoorSensor = device.temperatureOutdoorSensor || false;
this.temperatureRoomSensor = device.temperatureRoomSensor || false;
this.temperatureFlowSensor = device.temperatureFlowSensor || false;
this.temperatureReturnSensor = device.temperatureReturnSensor || false;
this.temperatureRoomZone1Sensor = device.temperatureRoomZone1Sensor || false;
this.temperatureFlowZone1Sensor = device.temperatureFlowZone1Sensor || false;
this.temperatureReturnZone1Sensor = device.temperatureReturnZone1Sensor || false;
this.temperatureWaterTankSensor = device.temperatureWaterTankSensor || false;
this.temperatureFlowWaterTankSensor = device.temperatureFlowWaterTankSensor || false;
this.temperatureReturnWaterTankSensor = device.temperatureReturnWaterTankSensor || false;
this.temperatureRoomZone2Sensor = device.temperatureRoomZone2Sensor || false;
this.temperatureFlowZone2Sensor = device.temperatureFlowZone2Sensor || false;
this.temperatureReturnZone2Sensor = device.temperatureReturnZone2Sensor || false;
this.inStandbySensor = device.inStandbySensor || false;
this.connectSensor = device.connectSensor || false;
this.errorSensor = device.errorSensor || false;
this.frostProtectionSupport = device.frostProtectionSupport || false;
this.holidayModeSupport = device.holidayModeSupport || false;
this.presets = presets;
this.schedules = schedules;
this.scenes = scenes;
this.buttons = buttons;
//files
this.defaultTempsFile = defaultTempsFile;
//melcloud
this.melCloudClass = melCloudClass;
this.melCloudDeviceData = melCloudDeviceData;
this.melCloudAccountData = melCloudAccountData;
//external integrations
this.restFul = account.restFul ?? {};
this.restFul.port = device.restFulPort;
this.restFulConnected = false;
this.mqtt = account.mqtt ?? {};
this.mqttConnected = false;
const serviceType = [null, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, Service.MotionSensor, Service.OccupancySensor, Service.ContactSensor, null];
const characteristicType = [null, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, Characteristic.MotionDetected, Characteristic.OccupancyDetected, Characteristic.ContactSensorState, null];
//presets configured
for (const preset of this.presets) {
preset.serviceType = serviceType[preset.displayType];
preset.characteristicType = characteristicType[preset.displayType];
preset.state = false;
preset.previousSettings = {};
}
//schedules configured
for (const schedule of this.schedules) {
schedule.serviceType = serviceType[schedule.displayType];
schedule.characteristicType = characteristicType[schedule.displayType];
schedule.state = false;
}
//scenes configured
for (const scene of this.scenes) {
scene.serviceType = serviceType[scene.displayType];
scene.characteristicType = characteristicType[scene.displayType];
scene.state = false;
}
//buttons configured
for (const button of this.buttons) {
button.serviceType = serviceType[button.displayType];
button.characteristicType = characteristicType[button.displayType];
button.state = false;
button.previousValue = null;
}
this.functions = new Functions(this.logWarn, this.logError, this.logDebug)
.on('warn', warn => this.emit('warn', warn))
.on('error', error => this.emit('error', error))
.on('debug', debug => this.emit('debug', debug));
//other variables
this.displayDeviceInfo = true;
this.deviceData = {};
this.accessory = {};
}
async setOverExternalIntegration(integration, deviceData, key, value) {
try {
const accountTypeMelCloud = this.accountTypeMelCloud;
let payload = {};
let flag = null;
switch (key) {
case 'Power':
payload.power = value;
break;
case 'OperationModeZone1':
payload.operationModeZone1 = value;
flag = HeatPump.EffectiveFlags.OperationModeZone1;
break;
case 'SetTemperatureZone1':
payload.setTemperatureZone1 = value;
flag = HeatPump.EffectiveFlags.SetTemperatureZone1;
break;
case 'SetHeatFlowTemperatureZone1':
payload.setHeatFlowTemperatureZone1 = value;
flag = HeatPump.EffectiveFlags.SetHeatFlowTemperatureZone1;
break;
case 'SetCoolFlowTemperatureZone1':
payload.setCoolFlowTemperatureZone1 = value;
flag = HeatPump.EffectiveFlags.SetCoolFlowTemperatureZone1;
break;
case 'ProhibitZone1':
if (!accountTypeMelCloud) return;
payload.prohibitZone1 = value;
flag = HeatPump.EffectiveFlags.ProhibitHeatingZone1;
break;
case 'ForcedHotWaterMode':
payload.forcedHotWaterMode = value;
flag = HeatPump.EffectiveFlags.ForcedHotWaterMode;
break;
case 'EcoHotWater':
if (!accountTypeMelCloud) return;
payload.ecoHotWater = value;
flag = HeatPump.EffectiveFlags.EcoHotWater;
break;
case 'SetTankWaterTemperature':
payload.setTankWaterTemperature = value;
flag = HeatPump.EffectiveFlags.SetTankWaterTemperature;
break;
case 'ProhibitHotWater':
payload.prohibitHotWater = value;
flag = HeatPump.EffectiveFlags.ProhibitHotWater;
break;
case 'OperationModeZone2':
payload.operationModeZone2 = value;
flag = HeatPump.EffectiveFlags.OperationModeZone2;
break;
case 'SetTemperatureZone2':
payload.setTemperatureZone2 = value;
flag = HeatPump.EffectiveFlags.SetTemperatureZone2;
break;
case 'SetHeatFlowTemperatureZone2':
payload.setHeatFlowTemperatureZone2 = value;
flag = HeatPump.EffectiveFlags.SetHeatFlowTemperatureZone2;
break;
case 'SetCoolFlowTemperatureZone2':
payload.setCoolFlowTemperatureZone2 = value;
flag = HeatPump.EffectiveFlags.SetCoolFlowTemperatureZone2;
break;
case 'ProhibitZone2':
if (!accountTypeMelCloud) return;
payload.prohibitZone2 = value;
flag = HeatPump.EffectiveFlags.ProhibitHeatingZone2;
break;
case 'FrostProtection':
if (accountTypeMelCloud) return;
payload.enabled = value;
flag = 'frostprotection';
break;
case 'Schedules':
if (accountTypeMelCloud) return;
payload.enabled = value;
flag = 'schedule';
break;
case 'HolidayMode':
if (accountTypeMelCloud) {
payload.holidayMode = value;
flag = HeatPump.EffectiveFlags.HolidayMode;
}
if (!accountTypeMelCloud) {
payload.enabled = value;
flag = 'holidaymode';
}
break;
default:
this.emit('warn', `${integration}, received unknown key: ${key}, value: ${value}`);
return;
};
return await this.melCloudAtw.send(this.accountType, this.displayType, deviceData, payload, flag);
} catch (error) {
throw new Error(`${integration} set key: ${key}, value: ${value}, error: ${error.message ?? error}`);
};
}
async externalIntegrations() {
//RESTFul server
const restFulEnabled = this.restFul.enable || false;
if (restFulEnabled) {
try {
await new Promise((resolve) => {
const timer = setTimeout(resolve, 5000);
this.restFul1 = new RestFul({
port: this.device.restFul.port,
logWarn: this.logWarn,
logDebug: this.logDebug,
})
.once('connected', (success) => {
clearTimeout(timer);
this.restFulConnected = true;
this.emit('success', success);
resolve();
})
.on('set', async (key, value) => {
try {
await this.setOverExternalIntegration('RESTFul', this.deviceData, key, value);
} catch (error) {
if (this.logWarn) this.emit('warn', `RESTFul set error: ${error}`);
};
})
.on('debug', (debug) => this.emit('debug', debug))
.on('warn', (warn) => this.emit('warn', warn))
.on('error', (error) => this.emit('error', error));
});
} catch (error) {
this.emit('warn', `RESTFul integration start error: ${error}`);
}
}
const mqttEnabled = this.mqtt.enable || false;
if (mqttEnabled) {
try {
await new Promise((resolve) => {
const timer = setTimeout(resolve, 10000);
this.mqtt1 = new Mqtt({
host: this.mqtt.host,
port: this.mqtt.port || 1883,
clientId: this.mqtt.clientId ? `melcloud_${this.mqtt.clientId}_${Math.random().toString(16).slice(3)}` : `melcloud_${Math.random().toString(16).slice(3)}`,
prefix: this.mqtt.prefix ? `melcloud/${this.mqtt.prefix}/${this.deviceTypeString}/${this.deviceName}` : `melcloud/${this.deviceTypeString}/${this.deviceName}`,
user: this.mqtt.auth?.user,
passwd: this.mqtt.auth?.passwd,
logWarn: this.logWarn,
logDebug: this.logDebug
})
.once('connected', (success) => {
clearTimeout(timer);
this.mqttConnected = true;
this.emit('success', success);
resolve();
})
.on('subscribed', (success) => {
this.emit('success', success);
})
.on('set', async (key, value) => {
try {
await this.setOverExternalIntegration('MQTT', this.deviceData, key, value);
} catch (error) {
if (this.logWarn) this.emit('warn', `MQTT set, error: ${error}`);
};
})
.on('debug', (debug) => this.emit('debug', debug))
.on('warn', (warn) => this.emit('warn', warn))
.on('error', (error) => this.emit('error', error));
});
} catch (error) {
this.emit('warn', `MQTT integration start error: ${error}`);
}
};
return true;
}
//prepare accessory
async prepareAccessory() {
try {
const accountTypeMelCloud = this.accountTypeMelCloud;
const deviceData = this.deviceData;
const deviceId = this.deviceId;
const deviceTypeString = this.deviceTypeString;
const deviceName = this.deviceName;
const accountName = this.accountName;
const presetsOnServer = this.accessory.presets;
const schedulesOnServer = this.accessory.schedules;
const scenesOnServer = this.accessory.scenes;
const zonesCount = this.accessory.zonesCount;
const caseHeatPump = this.accessory.caseHeatPump;
const caseZone1 = this.accessory.caseZone1;
const caseHotWater = this.accessory.caseHotWater;
const caseZone2 = this.accessory.caseZone2;
const heatCoolModes = this.accessory.heatCoolModes;
const zonesSensorsCount = this.accessory.sensorsCount;
const caseHeatPumpSensor = this.accessory.caseHeatPumpSensor;
const caseZone1Sensor = this.accessory.caseZone1Sensor;
const caseHotWaterSensor = this.accessory.caseHotWaterSensor;
const caseZone2Sensor = this.accessory.caseZone2Sensor;
const supportsOutdoorTemperature = this.accessory.supportsOutdoorTemperature;
//accessory
if (this.logDebug) this.emit('debug', `Prepare accessory`);
const accessoryName = deviceName;
const accessoryUUID = AccessoryUUID.generate(accountName + deviceId.toString());
const accessoryCategory = Categories.AIR_HEATER;
const accessory = new Accessory(accessoryName, accessoryUUID, accessoryCategory);
//information service
if (this.logDebug) this.emit('debug', `Prepare information service`);
this.informationService = accessory.getService(Service.AccessoryInformation)
.setCharacteristic(Characteristic.Manufacturer, this.manufacturer)
.setCharacteristic(Characteristic.Model, this.model)
.setCharacteristic(Characteristic.SerialNumber, this.serialNumber)
.setCharacteristic(Characteristic.FirmwareRevision, this.firmwareRevision)
.setCharacteristic(Characteristic.ConfiguredName, accessoryName);
//services
if (zonesCount > 0) {
this.melCloudServices = [];
this.accessory.zones.forEach((zone, i) => {
const zoneName = zone.name
const serviceName = `${deviceTypeString} ${accessoryName}: ${zoneName}`;
switch (this.displayType) {
case 1: //Heater Cooler
if (this.logDebug) this.emit('debug', `Prepare heater/cooler ${zoneName} service`);
const melCloudService = new Service.HeaterCooler(serviceName, `HeaterCooler ${deviceId} ${i}`);
if (i === caseHeatPump) melCloudService.setPrimaryService(true);
melCloudService.getCharacteristic(Characteristic.Active)
.onGet(async () => {
const state = zone.state;
return state;
})
.onSet(async (state) => {
if (i !== caseHeatPump) return;
// Only heat pump
try {
const payload = { power: state ? true : false };
if (this.logInfo) this.emit('info', `${zoneName}, Set power: ${state ? 'On' : 'Off'}`);
await this.melCloudAtw.send(this.accountType, this.displayType, deviceData, payload);
} catch (error) {
if (this.logWarn) this.emit('warn', `Set power error: ${error}`);
};
});
melCloudService.getCharacteristic(Characteristic.CurrentHeaterCoolerState)
.onGet(async () => {
const value = zone.currentOperationMode;
return value;
});
melCloudService.getCharacteristic(Characteristic.TargetHeaterCoolerState)
.setProps({
minValue: zone.operationModesSetPropsMinValue,
maxValue: zone.operationModesSetPropsMaxValue,
validValues: zone.operationModesSetPropsValidValues
})
.onGet(async () => {
const value = zone.targetOperationMode;
return value;
})
.onSet(async (value) => {
try {
const payload = {};
let operationModeText = '';
let flag = null;
switch (i) {
case caseHeatPump: //Heat Pump - Operation Mode - IDLE, HOT WATER, HEATING, COOLING, HOT WATER STORAGE, FREEZE STAT, LEGIONELLA, HEATING ECO, MODE 1, MODE 2, MODE 3, HEATING UP // Unit Status - HEAT, COOL
switch (value) {
case 0: //AUTO Power OFF
payload.power = false;
break;
case 1: //HEAT
if (accountTypeMelCloud) deviceData.Device.UnitStatus = 0;
payload.power = true;
//payload.operationMode = 2;
break;
case 2: //COOL
if (accountTypeMelCloud) deviceData.Device.UnitStatus = 1;
payload.power = true;
//payload.operationMode = 3;
break;
};
operationModeText = HeatPump.OperationModeHeatPumpMapEnumToStringInfo[value];
break;
case caseZone1: //Zone 1 - HEAT ROOM, HEAT FLOW, HEAT CURVE, COOL ROOM, COOL FLOW, FLOOR DRY UP, IDLE
switch (value) {
case 0: //AUTO - HEAT CURVE / FLOOR DRY UP
payload.operationModeZone1 = [2, 5][zone.operationModeHeatPump];
flag = HeatPump.EffectiveFlags.OperationModeZone1;
break;
case 1: //HEAT - HEAT ROOM / COOL ROOM
payload.operationModeZone1 = [0, 3][zone.operationModeHeatPump];
flag = HeatPump.EffectiveFlags.OperationModeZone1;
break;
case 2: //COOL - HEAT FLOW / COOL FLOW
payload.operationModeZone1 = [1, 4][zone.operationModeHeatPump];
flag = HeatPump.EffectiveFlags.OperationModeZone1;
break;
};
operationModeText = HeatPump.OperationModeZoneMapEnumToStringInfo[payload.operationModeZone1];
break;
case caseHotWater: //Hot Water - AUTO, HEAT NOW
switch (value) {
case 0: //AUTO
//payload.forcedHotWaterMode = false;
//flag = HeatPump.EffectiveFlags.ForcedHotWaterMode;
return;
case 1: //HEAT
payload.forcedHotWaterMode = true;
flag = HeatPump.EffectiveFlags.ForcedHotWaterMode;
break;
case 2: //COOL
//payload.forcedHotWaterMode = false;
//flag = HeatPump.EffectiveFlags.ForcedHotWaterMode;
return
};
operationModeText = HeatPump.ForceDhwMapEnumToStringInfo[payload.forcedHotWaterMode ? 1 : 0];
break;
case caseZone2: //Zone 2 - HEAT ROOM, HEAT FLOW, HEAT CURVE, COOL ROOM, COOL FLOW, FLOOR DRY UP, IDLE
switch (value) {
case 0: //AUTO - HEAT CURVE / FLOOR DRY UP
payload.operationModeZone2 = [2, 5][zone.operationModeHeatPump];
flag = HeatPump.EffectiveFlags.OperationModeZone2;
break;
case 1: //HEAT - HEAT ROOM / COOL ROOM
payload.operationModeZone2 = [0, 3][zone.operationModeHeatPump];
flag = HeatPump.EffectiveFlags.OperationModeZone2;
break;
case 2: //COOL - HEAT FLOW / COOL FLOW
payload.operationModeZone2 = [1, 4][zone.operationModeHeatPump];
flag = HeatPump.EffectiveFlags.OperationModeZone2;
break;
};
operationModeText = HeatPump.OperationModeZoneMapEnumToStringInfo[payload.operationModeZone2];
break;
};
if (this.logInfo) this.emit('info', `${zoneName}, Set operation mode: ${operationModeText}`);
await this.melCloudAtw.send(this.accountType, this.displayType, deviceData, payload, flag);
} catch (error) {
if (this.logWarn) this.emit('warn', `${zoneName}, Set operation mode error: ${error}`);
};
});
melCloudService.getCharacteristic(Characteristic.CurrentTemperature)
.onGet(async () => {
const value = zone.roomTemperature;
return value;
});
//only for heat/cool, only cool and not for hot water tank
if ((heatCoolModes === 0 || heatCoolModes === 2) && i !== caseHotWater) {
melCloudService.getCharacteristic(Characteristic.CoolingThresholdTemperature)
.setProps({
minValue: zone.temperaturesSetPropsMinValue,
maxValue: zone.temperaturesSetPropsMaxValue,
minStep: this.accessory.temperatureIncrement
})
.onGet(async () => {
const value = zone.setTemperature;
return value;
})
.onSet(async (value) => {
try {
const payload = {};
let flag = null;
switch (this.accountType) {
case 'melcloud': //Melcloud
switch (i) {
case caseHeatPump: //Heat Pump
//flag = CONSTANTS.HeatPump.EffectiveFlags.SetTemperatureZone1;
return;
case caseZone1: //Zone 1
switch (zone.operationModeRaw) {
case 1: //HEAT FLOW
payload.setHeatFlowTemperatureZone1 = value;
flag = HeatPump.EffectiveFlags.SetHeatFlowTemperatureZone1;
break;
case 4: //COOL FLOW
payload.setCoolFlowTemperatureZone1 = value;
flag = HeatPump.EffectiveFlags.SetCoolFlowTemperatureZone1;
break;
default:
payload.setTemperatureZone1 = value;
flag = HeatPump.EffectiveFlags.SetTemperatureZone1;
break
};
break;
case caseHotWater: //Hot Water
payload.setTankWaterTemperature = value;
flag = HeatPump.EffectiveFlags.SetTankWaterTemperature;
break;
case caseZone2: //Zone 2
switch (zone.operationModeRaw) {
case 1: //HEAT FLOW
payload.setHeatFlowTemperatureZone2 = value;
flag = HeatPump.EffectiveFlags.SetHeatFlowTemperatureZone2;
break;
case 4: //COOL FLOW
payload.setCoolFlowTemperatureZone2 = value;
flag = HeatPump.EffectiveFlags.SetCoolFlowTemperatureZone2;
break;
default:
payload.setTemperatureZone2 = value;
flag = HeatPump.EffectiveFlags.SetTemperatureZone2;
break
};
break;
};
break;
case 'melcloudhome':
switch (i) {
case caseHeatPump: //Heat Pump
//flag = CONSTANTS.HeatPump.EffectiveFlags.SetTemperatureZone1;
return;
case caseZone1: //Zone 1
payload.setTemperatureZone1 = value;
break;
case caseHotWater: //Hot Water
payload.setTankWaterTemperature = value;
break;
case caseZone2: //Zone 2
payload.setTemperatureZone2 = value;
break;
};
break;
default:
if (this.logWarn) this.emit('warn', `Received unknown account type: ${this.accountType}`);
return;
}
if (this.logInfo) this.emit('info', `${zoneName}, Set cooling threshold temperature: ${value}${this.accessory.temperatureUnit}`);
await this.melCloudAtw.send(this.accountType, this.displayType, deviceData, payload, flag);
} catch (error) {
if (this.logWarn) this.emit('warn', `${zoneName}, Set cooling threshold temperature error: ${error}`);
};
});
};
//device can heat/cool or only heat
if (heatCoolModes === 0 || heatCoolModes === 1) {
melCloudService.getCharacteristic(Characteristic.HeatingThresholdTemperature)
.setProps({
minValue: zone.temperaturesSetPropsMinValue,
maxValue: zone.temperaturesSetPropsMaxValue,
minStep: this.accessory.temperatureIncrement
})
.onGet(async () => {
const value = zone.setTemperature;
return value;
})
.onSet(async (value) => {
try {
const payload = {};
let flag = null;
switch (this.accountType) {
case 'melcloud': //Melcloud
switch (i) {
case caseHeatPump: //Heat Pump
//flag = CONSTANTS.HeatPump.EffectiveFlags.SetTemperatureZone1;
return;
case caseZone1: //Zone 1
switch (zone.operationModeRaw) {
case 1: //HEAT FLOW
payload.setHeatFlowTemperatureZone1 = value;
flag = HeatPump.EffectiveFlags.SetHeatFlowTemperatureZone1;
break;
case 4: //COOL FLOW
payload.setCoolFlowTemperatureZone1 = value;
flag = HeatPump.EffectiveFlags.SetCoolFlowTemperatureZone1;
break;
default:
payload.setTemperatureZone1 = value;
flag = HeatPump.EffectiveFlags.SetTemperatureZone1;
break
};
break;
case caseHotWater: //Hot Water
payload.setTankWaterTemperature = value;
flag = HeatPump.EffectiveFlags.SetTankWaterTemperature;
break;
case caseZone2: //Zone 2
switch (zone.operationModeRaw) {
case 1: //HEAT FLOW
payload.setHeatFlowTemperatureZone2 = value;
flag = HeatPump.EffectiveFlags.SetHeatFlowTemperatureZone2;
break;
case 4: //COOL FLOW
payload.setCoolFlowTemperatureZone2 = value;
flag = HeatPump.EffectiveFlags.SetCoolFlowTemperatureZone2;
break;
default:
payload.setTemperatureZone2 = value;
flag = HeatPump.EffectiveFlags.SetTemperatureZone2;
break
};
break;
};
break;
case 'melcloudhome':
switch (i) {
case caseHeatPump: //Heat Pump
//flag = CONSTANTS.HeatPump.EffectiveFlags.SetTemperatureZone1;
return;
case caseZone1: //Zone 1
payload.setTemperatureZone1 = value;
break;
case caseHotWater: //Hot Water
payload.setTankWaterTemperature = value;
break;
case caseZone2: //Zone 2
payload.setTemperatureZone2 = value;
break;
};
break;
default:
if (this.logWarn) this.emit('warn', `Received unknown account type: ${this.accountType}`);
return;
}
if (this.logInfo) this.emit('info', `${zoneName}, Set heating threshold temperature: ${value}${this.accessory.temperatureUnit}`);
await this.melCloudAtw.send(this.accountType, this.displayType, deviceData, payload, flag);
} catch (error) {
if (this.logWarn) this.emit('warn', `${zoneName}, Set heating threshold temperature error: ${error}`);
};
});
};
melCloudService.getCharacteristic(Characteristic.LockPhysicalControls)
.onGet(async () => {
const value = zone.lockPhysicalControl;
return value;
})
.onSet(async (value) => {
try {
value = value ? true : false;
const payload = {};
let flag = null;
switch (i) {
case caseHeatPump: //Heat Pump
if (accountTypeMelCloud) payload.prohibitZone1 = value;
payload.prohibitHotWater = value;
if (accountTypeMelCloud) payload.prohibitZone2 = value;
flag = HeatPump.EffectiveFlags.ProhibitHeatingZone1 + HeatPump.EffectiveFlags.ProhibitHotWater + HeatPump.EffectiveFlags.ProhibitHeatingZone2;
break;
case caseZone1: //Zone 1
if (!accountTypeMelCloud) return;
payload.prohibitZone1 = value;
flag = HeatPump.EffectiveFlags.ProhibitHeatingZone1;
break;
case caseHotWater: //Hot Water
payload.prohibitHotWater = value;
flag = HeatPump.EffectiveFlags.ProhibitHotWater;
break;
case caseZone2: //Zone 2
if (!accountTypeMelCloud) return;
payload.prohibitZone2 = value;
flag = HeatPump.EffectiveFlags.ProhibitHeatingZone2;
break;
};
if (this.logInfo) this.emit('info', `${zoneName}, Set lock physical controls: ${value ? 'Lock' : 'Unlock'}`);
await this.melCloudAtw.send(this.accountType, this.displayType, deviceData, payload, flag);
} catch (error) {
if (this.logWarn) this.emit('warn', `${zoneName}, Set lock physical controls error: ${error}`);
};
});
melCloudService.getCharacteristic(Characteristic.TemperatureDisplayUnits)
.onGet(async () => {
const value = this.accessory.useFahrenheit;
return value;
})
.onSet(async (value) => {
if (!accountTypeMelCloud) return;
try {
this.accessory.useFahrenheit = value ? true : false;
this.melCloudAccountData.UseFahrenheit = value ? true : false;
this.melCloudAccountData.Account.LoginData.UseFahrenheit = value ? true : false;
const payload = this.melCloudAccountData;
if (this.logInfo) this.emit('info', `Set temperature display unit: ${TemperatureDisplayUnits[value]}`);
await this.melCloudAtw.send(this.accountType, this.displayType, deviceData, payload, 'account');
} catch (error) {
if (this.logWarn) this.emit('warn', `Set temperature display unit error: ${error}`);
};
});
this.melCloudServices.push(melCloudService);
accessory.addService(melCloudService);
break;
case 2: //Thermostat
if (this.logDebug) this.emit('debug', `Prepare thermostat ${zoneName} service`);
const melCloudServiceT = new Service.Thermostat(serviceName, `Thermostat ${deviceId} ${i}`);
if (i === caseHeatPump) melCloudServiceT.setPrimaryService(true);
melCloudServiceT.getCharacteristic(Characteristic.CurrentHeatingCoolingState)
.onGet(async () => {
const value = zone.currentOperationMode;
return value;
});
melCloudServiceT.getCharacteristic(Characteristic.TargetHeatingCoolingState)
.setProps({
minValue: zone.operationModesSetPropsMinValue,
maxValue: zone.operationModesSetPropsMaxValue,
validValues: zone.operationModesSetPropsValidValues
})
.onGet(async () => {
const value = zone.targetOperationMode;
return value;
})
.onSet(async (value) => {
try {
let operationModeText = '';
const payload = {};
let flag = null;
switch (i) {
case caseHeatPump: //Heat Pump - Operation Mode - IDLE, HOT WATER, HEATING, COOLING, HOT WATER STORAGE, FREEZE STAT, LEGIONELLA, HEATING ECO, MODE 1, MODE 2, MODE 3, HEATING UP // Unit Status - HEAT, COOL
switch (value) {
case 0: //OFF
payload.power = false;
break;
case 1: //HEAT
if (accountTypeMelCloud) deviceData.Device.UnitStatus = 0;
payload.power = true;
//payload.operationMode = 2;
break;
case 2: //COOL
if (accountTypeMelCloud) deviceData.Device.UnitStatus = 1;
payload.power = true;
//payload.operationMode = 3;
break;
case 3: //AUTO - not used
return;
};
operationModeText = HeatPump.OperationModeHeatPumpMapEnumToStringInfo[value];
break;
case caseZone1: //Zone 1 - HEAT ROOM, HEAT FLOW, HEAT CURVE, COOL ROOM, COOL FLOW, FLOOR DRY UP, IDLE
switch (value) {
case 0: //OFF
//payload.operationModeZone1 = 2;
//flag = HeatPump.EffectiveFlags.OperationModeZone1;
return;
case 1: //HEAT - HEAT ROOM / COOL ROOM
payload.operationModeZone1 = [0, 3][zone.operationModeHeatPump];
flag = HeatPump.EffectiveFlags.OperationModeZone1;
break;
case 2: //COOL - HEAT FLOW / COOL FLOW
payload.operationModeZone1 = [1, 4][zone.operationModeHeatPump];