Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
iothub_service_client/src/iothub_devicetwin.c@0:f7f1f0d76dd6, 2018-08-23 (annotated)
- Committer:
- XinZhangMS
- Date:
- Thu Aug 23 06:52:14 2018 +0000
- Revision:
- 0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
XinZhangMS | 0:f7f1f0d76dd6 | 1 | // Copyright (c) Microsoft. All rights reserved. |
XinZhangMS | 0:f7f1f0d76dd6 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
XinZhangMS | 0:f7f1f0d76dd6 | 3 | |
XinZhangMS | 0:f7f1f0d76dd6 | 4 | #include <stdlib.h> |
XinZhangMS | 0:f7f1f0d76dd6 | 5 | #include <ctype.h> |
XinZhangMS | 0:f7f1f0d76dd6 | 6 | #include "azure_c_shared_utility/optimize_size.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 7 | #include "azure_c_shared_utility/gballoc.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 8 | #include "azure_c_shared_utility/crt_abstractions.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 9 | #include "azure_c_shared_utility/string_tokenizer.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 10 | #include "azure_c_shared_utility/singlylinkedlist.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 11 | #include "azure_c_shared_utility/buffer_.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 12 | #include "azure_c_shared_utility/xlogging.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 13 | #include "azure_c_shared_utility/httpapiex.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 14 | #include "azure_c_shared_utility/httpapiexsas.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 15 | #include "azure_c_shared_utility/base64.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 16 | #include "azure_c_shared_utility/uniqueid.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 17 | #include "azure_c_shared_utility/connection_string_parser.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 18 | |
XinZhangMS | 0:f7f1f0d76dd6 | 19 | #include "parson.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 20 | #include "iothub_devicetwin.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 21 | #include "iothub_sc_version.h" |
XinZhangMS | 0:f7f1f0d76dd6 | 22 | |
XinZhangMS | 0:f7f1f0d76dd6 | 23 | #define IOTHUB_TWIN_REQUEST_MODE_VALUES \ |
XinZhangMS | 0:f7f1f0d76dd6 | 24 | IOTHUB_TWIN_REQUEST_GET, \ |
XinZhangMS | 0:f7f1f0d76dd6 | 25 | IOTHUB_TWIN_REQUEST_UPDATE, \ |
XinZhangMS | 0:f7f1f0d76dd6 | 26 | IOTHUB_TWIN_REQUEST_REPLACE_TAGS, \ |
XinZhangMS | 0:f7f1f0d76dd6 | 27 | IOTHUB_TWIN_REQUEST_REPLACE_DESIRED, \ |
XinZhangMS | 0:f7f1f0d76dd6 | 28 | IOTHUB_TWIN_REQUEST_UPDATE_DESIRED |
XinZhangMS | 0:f7f1f0d76dd6 | 29 | |
XinZhangMS | 0:f7f1f0d76dd6 | 30 | DEFINE_ENUM(IOTHUB_TWIN_REQUEST_MODE, IOTHUB_TWIN_REQUEST_MODE_VALUES); |
XinZhangMS | 0:f7f1f0d76dd6 | 31 | DEFINE_ENUM_STRINGS(IOTHUB_DEVICE_TWIN_RESULT, IOTHUB_DEVICE_TWIN_RESULT_VALUES); |
XinZhangMS | 0:f7f1f0d76dd6 | 32 | |
XinZhangMS | 0:f7f1f0d76dd6 | 33 | #define HTTP_HEADER_KEY_AUTHORIZATION "Authorization" |
XinZhangMS | 0:f7f1f0d76dd6 | 34 | #define HTTP_HEADER_VAL_AUTHORIZATION " " |
XinZhangMS | 0:f7f1f0d76dd6 | 35 | #define HTTP_HEADER_KEY_REQUEST_ID "Request-Id" |
XinZhangMS | 0:f7f1f0d76dd6 | 36 | #define HTTP_HEADER_KEY_USER_AGENT "User-Agent" |
XinZhangMS | 0:f7f1f0d76dd6 | 37 | #define HTTP_HEADER_VAL_USER_AGENT IOTHUB_SERVICE_CLIENT_TYPE_PREFIX IOTHUB_SERVICE_CLIENT_BACKSLASH IOTHUB_SERVICE_CLIENT_VERSION |
XinZhangMS | 0:f7f1f0d76dd6 | 38 | #define HTTP_HEADER_KEY_ACCEPT "Accept" |
XinZhangMS | 0:f7f1f0d76dd6 | 39 | #define HTTP_HEADER_VAL_ACCEPT "application/json" |
XinZhangMS | 0:f7f1f0d76dd6 | 40 | #define HTTP_HEADER_KEY_CONTENT_TYPE "Content-Type" |
XinZhangMS | 0:f7f1f0d76dd6 | 41 | #define HTTP_HEADER_VAL_CONTENT_TYPE "application/json; charset=utf-8" |
XinZhangMS | 0:f7f1f0d76dd6 | 42 | #define HTTP_HEADER_KEY_IFMATCH "If-Match" |
XinZhangMS | 0:f7f1f0d76dd6 | 43 | #define HTTP_HEADER_VAL_IFMATCH "*" |
XinZhangMS | 0:f7f1f0d76dd6 | 44 | #define UID_LENGTH 37 |
XinZhangMS | 0:f7f1f0d76dd6 | 45 | |
XinZhangMS | 0:f7f1f0d76dd6 | 46 | static const char* URL_API_VERSION = "?api-version=2017-11-08-preview"; |
XinZhangMS | 0:f7f1f0d76dd6 | 47 | |
XinZhangMS | 0:f7f1f0d76dd6 | 48 | static const char* RELATIVE_PATH_FMT_TWIN = "/twins/%s%s"; |
XinZhangMS | 0:f7f1f0d76dd6 | 49 | static const char* RELATIVE_PATH_FMT_TWIN_MODULE = "/twins/%s/modules/%s%s"; |
XinZhangMS | 0:f7f1f0d76dd6 | 50 | |
XinZhangMS | 0:f7f1f0d76dd6 | 51 | |
XinZhangMS | 0:f7f1f0d76dd6 | 52 | /** @brief Structure to store IoTHub authentication information |
XinZhangMS | 0:f7f1f0d76dd6 | 53 | */ |
XinZhangMS | 0:f7f1f0d76dd6 | 54 | typedef struct IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_TAG |
XinZhangMS | 0:f7f1f0d76dd6 | 55 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 56 | char* hostname; |
XinZhangMS | 0:f7f1f0d76dd6 | 57 | char* sharedAccessKey; |
XinZhangMS | 0:f7f1f0d76dd6 | 58 | char* keyName; |
XinZhangMS | 0:f7f1f0d76dd6 | 59 | } IOTHUB_SERVICE_CLIENT_DEVICE_TWIN; |
XinZhangMS | 0:f7f1f0d76dd6 | 60 | |
XinZhangMS | 0:f7f1f0d76dd6 | 61 | static const char* generateGuid(void) |
XinZhangMS | 0:f7f1f0d76dd6 | 62 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 63 | char* result; |
XinZhangMS | 0:f7f1f0d76dd6 | 64 | |
XinZhangMS | 0:f7f1f0d76dd6 | 65 | if ((result = malloc(UID_LENGTH)) != NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 66 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 67 | result[0] = '\0'; |
XinZhangMS | 0:f7f1f0d76dd6 | 68 | if (UniqueId_Generate(result, UID_LENGTH) != UNIQUEID_OK) |
XinZhangMS | 0:f7f1f0d76dd6 | 69 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 70 | free((void*)result); |
XinZhangMS | 0:f7f1f0d76dd6 | 71 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 72 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 73 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 74 | return (const char*)result; |
XinZhangMS | 0:f7f1f0d76dd6 | 75 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 76 | |
XinZhangMS | 0:f7f1f0d76dd6 | 77 | static STRING_HANDLE createRelativePath(IOTHUB_TWIN_REQUEST_MODE iotHubTwinRequestMode, const char* deviceId, const char* moduleId) |
XinZhangMS | 0:f7f1f0d76dd6 | 78 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 79 | //IOTHUB_TWIN_REQUEST_GET GET {iot hub}/twins/{device id} // Get device twin |
XinZhangMS | 0:f7f1f0d76dd6 | 80 | //IOTHUB_TWIN_REQUEST_UPDATE PATCH {iot hub}/twins/{device id} // Partally update device twin |
XinZhangMS | 0:f7f1f0d76dd6 | 81 | //IOTHUB_TWIN_REQUEST_REPLACE_TAGS PUT {iot hub}/twins/{device id}/tags // Replace update tags |
XinZhangMS | 0:f7f1f0d76dd6 | 82 | //IOTHUB_TWIN_REQUEST_REPLACE_DESIRED PUT {iot hub}/twins/{device id}/properties/desired // Replace update desired properties |
XinZhangMS | 0:f7f1f0d76dd6 | 83 | //IOTHUB_TWIN_REQUEST_UPDATE_DESIRED PATCH {iot hub}/twins/{device id}/properties/desired // Partially update desired properties |
XinZhangMS | 0:f7f1f0d76dd6 | 84 | |
XinZhangMS | 0:f7f1f0d76dd6 | 85 | STRING_HANDLE result; |
XinZhangMS | 0:f7f1f0d76dd6 | 86 | |
XinZhangMS | 0:f7f1f0d76dd6 | 87 | if ((iotHubTwinRequestMode == IOTHUB_TWIN_REQUEST_GET) || (iotHubTwinRequestMode == IOTHUB_TWIN_REQUEST_UPDATE)) |
XinZhangMS | 0:f7f1f0d76dd6 | 88 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 89 | if (moduleId == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 90 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 91 | result = STRING_construct_sprintf(RELATIVE_PATH_FMT_TWIN, deviceId, URL_API_VERSION); |
XinZhangMS | 0:f7f1f0d76dd6 | 92 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 93 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 94 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 95 | result = STRING_construct_sprintf(RELATIVE_PATH_FMT_TWIN_MODULE, deviceId, moduleId, URL_API_VERSION); |
XinZhangMS | 0:f7f1f0d76dd6 | 96 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 97 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 98 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 99 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 100 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 101 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 102 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 103 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 104 | |
XinZhangMS | 0:f7f1f0d76dd6 | 105 | static HTTP_HEADERS_HANDLE createHttpHeader(IOTHUB_TWIN_REQUEST_MODE iotHubTwinRequestMode) |
XinZhangMS | 0:f7f1f0d76dd6 | 106 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 107 | /*Codes_SRS_IOTHUBDEVICETWIN_12_020: [ IoTHubDeviceTwin_GetTwin shall add the following headers to the created HTTP GET request: authorization=sasToken,Request-Id=1001,Accept=application/json,Content-Type=application/json,charset=utf-8 ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 108 | HTTP_HEADERS_HANDLE httpHeader; |
XinZhangMS | 0:f7f1f0d76dd6 | 109 | const char* guid = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 110 | |
XinZhangMS | 0:f7f1f0d76dd6 | 111 | if ((httpHeader = HTTPHeaders_Alloc()) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 112 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 113 | LogError("HTTPHeaders_Alloc failed"); |
XinZhangMS | 0:f7f1f0d76dd6 | 114 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 115 | else if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_AUTHORIZATION, HTTP_HEADER_VAL_AUTHORIZATION) != HTTP_HEADERS_OK) |
XinZhangMS | 0:f7f1f0d76dd6 | 116 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 117 | LogError("HTTPHeaders_AddHeaderNameValuePair failed for Authorization header"); |
XinZhangMS | 0:f7f1f0d76dd6 | 118 | HTTPHeaders_Free(httpHeader); |
XinZhangMS | 0:f7f1f0d76dd6 | 119 | httpHeader = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 120 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 121 | else if ((guid = generateGuid()) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 122 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 123 | LogError("GUID creation failed"); |
XinZhangMS | 0:f7f1f0d76dd6 | 124 | HTTPHeaders_Free(httpHeader); |
XinZhangMS | 0:f7f1f0d76dd6 | 125 | httpHeader = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 126 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 127 | else if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_REQUEST_ID, guid) != HTTP_HEADERS_OK) |
XinZhangMS | 0:f7f1f0d76dd6 | 128 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 129 | LogError("HTTPHeaders_AddHeaderNameValuePair failed for RequestId header"); |
XinZhangMS | 0:f7f1f0d76dd6 | 130 | HTTPHeaders_Free(httpHeader); |
XinZhangMS | 0:f7f1f0d76dd6 | 131 | httpHeader = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 132 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 133 | else if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_USER_AGENT, HTTP_HEADER_VAL_USER_AGENT) != HTTP_HEADERS_OK) |
XinZhangMS | 0:f7f1f0d76dd6 | 134 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 135 | LogError("HTTPHeaders_AddHeaderNameValuePair failed for User-Agent header"); |
XinZhangMS | 0:f7f1f0d76dd6 | 136 | HTTPHeaders_Free(httpHeader); |
XinZhangMS | 0:f7f1f0d76dd6 | 137 | httpHeader = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 138 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 139 | else if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_CONTENT_TYPE, HTTP_HEADER_VAL_CONTENT_TYPE) != HTTP_HEADERS_OK) |
XinZhangMS | 0:f7f1f0d76dd6 | 140 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 141 | LogError("HTTPHeaders_AddHeaderNameValuePair failed for Content-Type header"); |
XinZhangMS | 0:f7f1f0d76dd6 | 142 | HTTPHeaders_Free(httpHeader); |
XinZhangMS | 0:f7f1f0d76dd6 | 143 | httpHeader = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 144 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 145 | else if (iotHubTwinRequestMode != IOTHUB_TWIN_REQUEST_GET) |
XinZhangMS | 0:f7f1f0d76dd6 | 146 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 147 | if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_IFMATCH, HTTP_HEADER_VAL_IFMATCH) != HTTP_HEADERS_OK) |
XinZhangMS | 0:f7f1f0d76dd6 | 148 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 149 | LogError("HTTPHeaders_AddHeaderNameValuePair failed for If-Match header"); |
XinZhangMS | 0:f7f1f0d76dd6 | 150 | HTTPHeaders_Free(httpHeader); |
XinZhangMS | 0:f7f1f0d76dd6 | 151 | httpHeader = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 152 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 153 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 154 | free((void*)guid); |
XinZhangMS | 0:f7f1f0d76dd6 | 155 | |
XinZhangMS | 0:f7f1f0d76dd6 | 156 | return httpHeader; |
XinZhangMS | 0:f7f1f0d76dd6 | 157 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 158 | |
XinZhangMS | 0:f7f1f0d76dd6 | 159 | static IOTHUB_DEVICE_TWIN_RESULT sendHttpRequestTwin(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE serviceClientDeviceTwinHandle, IOTHUB_TWIN_REQUEST_MODE iotHubTwinRequestMode, const char* deviceName, const char* moduleId, BUFFER_HANDLE deviceJsonBuffer, BUFFER_HANDLE responseBuffer) |
XinZhangMS | 0:f7f1f0d76dd6 | 160 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 161 | IOTHUB_DEVICE_TWIN_RESULT result; |
XinZhangMS | 0:f7f1f0d76dd6 | 162 | |
XinZhangMS | 0:f7f1f0d76dd6 | 163 | STRING_HANDLE uriResource = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 164 | STRING_HANDLE accessKey = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 165 | STRING_HANDLE keyName = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 166 | HTTPAPIEX_SAS_HANDLE httpExApiSasHandle; |
XinZhangMS | 0:f7f1f0d76dd6 | 167 | HTTPAPIEX_HANDLE httpExApiHandle; |
XinZhangMS | 0:f7f1f0d76dd6 | 168 | HTTP_HEADERS_HANDLE httpHeader; |
XinZhangMS | 0:f7f1f0d76dd6 | 169 | |
XinZhangMS | 0:f7f1f0d76dd6 | 170 | if ((uriResource = STRING_construct(serviceClientDeviceTwinHandle->hostname)) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 171 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 172 | /*Codes_SRS_IOTHUBDEVICETWIN_12_024: [ If any of the HTTPAPI call fails IoTHubDeviceTwin_GetTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 173 | LogError("STRING_construct failed for uriResource"); |
XinZhangMS | 0:f7f1f0d76dd6 | 174 | result = IOTHUB_DEVICE_TWIN_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 175 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 176 | else if ((accessKey = STRING_construct(serviceClientDeviceTwinHandle->sharedAccessKey)) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 177 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 178 | /*Codes_SRS_IOTHUBDEVICETWIN_12_024: [ If any of the call fails during the HTTP creation IoTHubDeviceTwin_GetTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 179 | LogError("STRING_construct failed for accessKey"); |
XinZhangMS | 0:f7f1f0d76dd6 | 180 | STRING_delete(uriResource); |
XinZhangMS | 0:f7f1f0d76dd6 | 181 | result = IOTHUB_DEVICE_TWIN_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 182 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 183 | else if ((keyName = STRING_construct(serviceClientDeviceTwinHandle->keyName)) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 184 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 185 | /*Codes_SRS_IOTHUBDEVICETWIN_12_024: [ If any of the call fails during the HTTP creation IoTHubDeviceTwin_GetTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 186 | LogError("STRING_construct failed for keyName"); |
XinZhangMS | 0:f7f1f0d76dd6 | 187 | STRING_delete(accessKey); |
XinZhangMS | 0:f7f1f0d76dd6 | 188 | STRING_delete(uriResource); |
XinZhangMS | 0:f7f1f0d76dd6 | 189 | result = IOTHUB_DEVICE_TWIN_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 190 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 191 | /*Codes_SRS_IOTHUBDEVICETWIN_12_020: [ IoTHubDeviceTwin_GetTwin shall add the following headers to the created HTTP GET request: authorization=sasToken,Request-Id=1001,Accept=application/json,Content-Type=application/json,charset=utf-8 ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 192 | else if ((httpHeader = createHttpHeader(iotHubTwinRequestMode)) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 193 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 194 | /*Codes_SRS_IOTHUBDEVICETWIN_12_024: [ If any of the call fails during the HTTP creation IoTHubDeviceTwin_GetTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 195 | LogError("HttpHeader creation failed"); |
XinZhangMS | 0:f7f1f0d76dd6 | 196 | STRING_delete(keyName); |
XinZhangMS | 0:f7f1f0d76dd6 | 197 | STRING_delete(accessKey); |
XinZhangMS | 0:f7f1f0d76dd6 | 198 | STRING_delete(uriResource); |
XinZhangMS | 0:f7f1f0d76dd6 | 199 | result = IOTHUB_DEVICE_TWIN_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 200 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 201 | /*Codes_SRS_IOTHUBDEVICETWIN_12_021: [ IoTHubDeviceTwin_GetTwin shall create an HTTPAPIEX_SAS_HANDLE handle by calling HTTPAPIEX_SAS_Create ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 202 | else if ((httpExApiSasHandle = HTTPAPIEX_SAS_Create(accessKey, uriResource, keyName)) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 203 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 204 | /*Codes_SRS_IOTHUBDEVICETWIN_12_025: [ If any of the HTTPAPI call fails IoTHubDeviceTwin_GetTwin shall fail and return IOTHUB_DEVICE_TWIN_HTTPAPI_ERROR ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 205 | LogError("HTTPAPIEX_SAS_Create failed"); |
XinZhangMS | 0:f7f1f0d76dd6 | 206 | HTTPHeaders_Free(httpHeader); |
XinZhangMS | 0:f7f1f0d76dd6 | 207 | STRING_delete(keyName); |
XinZhangMS | 0:f7f1f0d76dd6 | 208 | STRING_delete(accessKey); |
XinZhangMS | 0:f7f1f0d76dd6 | 209 | STRING_delete(uriResource); |
XinZhangMS | 0:f7f1f0d76dd6 | 210 | result = IOTHUB_DEVICE_TWIN_HTTPAPI_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 211 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 212 | /*Codes_SRS_IOTHUBDEVICETWIN_12_022: [ IoTHubDeviceTwin_GetTwin shall create an HTTPAPIEX_HANDLE handle by calling HTTPAPIEX_Create ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 213 | else if ((httpExApiHandle = HTTPAPIEX_Create(serviceClientDeviceTwinHandle->hostname)) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 214 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 215 | /*Codes_SRS_IOTHUBDEVICETWIN_12_025: [ If any of the HTTPAPI call fails IoTHubDeviceTwin_GetTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 216 | LogError("HTTPAPIEX_Create failed"); |
XinZhangMS | 0:f7f1f0d76dd6 | 217 | HTTPAPIEX_SAS_Destroy(httpExApiSasHandle); |
XinZhangMS | 0:f7f1f0d76dd6 | 218 | HTTPHeaders_Free(httpHeader); |
XinZhangMS | 0:f7f1f0d76dd6 | 219 | STRING_delete(keyName); |
XinZhangMS | 0:f7f1f0d76dd6 | 220 | STRING_delete(accessKey); |
XinZhangMS | 0:f7f1f0d76dd6 | 221 | STRING_delete(uriResource); |
XinZhangMS | 0:f7f1f0d76dd6 | 222 | result = IOTHUB_DEVICE_TWIN_HTTPAPI_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 223 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 224 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 225 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 226 | HTTPAPI_REQUEST_TYPE httpApiRequestType = HTTPAPI_REQUEST_GET; |
XinZhangMS | 0:f7f1f0d76dd6 | 227 | STRING_HANDLE relativePath; |
XinZhangMS | 0:f7f1f0d76dd6 | 228 | unsigned int statusCode = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 229 | unsigned char is_error = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 230 | |
XinZhangMS | 0:f7f1f0d76dd6 | 231 | //IOTHUB_TWIN_REQUEST_GET GET {iot hub}/twins/{device id} // Get device twin |
XinZhangMS | 0:f7f1f0d76dd6 | 232 | //IOTHUB_TWIN_REQUEST_UPDATE PATCH {iot hub}/twins/{device id} // Partally update device twin |
XinZhangMS | 0:f7f1f0d76dd6 | 233 | //IOTHUB_TWIN_REQUEST_REPLACE_TAGS PUT {iot hub}/twins/{device id}/tags // Replace update tags |
XinZhangMS | 0:f7f1f0d76dd6 | 234 | //IOTHUB_TWIN_REQUEST_REPLACE_DESIRED PUT {iot hub}/twins/{device id}/properties/desired // Replace update desired properties |
XinZhangMS | 0:f7f1f0d76dd6 | 235 | //IOTHUB_TWIN_REQUEST_UPDATE_DESIRED PATCH {iot hub}/twins/{device id}/properties/desired // Partially update desired properties |
XinZhangMS | 0:f7f1f0d76dd6 | 236 | |
XinZhangMS | 0:f7f1f0d76dd6 | 237 | if ((iotHubTwinRequestMode == IOTHUB_TWIN_REQUEST_REPLACE_TAGS) || (iotHubTwinRequestMode == IOTHUB_TWIN_REQUEST_REPLACE_DESIRED)) |
XinZhangMS | 0:f7f1f0d76dd6 | 238 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 239 | httpApiRequestType = HTTPAPI_REQUEST_PUT; |
XinZhangMS | 0:f7f1f0d76dd6 | 240 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 241 | else if ((iotHubTwinRequestMode == IOTHUB_TWIN_REQUEST_UPDATE) || (iotHubTwinRequestMode == IOTHUB_TWIN_REQUEST_UPDATE_DESIRED)) |
XinZhangMS | 0:f7f1f0d76dd6 | 242 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 243 | httpApiRequestType = HTTPAPI_REQUEST_PATCH; |
XinZhangMS | 0:f7f1f0d76dd6 | 244 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 245 | else if (iotHubTwinRequestMode == IOTHUB_TWIN_REQUEST_GET) |
XinZhangMS | 0:f7f1f0d76dd6 | 246 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 247 | httpApiRequestType = HTTPAPI_REQUEST_GET; |
XinZhangMS | 0:f7f1f0d76dd6 | 248 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 249 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 250 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 251 | is_error = 1; |
XinZhangMS | 0:f7f1f0d76dd6 | 252 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 253 | |
XinZhangMS | 0:f7f1f0d76dd6 | 254 | if (is_error) |
XinZhangMS | 0:f7f1f0d76dd6 | 255 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 256 | LogError("Invalid request type"); |
XinZhangMS | 0:f7f1f0d76dd6 | 257 | result = IOTHUB_DEVICE_TWIN_HTTPAPI_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 258 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 259 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 260 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 261 | /*Codes_SRS_IOTHUBDEVICETWIN_12_019: [ IoTHubDeviceTwin_GetTwin shall create HTTP GET request URL using the given deviceId using the following format: url/twins/[deviceId] ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 262 | if ((relativePath = createRelativePath(iotHubTwinRequestMode, deviceName, moduleId)) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 263 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 264 | /*Codes_SRS_IOTHUBDEVICETWIN_12_024: [ If any of the call fails during the HTTP creation IoTHubDeviceTwin_GetTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 265 | LogError("Failure creating relative path"); |
XinZhangMS | 0:f7f1f0d76dd6 | 266 | result = IOTHUB_DEVICE_TWIN_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 267 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 268 | /*Codes_SRS_IOTHUBDEVICETWIN_12_023: [ IoTHubDeviceTwin_GetTwin shall execute the HTTP GET request by calling HTTPAPIEX_ExecuteRequest ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 269 | else if (HTTPAPIEX_SAS_ExecuteRequest(httpExApiSasHandle, httpExApiHandle, httpApiRequestType, STRING_c_str(relativePath), httpHeader, deviceJsonBuffer, &statusCode, NULL, responseBuffer) != HTTPAPIEX_OK) |
XinZhangMS | 0:f7f1f0d76dd6 | 270 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 271 | /*Codes_SRS_IOTHUBDEVICETWIN_12_025: [ If any of the HTTPAPI call fails IoTHubDeviceTwin_GetTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 272 | LogError("HTTPAPIEX_SAS_ExecuteRequest failed"); |
XinZhangMS | 0:f7f1f0d76dd6 | 273 | STRING_delete(relativePath); |
XinZhangMS | 0:f7f1f0d76dd6 | 274 | result = IOTHUB_DEVICE_TWIN_HTTPAPI_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 275 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 276 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 277 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 278 | STRING_delete(relativePath); |
XinZhangMS | 0:f7f1f0d76dd6 | 279 | if (statusCode == 200) |
XinZhangMS | 0:f7f1f0d76dd6 | 280 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 281 | /*CodesSRS_IOTHUBDEVICETWIN_12_030: [ Otherwise IoTHubDeviceTwin_GetTwin shall save the received deviceTwin to the out parameter and return with it ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 282 | result = IOTHUB_DEVICE_TWIN_OK; |
XinZhangMS | 0:f7f1f0d76dd6 | 283 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 284 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 285 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 286 | /*Codes_SRS_IOTHUBDEVICETWIN_12_026: [ IoTHubDeviceTwin_GetTwin shall verify the received HTTP status code and if it is not equal to 200 then return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 287 | LogError("Http Failure status code %d.", statusCode); |
XinZhangMS | 0:f7f1f0d76dd6 | 288 | result = IOTHUB_DEVICE_TWIN_ERROR; |
XinZhangMS | 0:f7f1f0d76dd6 | 289 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 290 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 291 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 292 | HTTPAPIEX_Destroy(httpExApiHandle); |
XinZhangMS | 0:f7f1f0d76dd6 | 293 | HTTPAPIEX_SAS_Destroy(httpExApiSasHandle); |
XinZhangMS | 0:f7f1f0d76dd6 | 294 | HTTPHeaders_Free(httpHeader); |
XinZhangMS | 0:f7f1f0d76dd6 | 295 | STRING_delete(keyName); |
XinZhangMS | 0:f7f1f0d76dd6 | 296 | STRING_delete(accessKey); |
XinZhangMS | 0:f7f1f0d76dd6 | 297 | STRING_delete(uriResource); |
XinZhangMS | 0:f7f1f0d76dd6 | 298 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 299 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 300 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 301 | |
XinZhangMS | 0:f7f1f0d76dd6 | 302 | static void free_devicetwin_handle(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN* deviceTwin) |
XinZhangMS | 0:f7f1f0d76dd6 | 303 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 304 | free(deviceTwin->hostname); |
XinZhangMS | 0:f7f1f0d76dd6 | 305 | free(deviceTwin->sharedAccessKey); |
XinZhangMS | 0:f7f1f0d76dd6 | 306 | free(deviceTwin->keyName); |
XinZhangMS | 0:f7f1f0d76dd6 | 307 | free(deviceTwin); |
XinZhangMS | 0:f7f1f0d76dd6 | 308 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 309 | |
XinZhangMS | 0:f7f1f0d76dd6 | 310 | IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE IoTHubDeviceTwin_Create(IOTHUB_SERVICE_CLIENT_AUTH_HANDLE serviceClientHandle) |
XinZhangMS | 0:f7f1f0d76dd6 | 311 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 312 | IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE result; |
XinZhangMS | 0:f7f1f0d76dd6 | 313 | |
XinZhangMS | 0:f7f1f0d76dd6 | 314 | /*Codes_SRS_IOTHUBDEVICETWIN_12_001: [ If the serviceClientHandle input parameter is NULL IoTHubDeviceTwin_Create shall return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 315 | if (serviceClientHandle == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 316 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 317 | LogError("serviceClientHandle input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 318 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 319 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 320 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 321 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 322 | /*Codes_SRS_IOTHUBDEVICETWIN_12_002: [ If any member of the serviceClientHandle input parameter is NULL IoTHubDeviceTwin_Create shall return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 323 | IOTHUB_SERVICE_CLIENT_AUTH* serviceClientAuth = (IOTHUB_SERVICE_CLIENT_AUTH*)serviceClientHandle; |
XinZhangMS | 0:f7f1f0d76dd6 | 324 | |
XinZhangMS | 0:f7f1f0d76dd6 | 325 | if (serviceClientAuth->hostname == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 326 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 327 | LogError("authInfo->hostName input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 328 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 329 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 330 | else if (serviceClientAuth->iothubName == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 331 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 332 | LogError("authInfo->iothubName input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 333 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 334 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 335 | else if (serviceClientAuth->iothubSuffix == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 336 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 337 | LogError("authInfo->iothubSuffix input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 338 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 339 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 340 | else if (serviceClientAuth->keyName == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 341 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 342 | LogError("authInfo->keyName input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 343 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 344 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 345 | else if (serviceClientAuth->sharedAccessKey == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 346 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 347 | LogError("authInfo->sharedAccessKey input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 348 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 349 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 350 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 351 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 352 | /*Codes_SRS_IOTHUBDEVICETWIN_12_003: [ IoTHubDeviceTwin_Create shall allocate memory for a new IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE instance ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 353 | result = malloc(sizeof(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN)); |
XinZhangMS | 0:f7f1f0d76dd6 | 354 | if (result == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 355 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 356 | /*Codes_SRS_IOTHUBDEVICETWIN_12_004: [ If the allocation failed, IoTHubDeviceTwin_Create shall return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 357 | LogError("Malloc failed for IOTHUB_SERVICE_CLIENT_DEVICE_TWIN"); |
XinZhangMS | 0:f7f1f0d76dd6 | 358 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 359 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 360 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 361 | memset(result, 0, sizeof(*result)); |
XinZhangMS | 0:f7f1f0d76dd6 | 362 | |
XinZhangMS | 0:f7f1f0d76dd6 | 363 | /*Codes_SRS_IOTHUBDEVICETWIN_12_005: [ If the allocation successful, IoTHubDeviceTwin_Create shall create a IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE from the given IOTHUB_SERVICE_CLIENT_AUTH_HANDLE and return with it ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 364 | /*Codes_SRS_IOTHUBDEVICETWIN_12_006: [ IoTHubDeviceTwin_Create shall allocate memory and copy hostName to result->hostName by calling mallocAndStrcpy_s. ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 365 | if (mallocAndStrcpy_s(&result->hostname, serviceClientAuth->hostname) != 0) |
XinZhangMS | 0:f7f1f0d76dd6 | 366 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 367 | /*Codes_SRS_IOTHUBDEVICETWIN_12_007: [ If the mallocAndStrcpy_s fails, IoTHubDeviceTwin_Create shall do clean up and return NULL. ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 368 | LogError("mallocAndStrcpy_s failed for hostName"); |
XinZhangMS | 0:f7f1f0d76dd6 | 369 | free_devicetwin_handle(result); |
XinZhangMS | 0:f7f1f0d76dd6 | 370 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 371 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 372 | /*Codes_SRS_IOTHUBDEVICETWIN_12_012: [ IoTHubDeviceTwin_Create shall allocate memory and copy sharedAccessKey to result->sharedAccessKey by calling mallocAndStrcpy_s. ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 373 | else if (mallocAndStrcpy_s(&result->sharedAccessKey, serviceClientAuth->sharedAccessKey) != 0) |
XinZhangMS | 0:f7f1f0d76dd6 | 374 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 375 | /*Codes_SRS_IOTHUBDEVICETWIN_12_013: [ If the mallocAndStrcpy_s fails, IoTHubDeviceTwin_Create shall do clean up and return NULL. ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 376 | LogError("mallocAndStrcpy_s failed for sharedAccessKey"); |
XinZhangMS | 0:f7f1f0d76dd6 | 377 | free_devicetwin_handle(result); |
XinZhangMS | 0:f7f1f0d76dd6 | 378 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 379 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 380 | /*Codes_SRS_IOTHUBDEVICETWIN_12_014: [ IoTHubDeviceTwin_Create shall allocate memory and copy keyName to result->keyName by calling mallocAndStrcpy_s. ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 381 | else if (mallocAndStrcpy_s(&result->keyName, serviceClientAuth->keyName) != 0) |
XinZhangMS | 0:f7f1f0d76dd6 | 382 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 383 | /*Codes_SRS_IOTHUBDEVICETWIN_12_015: [ If the mallocAndStrcpy_s fails, IoTHubDeviceTwin_Create shall do clean up and return NULL. ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 384 | LogError("mallocAndStrcpy_s failed for keyName"); |
XinZhangMS | 0:f7f1f0d76dd6 | 385 | free_devicetwin_handle(result); |
XinZhangMS | 0:f7f1f0d76dd6 | 386 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 387 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 388 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 389 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 390 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 391 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 392 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 393 | |
XinZhangMS | 0:f7f1f0d76dd6 | 394 | void IoTHubDeviceTwin_Destroy(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE serviceClientDeviceTwinHandle) |
XinZhangMS | 0:f7f1f0d76dd6 | 395 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 396 | /*Codes_SRS_IOTHUBDEVICETWIN_12_016: [ If the serviceClientDeviceTwinHandle input parameter is NULL IoTHubDeviceTwin_Destroy shall return ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 397 | if (serviceClientDeviceTwinHandle != NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 398 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 399 | /*Codes_SRS_IOTHUBDEVICETWIN_12_017: [ If the serviceClientDeviceTwinHandle input parameter is not NULL IoTHubDeviceTwin_Destroy shall free the memory of it and return ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 400 | free_devicetwin_handle((IOTHUB_SERVICE_CLIENT_DEVICE_TWIN*)serviceClientDeviceTwinHandle); |
XinZhangMS | 0:f7f1f0d76dd6 | 401 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 402 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 403 | |
XinZhangMS | 0:f7f1f0d76dd6 | 404 | static int malloc_and_copy_uchar(char** strDestination, BUFFER_HANDLE strSource) |
XinZhangMS | 0:f7f1f0d76dd6 | 405 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 406 | int result; |
XinZhangMS | 0:f7f1f0d76dd6 | 407 | if ((strDestination == NULL) || (strSource == NULL)) |
XinZhangMS | 0:f7f1f0d76dd6 | 408 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 409 | /* If strDestination or strSource is a NULL pointer[...] function return line number where error is spotted */ |
XinZhangMS | 0:f7f1f0d76dd6 | 410 | LogError("invalid parameter strDestination or strSource"); |
XinZhangMS | 0:f7f1f0d76dd6 | 411 | result = __FAILURE__; |
XinZhangMS | 0:f7f1f0d76dd6 | 412 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 413 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 414 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 415 | size_t buffer_size = BUFFER_length(strSource); |
XinZhangMS | 0:f7f1f0d76dd6 | 416 | char *temp = malloc(buffer_size + 1); |
XinZhangMS | 0:f7f1f0d76dd6 | 417 | if (temp == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 418 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 419 | LogError("failed to malloc"); |
XinZhangMS | 0:f7f1f0d76dd6 | 420 | result = __FAILURE__; |
XinZhangMS | 0:f7f1f0d76dd6 | 421 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 422 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 423 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 424 | *strDestination = memcpy(temp, BUFFER_u_char(strSource), buffer_size); |
XinZhangMS | 0:f7f1f0d76dd6 | 425 | temp[buffer_size] = '\0'; |
XinZhangMS | 0:f7f1f0d76dd6 | 426 | result = 0; |
XinZhangMS | 0:f7f1f0d76dd6 | 427 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 428 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 429 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 430 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 431 | |
XinZhangMS | 0:f7f1f0d76dd6 | 432 | char* IoTHubDeviceTwin_GetDeviceOrModuleTwin(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE serviceClientDeviceTwinHandle, const char* deviceId, const char* moduleId) |
XinZhangMS | 0:f7f1f0d76dd6 | 433 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 434 | char* result; |
XinZhangMS | 0:f7f1f0d76dd6 | 435 | |
XinZhangMS | 0:f7f1f0d76dd6 | 436 | /*Codes_SRS_IOTHUBDEVICETWIN_12_018: [ IoTHubDeviceTwin_GetTwin shall verify the input parameters and if any of them are NULL then return IOTHUB_DEVICE_TWIN_INVALID_ARG ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 437 | if ((serviceClientDeviceTwinHandle == NULL) || (deviceId == NULL)) |
XinZhangMS | 0:f7f1f0d76dd6 | 438 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 439 | LogError("Input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 440 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 441 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 442 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 443 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 444 | BUFFER_HANDLE responseBuffer; |
XinZhangMS | 0:f7f1f0d76dd6 | 445 | |
XinZhangMS | 0:f7f1f0d76dd6 | 446 | if ((responseBuffer = BUFFER_new()) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 447 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 448 | LogError("BUFFER_new failed for responseBuffer"); |
XinZhangMS | 0:f7f1f0d76dd6 | 449 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 450 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 451 | /*Codes_SRS_IOTHUBDEVICETWIN_12_019: [ IoTHubDeviceTwin_GetTwin shall create HTTP GET request URL using the given deviceId using the following format: url/twins/[deviceId] ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 452 | /*Codes_SRS_IOTHUBDEVICETWIN_12_020: [ IoTHubDeviceTwin_GetTwin shall add the following headers to the created HTTP GET request: authorization=sasToken,Request-Id=1001,Accept=application/json,Content-Type=application/json,charset=utf-8 ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 453 | /*Codes_SRS_IOTHUBDEVICETWIN_12_021: [ IoTHubDeviceTwin_GetTwin shall create an HTTPAPIEX_SAS_HANDLE handle by calling HTTPAPIEX_SAS_Create ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 454 | /*Codes_SRS_IOTHUBDEVICETWIN_12_022: [ IoTHubDeviceTwin_GetTwin shall create an HTTPAPIEX_HANDLE handle by calling HTTPAPIEX_Create ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 455 | /*Codes_SRS_IOTHUBDEVICETWIN_12_023: [ IoTHubDeviceTwin_GetTwin shall execute the HTTP GET request by calling HTTPAPIEX_ExecuteRequest ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 456 | else if (sendHttpRequestTwin(serviceClientDeviceTwinHandle, IOTHUB_TWIN_REQUEST_GET, deviceId, moduleId, NULL, responseBuffer) != IOTHUB_DEVICE_TWIN_OK) |
XinZhangMS | 0:f7f1f0d76dd6 | 457 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 458 | /*Codes_SRS_IOTHUBDEVICETWIN_12_024: [ If any of the call fails during the HTTP creation IoTHubDeviceTwin_GetTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 459 | /*Codes_SRS_IOTHUBDEVICETWIN_12_025: [ If any of the HTTPAPI call fails IoTHubDeviceTwin_GetTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 460 | LogError("Failure sending HTTP request for create device"); |
XinZhangMS | 0:f7f1f0d76dd6 | 461 | BUFFER_delete(responseBuffer); |
XinZhangMS | 0:f7f1f0d76dd6 | 462 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 463 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 464 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 465 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 466 | /*Codes_SRS_IOTHUBDEVICETWIN_12_030: [ Otherwise IoTHubDeviceTwin_GetTwin shall save the received `deviceTwin` to the out parameter and return with it ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 467 | if (malloc_and_copy_uchar(&result, responseBuffer) != 0) |
XinZhangMS | 0:f7f1f0d76dd6 | 468 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 469 | LogError("failed to copy response"); |
XinZhangMS | 0:f7f1f0d76dd6 | 470 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 471 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 472 | BUFFER_delete(responseBuffer); |
XinZhangMS | 0:f7f1f0d76dd6 | 473 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 474 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 475 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 476 | |
XinZhangMS | 0:f7f1f0d76dd6 | 477 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 478 | |
XinZhangMS | 0:f7f1f0d76dd6 | 479 | char* IoTHubDeviceTwin_GetTwin(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE serviceClientDeviceTwinHandle, const char* deviceId) |
XinZhangMS | 0:f7f1f0d76dd6 | 480 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 481 | return IoTHubDeviceTwin_GetDeviceOrModuleTwin(serviceClientDeviceTwinHandle, deviceId, NULL); |
XinZhangMS | 0:f7f1f0d76dd6 | 482 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 483 | |
XinZhangMS | 0:f7f1f0d76dd6 | 484 | char* IoTHubDeviceTwin_GetModuleTwin(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE serviceClientDeviceTwinHandle, const char* deviceId, const char* moduleId) |
XinZhangMS | 0:f7f1f0d76dd6 | 485 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 486 | char* result; |
XinZhangMS | 0:f7f1f0d76dd6 | 487 | if ((serviceClientDeviceTwinHandle == NULL) || (deviceId == NULL) || (moduleId == NULL)) |
XinZhangMS | 0:f7f1f0d76dd6 | 488 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 489 | LogError("Input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 490 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 491 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 492 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 493 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 494 | result = IoTHubDeviceTwin_GetDeviceOrModuleTwin(serviceClientDeviceTwinHandle, deviceId, moduleId); |
XinZhangMS | 0:f7f1f0d76dd6 | 495 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 496 | |
XinZhangMS | 0:f7f1f0d76dd6 | 497 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 498 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 499 | |
XinZhangMS | 0:f7f1f0d76dd6 | 500 | char* IoTHubDeviceTwin_UpdateDeviceOrModuleTwin(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE serviceClientDeviceTwinHandle, const char* deviceId, const char* moduleId, const char* deviceTwinJson) |
XinZhangMS | 0:f7f1f0d76dd6 | 501 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 502 | char* result; |
XinZhangMS | 0:f7f1f0d76dd6 | 503 | |
XinZhangMS | 0:f7f1f0d76dd6 | 504 | /*CodesSRS_IOTHUBDEVICETWIN_12_031: [ IoTHubDeviceTwin_UpdateTwin shall verify the input parameters and if any of them are NULL then return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 505 | if ((serviceClientDeviceTwinHandle == NULL) || (deviceId == NULL) || (deviceTwinJson == NULL)) |
XinZhangMS | 0:f7f1f0d76dd6 | 506 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 507 | LogError("Input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 508 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 509 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 510 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 511 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 512 | BUFFER_HANDLE updateJson; |
XinZhangMS | 0:f7f1f0d76dd6 | 513 | BUFFER_HANDLE responseBuffer; |
XinZhangMS | 0:f7f1f0d76dd6 | 514 | |
XinZhangMS | 0:f7f1f0d76dd6 | 515 | /*CodesSRS_IOTHUBDEVICETWIN_12_032: [ IoTHubDeviceTwin_UpdateTwin shall create a BUFFER_HANDLE from deviceTwinJson by calling BUFFER_create ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 516 | if ((updateJson = BUFFER_create((const unsigned char*)deviceTwinJson, strlen(deviceTwinJson))) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 517 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 518 | /*CodesSRS_IOTHUBDEVICETWIN_12_033: [ If the creation fails, IoTHubDeviceTwin_UpdateTwin shall return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 519 | LogError("BUFFER_create failed for deviceTwinJson"); |
XinZhangMS | 0:f7f1f0d76dd6 | 520 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 521 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 522 | /*CodesSRS_IOTHUBDEVICETWIN_12_034: [ IoTHubDeviceTwin_UpdateTwin shall allocate memory for response buffer by calling BUFFER_new ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 523 | /*CodesSRS_IOTHUBDEVICETWIN_12_035: [ If the allocation failed, IoTHubDeviceTwin_UpdateTwin shall return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 524 | else if ((responseBuffer = BUFFER_new()) == NULL) |
XinZhangMS | 0:f7f1f0d76dd6 | 525 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 526 | /*CodesSRS_IOTHUBDEVICETWIN_12_034: [ If the creation fails, IoTHubDeviceTwin_UpdateTwin shall return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 527 | LogError("BUFFER_new failed for responseBuffer"); |
XinZhangMS | 0:f7f1f0d76dd6 | 528 | BUFFER_delete(updateJson); |
XinZhangMS | 0:f7f1f0d76dd6 | 529 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 530 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 531 | /*CodesSRS_IOTHUBDEVICETWIN_12_039: [ IoTHubDeviceTwin_UpdateTwin shall create an HTTP PATCH request using deviceTwinJson ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 532 | /*CodesSRS_IOTHUBDEVICETWIN_12_040: [ IoTHubDeviceTwin_UpdateTwin shall create an HTTP PATCH request using the createdfollowing HTTP headers: authorization=sasToken,Request-Id=1001,Accept=application/json,Content-Type=application/json,charset=utf-8 ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 533 | /*CodesSRS_IOTHUBDEVICETWIN_12_041: [ IoTHubDeviceTwin_UpdateTwin shall create an HTTPAPIEX_SAS_HANDLE handle by calling HTTPAPIEX_SAS_Create ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 534 | /*CodesSRS_IOTHUBDEVICETWIN_12_042: [ IoTHubDeviceTwin_UpdateTwin shall create an HTTPAPIEX_HANDLE handle by calling HTTPAPIEX_Create ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 535 | /*CodesSRS_IOTHUBDEVICETWIN_12_043: [ IoTHubDeviceTwin_UpdateTwin shall execute the HTTP PATCH request by calling HTTPAPIEX_ExecuteRequest ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 536 | else if (sendHttpRequestTwin(serviceClientDeviceTwinHandle, IOTHUB_TWIN_REQUEST_UPDATE, deviceId, moduleId, updateJson, responseBuffer) != IOTHUB_DEVICE_TWIN_OK) |
XinZhangMS | 0:f7f1f0d76dd6 | 537 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 538 | /*CodesSRS_IOTHUBDEVICETWIN_12_044: [ If any of the call fails during the HTTP creation IoTHubDeviceTwin_UpdateTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 539 | /*CodesSRS_IOTHUBDEVICETWIN_12_045: [ If any of the HTTPAPI call fails IoTHubDeviceTwin_UpdateTwin shall fail and return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 540 | /*CodesSRS_IOTHUBDEVICETWIN_12_046: [ IoTHubDeviceTwin_UpdateTwin shall verify the received HTTP status code and if it is not equal to 200 then return NULL ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 541 | LogError("Failure sending HTTP request for create device"); |
XinZhangMS | 0:f7f1f0d76dd6 | 542 | BUFFER_delete(responseBuffer); |
XinZhangMS | 0:f7f1f0d76dd6 | 543 | BUFFER_delete(updateJson); |
XinZhangMS | 0:f7f1f0d76dd6 | 544 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 545 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 546 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 547 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 548 | /*CodesSRS_IOTHUBDEVICETWIN_12_047: [ Otherwise IoTHubDeviceTwin_UpdateTwin shall save the received updated device twin to the out parameter and return with it ]*/ |
XinZhangMS | 0:f7f1f0d76dd6 | 549 | if (malloc_and_copy_uchar(&result, responseBuffer) != 0) |
XinZhangMS | 0:f7f1f0d76dd6 | 550 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 551 | LogError("failed to copy response"); |
XinZhangMS | 0:f7f1f0d76dd6 | 552 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 553 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 554 | BUFFER_delete(responseBuffer); |
XinZhangMS | 0:f7f1f0d76dd6 | 555 | BUFFER_delete(updateJson); |
XinZhangMS | 0:f7f1f0d76dd6 | 556 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 557 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 558 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 559 | |
XinZhangMS | 0:f7f1f0d76dd6 | 560 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 561 | |
XinZhangMS | 0:f7f1f0d76dd6 | 562 | char* IoTHubDeviceTwin_UpdateTwin(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE serviceClientDeviceTwinHandle, const char* deviceId, const char* deviceTwinJson) |
XinZhangMS | 0:f7f1f0d76dd6 | 563 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 564 | return IoTHubDeviceTwin_UpdateDeviceOrModuleTwin(serviceClientDeviceTwinHandle, deviceId, NULL, deviceTwinJson); |
XinZhangMS | 0:f7f1f0d76dd6 | 565 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 566 | |
XinZhangMS | 0:f7f1f0d76dd6 | 567 | char* IoTHubDeviceTwin_UpdateModuleTwin(IOTHUB_SERVICE_CLIENT_DEVICE_TWIN_HANDLE serviceClientDeviceTwinHandle, const char* deviceId, const char* moduleId, const char* moduleTwinJson) |
XinZhangMS | 0:f7f1f0d76dd6 | 568 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 569 | char* result; |
XinZhangMS | 0:f7f1f0d76dd6 | 570 | if ((serviceClientDeviceTwinHandle == NULL) || (deviceId == NULL) || (moduleId == NULL) || (moduleTwinJson == NULL)) |
XinZhangMS | 0:f7f1f0d76dd6 | 571 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 572 | LogError("Input parameter cannot be NULL"); |
XinZhangMS | 0:f7f1f0d76dd6 | 573 | result = NULL; |
XinZhangMS | 0:f7f1f0d76dd6 | 574 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 575 | else |
XinZhangMS | 0:f7f1f0d76dd6 | 576 | { |
XinZhangMS | 0:f7f1f0d76dd6 | 577 | result = IoTHubDeviceTwin_UpdateDeviceOrModuleTwin(serviceClientDeviceTwinHandle, deviceId, moduleId, moduleTwinJson); |
XinZhangMS | 0:f7f1f0d76dd6 | 578 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 579 | |
XinZhangMS | 0:f7f1f0d76dd6 | 580 | return result; |
XinZhangMS | 0:f7f1f0d76dd6 | 581 | } |
XinZhangMS | 0:f7f1f0d76dd6 | 582 | |
XinZhangMS | 0:f7f1f0d76dd6 | 583 | |
XinZhangMS | 0:f7f1f0d76dd6 | 584 | |
XinZhangMS | 0:f7f1f0d76dd6 | 585 |