A modelling and serializer library for Microsoft Azure IoTHub client applications
Dependents: sht15_remote_monitoring f767zi_mqtt remote_monitoring simplesample_amqp ... more
This library implements a serializer library to be used in projects involving Microsoft Azure IoT Hub connectivity. The code is replicated from https://github.com/Azure/azure-iot-sdks
serializer_devicetwin.h@17:fa1bba4c6053, 2016-11-16 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Wed Nov 16 21:38:26 2016 -0800
- Revision:
- 17:fa1bba4c6053
- Child:
- 18:58b667752399
1.0.10
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AzureIoTClient | 17:fa1bba4c6053 | 1 | // Copyright (c) Microsoft. All rights reserved. |
AzureIoTClient | 17:fa1bba4c6053 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
AzureIoTClient | 17:fa1bba4c6053 | 3 | |
AzureIoTClient | 17:fa1bba4c6053 | 4 | |
AzureIoTClient | 17:fa1bba4c6053 | 5 | #ifndef SERIALIZER_DEVICE_TWIN_H |
AzureIoTClient | 17:fa1bba4c6053 | 6 | #define SERIALIZER_DEVICE_TWIN_H |
AzureIoTClient | 17:fa1bba4c6053 | 7 | |
AzureIoTClient | 17:fa1bba4c6053 | 8 | #include "serializer.h" |
AzureIoTClient | 17:fa1bba4c6053 | 9 | |
AzureIoTClient | 17:fa1bba4c6053 | 10 | #include "iothub_client.h" |
AzureIoTClient | 17:fa1bba4c6053 | 11 | #include "iothub_client_ll.h" |
AzureIoTClient | 17:fa1bba4c6053 | 12 | #include "parson.h" |
AzureIoTClient | 17:fa1bba4c6053 | 13 | #include "vector.h" |
AzureIoTClient | 17:fa1bba4c6053 | 14 | |
AzureIoTClient | 17:fa1bba4c6053 | 15 | static void serializer_ingest(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback) |
AzureIoTClient | 17:fa1bba4c6053 | 16 | { |
AzureIoTClient | 17:fa1bba4c6053 | 17 | /*by convention, userContextCallback is a pointer to a model instance created with CodeFirst_CreateDevice*/ |
AzureIoTClient | 17:fa1bba4c6053 | 18 | |
AzureIoTClient | 17:fa1bba4c6053 | 19 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_001: [ serializer_ingest shall clone the payload into a null terminated string. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 20 | char* copyOfPayload = (char*)malloc(size + 1); |
AzureIoTClient | 17:fa1bba4c6053 | 21 | if (copyOfPayload == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 22 | { |
AzureIoTClient | 17:fa1bba4c6053 | 23 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 24 | LogError("unable to malloc\n"); |
AzureIoTClient | 17:fa1bba4c6053 | 25 | } |
AzureIoTClient | 17:fa1bba4c6053 | 26 | else |
AzureIoTClient | 17:fa1bba4c6053 | 27 | { |
AzureIoTClient | 17:fa1bba4c6053 | 28 | memcpy(copyOfPayload, payLoad, size); |
AzureIoTClient | 17:fa1bba4c6053 | 29 | copyOfPayload[size] = '\0'; |
AzureIoTClient | 17:fa1bba4c6053 | 30 | |
AzureIoTClient | 17:fa1bba4c6053 | 31 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_002: [ serializer_ingest shall parse the null terminated string into parson data types. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 32 | JSON_Value* allJSON = json_parse_string(copyOfPayload); |
AzureIoTClient | 17:fa1bba4c6053 | 33 | if (allJSON == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 34 | { |
AzureIoTClient | 17:fa1bba4c6053 | 35 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 36 | LogError("failure in json_parse_string"); |
AzureIoTClient | 17:fa1bba4c6053 | 37 | } |
AzureIoTClient | 17:fa1bba4c6053 | 38 | else |
AzureIoTClient | 17:fa1bba4c6053 | 39 | { |
AzureIoTClient | 17:fa1bba4c6053 | 40 | JSON_Object *allObject = json_value_get_object(allJSON); |
AzureIoTClient | 17:fa1bba4c6053 | 41 | if (allObject == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 42 | { |
AzureIoTClient | 17:fa1bba4c6053 | 43 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 44 | LogError("failure in json_value_get_object"); |
AzureIoTClient | 17:fa1bba4c6053 | 45 | } |
AzureIoTClient | 17:fa1bba4c6053 | 46 | else |
AzureIoTClient | 17:fa1bba4c6053 | 47 | { |
AzureIoTClient | 17:fa1bba4c6053 | 48 | switch (update_state) |
AzureIoTClient | 17:fa1bba4c6053 | 49 | { |
AzureIoTClient | 17:fa1bba4c6053 | 50 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_003: [ If update_state is DEVICE_TWIN_UPDATE_COMPLETE then serializer_ingest shall locate "desired" json name. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 51 | case DEVICE_TWIN_UPDATE_COMPLETE: |
AzureIoTClient | 17:fa1bba4c6053 | 52 | { |
AzureIoTClient | 17:fa1bba4c6053 | 53 | JSON_Object* desired = json_object_get_object(allObject, "desired"); |
AzureIoTClient | 17:fa1bba4c6053 | 54 | if (desired == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 55 | { |
AzureIoTClient | 17:fa1bba4c6053 | 56 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 57 | LogError("failure in json_object_get_object"); |
AzureIoTClient | 17:fa1bba4c6053 | 58 | } |
AzureIoTClient | 17:fa1bba4c6053 | 59 | else |
AzureIoTClient | 17:fa1bba4c6053 | 60 | { |
AzureIoTClient | 17:fa1bba4c6053 | 61 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_004: [ If "desired" contains "$version" then serializer_ingest shall remove it. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 62 | (void)json_object_remove(desired, "$version"); //it might not exist |
AzureIoTClient | 17:fa1bba4c6053 | 63 | JSON_Value* desiredAfterRemove = json_object_get_value(allObject, "desired"); |
AzureIoTClient | 17:fa1bba4c6053 | 64 | if (desiredAfterRemove != NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 65 | { |
AzureIoTClient | 17:fa1bba4c6053 | 66 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_005: [ The "desired" value shall be outputed to a null terminated string and serializer_ingest shall call CodeFirst_IngestDesiredProperties. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 67 | char* pretty = json_serialize_to_string(desiredAfterRemove); |
AzureIoTClient | 17:fa1bba4c6053 | 68 | if (pretty == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 69 | { |
AzureIoTClient | 17:fa1bba4c6053 | 70 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 71 | LogError("failure in json_serialize_to_string\n"); |
AzureIoTClient | 17:fa1bba4c6053 | 72 | } |
AzureIoTClient | 17:fa1bba4c6053 | 73 | else |
AzureIoTClient | 17:fa1bba4c6053 | 74 | { |
AzureIoTClient | 17:fa1bba4c6053 | 75 | if (CodeFirst_IngestDesiredProperties(userContextCallback, pretty) != CODEFIRST_OK) |
AzureIoTClient | 17:fa1bba4c6053 | 76 | { |
AzureIoTClient | 17:fa1bba4c6053 | 77 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 78 | LogError("failure ingesting desired properties\n"); |
AzureIoTClient | 17:fa1bba4c6053 | 79 | } |
AzureIoTClient | 17:fa1bba4c6053 | 80 | else |
AzureIoTClient | 17:fa1bba4c6053 | 81 | { |
AzureIoTClient | 17:fa1bba4c6053 | 82 | /*all is fine*/ |
AzureIoTClient | 17:fa1bba4c6053 | 83 | } |
AzureIoTClient | 17:fa1bba4c6053 | 84 | free(pretty); |
AzureIoTClient | 17:fa1bba4c6053 | 85 | } |
AzureIoTClient | 17:fa1bba4c6053 | 86 | } |
AzureIoTClient | 17:fa1bba4c6053 | 87 | } |
AzureIoTClient | 17:fa1bba4c6053 | 88 | break; |
AzureIoTClient | 17:fa1bba4c6053 | 89 | } |
AzureIoTClient | 17:fa1bba4c6053 | 90 | case DEVICE_TWIN_UPDATE_PARTIAL: |
AzureIoTClient | 17:fa1bba4c6053 | 91 | { |
AzureIoTClient | 17:fa1bba4c6053 | 92 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_006: [ If update_state is DEVICE_TWIN_UPDATE_PARTIAL then serializer_ingest shall remove "$version" (if it exists). ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 93 | (void)json_object_remove(allObject, "$version"); |
AzureIoTClient | 17:fa1bba4c6053 | 94 | |
AzureIoTClient | 17:fa1bba4c6053 | 95 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_007: [ The JSON shall be outputed to a null terminated string and serializer_ingest shall call CodeFirst_IngestDesiredProperties. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 96 | char* pretty = json_serialize_to_string(allJSON); |
AzureIoTClient | 17:fa1bba4c6053 | 97 | if (pretty == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 98 | { |
AzureIoTClient | 17:fa1bba4c6053 | 99 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 100 | LogError("failure in json_serialize_to_string\n"); |
AzureIoTClient | 17:fa1bba4c6053 | 101 | } |
AzureIoTClient | 17:fa1bba4c6053 | 102 | else |
AzureIoTClient | 17:fa1bba4c6053 | 103 | { |
AzureIoTClient | 17:fa1bba4c6053 | 104 | if (CodeFirst_IngestDesiredProperties(userContextCallback, pretty) != CODEFIRST_OK) |
AzureIoTClient | 17:fa1bba4c6053 | 105 | { |
AzureIoTClient | 17:fa1bba4c6053 | 106 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_008: [ If any of the above operations fail, then serializer_ingest shall return. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 107 | LogError("failure ingesting desired properties\n"); |
AzureIoTClient | 17:fa1bba4c6053 | 108 | } |
AzureIoTClient | 17:fa1bba4c6053 | 109 | else |
AzureIoTClient | 17:fa1bba4c6053 | 110 | { |
AzureIoTClient | 17:fa1bba4c6053 | 111 | /*all is fine*/ |
AzureIoTClient | 17:fa1bba4c6053 | 112 | } |
AzureIoTClient | 17:fa1bba4c6053 | 113 | free(pretty); |
AzureIoTClient | 17:fa1bba4c6053 | 114 | } |
AzureIoTClient | 17:fa1bba4c6053 | 115 | break; |
AzureIoTClient | 17:fa1bba4c6053 | 116 | } |
AzureIoTClient | 17:fa1bba4c6053 | 117 | default: |
AzureIoTClient | 17:fa1bba4c6053 | 118 | { |
AzureIoTClient | 17:fa1bba4c6053 | 119 | LogError("INTERNAL ERROR: unexpected value for update_state=%d\n", (int)update_state); |
AzureIoTClient | 17:fa1bba4c6053 | 120 | } |
AzureIoTClient | 17:fa1bba4c6053 | 121 | } |
AzureIoTClient | 17:fa1bba4c6053 | 122 | } |
AzureIoTClient | 17:fa1bba4c6053 | 123 | json_value_free(allJSON); |
AzureIoTClient | 17:fa1bba4c6053 | 124 | } |
AzureIoTClient | 17:fa1bba4c6053 | 125 | free(copyOfPayload); |
AzureIoTClient | 17:fa1bba4c6053 | 126 | } |
AzureIoTClient | 17:fa1bba4c6053 | 127 | } |
AzureIoTClient | 17:fa1bba4c6053 | 128 | |
AzureIoTClient | 17:fa1bba4c6053 | 129 | /*an enum that sets the type of the handle used to record IoTHubDeviceTwin_Create was called*/ |
AzureIoTClient | 17:fa1bba4c6053 | 130 | #define IOTHUB_CLIENT_HANDLE_TYPE_VALUES \ |
AzureIoTClient | 17:fa1bba4c6053 | 131 | IOTHUB_CLIENT_CONVENIENCE_HANDLE_TYPE, \ |
AzureIoTClient | 17:fa1bba4c6053 | 132 | IOTHUB_CLIENT_LL_HANDLE_TYPE |
AzureIoTClient | 17:fa1bba4c6053 | 133 | |
AzureIoTClient | 17:fa1bba4c6053 | 134 | DEFINE_ENUM(IOTHUB_CLIENT_HANDLE_TYPE, IOTHUB_CLIENT_HANDLE_TYPE_VALUES) |
AzureIoTClient | 17:fa1bba4c6053 | 135 | |
AzureIoTClient | 17:fa1bba4c6053 | 136 | typedef union IOTHUB_CLIENT_HANDLE_VALUE_TAG |
AzureIoTClient | 17:fa1bba4c6053 | 137 | { |
AzureIoTClient | 17:fa1bba4c6053 | 138 | IOTHUB_CLIENT_HANDLE iothubClientHandle; |
AzureIoTClient | 17:fa1bba4c6053 | 139 | IOTHUB_CLIENT_LL_HANDLE iothubClientLLHandle; |
AzureIoTClient | 17:fa1bba4c6053 | 140 | } IOTHUB_CLIENT_HANDLE_VALUE; |
AzureIoTClient | 17:fa1bba4c6053 | 141 | |
AzureIoTClient | 17:fa1bba4c6053 | 142 | typedef struct IOTHUB_CLIENT_HANDLE_VARIANT_TAG |
AzureIoTClient | 17:fa1bba4c6053 | 143 | { |
AzureIoTClient | 17:fa1bba4c6053 | 144 | IOTHUB_CLIENT_HANDLE_TYPE iothubClientHandleType; |
AzureIoTClient | 17:fa1bba4c6053 | 145 | IOTHUB_CLIENT_HANDLE_VALUE iothubClientHandleValue; |
AzureIoTClient | 17:fa1bba4c6053 | 146 | } IOTHUB_CLIENT_HANDLE_VARIANT; |
AzureIoTClient | 17:fa1bba4c6053 | 147 | |
AzureIoTClient | 17:fa1bba4c6053 | 148 | typedef struct SERIALIZER_DEVICETWIN_PROTOHANDLE_TAG /*it is called "PROTOHANDLE" because it is a primitive type of handle*/ |
AzureIoTClient | 17:fa1bba4c6053 | 149 | { |
AzureIoTClient | 17:fa1bba4c6053 | 150 | IOTHUB_CLIENT_HANDLE_VARIANT iothubClientHandleVariant; |
AzureIoTClient | 17:fa1bba4c6053 | 151 | void* deviceAssigned; |
AzureIoTClient | 17:fa1bba4c6053 | 152 | } SERIALIZER_DEVICETWIN_PROTOHANDLE; |
AzureIoTClient | 17:fa1bba4c6053 | 153 | |
AzureIoTClient | 17:fa1bba4c6053 | 154 | static VECTOR_HANDLE g_allProtoHandles=NULL; /*contains SERIALIZER_DEVICETWIN_PROTOHANDLE*/ |
AzureIoTClient | 17:fa1bba4c6053 | 155 | |
AzureIoTClient | 17:fa1bba4c6053 | 156 | static int lazilyAddProtohandle(const SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle) |
AzureIoTClient | 17:fa1bba4c6053 | 157 | { |
AzureIoTClient | 17:fa1bba4c6053 | 158 | int result; |
AzureIoTClient | 17:fa1bba4c6053 | 159 | if ((g_allProtoHandles == NULL) && ((g_allProtoHandles = VECTOR_create(sizeof(SERIALIZER_DEVICETWIN_PROTOHANDLE))) == NULL)) |
AzureIoTClient | 17:fa1bba4c6053 | 160 | { |
AzureIoTClient | 17:fa1bba4c6053 | 161 | LogError("failure in VECTOR_create"); |
AzureIoTClient | 17:fa1bba4c6053 | 162 | result = __LINE__; |
AzureIoTClient | 17:fa1bba4c6053 | 163 | } |
AzureIoTClient | 17:fa1bba4c6053 | 164 | else |
AzureIoTClient | 17:fa1bba4c6053 | 165 | { |
AzureIoTClient | 17:fa1bba4c6053 | 166 | if (VECTOR_push_back(g_allProtoHandles, protoHandle, 1) != 0) |
AzureIoTClient | 17:fa1bba4c6053 | 167 | { |
AzureIoTClient | 17:fa1bba4c6053 | 168 | LogError("failure in VECTOR_push_back"); |
AzureIoTClient | 17:fa1bba4c6053 | 169 | result = __LINE__; |
AzureIoTClient | 17:fa1bba4c6053 | 170 | |
AzureIoTClient | 17:fa1bba4c6053 | 171 | /*leave it as it was*/ |
AzureIoTClient | 17:fa1bba4c6053 | 172 | |
AzureIoTClient | 17:fa1bba4c6053 | 173 | if (VECTOR_size(g_allProtoHandles) == 0) |
AzureIoTClient | 17:fa1bba4c6053 | 174 | { |
AzureIoTClient | 17:fa1bba4c6053 | 175 | VECTOR_destroy(g_allProtoHandles); |
AzureIoTClient | 17:fa1bba4c6053 | 176 | g_allProtoHandles = NULL; |
AzureIoTClient | 17:fa1bba4c6053 | 177 | } |
AzureIoTClient | 17:fa1bba4c6053 | 178 | } |
AzureIoTClient | 17:fa1bba4c6053 | 179 | else |
AzureIoTClient | 17:fa1bba4c6053 | 180 | { |
AzureIoTClient | 17:fa1bba4c6053 | 181 | result = 0; |
AzureIoTClient | 17:fa1bba4c6053 | 182 | } |
AzureIoTClient | 17:fa1bba4c6053 | 183 | } |
AzureIoTClient | 17:fa1bba4c6053 | 184 | return result; |
AzureIoTClient | 17:fa1bba4c6053 | 185 | } |
AzureIoTClient | 17:fa1bba4c6053 | 186 | |
AzureIoTClient | 17:fa1bba4c6053 | 187 | static IOTHUB_CLIENT_RESULT Generic_IoTHubClient_SetDeviceTwinCallback(const SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback) |
AzureIoTClient | 17:fa1bba4c6053 | 188 | { |
AzureIoTClient | 17:fa1bba4c6053 | 189 | IOTHUB_CLIENT_RESULT result; |
AzureIoTClient | 17:fa1bba4c6053 | 190 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_011: [ IoTHubDeviceTwinCreate_Impl shall set the device twin callback. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 191 | switch (protoHandle->iothubClientHandleVariant.iothubClientHandleType) |
AzureIoTClient | 17:fa1bba4c6053 | 192 | { |
AzureIoTClient | 17:fa1bba4c6053 | 193 | case IOTHUB_CLIENT_CONVENIENCE_HANDLE_TYPE: |
AzureIoTClient | 17:fa1bba4c6053 | 194 | { |
AzureIoTClient | 17:fa1bba4c6053 | 195 | if ((result = IoTHubClient_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle, deviceTwinCallback, userContextCallback)) != IOTHUB_CLIENT_OK) |
AzureIoTClient | 17:fa1bba4c6053 | 196 | { |
AzureIoTClient | 17:fa1bba4c6053 | 197 | LogError("failure in IoTHubClient_SetDeviceTwinCallback"); |
AzureIoTClient | 17:fa1bba4c6053 | 198 | } |
AzureIoTClient | 17:fa1bba4c6053 | 199 | break; |
AzureIoTClient | 17:fa1bba4c6053 | 200 | } |
AzureIoTClient | 17:fa1bba4c6053 | 201 | case IOTHUB_CLIENT_LL_HANDLE_TYPE: |
AzureIoTClient | 17:fa1bba4c6053 | 202 | { |
AzureIoTClient | 17:fa1bba4c6053 | 203 | if ((result =IoTHubClient_LL_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle, deviceTwinCallback, userContextCallback)) != IOTHUB_CLIENT_OK) |
AzureIoTClient | 17:fa1bba4c6053 | 204 | { |
AzureIoTClient | 17:fa1bba4c6053 | 205 | LogError("failure in IoTHubClient_LL_SetDeviceTwinCallback"); |
AzureIoTClient | 17:fa1bba4c6053 | 206 | } |
AzureIoTClient | 17:fa1bba4c6053 | 207 | break; |
AzureIoTClient | 17:fa1bba4c6053 | 208 | } |
AzureIoTClient | 17:fa1bba4c6053 | 209 | default: |
AzureIoTClient | 17:fa1bba4c6053 | 210 | { |
AzureIoTClient | 17:fa1bba4c6053 | 211 | result = IOTHUB_CLIENT_ERROR; |
AzureIoTClient | 17:fa1bba4c6053 | 212 | LogError("INTERNAL ERROR"); |
AzureIoTClient | 17:fa1bba4c6053 | 213 | } |
AzureIoTClient | 17:fa1bba4c6053 | 214 | }/*switch*/ |
AzureIoTClient | 17:fa1bba4c6053 | 215 | return result; |
AzureIoTClient | 17:fa1bba4c6053 | 216 | } |
AzureIoTClient | 17:fa1bba4c6053 | 217 | |
AzureIoTClient | 17:fa1bba4c6053 | 218 | static void* IoTHubDeviceTwinCreate_Impl(const char* name, size_t sizeOfName, SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle) |
AzureIoTClient | 17:fa1bba4c6053 | 219 | { |
AzureIoTClient | 17:fa1bba4c6053 | 220 | void* result; |
AzureIoTClient | 17:fa1bba4c6053 | 221 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_009: [ IoTHubDeviceTwinCreate_Impl shall locate the model and the metadata for name by calling Schema_GetSchemaForModel/Schema_GetMetadata/Schema_GetModelByName. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 222 | SCHEMA_HANDLE h = Schema_GetSchemaForModel(name); |
AzureIoTClient | 17:fa1bba4c6053 | 223 | if (h == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 224 | { |
AzureIoTClient | 17:fa1bba4c6053 | 225 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 226 | LogError("failure in Schema_GetSchemaForModel."); |
AzureIoTClient | 17:fa1bba4c6053 | 227 | result = NULL; |
AzureIoTClient | 17:fa1bba4c6053 | 228 | } |
AzureIoTClient | 17:fa1bba4c6053 | 229 | else |
AzureIoTClient | 17:fa1bba4c6053 | 230 | { |
AzureIoTClient | 17:fa1bba4c6053 | 231 | void* metadata = Schema_GetMetadata(h); |
AzureIoTClient | 17:fa1bba4c6053 | 232 | SCHEMA_MODEL_TYPE_HANDLE modelType = Schema_GetModelByName(h, name); |
AzureIoTClient | 17:fa1bba4c6053 | 233 | if (modelType == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 234 | { |
AzureIoTClient | 17:fa1bba4c6053 | 235 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 236 | LogError("failure in Schema_GetModelByName"); |
AzureIoTClient | 17:fa1bba4c6053 | 237 | result = NULL; |
AzureIoTClient | 17:fa1bba4c6053 | 238 | } |
AzureIoTClient | 17:fa1bba4c6053 | 239 | else |
AzureIoTClient | 17:fa1bba4c6053 | 240 | { |
AzureIoTClient | 17:fa1bba4c6053 | 241 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_010: [ IoTHubDeviceTwinCreate_Impl shall call CodeFirst_CreateDevice. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 242 | result = CodeFirst_CreateDevice(modelType, (REFLECTED_DATA_FROM_DATAPROVIDER *)metadata, sizeOfName, true); |
AzureIoTClient | 17:fa1bba4c6053 | 243 | if (result == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 244 | { |
AzureIoTClient | 17:fa1bba4c6053 | 245 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 246 | LogError("failure in CodeFirst_CreateDevice"); |
AzureIoTClient | 17:fa1bba4c6053 | 247 | /*return as is*/ |
AzureIoTClient | 17:fa1bba4c6053 | 248 | } |
AzureIoTClient | 17:fa1bba4c6053 | 249 | else |
AzureIoTClient | 17:fa1bba4c6053 | 250 | { |
AzureIoTClient | 17:fa1bba4c6053 | 251 | protoHandle->deviceAssigned = result; |
AzureIoTClient | 17:fa1bba4c6053 | 252 | if (Generic_IoTHubClient_SetDeviceTwinCallback(protoHandle, serializer_ingest, result) != IOTHUB_CLIENT_OK) |
AzureIoTClient | 17:fa1bba4c6053 | 253 | { |
AzureIoTClient | 17:fa1bba4c6053 | 254 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 255 | LogError("failure in Generic_IoTHubClient_SetDeviceTwinCallback"); |
AzureIoTClient | 17:fa1bba4c6053 | 256 | CodeFirst_DestroyDevice(result); |
AzureIoTClient | 17:fa1bba4c6053 | 257 | result = NULL; |
AzureIoTClient | 17:fa1bba4c6053 | 258 | } |
AzureIoTClient | 17:fa1bba4c6053 | 259 | else |
AzureIoTClient | 17:fa1bba4c6053 | 260 | { |
AzureIoTClient | 17:fa1bba4c6053 | 261 | /*lazily add the protohandle to the array of tracking handles*/ |
AzureIoTClient | 17:fa1bba4c6053 | 262 | |
AzureIoTClient | 17:fa1bba4c6053 | 263 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_012: [ IoTHubDeviceTwinCreate_Impl shall record the pair of (device, IoTHubClient(_LL)). ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 264 | if (lazilyAddProtohandle(protoHandle) != 0) |
AzureIoTClient | 17:fa1bba4c6053 | 265 | { |
AzureIoTClient | 17:fa1bba4c6053 | 266 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_014: [ Otherwise, IoTHubDeviceTwinCreate_Impl shall fail and return NULL. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 267 | LogError("unable to add the protohandle to the collection of handles"); |
AzureIoTClient | 17:fa1bba4c6053 | 268 | /*unsubscribe*/ |
AzureIoTClient | 17:fa1bba4c6053 | 269 | if (Generic_IoTHubClient_SetDeviceTwinCallback(protoHandle, NULL, NULL) != IOTHUB_CLIENT_OK) |
AzureIoTClient | 17:fa1bba4c6053 | 270 | { |
AzureIoTClient | 17:fa1bba4c6053 | 271 | /*just log the error*/ |
AzureIoTClient | 17:fa1bba4c6053 | 272 | LogError("failure in Generic_IoTHubClient_SetDeviceTwinCallback"); |
AzureIoTClient | 17:fa1bba4c6053 | 273 | } |
AzureIoTClient | 17:fa1bba4c6053 | 274 | CodeFirst_DestroyDevice(result); |
AzureIoTClient | 17:fa1bba4c6053 | 275 | result = NULL; |
AzureIoTClient | 17:fa1bba4c6053 | 276 | } |
AzureIoTClient | 17:fa1bba4c6053 | 277 | else |
AzureIoTClient | 17:fa1bba4c6053 | 278 | { |
AzureIoTClient | 17:fa1bba4c6053 | 279 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_013: [ If all operations complete successfully then IoTHubDeviceTwinCreate_Impl shall succeeds and return a non-NULL value. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 280 | /*return as is*/ |
AzureIoTClient | 17:fa1bba4c6053 | 281 | } |
AzureIoTClient | 17:fa1bba4c6053 | 282 | } |
AzureIoTClient | 17:fa1bba4c6053 | 283 | } |
AzureIoTClient | 17:fa1bba4c6053 | 284 | } |
AzureIoTClient | 17:fa1bba4c6053 | 285 | } |
AzureIoTClient | 17:fa1bba4c6053 | 286 | return result; |
AzureIoTClient | 17:fa1bba4c6053 | 287 | } |
AzureIoTClient | 17:fa1bba4c6053 | 288 | |
AzureIoTClient | 17:fa1bba4c6053 | 289 | static bool protoHandleHasDeviceStartAddress(const void* element, const void* value) |
AzureIoTClient | 17:fa1bba4c6053 | 290 | { |
AzureIoTClient | 17:fa1bba4c6053 | 291 | const SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle = (const SERIALIZER_DEVICETWIN_PROTOHANDLE*)element; |
AzureIoTClient | 17:fa1bba4c6053 | 292 | return protoHandle->deviceAssigned == value; |
AzureIoTClient | 17:fa1bba4c6053 | 293 | } |
AzureIoTClient | 17:fa1bba4c6053 | 294 | |
AzureIoTClient | 17:fa1bba4c6053 | 295 | static void IoTHubDeviceTwin_Destroy_Impl(void* model) |
AzureIoTClient | 17:fa1bba4c6053 | 296 | { |
AzureIoTClient | 17:fa1bba4c6053 | 297 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_020: [ If model is NULL then IoTHubDeviceTwin_Destroy_Impl shall return. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 298 | if (model == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 299 | { |
AzureIoTClient | 17:fa1bba4c6053 | 300 | LogError("invalid argument void* model=%p", model); |
AzureIoTClient | 17:fa1bba4c6053 | 301 | } |
AzureIoTClient | 17:fa1bba4c6053 | 302 | else |
AzureIoTClient | 17:fa1bba4c6053 | 303 | { |
AzureIoTClient | 17:fa1bba4c6053 | 304 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_015: [ IoTHubDeviceTwin_Destroy_Impl shall locate the saved handle belonging to model. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 305 | SERIALIZER_DEVICETWIN_PROTOHANDLE* protoHandle = (SERIALIZER_DEVICETWIN_PROTOHANDLE*)VECTOR_find_if(g_allProtoHandles, protoHandleHasDeviceStartAddress, model); |
AzureIoTClient | 17:fa1bba4c6053 | 306 | if (protoHandle == NULL) |
AzureIoTClient | 17:fa1bba4c6053 | 307 | { |
AzureIoTClient | 17:fa1bba4c6053 | 308 | LogError("failure in VECTOR_find_if [not found]"); |
AzureIoTClient | 17:fa1bba4c6053 | 309 | } |
AzureIoTClient | 17:fa1bba4c6053 | 310 | else |
AzureIoTClient | 17:fa1bba4c6053 | 311 | { |
AzureIoTClient | 17:fa1bba4c6053 | 312 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_016: [ IoTHubDeviceTwin_Destroy_Impl shall set the devicetwin callback to NULL. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 313 | switch (protoHandle->iothubClientHandleVariant.iothubClientHandleType) |
AzureIoTClient | 17:fa1bba4c6053 | 314 | { |
AzureIoTClient | 17:fa1bba4c6053 | 315 | case IOTHUB_CLIENT_CONVENIENCE_HANDLE_TYPE: |
AzureIoTClient | 17:fa1bba4c6053 | 316 | { |
AzureIoTClient | 17:fa1bba4c6053 | 317 | if (IoTHubClient_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle, NULL, NULL) != IOTHUB_CLIENT_OK) |
AzureIoTClient | 17:fa1bba4c6053 | 318 | { |
AzureIoTClient | 17:fa1bba4c6053 | 319 | LogError("failure in IoTHubClient_SetDeviceTwinCallback"); |
AzureIoTClient | 17:fa1bba4c6053 | 320 | } |
AzureIoTClient | 17:fa1bba4c6053 | 321 | break; |
AzureIoTClient | 17:fa1bba4c6053 | 322 | } |
AzureIoTClient | 17:fa1bba4c6053 | 323 | case IOTHUB_CLIENT_LL_HANDLE_TYPE: |
AzureIoTClient | 17:fa1bba4c6053 | 324 | { |
AzureIoTClient | 17:fa1bba4c6053 | 325 | if (IoTHubClient_LL_SetDeviceTwinCallback(protoHandle->iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle, NULL, NULL) != IOTHUB_CLIENT_OK) |
AzureIoTClient | 17:fa1bba4c6053 | 326 | { |
AzureIoTClient | 17:fa1bba4c6053 | 327 | LogError("failure in IoTHubClient_LL_SetDeviceTwinCallback"); |
AzureIoTClient | 17:fa1bba4c6053 | 328 | } |
AzureIoTClient | 17:fa1bba4c6053 | 329 | break; |
AzureIoTClient | 17:fa1bba4c6053 | 330 | } |
AzureIoTClient | 17:fa1bba4c6053 | 331 | default: |
AzureIoTClient | 17:fa1bba4c6053 | 332 | { |
AzureIoTClient | 17:fa1bba4c6053 | 333 | LogError("INTERNAL ERROR"); |
AzureIoTClient | 17:fa1bba4c6053 | 334 | } |
AzureIoTClient | 17:fa1bba4c6053 | 335 | }/*switch*/ |
AzureIoTClient | 17:fa1bba4c6053 | 336 | } |
AzureIoTClient | 17:fa1bba4c6053 | 337 | |
AzureIoTClient | 17:fa1bba4c6053 | 338 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_017: [ IoTHubDeviceTwin_Destroy_Impl shall call CodeFirst_DestroyDevice. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 339 | CodeFirst_DestroyDevice(protoHandle->deviceAssigned); |
AzureIoTClient | 17:fa1bba4c6053 | 340 | |
AzureIoTClient | 17:fa1bba4c6053 | 341 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_018: [ IoTHubDeviceTwin_Destroy_Impl shall remove the IoTHubClient_Handle and the device handle from the recorded set. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 342 | VECTOR_erase(g_allProtoHandles, protoHandle, 1); |
AzureIoTClient | 17:fa1bba4c6053 | 343 | |
AzureIoTClient | 17:fa1bba4c6053 | 344 | /*Codes_SRS_SERIALIZERDEVICETWIN_02_019: [ If the recorded set of IoTHubClient handles is zero size, then the set shall be destroyed. ]*/ |
AzureIoTClient | 17:fa1bba4c6053 | 345 | if (VECTOR_size(g_allProtoHandles) == 0) /*lazy init means more work @ destroy time*/ |
AzureIoTClient | 17:fa1bba4c6053 | 346 | { |
AzureIoTClient | 17:fa1bba4c6053 | 347 | VECTOR_destroy(g_allProtoHandles); |
AzureIoTClient | 17:fa1bba4c6053 | 348 | g_allProtoHandles = NULL; |
AzureIoTClient | 17:fa1bba4c6053 | 349 | } |
AzureIoTClient | 17:fa1bba4c6053 | 350 | } |
AzureIoTClient | 17:fa1bba4c6053 | 351 | } |
AzureIoTClient | 17:fa1bba4c6053 | 352 | |
AzureIoTClient | 17:fa1bba4c6053 | 353 | #define DECLARE_DEVICETWIN_MODEL(name, ...) \ |
AzureIoTClient | 17:fa1bba4c6053 | 354 | DECLARE_MODEL(name, __VA_ARGS__) \ |
AzureIoTClient | 17:fa1bba4c6053 | 355 | static name* C2(IoTHubDeviceTwin_Create, name)(IOTHUB_CLIENT_HANDLE iotHubClientHandle) \ |
AzureIoTClient | 17:fa1bba4c6053 | 356 | { \ |
AzureIoTClient | 17:fa1bba4c6053 | 357 | SERIALIZER_DEVICETWIN_PROTOHANDLE protoHandle; \ |
AzureIoTClient | 17:fa1bba4c6053 | 358 | protoHandle.iothubClientHandleVariant.iothubClientHandleType = IOTHUB_CLIENT_CONVENIENCE_HANDLE_TYPE; \ |
AzureIoTClient | 17:fa1bba4c6053 | 359 | protoHandle.iothubClientHandleVariant.iothubClientHandleValue.iothubClientHandle = iotHubClientHandle; \ |
AzureIoTClient | 17:fa1bba4c6053 | 360 | return (name*)IoTHubDeviceTwinCreate_Impl(#name, sizeof(name), &protoHandle); \ |
AzureIoTClient | 17:fa1bba4c6053 | 361 | } \ |
AzureIoTClient | 17:fa1bba4c6053 | 362 | \ |
AzureIoTClient | 17:fa1bba4c6053 | 363 | static void C2(IoTHubDeviceTwin_Destroy, name) (name* model) \ |
AzureIoTClient | 17:fa1bba4c6053 | 364 | { \ |
AzureIoTClient | 17:fa1bba4c6053 | 365 | IoTHubDeviceTwin_Destroy_Impl(model); \ |
AzureIoTClient | 17:fa1bba4c6053 | 366 | } \ |
AzureIoTClient | 17:fa1bba4c6053 | 367 | \ |
AzureIoTClient | 17:fa1bba4c6053 | 368 | static name* C2(IoTHubDeviceTwin_LL_Create, name)(IOTHUB_CLIENT_LL_HANDLE iotHubClientLLHandle) \ |
AzureIoTClient | 17:fa1bba4c6053 | 369 | { \ |
AzureIoTClient | 17:fa1bba4c6053 | 370 | SERIALIZER_DEVICETWIN_PROTOHANDLE protoHandle; \ |
AzureIoTClient | 17:fa1bba4c6053 | 371 | protoHandle.iothubClientHandleVariant.iothubClientHandleType = IOTHUB_CLIENT_LL_HANDLE_TYPE; \ |
AzureIoTClient | 17:fa1bba4c6053 | 372 | protoHandle.iothubClientHandleVariant.iothubClientHandleValue.iothubClientLLHandle = iotHubClientLLHandle; \ |
AzureIoTClient | 17:fa1bba4c6053 | 373 | return (name*)IoTHubDeviceTwinCreate_Impl(#name, sizeof(name), &protoHandle); \ |
AzureIoTClient | 17:fa1bba4c6053 | 374 | } \ |
AzureIoTClient | 17:fa1bba4c6053 | 375 | \ |
AzureIoTClient | 17:fa1bba4c6053 | 376 | static void C2(IoTHubDeviceTwin_LL_Destroy, name) (name* model) \ |
AzureIoTClient | 17:fa1bba4c6053 | 377 | { \ |
AzureIoTClient | 17:fa1bba4c6053 | 378 | IoTHubDeviceTwin_Destroy_Impl(model); \ |
AzureIoTClient | 17:fa1bba4c6053 | 379 | } \ |
AzureIoTClient | 17:fa1bba4c6053 | 380 | |
AzureIoTClient | 17:fa1bba4c6053 | 381 | #endif /*SERIALIZER_DEVICE_TWIN_H*/ |
AzureIoTClient | 17:fa1bba4c6053 | 382 | |
AzureIoTClient | 17:fa1bba4c6053 | 383 |