I have taken bulk import code from github msdn link but using this same code in console and in web application it is unable to register any new devices into iot hub.
it is creating a list of devices into blob file but why it is not able to successfully execute import job? i do not get any exception also.
class Program
{
static RegistryManager registryManager;
static string connectionString = "iothub-connectionstring";
static void Main(string[] args)
{
BulkImport();
}
static string GetContainerSasUri(CloudBlobContainer container)
{
// Set the expiry time and permissions for the container.
// In this case no start time is specified, so the
// shared access signature becomes valid immediately.
var sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24);
sasConstraints.Permissions =
SharedAccessBlobPermissions.Write |
SharedAccessBlobPermissions.Read |
SharedAccessBlobPermissions.Delete;
// Generate the shared access signature on the container,
// setting the constraints directly on the signature.
string sasContainerToken = container.GetSharedAccessSignature(sasConstraints);
// Return the URI string for the container,
// including the SAS token.
return container.Uri + sasContainerToken;
}
private static async Task BulkImport()
{
try
{
registryManager = RegistryManager.CreateFromConnectionString(connectionString);
StorageCredentials storageCredentials = new StorageCredentials("storeage-name", "storage-key");
CloudStorageAccount storageAccount = new CloudStorageAccount(storageCredentials, useHttps: true);
// Create a blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("bulkiothubimport");
CloudBlockBlob blob = container.GetBlockBlobReference("devices.txt");
var containerSasUri = GetContainerSasUri(container);
// Provision 1,000 more devices
var serializedDevices = new List<string>();
for (var i = 0; i < 5; i++)
{
// Create a new ExportImportDevice
// CryptoKeyGenerator is in the Microsoft.Azure.Devices.Common namespace
var deviceToAdd = new ExportImportDevice()
{
Id = i+"mydevicenew",
Status = DeviceStatus.Enabled,
Authentication = new AuthenticationMechanism()
{
SymmetricKey = new SymmetricKey()
{
PrimaryKey = CryptoKeyGenerator.GenerateKey(32),
SecondaryKey = CryptoKeyGenerator.GenerateKey(32)
}
},
ImportMode = ImportMode.Create
};
// Add device to the list
serializedDevices.Add(JsonConvert.SerializeObject(deviceToAdd));
}
// Write the list to the blob
var sb = new StringBuilder();
serializedDevices.ForEach(serializedDevice => sb.AppendLine(serializedDevice));
//await blob.DeleteIfExistsAsync();
using (CloudBlobStream stream = await blob.OpenWriteAsync())
{
byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString());
for (var i = 0; i < bytes.Length; i += 500)
{
int length = Math.Min(bytes.Length - i, 500);
await stream.WriteAsync(bytes, i, length);
}
}
// Call import using the blob to add new devices
// Log information related to the job is written to the same container
// This normally takes 1 minute per 100 devices
JobProperties importJob =
await registryManager.ImportDevicesAsync(containerSasUri, containerSasUri);
// Wait until job is finished
while (true)
{
importJob = await registryManager.GetJobAsync(importJob.JobId);
if (importJob.Status == JobStatus.Completed ||
importJob.Status == JobStatus.Failed ||
importJob.Status == JobStatus.Cancelled)
{
// Job has finished executing
break;
}
await Task.Delay(TimeSpan.FromSeconds(5));
}
}
catch (Exception ex)
{
throw ex;
}
}
}
Behind the bulk import devices method are the REST API calls to the Azure IoT Hub service-facing endpoint. Using the registryManager.ImportDevicesAsync method is to create a background job in the Azure IoT Hub namespace. When the job has been accepted, the jobId is returned for its polling processing status.
Basically, we need two REST APIs such as the POST and GET job. More details can be found in the doc Service - Create Import Export Job and Service - Get Import Export Job.
The following steps show how to test this bulk import devices job using the REST APIs:
Use the latest Microsoft Azure Storage Explorer for creating two containers such as one for input and the other one for output log messages. Also, this tool allows to generate a full uri address with a sas token for those containers.
Create a text file with the name devices.txt and following contains (example for provisioning two devices):
{"id":"Device1", "importMode":"Create", "status":"enabled", "properties":{"desired":{"abcd":12345 } } }
{"id":"Device2", "importMode":"Create", "status":"enabled", "properties":{"desired":{"abcd":12345 } } }
Upload the file devices.txt to the input container.
POST the job to the Azure IoT Hub
POST https://{yourIoTHub}.azure-devices.net/jobs/create?api-version=2018-06-30
Authorization:{yourIoTHubSasToken}
body:
{
"inputBlobContainerUri": "{inputContainerUriWithSasToken}",
"outputBlobContainerUri": "{outputContainerUriWithSasToken}",
"inputBlobName": "devices.txt",
"type": "import"
}
the response should be:
{
"jobId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"startTimeUtc": "2019-01-06T16:19:54.9535051Z",
"type": "import",
"status": "enqueued",
"progress": 0,
"inputBlobContainerUri": "xxxxxx",
"outputBlobContainerUri": "xxxxxx",
"excludeKeysInExport": false,
"useSecondaryStorageAsSource": false
}
Polling the job status until the job is either completed or failed or cancelled
GET https://{yourIoTHub}.azure-devices.net/jobs/xxxxx-xxxx-xxxx-xxxxxxxxxxxx?api-version=2018-06-30
Authorization:{yourIoTHubSasToken}
the response:
{
"jobId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"startTimeUtc": "2019-01-06T16:19:54.9535051Z",
"endTimeUtc": "2019-01-06T16:20:11.4043137Z",
"type": "import",
"status": "completed",
"progress": 100,
"outputBlobContainerUri": "",
"excludeKeysInExport": false,
"useSecondaryStorageAsSource": false
}
Note, that the above steps 4. and 5. can be implemented using an Azure Functions to hide all details related to the storage and iot hub.