iobroker.melcloud
Version:
998 lines (933 loc) • 31.4 kB
JavaScript
"use strict";
const commonDefines = require("./commonDefines");
const HttpStatus = require("http-status-codes");
const MelcloudBaseDevice = require("./melcloudBaseDevice");
const Axios = require("axios").default;
class MelcloudAtaDevice extends MelcloudBaseDevice {
constructor(adapter, platform) {
super(adapter, platform, commonDefines.DeviceTypes.AirToAir);
// Info
this.canDry = false;
this.minTempCoolDry = 0;
this.maxTempCoolDry = 0;
this.minTempHeat = 0;
this.maxTempHeat = 0;
this.minTempAuto = 0;
this.maxTempAuto = 0;
this.roomTemp = 0;
this.actualFanSpeed = 0;
this.numberOfFanSpeeds = 0;
// Control
this.operationMode = commonDefines.AtaDeviceOperationModes.UNDEF.value;
this.targetTemp = 0;
this.fanSpeed = 0;
this.vaneVerticalDirection = 0;
this.vaneHorizontalDirection = 0;
// Reports
this.totalPowerConsumptionAuto = 0;
this.totalPowerConsumptionDry = 0;
this.totalPowerConsumptionVent = 0;
}
// Creates all necessary states and channels and writes the values into the DB
async CreateAndSave() {
// check if object has already been created
if (this.hasBeenCreated) {
return;
}
await super.createCommonStates();
const devicePrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}`;
//#region INFO
const infoPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Info}`;
await this.createStates(infoPrefix, [
{
id: commonDefines.AtaDeviceStateIDs.CanDry,
definition: {
type: "state",
common: {
name: "Ability to dry",
type: "boolean",
role: "value",
read: true,
write: false,
def: this.canDry,
desc: "Ability to dry",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.MinTempCoolDry,
definition: {
type: "state",
common: {
name: "Minimal temperature (Cool/Dry)",
type: "number",
role: "value.temperature",
unit: this.platform.UseFahrenheit ? "°F" : "°C",
read: true,
write: false,
def: this.minTempCoolDry,
desc: "Minimal temperature in cool/dry-mode",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.MaxTempCoolDry,
definition: {
type: "state",
common: {
name: "Maximal temperature (Cool/Dry)",
type: "number",
role: "value.temperature",
unit: this.platform.UseFahrenheit ? "°F" : "°C",
read: true,
write: false,
def: this.maxTempCoolDry,
desc: "Maximal temperature in cool/dry-mode",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.MinTempAuto,
definition: {
type: "state",
common: {
name: "Minimal Temperature (Auto)",
type: "number",
role: "value.temperature",
unit: this.platform.UseFahrenheit ? "°F" : "°C",
read: true,
write: false,
def: this.minTempAuto,
desc: "Minimal temperature in auto-mode",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.MaxTempAuto,
definition: {
type: "state",
common: {
name: "Maximal Temperature (Auto)",
type: "number",
role: "value.temperature",
unit: this.platform.UseFahrenheit ? "°F" : "°C",
read: true,
write: false,
def: this.maxTempAuto,
desc: "Maximal temperature in auto-mode",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.RoomTemp,
definition: {
type: "state",
common: {
name: "Room temperature",
type: "number",
role: "value.temperature",
unit: this.platform.UseFahrenheit ? "°F" : "°C",
read: true,
write: false,
def: this.roomTemp,
desc: "Maximal temperature in auto-mode",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.FanSpeedAuto,
definition: {
type: "state",
common: {
name: "Fan speed (while in auto mode)",
type: "number",
role: "value",
read: true,
write: false,
def: this.actualFanSpeed,
desc: "Actual fan speed when fan is set to auto mode",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.NumberOfFanSpeeds,
definition: {
type: "state",
common: {
name: "Number of fan speeds",
type: "number",
role: "value",
read: true,
write: false,
def: this.numberOfFanSpeeds,
desc: "Number of available fan speeds",
},
native: {},
},
},
]);
if (this.canHeat) {
await this.createStates(infoPrefix, [
{
id: commonDefines.AtaDeviceStateIDs.MinTempHeat,
definition: {
type: "state",
common: {
name: "Minimal temperature (Heat)",
type: "number",
role: "value.temperature",
unit: this.platform.UseFahrenheit ? "°F" : "°C",
read: true,
write: false,
def: this.minTempHeat,
desc: "Minimal temperature in heat-mode",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.MaxTempHeat,
definition: {
type: "state",
common: {
name: "Maximal temperature (Heat)",
type: "number",
role: "value.temperature",
unit: this.platform.UseFahrenheit ? "°F" : "°C",
read: true,
write: false,
def: this.maxTempHeat,
desc: "Maximal temperature in heat-mode",
},
native: {},
},
},
]);
}
//#endregion
//#region CONTROL
const controlPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Control}`;
const minTemp = Math.min(this.minTempAuto, this.minTempCoolDry, this.minTempHeat);
const maxTemp = Math.max(this.maxTempAuto, this.maxTempCoolDry, this.maxTempHeat);
await this.createStates(controlPrefix, [
{
id: commonDefines.AtaDeviceStateIDs.Power,
definition: {
type: "state",
common: {
name: "Power",
type: "boolean",
role: "switch.power",
read: true,
write: true,
def: this.power,
desc: "Power switch",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.Mode,
definition: {
type: "state",
common: {
name: "Operation mode",
type: "number",
role: "value",
read: true,
write: true,
def: this.operationMode,
desc: "Operation mode of the device",
states: {
1: "HEAT",
2: "DRY",
3: "COOL",
7: "VENT",
8: "AUTO",
},
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.TargetTemp,
definition: {
type: "state",
common: {
name: "Target temperature",
type: "number",
role: "level.temperature",
unit: this.platform.UseFahrenheit ? "°F" : "°C",
min: minTemp,
max: maxTemp,
step: 0.5,
read: true,
write: true,
def: this.targetTemp,
desc: "Target temperature of the device",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.FanSpeedManual,
definition: {
type: "state",
common: {
name: "Fan speed (while in manual mode)",
type: "number",
role: "value",
min: 0,
max: 5,
states: {
0: "AUTO",
1: "LOWEST",
2: "LOW",
3: "MEDIUM",
4: "HIGH",
5: "MAX",
},
read: true,
write: true,
def: this.fanSpeed,
desc: "Current fan speed of the device (while in manual mode)",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.VaneVerticalDirection,
definition: {
type: "state",
common: {
name: "Vane vertical direction",
type: "number",
role: "value",
min: 0,
max: 7,
states: {
0: "AUTO",
1: "TOPMOST",
2: "UP",
3: "MIDDLE",
4: "DOWN",
5: "BOTTOMMOST",
7: "SWING",
},
read: true,
write: true,
def: this.vaneVerticalDirection,
desc: "Current vertical direction of the device's vane",
},
native: {},
},
},
{
id: commonDefines.AtaDeviceStateIDs.VaneHorizontalDirection,
definition: {
type: "state",
common: {
name: "Vane horizontal direction",
type: "number",
role: "value",
min: 0,
max: 12,
states: {
0: "AUTO",
1: "LEFTMOST",
2: "LEFT",
3: "MIDDLE",
4: "RIGHT",
5: "RIGHTMOST",
8: "50/50",
12: "SWING",
},
read: true,
write: true,
def: this.vaneHorizontalDirection,
desc: "Current horizontal direction of the device's vane",
},
native: {},
},
},
]);
//#endregion
//#region REPORTS
const lastReportDataPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Reports}.${commonDefines.AdapterDatapointIDs.LastReportData}`;
const reportModes = [
commonDefines.AtaDeviceOperationModes.HEAT.id,
commonDefines.AtaDeviceOperationModes.COOL.id,
commonDefines.AtaDeviceOperationModes.AUTO.id,
commonDefines.AtaDeviceOperationModes.VENT.id,
commonDefines.AtaDeviceOperationModes.DRY.id,
];
reportModes.forEach(mode => async () => {
if (
(mode == commonDefines.AtaDeviceOperationModes.HEAT.id && !this.canHeat) ||
(mode == commonDefines.AtaDeviceOperationModes.DRY.id && !this.canDry) ||
(mode == commonDefines.AtaDeviceOperationModes.COOL.id && !this.canCool)
) {
return;
}
await this.createStates(lastReportDataPrefix, [
{
id: lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix + mode,
definition: {
type: "state",
common: {
name: `Total power consumption for mode '${mode}'`,
type: "number",
role: "value.power.consumption",
min: 0,
read: true,
write: false,
unit: "kWh",
def: 0,
desc: `Total power consumption for mode '${mode}'`,
},
native: {},
},
},
]);
});
//#endregion
this.adapter.log.debug(`Created and saved ATA device ${this.id} (${this.name})`);
this.hasBeenCreated = true;
}
// Only writes changed device data into the DB
async UpdateDeviceData(deviceOption) {
super.UpdateCommonDeviceData();
//#region INFO
const infoPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Info}.`;
await this.adapter.setStateChangedAsync(infoPrefix + commonDefines.AtaDeviceStateIDs.CanDry, this.canDry, true);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.AtaDeviceStateIDs.MinTempCoolDry,
this.minTempCoolDry,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.AtaDeviceStateIDs.MaxTempCoolDry,
this.maxTempCoolDry,
true,
);
if (this.canHeat) {
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.AtaDeviceStateIDs.MinTempHeat,
this.minTempHeat,
true,
);
}
if (this.canHeat) {
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.AtaDeviceStateIDs.MaxTempHeat,
this.maxTempHeat,
true,
);
}
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.AtaDeviceStateIDs.MinTempAuto,
this.minTempAuto,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.AtaDeviceStateIDs.MaxTempAuto,
this.maxTempAuto,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.AtaDeviceStateIDs.RoomTemp,
this.roomTemp,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.AtaDeviceStateIDs.FanSpeedAuto,
this.actualFanSpeed,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.AtaDeviceStateIDs.NumberOfFanSpeeds,
this.numberOfFanSpeeds,
true,
);
//#endregion
//#region CONTROL
const controlPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Control}.`;
switch (deviceOption) {
case commonDefines.AtaDeviceOptions.PowerState:
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.Power,
this.power,
true,
);
break;
case commonDefines.AtaDeviceOptions.TargetHeatingCoolingState:
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.Mode,
this.operationMode,
true,
);
break;
case commonDefines.AtaDeviceOptions.TargetTemperature:
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.TargetTemp,
this.targetTemp,
true,
);
break;
case commonDefines.AtaDeviceOptions.FanSpeed:
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.FanSpeedManual,
this.fanSpeed,
true,
);
break;
case commonDefines.AtaDeviceOptions.VaneHorizontalDirection:
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.VaneHorizontalDirection,
this.vaneHorizontalDirection,
true,
);
break;
case commonDefines.AtaDeviceOptions.VaneVerticalDirection:
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.VaneVerticalDirection,
this.vaneVerticalDirection,
true,
);
break;
case "ALL":
default:
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.Power,
this.power,
true,
);
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.Mode,
this.operationMode,
true,
);
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.TargetTemp,
this.targetTemp,
true,
);
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.FanSpeedManual,
this.fanSpeed,
true,
);
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.VaneHorizontalDirection,
this.vaneHorizontalDirection,
true,
);
await this.adapter.setStateChangedAsync(
controlPrefix + commonDefines.AtaDeviceStateIDs.VaneVerticalDirection,
this.vaneVerticalDirection,
true,
);
break;
}
//#endregion
this.adapter.log.debug(`Updated device data for ATA device ${this.id} (${this.name})`);
}
// Only writes changed report data into the DB
async UpdateReportData() {
await super.UpdateCommonReportData();
const lastReportDataPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Reports}.${commonDefines.AdapterDatapointIDs.LastReportData}.`;
let totalConsumption = 0;
if (this.canCool) {
await this.adapter.setStateChangedAsync(
lastReportDataPrefix +
commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix +
commonDefines.AtaDeviceOperationModes.COOL.id,
commonDefines.roundValue(this.totalPowerConsumptionCooling, 3),
true,
);
totalConsumption += this.totalPowerConsumptionCooling;
}
if (this.canHeat) {
await this.adapter.setStateChangedAsync(
lastReportDataPrefix +
commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix +
commonDefines.AtaDeviceOperationModes.HEAT.id,
commonDefines.roundValue(this.totalPowerConsumptionHeating, 3),
true,
);
totalConsumption += this.totalPowerConsumptionHeating;
}
await this.adapter.setStateChangedAsync(
lastReportDataPrefix +
commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix +
commonDefines.AtaDeviceOperationModes.AUTO.id,
commonDefines.roundValue(this.totalPowerConsumptionAuto, 3),
true,
);
totalConsumption += this.totalPowerConsumptionAuto;
if (this.canDry) {
await this.adapter.setStateChangedAsync(
lastReportDataPrefix +
commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix +
commonDefines.AtaDeviceOperationModes.DRY.id,
commonDefines.roundValue(this.totalPowerConsumptionDry, 3),
true,
);
totalConsumption += this.totalPowerConsumptionDry;
}
await this.adapter.setStateChangedAsync(
lastReportDataPrefix +
commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix +
commonDefines.AtaDeviceOperationModes.VENT.id,
commonDefines.roundValue(this.totalPowerConsumptionVent, 3),
true,
);
totalConsumption += this.totalPowerConsumptionVent;
await this.adapter.setStateChangedAsync(
lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix,
commonDefines.roundValue(totalConsumption, 3),
true,
);
this.adapter.log.debug(`Updated report data for device ${this.id} (${this.name})`);
}
setDevice(deviceOption, value) {
if (this.currentDeviceSetRequests < 1) {
this.currentDeviceSetRequests++;
this.adapter.log.debug(
`Changing device option '${deviceOption.id}' to '${value.value != undefined ? value.value : value}'...`,
);
const modifiedAirInfo = this.airInfo;
if (modifiedAirInfo == null) {
this.adapter.log.error(
`setDevice(): modifiedAirInfo is not filled - please report this to the developer!`,
);
return;
}
value = this.verifyDeviceOptionValue(deviceOption, value);
if (deviceOption == commonDefines.AtaDeviceOptions.PowerState) {
switch (value) {
case commonDefines.DevicePowerStates.OFF:
modifiedAirInfo.Power = commonDefines.DevicePowerStates.OFF.value;
modifiedAirInfo.EffectiveFlags = commonDefines.DevicePowerStates.OFF.effectiveFlags;
break;
case commonDefines.DevicePowerStates.ON:
modifiedAirInfo.Power = commonDefines.DevicePowerStates.ON.value;
modifiedAirInfo.EffectiveFlags = commonDefines.DevicePowerStates.ON.effectiveFlags;
break;
default:
this.adapter.log.error(
"setDevice(): Unsupported value for device option - please report this to the developer!",
);
this.currentDeviceSetRequests--;
return;
}
} else if (deviceOption == commonDefines.AtaDeviceOptions.TargetHeatingCoolingState) {
switch (value) {
case commonDefines.AtaDeviceOperationModes.HEAT:
modifiedAirInfo.OperationMode = commonDefines.AtaDeviceOperationModes.HEAT.value;
modifiedAirInfo.EffectiveFlags = commonDefines.AtaDeviceOperationModes.HEAT.effectiveFlags;
break;
case commonDefines.AtaDeviceOperationModes.DRY:
modifiedAirInfo.OperationMode = commonDefines.AtaDeviceOperationModes.DRY.value;
modifiedAirInfo.EffectiveFlags = commonDefines.AtaDeviceOperationModes.DRY.effectiveFlags;
break;
case commonDefines.AtaDeviceOperationModes.COOL:
modifiedAirInfo.OperationMode = commonDefines.AtaDeviceOperationModes.COOL.value;
modifiedAirInfo.EffectiveFlags = commonDefines.AtaDeviceOperationModes.COOL.effectiveFlags;
break;
case commonDefines.AtaDeviceOperationModes.VENT:
modifiedAirInfo.OperationMode = commonDefines.AtaDeviceOperationModes.VENT.value;
modifiedAirInfo.EffectiveFlags = commonDefines.AtaDeviceOperationModes.VENT.effectiveFlags;
break;
case commonDefines.AtaDeviceOperationModes.AUTO:
modifiedAirInfo.OperationMode = commonDefines.AtaDeviceOperationModes.AUTO.value;
modifiedAirInfo.EffectiveFlags = commonDefines.AtaDeviceOperationModes.AUTO.effectiveFlags;
break;
default:
this.adapter.log.error(
"setDevice(): Unsupported value for device option - please report this to the developer!",
);
this.currentDeviceSetRequests--;
return;
}
} else if (deviceOption == commonDefines.AtaDeviceOptions.TargetTemperature) {
modifiedAirInfo.SetTemperature = value;
modifiedAirInfo.EffectiveFlags = commonDefines.AtaDeviceOptions.TargetTemperature.effectiveFlags;
} else if (deviceOption == commonDefines.AtaDeviceOptions.FanSpeed) {
modifiedAirInfo.SetFanSpeed = value;
modifiedAirInfo.EffectiveFlags = commonDefines.AtaDeviceOptions.FanSpeed.effectiveFlags;
} else if (deviceOption == commonDefines.AtaDeviceOptions.VaneHorizontalDirection) {
modifiedAirInfo.VaneHorizontal = value;
modifiedAirInfo.EffectiveFlags = commonDefines.AtaDeviceOptions.VaneHorizontalDirection.effectiveFlags;
} else if (deviceOption == commonDefines.AtaDeviceOptions.VaneVerticalDirection) {
modifiedAirInfo.VaneVertical = value;
modifiedAirInfo.EffectiveFlags = commonDefines.AtaDeviceOptions.VaneVerticalDirection.effectiveFlags;
} else {
this.adapter.log.error("setDevice(): Unsupported device option - please report this to the developer!");
this.currentDeviceSetRequests--;
return;
}
modifiedAirInfo.HasPendingCommand = true;
const url = "https://app.melcloud.com/Mitsubishi.Wifi.Client/Device/SetAta";
const body = JSON.stringify(modifiedAirInfo);
this.adapter.log.silly(`Request body: ${body}`);
Axios.post(url, body, {
httpsAgent: this.platform.customHttpsAgent,
headers: {
Host: "app.melcloud.com",
"X-MitsContextKey": this.platform.contextKey,
"Content-Type": "application/json; charset=utf-8",
},
})
.then(response => {
if (!response) {
this.adapter.log.error(`There was a problem receiving the response from: ${url}`);
this.airInfo = null;
this.currentDeviceSetRequests--;
return;
}
const statusCode = response.status;
const statusText = response.statusText;
this.adapter.log.debug(
`Received response from: ${url} (status code: ${statusCode} - ${statusText})`,
);
if (statusCode != HttpStatus.StatusCodes.OK) {
this.airInfo = null;
this.adapter.log.error(
`Invalid HTTP status code (${statusCode} - ${statusText}). Changing device option failed!`,
);
this.currentDeviceSetRequests--;
return;
}
const responseData = response.data;
this.adapter.log.debug(`Response from cloud: ${JSON.stringify(responseData)}`);
this.lastCommunication = responseData.LastCommunication;
this.nextCommunication = responseData.NextCommunication;
this.roomTemp = responseData.RoomTemperature;
this.deviceOnline = !responseData.Offline;
this.errorCode = responseData.ErrorCode;
this.errorMessages = responseData.ErrorMessage;
switch (deviceOption) {
case commonDefines.AtaDeviceOptions.PowerState:
this.power = responseData.Power;
break;
case commonDefines.AtaDeviceOptions.TargetHeatingCoolingState:
this.operationMode = responseData.OperationMode;
break;
case commonDefines.AtaDeviceOptions.TargetTemperature:
this.targetTemp = responseData.SetTemperature;
break;
case commonDefines.AtaDeviceOptions.FanSpeed:
this.fanSpeed = responseData.SetFanSpeed;
break;
case commonDefines.AtaDeviceOptions.VaneHorizontalDirection:
this.vaneHorizontalDirection = responseData.VaneHorizontal;
break;
case commonDefines.AtaDeviceOptions.VaneVerticalDirection:
this.vaneVerticalDirection = responseData.VaneVertical;
break;
default:
break;
}
this.UpdateDeviceData(deviceOption); // write updated values
this.currentDeviceSetRequests--;
if (this.deviceSetRequestQueue.length) {
const args = this.deviceSetRequestQueue.shift();
this.adapter.log.debug(
`Dequeueing setDevice remote request for device option '${args[0].id}' with value '${args[1].value != undefined ? args[1].value : args[1]}'`,
);
this.setDevice.apply(this, args);
}
})
.catch(error => {
this.adapter.log.error(`There was a problem setting info to: ${url}`);
this.adapter.log.error(error);
this.currentDeviceSetRequests--;
if (error.response && error.response.status && error.response.status == 429) {
this.adapter.log.error(
"You have probably been rate limited by the MELCloud servers because of too much requests. Stop the adapter for a few hours, increase the polling interval in the settings and try again later.",
);
}
if (this.deviceSetRequestQueue.length) {
const args = this.deviceSetRequestQueue.shift();
this.adapter.log.debug(
`Dequeueing setDevice remote request for device option '${args[0].id}' with value '${args[1].value != undefined ? args[1].value : args[1]}'`,
);
this.setDevice.apply(this, args);
}
});
} else {
this.adapter.log.debug(
`Queueing setDevice remote request for '${deviceOption.id}' with value '${value.value != undefined ? value.value : value}'...`,
);
this.deviceSetRequestQueue.push(arguments);
}
}
verifyDeviceOptionValue(deviceOption, value) {
switch (deviceOption) {
case commonDefines.AtaDeviceOptions.FanSpeed:
if (value > this.numberOfFanSpeeds) {
this.adapter.log.warn(
`Fan speed limited to ${this.numberOfFanSpeeds} because device can't handle more than that!`,
);
return this.numberOfFanSpeeds;
}
return value;
case commonDefines.AtaDeviceOptions.TargetTemperature:
// eslint-disable-next-line no-case-declarations
let min, max;
switch (this.operationMode) {
case commonDefines.AtaDeviceOperationModes.COOL.value:
case commonDefines.AtaDeviceOperationModes.DRY.value:
min = this.minTempCoolDry;
max = this.maxTempCoolDry;
break;
case commonDefines.AtaDeviceOperationModes.HEAT.value:
min = this.minTempHeat;
max = this.maxTempHeat;
break;
case commonDefines.AtaDeviceOperationModes.AUTO.value:
min = this.minTempAuto;
max = this.maxTempAuto;
break;
default:
min = this.platform.UseFahrenheit ? 60 : 16;
max = this.platform.UseFahrenheit ? 104 : 40;
break;
}
if (value < min) {
value = min;
this.adapter.log.warn(
`SetTemperature limited to ${min} because device can't handle lower than that!`,
);
} else if (value > max) {
value = max;
this.adapter.log.warn(
`SetTemperature limited to ${max} because device can't handle more than that!`,
);
}
return value;
case commonDefines.AtaDeviceOptions.VaneHorizontalDirection:
if (value < 0 || (value > 5 && value != 8 && value != 12)) {
this.adapter.log.warn(
`VaneHorizontalDirection: unsupported value '${value}' - falling back to '0'!`,
);
value = 0;
}
return value;
case commonDefines.AtaDeviceOptions.VaneVerticalDirection:
if (value < 0 || (value > 5 && value != 7)) {
this.adapter.log.warn(`VaneVerticalDirection: unsupported value '${value}' - falling back to '0'!`);
value = 0;
}
return value;
case commonDefines.AtaDeviceOptions.TargetHeatingCoolingState:
if (value == commonDefines.AtaDeviceOperationModes.COOL.value && !this.canCool) {
this.adapter.log.warn(
`TargetHeatingCoolingState: unsupported value '${value}'. Device can not cool!`,
);
} else if (value == commonDefines.AtaDeviceOperationModes.DRY.value && !this.canDry) {
this.adapter.log.warn(
`TargetHeatingCoolingState: unsupported value '${value}'. Device can not dry!`,
);
} else if (value == commonDefines.AtaDeviceOperationModes.HEAT.value && !this.canHeat) {
this.adapter.log.warn(
`TargetHeatingCoolingState: unsupported value '${value}'. Device can not heat!`,
);
}
return value; // don't modify the value as the correct value cant't be known here
default:
return value;
}
}
async getPowerConsumptionReport(isCumulatedReport = false) {
return new Promise((resolve, reject) => {
this.adapter.log.debug(`Getting power consumption report for ${this.id} (${this.name})`);
const url = "https://app.melcloud.com/Mitsubishi.Wifi.Client/EnergyCost/Report";
this.buildPowerConsumptionReportRequestBody(isCumulatedReport)
.then(requestBody => {
const body = JSON.stringify(requestBody);
this.adapter.log.silly(`Request body: ${body}`);
if (body == "{}") {
return; // creating body failed or was provided dates were invalid
}
Axios.post(url, body, {
httpsAgent: this.platform.customHttpsAgent,
headers: {
Host: "app.melcloud.com",
"X-MitsContextKey": this.platform.contextKey,
"Content-Type": "application/json; charset=utf-8",
},
})
.then(response => {
if (!response) {
this.adapter.log.error(`There was a problem receiving the response from: ${url}`);
reject();
} else {
const statusCode = response.status;
const statusText = response.statusText;
this.adapter.log.debug(
`Received response from: ${url} (status code: ${statusCode} - ${statusText})`,
);
if (statusCode != HttpStatus.StatusCodes.OK) {
this.adapter.log.error(
`Invalid HTTP status code (${statusCode} - ${statusText}). Getting power consumption report failed!`,
);
reject();
return;
}
const responseData = response.data;
this.adapter.log.debug(`Response from cloud: ${JSON.stringify(responseData)}`);
// only save date portion of timestamp without the empty time
let timestampPos = responseData.FromDate.indexOf("T");
if (timestampPos != -1) {
this.powerConsumptionReportStartDate = responseData.FromDate.substring(
0,
timestampPos,
);
} else {
this.powerConsumptionReportStartDate = responseData.FromDate;
}
timestampPos = responseData.ToDate.indexOf("T");
if (timestampPos != -1) {
this.powerConsumptionReportEndDate = responseData.ToDate.substring(0, timestampPos);
} else {
this.powerConsumptionReportEndDate = responseData.ToDate;
}
// round all consumption values to 3 digits
this.totalPowerConsumptionCooling = responseData.TotalCoolingConsumed;
this.totalPowerConsumptionHeating = responseData.TotalHeatingConsumed;
this.totalPowerConsumptionAuto = responseData.TotalAutoConsumed;
this.totalPowerConsumptionDry = responseData.TotalDryConsumed;
this.totalPowerConsumptionVent = responseData.TotalFanConsumed;
this.totalPowerConsumptionMinutes = responseData.TotalMinutes;
this.rawPowerConsumptionReportData = responseData;
this.linkedDevicesIncludedInArregateEnergyReport =
responseData.LinkedDevicesIncludedInArregateEnergyReport;
this.UpdateReportData();
resolve();
}
})
.catch(error => {
this.adapter.log.error(`There was a problem getting power consumption report from: ${url}`);
this.adapter.log.error(`Error: ${error}`);
if (error.response && error.response.status && error.response.status == 429) {
this.adapter.log.error(
"You have probably been rate limited by the MELCloud servers because of too much requests. Stop the adapter for a few hours, increase the polling interval in the settings and try again later.",
);
}
reject();
});
})
.catch(reject);
});
}
}
exports.MelCloudDevice = MelcloudAtaDevice;