homebridge#Logger TypeScript Examples

The following examples show how to use homebridge#Logger. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: platform.ts    From homebridge-vieramatic with Apache License 2.0 6 votes vote down vote up
constructor(
    readonly log: Logger,
    private readonly config: PlatformConfig,
    private readonly api: API
  ) {
    this.storage = new Storage(api)
    this.Characteristic = this.api.hap.Characteristic
    this.Service = this.api.hap.Service

    this.log.debug('Finished initializing platform:', this.config.platform)

    this.api.on('didFinishLaunching', async () => {
      log.debug('Executed didFinishLaunching callback')
      await this.discoverDevices()
    })
  }
Example #2
Source File: auth.ts    From homebridge-lg-thinq-ac with Apache License 2.0 6 votes vote down vote up
constructor(logger: Logger, thinqConfig: ThinqConfig, state?: string) {
    this.log = logger
    this.authState = state || uuidv4()
    this.thinqConfig = thinqConfig
    this.auth = new ClientOAuth2({
      clientId: THINQ_CLIENT_ID,
      redirectUri: this.thinqConfig.redirectUri,
      accessTokenUri: this.thinqConfig.accessTokenUri,
      authorizationUri: this.thinqConfig.authorizationUri,
      state: this.authState,
    })
  }
Example #3
Source File: platform.ts    From homebridge-screenlogic with MIT License 6 votes vote down vote up
constructor(public readonly log: Logger, config: PlatformConfig, public readonly api: API) {
    this.log.debug('Finished initializing platform', PLATFORM_NAME)

    this.config = config as ScreenLogicPlatformConfig
    // do this first to make sure we have proper defaults moving forward
    this.applyConfigDefaults(config)

    this.controller = new Controller({
      log: this.log,
      ip_address: this.config.ip_address,
      port: this.config.port,
      username: this.config.username,
      password: this.config.password,
    })

    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on('didFinishLaunching', () => {
      log.debug('Executed didFinishLaunching callback')
      // run the method to discover / register your devices as accessories
      this.discoverDevices(0)
    })
  }
Example #4
Source File: platform.ts    From homebridge-tuya-ir with Apache License 2.0 6 votes vote down vote up
constructor(
    public readonly log: Logger,
    public readonly config: PlatformConfig,
    public readonly api: API,
  ) {
    this.log.debug('Finished initializing platform:', this.config.name);


    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on('didFinishLaunching', () => {
      log.debug('Executed didFinishLaunching callback');
      // run the method to discover / register your devices as accessories
      this.discoverDevices();
    });
  }
Example #5
Source File: remote.ts    From homebridge-samsungtv-control2 with MIT License 6 votes vote down vote up
getPairing = async (config: DeviceConfig, log: Logger) => {
  const { token, modelName } = config
  if (token) {
    return token
  }
  const model = parseSerialNumber(modelName)
  const { year = 2013 } = model || {}
  const supportsLegacy = typeof year === `number` && year < 2014
  if (supportsLegacy) {
    log.debug(
      `${config.name} - This TV probably won't need to be paired since it is from ${year} and should support the legacy protocol.` +
        chalk`If you can't control it you still can try pairing it however with {blue npx ${PLUGIN_NAME} pair2 ${config.lastKnownIp} ${config.mac}}`,
    )
    return null
  }
  const { yearKey } = model || {}
  if (yearKey === `J` || yearKey === `H`) {
    log.info(
      `${config.name} - This TV seems to be a ${yearKey}-Series.` +
        chalk`Please run {blue npx ${PLUGIN_NAME} pair1 ${config.lastKnownIp} ${config.mac}} to get a pairing token.`,
    )
  } else {
    log.info(
      chalk`${config.name} - Please run {blue npx ${PLUGIN_NAME} pair2 ${config.lastKnownIp} ${config.mac}} or` +
        chalk`{blue npx ${PLUGIN_NAME} pair1 ${config.lastKnownIp} ${config.mac}} to get a pairing token.`,
    )
  }
  return null
}
Example #6
Source File: platform.ts    From homebridge-zigbee-nt with Apache License 2.0 6 votes vote down vote up
constructor(
    public readonly log: Logger,
    public readonly config: ZigBeeNTPlatformConfig,
    public readonly api: API
  ) {
    const packageJson = JSON.parse(
      fs.readFileSync(`${path.resolve(__dirname, '../package.json')}`, 'utf-8')
    );
    this.accessories = new Map<string, PlatformAccessory>();
    this.homekitAccessories = new Map<string, ZigBeeAccessory>();
    this.permitJoinAccessory = null;
    this.PlatformAccessory = this.api.platformAccessory;
    this.log.info(
      `Initializing platform: ${this.config.name} - v${packageJson.version} (API v${api.version})`
    );
    if (config.devices) {
      config.devices.forEach(config => {
        this.log.info(
          `Registering custom configured device ${config.manufacturer} - ${config.models.join(
            ', '
          )}`
        );
        registerAccessoryFactory(
          config.manufacturer,
          config.models,
          (
            platform: ZigbeeNTHomebridgePlatform,
            accessory: PlatformAccessory,
            client: ZigBeeClient,
            device: Device
          ) => new ConfigurableAccessory(platform, accessory, client, device, config.services)
        );
      });
    }
    this.api.on(APIEvent.DID_FINISH_LAUNCHING, () => this.startZigBee());
    this.api.on(APIEvent.SHUTDOWN, () => this.stopZigbee());
  }
Example #7
Source File: wiz.ts    From homebridge-wiz-lan with Apache License 2.0 6 votes vote down vote up
constructor(
    public readonly log: Logger,
    public readonly config: Config,
    public readonly api: API
  ) {
    this.socket = createSocket(this);

    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on("didFinishLaunching", () => {
      log.debug("Executed didFinishLaunching callback");
      // run the method to discover / register your devices as accessories
      bindSocket(this, () => {
        registerDiscoveryHandler(this, this.tryAddDevice.bind(this));
        sendDiscoveryBroadcast(this);
      });
    });
  }
Example #8
Source File: platform.ts    From homebridge-konnected with MIT License 6 votes vote down vote up
constructor(public readonly log: Logger, public readonly config: PlatformConfig, public readonly api: API) {
    this.log.debug('Finished initializing platform');

    // Homebridge looks for and fires this event when it has retrieved all cached accessories from disk
    // this event is also used to init other methods for this plugin
    this.api.on('didFinishLaunching', () => {
      log.debug('Executed didFinishLaunching callback. Accessories retreived from cache...');

      // run the listening server & register the security system
      this.listeningServer();
      this.registerSecuritySystem();
      this.discoverPanels();
    });
  }
Example #9
Source File: platform.ts    From homebridge-plugin-template with Apache License 2.0 6 votes vote down vote up
constructor(
    public readonly log: Logger,
    public readonly config: PlatformConfig,
    public readonly api: API,
  ) {
    this.log.debug('Finished initializing platform:', this.config.name);

    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on('didFinishLaunching', () => {
      log.debug('Executed didFinishLaunching callback');
      // run the method to discover / register your devices as accessories
      this.discoverDevices();
    });
  }
Example #10
Source File: platform.ts    From homebridge-iRobot with Apache License 2.0 6 votes vote down vote up
constructor(
    public readonly log: Logger,
    public readonly config: PlatformConfig,
    public readonly api: API,
  ) {
    this.log.debug('Finished initializing platform:', this.config.name);

    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on('didFinishLaunching', () => {
      log.debug('Executed didFinishLaunching callback');
      // run the method to discover / register your devices as accessories
      this.discoverDevices();
    });
  }
Example #11
Source File: platform.ts    From homebridge-plugin-eufy-security with Apache License 2.0 6 votes vote down vote up
constructor(
    public readonly log: Logger,
    config: PlatformConfig,
    public readonly api: API,
  ) {
    this.config = config as EufyPlatformConfig;
    // this.log.debug('Config', this.config);
    this.log.debug('Finished initializing platform:', this.config.platform);

    this.httpService = new HttpService(this.config.username, this.config.password);

    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on('didFinishLaunching', async () => {
      if (this.config.enablePush) {
        this.log.info('push client enabled');
        await this.setupPushClient();
      } else {
        this.log.info('push client disabled');
      }

      log.debug('Executed didFinishLaunching callback');
      // run the method to discover / register your devices as accessories

      try {
        this.discoverDevices();
      } catch(error) {
        this.log.error('error while discovering devices');
        this.log.error(error);
      }
    });
  }
Example #12
Source File: platform.ts    From homebridge-plugin-govee with Apache License 2.0 6 votes vote down vote up
constructor(
    public readonly log: Logger,
    public readonly config: PlatformConfig,
    public readonly api: API
  ) {
    this.log.info("Finished initializing platform:", this.config.name);

    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on("didFinishLaunching", () => {
      log.debug("Executed didFinishLaunching callback");
      // run the method to discover / register your devices as accessories

      this.platformStatus = APIEvent.DID_FINISH_LAUNCHING;

      this.discoverDevices();
    });

    this.api.on("shutdown", () => {
      this.platformStatus = APIEvent.SHUTDOWN;
    });
  }
Example #13
Source File: p110.ts    From homebridge-tapo-p100 with Apache License 2.0 6 votes vote down vote up
constructor(
        public readonly log: Logger,
        public readonly ipAddress: string,
        public readonly email: string,
        public readonly password: string,
        public readonly timeout: number,
  ) {
    super(log, ipAddress, email, password, timeout);
    this.log.debug('Constructing P110 on host: ' + ipAddress);
  }
Example #14
Source File: viera.ts    From homebridge-vieramatic with Apache License 2.0 6 votes vote down vote up
private constructor(ip: string, log: Logger | Console) {
    this.address = ip
    this.log = log

    this.#client = got.extend({
      headers: {
        Accept: 'application/xml',
        'Cache-Control': 'no-cache',
        'Content-Type': 'application/xml; charset="utf-8"',
        Host: `${this.address}:${VieraTV.port}`,
        Pragma: 'no-cache'
      },
      prefixUrl: `http://${this.address}:${VieraTV.port}`,
      retry: { limit: 0 },
      timeout: { request: 1500 }
    })
  }
Example #15
Source File: platform.ts    From HomebridgeMagicHome-DynamicPlatform with Apache License 2.0 6 votes vote down vote up
constructor(
    public readonly hbLogger: Logger,
    public readonly config: PlatformConfig,
    public readonly api: API,
  ) {
    if (this.config.advancedOptions.logLevel) {
      this.logs = new Logs(hbLogger, this.config.advancedOptions.logLevel);
    } else {
      this.logs = new Logs(hbLogger);
    }

    //this.logs = getLogger();
    this.logs.warn('Finished initializing homebridge-magichome-dynamic-platform %o', loadJson<any>(join(__dirname, '../package.json'), {}).version);
    this.logs.info('If this plugin brings you joy, consider visiting GitHub and giving it a ⭐.');

    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on(APIEvent.DID_FINISH_LAUNCHING, () => {
      this.logs.debug('Executed didFinishLaunching callback');
      this.count = 1;
      // run the method to discover / register your devices as accessories
      this.discoverDevices(true);
      // Periodic scan for devices
      const shouldRediscover = this.config.advancedOptions?.periodicDiscovery ?? false;

      if (shouldRediscover) {
        this.periodicDiscovery = setInterval(() => this.discoverDevices(false), 30000);
      }
    });
  }
Example #16
Source File: platform.ts    From homebridge-tapo-p100 with Apache License 2.0 6 votes vote down vote up
constructor(
    public readonly log: Logger,
    config: PlatformConfig,
    public readonly api: API,
  ) {
    this.log.debug('config.json: %j', config);
    this.config = parseConfig(config);
    this.log.debug('config: %j', this.config);
    this.log.debug('Finished initializing platform:', this.config.name);
    this.customCharacteristics = Characteristics(api.hap.Characteristic);
    this.FakeGatoHistoryService = fakegato(this.api);
    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on('didFinishLaunching', () => {
      log.debug('Executed didFinishLaunching callback');
      // run the method to discover / register your devices as accessories
      this.discoverDevices();
    });
  }
Example #17
Source File: zigBee-controller.ts    From homebridge-zigbee-nt with Apache License 2.0 5 votes vote down vote up
private readonly log: Logger;
Example #18
Source File: auth.ts    From homebridge-lg-thinq-ac with Apache License 2.0 5 votes vote down vote up
private readonly log: Logger
Example #19
Source File: platform.ts    From homebridge-samsungtv-control2 with MIT License 5 votes vote down vote up
constructor(
    public readonly log: Logger,
    public readonly config: PlatformConfig,
    public readonly api: API,
  ) {
    this.log = log
    this.config = config
    this.api = api

    this.Service = api.hap.Service
    this.Characteristic = api.hap.Characteristic

    this.log.debug(`Got config`, this.config)

    // Add devices
    api.on(APIEvent.DID_FINISH_LAUNCHING, async () => {
      const dir = path.join(api.user.storagePath(), `.${PLUGIN_NAME}`)
      this.log.debug(`Using node-persist path:`, dir)
      await storage.init({
        dir,
        logging: (...args) => this.log.debug(`${PLATFORM_NAME} db -`, ...args),
      })

      let devices = await this.discoverDevices()
      devices = await this.applyConfig(devices)
      this.devices = await this.checkDevicePairing(devices)

      // Register all TV's
      for (const device of this.devices) {
        // Log all devices so that the user knows how to configure them
        this.log.info(
          chalk`Found device {blue ${device.name}} (${device.modelName}), usn: {green ${device.usn}}`,
        )
        this.log.debug(
          `${device.name} - (ip: ${device.lastKnownIp}, mac: ${device.mac})`,
        )
        // Register it
        this.registerTV(device.usn)
      }

      // Regularly discover upnp devices and update ip's, locations for registered devices
      setInterval(async () => {
        const devices = await this.discoverDevices()
        this.devices = await this.applyConfig(devices)
        /**
         * @todo
         * add previously not registered devices
         */
      }, 1000 * 60 * 5 /* 5min */)

      /**
       * @TODO
       * Add subscriptions to update getters
       */
    })
  }
Example #20
Source File: platform.ts    From homebridge-tasmota with Apache License 2.0 5 votes vote down vote up
constructor(
    public readonly log: Logger,
    public readonly config: any,
    public readonly api: API,
  ) {
    this.log.debug('Finished initializing platform:', this.config.name);

    this.cleanup = this.config['cleanup'] || 24; // Default removal of defunct devices after 24 hours
    this.debug = this.config['debug'] || false;
    this.teleperiod = this.config['teleperiod'] || 300;

    if (this.debug) {

      let namespaces = debugEnable.disable();

      // this.log("DEBUG-1", namespaces);
      if (namespaces) {
        namespaces = namespaces + ',Tasmota*';
      } else {
        namespaces = 'Tasmota*';
      }
      // this.log("DEBUG-2", namespaces);
      debugEnable.enable(namespaces);
    }

    if (this.config.override) {
      interface Injection { key: string, value: any }
      interface Injections { topic: string, injection: Injection[] }
      const injections: Injections[] = [];
      Object.keys(this.config.override).forEach((topic) => {
        const inject: Injection[] = [];
        Object.entries(this.config.override[topic]).forEach(
          ([key, value]) => {
            // debug("topic: %s, key: %s, value: %s", topic, key, value);
            const injection: Injection = { key: key, value: value };
            inject.push(injection);
          },
        );
        injections.push({ topic: topic, injection: inject });
      });
      debug('This is your override reformated to injections.');
      debug('"injections": %s\n', JSON.stringify(injections, null, 2));
    }

    /* eslint-disable */
    this.CustomCharacteristic = require('./lib/CustomCharacteristics')(this.Service, this.Characteristic);

    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on('didFinishLaunching', () => {
      log.debug('Executed didFinishLaunching callback');
      // run the method to discover / register your devices as accessories
      debug('%d accessories for cleanup', this.defunctAccessories.length);
      if (this.defunctAccessories.length > 0) {
        this.cleanupDefunctAccessories();
      }
      this.discoverDevices();

      if (this.config.history) {

        this.FakeGatoHistoryService = fakegato(this.api);

        // Only addEntries that match the expected profile of the function.

        this.FakeGatoHistoryService.prototype.appendData = function(entry) {
          entry.time = Math.round(new Date().valueOf() / 1000);
          switch (this.accessoryType) {
            default:
              // debug('unhandled this.accessoryType', this.accessoryType);
              this.addEntry(entry);
          }
        };
      }
    });
  }
Example #21
Source File: TuyaAPIHelper.d.ts    From homebridge-tuya-ir with Apache License 2.0 5 votes vote down vote up
static Instance(config: Config, log: Logger): TuyaAPIHelper;
Example #22
Source File: viera.ts    From homebridge-vieramatic with Apache License 2.0 5 votes vote down vote up
static probe = async (ip: string, log: Logger | Console = console): Promise<Outcome<VieraTV>> =>
    !isValidIPv4(ip)
      ? { error: Error('Please introduce a valid ip address!') }
      : !(await VieraTV.livenessProbe(ip))
      ? { error: Error(`The provided IP (${ip}) is unreachable.`) }
      : await this.connect(ip, log, { bootstrap: true })
Example #23
Source File: platform.ts    From homebridge-eufy-security with Apache License 2.0 5 votes vote down vote up
constructor(
    public readonly hblog: Logger,
    config: PlatformConfig,
    public readonly api: API,
  ) {
    this.config = config as EufySecurityPlatformConfig;

    this.eufyConfig = {
      username: this.config.username,
      password: this.config.password,
      country: 'US',
      language: 'en',
      persistentDir: api.user.storagePath(),
      p2pConnectionSetup: 0,
      pollingIntervalMinutes: this.config.pollingIntervalMinutes ?? 10,
      eventDurationSeconds: 10,
    } as EufySecurityConfig;


    this.config.ignoreStations = this.config.ignoreStations || [];
    this.config.ignoreDevices = this.config.ignoreDevices || [];

    if (this.config.enableDetailedLogging >= 1) {

      const plugin = require('../package.json');

      this.log = bunyan.createLogger({
        name: '[EufySecurity-' + plugin.version + ']',
        hostname: '',
        streams: [{
          level: (this.config.enableDetailedLogging === 2) ? 'trace' : 'debug',
          type: 'raw',
          stream: bunyanDebugStream({
            forceColor: true,
            showProcess: false,
            showPid: false,
            showDate: (time) => {
              return '[' + time.toLocaleString('en-US') + ']';
            },
          }),
        }],
        serializers: bunyanDebugStream.serializers,
      });
      this.log.info('Eufy Security Plugin: enableDetailedLogging on');
    } else {
      this.log = hblog;
    }

    this.eufyClient = (this.config.enableDetailedLogging === 2)
      ? new EufySecurity(this.eufyConfig, this.log)
      : new EufySecurity(this.eufyConfig);

    // Removing the ability to set Off(6) waiting Bropat feedback bropat/eufy-security-client#27
    this.config.hkOff = (this.config.hkOff === 6) ? 63 : this.config.hkOff;

    // When this event is fired it means Homebridge has restored all cached accessories from disk.
    // Dynamic Platform plugins should only register new accessories after this event was fired,
    // in order to ensure they weren't added to homebridge already. This event can also be used
    // to start discovery of new accessories.
    this.api.on('didFinishLaunching', async () => {
      // await this.createConnection();
      // run the method to discover / register your devices as accessories
      await this.discoverDevices();
    });

    this.log.info('Finished initializing Eufy Security Platform');
  }
Example #24
Source File: controller.ts    From homebridge-screenlogic with MIT License 5 votes vote down vote up
private readonly log: Logger
Example #25
Source File: viera.ts    From homebridge-vieramatic with Apache License 2.0 5 votes vote down vote up
readonly log: Logger | Console
Example #26
Source File: RoombaController.ts    From homebridge-iRobot with Apache License 2.0 5 votes vote down vote up
constructor(private readonly blid: string, private readonly password: string, private readonly ip: string, private readonly sku: string,
    private readonly refreshInterval: number, private readonly log: Logger, private readonly logPrefix: string) {
    super();
    process.env.ROBOT_CIPHERS = this.sku.startsWith('j') ? 'TLS_AES_256_GCM_SHA384' : 'AES128-SHA256';
  }
Example #27
Source File: tpLinkCipher.ts    From homebridge-tapo-p100 with Apache License 2.0 5 votes vote down vote up
constructor(public readonly log: Logger, b_arr: any, b_arr2: any){
      this.iv = b_arr2;
      this.key = b_arr;
    }
Example #28
Source File: platform.d.ts    From homebridge-plugin-govee with Apache License 2.0 5 votes vote down vote up
constructor(log: Logger, config: PlatformConfig, api: API);
Example #29
Source File: ffmpeg.ts    From homebridge-plugin-eufy-security with Apache License 2.0 5 votes vote down vote up
constructor(
    cameraName: string,
    sessionId: string,
    videoProcessor: string,
    ffmpegArgs: string,
    log: Logger,
    debug: boolean,
    delegate: EufyCameraStreamingDelegate,
    callback?: StreamRequestCallback,
  ) {
    log.debug(
      'Stream command: ' + videoProcessor + ' ' + ffmpegArgs,
      cameraName,
      debug,
    );

    let started = false;
    this.process = spawn(videoProcessor, ffmpegArgs.split(/\s+/), {
      env: process.env,
    });

    if (this.process.stdin) {
      this.process.stdin.on('error', (error: Error) => {
        if (!error.message.includes('EPIPE')) {
          log.error(error.message, cameraName);
        }
      });
    }
    if (this.process.stderr) {
      this.process.stderr.on('data', (data) => {
        if (!started) {
          started = true;
          if (callback) {
            callback();
          }
        }

        if (debug) {
          data
            .toString()
            .split(/\n/)
            .forEach((line: string) => {
              if (line && line !== '') {
                log.debug(line);
              }
            });
        }
      });
    }
    this.process.on('error', (error: Error) => {
      log.error('Failed to start stream: ' + error.message, cameraName);
      if (callback) {
        callback(new Error('FFmpeg process creation failed'));
      }
      delegate.stopStream(sessionId);
    });
    this.process.on('exit', (code: number, signal: NodeJS.Signals) => {
      const message =
        'FFmpeg exited with code: ' + code + ' and signal: ' + signal;

      if (code === null || code === 255) {
        if (this.process.killed) {
          log.debug(message + ' (Expected)', cameraName, debug);
        } else {
          log.error(message + ' (Unexpected)', cameraName);
        }
      } else {
        log.error(message + ' (Error)', cameraName);
        delegate.stopStream(sessionId);
        if (!started && callback) {
          callback(new Error(message));
        } else {
          delegate.controller!.forceStopStreamingSession(sessionId);
        }
      }
    });
  }