Azure IoT SDK per dispositivi per C: altre informazioni su IoTHubClientAzure IoT device SDK for C – more about IoTHubClient

Il primo articolo di questa serie ha introdotto Azure IoT SDK per dispositivi per C. e spiegato che l'SDK comprende due livelli architetturali.The first article in this series introduced the Azure IoT device SDK for C. That article explained that there are two architectural layers in SDK. Al livello di base è presente la libreria IoTHubClient che gestisce direttamente la comunicazione con l'hub IoT.At the base is the IoTHubClient library which directly manages communication with IoT Hub. È inclusa anche libreria serializer, che si basa sulla libreria IoTHubClient per fornire i servizi di serializzazione.There's also the serializer library that builds on top of that to provide serialization services. In questo articolo sono forniti dettagli aggiuntivi sulla libreria IoTHubClient.In this article we'll provide additional detail on the IoTHubClient library.

L'articolo precedente descrive come usare la libreria IoTHubClient per inviare eventi all'hub IoT e ricevere messaggi.The previous article described how to use the IoTHubClient library to send events to IoT Hub and receive messages. Questo articolo estende la discussione, spiegando come gestire con più precisione quando inviare e ricevere dati, introducendo le API di livello inferiore.This article extends that discussion by explaining how to more precisely manage when you send and receive data, introducing you to the lower-level APIs. Viene illustrato anche come associare le proprietà agli eventi, e recuperarle dai messaggi, usando le funzionalità di gestione delle proprietà nella libreria IoTHubClient .We'll also explain how to attach properties to events (and retrieve them from messages) using the property handling features in the IoTHubClient library. Saranno infine descritti diversi metodi aggiuntivi per gestire i messaggi ricevuti dall'hub IoT.Finally, we'll provide additional explanation of different ways to handle messages received from IoT Hub.

Questo articolo si conclude con il riepilogo di un paio di vari argomenti, incluse altre informazioni sulle credenziali del dispositivo e come gestire il comportamento della libreria IoTHubClient tramite le opzioni di configurazione.The article concludes by covering a couple of miscellaneous topics, including more about device credentials and how to change the behavior of the IoTHubClient through configuration options.

Per illustrare questi argomenti, si useranno esempi dell'SDK relativi a IoTHubClient.We'll use the IoTHubClient SDK samples to explain these topics. Se si vuole seguire la procedura, vedere le applicazioni iothub_client_sample_http e iothub_client_sample_amqp incluse in Azure IoT SDK per dispositivi per C. Tutto ciò che viene descritto nelle sezioni seguenti è illustrato in questi esempi.If you want to follow along, see the iothub_client_sample_http and iothub_client_sample_amqp applications that are included in the Azure IoT device SDK for C. Everything described in the following sections is demonstrated in these samples.

È possibile trovare il repository GitHub di Azure IoT SDK per dispositivi per C e visualizzare i dettagli dell'API nelle informazioni di riferimento per l'API C.You can find the Azure IoT device SDK for C GitHub repository and view details of the API in the C API reference.

API di livello inferioreThe lower-level APIs

Nell'articolo precedente è descritto il funzionamento di base di IotHubClient nel contesto dell'applicazione iothub_client_sample_amqp.The previous article described the basic operation of the IotHubClient within the context of the iothub_client_sample_amqp application. Spiega ad esempio come inizializzare la libreria con questo codice.For example, it explained how to initialize the library using this code.

IOTHUB_CLIENT_HANDLE iotHubClientHandle;
iotHubClientHandle = IoTHubClient_CreateFromConnectionString(connectionString, AMQP_Protocol);

Spiega anche come inviare eventi con questa chiamata di funzione.It also described how to send events using this function call.

IoTHubClient_SendEventAsync(iotHubClientHandle, message.messageHandle, SendConfirmationCallback, &message);

Viene anche descritto come ricevere messaggi registrando una funzione di callback.The article also described how to receive messages by registering a callback function.

int receiveContext = 0;
IoTHubClient_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, &receiveContext);

L'articolo illustra anche come liberare risorse con codice simile al seguente.The article also showed how to free resources using code such as the following.

IoTHubClient_Destroy(iotHubClientHandle);

Ci sono tuttavia funzioni complementari per ognuna di queste API:However there are companion functions to each of these APIs:

  • IoTHubClient_LL_CreateFromConnectionStringIoTHubClient_LL_CreateFromConnectionString
  • IoTHubClient_LL_SendEventAsyncIoTHubClient_LL_SendEventAsync
  • IoTHubClient_LL_SetMessageCallbackIoTHubClient_LL_SetMessageCallback
  • IoTHubClient_LL_DestroyIoTHubClient_LL_Destroy

Il nome dell'API per tutte queste funzioni include "LL".These functions all include “LL” in the API name. I parametri di ognuna di queste funzioni sono inoltre identici ai rispettivi elementi analoghi non LL.Other than that, the parameters of each of these functions are identical to their non-LL counterparts. Il comportamento di queste funzioni è tuttavia diverso per un aspetto importante.However, the behavior of these functions is different in one important way.

Quando si chiama IoTHubClient_CreateFromConnectionString, le librerie sottostanti creano un nuovo thread che viene eseguito in background.When you call IoTHubClient_CreateFromConnectionString, the underlying libraries create a new thread that runs in the background. Questo thread invia eventi all'hub IoT e ne riceve i messaggi.This thread sends events to, and receives messages from, IoT Hub. Questi thread non vengono creati quando si utilizzano le API "LL".No such thread is created when working with the "LL" APIs. La creazione del thread in background è un aspetto pratico per lo sviluppatore.The creation of the background thread is a convenience to the developer. Non occorre preoccuparsi in modo esplicito dell'invio di eventi e della ricezione di messaggi dall'hub IoT, perché tutto avviene automaticamente in background.You don’t have to worry about explicitly sending events and receiving messages from IoT Hub -- it happens automatically in the background. Al contrario, le API "LL" forniscono il controllo esplicito sulla comunicazione con l'hub IoT, se necessario.In contrast, the "LL" APIs give you explicit control over communication with IoT Hub, if you need it.

Per comprendere meglio questo aspetto, si esaminerà un esempio:To understand this better, let’s look at an example:

Quando si chiama IoTHubClient_SendEventAsync, si inserisce effettivamente l'evento in un buffer.When you call IoTHubClient_SendEventAsync, what you're actually doing is putting the event in a buffer. Il thread in background creato quando si chiama IoTHubClient_CreateFromConnectionString monitora continuamente questo buffer e invia tutti i dati che contiene all'hub IoT.The background thread created when you call IoTHubClient_CreateFromConnectionString continually monitors this buffer and sends any data that it contains to IoT Hub. Ciò avviene in background contemporaneamente all'esecuzione di altre attività da parte del thread principale.This happens in the background at the same time that the main thread is performing other work.

In modo analogo, quando si registra una funzione di callback per i messaggi tramite IoTHubClient_SetMessageCallback, si indica all'SDK di fare in modo che il thread in background richiami la funzione di callback quando si riceve un messaggio, indipendentemente dal thread principale.Similarly, when you register a callback function for messages using IoTHubClient_SetMessageCallback, you're instructing the SDK to have the background thread invoke the callback function when a message is received, independent of the main thread.

Le API "LL" non creano un thread in background.The "LL" APIs don’t create a background thread. È necessario invece chiamare una nuova API per inviare e ricevere esplicitamente i dati dall'hub IoT.Instead, a new API must be called to explicitly send and receive data from IoT Hub. Questo approccio è illustrato nell'esempio seguente.This is demonstrated in the following example.

L'applicazione iothub_client_sample_http inclusa nell'SDK fornisce una dimostrazione delle API di livello inferiore.The iothub_client_sample_http application that’s included in the SDK demonstrates the lower-level APIs. In questo esempio, si inviano eventi all'hub IoT con codice simile al seguente:In that sample, we send events to IoT Hub with code such as the following:

EVENT_INSTANCE message;
sprintf_s(msgText, sizeof(msgText), "Message_%d_From_IoTHubClient_LL_Over_HTTP", i);
message.messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, strlen(msgText));

IoTHubClient_LL_SendEventAsync(iotHubClientHandle, message.messageHandle, SendConfirmationCallback, &message)

Le prime tre righe creano il messaggio e l'ultima riga invia l'evento.The first three lines create the message, and the last line sends the event. Tuttavia, come detto in precedenza, "inviare" l'evento significa che i dati vengono semplicemente inseriti in un buffer.However, as mentioned previously, "sending" the event means that the data is simply placed in a buffer. Quando si chiama IoTHubClient_LL_SendEventAsync, non viene trasmesso nulla in rete.Nothing is transmitted on the network when we call IoTHubClient_LL_SendEventAsync. Per inserire effettivamente i dati nell'hub IoT, è necessario chiamare IoTHubClient_LL_DoWork come in questo esempio:In order to actually ingress the data to IoT Hub, you must call IoTHubClient_LL_DoWork, as in this example:

while (1)
{
    IoTHubClient_LL_DoWork(iotHubClientHandle);
    ThreadAPI_Sleep(1000);
}

Questo codice dall'applicazione iothub_client_sample_http chiama ripetutamente IoTHubClient_LL_DoWork.This code (from the iothub_client_sample_http application) repeatedly calls IoTHubClient_LL_DoWork. Ogni volta che viene chiamato, IoTHubClient_LL_DoWork invia alcuni eventi dal buffer all'hub IoT e recupera un messaggio in coda inviato al dispositivo.Each time IoTHubClient_LL_DoWork is called, it sends some events from the buffer to IoT Hub and it retrieves a queued message being sent to the device. In quest'ultimo caso, se è stata registrata una funzione di callback per i messaggi, verrà richiamato il callback, presupponendo la presenza di messaggi nella coda.The latter case means that if we registered a callback function for messages, then the callback is invoked (assuming any messages are queued up). Questa funzione di callback sarà stata registrata con codice simile al seguente:We would have registered such a callback function with code such as the following:

IoTHubClient_LL_SetMessageCallback(iotHubClientHandle, ReceiveMessageCallback, &receiveContext)

Il motivo per cui si chiama spesso IoTHubClient_LL_DoWork in un ciclo è dovuto al fatto che a ogni chiamata vengono inviati alcuni eventi memorizzati nel buffer all'hub IoT e viene recuperato il successivo messaggio in coda per il dispositivo.The reason that IoTHubClient_LL_DoWork is often called in a loop is that each time it’s called, it sends some buffered events to IoT Hub and retrieves the next message queued up for the device. Non è garantito che a ogni chiamata siano inviati tutti gli eventi nel buffer o siano recuperati tutti i messaggi in coda.Each call isn’t guaranteed to send all buffered events or to retrieve all queued messages. Se si vuole inviare tutti gli eventi nel buffer e quindi continuare con altre attività di elaborazione, è possibile sostituire questo ciclo con codice simile al seguente:If you want to send all events in the buffer and then continue on with other processing you can replace this loop with code such as the following:

IOTHUB_CLIENT_STATUS status;

while ((IoTHubClient_LL_GetSendStatus(iotHubClientHandle, &status) == IOTHUB_CLIENT_OK) && (status == IOTHUB_CLIENT_SEND_STATUS_BUSY))
{
    IoTHubClient_LL_DoWork(iotHubClientHandle);
    ThreadAPI_Sleep(1000);
}

Questo codice chiama IoTHubClient_LL_DoWork finché tutti gli eventi non saranno stati inviati all'hub IoT.This code calls IoTHubClient_LL_DoWork until all events in the buffer have been sent to IoT Hub. Non significa però che si siano ricevuti anche tutti i messaggi in coda.Note this does not also imply that all queued messages have been received. Questo comportamento è dovuto in parte al fatto che la verifica di "tutti" i messaggi non è un'azione deterministica.Part of the reason for this is that checking for "all" messages isn’t as deterministic an action. Cosa accadrebbe che si recuperassero "tutti" i messaggi, ma subito dopo ne venisse inviato un altro al dispositivo?What happens if you retrieve "all" of the messages, but then another one is sent to the device immediately after? Un modo migliore per gestire questo meccanismo consiste nell'usare un timeout programmato.A better way to deal with that is with a programmed timeout. Ad esempio, la funzione di callback dei messaggi potrebbe reimpostare un timer ogni volta che viene richiamata.For example, the message callback function could reset a timer every time it’s invoked. Si può quindi scrivere la logica per continuare l'elaborazione, ad esempio, non sono stati ricevuti messaggi negli ultimi X secondi.You can then write logic to continue processing if, for example, no messages have been received in the last X seconds.

Una volta completato l'inserimento degli eventi e la ricezione dei messaggi, accertarsi di chiamare la funzione corrispondente per pulire le risorse.When you’re finished ingressing events and receiving messages, be sure to call the corresponding function to clean up resources.

IoTHubClient_LL_Destroy(iotHubClientHandle);

Sostanzialmente è disponibile un solo set di API per inviare e ricevere dati con un thread in background e un altro set di API che esegue la stessa operazione senza il thread in background.Basically there’s only one set of APIs to send and receive data with a background thread and another set of APIs that does the same thing without the background thread. Molti sviluppatori potrebbero preferire le API non LL, ma le API di livello inferiore sono utili quando lo sviluppatore vuole avere il controllo esplicito delle trasmissioni in rete.A lot of developers may prefer the non-LL APIs, but the lower-level APIs are useful when the developer wants explicit control over network transmissions. Ad esempio, alcuni dispositivi raccolgono dati nel tempo e solo eventi in ingresso a intervalli specificati, come una volta all'ora o una volta al giorno.For example, some devices collect data over time and only ingress events at specified intervals (for example, once an hour or once a day). Le API di livello inferiore consentono di controllare in modo esplicito quando inviare e ricevere dati dall'hub IoT.The lower-level APIs give you the ability to explicitly control when you send and receive data from IoT Hub. Altri preferiscono la semplicità offerta dalle API di livello inferiore.Others will simply prefer the simplicity that the lower-level APIs provide. Tutto avviene nel thread principale, invece di eseguire una parte delle operazioni in background.Everything happens on the main thread rather than some work happening in the background.

Qualunque sia il modello scelto, assicurarsi di usare le API in modo coerente.Whichever model you choose, be sure to be consistent in which APIs you use. Se si inizia a chiamare IoTHubClient_LL_CreateFromConnectionString, assicurarsi di usare solo le API di livello inferiore corrispondenti per tutte le attività successive:If you start by calling IoTHubClient_LL_CreateFromConnectionString, be sure you only use the corresponding lower-level APIs for any follow-up work:

  • IoTHubClient_LL_SendEventAsyncIoTHubClient_LL_SendEventAsync
  • IoTHubClient_LL_SetMessageCallbackIoTHubClient_LL_SetMessageCallback
  • IoTHubClient_LL_DestroyIoTHubClient_LL_Destroy
  • IoTHubClient_LL_DoWorkIoTHubClient_LL_DoWork

È vero comunque anche il contrario.The opposite is true as well. Se si inizia con IoTHubClient_CreateFromConnectionString, continuare a usare le API non LL per tutte le altre attività di elaborazione.If you start with IoTHubClient_CreateFromConnectionString, then use the non-LL APIs for any additional processing.

Per un esempio completo delle API di livello inferiore, vedere l'applicazione iothub_client_sample_http in Azure IoT SDK per dispositivi per C.In the Azure IoT device SDK for C, see the iothub_client_sample_http application for a complete example of the lower-level APIs. Si può fare riferimento all'applicazione iothub_client_sample_amqp per un esempio completo delle API non LL.The iothub_client_sample_amqp application can be referenced for a full example of the non-LL APIs.

Gestione delle proprietàProperty handling

Fino a questo punto, nel descrivere l'invio di dati si è fatto riferimento al corpo del messaggio.So far when we've described sending data, we've been referring to the body of the message. Si consideri ad esempio questo codice:For example, consider this code:

EVENT_INSTANCE message;
sprintf_s(msgText, sizeof(msgText), "Hello World");
message.messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)msgText, strlen(msgText));
IoTHubClient_LL_SendEventAsync(iotHubClientHandle, message.messageHandle, SendConfirmationCallback, &message)

Questo esempio invia l'evento all'hub IoT con il testo "Hello World".This example sends a message to IoT Hub with the text "Hello World." L'hub IoT consente tuttavia di associare proprietà a ogni messaggio.However, IoT Hub also allows properties to be attached to each message. Le proprietà sono coppie nome/valore che possono essere associate al messaggio.Properties are name/value pairs that can be attached to the message. Ad esempio, è possibile modificare il codice precedente per associare una proprietà al messaggio.For example, we can modify the previous code to attach a property to the message:

MAP_HANDLE propMap = IoTHubMessage_Properties(message.messageHandle);
sprintf_s(propText, sizeof(propText), "%d", i);
Map_AddOrUpdate(propMap, "SequenceNumber", propText);

Per iniziare, chiamare IoTHubMessage_Properties e passare l'handle del messaggio.We start by calling IoTHubMessage_Properties and passing it the handle of our message. Verrà restituito un riferimento a MAP_HANDLE che consente di iniziare ad aggiungere proprietà.What we get back is a MAP_HANDLE reference that enables us to start adding properties. Quest'ultima operazione si esegue chiamando Map_AddOrUpdate, che riceve un riferimento a MAP_HANDLE, il nome della proprietà e il valore della proprietà.The latter is accomplished by calling Map_AddOrUpdate, which takes a reference to a MAP_HANDLE, the property name, and the property value. Con questa API è possibile aggiungere tutte le proprietà necessarie.With this API we can add as many properties as we like.

Quando l'evento viene letto da Hub eventi, il ricevitore può enumerare le proprietà e recuperare i valori corrispondenti.When the event is read from Event Hubs, the receiver can enumerate the properties and retrieve their corresponding values. Ad esempio, in .NET questa operazione verrebbe eseguita con l'accesso alla raccolta delle proprietà nell'oggetto EventData.For example, in .NET this would be accomplished by accessing the Properties collection on the EventData object.

Nell'esempio precedente le proprietà vengono associate a un evento inviato all'hub IoT.In the previous example, we’re attaching properties to an event that we send to IoT Hub. Le proprietà possono anche essere associate ai messaggi ricevuti dall'hub IoT.Properties can also be attached to messages received from IoT Hub. Per recuperare le proprietà da un messaggio, è possibile usare codice come il seguente nella funzione di callback del messaggio:If we want to retrieve properties from a message, we can use code such as the following in our message callback function:

static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
{
    . . .

    // Retrieve properties from the message
    MAP_HANDLE mapProperties = IoTHubMessage_Properties(message);
    if (mapProperties != NULL)
    {
        const char*const* keys;
        const char*const* values;
        size_t propertyCount = 0;
        if (Map_GetInternals(mapProperties, &keys, &values, &propertyCount) == MAP_OK)
        {
            if (propertyCount > 0)
            {
                printf("Message Properties:\r\n");
                for (size_t index = 0; index < propertyCount; index++)
                {
                    printf("\tKey: %s Value: %s\r\n", keys[index], values[index]);
                }
                printf("\r\n");
            }
        }
    }

    . . .
}

La chiamata a IoTHubMessage_Properties restituisce il riferimento a MAP_HANDLE.The call to IoTHubMessage_Properties returns the MAP_HANDLE reference. Il riferimento viene quindi passato a Map_GetInternals per ottenere un riferimento a una matrice di coppie nome/valore, oltre a un conteggio delle proprietà.We then pass that reference to Map_GetInternals to obtain a reference to an array of the name/value pairs (as well as a count of the properties). A questo punto, si tratta semplicemente di enumerare le proprietà per ottenere i valori necessari.At that point it's a simple matter of enumerating the properties to get to the values we want.

Non si devono usare proprietà nell'applicazione,You don't have to use properties in your application. ma se è necessario impostarle negli eventi o recuperarle dai messaggi, la libreria IoTHubClient facilita l'operazione.However, if you need to set them on events or retrieve them from messages, the IoTHubClient library makes it easy.

Gestione dei messaggiMessage handling

Come spiegato in precedenza, quando arriva un messaggio dall'hub IoT, la libreria IoTHubClient risponde richiamando una funzione di callback registrata.As stated previously, when messages arrive from IoT Hub the IoTHubClient library responds by invoking a registered callback function. Un parametro restituito da questa funzione merita tuttavia qualche spiegazione aggiuntiva.There is a return parameter of this function that deserves some additional explanation. Ecco un estratto della funzione di callback nell'applicazione di esempio iothub_client_sample_http:Here’s an excerpt of the callback function in the iothub_client_sample_http sample application:

static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
{
    . . .
    return IOTHUBMESSAGE_ACCEPTED;
}

Il tipo restituito è IOTHUBMESSAGE_DISPOSITION_RESULT e in questo caso specifico verrà restituito IOTHUBMESSAGE_ACCEPTED.Note that the return type is IOTHUBMESSAGE_DISPOSITION_RESULT and in this particular case we return IOTHUBMESSAGE_ACCEPTED. Sono presenti altri valori che possono essere restituiti da questa funzione e che modificano il modo in cui la libreria IoTHubClient risponde al callback del messaggio.There are other values we can return from this function that change how the IoTHubClient library reacts to the message callback. Ecco le opzioni.Here are the options.

  • IOTHUBMESSAGE_ACCEPTED: il messaggio è stato elaborato correttamente.IOTHUBMESSAGE_ACCEPTED – The message has been processed successfully. La libreria IoTHubClient non richiamerà di nuovo la funzione di callback con lo stesso messaggio.The IoTHubClient library will not invoke the callback function again with the same message.
  • IOTHUBMESSAGE_REJECTED: il messaggio non è stato elaborato e non si prevede di farlo in futuro.IOTHUBMESSAGE_REJECTED – The message was not processed and there is no desire to do so in the future. La libreria IoTHubClient non dovrà richiamare di nuovo la funzione di callback con lo stesso messaggio.The IoTHubClient library should not invoke the callback function again with the same message.
  • IOTHUBMESSAGE_ABANDONED: il messaggio non è stato elaborato, ma la libreria IoTHubClient dovrà richiamare di nuovo la funzione di callback con lo stesso messaggio.IOTHUBMESSAGE_ABANDONED – The message was not processed successfully, but the IoTHubClient library should invoke the callback function again with the same message.

Per i primo due codici restituiti la libreria IoTHubClient invia un messaggio all'hub IoT indicando che il messaggio dovrà essere eliminato dalla coda del dispositivo e non essere recapitato di nuovo.For the first two return codes, the IoTHubClient library sends a message to IoT Hub indicating that the message should be deleted from the device queue and not delivered again. L'effetto in definitiva è lo stesso, ovvero il messaggio viene eliminato dalla coda del dispositivo, ma rimane ancora la registrazione se il messaggio è stato accettato o rifiutato.The net effect is the same (the message is deleted from the device queue), but whether the message was accepted or rejected is still recorded. La registrazione di questa distinzione è utile per i mittenti del messaggio, che possono rimanere in ascolto dei commenti e scoprire se un dispositivo ha accettato o rifiutato un messaggio specifico.Recording this distinction is useful to senders of the message who can listen for feedback and find out if a device has accepted or rejected a particular message.

Nell'ultimo caso, viene inviato un messaggio anche all'hub IoT, ma con l'indicazione che il messaggio dovrà essere recapitato di nuovo.In the last case a message is also sent to IoT Hub, but it indicates that the message should be redelivered. In genere, un messaggio viene abbandonato se si verifica un errore, ma si vuole provare a elaborarlo di nuovo.Typically you’ll abandon a message if you encounter some error but want to try to process the message again. Al contrario, è opportuno rifiutare un messaggio quando si verifica un errore irreversibile o si decide semplicemente che non si vuole elaborare il messaggio.In contrast, rejecting a message is appropriate when you encounter an unrecoverable error (or if you simply decide you don’t want to process the message).

In ogni caso, è sufficiente conoscere i diversi codici restituiti per poter dedurre il comportamento che si vuole ottenere dalla libreria IoTHubClient .In any case, be aware of the different return codes so that you can elicit the behavior you want from the IoTHubClient library.

Credenziali del dispositivo alternativeAlternate device credentials

Come spiegato in precedenza, la prima cosa da fare quando si usa la libreria IoTHubClient è ottenere un IOTHUB_CLIENT_HANDLE con una chiamata come la seguente:As explained previously, the first thing to do when working with the IoTHubClient library is to obtain a IOTHUB_CLIENT_HANDLE with a call such as the following:

IOTHUB_CLIENT_HANDLE iotHubClientHandle;
iotHubClientHandle = IoTHubClient_CreateFromConnectionString(connectionString, AMQP_Protocol);

Gli argomenti di IoTHubClient_CreateFromConnectionString sono la stringa di connessione del dispositivo e un parametro che indica il protocollo da usare per comunicare con l'hub IoT.The arguments to IoTHubClient_CreateFromConnectionString are the device connection string and a parameter that indicates the protocol we use to communicate with IoT Hub. La stringa di connessione del dispositivo ha un formato simile al seguente:The device connection string has a format that appears as follows:

HostName=IOTHUBNAME.IOTHUBSUFFIX;DeviceId=DEVICEID;SharedAccessKey=SHAREDACCESSKEY

Questa stringa contiene quattro informazioni: nome dell'hub IoT, suffisso dell'hub IoT, ID dispositivo e chiave di accesso condivisa.There are four pieces of information in this string: IoT Hub name, IoT Hub suffix, device ID, and shared access key. Si ottiene il nome di dominio completo (FQDN) di un hub IoT quando si crea l'istanza dell'hub IoT nel portale di Azure. Si avrà così il nome dell'hub IoT (la prima parte dell'FQDN) e il suffisso dell'hub IoT (il resto dell'FQDN).You obtain the fully qualified domain name (FQDN) of an IoT hub when you create your IoT hub instance in the Azure portal — this gives you the IoT hub name (the first part of the FQDN) and the IoT hub suffix (the rest of the FQDN). L'ID dispositivo e la chiave di accesso condiviso si ottengono al momento della registrazione del dispositivo con l'hub IoT, come descritto nell'articolo precedente.You get the device ID and the shared access key when you register your device with IoT Hub (as described in the previous article).

IoTHubClient_CreateFromConnectionString offre un modo per inizializzare la libreria.IoTHubClient_CreateFromConnectionString gives you one way to initialize the library. Se si preferisce, è possibile creare un nuovo IOTHUB_CLIENT_HANDLE usando i singoli parametri invece della stringa di connessione del dispositivo.If you prefer, you can create a new IOTHUB_CLIENT_HANDLE by using these individual parameters rather than the device connection string. Questo risultato si ottiene con il codice seguente:This is achieved with the following code:

IOTHUB_CLIENT_CONFIG iotHubClientConfig;
iotHubClientConfig.iotHubName = "";
iotHubClientConfig.deviceId = "";
iotHubClientConfig.deviceKey = "";
iotHubClientConfig.iotHubSuffix = "";
iotHubClientConfig.protocol = HTTP_Protocol;
IOTHUB_CLIENT_HANDLE iotHubClientHandle = IoTHubClient_LL_Create(&iotHubClientConfig);

Si ottiene lo stesso risultato di IoTHubClient_CreateFromConnectionString.This accomplishes the same thing as IoTHubClient_CreateFromConnectionString.

Può sembrare ovvio che si preferisca usare IoTHubClient_CreateFromConnectionString invece di questo metodo di inizializzazione più dettagliato.It may seem obvious that you would want to use IoTHubClient_CreateFromConnectionString rather than this more verbose method of initialization. Tenere però presente che quando si registra un dispositivo nell'hub IoT, si ottiene un ID dispositivo e una chiave del dispositivo, non una stringa di connessione.Keep in mind, however, that when you register a device in IoT Hub what you get is a device ID and device key (not a connection string). Lo strumento SDK per l'esplorazione dei dispositivi introdotto nell'articolo precedente usa le librerie di Azure IoT SDK per servizi per creare la stringa di connessione del dispositivo da ID dispositivo, chiave del dispositivo e nome host dell'hub IoT.The device explorer SDK tool introduced in the previous article uses libraries in the Azure IoT service SDK to create the device connection string from the device ID, device key, and IoT Hub host name. Può quindi essere preferibile chiamare IoTHubClient_LL_Create, perché evita di dover generare una stringa di connessione.So calling IoTHubClient_LL_Create may be preferable because it saves you the step of generating a connection string. Usare il metodo più pratico.Use whichever method is convenient.

Opzioni di configurazioneConfiguration options

Fino a questo punto, tutto ciò che è stato illustrato sul funzionamento della libreria IoTHubClient riflette il relativo comportamento predefinito.So far everything described about the way the IoTHubClient library works reflects its default behavior. Sono tuttavia disponibili alcune opzioni che si possono impostare per modificare il funzionamento della libreria.However, there are a few options that you can set to change how the library works. Questa operazione viene eseguita sfruttando l'API IoTHubClient_LL_SetOption.This is accomplished by leveraging the IoTHubClient_LL_SetOption API. Considerare questo esempio:Consider this example:

unsigned int timeout = 30000;
IoTHubClient_LL_SetOption(iotHubClientHandle, "timeout", &timeout);

Ci sono un paio di opzioni usate comunemente:There are a couple of options that are commonly used:

  • SetBatching (bool): se true, i dati destinati all'hub IoT vengono inviati in batch.SetBatching (bool) – If true, then data sent to IoT Hub is sent in batches. Se false, i messaggi vengono inviati singolarmente.If false, then messages are sent individually. Il valore predefinito è false.The default is false. Si noti che l'opzione SetBatching si applica solo al protocollo HTTPS e non ai protocolli MQTT o AMQP.Note that the SetBatching option only applies to the HTTPS protocol and not to the MQTT or AMQP protocols.
  • Timeout (unsigned int): questo valore è rappresentato in millisecondi.Timeout (unsigned int) – This value is represented in milliseconds. Se l'invio di una richiesta HTTPS o la ricezione di una risposta richiede più tempo di questo intervallo, si verifica il timeout della connessione.If sending an HTTPS request or receiving a response takes longer than this time, then the connection times out.

L'opzione di invio in batch è importante.The batching option is important. Per impostazione predefinita, la libreria accetta eventi in ingresso singolarmente. Un singolo evento è qualsiasi elemento passato a IoTHubClient_LL_SendEventAsync.By default, the library ingresses events individually (a single event is whatever you pass to IoTHubClient_LL_SendEventAsync). Se l'opzione di invio in batch è true, la libreria raccoglie dal buffer quanti più eventi possibile, fino alle dimensioni massime dei messaggi accettate dall'hub IoT.If the batching option is true, the library collects as many events as it can from the buffer (up to the maximum message size that IoT Hub will accept). Il batch di eventi viene inviato all'hub IoT in una singola chiamata HTTPS. I singoli eventi vengono aggregati in una matrice JSON.The event batch is sent to IoT Hub in a single HTTPS call (the individual events are bundled into a JSON array). In genere l'abilitazione dell'invio in batch consente di ottenere un miglioramento significativo delle prestazioni, perché si riducono le sequenze di andata e ritorno in rete.Enabling batching typically results in big performance gains since you’re reducing network round-trips. Si riduce in modo significativo anche la larghezza di banda, perché si invia un unico set di intestazioni HTTPS con un batch di eventi, invece di un set di intestazioni per ogni singolo evento.It also significantly reduces bandwidth since you are sending one set of HTTPS headers with an event batch rather than a set of headers for each individual event. A meno di avere un motivo specifico per agire diversamente, è consigliabile abilitare l'invio in batch.Unless you have a specific reason to do otherwise, typically you’ll want to enable batching.

Passaggi successiviNext steps

In questo articolo viene descritto in dettaglio il comportamento della libreria IoTHubClient inclusa in Azure IoT SDK per dispositivi per C. Grazie a queste informazioni si dovrebbe avere acquisito una buona conoscenza delle funzionalità della libreria IoTHubClient.This article describes in detail the behavior of the IoTHubClient library found in the Azure IoT device SDK for C. With this information, you should have a good understanding of the capabilities of the IoTHubClient library. L' articolo successivo fornisce dettagli simili sulla libreria serializer .The next article provides similar detail on the serializer library.

Per altre informazioni sullo sviluppo dell'hub IoT, vedere gli Azure IoT SDK.To learn more about developing for IoT Hub, see the Azure IoT SDKs.

Per altre informazioni sulle funzionalità dell'hub IoT, vedere:To further explore the capabilities of IoT Hub, see: