iobroker.melcloud
Version:
915 lines (846 loc) • 26.2 kB
JavaScript
"use strict";
const Axios = require("axios").default;
const commonDefines = require("./commonDefines");
const HttpStatus = require("http-status-codes");
class MelcloudBaseDevice {
constructor(adapter, platform, deviceType) {
this.adapter = adapter;
this.platform = platform;
this.deviceType = deviceType;
this.airInfo = null;
this.deviceInfoRequestQueue = [];
this.currentDeviceInfoRequests = 0;
this.deviceSetRequestQueue = [];
this.currentDeviceSetRequests = 0;
this.hasBeenCreated = false;
// Info
this.id = -1;
this.name = "";
this.serialNumber = "";
this.macAddress = "";
this.buildingId = -1;
this.floorId = -1;
this.canCool = false;
this.canHeat = false;
this.lastCommunication = null;
this.nextCommunication = null;
this.deviceOnline = false;
this.deviceHasError = false;
this.errorMessages = "";
this.errorCode = 8000;
// Control
this.power = false;
this.timerToggle = false;
// Reports
this.powerConsumptionReportStartDate = "";
this.powerConsumptionReportEndDate = "";
this.totalPowerConsumptionCooling = 0;
this.totalPowerConsumptionHeating = 0;
this.totalPowerConsumptionMinutes = 0;
this.rawPowerConsumptionReportData = null;
this.linkedDevicesIncludedInArregateEnergyReport = "";
}
async createStates(prefix, stateDefs) {
for (const def of stateDefs) {
const stateName = def.id != null ? `${prefix}.${def.id}` : prefix;
await this.adapter.extendObjectAsync(stateName, def.definition);
}
}
async createCommonStates() {
let deviceTypeName = "";
switch (this.deviceType) {
case commonDefines.DeviceTypes.AirToAir:
deviceTypeName = "AirToAir";
break;
case commonDefines.DeviceTypes.AirToWater:
deviceTypeName = "AirToWater";
break;
case commonDefines.DeviceTypes.EnergyRecoveryVentilation:
deviceTypeName = "EnergyRecoveryVentilation";
break;
default:
break;
}
const devicePrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}`;
await this.createStates(devicePrefix, [
{
id: null,
definition: {
type: "device",
common: {
statusStates: {
onlineId: `${this.adapter.namespace}.${devicePrefix}.${commonDefines.AdapterDatapointIDs.Info}.${commonDefines.CommonDeviceStateIDs.DeviceOnline}`,
errorId: `${this.adapter.namespace}.${devicePrefix}.${commonDefines.AdapterDatapointIDs.Info}.${commonDefines.CommonDeviceStateIDs.DeviceHasError}`,
},
name: `${deviceTypeName} Device ${this.id} (${this.name})`,
},
native: {},
},
},
]);
//#region INFO
const infoPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Info}`;
await this.createStates(infoPrefix, [
{
id: null,
definition: {
type: "channel",
common: {
name: "Device information",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.DeviceName,
definition: {
type: "state",
common: {
name: "Device name",
type: "string",
role: "info.name",
read: true,
write: false,
def: this.name,
desc: "MELCloud device name",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.DeviceType,
definition: {
type: "state",
common: {
name: "Device type",
type: "number",
role: "value",
states: {
0: "Air to air heat pump / air conditioner (ATA)",
1: "Air to water heat pump (ATW)",
3: "Energy recovery ventilation (ERV)",
},
read: true,
write: false,
def: this.deviceType,
desc: "MELCloud device type",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.SerialNumber,
definition: {
type: "state",
common: {
name: "Serial number",
type: "string",
role: "value",
read: true,
write: false,
def: this.serialNumber,
desc: "Serial number of the device",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.MacAddress,
definition: {
type: "state",
common: {
name: "MAC address",
type: "string",
role: "info.mac",
read: true,
write: false,
def: this.macAddress,
desc: "MAC address of the device",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.BuildingId,
definition: {
type: "state",
common: {
name: "Building ID",
type: "number",
role: "value",
read: true,
write: false,
def: this.buildingId,
desc: "MELCloud building ID",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.FloorId,
definition: {
type: "state",
common: {
name: "Floor ID",
type: "number",
role: "value",
read: true,
write: false,
def: this.floorId,
desc: "MELCloud floor ID",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.CanCool,
definition: {
type: "state",
common: {
name: "Ability to cool",
type: "boolean",
role: "value",
read: true,
write: false,
def: this.canCool,
desc: "Ability to cool",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.CanHeat,
definition: {
type: "state",
common: {
name: "Ability to heat",
type: "boolean",
role: "value",
read: true,
write: false,
def: this.canHeat,
desc: "Ability to heat",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.LastCommunication,
definition: {
type: "state",
common: {
name: "Last communication",
type: "string",
role: "date",
read: true,
write: false,
def: this.lastCommunication,
desc: "Last communication date/time (MELCloud to device)",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.NextCommunication,
definition: {
type: "state",
common: {
name: "Next communication",
type: "string",
role: "date",
read: true,
write: false,
def: this.nextCommunication,
desc: "Next communication date/time (MELCloud to device)",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.DeviceOnline,
definition: {
type: "state",
common: {
name: "Is device online",
type: "boolean",
role: "indicator.reachable",
read: true,
write: false,
def: this.deviceOnline,
desc: "Indicates if device is reachable",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.DeviceHasError,
definition: {
type: "state",
common: {
name: "Has device an error",
type: "boolean",
role: "indicator.maintenance.alarm",
read: true,
write: false,
def: this.deviceHasError,
desc: "Indicates if device has an error",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.ErrorMessages,
definition: {
type: "state",
common: {
name: "Error messages",
type: "string",
role: "value",
read: true,
write: false,
def: this.errorMessages,
desc: "Current error messages",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.ErrorCode,
definition: {
type: "state",
common: {
name: "Error code",
type: "number",
role: "value",
read: true,
write: false,
def: this.errorCode,
desc: "Current error code",
states: {
8000: "No error",
},
},
native: {},
},
},
]);
//#endregion
//#region CONTROL
const controlPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Control}`;
await this.createStates(controlPrefix, [
{
id: null,
definition: {
type: "channel",
common: {
name: "Device control",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.TimerToogle,
definition: {
type: "state",
common: {
name: "Timer toggle",
type: "boolean",
role: "switch.enable",
read: true,
write: true,
def: this.timerToggle,
desc: "Enable or disable the device's timer",
},
native: {},
},
},
]);
//#endregion
//#region REPORTS
if (this.deviceType != commonDefines.DeviceTypes.EnergyRecoveryVentilation) {
const reportsPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Reports}`;
await this.createStates(reportsPrefix, [
{
id: null,
definition: {
type: "channel",
common: {
name: "Device reports",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.PowerConsumptionReportStartDate,
definition: {
type: "state",
common: {
name: "Report start date (format: YYYY-MM-DD)",
type: "string",
role: "date",
read: true,
write: true,
desc: "Report data will be collected starting at this date",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.PowerConsumptionReportEndDate,
definition: {
type: "state",
common: {
name: "Report end date (format: YYYY-MM-DD)",
type: "string",
role: "date",
read: true,
write: true,
desc: "Report data will be collected until this date",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.GetPowerConsumptionReport,
definition: {
type: "state",
common: {
name: "Get current power consumption report",
type: "boolean",
role: "button",
read: false,
write: true,
def: false,
desc: "Get current power consumption report",
},
native: {},
},
},
]);
const lastReportDataPrefix = `${devicePrefix}.${commonDefines.AdapterDatapointIDs.Reports}.${commonDefines.AdapterDatapointIDs.LastReportData}`;
await this.createStates(lastReportDataPrefix, [
{
id: null,
definition: {
type: "channel",
common: {
name: "Last report data",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.TotalPowerConsumptionPrefix,
definition: {
type: "state",
common: {
name: "Total power consumption for all modes",
type: "number",
role: "value.power.consumption",
min: 0,
read: true,
write: false,
unit: "kWh",
def: 0,
desc: "Total power consumption for all modes",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.TotalReportedMinutes,
definition: {
type: "state",
common: {
name: "Total power consumption minutes",
type: "number",
role: "value",
min: 0,
read: true,
write: false,
unit: "min",
def: 0,
desc: "Total operation time",
},
native: {},
},
},
{
id: commonDefines.CommonDeviceStateIDs.RawPowerConsumptionData,
definition: {
type: "state",
common: {
name: "Raw data of current report",
type: "string",
role: "json",
read: true,
write: false,
desc: "Raw data of current report",
},
native: {},
},
},
]);
}
//#endregion
}
async UpdateCommonDeviceData() {
//#region INFO
const infoPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Info}.`;
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.DeviceName,
this.name,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.SerialNumber,
this.serialNumber,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.MacAddress,
this.macAddress,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.BuildingId,
this.buildingId,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.FloorId,
this.floorId,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.CanCool,
this.canCool,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.CanHeat,
this.canHeat,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.LastCommunication,
this.lastCommunication,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.NextCommunication,
this.nextCommunication,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.DeviceOnline,
this.deviceOnline,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.DeviceHasError,
this.deviceHasError,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.ErrorMessages,
this.errorMessages,
true,
);
await this.adapter.setStateChangedAsync(
infoPrefix + commonDefines.CommonDeviceStateIDs.ErrorCode,
this.errorCode,
true,
);
//#endregion
}
async UpdateCommonReportData() {
const reportsPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Reports}.`;
await this.adapter.setStateChangedAsync(
reportsPrefix + commonDefines.CommonDeviceStateIDs.PowerConsumptionReportStartDate,
this.powerConsumptionReportStartDate,
true,
);
await this.adapter.setStateChangedAsync(
reportsPrefix + commonDefines.CommonDeviceStateIDs.PowerConsumptionReportEndDate,
this.powerConsumptionReportEndDate,
true,
);
const lastReportDataPrefix = `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Reports}.${commonDefines.AdapterDatapointIDs.LastReportData}.`;
await this.adapter.setStateChangedAsync(
lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.TotalReportedMinutes,
this.totalPowerConsumptionMinutes,
true,
);
await this.adapter.setStateChangedAsync(
lastReportDataPrefix + commonDefines.CommonDeviceStateIDs.RawPowerConsumptionData,
JSON.stringify(this.rawPowerConsumptionReportData),
true,
);
}
getDeviceInfo(callback, deviceOption, value) {
if (this.airInfo != null) {
this.adapter.log.debug(`Data already available for: ${this.id} (${this.name})`);
callback && callback(deviceOption, value, this);
if (this.deviceInfoRequestQueue.length) {
const args = this.deviceInfoRequestQueue.shift();
this.adapter.log.debug(
`Dequeueing getDeviceInfo remote request for device option '${args[1].id}' with value '${args[2].value != undefined ? args[2].value : args[2]}'...`,
);
this.getDeviceInfo.apply(this, args);
}
return;
}
this.adapter.log.debug(`Getting device data for ${this.id} (${this.name})`);
if (this.currentDeviceInfoRequests < 1) {
this.currentDeviceInfoRequests++;
const url = `https://app.melcloud.com/Mitsubishi.Wifi.Client/Device/Get?id=${this.id}&buildingID=${this.buildingId}`;
Axios.get(url, {
httpsAgent: this.platform.customHttpsAgent,
headers: {
Host: "app.melcloud.com",
"X-MitsContextKey": this.platform.contextKey,
},
})
.then(response => {
this.currentDeviceInfoRequests--;
if (!response || !response.data || JSON.stringify(response.data).search("<!DOCTYPE html>") != -1) {
this.adapter.log.error(`There was a problem receiving the response from: ${url}`);
this.airInfo = null;
} else {
const statusCode = response.status;
this.adapter.log.debug(
`Received response from: ${url} (status code: ${statusCode} - ${response.statusText})`,
);
if (statusCode != HttpStatus.StatusCodes.OK) {
this.airInfo = null;
this.adapter.log.error(
`Invalid HTTP status code (${statusCode} - ${response.statusText}). Getting device data failed!`,
);
} else {
this.adapter.log.debug(`Response from cloud: ${JSON.stringify(response.data)}`);
this.airInfo = response.data;
// Cache airInfo data for 1 minute
setTimeout(() => {
this.airInfo = null;
}, 60 * 1000);
callback && callback(deviceOption, value, this);
}
}
if (this.deviceInfoRequestQueue.length) {
const args = this.deviceInfoRequestQueue.shift();
this.adapter.log.debug(
`Dequeueing getDeviceInfo remote request for device option '${args[1].id}' with value '${args[2].value != undefined ? args[2].value : args[2]}'`,
);
this.getDeviceInfo.apply(this, args);
}
})
.catch(error => {
this.adapter.log.error(`There was a problem getting device data from: ${url}`);
this.adapter.log.error(`Error: ${error}`);
this.airInfo = null;
this.currentDeviceInfoRequests--;
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.deviceInfoRequestQueue.length) {
const args = this.deviceInfoRequestQueue.shift();
this.adapter.log.debug(
`Dequeueing getDeviceInfo remote request for device option '${args[1].id}' with value '${args[2].value != undefined ? args[2].value : args[2]}'`,
);
this.getDeviceInfo.apply(this, args);
}
});
} else {
this.adapter.log.debug(
`Queueing getDeviceInfo remote request for '${deviceOption.id}' with value '${value.value != undefined ? value.value : value}'...`,
);
this.deviceInfoRequestQueue.push(arguments);
}
}
async buildPowerConsumptionReportRequestBody(isCumulatedReport = false) {
const requestBody = {};
const startStateId = isCumulatedReport
? `${commonDefines.AdapterDatapointIDs.Reports}.${commonDefines.CommonDeviceStateIDs.PowerConsumptionReportStartDate}`
: `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Reports}.${commonDefines.CommonDeviceStateIDs.PowerConsumptionReportStartDate}`;
const startDateObj = await this.adapter.getStateAsync(startStateId);
let startDate = startDateObj == null || startDateObj.val == null ? "" : startDateObj.val;
const endStateId = isCumulatedReport
? `${commonDefines.AdapterDatapointIDs.Reports}.${commonDefines.CommonDeviceStateIDs.PowerConsumptionReportEndDate}`
: `${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Reports}.${commonDefines.CommonDeviceStateIDs.PowerConsumptionReportEndDate}`;
const endDateObj = await this.adapter.getStateAsync(endStateId);
let endDate = endDateObj == null || endDateObj.val == null ? "" : endDateObj.val;
if (startDate == "") {
this.adapter.log.warn(
"No valid start date was provided (format: YYYY-MM-DD). Defaulting to 6 months prior.",
);
const d = new Date();
d.setMonth(d.getMonth() - 6);
startDate = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
}
const parsedStartDate = startDate.split("-");
if (
parsedStartDate.length != 3 ||
parsedStartDate[0].length != 4 ||
parsedStartDate[1].length > 2 ||
parsedStartDate[2].length > 2
) {
this.adapter.log.warn(
"No valid start date was provided (format: YYYY-MM-DD). Defaulting to 6 months prior.",
);
const d = new Date();
d.setMonth(d.getMonth() - 6);
startDate = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
}
if (endDate == "") {
this.adapter.log.warn("No valid end date was provided (format: YYYY-MM-DD). Defaulting to today.");
const d = new Date();
endDate = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
}
const parsedEndDate = endDate.split("-");
if (
parsedEndDate.length != 3 ||
parsedEndDate[0].length != 4 ||
parsedEndDate[1].length > 2 ||
parsedEndDate[2].length > 2
) {
this.adapter.log.warn("No valid end date was provided (format: YYYY-MM-DD). Defaulting to today.");
const d = new Date();
endDate = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;
}
requestBody.DeviceId = this.id;
requestBody.FromDate = `${startDate}T00:00:00`;
requestBody.ToDate = `${endDate}T00:00:00`;
requestBody.UseCurrency = false;
return requestBody;
}
async toggleTimerState(enableTimer) {
return new Promise((resolve, reject) => {
this.adapter.log.debug(`${enableTimer ? `Enabling` : `Disabling`} timer for ${this.id} (${this.name})`);
(async () => {
// Step 1: Get current timer infos
const getTimerUrl = `https://app.melcloud.com/Mitsubishi.Wifi.Client/Timer/Get2?deviceId=${this.id}`;
try {
const response = await Axios.get(getTimerUrl, {
httpsAgent: this.platform.customHttpsAgent,
headers: {
Host: "app.melcloud.com",
"X-MitsContextKey": this.platform.contextKey,
},
});
if (!response) {
this.adapter.log.error(`There was a problem receiving the response from: ${getTimerUrl}`);
reject();
return;
}
const statusCode = response.status;
const statusText = response.statusText;
this.adapter.log.debug(
`Received response from: ${getTimerUrl} (status code: ${statusCode} - ${statusText})`,
);
if (statusCode != HttpStatus.StatusCodes.OK) {
this.adapter.log.error(
`Invalid HTTP status code (${statusCode} - ${statusText}). Getting timer information failed!`,
);
reject();
return;
}
const responseData = response.data;
this.adapter.log.debug(`Response from cloud: ${JSON.stringify(responseData)}`);
this.timerToggle = responseData.Enabled;
this.adapter.setStateChangedAsync(
`${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Control}.${commonDefines.CommonDeviceStateIDs.TimerToogle}`,
this.timerToggle,
true,
);
if (enableTimer == this.timerToggle) {
this.adapter.log.warn(
`Timer for ${this.id} (${this.name}) is already ${enableTimer ? `enabled` : `disabled`}. Ignoring request.`,
);
resolve();
return;
}
if (responseData.Seasons[0].Events.length == 0) {
this.adapter.log.warn(
`No timer events for ${this.id} (${this.name}) set. Please set them first in the MelCloud app/website before toggling it here. Ignoring request.`,
);
resolve();
return;
}
// Step 2: Set desired timer state with infos retrieved from step 1
const toggleRequest = response.data;
toggleRequest.Devices = this.id;
toggleRequest.TimerEnabled = enableTimer;
toggleRequest.SkipPage1 = true;
const setTimerUrl = "https://app.melcloud.com/Mitsubishi.Wifi.Client/Timer/SetAta2";
const body = JSON.stringify(toggleRequest);
this.adapter.log.silly(`Request body: ${body}`);
try {
const setResponse = await Axios.post(setTimerUrl, body, {
httpsAgent: this.platform.customHttpsAgent,
headers: {
Host: "app.melcloud.com",
"X-MitsContextKey": this.platform.contextKey,
"Content-Type": "application/json; charset=utf-8",
},
});
if (!setResponse) {
this.adapter.log.error(`There was a problem receiving the response from: ${setTimerUrl}`);
reject();
return;
}
const setStatusCode = setResponse.status;
const setStatusText = setResponse.statusText;
this.adapter.log.debug(
`Received response from: ${setTimerUrl} (status code: ${setStatusCode} - ${setStatusText})`,
);
if (setStatusCode != HttpStatus.StatusCodes.OK) {
this.adapter.log.error(
`Invalid HTTP status code (${setStatusCode} - ${setStatusText}). Toggling timer failed!`,
);
reject();
return;
}
const setResponseData = setResponse.data;
this.adapter.log.debug(`Response from cloud: ${JSON.stringify(setResponseData)}`);
if (setResponseData.Success == true) {
this.timerToggle = enableTimer;
this.adapter.setStateChangedAsync(
`${commonDefines.AdapterDatapointIDs.Devices}.${this.id}.${commonDefines.AdapterDatapointIDs.Control}.${commonDefines.CommonDeviceStateIDs.TimerToogle}`,
this.timerToggle,
true,
);
resolve();
} else {
this.adapter.log.error(
`${enableTimer ? `Enabling` : `Disabling`} timer failed with error code ${setResponseData.Data.ErrorCode}`,
);
reject();
}
} catch (error) {
this.adapter.log.error(`There was a problem setting timer to: ${setTimerUrl}`);
this.adapter.log.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 (error) {
this.adapter.log.error(`There was a problem getting timer information from: ${getTimerUrl}`);
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();
}
})();
});
}
}
module.exports = MelcloudBaseDevice;