submitApiCall method

  1. @override
Future<void> submitApiCall(
  1. Map<String, dynamic> data
)
override

Implementation

@override
Future<void> submitApiCall(Map<String, dynamic> data) async {
  try {
    LogbotLogger().simple("Starting finalization of setup");

    /// Sets the license on the device with dry run to test the device and get
    /// the device ID
    if (mounted) {
      setState(() {
        currentStatus = SetupStatus.setting_license;
      });
    } else {
      currentStatus = SetupStatus.setting_license;
    }

    /// Should be much longer than the usual submit delay just to be sure every
    /// other api call proceeding this is completed
    await Future.delayed(Duration(seconds: LogbotSetupEnv.submitDelay));
    await Future.delayed(Duration(seconds: LogbotSetupEnv.submitDelay));
    License? license = await LogbotSetupApiManager.device.setLicense(
        LicenseToken(token: widget.licenseToken),
        dryrun: true,
        uuidToken: LogbotSetupEnv().deviceId);
    setState(() {
      deviceId = license!.uuid!;
    });
    LogbotLogger().simple("Device UUID: $deviceId");

    /// Actually sets the license a nd restart the device
    await LogbotSetupApiManager.device.setLicense(
        LicenseToken(token: widget.licenseToken),
        uuidToken: LogbotSetupEnv().deviceId);
    LogbotLogger().simple("Set License, will now wait 100 seconds");

    /// Awaits some time for the device to reboot
    if (mounted) {
      setState(() {
        currentStatus = SetupStatus.rebooting;
      });
    } else {
      currentStatus = SetupStatus.rebooting;
    }

    /// If the setup is via bluetooth, the device will disconnect when rebooting
    /// and the LB Setup UI will show the Device Status error page, so the following
    /// steps will not complete. Will directly call it a success and return.
    if (LogbotSetupEnv().isBluetooth()) {
      await Future.delayed(Duration(seconds: 5));
      widget.onSuccess(deviceId, currentStatus);
    }
    await Future.delayed(Duration(seconds: 100));
    LogbotLogger().simple("Waiting complete");

    /// Starts the MDNS discovery as bluetooth is no longer working
    /// if device has been setup correctly
    /// If you are not logged in, it will discover only local
    /// devices
    await LogbotDiscovery.startDiscovery();
    if (mounted) {
      setState(() {
        currentStatus = SetupStatus.searching_device;
      });
    } else {
      currentStatus = SetupStatus.searching_device;
    }
    LogbotLogger().simple("Discovery started!");

    /// Retries a few times and check if device has rebooted using
    /// the health check of lb_core via WiFi
    int attempt = 1;
    int maxAttempts = 5;
    int delay = 10;
    Device? device;
    while (device == null && attempt <= maxAttempts) {
      LogbotLogger().simple(
          "Trying to discover the device in the local network. Attempt $attempt");
      device = await LogbotDiscovery.discovery.discoverDevice(deviceId);
      await Future.delayed(Duration(seconds: delay));
      attempt++;
    }

    /// If the device was not found on the local network, doesn't mean that
    /// the config was not successful. Maybe the user is conneted to another
    /// network, or the device is very slow.
    if (attempt >= maxAttempts || device == null) {
      LogbotLogger().simple("Could not find device in local network");
      widget.onPartialSuccess?.call(deviceId);
      return;
    }
    setState(() {
      currentStatus = SetupStatus.device_found;
    });
    LogbotLogger().simple("Device found!");

    /// Tests the health of the device to check if lb_setup is up
    /// and running
    attempt = 1;
    maxAttempts = 5;
    delay = 10;
    LogbotLogger().simple("Checking LB Setup health");
    setState(() {
      currentStatus = SetupStatus.checking_health;
    });
    while (attempt <= maxAttempts) {
      try {
        LogbotLogger()
            .simple("Trying to check LB Setup health. Attempt $attempt");
        await LogbotSetup.info.getHealth(uuidToken: deviceId);
        break;
      } catch (e) {
        LogbotLogger().simple("LB Setup is not up yet!");
      }
      await Future.delayed(Duration(seconds: delay));
      attempt++;
    }

    /// If I reached max attempts, throws error
    if (attempt >= maxAttempts) {
      LogbotLogger().simple("Device was found but LB Setup was not ready");
      widget.onPartialSuccess?.call(deviceId);
      return;
    }
    LogbotLogger().simple("LB Setup is up and healthy");

    /// If user has logged in, I can proceed with some
    /// more configuration
    /// Only an editor can call the APIs
    if (LogbotAuth.accessToken() != null && LogbotAuth.isEditor()) {
      /// Checks if device is registered in Logbot with
      /// lb_core
      LogbotLogger().simple("Downloading user devices");
      setState(() {
        currentStatus = SetupStatus.retrieving_registered_devices;
      });
      List<IoT>? iots = await LogbotCore.iots.listIoTs() ?? [];
      int index = iots.indexWhere((iot) => iot.token == deviceId);

      /// Device index -1 means that was not found in the list of
      /// user devices. This is the first time user set up this device
      /// so it must be registered on the platform
      if (index == -1) {
        LogbotLogger()
            .simple("This is a new device! Will register the device");
        setState(() {
          currentStatus = SetupStatus.registering_new_device;
        });

        /// To register the device, a name must be assigned to it
        return widget.onSuccess(deviceId, currentStatus);
      }

      /// If device is present, then configuration is complete
      /// nothing more to do
    }
    LogbotLogger().simple("Reboot complete!");
    setState(() {
      currentStatus = SetupStatus.complete;
    });

    /// If user is not logged in, then I cannot do anything else
    /// the user will have to register the iot manually on the platform
    /// if it hasn't done already
    widget.onSuccess(deviceId, currentStatus);
  } catch (e, s) {
    LogbotLogger().error("LbSetupBonjourPage.apiCall()", e.toString(), s);
    widget.onError?.call();
  }
}