{"version":3,"sources":["jsdelivr-header.js","/npm/@romacv/homebridge-miot@1.5.3/index.js"],"names":[],"mappings":"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","file":"/npm/@romacv/homebridge-miot@1.5.3/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.37.0.\n * Original file: /npm/@romacv/homebridge-miot@1.5.3/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","const fs = require('fs').promises;\nconst MiotDevice = require('./lib/protocol/MiotDevice.js');\nconst DeviceFactory = require('./lib/factories/DeviceFactory.js');\nconst DevTypes = require('./lib/constants/DevTypes.js');\nconst Constants = require('./lib/constants/Constants.js');\nconst Logger = require('./lib/utils/Logger.js');\nconst Events = require('./lib/constants/Events.js');\n\nlet Service, Characteristic, Homebridge, Accessory;\n\nconst PLUGIN_NAME = 'homebridge-miot';\nconst PLATFORM_NAME = 'miot';\nconst PLUGIN_VERSION = '1.5.2';\n\nmodule.exports = function(homebridge) {\n  Service = homebridge.hap.Service;\n  Characteristic = homebridge.hap.Characteristic;\n  Homebridge = homebridge;\n  Accessory = homebridge.platformAccessory;\n  homebridge.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, miotPlatform, true);\n};\n\n\nclass miotDeviceController {\n  constructor(log, config, globalmicloudconfig, api) {\n    this.log = log;\n    this.config = config;\n    this.api = api;\n\n    this.logger = new Logger(log, config.name);\n\n    // check if we have mandatory device info\n    try {\n      if (!config.ip) throw new Error(`'ip' is required but not defined for ${config.name}!`);\n      if (!config.token) throw new Error(`'token' is required but not defined for ${config.name}!`);\n    } catch (error) {\n      this.logger.error(error);\n      this.logger.error(`Failed to create platform device, missing mandatory information!`, CLASS_LOG_PREFIX);\n      this.logger.error(`Please check your device config!`);\n      return;\n    }\n\n    // configuration\n    this.name = config.name;\n    this.ip = config.ip;\n    this.token = config.token;\n    this.deviceId = config.deviceId;\n    this.model = config.model;\n    this.miCloudConfig = {};\n    this.miCloudConfig.global = globalmicloudconfig;\n    this.miCloudConfig.device = config.micloud;\n    this.pollingInterval = config.pollingInterval || Constants.DEFAULT_POLLING_INTERVAL;\n    if (this.pollingInterval < 500) {\n      this.pollingInterval = this.pollingInterval * 1000; // if less then 500 then probably those are seconds so multiply by 1000 to convert to miliseconds\n    }\n    this.propertyChunkSize = config.propertyChunkSize;\n    this.isCustomAccessory = config.customAccessory || false;\n    this.prefsDir = config.prefsDir || api.user.storagePath() + '/.xiaomiMiot/';\n    this.deepDebugLog = config.deepDebugLog;\n    if (this.deepDebugLog === undefined) {\n      this.deepDebugLog = false;\n    }\n\n    this.logger.info(`Got device configuration, initializing device with name: ${this.name}`);\n\n    // set deep debug log\n    this.logger.setDeepDebugLogEnabled(this.deepDebugLog);\n\n    // check if prefs directory ends with a /, if not then add it\n    if (this.prefsDir.endsWith('/') === false) {\n      this.prefsDir = this.prefsDir + '/';\n    }\n\n    //spec dir to store device specs\n    this.specDir = this.prefsDir + 'spec/';\n\n    // create device model info file name\n    this.deviceInfoFile = this.prefsDir + 'info_' + this.ip.split('.').join('') + '_' + this.token;\n\n    // generate uuid\n    if (this.deviceId) {\n      this.UUID = Homebridge.hap.uuid.generate(this.token + this.ip + this.deviceId + PLATFORM_NAME);\n    } else {\n      this.UUID = Homebridge.hap.uuid.generate(this.token + this.ip + PLATFORM_NAME);\n    }\n\n    // prepare variables\n    this.miotDevice = undefined;\n    this.device = undefined;\n    this.cachedDeviceInfo = {};\n\n    //restored cashed accessory\n    this.restoredCachedAccessory = null;\n  }\n\n\n  /*----------========== SETUP ==========----------*/\n\n  async setupController() {\n    // check if the preferences directory exists, if not then create it\n    await this._createDirIfNeeded(this.prefsDir);\n\n    // check if the spec directory exists, if not then create it recursively\n    await this._createDirIfNeeded(this.specDir);\n\n    // first try to load cached device info\n    await this._loadDeviceInfo();\n\n    //init the device and start the device discovery\n    this._initMiotDevice();\n  }\n\n  async _initMiotDevice() {\n    // if the user specified a model then use that, else try to get cached model\n    let deviceId = this.deviceId || this.cachedDeviceInfo.deviceId;\n    let model = this.model || this.cachedDeviceInfo.model;\n\n    this.miotDevice = new MiotDevice(this.ip, this.token, deviceId, model, this.name, this.logger);\n    this.miotDevice.setPollingInterval(this.pollingInterval);\n    this.miotDevice.setMiCloudConfig(this.miCloudConfig);\n\n    this.miotDevice.on(Events.MIOT_DEVICE_IDENTIFIED, async (miotDevice) => {\n      // init the actual device\n      this._initDevice(miotDevice);\n    });\n\n    this.miotDevice.on(Events.MIOT_DEVICE_SPEC_FETCHED, (miotDevice) => {\n      // save miot spec\n      this._saveMiotSpec(miotDevice);\n    });\n\n    this.miotDevice.on(Events.MIOT_DEVICE_CONNECTED, (miotDevice) => {\n      // save device information\n      this._saveDeviceInfo(miotDevice);\n    });\n\n    this.miotDevice.identify();\n  }\n\n  async _initDevice(miotDevice) {\n    if (!this.device) {\n      this.logger.info('Initializing device!');\n      this.device = await DeviceFactory.createDevice(miotDevice, this.specDir, this.name, this.isCustomAccessory, this.logger);\n      if (this.device) {\n        await this.device.initDevice(this.propertyChunkSize);\n        if (this.device.getType() === DevTypes.UNKNOWN) {\n          this.logger.warn(`Device not supported! Using a generic device with limited properties! Consider requesting device support!`);\n        } else if (this.device.getType() === DevTypes.CUSTOM) {\n          this.logger.info(`Successfully created a custom accessory device! It is a ${this.device.getDeviceName()}. Make sure to configure the properties and actions!`);\n        } else {\n          this.logger.info(`Successfully created a ${this.device.getType()} device! It is a ${this.device.getDeviceName()}.`);\n        }\n        this.prepareAccessoryAndStartPolling();\n      } else {\n        this.logger.warn(`Something went wrong during device creation! Initialization failed, cannot create device!`);\n      }\n    }\n  }\n\n\n  /*----------========== SETUP SERVICES ==========----------*/\n\n  prepareAccessoryAndStartPolling() {\n    // first unregister a cached accessory if present!\n    if (this.restoredCachedAccessory) {\n      this.logger.debug('Found cached accessory for this device! Unregistering it first!');\n      this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [this.restoredCachedAccessory]);\n      this.restoredCachedAccessory = null;\n    }\n\n    // init the accessory\n    this.device.initDeviceAccessory(this.getAccessoryUuid(), this.config, this.api, this.cachedDeviceInfo);\n\n    if (this.device.getAccessoryWrapper() && this.device.getAccessories().length > 0) {\n      this.logger.info(`Registering ${this.device.getAccessories().length} accessories!`);\n      this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, this.device.getAccessories());\n      this.logger.info('Everything looks good! Initiating property polling!');\n      this.miotDevice.startPropertyPolling();\n    }\n  }\n\n  /*----------========== PUBLIC ==========----------*/\n\n  getAccessoryUuid() {\n    return this.UUID;\n  }\n\n  setRestoredCachedAccessory(accessory) {\n    this.restoredCachedAccessory = accessory;\n  }\n\n\n  /*----------========== HELPERS ==========----------*/\n\n  _saveDeviceInfo(miotDevice) {\n    if (miotDevice) {\n      this.cachedDeviceInfo.model = miotDevice.getModel();\n      this.cachedDeviceInfo.deviceId = miotDevice.getDeviceId();\n      this.cachedDeviceInfo.firmwareRev = miotDevice.getFirmwareRevision();\n      const deviceInfo = JSON.stringify(this.cachedDeviceInfo);\n      fs.writeFile(this.deviceInfoFile, deviceInfo, 'utf8').then(() => {\n        this.logger.debug('Successfully saved device info!');\n      }).catch((err) => {\n        this.logger.debug(`Could not write device info! Error: ${err}`);\n      });\n    }\n  }\n\n  async _loadDeviceInfo() {\n    try {\n      const deviceInfo = await fs.readFile(this.deviceInfoFile, 'utf8');\n      if (deviceInfo) {\n        this.cachedDeviceInfo = JSON.parse(deviceInfo);\n        this.logger.debug(`Found cached device information: ${this.cachedDeviceInfo.model}`);\n      }\n    } catch (err) {\n      this.logger.debug('No cached device info found!');\n    }\n  }\n\n  _saveMiotSpec(miotDevice) {\n    if (miotDevice && miotDevice.getMiotSpec()) {\n      let fileName = this.specDir + miotDevice.getModel() + '.spec.json';\n      const miotSpec = JSON.stringify(miotDevice.getMiotSpec(), null, 2);\n      fs.writeFile(fileName, miotSpec, 'utf8').then(() => {\n        this.logger.debug('Successfully saved device miot spec!');\n      }).catch((err) => {\n        this.logger.debug(`Could not save device miot spec! Error: ${err}`);\n      });\n    }\n  }\n\n  async _createDirIfNeeded(dir) {\n    try {\n      await fs.access(dir)\n    } catch (err) {\n      this.logger.debug(`Directory ${dir} is missing! Creating!`);\n      await fs.mkdir(dir, {\n        recursive: true\n      });\n    }\n  }\n\n}\n\n\n/*----------========== PLATFORM STUFF ==========----------*/\nclass miotPlatform {\n  constructor(log, config, api) {\n\n    this.cachedAccessories = [];\n    this.log = log;\n    this.api = api;\n    this.config = config;\n\n    if (this.api) {\n      /*\n       * When this event is fired, homebridge restored all cached accessories from disk and did call their respective\n       * `configureAccessory` method for all of them. Dynamic Platform plugins should only register new accessories\n       * after this event was fired, in order to ensure they weren't added to homebridge already.\n       * This event can also be used to start discovery of new accessories.\n       */\n      this.api.on(\"didFinishLaunching\", () => {\n        this.initDevices();\n      });\n    }\n\n  }\n\n  /*\n   * This function is invoked when homebridge restores cached accessories from disk at startup.\n   * It should be used to setup event handlers for characteristics and update respective values.\n   */\n  configureAccessory(accessory) {\n    this.log.debug(`Found cached accessory ${accessory.displayName}`);\n    this.cachedAccessories.push(accessory);\n  }\n\n  // ------------ CUSTOM METHODS ------------\n\n  initDevices() {\n    this.log.info('Initializing devices');\n\n    // read from config.devices\n    if (this.config.devices && Array.isArray(this.config.devices)) {\n      for (let deviceConfig of this.config.devices) {\n        if (deviceConfig) {\n          this.initDevice(deviceConfig);\n        }\n      }\n    } else if (this.config.devices) {\n      this.log.info(`The devices property is not of type array. Cannot initialize. Type: ${typeof this.config.devices}`);\n    }\n\n    if (!this.config.devices && !this.config.fans) {\n      this.log.info('-------------------------------------------');\n      this.log.info('No device configuration found');\n      this.log.info('Missing devices in your platform config');\n      this.log.info('-------------------------------------------');\n    }\n\n    // remove all accessories which are still left over\n    this.removeAccessories();\n\n  }\n\n  initDevice(deviceConfig) {\n    const newDevCtrl = new miotDeviceController(this.log, deviceConfig, this.config.micloud, this.api);\n    const restoredAccessory = this.cachedAccessories.find(accessory => accessory.UUID === newDevCtrl.getAccessoryUuid());\n    if (restoredAccessory) {\n      newDevCtrl.setRestoredCachedAccessory(restoredAccessory);\n      this.cachedAccessories = this.cachedAccessories.filter(item => item !== restoredAccessory); // remove the cached accessory from the list since the controller will remove it later.\n    }\n    newDevCtrl.setupController(); // begin the controller setup\n  }\n\n  removeAccessories() {\n    if (this.cachedAccessories && this.cachedAccessories.length > 0) {\n      // we don't have any special identifiers, we just remove all our accessories\n      this.log.debug('Removing all cached accessories');\n      this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, this.cachedAccessories);\n      this.cachedAccessories = []; // clear out the array\n    } else {\n      this.log.debug('No accessories to remove!');\n    }\n  }\n\n  removeAccessory(accessory) {\n    this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);\n    this.cachedAccessories = this.cachedAccessories.filter(item => item !== accessory);\n  }\n\n\n}\n"]}