UNPKG

iobroker.melcloud

Version:
1,401 lines (1,323 loc) 44 kB
"use strict"; const commonDefines = require("./commonDefines"); const HttpStatus = require("http-status-codes"); const MelcloudBaseDevice = require("./melcloudBaseDevice"); const Axios = require("axios").default; class MelcloudAtwDevice extends MelcloudBaseDevice { constructor(adapter, platform) { super(adapter, platform, commonDefines.DeviceTypes.AirToWater); // Info this.hasZone2 = false; this.roomTemperatureZone1 = -1; this.roomTemperatureZone2 = -1; this.mixingTankWaterTemperature = -1; this.condensingTemperature = -1; this.outdoorTemperature = -1; this.flowTemperature = -1; this.flowTemperatureZone1 = -1; this.flowTemperatureZone2 = -1; this.flowTemperatureBoiler = -1; this.returnTemperature = -1; this.returnTemperatureZone1 = -1; this.ReturnTemperatureZone2 = -1; this.returnTemperatureBoiler = -1; this.tankWaterTemperature = -1; this.heatPumpFrequency = -1; this.operationState = -1; // Control this.forcedHotWaterMode = commonDefines.AtwDeviceOperationModes.UNDEF.value; this.operationModeZone1 = commonDefines.AtwDeviceZoneOperationModes.UNDEF.value; this.operationModeZone2 = commonDefines.AtwDeviceZoneOperationModes.UNDEF.value; this.setTankWaterTemperature = -1; this.setTemperatureZone1 = -1; this.setTemperatureZone2 = -1; this.setHeatFlowTemperatureZone1 = -1; this.setHeatFlowTemperatureZone2 = -1; this.setCoolFlowTemperatureZone1 = -1; this.setCoolFlowTemperatureZone2 = -1; // Reports this.totalPowerConsumptionHotWater = 0; this.totalPowerProductionCooling = 0; this.totalPowerProductionHeating = 0; this.totalPowerProductionHotWater = 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.AtwDeviceStateIDs.HasZone2, definition: { type: "state", common: { name: "Has Zone 2", type: "boolean", role: "value", read: true, write: false, def: this.hasZone2, desc: "Has Zone 2?", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.RoomTemperatureZone1, definition: { type: "state", common: { name: "Room temperature zone 1", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.roomTemperatureZone1, desc: "Room temperature in zone 1", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.MixingTankWaterTemperature, definition: { type: "state", common: { name: "Mixing tank temperature", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.mixingTankWaterTemperature, desc: "Mixing tank temperature", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.CondensingTemperature, definition: { type: "state", common: { name: "Condensing temperature", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.condensingTemperature, desc: "Condensing temperature", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.OutdoorTemperature, definition: { type: "state", common: { name: "Outdoor temperature", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.outdoorTemperature, desc: "Outdoor temperature", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.FlowTemperature, definition: { type: "state", common: { name: "Flow temperature", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.flowTemperature, desc: "Flow temperature", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.FlowTemperatureZone1, definition: { type: "state", common: { name: "Flow temperature zone 1", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.flowTemperatureZone1, desc: "Flow temperaturein zone 1", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.FlowTemperatureBoiler, definition: { type: "state", common: { name: "Flow temperature boiler", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.flowTemperatureBoiler, desc: "Flow temperature boiler", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.ReturnTemperature, definition: { type: "state", common: { name: "Return temperature", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.returnTemperature, desc: "Return temperature", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.ReturnTemperatureZone1, definition: { type: "state", common: { name: "Return temperature zone 1", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.returnTemperatureZone1, desc: "Return temperature in zone 1", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.ReturnTemperatureBoiler, definition: { type: "state", common: { name: "Return temperature boiler", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.returnTemperatureBoiler, desc: "Return temperature boiler", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.TankWaterTemperature, definition: { type: "state", common: { name: "Tank water temperature", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.tankWaterTemperature, desc: "Tank water temperature", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.HeatPumpFrequency, definition: { type: "state", common: { name: "Heat pump frequency", type: "number", role: "value", unit: "Hz", read: true, write: false, def: this.heatPumpFrequency, desc: "Heat pump frequency", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.OperationState, definition: { type: "state", common: { name: "Heat pump operation state", type: "number", role: "value", read: true, write: false, def: this.operationState, states: { 0: "Idle", 1: "Heating Water", 2: "Heating Zone", 3: "Cooling", 4: "Defrost", 5: "Standby", 6: "Legionella", }, desc: "Heat pump operation state", }, native: {}, }, }, ]); if (this.hasZone2) { await this.createStates(infoPrefix, [ { id: commonDefines.AtwDeviceStateIDs.RoomTemperatureZone2, definition: { type: "state", common: { name: "Room temperature zone 2", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.roomTemperatureZone2, desc: "Room temperature in zone 2", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.FlowTemperatureZone2, definition: { type: "state", common: { name: "Flow temperature zone 1", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.flowTemperatureZone2, desc: "Flow temperaturein zone 2", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.ReturnTemperatureZone2, definition: { type: "state", common: { name: "Return temperature zone 2", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: false, def: this.ReturnTemperatureZone2, desc: "Return temperature in zone 2", }, native: {}, }, }, ]); } //#endregion //#region CONTROL const controlPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Control}`; await this.createStates(controlPrefix, [ { id: commonDefines.AtwDeviceStateIDs.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.AtwDeviceStateIDs.ForcedHotWaterMode, definition: { type: "state", common: { name: "Forced hot water mode", type: "boolean", role: "value", read: true, write: true, def: this.forcedHotWaterMode, desc: "Forced hot water mode", states: { false: "AUTO", true: "FORCEDHOTWATERMODE", }, }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.OperationModeZone1, definition: { type: "state", common: { name: "Operation mode zone 1", type: "number", role: "value", read: true, write: true, def: this.operationModeZone1, min: this.canHeat ? 0 : 3, max: this.canCool ? 4 : 2, desc: "Operation mode zone 1", states: { 0: "HEATTHERMOSTAT", 1: "HEATFLOW", 2: "CURVE", 3: "COOLTHERMOSTAT", 4: "COOLFLOW", }, }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.SetTankWaterTemperature, definition: { type: "state", common: { name: "Set tank water temperature", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: true, def: this.setTankWaterTemperature, desc: "Set tank water temperature", }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.SetTemperatureZone1, definition: { type: "state", common: { name: "Set temperature zone 1", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: true, def: this.setTemperatureZone1, desc: "Set temperature for zone 1", }, native: {}, }, }, ]); if (this.hasZone2) { await this.createStates(controlPrefix, [ { id: commonDefines.AtwDeviceStateIDs.OperationModeZone2, definition: { type: "state", common: { name: "Operation mode zone 2", type: "number", role: "value", read: true, write: true, def: this.operationModeZone2, min: this.canHeat ? 0 : 3, max: this.canCool ? 4 : 2, desc: "Operation mode zone 2", states: { 0: "HEATTHERMOSTAT", 1: "HEATFLOW", 2: "CURVE", 3: "COOLTHERMOSTAT", 4: "COOLFLOW", }, }, native: {}, }, }, { id: commonDefines.AtwDeviceStateIDs.SetTemperatureZone2, definition: { type: "state", common: { name: "Set temperature zone 2", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: true, def: this.setTemperatureZone2, desc: "Set temperature for zone 2", }, native: {}, }, }, ]); if (this.canHeat) { await this.createStates(controlPrefix, [ { id: commonDefines.AtwDeviceStateIDs.SetHeatFlowTemperatureZone1, definition: { type: "state", common: { name: "Set heat flow temperature zone 1", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: true, def: this.setHeatFlowTemperatureZone1, desc: "Set heat flow temperature for zone 1", }, native: {}, }, }, ]); if (this.hasZone2) { await this.createStates(controlPrefix, [ { id: commonDefines.AtwDeviceStateIDs.SetHeatFlowTemperatureZone2, definition: { type: "state", common: { name: "Set heat flow temperature zone 2", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: true, def: this.setHeatFlowTemperatureZone2, desc: "Set heat flow temperature for zone 2", }, native: {}, }, }, ]); } } if (this.canCool) { await this.createStates(controlPrefix, [ { id: commonDefines.AtwDeviceStateIDs.SetCoolFlowTemperatureZone1, definition: { type: "state", common: { name: "Set cool flow temperature zone 1", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: true, def: this.setCoolFlowTemperatureZone1, desc: "Set cool flow temperature for zone 1", }, native: {}, }, }, ]); if (this.hasZone2) { await this.createStates(controlPrefix, [ { id: commonDefines.AtwDeviceStateIDs.SetCoolFlowTemperatureZone2, definition: { type: "state", common: { name: "Set cool flow temperature zone 2", type: "number", role: "value.temperature", unit: this.platform.UseFahrenheit ? "°F" : "°C", read: true, write: true, def: this.setCoolFlowTemperatureZone2, desc: "Set cool flow temperature for zone 2", }, native: {}, }, }, ]); } } //#endregion //#region REPORTS const lastReportDataPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Reports}.${commonDefines.AdapterDatapointIDs.LastReportData}`; const reportModes = ["Heat", "Cool", "HotWater"]; reportModes.forEach(mode => async () => { 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: {}, }, }, { id: lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerProductionPrefix + mode, definition: { type: "state", common: { name: `Total power production for mode '${mode}'`, type: "number", role: "value.power.consumption", min: 0, read: true, write: false, unit: "kWh", def: 0, desc: `Total power production for mode '${mode}'`, }, native: {}, }, }, { id: lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerProductionPrefix, definition: { type: "state", common: { name: "Total power production for all modes", type: "number", role: "value.power.consumption", min: 0, read: true, write: false, unit: "kWh", def: 0, desc: "Total power production for all modes", }, native: {}, }, }, ]); }); //#endregion this.adapter.log.debug(`Created and saved ATW 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.AtwDeviceStateIDs.RoomTemperatureZone1, this.roomTemperatureZone1, true, ); if (this.hasZone2) { await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.RoomTemperatureZone2, this.roomTemperatureZone2, true, ); } await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.MixingTankWaterTemperature, this.mixingTankWaterTemperature, true, ); await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.CondensingTemperature, this.condensingTemperature, true, ); await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.OutdoorTemperature, this.outdoorTemperature, true, ); await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.FlowTemperature, this.flowTemperature, true, ); await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.FlowTemperatureZone1, this.flowTemperatureZone1, true, ); if (this.hasZone2) { await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.FlowTemperatureZone2, this.flowTemperatureZone2, true, ); } await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.FlowTemperatureBoiler, this.flowTemperatureBoiler, true, ); await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.ReturnTemperature, this.returnTemperature, true, ); await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.ReturnTemperatureZone1, this.returnTemperatureZone1, true, ); if (this.hasZone2) { await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.ReturnTemperatureZone2, this.ReturnTemperatureZone2, true, ); } await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.ReturnTemperatureBoiler, this.returnTemperatureBoiler, true, ); await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.TankWaterTemperature, this.tankWaterTemperature, true, ); await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.HeatPumpFrequency, this.heatPumpFrequency, true, ); await this.adapter.setStateChangedAsync( infoPrefix + commonDefines.AtwDeviceStateIDs.OperationState, this.operationState, true, ); //#endregion //#region CONTROL const controlPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Control}.`; switch (deviceOption) { case commonDefines.AtwDeviceOptions.PowerState: await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.Power, this.power, true, ); break; case commonDefines.AtwDeviceOptions.ForcedHotWaterMode: await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.ForcedHotWaterMode, this.forcedHotWaterMode, true, ); break; case commonDefines.AtwDeviceOptions.OperationModeZone1: await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.OperationModeZone1, this.operationModeZone1, true, ); break; case commonDefines.AtwDeviceOptions.OperationModeZone2: if (this.hasZone2) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.OperationModeZone2, this.operationModeZone2, true, ); } break; case commonDefines.AtwDeviceOptions.SetTankWaterTemperature: await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetTankWaterTemperature, this.setTankWaterTemperature, true, ); break; case commonDefines.AtwDeviceOptions.SetTemperatureZone1: await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetTemperatureZone1, this.setTemperatureZone1, true, ); break; case commonDefines.AtwDeviceOptions.SetTemperatureZone2: if (this.hasZone2) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetTemperatureZone2, this.setTemperatureZone2, true, ); } break; case commonDefines.AtwDeviceOptions.SetHeatFlowTemperatureZone1: if (this.canHeat) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetHeatFlowTemperatureZone1, this.setHeatFlowTemperatureZone1, true, ); } break; case commonDefines.AtwDeviceOptions.SetHeatFlowTemperatureZone2: if (this.canHeat && this.hasZone2) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetHeatFlowTemperatureZone2, this.setHeatFlowTemperatureZone2, true, ); } break; case commonDefines.AtwDeviceOptions.SetCoolFlowTemperatureZone1: if (this.canCool) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetCoolFlowTemperatureZone1, this.setCoolFlowTemperatureZone1, true, ); } break; case commonDefines.AtwDeviceOptions.SetCoolFlowTemperatureZone2: if (this.canCool && this.hasZone2) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetCoolFlowTemperatureZone2, this.setCoolFlowTemperatureZone2, true, ); } break; case "ALL": default: await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.Power, this.power, true, ); await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.ForcedHotWaterMode, this.forcedHotWaterMode, true, ); await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.OperationModeZone1, this.operationModeZone1, true, ); if (this.hasZone2) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.OperationModeZone2, this.operationModeZone2, true, ); } await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetTankWaterTemperature, this.setTankWaterTemperature, true, ); await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetTemperatureZone1, this.setTemperatureZone1, true, ); if (this.hasZone2) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetTemperatureZone2, this.setTemperatureZone2, true, ); } if (this.canHeat) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetHeatFlowTemperatureZone1, this.setHeatFlowTemperatureZone1, true, ); } if (this.canHeat && this.hasZone2) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetHeatFlowTemperatureZone2, this.setHeatFlowTemperatureZone2, true, ); } if (this.canCool) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetCoolFlowTemperatureZone1, this.setCoolFlowTemperatureZone1, true, ); } if (this.canCool && this.hasZone2) { await this.adapter.setStateChangedAsync( controlPrefix + commonDefines.AtwDeviceStateIDs.SetCoolFlowTemperatureZone2, this.setCoolFlowTemperatureZone2, true, ); } break; } //#endregion this.adapter.log.debug(`Updated device data for ATW 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; let totalProduction = 0; await this.adapter.setStateChangedAsync( `${lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix}Cool`, commonDefines.roundValue(this.totalPowerConsumptionCooling, 3), true, ); totalConsumption += this.totalPowerConsumptionCooling; await this.adapter.setStateChangedAsync( `${lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerProductionPrefix}Cool`, commonDefines.roundValue(this.totalPowerProductionCooling, 3), true, ); totalProduction += this.totalPowerProductionCooling; await this.adapter.setStateChangedAsync( `${lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix}Heat`, commonDefines.roundValue(this.totalPowerConsumptionHeating, 3), true, ); totalConsumption += this.totalPowerConsumptionHeating; await this.adapter.setStateChangedAsync( `${lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerProductionPrefix}Heat`, commonDefines.roundValue(this.totalPowerProductionHeating, 3), true, ); totalProduction += this.totalPowerProductionHeating; await this.adapter.setStateChangedAsync( `${lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix}HotWater`, commonDefines.roundValue(this.totalPowerConsumptionHotWater, 3), true, ); totalConsumption += this.totalPowerConsumptionHotWater; await this.adapter.setStateChangedAsync( `${lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerProductionPrefix}HotWater`, commonDefines.roundValue(this.totalPowerProductionHotWater, 3), true, ); totalProduction += this.totalPowerProductionHotWater; await this.adapter.setStateChangedAsync( lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix, commonDefines.roundValue(totalConsumption, 3), true, ); await this.adapter.setStateChangedAsync( lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalPowerProductionPrefix, commonDefines.roundValue(totalProduction, 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!`, ); this.currentDeviceSetRequests--; return; } if (deviceOption == commonDefines.AtwDeviceOptions.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.AtwDeviceOptions.ForcedHotWaterMode) { modifiedAirInfo.ForcedHotWaterMode = value; modifiedAirInfo.EffectiveFlags = commonDefines.AtwDeviceOptions.ForcedHotWaterMode.effectiveFlags; } else if ( deviceOption == commonDefines.AtwDeviceOptions.OperationModeZone1 || deviceOption == commonDefines.AtwDeviceOptions.OperationModeZone2 ) { const isZone1 = deviceOption == commonDefines.AtwDeviceOptions.OperationModeZone1; if (!isZone1 && !this.hasZone2) { this.adapter.log.error("setDevice(): Unsupported operation mode. This device has no zone 2."); this.currentDeviceSetRequests--; return; } if ( (value == commonDefines.AtwDeviceZoneOperationModes.COOLFLOW.value || value == commonDefines.AtwDeviceZoneOperationModes.COOLTHERMOSTAT.value) && !this.canCool ) { this.adapter.log.error("setDevice(): Unsupported operation mode. Device can not cool!"); this.currentDeviceSetRequests--; return; } if ( (value == commonDefines.AtwDeviceZoneOperationModes.HEATFLOW.value || value == commonDefines.AtwDeviceZoneOperationModes.HEATFLOW.value || value == commonDefines.AtwDeviceZoneOperationModes.CURVE.value) && !this.canHeat ) { this.adapter.log.error("setDevice(): Unsupported operation mode. Device can not heat!"); this.currentDeviceSetRequests--; return; } modifiedAirInfo.EffectiveFlags = isZone1 ? commonDefines.AtwDeviceOptions.OperationModeZone1.effectiveFlags : commonDefines.AtwDeviceOptions.OperationModeZone2.effectiveFlags; switch (value) { case commonDefines.AtwDeviceZoneOperationModes.HEATTHERMOSTAT: isZone1 ? (modifiedAirInfo.OperationModeZone1 = commonDefines.AtwDeviceZoneOperationModes.HEATTHERMOSTAT.value) : (modifiedAirInfo.OperationModeZone2 = commonDefines.AtwDeviceZoneOperationModes.HEATTHERMOSTAT.value); break; case commonDefines.AtwDeviceZoneOperationModes.HEATFLOW: isZone1 ? (modifiedAirInfo.OperationModeZone1 = commonDefines.AtwDeviceZoneOperationModes.HEATFLOW.value) : (modifiedAirInfo.OperationModeZone2 = commonDefines.AtwDeviceZoneOperationModes.HEATFLOW.value); break; case commonDefines.AtwDeviceZoneOperationModes.CURVE: isZone1 ? (modifiedAirInfo.OperationModeZone1 = commonDefines.AtwDeviceZoneOperationModes.CURVE.value) : (modifiedAirInfo.OperationModeZone2 = commonDefines.AtwDeviceZoneOperationModes.CURVE.value); break; case commonDefines.AtwDeviceZoneOperationModes.COOLTHERMOSTAT: isZone1 ? (modifiedAirInfo.OperationModeZone1 = commonDefines.AtwDeviceZoneOperationModes.COOLTHERMOSTAT.value) : (modifiedAirInfo.OperationModeZone2 = commonDefines.AtwDeviceZoneOperationModes.COOLTHERMOSTAT.value); break; case commonDefines.AtwDeviceZoneOperationModes.COOLFLOW: isZone1 ? (modifiedAirInfo.OperationModeZone1 = commonDefines.AtwDeviceZoneOperationModes.COOLFLOW.value) : (modifiedAirInfo.OperationModeZone2 = commonDefines.AtwDeviceZoneOperationModes.COOLFLOW.value); 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.AtwDeviceOptions.SetTankWaterTemperature) { modifiedAirInfo.SetTankWaterTemperature = value; modifiedAirInfo.EffectiveFlags = commonDefines.AtwDeviceOptions.SetTankWaterTemperature.effectiveFlags; } else if (deviceOption == commonDefines.AtwDeviceOptions.SetTemperatureZone1) { modifiedAirInfo.SetTemperatureZone1 = value; modifiedAirInfo.EffectiveFlags = commonDefines.AtwDeviceOptions.SetTemperatureZone1.effectiveFlags; } else if (deviceOption == commonDefines.AtwDeviceOptions.SetTemperatureZone2) { if (!this.hasZone2) { this.adapter.log.error("setDevice(): Unsupported device option. This device has no zone 2."); this.currentDeviceSetRequests--; return; } modifiedAirInfo.SetTemperatureZone2 = value; modifiedAirInfo.EffectiveFlags = commonDefines.AtwDeviceOptions.SetTemperatureZone2.effectiveFlags; } else if (deviceOption == commonDefines.AtwDeviceOptions.SetHeatFlowTemperatureZone1) { modifiedAirInfo.SetHeatFlowTemperatureZone1 = value; modifiedAirInfo.EffectiveFlags = commonDefines.AtwDeviceOptions.SetHeatFlowTemperatureZone1.effectiveFlags; } else if (deviceOption == commonDefines.AtwDeviceOptions.SetHeatFlowTemperatureZone2) { if (!this.hasZone2) { this.adapter.log.error("setDevice(): Unsupported device option. This device has no zone 2."); this.currentDeviceSetRequests--; return; } modifiedAirInfo.SetHeatFlowTemperatureZone2 = value; modifiedAirInfo.EffectiveFlags = commonDefines.AtwDeviceOptions.SetHeatFlowTemperatureZone2.effectiveFlags; } else if (deviceOption == commonDefines.AtwDeviceOptions.SetCoolFlowTemperatureZone1) { modifiedAirInfo.SetCoolFlowTemperatureZone1 = value; modifiedAirInfo.EffectiveFlags = commonDefines.AtwDeviceOptions.SetCoolFlowTemperatureZone1.effectiveFlags; } else if (deviceOption == commonDefines.AtwDeviceOptions.SetCoolFlowTemperatureZone2) { if (!this.hasZone2) { this.adapter.log.error("setDevice(): Unsupported device option. This device has no zone 2."); this.currentDeviceSetRequests--; return; } modifiedAirInfo.SetCoolFlowTemperatureZone2 = value; modifiedAirInfo.EffectiveFlags = commonDefines.AtwDeviceOptions.SetCoolFlowTemperatureZone2.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/SetAtw"; 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; } 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.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.AtwDeviceOptions.PowerState: this.power = responseData.Power; break; case commonDefines.AtwDeviceOptions.ForcedHotWaterMode: this.forcedHotWaterMode = responseData.ForcedHotWaterMode; break; case commonDefines.AtwDeviceOptions.OperationModeZone1: this.operationModeZone1 = responseData.OperationModeZone1; break; case commonDefines.AtwDeviceOptions.OperationModeZone2: if (this.hasZone2) { this.operationModeZone2 = responseData.OperationModeZone2; } break; case commonDefines.AtwDeviceOptions.SetTankWaterTemperature: this.setTankWaterTemperature = responseData.SetTankWaterTemperature; break; case commonDefines.AtwDeviceOptions.SetTemperatureZone1: this.setTemperatureZone1 = responseData.SetTemperatureZone1; break; case commonDefines.AtwDeviceOptions.SetTemperatureZone2: if (this.hasZone2) { this.setTemperatureZone2 = responseData.SetTemperatureZone2; } break; case commonDefines.AtwDeviceOptions.SetHeatFlowTemperatureZone1: if (this.canHeat) { this.setHeatFlowTemperatureZone1 = responseData.SetHeatFlowTemperatureZone1; } break; case commonDefines.AtwDeviceOptions.SetHeatFlowTemperatureZone2: if (this.canHeat && this.hasZone2) { this.setHeatFlowTemperatureZone2 = responseData.SetHeatFlowTemperatureZone2; } break; case commonDefines.AtwDeviceOptions.SetCoolFlowTemperatureZone1: if (this.canCool) { this.setCoolFlowTemperatureZone1 = responseData.SetCoolFlowTemperatureZone1; } break; case commonDefines.AtwDeviceOptions.SetCoolFlowTemperatureZone2: if (this.canCool && this.hasZone2) { this.setCoolFlowTemperatureZone2 = responseData.SetCoolFlowTemperatureZone2; } 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([deviceOption, value]); } } async getPowerConsumptionReport(isCumulatedReport = false) { return new Promise((resolve, reject) => { this.adapter.log.debug(`Getting power consumption report for ${this.id} (${this.name})`); const doRequest = async () => { const url = "https://app.melcloud.com/Mitsubishi.Wifi.Client/EnergyCost/Report"; const body = JSON.stringify(await this.buildPowerConsumptionReportRequestBody(isCumulatedReport)); 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.totalPowerConsumptionHeating = responseData.TotalHeatingConsumed; this.totalPowerConsumptionCooling = responseData.TotalCoolingConsumed; this.totalPowerConsumptionHotWater = responseData.TotalHotWaterConsumed; this.totalPowerProductionHeating = responseData.TotalHeatingProduced; this.totalPowerProductionCooling = responseData.TotalCoolingProduced; this.totalPowerProductionHotWater = responseData.TotalHotWaterProduced; 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(); }); }; doRequest(); }); } } exports.MelCloudDevice = MelcloudAtwDevice;