int main(void)
{
    TRANSPORT_HANDLE transport_handle;
    IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol;
    IOTHUB_DEVICE_CLIENT_HANDLE device_handle1;
    IOTHUB_DEVICE_CLIENT_HANDLE device_handle2;

#ifdef SAMPLE_AMQP
    protocol = AMQP_Protocol;
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
    protocol = AMQP_Protocol_over_WebSocketsTls;
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS

    (void)printf("Starting the IoTHub client sample C2D methods on AMQP over WebSockets with multiplexing ...\r\n");

    // Used to initialize IoTHub SDK subsystem
    (void)IoTHub_Init();

    if ((transport_handle = IoTHubTransport_Create(protocol, hubName, hubSuffix)) == NULL)
    {
        (void)printf("Failed to creating the protocol handle.\r\n");
    }
    else
    {
        IOTHUB_CLIENT_CONFIG client_config1;
        client_config1.deviceId = deviceId1;
        client_config1.deviceKey = deviceKey1;
        client_config1.deviceSasToken = NULL;
        client_config1.iotHubName = hubName;
        client_config1.iotHubSuffix = hubSuffix;
        client_config1.protocol = protocol;
        client_config1.protocolGatewayHostName = NULL;

        IOTHUB_CLIENT_CONFIG client_config2;
        client_config2.deviceId = deviceId2;
        client_config2.deviceKey = deviceKey2;
        client_config2.deviceSasToken = NULL;
        client_config2.iotHubName = hubName;
        client_config2.iotHubSuffix = hubSuffix;
        client_config2.protocol = protocol;
        client_config2.protocolGatewayHostName = NULL;

        if ((device_handle1 = IoTHubDeviceClient_CreateWithTransport(transport_handle, &client_config1)) == NULL)
        {
            (void)printf("ERROR: iotHubClientHandle1 is NULL!\r\n");
        }
        else if ((device_handle2 = IoTHubDeviceClient_CreateWithTransport(transport_handle, &client_config2)) == NULL)
        {
            (void)printf("ERROR: iotHubClientHandle1 is NULL!\r\n");
        }
        else
        {
            // Set any option that are neccessary.
            // For available options please see the iothub_sdk_options.md documentation
            //bool traceOn = true;
            //IoTHubDeviceClient_SetOption(device_handle1, OPTION_LOG_TRACE, &traceOn);
            //IoTHubDeviceClient_SetOption(device_handle2, OPTION_LOG_TRACE, &traceOn);
#ifdef SET_TRUSTED_CERT_IN_SAMPLES
            // Setting the Trusted Certificate.  This is only necessary on system without
            // built in certificate stores.
            IoTHubDeviceClient_SetOption(device_handle1, OPTION_TRUSTED_CERT, certificates);
            IoTHubDeviceClient_SetOption(device_handle2, OPTION_TRUSTED_CERT, certificates);
#endif // SET_TRUSTED_CERT_IN_SAMPLES

            /* Here subscribe for C2D methods */
            if (IoTHubDeviceClient_SetDeviceMethodCallback(device_handle1, DeviceMethodCallback, (void*)deviceId1) != IOTHUB_CLIENT_OK)
            {
                (void)printf("ERROR: IoTHubClient_SetDeviceMethodCallback for the first device..........FAILED!\r\n");
            }
            else if (IoTHubDeviceClient_SetDeviceMethodCallback(device_handle2, DeviceMethodCallback, (void*)deviceId2) != IOTHUB_CLIENT_OK)
            {
                (void)printf("ERROR: IoTHubClient_SetDeviceMethodCallback for the second device..........FAILED!\r\n");
            }
            else
            {
                (void)printf("IoTHubClient_SetMessageCallback...successful.\r\n");
                (void)printf("Waiting for C2D methods ...\r\n");

                (void)printf("Press enter to close application\r\n");
                (void)getchar();
            }

            // Clean up the iothub sdk handle
            IoTHubDeviceClient_Destroy(device_handle1);
            IoTHubDeviceClient_Destroy(device_handle2);
        }
        IoTHubTransport_Destroy(transport_handle);
        // Free all the sdk subsystem
        IoTHub_Deinit();
    }
    return 0;
}
void iothub_client_sample_http_run(void)
{
    TRANSPORT_HANDLE httpTransport;
    IOTHUB_CLIENT_HANDLE iothubClient1;
    IOTHUB_CLIENT_HANDLE iothubClient2;


    EVENT_INSTANCE messages1[MESSAGE_COUNT];
    EVENT_INSTANCE messages2[MESSAGE_COUNT];
    double avgWindSpeed = 10.0;
    double minTemperature = 20.0;
    double minHumidity = 60.0;
    double temperature = 0;
    double humidity = 0;
    int receiveContext1 = 0;
    int receiveContext2 = 0;

    srand((unsigned int)time(NULL));

    callbackCounter = 0;

    if (platform_init() != 0)
    {
        printf("Failed to initialize the platform.\r\n");
    }
    else
    {
        (void)printf("Starting the IoTHub client sample HTTP with Shared connection...\r\n");


        if ((httpTransport = IoTHubTransport_Create(HTTP_Protocol, hubName, hubSuffix)) == NULL)
        {
            (void)printf("ERROR: httpTransport is NULL\r\n");
        }
        else
        {
            IOTHUB_CLIENT_CONFIG config1;
            config1.deviceId = deviceId1;
            config1.deviceKey = deviceKey1;
            config1.protocol = HTTP_Protocol;
            config1.iotHubName = NULL;
            config1.iotHubSuffix = NULL;
            config1.deviceSasToken = NULL;
            if ((iothubClient1 = IoTHubClient_CreateWithTransport(httpTransport, &config1)) == NULL)
            {
                (void)printf("ERROR: 1st device handle is NULL\r\n");
            }
            else
            {
                IOTHUB_CLIENT_CONFIG config2;
                config2.deviceId = deviceId2;
                config2.deviceKey = deviceKey2;
                config2.protocol = HTTP_Protocol;
                config2.iotHubName = NULL;
                config2.iotHubSuffix = NULL;
                config2.deviceSasToken = NULL;
                if ((iothubClient2 = IoTHubClient_CreateWithTransport(httpTransport, &config2)) == NULL)
                {
                    (void)printf("ERROR: 2nd device handle is NULL\r\n");
                }
                else
                {
                    unsigned int timeout = 241000;
                    // Because it can poll "after 9 seconds" polls will happen effectively // at ~10 seconds.
                    // Note that for scalabilty, the default value of minimumPollingTime
                    // is 25 minutes. For more information, see:
                    // https://azure.microsoft.com/documentation/articles/iot-hub-devguide/#messaging
                    unsigned int minimumPollingTime = 9;
                    iothub_client_sample_http_setoptions(iothubClient1, timeout, minimumPollingTime);
                    iothub_client_sample_http_setoptions(iothubClient2, timeout, minimumPollingTime);

                    // Setting message callbacks so we can receive commands
                    if (IoTHubClient_SetMessageCallback(iothubClient1, ReceiveMessageCallback, &receiveContext1) != IOTHUB_CLIENT_OK)
                    {
                        (void)printf("ERROR: IoTHubClient_LL_SetMessageCallback 1st device..........FAILED!\r\n");
                    }
                    else
                    {
                        if (IoTHubClient_SetMessageCallback(iothubClient2, ReceiveMessageCallback, &receiveContext2) != IOTHUB_CLIENT_OK)
                        {
                            (void)printf("ERROR: IoTHubClient_LL_SetMessageCallback 2nd device..........FAILED!\r\n");
                        }
                        else
                        {
                            // Now that we are ready to receive commands, let's send some messages
                            int i;

                            (void)printf("IoTHubClient_LL_SetMessageCallback...successful.\r\n");

                            for (i = 0; i < MESSAGE_COUNT; i++)
                            {
                                temperature = minTemperature + (rand() % 10);
                                humidity = minHumidity +  (rand() % 20);

                                sprintf_s(msgText, sizeof(msgText), "{\"deviceId\": \"%s\",\"windSpeed\":%.2f,\"temperature\":%.2f,\"humidity\":%.2f}", deviceId1, avgWindSpeed + (rand() % 4 + 2), temperature, humidity);
                                iothub_client_sample_http_send_one_msg(iothubClient1, &messages1[i], i);

                                temperature = minTemperature + (rand() % 10);
                                humidity = minHumidity +  (rand() % 20);

                                sprintf_s(msgText, sizeof(msgText), "{\"deviceId\": \"%s\",\"windSpeed\":%.2f,\"temperature\":%.2f,\"humidity\":%.2f}", deviceId2, avgWindSpeed + (rand() % 4 + 2), temperature, humidity);
                                iothub_client_sample_http_send_one_msg(iothubClient2, &messages2[i], i);
                            }
                            // Wait for any incoming messages
                            (void)printf("Press any key to exit the application. \r\n");
                            (void)getchar();
                        }
                    }
                    IoTHubClient_Destroy(iothubClient2);
                }
                IoTHubClient_Destroy(iothubClient1);
            }
            IoTHubTransport_Destroy(httpTransport);
        }
        platform_deinit();
    }
}
void iothub_client_sample_amqp_run(void)
{
    TRANSPORT_HANDLE transport_handle;
    IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle1;
    IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle2;

    EVENT_INSTANCE messages_device1[MESSAGE_COUNT];
    EVENT_INSTANCE messages_device2[MESSAGE_COUNT];

    g_continueRunning = true;

    //callbackCounter = 0;
    int receiveContext1 = 0;
    int receiveContext2 = 0;

    (void)printf("Starting the IoTHub client sample AMQP...\r\n");

    if (platform_init() != 0)
    {
        printf("Failed to initialize the platform.\r\n");
    }
    else
    {
        if ((transport_handle = IoTHubTransport_Create(AMQP_Protocol, hubName, hubSuffix)) == NULL)
        {
            printf("Failed to creating the protocol handle.\r\n");
        }
        else
        {
            IOTHUB_CLIENT_DEVICE_CONFIG config1;
            config1.deviceId = deviceId1;
            config1.deviceKey = deviceKey1;
            config1.deviceSasToken = NULL;
            config1.protocol = AMQP_Protocol;
            config1.transportHandle = IoTHubTransport_GetLLTransport(transport_handle);

            IOTHUB_CLIENT_DEVICE_CONFIG config2;
            config2.deviceId = deviceId2;
            config2.deviceKey = deviceKey2;
            config2.deviceSasToken = NULL;
            config2.protocol = AMQP_Protocol;
            config2.transportHandle = IoTHubTransport_GetLLTransport(transport_handle);

            if ((iotHubClientHandle1 = IoTHubClient_LL_CreateWithTransport(&config1)) == NULL)
            {
                (void)printf("ERROR: iotHubClientHandle1 is NULL!\r\n");
            }
            else if ((iotHubClientHandle2 = IoTHubClient_LL_CreateWithTransport(&config2)) == NULL)
            {
                (void)printf("ERROR: iotHubClientHandle1 is NULL!\r\n");
            }
            else
            {
                bool traceOn = true;
                IoTHubClient_LL_SetOption(iotHubClientHandle1, OPTION_LOG_TRACE, &traceOn);

    #ifdef SET_TRUSTED_CERT_IN_SAMPLES
                // For mbed add the certificate information
                if (IoTHubClient_LL_SetOption(iotHubClientHandle1, OPTION_TRUSTED_CERT, certificates) != IOTHUB_CLIENT_OK)
                {
                    printf("failure to set option \"TrustedCerts\"\r\n");
                }
    #endif // SET_TRUSTED_CERT_IN_SAMPLES

                if (create_events(messages_device1, config1.deviceId) != 0 || create_events(messages_device2, config2.deviceId) != 0)
                {
                    (void)printf("ERROR: failed creating events for the devices..........FAILED!\r\n");
                }
                /* Setting Message call back, so we can receive Commands. */
                else if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle1, ReceiveMessageCallback, &receiveContext1) != IOTHUB_CLIENT_OK)
                {
                    (void)printf("ERROR: IoTHubClient_SetMessageCallback for device 1..........FAILED!\r\n");
                }
                else if (IoTHubClient_LL_SetMessageCallback(iotHubClientHandle2, ReceiveMessageCallback, &receiveContext2) != IOTHUB_CLIENT_OK)
                {
                    (void)printf("ERROR: IoTHubClient_SetMessageCallback for device 2..........FAILED!\r\n");
                }
                else
                {
                    (void)printf("IoTHubClient_SetMessageCallback...successful.\r\n");

                    /* Now that we are ready to receive commands, let's send some messages */
                    size_t iterator = 0;
                    do
                    {
                        if (iterator < MESSAGE_COUNT)
                        {
                            if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle1, messages_device1[iterator].messageHandle, SendConfirmationCallback, &messages_device1[iterator]) != IOTHUB_CLIENT_OK)
                            {
                                (void)printf("ERROR: IoTHubClient_SendEventAsync for device 1..........FAILED!\r\n");
                            }
                            else if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle2, messages_device2[iterator].messageHandle, SendConfirmationCallback, &messages_device2[iterator]) != IOTHUB_CLIENT_OK)
                            {
                                (void)printf("ERROR: IoTHubClient_SendEventAsync for device 2..........FAILED!\r\n");
                            }
                            else
                            {
                                (void)printf("IoTHubClient_SendEventAsync accepted data for transmission to IoT Hub.\r\n");
                            }

                            IoTHubMessage_Destroy(messages_device1[iterator].messageHandle);
                            IoTHubMessage_Destroy(messages_device2[iterator].messageHandle);
                        }

                        IoTHubClient_LL_DoWork(iotHubClientHandle1);
                        IoTHubClient_LL_DoWork(iotHubClientHandle2);
                        ThreadAPI_Sleep(1);

                        iterator++;
                    } while (g_continueRunning);

                    (void)printf("iothub_client_sample_mqtt has gotten quit message, call DoWork %d more time to complete final sending...\r\n", DOWORK_LOOP_NUM);
                    for (size_t index = 0; index < DOWORK_LOOP_NUM; index++)
                    {
                        IoTHubClient_LL_DoWork(iotHubClientHandle1);
                        ThreadAPI_Sleep(1);
                    }
                }
                IoTHubClient_LL_Destroy(iotHubClientHandle1);
                IoTHubClient_LL_Destroy(iotHubClientHandle2);
            }
            IoTHubTransport_Destroy(transport_handle);
        }
        platform_deinit();
    }
}
int main(void)
{
    TRANSPORT_HANDLE transport_handle;
    IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol;
    IOTHUB_DEVICE_CLIENT_LL_HANDLE device_ll_handle1;
    IOTHUB_DEVICE_CLIENT_LL_HANDLE device_ll_handle2;

#ifdef SAMPLE_AMQP
    protocol = AMQP_Protocol;
#endif // SAMPLE_AMQP
#ifdef SAMPLE_AMQP_OVER_WEBSOCKETS
    protocol = AMQP_Protocol_over_WebSocketsTls;
#endif // SAMPLE_AMQP_OVER_WEBSOCKETS
#ifdef SAMPLE_HTTP
    protocol = HTTP_Protocol;
#endif // SAMPLE_HTTP

    g_continueRunning = true;

    //callbackCounter = 0;
    int receiveContext1 = 0;
    int receiveContext2 = 0;

    (void)printf("Starting the IoTHub client shared sample.  Send `quit` message to either device to close...\r\n");

    // Used to initialize IoTHub SDK subsystem
    (void)IoTHub_Init();

    if ((transport_handle = IoTHubTransport_Create(protocol, hubName, hubSuffix)) == NULL)
    {
        printf("Failed to creating the protocol handle.\r\n");
    }
    else
    {
        EVENT_INSTANCE device1_event;
        EVENT_INSTANCE device2_event;

        device1_event.deviceId = deviceId1;

        IOTHUB_CLIENT_DEVICE_CONFIG config1 = { 0 };
        config1.deviceId = deviceId1;
        config1.deviceKey = deviceKey1;
        config1.deviceSasToken = NULL;
        config1.protocol = protocol;
        config1.transportHandle = IoTHubTransport_GetLLTransport(transport_handle);

        device2_event.deviceId = deviceId2;

        IOTHUB_CLIENT_DEVICE_CONFIG config2 = { 0 };
        config2.deviceId = deviceId2;
        config2.deviceKey = deviceKey2;
        config2.deviceSasToken = NULL;
        config2.protocol = protocol;
        config2.transportHandle = IoTHubTransport_GetLLTransport(transport_handle);

        if ((device_ll_handle1 = IoTHubDeviceClient_LL_CreateWithTransport(&config1)) == NULL)
        {
            (void)printf("ERROR: iotHubClientHandle1 is NULL!\r\n");
        }
        else if ((device_ll_handle2 = IoTHubDeviceClient_LL_CreateWithTransport(&config2)) == NULL)
        {
            (void)printf("ERROR: iotHubClientHandle1 is NULL!\r\n");
        }
        else
        {
            // Set any option that are neccessary.
            // For available options please see the iothub_sdk_options.md documentation
            //bool traceOn = true;
            //IoTHubDeviceClient_LL_SetOption(device_ll_handle1, OPTION_LOG_TRACE, &traceOn);
            //IoTHubDeviceClient_LL_SetOption(device_ll_handle2, OPTION_LOG_TRACE, &traceOn);
#ifdef SET_TRUSTED_CERT_IN_SAMPLES
            // Setting the Trusted Certificate.  This is only necessary on system without
            // built in certificate stores.
            IoTHubDeviceClient_LL_SetOption(device_ll_handle1, OPTION_TRUSTED_CERT, certificates);
            IoTHubDeviceClient_LL_SetOption(device_ll_handle2, OPTION_TRUSTED_CERT, certificates);
#endif // SET_TRUSTED_CERT_IN_SAMPLES

#ifdef SAMPLE_HTTP
            unsigned int timeout = 241000;
            // Because it can poll "after 9 seconds" polls will happen effectively // at ~10 seconds.
            // Note that for scalabilty, the default value of minimumPollingTime
            // is 25 minutes. For more information, see:
            // https://azure.microsoft.com/documentation/articles/iot-hub-devguide/#messaging
            unsigned int minimumPollingTime = 9;
            IoTHubDeviceClient_LL_SetOption(device_ll_handle1, OPTION_MIN_POLLING_TIME, &minimumPollingTime);
            IoTHubDeviceClient_LL_SetOption(device_ll_handle1, OPTION_HTTP_TIMEOUT, &timeout);
            IoTHubDeviceClient_LL_SetOption(device_ll_handle2, OPTION_MIN_POLLING_TIME, &minimumPollingTime);
            IoTHubDeviceClient_LL_SetOption(device_ll_handle2, OPTION_HTTP_TIMEOUT, &timeout);
#endif // SAMPLE_HTTP

            /* Setting Message call back, so we can receive Commands. */
            (void)IoTHubDeviceClient_LL_SetMessageCallback(device_ll_handle1, ReceiveMessageCallback, &receiveContext1);
            (void)IoTHubDeviceClient_LL_SetMessageCallback(device_ll_handle2, ReceiveMessageCallback, &receiveContext2);

            /* Now that we are ready to receive commands, let's send some messages */
            size_t messages_sent = 0;
            IOTHUB_MESSAGE_HANDLE message_handle;
            do
            {
                if (messages_sent < MESSAGE_COUNT)
                {
                    // Create the event hub message
                    message_handle = create_events(&device1_event);
                    (void)IoTHubDeviceClient_LL_SendEventAsync(device_ll_handle1, message_handle, SendConfirmationCallback, &device1_event);
                    // The message is copied to the sdk so the we can destroy it
                    IoTHubMessage_Destroy(message_handle);

                    message_handle = create_events(&device2_event);
                    (void)IoTHubDeviceClient_LL_SendEventAsync(device_ll_handle2, message_handle, SendConfirmationCallback, &device2_event);
                    // The message is copied to the sdk so the we can destroy it
                    IoTHubMessage_Destroy(message_handle);

                    messages_sent++;
                }

                IoTHubDeviceClient_LL_DoWork(device_ll_handle1);
                IoTHubDeviceClient_LL_DoWork(device_ll_handle2);
                ThreadAPI_Sleep(1);
            } while (g_continueRunning);

            (void)printf("client_amqp_shared_sample has gotten quit message, call DoWork %d more time to complete final sending...\r\n", DOWORK_LOOP_NUM);
            for (size_t index = 0; index < DOWORK_LOOP_NUM; index++)
            {
                IoTHubDeviceClient_LL_DoWork(device_ll_handle1);
                IoTHubDeviceClient_LL_DoWork(device_ll_handle2);
                ThreadAPI_Sleep(1);
            }

            // Clean up the iothub sdk handle
            IoTHubDeviceClient_LL_Destroy(device_ll_handle1);
            IoTHubDeviceClient_LL_Destroy(device_ll_handle2);
        }
        IoTHubTransport_Destroy(transport_handle);
        // Free all the sdk subsystem
        IoTHub_Deinit();
    }
    return 0;
}