{"version":3,"sources":["jsdelivr-header.js","/npm/iobroker.homeconnect@1.5.2/main.js"],"names":[],"mappings":"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","file":"/npm/iobroker.homeconnect@1.5.2/main.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/iobroker.homeconnect@1.5.2/main.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","'use strict';\n\n/*\n * Created with @iobroker/create-adapter v2.1.1\n */\n\n// The adapter-core module gives you access to the core ioBroker functions\n// you need to create an adapter\nconst utils = require('@iobroker/adapter-core');\nconst axios = require('axios');\nconst axiosRateLimit = require('axios-rate-limit');\nconst helper = require('./lib/helper');\nconst limiting = require('./lib/rateLimiting');\nconst constants = require('./lib/constants');\nconst qs = require('qs');\nconst { EventSource } = require('eventsource');\nconst tough = require('tough-cookie');\nconst { HttpsCookieAgent } = require('http-cookie-agent/http');\nclass Homeconnect extends utils.Adapter {\n  /**\n   * @param {Partial<utils.AdapterOptions>} [options={}]\n   */\n  constructor(options) {\n    super({\n      ...options,\n      name: 'homeconnect',\n    });\n    this.on('ready', this.onReady.bind(this));\n    this.on('stateChange', this.onStateChange.bind(this));\n    this.on('unload', this.onUnload.bind(this));\n    this.createDataPoint = helper.createDataPoint;\n    this.createDevices = helper.createDevices;\n    this.createObjects = helper.createObjects;\n    this.createFolders = helper.createFolders;\n    this.createFolders = helper.createFolders;\n    this.createOwnRequest = helper.createOwnRequest;\n    this.createLimit = limiting.createLimit;\n    this.getRateLimit = limiting.getRateLimit;\n    this.checkToken = limiting.checkToken;\n    this.checkBlock = limiting.checkBlock;\n    this.setLimitCounter = limiting.setLimitCounter;\n    this.checkLimitCounter = limiting.checkLimitCounter;\n    this.userAgent = 'ioBroker v1.0.0';\n    this.headers = {\n      'user-agent': this.userAgent,\n      Accept: 'application/vnd.bsh.sdk.v1+json',\n      'Accept-Language': 'de-DE',\n    };\n    this.deviceArray = [];\n    this.typeJson = {};\n    this.stateCheck = [];\n    this.fetchedDevice = {};\n    //this.refreshStatusInterval = null;\n    this.reLoginTimeout = null;\n    //this.reconnectInterval = null;\n    this.reconnectTimeout = null;\n    this.refreshTokenInterval = null;\n    this.availablePrograms = {};\n    this.availableProgramOptions = {};\n    this.eventSourceState;\n    this.currentSelected = {};\n    this.sleepTimer = null;\n    this.rateLimiting = {};\n    this.tokenRateLimiting = {};\n    this.rateLimitingInterval = null;\n    this.cookieJar = new tough.CookieJar();\n    // @ts-expect-error //Nothing\n    this.requestClient = axiosRateLimit(\n      axios.create({\n        withCredentials: true,\n        httpsAgent: new HttpsCookieAgent({\n          cookies: {\n            jar: this.cookieJar,\n          },\n        }),\n      }),\n      { maxRequests: 15, perMilliseconds: 1000 },\n    );\n  }\n\n  /**\n   * Is called when databases are connected and adapter received configuration.\n   */\n  async onReady() {\n    // Reset the connection indicator during startup\n    this.setState('info.connection', false, true);\n    if (this.config.resetAccess) {\n      this.log.info('Reset access');\n      this.setState('auth.session', '', true);\n      const adapterConfig = `system.adapter.${this.name}.${this.instance}`;\n      this.getForeignObject(adapterConfig, (error, obj) => {\n        if (obj) {\n          obj.native.resetAccess = false;\n          this.setForeignObject(adapterConfig, obj);\n        } else {\n          this.log.error('No reset possible no Adapterconfig found');\n        }\n      });\n      return;\n    }\n    await this.createLimit();\n    await this.getRateLimit(constants);\n    this.session = {};\n    this.subscribeStates('*');\n    const sessionState = await this.getStateAsync('auth.session');\n\n    if (sessionState && sessionState.val && typeof sessionState.val === 'string') {\n      this.log.debug('Found current session');\n      //this.session = JSON.parse(this.decrypt(sessionState.val));\n      this.session = JSON.parse(sessionState.val);\n    }\n\n    if (this.session.refresh_token) {\n      await this.refreshToken();\n    } else {\n      if (!this.config.username || !this.config.password || !this.config.clientID) {\n        this.log.warn('please enter homeconnect app username and password and clientId in the instance settings');\n        return;\n      }\n\n      this.log.debug('Start normal login');\n      await this.login();\n    }\n    if (this.session.access_token) {\n      this.headers.authorization = `Bearer ${this.session.access_token}`;\n      await this.getDeviceList();\n      await this.startEventStream();\n\n      // this.refreshStatusInterval = this.setInterval(async () => {\n      //     for (const haId of this.deviceArray) {\n      //         this.log.debug(\"Update status for \" + haId);\n      //         this.getAPIValues(haId, \"/status\");\n      //     }\n      // }, 10 * 60 * 1000); //every 10 minutes\n      //Workaround because sometimes no connect event for offline events\n      // this.reconnectInterval = this.setInterval(async () => {\n      //     this.startEventStream();\n      // }, 60 * 60 * 1000); //every 60 minutes\n      this.refreshTokenInterval = this.setInterval(\n        async () => {\n          await this.refreshToken();\n          this.startEventStream();\n        },\n        (this.session.expires_in - 200) * 1000,\n      );\n    }\n    this.setLimitInterval();\n  }\n  setLimitInterval() {\n    this.rateLimitingInterval = this.setInterval(async () => {\n      await this.checkLimitCounter();\n    }, 60 * 1000);\n  }\n  async login() {\n    let loginUrl = '';\n    let tokenRequestSuccesful = false;\n    const deviceAuth = await this.requestClient({\n      method: 'post',\n      url: 'https://api.home-connect.com/security/oauth/device_authorization',\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n      },\n      data: `client_id=${this.config.clientID}&scope=IdentifyAppliance%20Monitor%20Settings%20Control`,\n    })\n      .then(res => {\n        this.log.debug(`login: ${JSON.stringify(res.data)}`);\n        return res.data;\n      })\n      .catch(error => {\n        this.log.error(`login: ${error}`);\n        if (error.response) {\n          this.log.error(`login: ${JSON.stringify(error.response.data)}`);\n          if (error.response.data.error === 'unauthorized_client') {\n            this.log.error('Please check your clientID or wait 15 minutes until it is active');\n          }\n        }\n      });\n    if (!deviceAuth || !deviceAuth.verification_uri_complete) {\n      this.log.error('No verification_uri_complete in device_authorization');\n      return;\n    }\n\n    const loginResponse = await this.requestClient({\n      method: 'post',\n      url: 'https://api.home-connect.com/security/oauth/device_login',\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n      },\n\n      data: qs.stringify({\n        user_code: deviceAuth.user_code,\n        client_id: this.config.clientID,\n        accept_language: 'de',\n        region: 'EU',\n        environment: 'PRD',\n        lookup: 'true',\n        email: this.config.username,\n        password: this.config.password,\n      }),\n    })\n      .then(async res => {\n        this.log.debug(`device login: ${JSON.stringify(res.data)}`);\n        if (res.data.match('data-error-data=\"\" >(.*)<')) {\n          this.log.info(`Normal Login response ${res.data.match('data-error-data=\"\" >(.*)<')[1]}`);\n          this.log.info('Try new SingleKey Login');\n\n          const formData = await this.requestClient({\n            method: 'post',\n            url: 'https://api.home-connect.com/security/oauth/device_login',\n            headers: {\n              'Content-Type': 'application/x-www-form-urlencoded',\n            },\n\n            data: qs.stringify({\n              user_code: deviceAuth.user_code,\n              client_id: this.config.clientID,\n              accept_language: 'de',\n              region: 'EU',\n              environment: 'PRD',\n              lookup: 'true',\n              email: this.config.username,\n            }),\n          })\n            .then(res => {\n              this.log.debug(`device login2: ${JSON.stringify(res.data)}`);\n\n              loginUrl = res.request.path;\n              return this.extractHidden(res.data);\n            })\n            .catch(error => {\n              this.log.error(`device login2: ${error}`);\n              if (error.response) {\n                this.log.error(`device login2: ${JSON.stringify(error.response.data)}`);\n              }\n            });\n          const loginParams = qs.parse(loginUrl.split('?')[1]);\n          const returnUrl = loginParams.returnUrl || loginParams.ReturnUrl;\n\n          await this.requestClient({\n            method: 'post',\n            maxBodyLength: Infinity,\n            url: 'https://singlekey-id.com/auth/de-de/login/password',\n            headers: {\n              'content-type': 'application/x-www-form-urlencoded',\n              accept: '*/*',\n              'hx-request': 'true',\n              'sec-fetch-site': 'same-origin',\n              'hx-boosted': 'true',\n              'accept-language': 'de-DE,de;q=0.9',\n              'sec-fetch-mode': 'cors',\n              origin: 'https://singlekey-id.com',\n              'user-agent':\n                'Mozilla/5.0 (iPhone; CPU iPhone OS 16_7_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1',\n              'sec-fetch-dest': 'empty',\n            },\n            params: loginParams,\n            data: {\n              Password: this.config.password,\n              RememberMe: 'true',\n              __RequestVerificationToken: formData['undefined'],\n            },\n          }).catch(error => {\n            this.log.error(error);\n            error.response && this.log.error(JSON.stringify(error.response.data));\n          });\n          return await this.requestClient({\n            method: 'get',\n            url: `https://singlekey-id.com${returnUrl}`,\n          })\n            .then(res => {\n              this.log.debug(`Password: ${JSON.stringify(res.data)}`);\n              return res.data;\n            })\n            .catch(error => {\n              this.log.error(`Password: ${error}`);\n              error.response && this.log.error(`Password: ${JSON.stringify(error.response.data)}`);\n            });\n        }\n        this.log.info('Login details submitted');\n        return this.extractHidden(res.data);\n      })\n      .catch(error => {\n        this.log.error('Please check username and password');\n        this.log.error(error);\n        if (error.response) {\n          this.log.error(JSON.stringify(error.response.data));\n        }\n      });\n    const grantData = this.extractHidden(loginResponse);\n    await this.requestClient({\n      method: 'post',\n      url: 'https://api.home-connect.com/security/oauth/device_grant',\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n      },\n\n      data: grantData,\n    })\n      .then(res => {\n        this.log.debug(`Grand: ${JSON.stringify(res.data)}`);\n        return;\n      })\n      .catch(error => {\n        this.log.error(error);\n        if (error.response) {\n          this.log.error(`Grand: ${JSON.stringify(error.response.data)}`);\n        }\n      });\n\n    await this.sleep(6000);\n\n    while (!tokenRequestSuccesful) {\n      await this.requestClient({\n        method: 'post',\n        url: 'https://api.home-connect.com/security/oauth/token',\n        headers: {\n          'Content-Type': 'application/x-www-form-urlencoded',\n        },\n\n        data: qs.stringify({\n          grant_type: 'device_code',\n          device_code: deviceAuth.device_code,\n          client_id: this.config.clientID,\n        }),\n      })\n        .then(async res => {\n          this.log.debug(`Token: ${JSON.stringify(res.data)}`);\n          this.session = res.data;\n          this.log.info('Token received succesfully');\n          await this.setState('info.connection', true, true);\n          this.session.next = new Date().getTime() + parseInt(this.session.expires_in) * 1000;\n          //await this.setState('auth.session', { val: this.encrypt(JSON.stringify(this.session)), ack: true });\n          await this.setState('auth.session', { val: JSON.stringify(this.session), ack: true });\n          tokenRequestSuccesful = true;\n        })\n        .catch(async error => {\n          this.log.error(error);\n          this.log.error('Please check username and password or visit this site for manually login: ');\n          this.log.error('Bitte überprüfe Benutzername und Passwort oder besuche diese Seite für manuelle Anmeldung: ');\n          this.log.error(deviceAuth.verification_uri_complete);\n          //   this.log.error(error);\n          if (error.response) {\n            this.log.error(JSON.stringify(error.response.data));\n            if (error.response.status === 429) {\n              this.log.info('The maximum number of requests has been reached!');\n              if (error.response.headers) {\n                if (error.response.headers['retry-after']) {\n                  this.log.error(`API retry-after: ${this.convertRetryAfter(error.response.headers['retry-after'])}`);\n                }\n              }\n            }\n          }\n\n          this.log.info('Wait 10 seconds to retry');\n\n          await this.sleep(10000);\n        });\n    }\n  }\n  async getDeviceList() {\n    this.log.debug('Get device list');\n    await this.requestClient({\n      method: 'get',\n      url: 'https://api.home-connect.com/api/homeappliances',\n      headers: this.headers,\n    })\n      .then(async res => {\n        this.log.debug(`Homeappliances: ${JSON.stringify(res.data)}`);\n        let count = 1;\n        if (res.data.data.homeappliances.length > 2) {\n          this.log.info(`Found ${res.data.data.homeappliances.length} devices. Start slow update!`);\n        } else {\n          this.log.info(`Found ${res.data.data.homeappliances.length} devices`);\n        }\n        for (const device of res.data.data.homeappliances) {\n          let haID = device.haId;\n          if (!haID) {\n            this.log.info(`Invalid device ${JSON.stringify(device)}`);\n            continue;\n          }\n          haID = haID.replace(/\\.?-001*$/, '');\n          this.typeJson[haID] = device.type;\n          await this.createFolders(haID);\n          this.deviceArray.push(haID);\n          const name = device.name;\n          await this.createDevices(haID, name, device);\n          if (this.config.ownRequest) {\n            await this.createOwnRequest(haID);\n          } else {\n            await this.delObjectAsync(`${haID}.own_request`, { recursive: true });\n          }\n          if (device.connected) {\n            this.fetchDeviceInformation(haID);\n          }\n          if (\n            (count % 2 == 0 && count != res.data.data.homeappliances.length) ||\n            (this.rateLimiting.requestsMinutesCount > 45 && count != res.data.data.homeappliances.length)\n          ) {\n            this.log.info(`Wait 1 minute!`);\n            await this.sleep(61 * 1000);\n          }\n          ++count;\n        }\n      })\n      .catch(error => {\n        this.log.error(`getDeviceList: ${error}`);\n        if (error.response) {\n          this.log.error(JSON.stringify(error.response.data));\n          if (error.response.status === 429) {\n            this.log.info('The maximum number of requests has been reached!');\n            if (error.response.headers) {\n              if (error.response.headers['retry-after']) {\n                this.log.error(`API retry-after: ${this.convertRetryAfter(error.response.headers['retry-after'])}`);\n              }\n            }\n          }\n        }\n      });\n  }\n\n  async fetchDeviceInformation(haId) {\n    //this.getAPIValues(haId, '/events'); // Response empty\n    //this.getAPIValues(haId, '/images');\n    this.getAPIValues(haId, '/status');\n    this.getAPIValues(haId, '/settings');\n    if (!this.isPrograms(haId)) {\n      this.getAPIValues(haId, '/programs/active');\n      this.getAPIValues(haId, '/programs/selected');\n    }\n    if (!this.fetchedDevice[haId] && !this.isPrograms(haId)) {\n      this.fetchedDevice[haId] = true;\n      this.getAPIValues(haId, '/programs');\n      this.updateOptions(haId, '/programs/active');\n      this.updateOptions(haId, '/programs/selected');\n    }\n  }\n  async getAPIValues(haId, url) {\n    await this.sleep(Math.floor(Math.random() * 1500));\n    if (!(await this.checkBlock())) {\n      return;\n    }\n    await this.setLimitCounter('OK', haId, 'NOK', url, 'GET');\n    const header = Object.assign({}, this.headers);\n    header['Accept-Language'] = this.config.language;\n    const returnValue = await this.requestClient({\n      method: 'get',\n      url: `https://api.home-connect.com/api/homeappliances/${haId}${url}`,\n      headers: header,\n    })\n      .then(res => {\n        this.log.debug(`Homeappliances device: ${JSON.stringify(res.data)}`);\n        return res.data;\n      })\n      .catch(error => {\n        if (error.response) {\n          if (error.response.status === 429) {\n            this.log.info('The maximum number of requests has been reached!');\n            if (error.response.headers) {\n              if (error.response.headers['retry-after']) {\n                this.log.error(`API retry-after: ${this.convertRetryAfter(error.response.headers['retry-after'])}`);\n              }\n            }\n          }\n          const description = error.response.data.error ? error.response.data.error.description : '';\n          this.log.info(`${haId}${url}: ${description}.`);\n          this.log.debug(`Homeappliances device: ${JSON.stringify(error.response.data)}`);\n        } else {\n          this.log.info(error);\n        }\n        return;\n      });\n    if (!returnValue || returnValue.error) {\n      await this.setErrorResponse(true);\n      returnValue && this.log.debug(`Error: ${returnValue.error}`);\n      return;\n    }\n    try {\n      this.log.debug(`URL: ${url}`);\n      this.log.debug(`returnValue: ${JSON.stringify(returnValue)}`);\n      if (url.indexOf('/settings/') !== -1) {\n        let defaults;\n        let type = 'string';\n        let role = 'state';\n        defaults = '';\n        if (returnValue.data.type === 'Int' || returnValue.data.type === 'Double') {\n          type = 'number';\n          role = 'value';\n          defaults = 0;\n        }\n        if (returnValue.data.type === 'Boolean') {\n          type = 'boolean';\n          role = 'switch';\n          defaults = false;\n        }\n        const common = {\n          name: returnValue.data.name,\n          type: type,\n          role: role,\n          write: true,\n          read: true,\n          def: defaults,\n        };\n        if (returnValue.data.constraints && returnValue.data.constraints.allowedvalues) {\n          const states = {};\n          for (let index in returnValue.data.constraints.allowedvalues) {\n            const val = returnValue.data.constraints.allowedvalues[index];\n            states[val] = returnValue.data.constraints.displayvalues[index] || val;\n          }\n          common.states = states;\n        }\n        const folder = `.settings.${returnValue.data.key.replace(/\\./g, '_')}`;\n        this.log.debug(`Extend Settings: ${haId}${folder}`);\n        let value = null;\n        value = returnValue.data.value != null ? returnValue.data.value : value;\n        await this.createDataPoint(haId + folder, common, 'state', value, true, null);\n        return;\n      }\n\n      if (url.indexOf('/programs/available/') !== -1) {\n        if (returnValue.data.options) {\n          this.availableProgramOptions[returnValue.data.key] = this.availableProgramOptions[returnValue.data.key] || [];\n          for (const option of returnValue.data.options) {\n            this.availableProgramOptions[returnValue.data.key].push(option.key);\n            let defaults;\n            let type = 'string';\n            let role = 'state';\n            defaults = '';\n            if (option.type === 'Int' || option.type === 'Double') {\n              type = 'number';\n              role = 'value';\n              defaults = 0;\n            }\n            if (option.type === 'Boolean') {\n              type = 'boolean';\n              role = 'switch';\n              defaults = false;\n            }\n            let common = {\n              name: option.name,\n              type: type,\n              role: role,\n              write: true,\n              read: true,\n              def: defaults,\n            };\n            if (option.unit && option.unit != '') {\n              common.unit = option.unit;\n            }\n            if (option.constraints && option.constraints.min != null && typeof option.constraints.min === 'number') {\n              common.min = option.constraints.min;\n              common.def = option.constraints.min;\n            }\n            if (option.constraints && option.constraints.max != null && typeof option.constraints.max === 'number') {\n              common.max = option.constraints.max;\n            }\n\n            if (option.constraints && option.constraints.allowedvalues) {\n              common.states = {};\n              for (const element of option.constraints.allowedvalues) {\n                common.states[element] =\n                  option.constraints.displayvalues[option.constraints.allowedvalues.indexOf(element)];\n              }\n            }\n            let folder = `.programs.available.options.${option.key.replace(/\\./g, '_')}`;\n            this.log.debug(`Extend Options: ${haId}${folder}`);\n            await this.createDataPoint(haId + folder, common, 'state', null, true, null);\n            this.log.debug('Set default value');\n            if (option.constraints && option.constraints.default) {\n              let value = option.constraints.default;\n              if (option.constraints.default > option.constraints.max) {\n                value = option.constraints.max;\n                this.log.debug(\n                  `Default value ${option.constraints.default} is greater than max ${option.constraints.max}. Set to max.`,\n                );\n              }\n              await this.setState(haId + folder, value, true);\n            }\n            const key = returnValue.data.key.split('.').pop();\n            const com = {\n              name: returnValue.data.name,\n              desc: returnValue.data.desc ? returnValue.data.desc : returnValue.data.name,\n            };\n            if (!this.stateCheck.includes(`${this.namespace}.${haId}.programs.selected.options.${key}`)) {\n              await this.createDataPoint(`${haId}.programs.selected.options.${key}`, com, 'folder', null, true, null);\n            }\n            folder = `.programs.selected.options.${key}.${option.key.replace(/\\./g, '_')}`;\n            await this.createDataPoint(haId + folder, common, 'state', null, true, null);\n          }\n        }\n        return;\n      }\n\n      if ('key' in returnValue.data) {\n        returnValue.data = {\n          items: [returnValue.data],\n        };\n      }\n      for (const item in returnValue.data) {\n        if (Array.isArray(returnValue.data[item])) {\n          for (const subElement of returnValue.data[item]) {\n            let folder = url.replace(/\\//g, '.');\n            if (url === '/programs/active') {\n              subElement.value = subElement.key;\n              subElement.key = 'BSH_Common_Root_ActiveProgram';\n              subElement.name = 'BSH_Common_Root_ActiveProgram';\n            }\n            if (url === '/programs/selected') {\n              if (subElement.key) {\n                subElement.value = subElement.key;\n                this.currentSelected[haId] = { key: subElement.value, name: subElement.name };\n                subElement.key = 'BSH_Common_Root_SelectedProgram';\n                subElement.name = 'BSH_Common_Root_SelectedProgram';\n              } else {\n                this.log.warn(`Empty sublement: ${JSON.stringify(subElement)}`);\n              }\n            }\n            if (url === '/programs') {\n              this.log.debug(`${haId} available: ${JSON.stringify(subElement)}`);\n              if (this.availablePrograms[haId]) {\n                this.availablePrograms[haId].push({\n                  key: subElement.key,\n                  name: subElement.name || subElement.key,\n                });\n              } else {\n                this.availablePrograms[haId] = [\n                  {\n                    key: subElement.key,\n                    name: subElement.name || subElement.key,\n                  },\n                ];\n              }\n              this.getAPIValues(haId, `/programs/available/${subElement.key}`);\n              folder += '.available';\n            }\n            if (url === '/settings') {\n              this.getAPIValues(haId, `/settings/${subElement.key}`);\n            }\n\n            if (url.indexOf('/programs/selected/') !== -1) {\n              //TODO override channel as state - WHY???\n              if (!this.currentSelected[haId]) {\n                return;\n              }\n              if (!this.currentSelected[haId].key) {\n                this.log.warn(`${JSON.stringify(this.currentSelected[haId])} is selected but has no key selected `);\n                return;\n              }\n              const key = this.currentSelected[haId].key.split('.').pop();\n              folder += `.${key}`;\n              /**\n              const common = {\n                name: this.currentSelected[haId].name,\n                type: 'mixed',\n                role: 'state',\n                write: true,\n                read: true,\n              };\n               */\n              this.log.debug(`FOLDER: ${JSON.stringify(this.currentSelected[haId])}`);\n              //await this.createDataPoint(haId + folder, common, 'state', null, true, null);\n              if (this.currentSelected[haId].name) {\n                const common = {\n                  name: this.currentSelected[haId].name,\n                  desc: this.currentSelected[haId].name,\n                };\n                await this.createDataPoint(haId + folder, common, 'folder', null, true, null);\n              }\n            }\n            this.log.debug(`Create State: ${haId}${folder}.${subElement.key.replace(/\\./g, '_')}`);\n            let defaults;\n            let type = 'mixed';\n            let role = 'state';\n            defaults = '';\n            if (typeof subElement.value === 'boolean') {\n              type = 'boolean';\n              role = 'switch';\n              defaults = false;\n            }\n            if (typeof subElement.value === 'number') {\n              type = 'number';\n              role = 'value';\n              defaults = 0;\n            }\n            let common = {\n              name: subElement.name,\n              type: type,\n              role: role,\n              write: true,\n              read: true,\n              def: defaults,\n            };\n            if (subElement.unit && subElement.unit != '') {\n              common.unit = subElement.unit;\n            }\n            if (\n              subElement.constraints &&\n              subElement.constraints.min != null &&\n              typeof subElement.constraints.min === 'number'\n            ) {\n              common.min = subElement.constraints.min;\n              common.def = subElement.constraints.min;\n            }\n            if (\n              subElement.constraints &&\n              subElement.constraints.max != null &&\n              typeof subElement.constraints.max === 'number'\n            ) {\n              common.max = subElement.constraints.max;\n            }\n            const path = `${haId + folder}.${subElement.key.replace(/\\./g, '_')}`;\n            await this.createDataPoint(path, common, 'state', null, true, null);\n            let value = null;\n            if (subElement.value !== undefined) {\n              this.log.debug('Set api value');\n              value = subElement.value;\n              //check if value is an object\n              if (typeof value === 'object' && value !== null) {\n                value = JSON.stringify(value);\n              }\n            }\n            if (value == null) {\n              this.log.debug(`failed set state - Path: ${path} - ${JSON.stringify(subElement)}`);\n              this.log.debug(`Value: '${value}'`);\n            }\n            await this.createDataPoint(path, common, 'state', value, true, null);\n          }\n        } else {\n          this.log.info(`No array: ${item}`);\n        }\n      }\n      if (url === '/programs') {\n        const rootItems = [\n          {\n            key: 'BSH_Common_Root_ActiveProgram',\n            folder: '.programs.active',\n          },\n          {\n            key: 'BSH_Common_Root_SelectedProgram',\n            folder: '.programs.selected',\n          },\n        ];\n        if (!this.availablePrograms[haId]) {\n          this.log.info(`No available programs found for: ${haId}`);\n          return;\n        }\n        for (const rootItem of rootItems) {\n          const common = {\n            name: rootItem.key,\n            type: 'string',\n            role: 'state',\n            write: true,\n            read: true,\n            states: {},\n          };\n          if (this.availablePrograms[haId]) {\n            for (const program of this.availablePrograms[haId]) {\n              common.states[program.key] = program.name;\n            }\n          }\n          await this.createDataPoint(\n            `${haId + rootItem.folder}.${rootItem.key.replace(/\\./g, '_')}`,\n            common,\n            'state',\n            null,\n            true,\n            null,\n          );\n        }\n      }\n    } catch (error) {\n      this.log.error(error);\n      this.log.error(error.stack);\n      this.log.error(url);\n      this.log.error(JSON.stringify(returnValue));\n    }\n  }\n  async updateOptions(haId, url, forceDeletion) {\n    const pre = `${this.name}.${this.instance}`;\n    const states = await this.getStatesAsync(`${pre}.${haId}.programs.*`);\n    if (!states) {\n      this.log.warn(`No states found for: ${pre}.${haId}.programs.*`);\n      return;\n    }\n    const allIds = Object.keys(states);\n    let searchString = 'selected.options.';\n    if (url.indexOf('/active') !== -1) {\n      searchString = 'active.options.';\n      this.log.debug(`search: ${searchString}`);\n      //delete only for active options\n      this.log.debug(`Delete: ${haId}${url.replace(/\\//g, '.')}.options`);\n\n      for (const keyName of allIds) {\n        if (\n          (keyName.indexOf(searchString) !== -1 && keyName.indexOf('BSH_Common_Option') === -1) ||\n          (forceDeletion && keyName.indexOf('BSH_Common_Option_RemainingProgramTime') === -1)\n        ) {\n          this.stateCheck = this.stateCheck.filter(r => r !== keyName);\n          await this.delObjectAsync(keyName.split('.').slice(2).join('.'));\n        } else if (keyName.indexOf('BSH_Common_Option_ProgramProgress') !== -1) {\n          const programProgess = await this.getStateAsync(\n            `${haId}.programs.active.options.BSH_Common_Option_ProgramProgress`,\n          );\n          if (programProgess && programProgess.val !== 100) {\n            await this.setState(`${haId}.programs.active.options.BSH_Common_Option_ProgramProgress`, 100, true);\n          }\n        } else if (keyName.indexOf('BSH_Common_Option_RemainingProgramTime') !== -1) {\n          const remainTime = await this.getStateAsync(\n            `${haId}.programs.active.options.BSH_Common_Option_RemainingProgramTime`,\n          );\n          if (remainTime && remainTime.val !== 0) {\n            await this.setState(`${haId}.programs.active.options.BSH_Common_Option_RemainingProgramTime`, 0, true);\n          }\n        }\n      }\n    }\n    this.setTimeout(() => this.getAPIValues(haId, `${url}/options`), 0); //ToDo Why 0\n  }\n  async putAPIValues(haId, url, data) {\n    this.log.debug(`Put ${JSON.stringify(data)} to ${url} for ${haId}`);\n    if (!(await this.checkBlock())) {\n      return;\n    }\n    let start = 'NOK';\n    if (data && data.data && data.data.key) {\n      if (data.data.key.indexOf('StopProgram') !== -1) {\n        start = 'Stop';\n      } else if (\n        data.data.key.indexOf('Root_ActiveProgram') !== -1 ||\n        data.data.key.indexOf('StartInRelative') !== -1\n      ) {\n        start = 'Stop';\n      }\n    }\n    await this.setLimitCounter('OK', haId, start, url, 'PUT');\n    await this.requestClient({\n      method: 'PUT',\n      url: `https://api.home-connect.com/api/homeappliances/${haId}${url}`,\n      headers: this.headers,\n      data: data,\n    })\n      .then(res => {\n        this.log.debug(`Put data: ${JSON.stringify(res.data)}`);\n        return res.data;\n      })\n      .catch(error => {\n        this.setLimitCounter('ERR', haId, start, null, null);\n        this.log.error(`Put: ${error}`);\n        if (error.response) {\n          if (error.response.headers && error.response.headers['rate-limit-type'] === 'start') {\n            this.log.error(JSON.stringify(error.response.headers));\n            this.log.error(`Block time ${error.response.headers['retry-after']} second(s)`);\n          }\n          if (error.response.status === 409) {\n            this.log.info(\n              'Command cannot be executed for the home appliance, the error response contains the error details',\n            );\n          } else if (error.response.status === 429) {\n            this.log.info('The number of requests for a specific endpoint exceeded the quota of the client');\n          } else if (error.response.status === 403) {\n            this.log.info('Scope has not been granted or home appliance is not assigned to HC account');\n          }\n          this.log.error(JSON.stringify(error.response.data));\n        }\n      });\n  }\n\n  async deleteAPIValues(haId, url) {\n    if (!(await this.checkBlock())) {\n      return;\n    }\n    await this.setLimitCounter('OK', haId, 'Stop', url, 'DELETE');\n    await this.requestClient({\n      method: 'DELETE',\n      url: `https://api.home-connect.com/api/homeappliances/${haId}${url}`,\n      headers: this.headers,\n    })\n      .then(res => {\n        this.log.debug(`deleteAPIValues: ${JSON.stringify(res.data)}`);\n        return res.data;\n      })\n      .catch(error => {\n        this.setLimitCounter('ERR', haId, 'NOK', null, null);\n        this.log.error(`deleteAPIValues: ${error}`);\n        if (error.response) {\n          if (error.response.status === 429) {\n            this.log.info('The maximum number of requests has been reached!');\n            if (error.response.headers) {\n              if (error.response.headers['retry-after']) {\n                this.log.error(`API retry-after: ${this.convertRetryAfter(error.response.headers['retry-after'])}`);\n              }\n            }\n          }\n          if (error.response.status === 403) {\n            this.log.info('Homeconnect API has not the rights for this command and device');\n          }\n          this.log.error(JSON.stringify(error.response.data));\n        }\n      });\n  }\n  async startEventStream() {\n    this.log.debug('Start EventStream');\n    const baseUrl = 'https://api.home-connect.com/api/homeappliances/events';\n    if (this.eventSourceState) {\n      this.eventSourceState.close();\n      this.eventSourceState.removeEventListener('PAIRED', e => this.processEvent(e), false);\n      this.eventSourceState.removeEventListener('DEPAIRED', e => this.processEvent(e), false);\n      this.eventSourceState.removeEventListener('STATUS', e => this.processEvent(e), false);\n      this.eventSourceState.removeEventListener('NOTIFY', e => this.processEvent(e), false);\n      this.eventSourceState.removeEventListener('EVENT', e => this.processEvent(e), false);\n      this.eventSourceState.removeEventListener('CONNECTED', e => this.processEvent(e), false);\n      this.eventSourceState.removeEventListener('DISCONNECTED', e => this.processEvent(e), false);\n      this.eventSourceState.removeEventListener('KEEP-ALIVE', () => this.resetReconnectTimeout(), false);\n    }\n    this.eventSourceState = new EventSource(baseUrl, {\n      fetch: (input, init) =>\n        fetch(input, {\n          ...init,\n          headers: {\n            ...init.headers,\n            Authorization: `Bearer ${this.session.access_token}`,\n            Accept: 'text/event-stream',\n          },\n        }),\n    });\n    // Error handling\n    this.eventSourceState.onerror = err => {\n      if (err.code) {\n        this.log.error(`${err.code} ${err.message}`);\n      } else {\n        this.log.debug(`EventSource error: ${JSON.stringify(err)}`);\n        this.log.debug('Undefined Error from Homeconnect this happens sometimes.');\n      }\n      if (err.code !== undefined) {\n        this.log.error(`Start Event Stream Error: ${JSON.stringify(err)}`);\n        if (err.code === 401) {\n          this.refreshToken();\n          // Most likely the token has expired, try to refresh the token\n          this.log.info('Token abgelaufen');\n        } else if (err.code === 429) {\n          this.log.info('Too many requests. Please wait 24h.');\n        } else {\n          this.log.error(`Error: ${err.code}`);\n          this.log.error(`Error: ${JSON.stringify(err)}`);\n          if (err.code >= 500) {\n            this.log.error('Homeconnect API are not available please try again later');\n          }\n        }\n      }\n    };\n\n    this.eventSourceState.addEventListener('PAIRED', e => this.processEvent(e), false);\n    this.eventSourceState.addEventListener('DEPAIRED', e => this.processEvent(e), false);\n    this.eventSourceState.addEventListener('STATUS', e => this.processEvent(e), false);\n    this.eventSourceState.addEventListener('NOTIFY', e => this.processEvent(e), false);\n    this.eventSourceState.addEventListener('EVENT', e => this.processEvent(e), false);\n    this.eventSourceState.addEventListener('CONNECTED', e => this.processEvent(e), false);\n    this.eventSourceState.addEventListener('DISCONNECTED', e => this.processEvent(e), false);\n    this.eventSourceState.addEventListener(\n      'KEEP-ALIVE',\n      e => {\n        this.resetReconnectTimeout();\n        const val = {\n          type: e.type,\n          data: e.data,\n          lastEventId: e.lastEventId, // is empty...why?\n          timestamp: e.timeStamp,\n          origin: e.origin,\n        };\n        this.log.debug(`KEEP-ALIVE: ${JSON.stringify(val)}`);\n      },\n      false,\n    );\n\n    this.resetReconnectTimeout();\n  }\n  resetReconnectTimeout() {\n    this.reconnectTimeout && this.clearInterval(this.reconnectTimeout);\n    this.reconnectTimeout = this.setInterval(() => {\n      this.log.info('Keep Alive failed Reconnect EventStream');\n      this.startEventStream();\n    }, 70000);\n  }\n\n  async processEvent(msg) {\n    try {\n      this.log.debug(`event: ${JSON.stringify(msg.data)}`);\n      this.log.debug(`eventType: ${JSON.stringify(msg.type)}`);\n      this.log.debug(`lastEventId: ${msg.lastEventId}`);\n      const stream = msg;\n      //eslint-disable-next-line no-useless-escape\n      const lastEventId = stream.lastEventId.replace(/\\.?\\-001*$/, '');\n      if (!stream) {\n        this.log.debug(`No Return: ${stream}`);\n        return;\n      }\n      this.resetReconnectTimeout();\n      if (stream.type == 'DISCONNECTED') {\n        this.log.info(`DISCONNECTED: ${lastEventId}`);\n        this.setState(`${lastEventId}.general.connected`, false, true);\n        this.updateOptions(lastEventId, '/programs/active');\n        return;\n      }\n      if (stream.type == 'CONNECTED' || stream.type == 'PAIRED') {\n        this.log.info(`CONNECTED: ${lastEventId}`);\n        this.setState(`${lastEventId}.general.connected`, true, true);\n        if (this.config.disableFetchConnect) {\n          return;\n        }\n        this.fetchDeviceInformation(lastEventId);\n        return;\n      }\n\n      const parseMsg = msg.data;\n\n      const parseMessage = JSON.parse(parseMsg);\n      for (let element of parseMessage.items) {\n        let haId = parseMessage.haId;\n        //eslint-disable-next-line no-useless-escape\n        haId = haId.replace(/\\.?\\-001*$/, '');\n        let folder;\n        let key;\n        if (stream.type === 'EVENT') {\n          folder = 'events';\n          key = element.key.replace(/\\./g, '_');\n        } else {\n          folder = element.uri.split('/').splice(4);\n          if (folder[folder.length - 1].indexOf('.') != -1) {\n            folder.pop();\n          }\n          folder = folder.join('.');\n          key = element.key.replace(/\\./g, '_');\n        }\n        this.log.debug(`Path: ${haId}.${folder}.${key}:${element.value}`);\n        let value = null;\n        if (element.value !== undefined) {\n          this.log.debug('Set event state ');\n          value = element.value;\n          await this.setState(`${haId}.${folder}.${key}`, element.value, true);\n        }\n        const common = {\n          name: key,\n          type: 'mixed',\n          role: 'state',\n          write: true,\n          read: true,\n        };\n        if (element.unit && element.unit != '') {\n          common.unit = element.unit;\n        }\n        await this.createDataPoint(`${haId}.${folder}.${key}`, common, 'state', value, true, null);\n        if (element.value !== undefined) {\n          this.log.debug('Set event state ');\n          await this.setState(`${haId}.${folder}.${key}`, element.value, true);\n        }\n      }\n    } catch (error) {\n      this.log.error(`Parsemessage: ${error}`);\n      this.log.error(`Error Event: ${JSON.stringify(msg)}`);\n    }\n  }\n\n  async refreshToken() {\n    if (!this.session) {\n      this.log.error('No session found relogin');\n      await this.login();\n      return;\n    }\n    if (!this.checkToken(false)) {\n      return;\n    }\n    this.log.debug('Refresh Token');\n    await this.requestClient({\n      method: 'post',\n      url: 'https://api.home-connect.com/security/oauth/token',\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n      },\n      data: `grant_type=refresh_token&refresh_token=${this.session.refresh_token}`,\n    })\n      .then(res => {\n        this.log.debug(`RefreshToken: ${JSON.stringify(res.data)}`);\n        this.session = res.data;\n        this.headers.authorization = `Bearer ${this.session.access_token}`;\n        this.setState('info.connection', true, true);\n        this.session.next = new Date().getTime() + parseInt(this.session.expires_in) * 1000;\n        //await this.setState('auth.session', { val: this.encrypt(JSON.stringify(this.session)), ack: true });\n        this.setState('auth.session', { val: JSON.stringify(this.session), ack: true });\n      })\n      .catch(error => {\n        if (error.response) {\n          this.log.error(JSON.stringify(error.response.data));\n          if (error.response.status === 429) {\n            this.log.info('The maximum number of requests has been reached!');\n            if (error.response.headers) {\n              if (error.response.headers['retry-after']) {\n                this.log.error(`API retry-after: ${this.convertRetryAfter(error.response.headers['retry-after'])}`);\n              }\n            }\n          }\n        }\n        this.log.error('refresh token failed');\n        this.log.error(error);\n        this.log.error('Restart adapter in 20min');\n        this.reconnectTimeout && this.clearInterval(this.reconnectTimeout);\n        this.reLoginTimeout && this.clearTimeout(this.reLoginTimeout);\n        this.reLoginTimeout = this.setTimeout(\n          async () => {\n            this.restart();\n          },\n          1000 * 60 * 20,\n        );\n      });\n  }\n  extractHidden(body) {\n    const returnObject = {};\n    const matches = this.matchAll(/<input (?=[^>]* name=[\"']([^'\"]*)|)(?=[^>]* value=[\"']([^'\"]*)|)/g, body);\n    for (const match of matches) {\n      returnObject[match[1]] = match[2];\n    }\n    return returnObject;\n  }\n  matchAll(re, str) {\n    let match;\n    const matches = [];\n\n    while ((match = re.exec(str))) {\n      // add all matched groups\n      matches.push(match);\n    }\n\n    return matches;\n  }\n  /**\n   * @param ms milliseconds\n   */\n  sleep(ms) {\n    return new Promise(resolve => {\n      this.sleepTimer = this.setTimeout(() => {\n        resolve(true);\n      }, ms);\n    });\n  }\n  /**\n   * Is called when adapter shuts down - callback has to be called under any circumstances!\n   *\n   * @param {() => void} callback\n   */\n  onUnload(callback) {\n    try {\n      this.setState('info.connection', false, true);\n      //this.refreshStatusInterval && this.clearTimeout(this.refreshStatusInterval);\n      this.reLoginTimeout && this.clearTimeout(this.reLoginTimeout);\n      //this.reconnectInterval && this.clearInterval(this.reconnectInterval);\n      this.refreshTokenInterval && this.clearInterval(this.refreshTokenInterval);\n      this.rateLimitingInterval && this.clearInterval(this.rateLimitingInterval);\n      this.sleepTimer && this.clearTimeout(this.sleepTimer);\n      if (this.eventSourceState) {\n        this.eventSourceState.close();\n        this.eventSourceState.removeEventListener('STATUS', e => this.processEvent(e), false);\n        this.eventSourceState.removeEventListener('NOTIFY', e => this.processEvent(e), false);\n        this.eventSourceState.removeEventListener('EVENT', e => this.processEvent(e), false);\n        this.eventSourceState.removeEventListener('CONNECTED', e => this.processEvent(e), false);\n        this.eventSourceState.removeEventListener('DISCONNECTED', e => this.processEvent(e), false);\n        this.eventSourceState.removeEventListener('KEEP-ALIVE', () => this.resetReconnectTimeout(), false);\n      }\n\n      callback();\n    } catch (e) {\n      this.log.error(`Error onUnload: ${e}`);\n      callback();\n    }\n  }\n\n  /**\n   * Is called if a subscribed state changes\n   *\n   * @param {string} id\n   * @param {ioBroker.State | null | undefined} state\n   */\n  async onStateChange(id, state) {\n    if (state) {\n      if (!state.ack) {\n        const idArray = id.split('.') || [];\n        const commands = idArray.pop();\n        if (commands === 'request_json') {\n          this.sendOwnRequest(idArray[2], state.val);\n          return;\n        } else if (commands === 'response') {\n          return;\n        }\n        const command = commands ? commands.replace(/_/g, '.') : '';\n        const haId = idArray[2];\n        if (state.val != null && !Number.isNaN(state.val) && !Number.isNaN(parseFloat(state.val.toString()))) {\n          state.val = parseFloat(state.val.toString());\n        }\n        if (state.val === 'true') {\n          state.val = true;\n        }\n        if (state.val === 'false') {\n          state.val = false;\n        }\n        if (id.indexOf('.commands.') !== -1) {\n          this.log.debug(`onStateChange - ${id} ${state.val}`);\n          if (id.indexOf('StopProgram') !== -1 && state.val) {\n            this.deleteAPIValues(haId, '/programs/active');\n          } else {\n            const data = {\n              data: {\n                key: command,\n                value: state.val,\n              },\n            };\n\n            this.putAPIValues(haId, `/commands/${command}`, data).catch(() => {\n              this.log.error(`Put value failed ${haId}/commands/${command}${JSON.stringify(data)}`);\n              this.log.error(`Original state ${id} change: ${JSON.stringify(state)}`);\n            });\n          }\n        }\n        if (id.indexOf('.settings.') !== -1) {\n          const data = {\n            data: {\n              key: command,\n              value: state.val,\n              type: command,\n            },\n          };\n\n          this.putAPIValues(haId, `/settings/${command}`, data);\n        }\n        if (id.indexOf('.options.') !== -1) {\n          const data = {\n            data: {\n              key: command,\n              value: state.val,\n            },\n          };\n          if (id.indexOf('selected') !== -1) {\n            idArray.pop();\n          }\n          const folder = idArray.slice(3, idArray.length).join('/');\n          if (\n            data.data.key === 'BSH.Common.Option.StartInRelative' ||\n            data.data.key === 'BSH.Common.Option.FinishInRelative'\n          ) {\n            this.log.warn('Relative time cannot be changed here. Please use the specific program options.');\n          }\n\n          this.putAPIValues(haId, `/${folder}/${command}`, data);\n        }\n        if (id.indexOf('BSH_Common_Root_') !== -1) {\n          const pre = `${this.name}.${this.instance}`;\n          if (!state.val) {\n            this.log.warn(`No state val: ${JSON.stringify(state)}`);\n            return;\n          }\n          if (state.val.toString().indexOf('.') === -1) {\n            this.log.warn(`No valid state val: ${JSON.stringify(state)}`);\n            return;\n          }\n          const key = state.val.toString().split('.').pop();\n          const states = await this.getStatesAsync(`${pre}.${haId}.programs.selected.options.${key}.*`);\n          if (typeof states !== 'object') {\n            this.log.error(`Missing States: ${pre}.${haId}.programs.selected.options.${key}.*`);\n            return;\n          }\n          const allIds = Object.keys(states);\n          const options = [];\n          for (const keyName of allIds) {\n            if (\n              keyName.indexOf('BSH_Common_Option_ProgramProgress') === -1 &&\n              keyName.indexOf('BSH_Common_Option_RemainingProgramTime') === -1\n            ) {\n              const idArray = keyName.split('.');\n              const commandOptions = idArray.pop();\n              const commandOption = commandOptions ? commandOptions.replace(/_/g, '.') : '';\n              if (\n                ((this.availableProgramOptions[state.val] &&\n                  this.availableProgramOptions[state.val].includes(commandOption)) ||\n                  commandOption === 'BSH.Common.Option.StartInRelative') &&\n                states &&\n                states[keyName] !== null\n              ) {\n                if (\n                  (commandOption === 'BSH.Common.Option.StartInRelative' ||\n                    commandOption === 'BSH.Common.Option.FinishInRelative') &&\n                  command === 'BSH.Common.Root.SelectedProgram'\n                ) {\n                  this.log.debug('Relative time cannot be changed here. Please use the specific program options.');\n                } else {\n                  options.push({\n                    key: commandOption,\n                    value: states[keyName].val,\n                  });\n                }\n              } else {\n                this.log.debug(`Option ${commandOption} is not available for ${state.val}`);\n                this.log.debug(`Available options: ${JSON.stringify(this.availableProgramOptions[state.val])}`);\n              }\n            }\n          }\n          const data = {\n            data: {\n              key: state.val,\n              options: options,\n            },\n          };\n          if (id.indexOf('Active') !== -1) {\n            this.putAPIValues(haId, '/programs/active', data)\n              .catch(() => {\n                this.log.info(\"Programm doesn't start with options. Try again without selected options.\");\n                this.putAPIValues(haId, '/programs/active', {\n                  data: {\n                    key: state.val,\n                  },\n                }).catch(() => {\n                  this.log.error(`Put active failed ${haId}${state.val}`);\n                });\n              })\n              .then(() => this.updateOptions(haId, '/programs/active'))\n              .catch(() => {\n                this.log.error('Error update active program');\n              });\n          }\n          if (id.indexOf('Selected') !== -1) {\n            if (state.val) {\n              this.currentSelected[haId] = { key: state.val };\n\n              this.putAPIValues(haId, '/programs/selected', data)\n                .then(\n                  () => {\n                    this.updateOptions(haId, '/programs/selected');\n                  },\n                  () => {\n                    this.log.warn('Setting selected program was not succesful');\n                  },\n                )\n                .catch(() => {\n                  this.log.debug('No program selected found');\n                });\n            } else {\n              this.log.warn(`No state val: ${JSON.stringify(state)}`);\n            }\n          }\n        }\n      } else {\n        const idArray = id.split('.');\n        const commands = idArray.pop();\n        const command = commands ? commands.replace(/_/g, '.') : '';\n        const stop = ['isBlocked', 'limitJson', 'reason', 'connection', 'session', 'response', 'request.json'];\n        if (stop.includes(command)) {\n          this.log.debug(`Catch state - ${id} - ${command}`);\n          return;\n        }\n        const haId = idArray[2];\n        this.log.debug(`State changed: ${id} ${JSON.stringify(state)} ${command}`);\n        if (id.indexOf('BSH_Common_Root_') !== -1) {\n          if (id.indexOf('Active') !== -1) {\n            this.updateOptions(haId, '/programs/active');\n          }\n          if (id.indexOf('Selected') !== -1) {\n            if (state && state.val) {\n              this.currentSelected[haId] = { key: state.val };\n            } else {\n              this.log.debug(`Selected program is empty: ${JSON.stringify(state)}`);\n            }\n\n            this.updateOptions(haId, '/programs/selected');\n          }\n        }\n        if (id.indexOf('BSH_Common_Status_OperationState') !== -1) {\n          if (\n            state.val &&\n            typeof state.val === 'string' &&\n            (state.val.indexOf('.Finished') !== -1 || state.val.indexOf('.Aborting') !== -1)\n          ) {\n            const remainTime = await this.getStateAsync(\n              `${haId}.programs.active.options.BSH_Common_Option_RemainingProgramTime`,\n            );\n            if (remainTime && remainTime.val !== 0) {\n              await this.setState(`${haId}.programs.active.options.BSH_Common_Option_RemainingProgramTime`, 0, true);\n            }\n            const programProgess = await this.getStateAsync(\n              `${haId}.programs.active.options.BSH_Common_Option_ProgramProgress`,\n            );\n            if (programProgess && programProgess.val !== 100) {\n              await this.setState(`${haId}.programs.active.options.BSH_Common_Option_ProgramProgress`, 100, true);\n            }\n          }\n        }\n        if (id.indexOf('.options.') !== -1 || id.indexOf('.events.') !== -1 || id.indexOf('.status.') !== -1) {\n          if (\n            id.indexOf('BSH_Common_Option') === -1 &&\n            state &&\n            state.val &&\n            state.val.toString().indexOf('.') !== -1\n          ) {\n            this.getObject(id, async (err, obj) => {\n              if (obj && state.val != null) {\n                const common = obj.common;\n                const valArray = state.val.toString().split('.');\n                common.states = {};\n                common.states[state.val.toString()] = valArray[valArray.length - 1];\n                this.log.debug(`Extend common option: ${id}`);\n                await this.createDataPoint(id, common, 'state', null, true, null);\n              }\n            });\n          }\n        }\n      }\n    }\n  }\n  async sendOwnRequest(haId, json) {\n    if (json && json.startsWith('{')) {\n      let val = {};\n      try {\n        val = JSON.parse(json);\n      } catch (e) {\n        this.log.error(e);\n        return;\n      }\n      if (!val && !val.methode) {\n        this.log.error(`Missing methode!`);\n        return;\n      }\n      if (!val && !val.url) {\n        this.log.error(`Missing URL!`);\n        return;\n      }\n      let data = {};\n      if (val && val.data) {\n        data = { data: val.data };\n        return;\n      }\n      if (!(await this.checkBlock())) {\n        return;\n      }\n      let start = 'NOK';\n      if (data && data.data && data.data.key) {\n        if (\n          data.data.key.indexOf('StopProgram') !== -1 ||\n          data.data.key.indexOf('Root_ActiveProgram') !== -1 ||\n          data.data.key.indexOf('StartInRelative') !== -1\n        ) {\n          start = 'Stop';\n        }\n      }\n      await this.setLimitCounter('OK', haId, start, val.url, val.methode);\n      const resp = await this.requestClient({\n        method: val.methode,\n        url: `https://api.home-connect.com/api/homeappliances/${val.url}`,\n        headers: this.headers,\n        ...data,\n      })\n        .then(res => {\n          return res.data;\n        })\n        .catch(error => {\n          this.setLimitCounter('ERR', haId, start, null, null);\n          if (error.response) {\n            if (error.response.headers && error.response.headers['rate-limit-type'] === 'start') {\n              this.log.error(JSON.stringify(error.response.headers));\n              this.log.error(`Block time ${error.response.headers['retry-after']} second(s)`);\n              return { error: error.message, data: error.response.data, header: error.response.headers };\n            }\n            if (error.response.status === 409) {\n              this.log.info(\n                'Command cannot be executed for the home appliance, the error response contains the error details',\n              );\n            } else if (error.response.status === 429) {\n              this.log.info('The number of requests for a specific endpoint exceeded the quota of the client');\n            } else if (error.response.status === 403) {\n              this.log.info('Scope has not been granted or home appliance is not assigned to HC account');\n            }\n            this.log.error(JSON.stringify(error.response.data));\n            return { error: error.message, data: error.response.data };\n          }\n          return { error: error.message };\n        });\n      await this.setState(`${haId}.own_request.response`, { val: JSON.stringify(resp), ack: true });\n      await this.setState(`${haId}.own_request.request_json`, { val: json, ack: true });\n    }\n  }\n  convertRetryAfter(inputSeconds) {\n    try {\n      const days = Math.floor(inputSeconds / (60 * 60 * 24));\n      const hours = Math.floor((inputSeconds % (60 * 60 * 24)) / (60 * 60));\n      const minutes = Math.floor(((inputSeconds % (60 * 60 * 24)) % (60 * 60)) / 60);\n      const seconds = Math.floor(((inputSeconds % (60 * 60 * 24)) % (60 * 60)) % 60);\n      let day = '';\n      if (days > 0) {\n        day = `${days}d - `;\n      }\n      return (\n        day +\n        [hours, minutes, seconds]\n          .map(v => (v < 10 ? `0${v}` : v))\n          .filter((v, i) => v !== '00' || i > 0)\n          .join(':')\n      );\n    } catch {\n      return 0;\n    }\n  }\n  getWeek(timestamp) {\n    if (typeof timestamp === 'number' && timestamp === 0) {\n      return '0-0';\n    }\n    const target = timestamp != null ? new Date(timestamp) : new Date();\n    const getDay = target.getDay();\n    const dayNr = (target.getDay() + 6) % 7;\n    target.setDate(target.getDate() - dayNr + 3);\n    const jan4 = new Date(target.getFullYear(), 0, 4);\n    const dayDiff = (target.getTime() - jan4.getTime()) / 86400000;\n    if (new Date(target.getFullYear(), 0, 1).getDay() < 5) {\n      return `${1 + Math.ceil(dayDiff / 7)}-${getDay}`;\n    }\n    return `${Math.ceil(dayDiff / 7)}-${getDay}`;\n  }\n  async setTokenJson(block, reason) {\n    await this.setState(`rateTokenLimit.limitJson`, { val: JSON.stringify(this.tokenRateLimiting), ack: true });\n    await this.setState(`rateTokenLimit.isBlocked`, { val: block, ack: true });\n    await this.setState(`rateTokenLimit.reason`, { val: reason, ack: true });\n  }\n  async setLimitJson(block, reason) {\n    await this.setState(`rateLimit.limitJson`, { val: JSON.stringify(this.rateLimiting), ack: true });\n    await this.setState(`rateLimit.isBlocked`, { val: block, ack: true });\n    await this.setState(`rateLimit.reason`, { val: reason, ack: true });\n  }\n  async setErrorResponse(update) {\n    try {\n      this.log.debug(this.rateLimiting.requests.length);\n      if (this.rateLimiting.requests.length > 0) {\n        const last = this.rateLimiting.requests.length - 1;\n        this.rateLimiting.requests[last].response = 'Error';\n      }\n    } catch (e) {\n      this.log.warn(`Cannot change response - ${e}`);\n    }\n    if (update) {\n      await this.setState(`rateLimit.limitJson`, { val: JSON.stringify(this.rateLimiting), ack: true });\n    }\n  }\n  /**\n   * Is program for your type available\n   *\n   * @param {string} haID\n   */\n  isPrograms(haID) {\n    return ['Cooktop', 'FridgeFreezer', 'WineCooler', 'Freezer', 'Refrigerator', 'CookProcessor'].includes(\n      this.typeJson[haID],\n    );\n  }\n}\n\nif (require.main !== module) {\n  // Export the constructor in compact mode\n  /**\n   * @param {Partial<utils.AdapterOptions>} [options={}]\n   */\n  module.exports = options => new Homeconnect(options);\n} else {\n  // otherwise start the instance directly\n  new Homeconnect();\n}\n"]}