New to IoTC, how to bulk activate devices in PowerShell?

James Heffers 0 Reputation points
2023-05-16T22:01:56.32+00:00

Hi all!

So I have just started messing around with IoTC (literally just today, so apologies if this is a newb question), and I have constructed/imported myriad test devices (using the plug and play thermometer template), however I am unsure how to bulk activate them. The documentation provided only explains how to activate them one at a time in PowerShell (as follows):

$env:IOTHUB_DEVICE_SECURITY_TYPE='DPS' $env:IOTHUB_DEVICE_DPS_ID_SCOPE='<application ID scope>' $env:IOTHUB_DEVICE_DPS_DEVICE_KEY='<device primary key>' $env:IOTHUB_DEVICE_DPS_DEVICE_ID='<your device ID>' $env:IOTHUB_DEVICE_DPS_ENDPOINT='global.azure-devices-provisioning.net'

Then running the provided script after setting the environment. I am fine with this, but what if, say, I have 1,000 devices in a device group (all with the same template). How can one activate all of them simultaneously? I'm not well versed in PowerShell, so I have no gauge of if this is a straightforward request or not. I have tried searching for an answer but to no avail. Any guidance is appreciated!

Azure IoT Central
Azure IoT Central
An Azure hosted internet of things (IoT) application platform.
362 questions
{count} votes

1 answer

Sort by: Most helpful
  1. LeelaRajeshSayana-MSFT 14,756 Reputation points Microsoft Employee
    2023-05-17T00:02:29.8233333+00:00

    Hi @James Heffers Greetings! Welcome to Microsoft Q&A forum. Thank you for posting the question here.

    You can customize the code to leverage IoT Central Rest API end points to Create a Device and get the Device Credentials. Once you obtain those credentials needed you can provision the device by setting the values from the code instead of using PowerShell. Please refer the below code which provides a reference on how to use the IoT Central Rest APIs to create a device and fetch the credentials.

    using System;
    using System.Diagnostics;
    using Newtonsoft.Json;
    using Microsoft.Azure.Devices.Shared;
    using Microsoft.Azure.Devices.Provisioning.Client;
    using Microsoft.Azure.Devices.Provisioning.Client.Transport;
    
    
    namespace BulkProvision // Note: actual namespace depends on the project name.
    {
        internal class Program
        {
            static string subdomain = "<subdomain>";
            static string baseDomain = "azureiotcentral.com";
    
            static string displayName = "TestDPS1";
            static string apiVersion = "2022-07-31";
    
            static string DeviceId = "TestDPS1";
    
            static string DpsIdScope;
    
    
            static string DeviceSymmetricKey;
    
            static string DeviceSecurityType = "DPS";
    
            static string DpsEndpoint = "global.azure-devices-provisioning.net";
    
            static string modelId = "<templateID>";
    
            static async Task Main(string[] args)
            {
                var token = GetAccessToken();
                Console.WriteLine(token);
                await CreateDevice(token);
                await GetDeviceCredentials(token);
            }
    
            public static string GetAccessToken()
            {
                var process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "C:\\Program Files (x86)\\Microsoft SDKs\\Azure\\CLI2\\wbin\\az.cmd",
                        Arguments = $"account get-access-token --resource https://apps.azureiotcentral.com",
                        RedirectStandardOutput = true,
                        UseShellExecute = false,
                        CreateNoWindow = true
                    }
                };
    
                process.Start();
                var output = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
    
                return output.Split('"')[3];
            }
    
            static async Task CreateDevice(string AccessToken)
            {
                string url = $"https://{subdomain}.{baseDomain}/api/devices/{DeviceId}?api-version={apiVersion}";
                string accessToken = AccessToken;
                string requestBody = $@"{{""name"": ""{displayName}"",""displayName"": ""{displayName}"",""template"": ""{modelId}"",""enabled"": true,""simulated"": false}}";
    
                using (var httpClient = new HttpClient())
                {
                    using (var request = new HttpRequestMessage(new HttpMethod("PUT"), url))
                    {
                        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
                        request.Content = new StringContent(requestBody, System.Text.Encoding.UTF8, "application/json");
    
                        HttpResponseMessage response = await httpClient.SendAsync(request);
    
                        if (response.IsSuccessStatusCode)
                        {
                            Console.WriteLine("Device updated successfully.");
                        }
                        else
                        {
                            Console.WriteLine($"Failed to update device. Status code: {response}");
                        }
                    }
                }
            }
    
            static async Task GetDeviceCredentials(string AccessToken)
            {
                string url = $"https://{subdomain}.{baseDomain}/api/devices/{DeviceId}/credentials?api-version={apiVersion}";
                string accessToken = AccessToken;
                using (var httpClient = new HttpClient())
                {
                    using (var request = new HttpRequestMessage(new HttpMethod("GET"), url))
                    {
                        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
    
                        HttpResponseMessage response = await httpClient.SendAsync(request);
    
                        if (response.IsSuccessStatusCode)
                        {
                            string responseBody = await response.Content.ReadAsStringAsync();
                            dynamic responseObj = JsonConvert.DeserializeObject(responseBody);
                            DpsIdScope = responseObj.idScope;
                            DeviceSymmetricKey = responseObj.symmetricKey.primaryKey;
                            Console.WriteLine("DpsIdScope: " + DpsIdScope);
                            Console.WriteLine("DeviceSymmetricKey: " + DeviceSymmetricKey);
                        }
                        else
                        {
                            Console.WriteLine($"Failed to update device. Status code: {response}");
                        }
    
                    }
                }
            }
    
        }
    }
    
    

    Modify the file \azure-iot-sdk-csharp-main\iothub\device\samples\solutions\PnpDeviceSamples\TemperatureController\Program.cs to include the above methods. Once you get these credentials, you can use them in the ProvisionDeviceAsync method of where the device is getting provisioned.

    Hope this helps you. Please let us know if you have any questions or need further assistance with implementation.


    If the response helped, please do click Accept Answer and Yes. Doing so would help other community members with similar issue identify the solution. I highly appreciate your contribution to the community.

    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.