Beispiel #1
0
        static public async Task Do(CmdArguments args)
        {
            var client = JobClient.CreateFromConnectionString(Settings.Default.ConnectionString);

            var method = new CloudToDeviceMethod(args.Names.Single());

            method.SetPayloadJson(args.Values.Single());

            var startTime = DateTime.UtcNow + TimeSpan.FromSeconds(args.StartOffsetInSeconds);

            var jobId = args.JobId;

            if (string.IsNullOrEmpty(jobId))
            {
                jobId = Guid.NewGuid().ToString();
            }

            JobResponse job = await client.ScheduleDeviceMethodAsync(
                jobId,
                args.QueryCondition,
                method,
                startTime,
                args.TimeoutInSeconds);

            Console.WriteLine($"{job.Type} job {job.JobId} scheduled");
            await IoTHubHelper.WaitJob(client, job);
        }
 /// <summary>
 /// DI Constructor
 /// </summary>
 public RegistryManagerHelper(IOptions <IoTHubControllerOptions> config, ILogger <RegistryManagerHelper> logger)
 {
     _config          = config.Value;
     _registryManager = RegistryManager.CreateFromConnectionString(_config.IoTHubConnectionString);
     _jobClient       = JobClient.CreateFromConnectionString(_config.IoTHubConnectionString);
     _logger          = logger;
 }
Beispiel #3
0
        static public async Task Do(CmdArguments args)
        {
            var twin = new Twin();

            twin.ETag = "*";
            twin.Set(args.KVPairs);

            var startTime = DateTime.UtcNow + TimeSpan.FromSeconds(args.StartOffsetInSeconds);

            var client = JobClient.CreateFromConnectionString(Settings.Default.ConnectionString);

            var jobId = args.JobId;

            if (string.IsNullOrEmpty(jobId))
            {
                jobId = Guid.NewGuid().ToString();
            }

            JobResponse job = await client.ScheduleTwinUpdateAsync(
                jobId,
                args.QueryCondition,
                twin,
                startTime,
                args.TimeoutInSeconds);

            Console.WriteLine($"{job.Type} job {job.JobId} scheduled");
            await IoTHubHelper.WaitJob(client, job);
        }
        public async Task JobClient_ScheduleTwinUpdateInvalidServiceCertificateHttp_Fails()
        {
            var job       = JobClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionStringInvalidServiceCertificate);
            var exception = await Assert.ThrowsExceptionAsync <IotHubCommunicationException>(
                () => job.ScheduleTwinUpdateAsync(
                    "testDevice",
                    "DeviceId IN ['testDevice']",
                    new Shared.Twin(),
                    DateTime.UtcNow,
                    60)).ConfigureAwait(false);

#if NET451 || NET47
            Assert.IsInstanceOfType(exception.InnerException.InnerException.InnerException, typeof(AuthenticationException));
#elif NETCOREAPP2_0
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // WinHttpException (0x80072F8F): A security error occurred
                Assert.AreEqual(unchecked ((int)0x80072F8F), exception.InnerException.InnerException.HResult);
            }
            else
            {
                // CURLE_SSL_CACERT (60): Peer certificate cannot be authenticated with known CA certificates.
                Assert.AreEqual(60, exception.InnerException.InnerException.HResult);
            }
#else
            Assert.IsInstanceOfType(exception.InnerException.InnerException, typeof(AuthenticationException));
#endif
        }
Beispiel #5
0
        static public async Task Do(CmdArguments args)
        {
            if (args.Ids != null)
            {
                var client = JobClient.CreateFromConnectionString(Settings.Default.ConnectionString);

                foreach (var jobId in args.Ids)
                {
                    var job = await client.GetJobAsync(jobId);

                    Console.WriteLine(JsonConvert.SerializeObject(job, Formatting.Indented));
                    Console.WriteLine();
                }
            }
            else
            {
                var manager = RegistryManager.CreateFromConnectionString(Settings.Default.ConnectionString);

                var query = manager.CreateQuery(args.QueryCondition ?? "select * from devices.jobs");

                while (query.HasMoreResults)
                {
                    var result = await query.GetNextAsJsonAsync();

                    foreach (var job in result)
                    {
                        Console.WriteLine(job);
                        Console.WriteLine();
                    }
                }
            }
        }
        private async void buttonConnect_Click(object sender, RoutedEventArgs e)
        {
            jobClient = JobClient.CreateFromConnectionString(this.tbCS.Text);
            await jobClient.OpenAsync();

            buttonUpdateTwins.IsEnabled = true;
        }
        private async Task JobClient_ScheduleAndRunTwinJob(HttpTransportSettings httpTransportSettings)
        {
            Twin twin = new Twin(JobDeviceId);

            twin.Tags = new TwinCollection();
            twin.Tags[JobTestTagName] = JobDeviceId;

            using (JobClient jobClient = JobClient.CreateFromConnectionString(s_connectionString, httpTransportSettings))
            {
                int tryCount = 0;
                while (true)
                {
                    try
                    {
                        string      jobId             = "JOBSAMPLE" + Guid.NewGuid().ToString();
                        string      query             = $"DeviceId IN ['{JobDeviceId}']";
                        JobResponse createJobResponse = await jobClient.ScheduleTwinUpdateAsync(jobId, query, twin, DateTime.UtcNow, (long)TimeSpan.FromMinutes(2).TotalSeconds).ConfigureAwait(false);

                        break;
                    }
                    // Concurrent jobs can be rejected, so implement a retry mechanism to handle conflicts with other tests
                    catch (ThrottlingException) when(++tryCount < MaxIterationWait)
                    {
                        Logger.Trace($"ThrottlingException... waiting.");
                        await Task.Delay(_waitDuration).ConfigureAwait(false);

                        continue;
                    }
                }
            }
        }
 public CloudToDeviceViewModel(
     IOptions <ConnectionStrings> connectionStrings,
     FilteredDeviceListViewModel filteredDeviceListViewModel)
 {
     _filteredDeviceListViewModel = filteredDeviceListViewModel;
     _jobClient     = JobClient.CreateFromConnectionString(connectionStrings.Value.IoTHub);
     ExecuteCommand = new RelayCommand(async() => await ExecuteCommandAsync());
 }
        static async Task Main(string[] args)
        {
            using var registryManager = RegistryManager.CreateFromConnectionString(iotHubConnectionString);
            using var deviceClient    = DeviceClient.CreateFromConnectionString(deviceConnectionString, Microsoft.Azure.Devices.Client.TransportType.Mqtt); // need Mqtt !
            using var serviceClient   = ServiceClient.CreateFromConnectionString(iotHubConnectionString);
            using var jobClient       = JobClient.CreateFromConnectionString(iotHubConnectionString);

            await StartListeningForDirectMethods(deviceClient);

            while (true)
            {
                ConsoleWriteLine();
                ConsoleWriteLine($"*** Press 'I' followed by a method name ({GetDesiredPropertiesMethodName} or {GetReportedPropertiesMethodName}) to invoke a direct method ***");
                ConsoleWriteLine("*** Press 'E' to export all devices to blob storage ***");
                ConsoleWriteLine("*** Press 'U' followed by a device query condition, to launch a twin update job ***");
                ConsoleWriteLine("*** Press 'S' followed by a blob container name, to get a blob URI including SAS ***");
                ConsoleWriteLine("*** Press ENTER to quit ***");
                ConsoleWriteLine();
                var consoleInput = Console.ReadLine();


                if (string.IsNullOrEmpty(consoleInput))
                {
                    // quit
                    break;
                }
                else if ("E".Equals(consoleInput, StringComparison.InvariantCultureIgnoreCase))
                {
                    await ExportDevices(registryManager);
                }
                else if (consoleInput.StartsWith("U ", StringComparison.InvariantCultureIgnoreCase))
                {
                    var queryCondition = consoleInput.Substring(2).Trim();
                    await StartTwinUpdateJob(jobClient, queryCondition);
                }
                else if ("U".Equals(consoleInput, StringComparison.InvariantCultureIgnoreCase))
                {
                }
                else if (consoleInput.StartsWith("I ", StringComparison.InvariantCultureIgnoreCase))
                {
                    var methodName = consoleInput.Substring(2).Trim();

                    await InvokeDirectMethod(serviceClient, methodName);
                }
                else if (consoleInput.StartsWith("S ", StringComparison.InvariantCultureIgnoreCase))
                {
                    var blobContainerName = consoleInput.Substring(2).Trim();

                    var blobContainerUri = await GetBlobContainerUriWithSas(blobContainerName);

                    ConsoleWriteLine($"Blob URI with SAS: {blobContainerUri}", ConsoleColor.Yellow);
                }
                else
                {
                    ConsoleWriteLine("*** Sorry, I didn't understand that input ***", ConsoleColor.Red);
                }
            }
        }
Beispiel #10
0
 public DirectMethodJob(DirectMethodOptions opts, AppSettings appsettings)
 {
     _appsettings = appsettings;
     _opts        = opts;
     if (_jobClient == null)
     {
         _jobClient = JobClient.CreateFromConnectionString(appsettings.IoTHubOwnerConnectionString);
     }
 }
Beispiel #11
0
 public DeviceTwinJob(TwinPropertyOptions opts, AppSettings appsettings)
 {
     _deviceId    = opts.Query;
     _opts        = opts;
     _appsettings = appsettings;
     if (_jobClient == null)
     {
         _jobClient = JobClient.CreateFromConnectionString(appsettings.IoTHubOwnerConnectionString);
     }
 }
Beispiel #12
0
        public IoTHubDeviceManager(IConfigurationProvider configProvider)
        {
            // Temporary code to bypass https cert validation till DNS on IotHub is configured
            ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
            var iotHubConnectionString = configProvider.GetConfigurationSettingValue("iotHub.ConnectionString");

            this._deviceManager = RegistryManager.CreateFromConnectionString(iotHubConnectionString);
            this._serviceClient = ServiceClient.CreateFromConnectionString(iotHubConnectionString);
            this._jobClient     = JobClient.CreateFromConnectionString(iotHubConnectionString);
        }
Beispiel #13
0
        static public async Task Do(CmdArguments args)
        {
            var client = JobClient.CreateFromConnectionString(Settings.Default.ConnectionString);

            foreach (var jobId in args.Names)
            {
                var response = await client.CancelJobAsync(jobId);

                Console.WriteLine($"Job {jobId} status = {response.Status}");
            }
        }
Beispiel #14
0
    public static async Task MonitorAsync(AppSettings appsettings, string jobId)
    {
        JobResponse result;
        var         jobClient = JobClient.CreateFromConnectionString(appsettings.IoTHubOwnerConnectionString);

        do
        {
            result = await jobClient.GetJobAsync(jobId);

            Logger.Info($"[{jobId}]Job Status : " + result.Status.ToString());
            Thread.Sleep(2000);
        }while ((result.Status != JobStatus.Completed) &&
                (result.Status != JobStatus.Failed));
    }
Beispiel #15
0
        public JobClient GetJobClient()
        {
            JobClient job = null;

            IoTHubConnectionHelper.CreateUsingHubConnectionString(this.GetIotHubConnectionString(), conn =>
            {
                job = JobClient.CreateFromConnectionString(conn);
            });
            if (job == null)
            {
                throw new InvalidConfigurationException($"Invalid tenant information for HubConnectionstring.");
            }

            return(job);
        }
        private async Task JobClient_ScheduleAndRunTwinJob(HttpTransportSettings httpTransportSettings)
        {
            string jobId = "JOBSAMPLE" + Guid.NewGuid().ToString();
            string query = $"DeviceId IN ['{JobDeviceId}']";

            Twin twin = new Twin(JobDeviceId);

            twin.Tags = new TwinCollection();
            twin.Tags[JobTestTagName] = JobDeviceId;

            JobClient   jobClient         = JobClient.CreateFromConnectionString(ConnectionString, httpTransportSettings);
            JobResponse createJobResponse = await jobClient.ScheduleTwinUpdateAsync(jobId, query, twin, DateTime.UtcNow, (long)TimeSpan.FromMinutes(2).TotalSeconds).ConfigureAwait(false);

            JobResponse jobResponse = await jobClient.GetJobAsync(jobId).ConfigureAwait(false);
        }
        public static async Task <int> Main(string[] args)
        {
            if (string.IsNullOrEmpty(s_connectionString) && args.Length > 0)
            {
                s_connectionString = args[0];
            }

            using JobClient jobClient = JobClient.CreateFromConnectionString(s_connectionString);

            var sample = new JobsSample(jobClient);
            await sample.RunSampleAsync().ConfigureAwait(false);

            Console.WriteLine("Done.");
            return(0);
        }
Beispiel #18
0
        public static int Main(string[] args)
        {
            if (string.IsNullOrEmpty(s_connectionString) && args.Length > 0)
            {
                s_connectionString = args[0];
            }

            JobClient jobClient = JobClient.CreateFromConnectionString(s_connectionString);

            var sample = new JobsSample(jobClient);

            sample.RunSampleAsync().GetAwaiter().GetResult();

            Console.WriteLine("Done.\n");
            return(0);
        }
        public Jobs(IServicesConfig config, IDeviceProperties deviceProperties)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }
            this.deviceProperties = deviceProperties;

            IoTHubConnectionHelper.CreateUsingHubConnectionString(
                config.IoTHubConnString,
                conn => { this.jobClient = JobClient.CreateFromConnectionString(conn); });

            IoTHubConnectionHelper.CreateUsingHubConnectionString(
                config.IoTHubConnString,
                conn => { this.registryManager = RegistryManager.CreateFromConnectionString(conn); });
        }
        public async Task <JobResponse> MonitorJobWithDetailsAsync(string jobId)
        {
            if (string.IsNullOrEmpty(jobId))
            {
                throw new ArgumentNullException("jobId");
            }

            using (var jobClient = JobClient.CreateFromConnectionString(_settings.IoTHub.ConnectionString))
            {
                if (jobClient != null)
                {
                    return(await jobClient.GetJobAsync(jobId));
                }
                return(null);
            }
        }
Beispiel #21
0
        public async Task JobClient_ScheduleTwinUpdateInvalidServiceCertificateHttp_Fails()
        {
            var job       = JobClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionStringInvalidServiceCertificate);
            var exception = await Assert.ThrowsExceptionAsync <IotHubCommunicationException>(
                () => job.ScheduleTwinUpdateAsync(
                    "testDevice",
                    "DeviceId IN ['testDevice']",
                    new Shared.Twin(),
                    DateTime.UtcNow,
                    60)).ConfigureAwait(false);

#if NET451 || NET472
            Assert.IsInstanceOfType(exception.InnerException.InnerException.InnerException, typeof(AuthenticationException));
#else
            Assert.IsInstanceOfType(exception.InnerException.InnerException, typeof(AuthenticationException));
#endif
        }
        /// <summary>
        /// Create service client
        /// </summary>
        /// <param name="config"></param>
        /// <param name="logger"></param>
        public IoTHubServiceClient(IIoTHubConfig config, ILogger logger)
        {
            if (string.IsNullOrEmpty(config?.IoTHubConnString))
            {
                throw new ArgumentNullException(nameof(config.IoTHubConnString));
            }

            _logger = logger ?? throw new ArgumentNullException(nameof(logger));

            _client   = ServiceClient.CreateFromConnectionString(config.IoTHubConnString);
            _registry = RegistryManager.CreateFromConnectionString(config.IoTHubConnString);
            _jobs     = JobClient.CreateFromConnectionString(config.IoTHubConnString);

            Task.WaitAll(_client.OpenAsync(), _registry.OpenAsync(), _jobs.OpenAsync());

            HostName = ConnectionString.Parse(config.IoTHubConnString).HostName;
        }
Beispiel #23
0
        static public async Task Do(CmdArguments args)
        {
            var client    = JobClient.CreateFromConnectionString(Settings.Default.ConnectionString);
            var condition = args.QueryCondition == null ? null : JsonConvert.DeserializeObject <QueryJobSummaryCondition>(args.QueryCondition);

            var query = client.CreateQuery(condition?.Type, condition?.Status);

            while (query.HasMoreResults)
            {
                var result = await query.GetNextAsJsonAsync();

                foreach (var job in result)
                {
                    Console.WriteLine(job);
                    Console.WriteLine();
                }
            }
        }
Beispiel #24
0
 public ScheduleJobsViewModel(
     IOptions <ConnectionStrings> connectionStrings,
     FilteredDeviceListViewModel filteredDeviceListViewModel)
 {
     _filteredDeviceListViewModel = filteredDeviceListViewModel;
     _jobClient     = JobClient.CreateFromConnectionString(connectionStrings.Value.IoTHub);
     _targetVersion = "1.1";
     _updateTimes   = new ObservableCollection <string>(new[]
     {
         "immediately",
         "5 seconds from now",
         "10 seconds from now",
         "30 seconds from now",
         "1 minute from now"
     });
     _selectedUpdateTime   = _updateTimes[1];
     UpdateFirmwareCommand = new RelayCommand(async() => await UpdateFirmwareAsync());
     _timer = new Timer(OnTick, null, Timeout.Infinite, 1000);
 }
Beispiel #25
0
        public Jobs(
            IServicesConfig config,
            IConfigService configService)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            IoTHubConnectionHelper.CreateUsingHubConnectionString(
                config.IoTHubConnString,
                conn => { this.jobClient = JobClient.CreateFromConnectionString(conn); });

            IoTHubConnectionHelper.CreateUsingHubConnectionString(
                config.IoTHubConnString,
                conn => { this.registryManager = RegistryManager.CreateFromConnectionString(conn); });

            this.configService = configService;
        }
Beispiel #26
0
        private async void cmd11ScheduledUpdate_Click(object sender, RoutedEventArgs e)
        {
            removeAndCloseClientDevicesConnections();
            dcPC = DeviceClient.CreateFromConnectionString(m_devConnection,
                                                           Microsoft.Azure.Devices.Client.TransportType.Mqtt);
            dcPC.SetMethodHandler("update", new MethodCallback(update_pc), new byte[] { 1 });

            //Second "device"
            dcPC1 = DeviceClient.CreateFromConnectionString(m_dev1Connection,
                                                            Microsoft.Azure.Devices.Client.TransportType.Mqtt);
            dcPC1.SetMethodHandler("update", new MethodCallback(update_pc1), new byte[] { 3 });

            RegistryManager rm = RegistryManager.CreateFromConnectionString(m_ownerConnection);
            JobClient       jc = JobClient.CreateFromConnectionString(m_ownerConnection);
            JobResponse     result;
            string          jobId;

            //Update Tags
            jobId = Guid.NewGuid().ToString();
            var twin = new Twin();

            twin.Tags["Virtual"] = true;
            twin.ETag            = "*";
            result = await jc.ScheduleTwinUpdateAsync(jobId,
                                                      "not is_defined(tags.abc)", //not is_defined(tags.virtual)
                                                      twin,
                                                      DateTime.Now,
                                                      100);
            await MonitorJob(jc, jobId);

            jobId = Guid.NewGuid().ToString();
            CloudToDeviceMethod directMethod = new CloudToDeviceMethod("update", TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));

            directMethod.SetPayloadJson("{\"url\":\"http://www.cos\"}");
            //var query = rm.CreateQuery("SELECT * FROM devices WHERE tags.devicetype = 'PC'");
            result = await jc.ScheduleDeviceMethodAsync(jobId,
                                                        "tags.devicetype = 'PC'", //Another
                                                        directMethod,
                                                        DateTime.Now,
                                                        10);
            await MonitorJob(jc, jobId);
        }
        public ScheduleJob(string _deviceId)
        {
            deviceId = _deviceId;
            System.Diagnostics.Debug.WriteLine("Press ENTER to start running jobs.");
            Thread.Sleep(2000);

            jobClient = JobClient.CreateFromConnectionString(connString);

            string methodJobId = Guid.NewGuid().ToString();

            StartMethodJob(methodJobId);
            MonitorJob(methodJobId).Wait();
            System.Diagnostics.Debug.WriteLine("Press ENTER to run the next job.");
            Thread.Sleep(2000);

            string twinUpdateJobId = Guid.NewGuid().ToString();

            StartTwinUpdateJob(twinUpdateJobId);
            MonitorJob(twinUpdateJobId).Wait();
            System.Diagnostics.Debug.WriteLine("Press ENTER to exit.");
            Thread.Sleep(2000);
        }
        public async Task RunTwinUpdateJobAsync(string jobId, string queryCondition, Twins twin, DateTime startTime,
                                                long timeOut)
        {
            if (string.IsNullOrEmpty(jobId))
            {
                throw new ArgumentNullException("jobId");
            }

            if (string.IsNullOrEmpty(queryCondition))
            {
                throw new ArgumentNullException("queryCondition");
            }

            if (twin == null)
            {
                throw new ArgumentNullException("twin");
            }

            var iotHubTwin = _mapper.Map <Twin>(twin);

            if (iotHubTwin == null)
            {
                throw new Exception("Twin mapping error.");
            }


            using (var jobClient = JobClient.CreateFromConnectionString(_settings.IoTHub.ConnectionString))
            {
                if (jobClient != null)
                {
                    var createJobResponse = await jobClient.ScheduleTwinUpdateAsync(
                        jobId,
                        queryCondition,
                        iotHubTwin,
                        startTime,
                        timeOut);
                }
            }
        }
Beispiel #29
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="deviceIdentity"></param>
        /// <param name="deviceId"></param>
        private static async void ManageDeviceJob(DeviceIdentity deviceIdentity, string deviceId)
        {
            var    jobClient   = JobClient.CreateFromConnectionString(deviceIdentity.GetConnectionString());
            string methodJobId = Guid.NewGuid().ToString();


            await deviceIdentity.StartMethodJob(methodJobId, jobClient, deviceId);

            Console.WriteLine("Started Twin Update Job");

            var result1 = deviceIdentity.MonitorJob(methodJobId, jobClient).Result;

            Console.WriteLine("Job Status : " + result1.Status);

            string twinUpdateJobId = Guid.NewGuid().ToString();

            await deviceIdentity.StartTwinUpdateJob(twinUpdateJobId, jobClient, deviceId);

            result1 = deviceIdentity.MonitorJob(twinUpdateJobId, jobClient).Result;
            Console.WriteLine("Job Status : " + result1.Status);
            Console.WriteLine("Press ENTER to exit.");
            Console.ReadLine();
        }
        static void Main(string[] args)
        {
            string jobId = "DHCMD" + Guid.NewGuid().ToString();

            // The query condition can also be on a single device Id or on a list of device Ids.
            // https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-query-language covers
            //   IoT Hub query language in additional detail.
            string query = $"DeviceId IN ['{deviceId}']";

            Twin twin = new Twin(deviceId);

            twin.Tags = new TwinCollection();
            twin.Tags[TestTagName] = TestTagValue;

            // *************************************** Start JobClient ***************************************
            Console.WriteLine($"Create JobClient from the connectionString...");
            JobClient jobClient = JobClient.CreateFromConnectionString(connectionString);

            Console.WriteLine($"JobClient created with success");
            Console.WriteLine();

            // *************************************** Schedule twin job ***************************************
            Console.WriteLine($"Schedule twin job {jobId} for {deviceId}...");
            JobResponse createJobResponse = jobClient.ScheduleTwinUpdateAsync(
                jobId, query, twin, DateTime.UtcNow, (long)TimeSpan.FromMinutes(2).TotalSeconds).Result;

            Console.WriteLine($"Schedule response");
            Console.WriteLine(JsonConvert.SerializeObject(createJobResponse, Formatting.Indented));
            Console.WriteLine();

            // *************************************** Get all Jobs ***************************************
            IEnumerable <JobResponse> queryResults = jobClient.CreateQuery().GetNextAsJobResponseAsync().Result;
            var getJobs = queryResults.ToList();

            Console.WriteLine($"getJobs return {getJobs.Count} result(s)");

            foreach (JobResponse job in getJobs)
            {
                Console.WriteLine(JsonConvert.SerializeObject(job, Formatting.Indented));

                if (job.Status != JobStatus.Completed)
                {
                    Console.WriteLine($"Incorrect query jobs result");
                    return;
                }
            }
            Console.WriteLine();

            // *************************************** Check completion ***************************************
            Console.WriteLine($"Monitoring jobClient for job completion...");
            JobResponse jobResponse = jobClient.GetJobAsync(jobId).Result;

            Console.WriteLine($"First result");
            Console.WriteLine(JsonConvert.SerializeObject(jobResponse, Formatting.Indented));
            while (jobResponse.Status != JobStatus.Completed)
            {
                Task.Delay(TimeSpan.FromMilliseconds(100));
                jobResponse = jobClient.GetJobAsync(jobId).Result;
            }
            Console.WriteLine($"Job ends with status {jobResponse.Status}");
        }