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

Committer:
AzureIoTClient
Date:
Fri Jan 15 15:49:46 2016 -0800
Revision:
6:36cc37b1dbc9
Parent:
0:1f9b2707ec7d
Child:
7:5176a13270bb
v1.0.0-preview.4

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AzureIoTClient 0:1f9b2707ec7d 1 // Copyright (c) Microsoft. All rights reserved.
AzureIoTClient 0:1f9b2707ec7d 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
AzureIoTClient 0:1f9b2707ec7d 3
AzureIoTClient 0:1f9b2707ec7d 4 #include <stdlib.h>
AzureIoTClient 0:1f9b2707ec7d 5 #ifdef _CRTDBG_MAP_ALLOC
AzureIoTClient 0:1f9b2707ec7d 6 #include <crtdbg.h>
AzureIoTClient 0:1f9b2707ec7d 7 #endif
AzureIoTClient 0:1f9b2707ec7d 8 #include "gballoc.h"
AzureIoTClient 0:1f9b2707ec7d 9
AzureIoTClient 0:1f9b2707ec7d 10 #include "codefirst.h"
AzureIoTClient 0:1f9b2707ec7d 11 #include "macro_utils.h"
AzureIoTClient 0:1f9b2707ec7d 12 #include "crt_abstractions.h"
AzureIoTClient 0:1f9b2707ec7d 13 #include "iot_logging.h"
AzureIoTClient 0:1f9b2707ec7d 14 #include <stddef.h>
AzureIoTClient 0:1f9b2707ec7d 15 #include "crt_abstractions.h"
AzureIoTClient 0:1f9b2707ec7d 16 #include "iotdevice.h"
AzureIoTClient 0:1f9b2707ec7d 17
AzureIoTClient 0:1f9b2707ec7d 18 DEFINE_ENUM_STRINGS(CODEFIRST_RESULT, CODEFIRST_ENUM_VALUES)
AzureIoTClient 0:1f9b2707ec7d 19 DEFINE_ENUM_STRINGS(EXECUTE_COMMAND_RESULT, EXECUTE_COMMAND_RESULT_VALUES)
AzureIoTClient 0:1f9b2707ec7d 20
AzureIoTClient 0:1f9b2707ec7d 21 #define LOG_CODEFIRST_ERROR \
AzureIoTClient 0:1f9b2707ec7d 22 LogError("(result = %s)\r\n", ENUM_TO_STRING(CODEFIRST_RESULT, result))
AzureIoTClient 0:1f9b2707ec7d 23
AzureIoTClient 0:1f9b2707ec7d 24 typedef struct DEVICE_HEADER_DATA_TAG
AzureIoTClient 0:1f9b2707ec7d 25 {
AzureIoTClient 0:1f9b2707ec7d 26 DEVICE_HANDLE DeviceHandle;
AzureIoTClient 0:1f9b2707ec7d 27 const REFLECTED_DATA_FROM_DATAPROVIDER* ReflectedData;
AzureIoTClient 0:1f9b2707ec7d 28 SCHEMA_MODEL_TYPE_HANDLE ModelHandle;
AzureIoTClient 0:1f9b2707ec7d 29 size_t DataSize;
AzureIoTClient 0:1f9b2707ec7d 30 unsigned char* data;
AzureIoTClient 0:1f9b2707ec7d 31 } DEVICE_HEADER_DATA;
AzureIoTClient 0:1f9b2707ec7d 32
AzureIoTClient 0:1f9b2707ec7d 33 #define COUNT_OF(A) (sizeof(A) / sizeof((A)[0]))
AzureIoTClient 0:1f9b2707ec7d 34
AzureIoTClient 0:1f9b2707ec7d 35 typedef enum CODEFIRST_STATE_TAG
AzureIoTClient 0:1f9b2707ec7d 36 {
AzureIoTClient 0:1f9b2707ec7d 37 CODEFIRST_STATE_NOT_INIT,
AzureIoTClient 0:1f9b2707ec7d 38 CODEFIRST_STATE_INIT
AzureIoTClient 0:1f9b2707ec7d 39 }CODEFIRST_STATE;
AzureIoTClient 0:1f9b2707ec7d 40
AzureIoTClient 0:1f9b2707ec7d 41 static CODEFIRST_STATE g_state = CODEFIRST_STATE_NOT_INIT;
AzureIoTClient 0:1f9b2707ec7d 42
AzureIoTClient 0:1f9b2707ec7d 43 static const char* g_OverrideSchemaNamespace;
AzureIoTClient 0:1f9b2707ec7d 44 static size_t g_DeviceCount = 0;
AzureIoTClient 0:1f9b2707ec7d 45 static DEVICE_HEADER_DATA** g_Devices = NULL;
AzureIoTClient 0:1f9b2707ec7d 46
AzureIoTClient 0:1f9b2707ec7d 47 static void DestroyDevice(DEVICE_HEADER_DATA* deviceHeader)
AzureIoTClient 0:1f9b2707ec7d 48 {
AzureIoTClient 0:1f9b2707ec7d 49 /* Codes_SRS_CODEFIRST_99_085:[CodeFirst_DestroyDevice shall free all resources associated with a device.] */
AzureIoTClient 0:1f9b2707ec7d 50 /* Codes_SRS_CODEFIRST_99_087:[In order to release the device handle, CodeFirst_DestroyDevice shall call Device_Destroy.] */
AzureIoTClient 0:1f9b2707ec7d 51 Device_Destroy(deviceHeader->DeviceHandle);
AzureIoTClient 0:1f9b2707ec7d 52 free(deviceHeader->data);
AzureIoTClient 0:1f9b2707ec7d 53 free(deviceHeader);
AzureIoTClient 0:1f9b2707ec7d 54 }
AzureIoTClient 0:1f9b2707ec7d 55
AzureIoTClient 0:1f9b2707ec7d 56 static CODEFIRST_RESULT buildStructTypes(SCHEMA_HANDLE schemaHandle, const REFLECTED_DATA_FROM_DATAPROVIDER* reflectedData)
AzureIoTClient 0:1f9b2707ec7d 57 {
AzureIoTClient 0:1f9b2707ec7d 58 CODEFIRST_RESULT result = CODEFIRST_OK;
AzureIoTClient 0:1f9b2707ec7d 59
AzureIoTClient 0:1f9b2707ec7d 60 const REFLECTED_SOMETHING* something;
AzureIoTClient 0:1f9b2707ec7d 61 for (something = reflectedData->reflectedData; something != NULL; something = something->next)
AzureIoTClient 0:1f9b2707ec7d 62 {
AzureIoTClient 0:1f9b2707ec7d 63 if (something->type == REFLECTION_STRUCT_TYPE)
AzureIoTClient 0:1f9b2707ec7d 64 {
AzureIoTClient 0:1f9b2707ec7d 65 SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle;
AzureIoTClient 0:1f9b2707ec7d 66 structTypeHandle = Schema_CreateStructType(schemaHandle, something->what.structure.name);
AzureIoTClient 0:1f9b2707ec7d 67
AzureIoTClient 0:1f9b2707ec7d 68 if (structTypeHandle == NULL)
AzureIoTClient 0:1f9b2707ec7d 69 {
AzureIoTClient 0:1f9b2707ec7d 70 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 71 result = CODEFIRST_SCHEMA_ERROR;
AzureIoTClient 0:1f9b2707ec7d 72 LogError("create struct failed %s\r\n", ENUM_TO_STRING(CODEFIRST_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 73 break;
AzureIoTClient 0:1f9b2707ec7d 74 }
AzureIoTClient 0:1f9b2707ec7d 75 else
AzureIoTClient 0:1f9b2707ec7d 76 {
AzureIoTClient 0:1f9b2707ec7d 77 const REFLECTED_SOMETHING* maybeField;
AzureIoTClient 0:1f9b2707ec7d 78 /*look for the field... */
AzureIoTClient 0:1f9b2707ec7d 79 for (maybeField = reflectedData->reflectedData; maybeField != NULL; maybeField = maybeField->next)
AzureIoTClient 0:1f9b2707ec7d 80 {
AzureIoTClient 0:1f9b2707ec7d 81 if (maybeField->type == REFLECTION_FIELD_TYPE)
AzureIoTClient 0:1f9b2707ec7d 82 {
AzureIoTClient 0:1f9b2707ec7d 83 if (strcmp(maybeField->what.field.structName, something->what.structure.name) == 0)
AzureIoTClient 0:1f9b2707ec7d 84 {
AzureIoTClient 0:1f9b2707ec7d 85 if (Schema_AddStructTypeProperty(structTypeHandle, maybeField->what.field.fieldName, maybeField->what.field.fieldType) != SCHEMA_OK)
AzureIoTClient 0:1f9b2707ec7d 86 {
AzureIoTClient 0:1f9b2707ec7d 87 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 88 result = CODEFIRST_SCHEMA_ERROR;
AzureIoTClient 0:1f9b2707ec7d 89 LogError("add struct property failed %s\r\n", ENUM_TO_STRING(CODEFIRST_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 90 break;
AzureIoTClient 0:1f9b2707ec7d 91 }
AzureIoTClient 0:1f9b2707ec7d 92 }
AzureIoTClient 0:1f9b2707ec7d 93 }
AzureIoTClient 0:1f9b2707ec7d 94 }
AzureIoTClient 0:1f9b2707ec7d 95 }
AzureIoTClient 0:1f9b2707ec7d 96 }
AzureIoTClient 0:1f9b2707ec7d 97 }
AzureIoTClient 0:1f9b2707ec7d 98
AzureIoTClient 0:1f9b2707ec7d 99 return result;
AzureIoTClient 0:1f9b2707ec7d 100 }
AzureIoTClient 0:1f9b2707ec7d 101
AzureIoTClient 0:1f9b2707ec7d 102 static CODEFIRST_RESULT buildModel(SCHEMA_HANDLE schemaHandle, const REFLECTED_DATA_FROM_DATAPROVIDER* reflectedData, const REFLECTED_SOMETHING* modelReflectedData)
AzureIoTClient 0:1f9b2707ec7d 103 {
AzureIoTClient 0:1f9b2707ec7d 104 CODEFIRST_RESULT result = CODEFIRST_OK;
AzureIoTClient 0:1f9b2707ec7d 105 const REFLECTED_SOMETHING* something;
AzureIoTClient 0:1f9b2707ec7d 106 SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle;
AzureIoTClient 0:1f9b2707ec7d 107
AzureIoTClient 0:1f9b2707ec7d 108 modelTypeHandle = Schema_GetModelByName(schemaHandle, modelReflectedData->what.model.name);
AzureIoTClient 0:1f9b2707ec7d 109 if (modelTypeHandle == NULL)
AzureIoTClient 0:1f9b2707ec7d 110 {
AzureIoTClient 0:1f9b2707ec7d 111 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 112 result = CODEFIRST_SCHEMA_ERROR;
AzureIoTClient 0:1f9b2707ec7d 113 LogError("cannot get model %s %s", modelReflectedData->what.model.name, ENUM_TO_STRING(CODEFIRST_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 114 goto out;
AzureIoTClient 0:1f9b2707ec7d 115 }
AzureIoTClient 0:1f9b2707ec7d 116
AzureIoTClient 0:1f9b2707ec7d 117 for (something = reflectedData->reflectedData; something != NULL; something = something->next)
AzureIoTClient 0:1f9b2707ec7d 118 {
AzureIoTClient 0:1f9b2707ec7d 119 /* looking for all elements that belong to a model: properties and actions */
AzureIoTClient 0:1f9b2707ec7d 120 if ((something->type == REFLECTION_PROPERTY_TYPE) &&
AzureIoTClient 0:1f9b2707ec7d 121 (strcmp(something->what.property.modelName, modelReflectedData->what.model.name) == 0))
AzureIoTClient 0:1f9b2707ec7d 122 {
AzureIoTClient 0:1f9b2707ec7d 123 SCHEMA_MODEL_TYPE_HANDLE childModelHande = Schema_GetModelByName(schemaHandle, something->what.property.type);
AzureIoTClient 0:1f9b2707ec7d 124
AzureIoTClient 0:1f9b2707ec7d 125 /* if this is a model type use the appropriate APIs for it */
AzureIoTClient 0:1f9b2707ec7d 126 if (childModelHande != NULL)
AzureIoTClient 0:1f9b2707ec7d 127 {
AzureIoTClient 0:1f9b2707ec7d 128 if (Schema_AddModelModel(modelTypeHandle, something->what.property.name, childModelHande) != SCHEMA_OK)
AzureIoTClient 0:1f9b2707ec7d 129 {
AzureIoTClient 0:1f9b2707ec7d 130 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 131 result = CODEFIRST_SCHEMA_ERROR;
AzureIoTClient 0:1f9b2707ec7d 132 LogError("add model failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 133 goto out;
AzureIoTClient 0:1f9b2707ec7d 134 }
AzureIoTClient 0:1f9b2707ec7d 135 }
AzureIoTClient 0:1f9b2707ec7d 136 else
AzureIoTClient 0:1f9b2707ec7d 137 {
AzureIoTClient 0:1f9b2707ec7d 138 if (Schema_AddModelProperty(modelTypeHandle, something->what.property.name, something->what.property.type) != SCHEMA_OK)
AzureIoTClient 0:1f9b2707ec7d 139 {
AzureIoTClient 0:1f9b2707ec7d 140 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 141 result = CODEFIRST_SCHEMA_ERROR;
AzureIoTClient 0:1f9b2707ec7d 142 LogError("add property failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 143 goto out;
AzureIoTClient 0:1f9b2707ec7d 144 }
AzureIoTClient 0:1f9b2707ec7d 145 }
AzureIoTClient 0:1f9b2707ec7d 146 }
AzureIoTClient 0:1f9b2707ec7d 147
AzureIoTClient 0:1f9b2707ec7d 148 if ((something->type == REFLECTION_ACTION_TYPE) &&
AzureIoTClient 0:1f9b2707ec7d 149 (strcmp(something->what.action.modelName, modelReflectedData->what.model.name) == 0))
AzureIoTClient 0:1f9b2707ec7d 150 {
AzureIoTClient 0:1f9b2707ec7d 151 SCHEMA_ACTION_HANDLE actionHandle;
AzureIoTClient 0:1f9b2707ec7d 152 size_t i;
AzureIoTClient 0:1f9b2707ec7d 153
AzureIoTClient 0:1f9b2707ec7d 154 if ((actionHandle = Schema_CreateModelAction(modelTypeHandle, something->what.action.name)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 155 {
AzureIoTClient 0:1f9b2707ec7d 156 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 157 result = CODEFIRST_SCHEMA_ERROR;
AzureIoTClient 0:1f9b2707ec7d 158 LogError("add model action failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 159 goto out;
AzureIoTClient 0:1f9b2707ec7d 160 }
AzureIoTClient 0:1f9b2707ec7d 161
AzureIoTClient 0:1f9b2707ec7d 162 for (i = 0; i < something->what.action.nArguments; i++)
AzureIoTClient 0:1f9b2707ec7d 163 {
AzureIoTClient 0:1f9b2707ec7d 164 if (Schema_AddModelActionArgument(actionHandle, something->what.action.arguments[i].name, something->what.action.arguments[i].type) != SCHEMA_OK)
AzureIoTClient 0:1f9b2707ec7d 165 {
AzureIoTClient 0:1f9b2707ec7d 166 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 167 result = CODEFIRST_SCHEMA_ERROR;
AzureIoTClient 0:1f9b2707ec7d 168 LogError("add model action argument failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 169 goto out;
AzureIoTClient 0:1f9b2707ec7d 170 }
AzureIoTClient 0:1f9b2707ec7d 171 }
AzureIoTClient 0:1f9b2707ec7d 172 }
AzureIoTClient 0:1f9b2707ec7d 173 }
AzureIoTClient 0:1f9b2707ec7d 174
AzureIoTClient 0:1f9b2707ec7d 175 out:
AzureIoTClient 0:1f9b2707ec7d 176 return result;
AzureIoTClient 0:1f9b2707ec7d 177 }
AzureIoTClient 0:1f9b2707ec7d 178
AzureIoTClient 0:1f9b2707ec7d 179 static CODEFIRST_RESULT buildModelTypes(SCHEMA_HANDLE schemaHandle, const REFLECTED_DATA_FROM_DATAPROVIDER* reflectedData)
AzureIoTClient 0:1f9b2707ec7d 180 {
AzureIoTClient 0:1f9b2707ec7d 181 CODEFIRST_RESULT result = CODEFIRST_OK;
AzureIoTClient 0:1f9b2707ec7d 182 const REFLECTED_SOMETHING* something;
AzureIoTClient 0:1f9b2707ec7d 183
AzureIoTClient 0:1f9b2707ec7d 184 /* first have a pass and add all the model types */
AzureIoTClient 0:1f9b2707ec7d 185 for (something = reflectedData->reflectedData; something != NULL; something = something->next)
AzureIoTClient 0:1f9b2707ec7d 186 {
AzureIoTClient 0:1f9b2707ec7d 187 if (something->type == REFLECTION_MODEL_TYPE)
AzureIoTClient 0:1f9b2707ec7d 188 {
AzureIoTClient 0:1f9b2707ec7d 189 if (Schema_CreateModelType(schemaHandle, something->what.model.name) == NULL)
AzureIoTClient 0:1f9b2707ec7d 190 {
AzureIoTClient 0:1f9b2707ec7d 191 /*Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CODEFIRST_SCHEMA_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 192 result = CODEFIRST_SCHEMA_ERROR;
AzureIoTClient 0:1f9b2707ec7d 193 LogError("create mdoel failed %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 194 goto out;
AzureIoTClient 0:1f9b2707ec7d 195 }
AzureIoTClient 0:1f9b2707ec7d 196 }
AzureIoTClient 0:1f9b2707ec7d 197 }
AzureIoTClient 0:1f9b2707ec7d 198
AzureIoTClient 0:1f9b2707ec7d 199 for (something = reflectedData->reflectedData; something != NULL; something = something->next)
AzureIoTClient 0:1f9b2707ec7d 200 {
AzureIoTClient 0:1f9b2707ec7d 201 if (something->type == REFLECTION_MODEL_TYPE)
AzureIoTClient 0:1f9b2707ec7d 202 {
AzureIoTClient 0:1f9b2707ec7d 203 result = buildModel(schemaHandle, reflectedData, something);
AzureIoTClient 0:1f9b2707ec7d 204 if (result != CODEFIRST_OK)
AzureIoTClient 0:1f9b2707ec7d 205 {
AzureIoTClient 0:1f9b2707ec7d 206 break;
AzureIoTClient 0:1f9b2707ec7d 207 }
AzureIoTClient 0:1f9b2707ec7d 208 }
AzureIoTClient 0:1f9b2707ec7d 209 }
AzureIoTClient 0:1f9b2707ec7d 210
AzureIoTClient 0:1f9b2707ec7d 211 out:
AzureIoTClient 0:1f9b2707ec7d 212 return result;
AzureIoTClient 0:1f9b2707ec7d 213 }
AzureIoTClient 0:1f9b2707ec7d 214
AzureIoTClient 0:1f9b2707ec7d 215 /*Codes_SRS_CODEFIRST_99_002:[ CodeFirst_Init shall initialize the CodeFirst module. If initialization is successful, it shall return CODEFIRST_OK.]*/
AzureIoTClient 0:1f9b2707ec7d 216 CODEFIRST_RESULT CodeFirst_Init(const char* overrideSchemaNamespace)
AzureIoTClient 0:1f9b2707ec7d 217 {
AzureIoTClient 0:1f9b2707ec7d 218 /*shall build the default EntityContainer*/
AzureIoTClient 0:1f9b2707ec7d 219 CODEFIRST_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 220
AzureIoTClient 0:1f9b2707ec7d 221 if (g_state != CODEFIRST_STATE_NOT_INIT)
AzureIoTClient 0:1f9b2707ec7d 222 {
AzureIoTClient 0:1f9b2707ec7d 223 /*Codes_SRS_CODEFIRST_99_003:[ If the module is already initialized, the initialization shall fail and the return value shall be CODEFIRST_ALREADY_INIT.]*/
AzureIoTClient 0:1f9b2707ec7d 224 result = CODEFIRST_ALREADY_INIT;
AzureIoTClient 0:1f9b2707ec7d 225 LogError("CodeFirst was already init %s", ENUM_TO_STRING(CODEFIRST_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 226 }
AzureIoTClient 0:1f9b2707ec7d 227 else
AzureIoTClient 0:1f9b2707ec7d 228 {
AzureIoTClient 0:1f9b2707ec7d 229 g_DeviceCount = 0;
AzureIoTClient 0:1f9b2707ec7d 230 g_OverrideSchemaNamespace = overrideSchemaNamespace;
AzureIoTClient 0:1f9b2707ec7d 231 g_Devices = NULL;
AzureIoTClient 0:1f9b2707ec7d 232
AzureIoTClient 0:1f9b2707ec7d 233 /*Codes_SRS_CODEFIRST_99_002:[ CodeFirst_Init shall initialize the CodeFirst module. If initialization is successful, it shall return CODEFIRST_OK.]*/
AzureIoTClient 0:1f9b2707ec7d 234 g_state = CODEFIRST_STATE_INIT;
AzureIoTClient 0:1f9b2707ec7d 235 result = CODEFIRST_OK;
AzureIoTClient 0:1f9b2707ec7d 236 }
AzureIoTClient 0:1f9b2707ec7d 237
AzureIoTClient 0:1f9b2707ec7d 238 return result;
AzureIoTClient 0:1f9b2707ec7d 239 }
AzureIoTClient 0:1f9b2707ec7d 240
AzureIoTClient 0:1f9b2707ec7d 241 void CodeFirst_Deinit(void)
AzureIoTClient 0:1f9b2707ec7d 242 {
AzureIoTClient 0:1f9b2707ec7d 243 /*Codes_SRS_CODEFIRST_99_006:[If the module is not previously initialed, CodeFirst_Deinit shall do nothing.]*/
AzureIoTClient 0:1f9b2707ec7d 244 if (g_state != CODEFIRST_STATE_INIT)
AzureIoTClient 0:1f9b2707ec7d 245 {
AzureIoTClient 0:1f9b2707ec7d 246 LogError("CodeFirst_Deinit called when CodeFirst was not INIT\r\n");
AzureIoTClient 0:1f9b2707ec7d 247 }
AzureIoTClient 0:1f9b2707ec7d 248 else
AzureIoTClient 0:1f9b2707ec7d 249 {
AzureIoTClient 0:1f9b2707ec7d 250 size_t i;
AzureIoTClient 0:1f9b2707ec7d 251
AzureIoTClient 0:1f9b2707ec7d 252 /*Codes_SRS_CODEFIRST_99_005:[ CodeFirst_Deinit shall deinitialize the module, freeing all the resources and placing the module in an uninitialized state.]*/
AzureIoTClient 0:1f9b2707ec7d 253 for (i = 0; i < g_DeviceCount; i++)
AzureIoTClient 0:1f9b2707ec7d 254 {
AzureIoTClient 0:1f9b2707ec7d 255 DestroyDevice(g_Devices[i]);
AzureIoTClient 0:1f9b2707ec7d 256 }
AzureIoTClient 0:1f9b2707ec7d 257
AzureIoTClient 0:1f9b2707ec7d 258 free(g_Devices);
AzureIoTClient 0:1f9b2707ec7d 259 g_Devices = NULL;
AzureIoTClient 0:1f9b2707ec7d 260 g_DeviceCount = 0;
AzureIoTClient 0:1f9b2707ec7d 261
AzureIoTClient 0:1f9b2707ec7d 262 g_state = CODEFIRST_STATE_NOT_INIT;
AzureIoTClient 0:1f9b2707ec7d 263 }
AzureIoTClient 0:1f9b2707ec7d 264 }
AzureIoTClient 0:1f9b2707ec7d 265
AzureIoTClient 0:1f9b2707ec7d 266 static const REFLECTED_SOMETHING* FindModelInCodeFirstMetadata(const REFLECTED_SOMETHING* reflectedData, const char* modelName)
AzureIoTClient 0:1f9b2707ec7d 267 {
AzureIoTClient 0:1f9b2707ec7d 268 const REFLECTED_SOMETHING* result;
AzureIoTClient 0:1f9b2707ec7d 269
AzureIoTClient 0:1f9b2707ec7d 270 for (result = reflectedData; result != NULL; result = result->next)
AzureIoTClient 0:1f9b2707ec7d 271 {
AzureIoTClient 0:1f9b2707ec7d 272 if ((result->type == REFLECTION_MODEL_TYPE) &&
AzureIoTClient 0:1f9b2707ec7d 273 (strcmp(result->what.model.name, modelName) == 0))
AzureIoTClient 0:1f9b2707ec7d 274 {
AzureIoTClient 0:1f9b2707ec7d 275 /* found model type */
AzureIoTClient 0:1f9b2707ec7d 276 break;
AzureIoTClient 0:1f9b2707ec7d 277 }
AzureIoTClient 0:1f9b2707ec7d 278 }
AzureIoTClient 0:1f9b2707ec7d 279
AzureIoTClient 0:1f9b2707ec7d 280 return result;
AzureIoTClient 0:1f9b2707ec7d 281 }
AzureIoTClient 0:1f9b2707ec7d 282
AzureIoTClient 0:1f9b2707ec7d 283 static const REFLECTED_SOMETHING* FindChildModelInCodeFirstMetadata(const REFLECTED_SOMETHING* reflectedData, const REFLECTED_SOMETHING* startModel, const char* relativePath, size_t* offset)
AzureIoTClient 0:1f9b2707ec7d 284 {
AzureIoTClient 0:1f9b2707ec7d 285 const REFLECTED_SOMETHING* result = startModel;
AzureIoTClient 0:1f9b2707ec7d 286 *offset = 0;
AzureIoTClient 0:1f9b2707ec7d 287
AzureIoTClient 0:1f9b2707ec7d 288 /* Codes_SRS_CODEFIRST_99_139:[If the relativeActionPath is empty then the action shall be looked up in the device model.] */
AzureIoTClient 0:1f9b2707ec7d 289 while ((*relativePath != 0) && (result != NULL))
AzureIoTClient 0:1f9b2707ec7d 290 {
AzureIoTClient 0:1f9b2707ec7d 291 /* Codes_SRS_CODEFIRST_99_142:[The relativeActionPath argument shall be in the format "childModel1/childModel2/.../childModelN".] */
AzureIoTClient 0:1f9b2707ec7d 292 const REFLECTED_SOMETHING* childModelProperty;
AzureIoTClient 0:1f9b2707ec7d 293 size_t propertyNameLength;
AzureIoTClient 0:1f9b2707ec7d 294 const char* slashPos = strchr(relativePath, '/');
AzureIoTClient 0:1f9b2707ec7d 295 if (slashPos == NULL)
AzureIoTClient 0:1f9b2707ec7d 296 {
AzureIoTClient 0:1f9b2707ec7d 297 slashPos = &relativePath[strlen(relativePath)];
AzureIoTClient 0:1f9b2707ec7d 298 }
AzureIoTClient 0:1f9b2707ec7d 299
AzureIoTClient 0:1f9b2707ec7d 300 propertyNameLength = slashPos - relativePath;
AzureIoTClient 0:1f9b2707ec7d 301
AzureIoTClient 0:1f9b2707ec7d 302 for (childModelProperty = reflectedData; childModelProperty != NULL; childModelProperty = childModelProperty->next)
AzureIoTClient 0:1f9b2707ec7d 303 {
AzureIoTClient 0:1f9b2707ec7d 304 if ((childModelProperty->type == REFLECTION_PROPERTY_TYPE) &&
AzureIoTClient 0:1f9b2707ec7d 305 (strcmp(childModelProperty->what.property.modelName, result->what.model.name) == 0) &&
AzureIoTClient 0:1f9b2707ec7d 306 (strncmp(childModelProperty->what.property.name, relativePath, propertyNameLength) == 0) &&
AzureIoTClient 0:1f9b2707ec7d 307 (strlen(childModelProperty->what.property.name) == propertyNameLength))
AzureIoTClient 0:1f9b2707ec7d 308 {
AzureIoTClient 0:1f9b2707ec7d 309 /* property found, now let's find the model */
AzureIoTClient 0:1f9b2707ec7d 310 /* Codes_SRS_CODEFIRST_99_140:[CodeFirst_InvokeAction shall pass to the action wrapper that it calls a pointer to the model where the action is defined.] */
AzureIoTClient 0:1f9b2707ec7d 311 *offset += childModelProperty->what.property.offset;
AzureIoTClient 0:1f9b2707ec7d 312 break;
AzureIoTClient 0:1f9b2707ec7d 313 }
AzureIoTClient 0:1f9b2707ec7d 314 }
AzureIoTClient 0:1f9b2707ec7d 315
AzureIoTClient 0:1f9b2707ec7d 316 if (childModelProperty == NULL)
AzureIoTClient 0:1f9b2707ec7d 317 {
AzureIoTClient 0:1f9b2707ec7d 318 /* not found */
AzureIoTClient 0:1f9b2707ec7d 319 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 320 }
AzureIoTClient 0:1f9b2707ec7d 321 else
AzureIoTClient 0:1f9b2707ec7d 322 {
AzureIoTClient 0:1f9b2707ec7d 323 result = FindModelInCodeFirstMetadata(reflectedData, childModelProperty->what.property.type);
AzureIoTClient 0:1f9b2707ec7d 324 }
AzureIoTClient 0:1f9b2707ec7d 325
AzureIoTClient 0:1f9b2707ec7d 326 relativePath = slashPos;
AzureIoTClient 0:1f9b2707ec7d 327 }
AzureIoTClient 0:1f9b2707ec7d 328
AzureIoTClient 0:1f9b2707ec7d 329 return result;
AzureIoTClient 0:1f9b2707ec7d 330 }
AzureIoTClient 0:1f9b2707ec7d 331
AzureIoTClient 0:1f9b2707ec7d 332 EXECUTE_COMMAND_RESULT CodeFirst_InvokeAction(void* deviceHandle, void* callbackUserContext, const char* relativeActionPath, const char* actionName, size_t parameterCount, const AGENT_DATA_TYPE* parameterValues)
AzureIoTClient 0:1f9b2707ec7d 333 {
AzureIoTClient 0:1f9b2707ec7d 334 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 335 DEVICE_HEADER_DATA* deviceHeader = (DEVICE_HEADER_DATA*)callbackUserContext;
AzureIoTClient 0:1f9b2707ec7d 336
AzureIoTClient 0:1f9b2707ec7d 337 /*Codes_SRS_CODEFIRST_99_068:[ If the function is called before CodeFirst is initialized then EXECUTE_COMMAND_ERROR shall be returned.] */
AzureIoTClient 0:1f9b2707ec7d 338 if (g_state != CODEFIRST_STATE_INIT)
AzureIoTClient 0:1f9b2707ec7d 339 {
AzureIoTClient 0:1f9b2707ec7d 340 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 341 LogError("CodeFirst_InvokeAction called before init has an error %s \r\n", ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 342 }
AzureIoTClient 0:1f9b2707ec7d 343 /*Codes_SRS_CODEFIRST_99_066:[ If actionName, relativeActionPath or deviceHandle is NULL then EXECUTE_COMMAND_ERROR shall be returned*/
AzureIoTClient 0:1f9b2707ec7d 344 else if ((actionName == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 345 (deviceHandle == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 346 (relativeActionPath == NULL))
AzureIoTClient 0:1f9b2707ec7d 347 {
AzureIoTClient 0:1f9b2707ec7d 348 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 349 LogError("action Name is NULL %s \r\n", ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 350 }
AzureIoTClient 0:1f9b2707ec7d 351 /*Codes_SRS_CODEFIRST_99_067:[ If parameterCount is greater than zero and parameterValues is NULL then EXECUTE_COMMAND_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 352 else if ((parameterCount > 0) && (parameterValues == NULL))
AzureIoTClient 0:1f9b2707ec7d 353 {
AzureIoTClient 0:1f9b2707ec7d 354 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 355 LogError("parameterValues error %s \r\n", ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 356 }
AzureIoTClient 0:1f9b2707ec7d 357 else
AzureIoTClient 0:1f9b2707ec7d 358 {
AzureIoTClient 0:1f9b2707ec7d 359 const REFLECTED_SOMETHING* something;
AzureIoTClient 0:1f9b2707ec7d 360 const REFLECTED_SOMETHING* childModel;
AzureIoTClient 0:1f9b2707ec7d 361 const char* modelName;
AzureIoTClient 0:1f9b2707ec7d 362 size_t offset;
AzureIoTClient 0:1f9b2707ec7d 363
AzureIoTClient 0:1f9b2707ec7d 364 modelName = Schema_GetModelName(deviceHeader->ModelHandle);
AzureIoTClient 0:1f9b2707ec7d 365
AzureIoTClient 0:1f9b2707ec7d 366 if (((childModel = FindModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, modelName)) == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 367 /* Codes_SRS_CODEFIRST_99_138:[The relativeActionPath argument shall be used by CodeFirst_InvokeAction to find the child model where the action is declared.] */
AzureIoTClient 0:1f9b2707ec7d 368 ((childModel = FindChildModelInCodeFirstMetadata(deviceHeader->ReflectedData->reflectedData, childModel, relativeActionPath, &offset)) == NULL))
AzureIoTClient 0:1f9b2707ec7d 369 {
AzureIoTClient 0:1f9b2707ec7d 370 /*Codes_SRS_CODEFIRST_99_141:[If a child model specified in the relativeActionPath argument cannot be found by CodeFirst_InvokeAction, it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 0:1f9b2707ec7d 371 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 372 LogError("action %s was not found %s \r\n", actionName, ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 373 }
AzureIoTClient 0:1f9b2707ec7d 374 else
AzureIoTClient 0:1f9b2707ec7d 375 {
AzureIoTClient 0:1f9b2707ec7d 376 /* Codes_SRS_CODEFIRST_99_062:[ When CodeFirst_InvokeAction is called it shall look through the codefirst metadata associated with a specific device for a previously declared action (function) named actionName.]*/
AzureIoTClient 0:1f9b2707ec7d 377 /* Codes_SRS_CODEFIRST_99_078:[If such a function is not found then the function shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 0:1f9b2707ec7d 378 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 379 for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
AzureIoTClient 0:1f9b2707ec7d 380 {
AzureIoTClient 0:1f9b2707ec7d 381 if ((something->type == REFLECTION_ACTION_TYPE) &&
AzureIoTClient 0:1f9b2707ec7d 382 (strcmp(actionName, something->what.action.name) == 0) &&
AzureIoTClient 0:1f9b2707ec7d 383 (strcmp(childModel->what.model.name, something->what.action.modelName) == 0))
AzureIoTClient 0:1f9b2707ec7d 384 {
AzureIoTClient 0:1f9b2707ec7d 385 /*Codes_SRS_CODEFIRST_99_063:[ If the function is found, then CodeFirst shall call the wrapper of the found function inside the data provider. The wrapper is linked in the reflected data to the function name. The wrapper shall be called with the same arguments as CodeFirst_InvokeAction has been called.]*/
AzureIoTClient 0:1f9b2707ec7d 386 /*Codes_SRS_CODEFIRST_99_064:[ If the wrapper call succeeds then CODEFIRST_OK shall be returned. ]*/
AzureIoTClient 0:1f9b2707ec7d 387 /*Codes_SRS_CODEFIRST_99_065:[ For all the other return values CODEFIRST_ACTION_EXECUTION_ERROR shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 388 /* Codes_SRS_CODEFIRST_99_140:[CodeFirst_InvokeAction shall pass to the action wrapper that it calls a pointer to the model where the action is defined.] */
AzureIoTClient 0:1f9b2707ec7d 389 /*Codes_SRS_CODEFIRST_02_013: [The wrapper's return value shall be returned.]*/
AzureIoTClient 0:1f9b2707ec7d 390 result = something->what.action.wrapper(deviceHeader->data + offset, parameterCount, parameterValues);
AzureIoTClient 0:1f9b2707ec7d 391 break;
AzureIoTClient 0:1f9b2707ec7d 392 }
AzureIoTClient 0:1f9b2707ec7d 393 }
AzureIoTClient 0:1f9b2707ec7d 394 }
AzureIoTClient 0:1f9b2707ec7d 395 }
AzureIoTClient 0:1f9b2707ec7d 396
AzureIoTClient 0:1f9b2707ec7d 397 if (result == EXECUTE_COMMAND_ERROR)
AzureIoTClient 0:1f9b2707ec7d 398 {
AzureIoTClient 0:1f9b2707ec7d 399 LogError(" %s \r\n", ENUM_TO_STRING(EXECUTE_COMMAND_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 400 }
AzureIoTClient 0:1f9b2707ec7d 401 return result;
AzureIoTClient 0:1f9b2707ec7d 402 }
AzureIoTClient 0:1f9b2707ec7d 403
AzureIoTClient 0:1f9b2707ec7d 404 /* Codes_SRS_CODEFIRST_99_002:[ CodeFirst_RegisterSchema shall create the schema information and give it to the Schema module for one schema, identified by the metadata argument. On success, it shall return a handle to the schema.] */
AzureIoTClient 0:1f9b2707ec7d 405 SCHEMA_HANDLE CodeFirst_RegisterSchema(const char* schemaNamespace, const REFLECTED_DATA_FROM_DATAPROVIDER* metadata)
AzureIoTClient 0:1f9b2707ec7d 406 {
AzureIoTClient 0:1f9b2707ec7d 407 SCHEMA_HANDLE result;
AzureIoTClient 0:1f9b2707ec7d 408
AzureIoTClient 0:1f9b2707ec7d 409 if (g_OverrideSchemaNamespace != NULL)
AzureIoTClient 0:1f9b2707ec7d 410 {
AzureIoTClient 0:1f9b2707ec7d 411 schemaNamespace = g_OverrideSchemaNamespace;
AzureIoTClient 0:1f9b2707ec7d 412 }
AzureIoTClient 0:1f9b2707ec7d 413
AzureIoTClient 0:1f9b2707ec7d 414 /* Codes_SRS_CODEFIRST_99_121:[If the schema has already been registered, CodeFirst_RegisterSchema shall return its handle.] */
AzureIoTClient 0:1f9b2707ec7d 415 result = Schema_GetSchemaByNamespace(schemaNamespace);
AzureIoTClient 0:1f9b2707ec7d 416 if (result == NULL)
AzureIoTClient 0:1f9b2707ec7d 417 {
AzureIoTClient 0:1f9b2707ec7d 418 if ((result = Schema_Create(schemaNamespace)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 419 {
AzureIoTClient 0:1f9b2707ec7d 420 /* Codes_SRS_CODEFIRST_99_076:[If any Schema APIs fail, CodeFirst_RegisterSchema shall return NULL.] */
AzureIoTClient 0:1f9b2707ec7d 421 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 422 LogError("schema init failed %s\r\n", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_SCHEMA_ERROR));
AzureIoTClient 0:1f9b2707ec7d 423 }
AzureIoTClient 0:1f9b2707ec7d 424 else
AzureIoTClient 0:1f9b2707ec7d 425 {
AzureIoTClient 0:1f9b2707ec7d 426 if ((buildStructTypes(result, metadata) != CODEFIRST_OK) ||
AzureIoTClient 0:1f9b2707ec7d 427 (buildModelTypes(result, metadata) != CODEFIRST_OK))
AzureIoTClient 0:1f9b2707ec7d 428 {
AzureIoTClient 0:1f9b2707ec7d 429 Schema_Destroy(result);
AzureIoTClient 0:1f9b2707ec7d 430 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 431 }
AzureIoTClient 0:1f9b2707ec7d 432 else
AzureIoTClient 0:1f9b2707ec7d 433 {
AzureIoTClient 0:1f9b2707ec7d 434 /* do nothing, everything is OK */
AzureIoTClient 0:1f9b2707ec7d 435 }
AzureIoTClient 0:1f9b2707ec7d 436 }
AzureIoTClient 0:1f9b2707ec7d 437 }
AzureIoTClient 0:1f9b2707ec7d 438
AzureIoTClient 0:1f9b2707ec7d 439 return result;
AzureIoTClient 0:1f9b2707ec7d 440 }
AzureIoTClient 0:1f9b2707ec7d 441
AzureIoTClient 0:1f9b2707ec7d 442 AGENT_DATA_TYPE_TYPE CodeFirst_GetPrimitiveType(const char* typeName)
AzureIoTClient 0:1f9b2707ec7d 443 {
AzureIoTClient 6:36cc37b1dbc9 444 #ifdef USE_FLOATS
AzureIoTClient 0:1f9b2707ec7d 445 if (strcmp(typeName, "double") == 0)
AzureIoTClient 0:1f9b2707ec7d 446 {
AzureIoTClient 0:1f9b2707ec7d 447 return EDM_DOUBLE_TYPE;
AzureIoTClient 0:1f9b2707ec7d 448 }
AzureIoTClient 0:1f9b2707ec7d 449 else if (strcmp(typeName, "float") == 0)
AzureIoTClient 0:1f9b2707ec7d 450 {
AzureIoTClient 0:1f9b2707ec7d 451 return EDM_SINGLE_TYPE;
AzureIoTClient 0:1f9b2707ec7d 452 }
AzureIoTClient 6:36cc37b1dbc9 453 else
AzureIoTClient 6:36cc37b1dbc9 454 #endif
AzureIoTClient 6:36cc37b1dbc9 455 if (strcmp(typeName, "int") == 0)
AzureIoTClient 0:1f9b2707ec7d 456 {
AzureIoTClient 0:1f9b2707ec7d 457 return EDM_INT32_TYPE;
AzureIoTClient 0:1f9b2707ec7d 458 }
AzureIoTClient 0:1f9b2707ec7d 459 else if (strcmp(typeName, "long") == 0)
AzureIoTClient 0:1f9b2707ec7d 460 {
AzureIoTClient 0:1f9b2707ec7d 461 return EDM_INT64_TYPE;
AzureIoTClient 0:1f9b2707ec7d 462 }
AzureIoTClient 0:1f9b2707ec7d 463 else if (strcmp(typeName, "int8_t") == 0)
AzureIoTClient 0:1f9b2707ec7d 464 {
AzureIoTClient 0:1f9b2707ec7d 465 return EDM_SBYTE_TYPE;
AzureIoTClient 0:1f9b2707ec7d 466 }
AzureIoTClient 0:1f9b2707ec7d 467 else if (strcmp(typeName, "uint8_t") == 0)
AzureIoTClient 0:1f9b2707ec7d 468 {
AzureIoTClient 0:1f9b2707ec7d 469 return EDM_BYTE_TYPE;
AzureIoTClient 0:1f9b2707ec7d 470 }
AzureIoTClient 0:1f9b2707ec7d 471 else if (strcmp(typeName, "int16_t") == 0)
AzureIoTClient 0:1f9b2707ec7d 472 {
AzureIoTClient 0:1f9b2707ec7d 473 return EDM_INT16_TYPE;
AzureIoTClient 0:1f9b2707ec7d 474 }
AzureIoTClient 0:1f9b2707ec7d 475 else if (strcmp(typeName, "int32_t") == 0)
AzureIoTClient 0:1f9b2707ec7d 476 {
AzureIoTClient 0:1f9b2707ec7d 477 return EDM_INT32_TYPE;
AzureIoTClient 0:1f9b2707ec7d 478 }
AzureIoTClient 0:1f9b2707ec7d 479 else if (strcmp(typeName, "int64_t") == 0)
AzureIoTClient 0:1f9b2707ec7d 480 {
AzureIoTClient 0:1f9b2707ec7d 481 return EDM_INT64_TYPE;
AzureIoTClient 0:1f9b2707ec7d 482 }
AzureIoTClient 0:1f9b2707ec7d 483 else if (
AzureIoTClient 0:1f9b2707ec7d 484 (strcmp(typeName, "_Bool") == 0) ||
AzureIoTClient 0:1f9b2707ec7d 485 (strcmp(typeName, "bool") == 0)
AzureIoTClient 0:1f9b2707ec7d 486 )
AzureIoTClient 0:1f9b2707ec7d 487 {
AzureIoTClient 0:1f9b2707ec7d 488 return EDM_BOOLEAN_TYPE;
AzureIoTClient 0:1f9b2707ec7d 489 }
AzureIoTClient 0:1f9b2707ec7d 490 else if (strcmp(typeName, "ascii_char_ptr") == 0)
AzureIoTClient 0:1f9b2707ec7d 491 {
AzureIoTClient 0:1f9b2707ec7d 492 return EDM_STRING_TYPE;
AzureIoTClient 0:1f9b2707ec7d 493 }
AzureIoTClient 0:1f9b2707ec7d 494 else if (strcmp(typeName, "ascii_char_ptr_no_quotes") == 0)
AzureIoTClient 0:1f9b2707ec7d 495 {
AzureIoTClient 0:1f9b2707ec7d 496 return EDM_STRING_NO_QUOTES_TYPE;
AzureIoTClient 0:1f9b2707ec7d 497 }
AzureIoTClient 0:1f9b2707ec7d 498 else if (strcmp(typeName, "EDM_DATE_TIME_OFFSET") == 0)
AzureIoTClient 0:1f9b2707ec7d 499 {
AzureIoTClient 0:1f9b2707ec7d 500 return EDM_DATE_TIME_OFFSET_TYPE;
AzureIoTClient 0:1f9b2707ec7d 501 }
AzureIoTClient 0:1f9b2707ec7d 502 else if (strcmp(typeName, "EDM_GUID") == 0)
AzureIoTClient 0:1f9b2707ec7d 503 {
AzureIoTClient 0:1f9b2707ec7d 504 return EDM_GUID_TYPE;
AzureIoTClient 0:1f9b2707ec7d 505 }
AzureIoTClient 0:1f9b2707ec7d 506 else if (strcmp(typeName, "EDM_BINARY") == 0)
AzureIoTClient 0:1f9b2707ec7d 507 {
AzureIoTClient 0:1f9b2707ec7d 508 return EDM_BINARY_TYPE;
AzureIoTClient 0:1f9b2707ec7d 509 }
AzureIoTClient 0:1f9b2707ec7d 510 else
AzureIoTClient 0:1f9b2707ec7d 511 {
AzureIoTClient 0:1f9b2707ec7d 512 return EDM_NO_TYPE;
AzureIoTClient 0:1f9b2707ec7d 513 }
AzureIoTClient 0:1f9b2707ec7d 514 }
AzureIoTClient 0:1f9b2707ec7d 515
AzureIoTClient 0:1f9b2707ec7d 516 /* Codes_SRS_CODEFIRST_99_079:[CodeFirst_CreateDevice shall create a device and allocate a memory block that should hold the device data.] */
AzureIoTClient 0:1f9b2707ec7d 517 void* CodeFirst_CreateDevice(SCHEMA_MODEL_TYPE_HANDLE model, const REFLECTED_DATA_FROM_DATAPROVIDER* metadata, size_t dataSize, bool includePropertyPath)
AzureIoTClient 0:1f9b2707ec7d 518 {
AzureIoTClient 0:1f9b2707ec7d 519 void* result;
AzureIoTClient 0:1f9b2707ec7d 520 DEVICE_HEADER_DATA* deviceHeader;
AzureIoTClient 0:1f9b2707ec7d 521
AzureIoTClient 0:1f9b2707ec7d 522 /* Codes_SRS_CODEFIRST_99_080:[If CodeFirst_CreateDevice is invoked with a NULL model, it shall return NULL.]*/
AzureIoTClient 0:1f9b2707ec7d 523 if (
AzureIoTClient 0:1f9b2707ec7d 524 (model == NULL))
AzureIoTClient 0:1f9b2707ec7d 525 {
AzureIoTClient 0:1f9b2707ec7d 526 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 527 LogError(" %s \r\n", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_INVALID_ARG));
AzureIoTClient 0:1f9b2707ec7d 528 }
AzureIoTClient 0:1f9b2707ec7d 529 /* Codes_SRS_CODEFIRST_99_106:[If CodeFirst_CreateDevice is called when the modules is not initialized is shall return NULL.] */
AzureIoTClient 0:1f9b2707ec7d 530 else if (g_state != CODEFIRST_STATE_INIT)
AzureIoTClient 0:1f9b2707ec7d 531 {
AzureIoTClient 0:1f9b2707ec7d 532 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 533 LogError(" %s \r\n", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_NOT_INIT));
AzureIoTClient 0:1f9b2707ec7d 534 }
AzureIoTClient 0:1f9b2707ec7d 535 else if ((deviceHeader = (DEVICE_HEADER_DATA*)malloc(sizeof(DEVICE_HEADER_DATA))) == NULL)
AzureIoTClient 0:1f9b2707ec7d 536 {
AzureIoTClient 0:1f9b2707ec7d 537 /* Codes_SRS_CODEFIRST_99_102:[On any other errors, Device_Create shall return NULL.] */
AzureIoTClient 0:1f9b2707ec7d 538 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 539 LogError(" %s \r\n", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_ERROR));
AzureIoTClient 0:1f9b2707ec7d 540 }
AzureIoTClient 0:1f9b2707ec7d 541 /* Codes_SRS_CODEFIRST_99_081:[CodeFirst_CreateDevice shall use Device_Create to create a device handle.] */
AzureIoTClient 0:1f9b2707ec7d 542 /* Codes_SRS_CODEFIRST_99_082:[CodeFirst_CreateDevice shall pass to Device_Create the function CodeFirst_InvokeAction as action callback argument.] */
AzureIoTClient 0:1f9b2707ec7d 543 else
AzureIoTClient 0:1f9b2707ec7d 544 {
AzureIoTClient 0:1f9b2707ec7d 545 if ((deviceHeader->data = malloc(dataSize))==NULL)
AzureIoTClient 0:1f9b2707ec7d 546 {
AzureIoTClient 0:1f9b2707ec7d 547 free(deviceHeader);
AzureIoTClient 0:1f9b2707ec7d 548 deviceHeader = NULL;
AzureIoTClient 0:1f9b2707ec7d 549 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 550 LogError(" %s \r\n", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_ERROR));
AzureIoTClient 0:1f9b2707ec7d 551 }
AzureIoTClient 0:1f9b2707ec7d 552 else
AzureIoTClient 0:1f9b2707ec7d 553 {
AzureIoTClient 0:1f9b2707ec7d 554 DEVICE_HEADER_DATA** newDevices;
AzureIoTClient 0:1f9b2707ec7d 555
AzureIoTClient 0:1f9b2707ec7d 556 if (Device_Create(model, CodeFirst_InvokeAction, deviceHeader,
AzureIoTClient 0:1f9b2707ec7d 557 includePropertyPath, &deviceHeader->DeviceHandle) != DEVICE_OK)
AzureIoTClient 0:1f9b2707ec7d 558 {
AzureIoTClient 0:1f9b2707ec7d 559 free(deviceHeader->data);
AzureIoTClient 0:1f9b2707ec7d 560 free(deviceHeader);
AzureIoTClient 0:1f9b2707ec7d 561
AzureIoTClient 0:1f9b2707ec7d 562 /* Codes_SRS_CODEFIRST_99_084:[If Device_Create fails, CodeFirst_CreateDevice shall return NULL.] */
AzureIoTClient 0:1f9b2707ec7d 563 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 564 LogError(" %s \r\n", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_DEVICE_FAILED));
AzureIoTClient 0:1f9b2707ec7d 565 }
AzureIoTClient 0:1f9b2707ec7d 566 else if ((newDevices = (DEVICE_HEADER_DATA**)realloc(g_Devices, sizeof(DEVICE_HEADER_DATA*) * (g_DeviceCount + 1))) == NULL)
AzureIoTClient 0:1f9b2707ec7d 567 {
AzureIoTClient 0:1f9b2707ec7d 568 Device_Destroy(deviceHeader->DeviceHandle);
AzureIoTClient 0:1f9b2707ec7d 569 free(deviceHeader->data);
AzureIoTClient 0:1f9b2707ec7d 570 free(deviceHeader);
AzureIoTClient 0:1f9b2707ec7d 571
AzureIoTClient 0:1f9b2707ec7d 572 /* Codes_SRS_CODEFIRST_99_102:[On any other errors, Device_Create shall return NULL.] */
AzureIoTClient 0:1f9b2707ec7d 573 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 574 LogError(" %s \r\n", ENUM_TO_STRING(CODEFIRST_RESULT, CODEFIRST_ERROR));
AzureIoTClient 0:1f9b2707ec7d 575 }
AzureIoTClient 0:1f9b2707ec7d 576 else
AzureIoTClient 0:1f9b2707ec7d 577 {
AzureIoTClient 0:1f9b2707ec7d 578 SCHEMA_RESULT schemaResult;
AzureIoTClient 0:1f9b2707ec7d 579 deviceHeader->ReflectedData = metadata;
AzureIoTClient 0:1f9b2707ec7d 580 deviceHeader->DataSize = dataSize;
AzureIoTClient 0:1f9b2707ec7d 581 deviceHeader->ModelHandle = model;
AzureIoTClient 0:1f9b2707ec7d 582 schemaResult = Schema_AddDeviceRef(model);
AzureIoTClient 0:1f9b2707ec7d 583 if (schemaResult != SCHEMA_OK)
AzureIoTClient 0:1f9b2707ec7d 584 {
AzureIoTClient 0:1f9b2707ec7d 585 Device_Destroy(deviceHeader->DeviceHandle);
AzureIoTClient 0:1f9b2707ec7d 586 free(deviceHeader->data);
AzureIoTClient 0:1f9b2707ec7d 587 free(deviceHeader);
AzureIoTClient 0:1f9b2707ec7d 588
AzureIoTClient 0:1f9b2707ec7d 589 /* Codes_SRS_CODEFIRST_99_102:[On any other errors, Device_Create shall return NULL.] */
AzureIoTClient 0:1f9b2707ec7d 590 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 591 }
AzureIoTClient 0:1f9b2707ec7d 592 else
AzureIoTClient 0:1f9b2707ec7d 593 {
AzureIoTClient 0:1f9b2707ec7d 594 g_Devices = newDevices;
AzureIoTClient 0:1f9b2707ec7d 595 g_Devices[g_DeviceCount] = deviceHeader;
AzureIoTClient 0:1f9b2707ec7d 596 g_DeviceCount++;
AzureIoTClient 0:1f9b2707ec7d 597
AzureIoTClient 0:1f9b2707ec7d 598 /* Codes_SRS_CODEFIRST_99_101:[On success, CodeFirst_CreateDevice shall return a non NULL pointer to the device data.] */
AzureIoTClient 0:1f9b2707ec7d 599 result = deviceHeader->data;
AzureIoTClient 0:1f9b2707ec7d 600 }
AzureIoTClient 0:1f9b2707ec7d 601 }
AzureIoTClient 0:1f9b2707ec7d 602 }
AzureIoTClient 0:1f9b2707ec7d 603 }
AzureIoTClient 0:1f9b2707ec7d 604
AzureIoTClient 0:1f9b2707ec7d 605 return result;
AzureIoTClient 0:1f9b2707ec7d 606 }
AzureIoTClient 0:1f9b2707ec7d 607
AzureIoTClient 0:1f9b2707ec7d 608 void CodeFirst_DestroyDevice(void* device)
AzureIoTClient 0:1f9b2707ec7d 609 {
AzureIoTClient 0:1f9b2707ec7d 610 /* Codes_SRS_CODEFIRST_99_086:[If the argument is NULL, CodeFirst_DestroyDevice shall do nothing.] */
AzureIoTClient 0:1f9b2707ec7d 611 if (device != NULL)
AzureIoTClient 0:1f9b2707ec7d 612 {
AzureIoTClient 0:1f9b2707ec7d 613 size_t i;
AzureIoTClient 0:1f9b2707ec7d 614
AzureIoTClient 0:1f9b2707ec7d 615 for (i = 0; i < g_DeviceCount; i++)
AzureIoTClient 0:1f9b2707ec7d 616 {
AzureIoTClient 0:1f9b2707ec7d 617 if (g_Devices[i]->data == device)
AzureIoTClient 0:1f9b2707ec7d 618 {
AzureIoTClient 0:1f9b2707ec7d 619 Schema_ReleaseDeviceRef(g_Devices[i]->ModelHandle);
AzureIoTClient 0:1f9b2707ec7d 620
AzureIoTClient 0:1f9b2707ec7d 621 // Delete the Created Schema if all the devices are unassociated
AzureIoTClient 0:1f9b2707ec7d 622 Schema_DestroyIfUnused(g_Devices[i]->ModelHandle);
AzureIoTClient 0:1f9b2707ec7d 623
AzureIoTClient 0:1f9b2707ec7d 624 DestroyDevice(g_Devices[i]);
AzureIoTClient 0:1f9b2707ec7d 625 memcpy(&g_Devices[i], &g_Devices[i + 1], (g_DeviceCount - i - 1) * sizeof(DEVICE_HEADER_DATA*));
AzureIoTClient 0:1f9b2707ec7d 626 g_DeviceCount--;
AzureIoTClient 0:1f9b2707ec7d 627 break;
AzureIoTClient 0:1f9b2707ec7d 628 }
AzureIoTClient 0:1f9b2707ec7d 629 }
AzureIoTClient 0:1f9b2707ec7d 630 }
AzureIoTClient 0:1f9b2707ec7d 631 }
AzureIoTClient 0:1f9b2707ec7d 632
AzureIoTClient 0:1f9b2707ec7d 633 static DEVICE_HEADER_DATA* FindDevice(void* value)
AzureIoTClient 0:1f9b2707ec7d 634 {
AzureIoTClient 0:1f9b2707ec7d 635 size_t i;
AzureIoTClient 0:1f9b2707ec7d 636 DEVICE_HEADER_DATA* result = NULL;
AzureIoTClient 0:1f9b2707ec7d 637
AzureIoTClient 0:1f9b2707ec7d 638 for (i = 0; i < g_DeviceCount; i++)
AzureIoTClient 0:1f9b2707ec7d 639 {
AzureIoTClient 0:1f9b2707ec7d 640 if ((g_Devices[i]->data <= (unsigned char*)value) &&
AzureIoTClient 0:1f9b2707ec7d 641 (g_Devices[i]->data + g_Devices[i]->DataSize > (unsigned char*)value))
AzureIoTClient 0:1f9b2707ec7d 642 {
AzureIoTClient 0:1f9b2707ec7d 643 result = g_Devices[i];
AzureIoTClient 0:1f9b2707ec7d 644 break;
AzureIoTClient 0:1f9b2707ec7d 645 }
AzureIoTClient 0:1f9b2707ec7d 646 }
AzureIoTClient 0:1f9b2707ec7d 647
AzureIoTClient 0:1f9b2707ec7d 648 return result;
AzureIoTClient 0:1f9b2707ec7d 649 }
AzureIoTClient 0:1f9b2707ec7d 650
AzureIoTClient 0:1f9b2707ec7d 651 static const REFLECTED_SOMETHING* FindValue(DEVICE_HEADER_DATA* deviceHeader, void* value, const char* modelName, size_t startOffset, STRING_HANDLE valuePath)
AzureIoTClient 0:1f9b2707ec7d 652 {
AzureIoTClient 0:1f9b2707ec7d 653 const REFLECTED_SOMETHING* result;
AzureIoTClient 0:1f9b2707ec7d 654 size_t valueOffset = (size_t)((unsigned char*)value - (unsigned char*)deviceHeader->data) - startOffset;
AzureIoTClient 0:1f9b2707ec7d 655
AzureIoTClient 0:1f9b2707ec7d 656 for (result = deviceHeader->ReflectedData->reflectedData; result != NULL; result = result->next)
AzureIoTClient 0:1f9b2707ec7d 657 {
AzureIoTClient 0:1f9b2707ec7d 658 if (result->type == REFLECTION_PROPERTY_TYPE &&
AzureIoTClient 0:1f9b2707ec7d 659 (strcmp(result->what.property.modelName, modelName) == 0) &&
AzureIoTClient 0:1f9b2707ec7d 660 (result->what.property.offset <= valueOffset) &&
AzureIoTClient 0:1f9b2707ec7d 661 (result->what.property.offset + result->what.property.size > valueOffset))
AzureIoTClient 0:1f9b2707ec7d 662 {
AzureIoTClient 0:1f9b2707ec7d 663 if (startOffset != 0)
AzureIoTClient 0:1f9b2707ec7d 664 {
AzureIoTClient 0:1f9b2707ec7d 665 STRING_concat(valuePath, "/");
AzureIoTClient 0:1f9b2707ec7d 666 }
AzureIoTClient 0:1f9b2707ec7d 667
AzureIoTClient 0:1f9b2707ec7d 668 STRING_concat(valuePath, result->what.property.name);
AzureIoTClient 0:1f9b2707ec7d 669 break;
AzureIoTClient 0:1f9b2707ec7d 670 }
AzureIoTClient 0:1f9b2707ec7d 671 }
AzureIoTClient 0:1f9b2707ec7d 672
AzureIoTClient 0:1f9b2707ec7d 673 if (result != NULL)
AzureIoTClient 0:1f9b2707ec7d 674 {
AzureIoTClient 0:1f9b2707ec7d 675 /* Codes_SRS_CODEFIRST_99_133:[CodeFirst_SendAsync shall allow sending of properties that are part of a child model.] */
AzureIoTClient 0:1f9b2707ec7d 676 if (result->what.property.offset < valueOffset)
AzureIoTClient 0:1f9b2707ec7d 677 {
AzureIoTClient 0:1f9b2707ec7d 678 /* find recursively the property in the inner model, if there is one */
AzureIoTClient 0:1f9b2707ec7d 679 result = FindValue(deviceHeader, value, result->what.property.type, startOffset + result->what.property.offset, valuePath);
AzureIoTClient 0:1f9b2707ec7d 680 }
AzureIoTClient 0:1f9b2707ec7d 681 }
AzureIoTClient 0:1f9b2707ec7d 682
AzureIoTClient 0:1f9b2707ec7d 683 return result;
AzureIoTClient 0:1f9b2707ec7d 684 }
AzureIoTClient 0:1f9b2707ec7d 685
AzureIoTClient 0:1f9b2707ec7d 686 /* Codes_SRS_CODEFIRST_99_130:[If a pointer to the beginning of a device block is passed to CodeFirst_SendAsync instead of a pointer to a property, CodeFirst_SendAsync shall send all the properties that belong to that device.] */
AzureIoTClient 0:1f9b2707ec7d 687 /* Codes_SRS_CODEFIRST_99_131:[The properties shall be given to Device as one transaction, as if they were all passed as individual arguments to Code_First.] */
AzureIoTClient 0:1f9b2707ec7d 688 static CODEFIRST_RESULT SendAllDeviceProperties(DEVICE_HEADER_DATA* deviceHeader, TRANSACTION_HANDLE transaction)
AzureIoTClient 0:1f9b2707ec7d 689 {
AzureIoTClient 0:1f9b2707ec7d 690 const char* modelName = Schema_GetModelName(deviceHeader->ModelHandle);
AzureIoTClient 0:1f9b2707ec7d 691 const REFLECTED_SOMETHING* something;
AzureIoTClient 0:1f9b2707ec7d 692 unsigned char* deviceAddress = (unsigned char*)deviceHeader->data;
AzureIoTClient 0:1f9b2707ec7d 693 CODEFIRST_RESULT result = CODEFIRST_OK;
AzureIoTClient 0:1f9b2707ec7d 694
AzureIoTClient 0:1f9b2707ec7d 695 for (something = deviceHeader->ReflectedData->reflectedData; something != NULL; something = something->next)
AzureIoTClient 0:1f9b2707ec7d 696 {
AzureIoTClient 0:1f9b2707ec7d 697 if ((something->type == REFLECTION_PROPERTY_TYPE) &&
AzureIoTClient 0:1f9b2707ec7d 698 (strcmp(something->what.property.modelName, modelName) == 0))
AzureIoTClient 0:1f9b2707ec7d 699 {
AzureIoTClient 0:1f9b2707ec7d 700 AGENT_DATA_TYPE agentDataType;
AzureIoTClient 0:1f9b2707ec7d 701
AzureIoTClient 0:1f9b2707ec7d 702 /* Codes_SRS_CODEFIRST_99_097:[For each value marshalling to AGENT_DATA_TYPE shall be performed.] */
AzureIoTClient 0:1f9b2707ec7d 703 /* Codes_SRS_CODEFIRST_99_098:[The marshalling shall be done by calling the Create_AGENT_DATA_TYPE_from_Ptr function associated with the property.] */
AzureIoTClient 0:1f9b2707ec7d 704 if (something->what.property.Create_AGENT_DATA_TYPE_from_Ptr(deviceAddress + something->what.property.offset, &agentDataType) != AGENT_DATA_TYPES_OK)
AzureIoTClient 0:1f9b2707ec7d 705 {
AzureIoTClient 0:1f9b2707ec7d 706 /* Codes_SRS_CODEFIRST_99_099:[If Create_AGENT_DATA_TYPE_from_Ptr fails, CodeFirst_SendAsync shall return CODEFIRST_AGENT_DATA_TYPE_ERROR.] */
AzureIoTClient 0:1f9b2707ec7d 707 result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
AzureIoTClient 0:1f9b2707ec7d 708 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 709 break;
AzureIoTClient 0:1f9b2707ec7d 710 }
AzureIoTClient 0:1f9b2707ec7d 711 else
AzureIoTClient 0:1f9b2707ec7d 712 {
AzureIoTClient 0:1f9b2707ec7d 713 /* Codes_SRS_CODEFIRST_99_092:[CodeFirst shall publish each value by using Device_PublishTransacted.] */
AzureIoTClient 0:1f9b2707ec7d 714 if (Device_PublishTransacted(transaction, something->what.property.name, &agentDataType) != DEVICE_OK)
AzureIoTClient 0:1f9b2707ec7d 715 {
AzureIoTClient 0:1f9b2707ec7d 716 Destroy_AGENT_DATA_TYPE(&agentDataType);
AzureIoTClient 0:1f9b2707ec7d 717
AzureIoTClient 0:1f9b2707ec7d 718 /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
AzureIoTClient 0:1f9b2707ec7d 719 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
AzureIoTClient 0:1f9b2707ec7d 720 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 721 break;
AzureIoTClient 0:1f9b2707ec7d 722 }
AzureIoTClient 0:1f9b2707ec7d 723
AzureIoTClient 0:1f9b2707ec7d 724 Destroy_AGENT_DATA_TYPE(&agentDataType);
AzureIoTClient 0:1f9b2707ec7d 725 }
AzureIoTClient 0:1f9b2707ec7d 726 }
AzureIoTClient 0:1f9b2707ec7d 727 }
AzureIoTClient 0:1f9b2707ec7d 728
AzureIoTClient 0:1f9b2707ec7d 729 return result;
AzureIoTClient 0:1f9b2707ec7d 730 }
AzureIoTClient 0:1f9b2707ec7d 731
AzureIoTClient 0:1f9b2707ec7d 732 /* Codes_SRS_CODEFIRST_99_088:[CodeFirst_SendAsync shall send to the Device module a set of properties, a destination and a destinationSize.]*/
AzureIoTClient 0:1f9b2707ec7d 733 CODEFIRST_RESULT CodeFirst_SendAsync(unsigned char** destination, size_t* destinationSize, size_t numProperties, ...)
AzureIoTClient 0:1f9b2707ec7d 734 {
AzureIoTClient 0:1f9b2707ec7d 735 CODEFIRST_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 736 va_list ap;
AzureIoTClient 0:1f9b2707ec7d 737
AzureIoTClient 0:1f9b2707ec7d 738 if (
AzureIoTClient 0:1f9b2707ec7d 739 (numProperties == 0) ||
AzureIoTClient 0:1f9b2707ec7d 740 (destination == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 741 (destinationSize == NULL)
AzureIoTClient 0:1f9b2707ec7d 742 )
AzureIoTClient 0:1f9b2707ec7d 743 {
AzureIoTClient 0:1f9b2707ec7d 744 /* Codes_SRS_CODEFIRST_04_002: [If CodeFirst_SendAsync receives destination or destinationSize NULL, CodeFirst_SendAsync shall return Invalid Argument.]*/
AzureIoTClient 0:1f9b2707ec7d 745 /* Codes_SRS_CODEFIRST_99_103:[If CodeFirst_SendAsync is called with numProperties being zero, CODEFIRST_INVALID_ARG shall be returned.] */
AzureIoTClient 0:1f9b2707ec7d 746 result = CODEFIRST_INVALID_ARG;
AzureIoTClient 0:1f9b2707ec7d 747 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 748 }
AzureIoTClient 0:1f9b2707ec7d 749 else
AzureIoTClient 0:1f9b2707ec7d 750 {
AzureIoTClient 0:1f9b2707ec7d 751 DEVICE_HEADER_DATA* deviceHeader = NULL;
AzureIoTClient 0:1f9b2707ec7d 752 size_t i;
AzureIoTClient 0:1f9b2707ec7d 753 TRANSACTION_HANDLE transaction = NULL;
AzureIoTClient 0:1f9b2707ec7d 754 result = CODEFIRST_OK;
AzureIoTClient 0:1f9b2707ec7d 755
AzureIoTClient 0:1f9b2707ec7d 756 /* Codes_SRS_CODEFIRST_99_105:[The properties are passed as pointers to the memory locations where the data exists in the device block allocated by CodeFirst_CreateDevice.] */
AzureIoTClient 0:1f9b2707ec7d 757 va_start(ap, numProperties);
AzureIoTClient 0:1f9b2707ec7d 758
AzureIoTClient 0:1f9b2707ec7d 759 /* Codes_SRS_CODEFIRST_99_089:[The numProperties argument shall indicate how many properties are to be sent.] */
AzureIoTClient 0:1f9b2707ec7d 760 for (i = 0; i < numProperties; i++)
AzureIoTClient 0:1f9b2707ec7d 761 {
AzureIoTClient 0:1f9b2707ec7d 762 void* value = (void*)va_arg(ap, void*);
AzureIoTClient 0:1f9b2707ec7d 763
AzureIoTClient 0:1f9b2707ec7d 764 /* Codes_SRS_CODEFIRST_99_095:[For each value passed to it, CodeFirst_SendAsync shall look up to which device the value belongs.] */
AzureIoTClient 0:1f9b2707ec7d 765 DEVICE_HEADER_DATA* currentValueDeviceHeader = FindDevice(value);
AzureIoTClient 0:1f9b2707ec7d 766 if (currentValueDeviceHeader == NULL)
AzureIoTClient 0:1f9b2707ec7d 767 {
AzureIoTClient 0:1f9b2707ec7d 768 /* Codes_SRS_CODEFIRST_99_104:[If a property cannot be associated with a device, CodeFirst_SendAsync shall return CODEFIRST_INVALID_ARG.] */
AzureIoTClient 0:1f9b2707ec7d 769 result = CODEFIRST_INVALID_ARG;
AzureIoTClient 0:1f9b2707ec7d 770 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 771 break;
AzureIoTClient 0:1f9b2707ec7d 772 }
AzureIoTClient 0:1f9b2707ec7d 773 else if ((deviceHeader != NULL) &&
AzureIoTClient 0:1f9b2707ec7d 774 (currentValueDeviceHeader != deviceHeader))
AzureIoTClient 0:1f9b2707ec7d 775 {
AzureIoTClient 0:1f9b2707ec7d 776 /* Codes_SRS_CODEFIRST_99_096:[All values have to belong to the same device, otherwise CodeFirst_SendAsync shall return CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR.] */
AzureIoTClient 0:1f9b2707ec7d 777 result = CODEFIRST_VALUES_FROM_DIFFERENT_DEVICES_ERROR;
AzureIoTClient 0:1f9b2707ec7d 778 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 779 break;
AzureIoTClient 0:1f9b2707ec7d 780 }
AzureIoTClient 0:1f9b2707ec7d 781 /* Codes_SRS_CODEFIRST_99_090:[All the properties shall be sent together by using the transacted APIs of the device.] */
AzureIoTClient 0:1f9b2707ec7d 782 /* Codes_SRS_CODEFIRST_99_091:[CodeFirst_SendAsync shall start a transaction by calling Device_StartTransaction.] */
AzureIoTClient 0:1f9b2707ec7d 783 else if ((deviceHeader == NULL) &&
AzureIoTClient 0:1f9b2707ec7d 784 ((transaction = Device_StartTransaction(currentValueDeviceHeader->DeviceHandle)) == NULL))
AzureIoTClient 0:1f9b2707ec7d 785 {
AzureIoTClient 0:1f9b2707ec7d 786 /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
AzureIoTClient 0:1f9b2707ec7d 787 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
AzureIoTClient 0:1f9b2707ec7d 788 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 789 break;
AzureIoTClient 0:1f9b2707ec7d 790 }
AzureIoTClient 0:1f9b2707ec7d 791 else
AzureIoTClient 0:1f9b2707ec7d 792 {
AzureIoTClient 0:1f9b2707ec7d 793 deviceHeader = currentValueDeviceHeader;
AzureIoTClient 0:1f9b2707ec7d 794
AzureIoTClient 0:1f9b2707ec7d 795 if (value == ((unsigned char*)deviceHeader->data))
AzureIoTClient 0:1f9b2707ec7d 796 {
AzureIoTClient 0:1f9b2707ec7d 797 /* we got a full device, send all its state data */
AzureIoTClient 0:1f9b2707ec7d 798 result = SendAllDeviceProperties(deviceHeader, transaction);
AzureIoTClient 0:1f9b2707ec7d 799 if (result != CODEFIRST_OK)
AzureIoTClient 0:1f9b2707ec7d 800 {
AzureIoTClient 0:1f9b2707ec7d 801 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 802 break;
AzureIoTClient 0:1f9b2707ec7d 803 }
AzureIoTClient 0:1f9b2707ec7d 804 }
AzureIoTClient 0:1f9b2707ec7d 805 else
AzureIoTClient 0:1f9b2707ec7d 806 {
AzureIoTClient 0:1f9b2707ec7d 807 const REFLECTED_SOMETHING* propertyReflectedData;
AzureIoTClient 0:1f9b2707ec7d 808 const char* modelName;
AzureIoTClient 0:1f9b2707ec7d 809 STRING_HANDLE valuePath;
AzureIoTClient 0:1f9b2707ec7d 810
AzureIoTClient 0:1f9b2707ec7d 811 if ((valuePath = STRING_new()) == NULL)
AzureIoTClient 0:1f9b2707ec7d 812 {
AzureIoTClient 0:1f9b2707ec7d 813 /* Codes_SRS_CODEFIRST_99_134:[If CodeFirst_Notify fails for any other reason it shall return CODEFIRST_ERROR.] */
AzureIoTClient 0:1f9b2707ec7d 814 result = CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 815 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 816 break;
AzureIoTClient 0:1f9b2707ec7d 817 }
AzureIoTClient 0:1f9b2707ec7d 818 else
AzureIoTClient 0:1f9b2707ec7d 819 {
AzureIoTClient 0:1f9b2707ec7d 820 if ((modelName = Schema_GetModelName(deviceHeader->ModelHandle)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 821 {
AzureIoTClient 0:1f9b2707ec7d 822 /* Codes_SRS_CODEFIRST_99_134:[If CodeFirst_Notify fails for any other reason it shall return CODEFIRST_ERROR.] */
AzureIoTClient 0:1f9b2707ec7d 823 result = CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 824 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 825 STRING_delete(valuePath);
AzureIoTClient 0:1f9b2707ec7d 826 break;
AzureIoTClient 0:1f9b2707ec7d 827 }
AzureIoTClient 0:1f9b2707ec7d 828 else if ((propertyReflectedData = FindValue(deviceHeader, value, modelName, 0, valuePath)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 829 {
AzureIoTClient 0:1f9b2707ec7d 830 /* Codes_SRS_CODEFIRST_99_104:[If a property cannot be associated with a device, CodeFirst_SendAsync shall return CODEFIRST_INVALID_ARG.] */
AzureIoTClient 0:1f9b2707ec7d 831 result = CODEFIRST_INVALID_ARG;
AzureIoTClient 0:1f9b2707ec7d 832 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 833 STRING_delete(valuePath);
AzureIoTClient 0:1f9b2707ec7d 834 break;
AzureIoTClient 0:1f9b2707ec7d 835 }
AzureIoTClient 0:1f9b2707ec7d 836 else
AzureIoTClient 0:1f9b2707ec7d 837 {
AzureIoTClient 0:1f9b2707ec7d 838 AGENT_DATA_TYPE agentDataType;
AzureIoTClient 0:1f9b2707ec7d 839
AzureIoTClient 0:1f9b2707ec7d 840 /* Codes_SRS_CODEFIRST_99_097:[For each value marshalling to AGENT_DATA_TYPE shall be performed.] */
AzureIoTClient 0:1f9b2707ec7d 841 /* Codes_SRS_CODEFIRST_99_098:[The marshalling shall be done by calling the Create_AGENT_DATA_TYPE_from_Ptr function associated with the property.] */
AzureIoTClient 0:1f9b2707ec7d 842 if (propertyReflectedData->what.property.Create_AGENT_DATA_TYPE_from_Ptr(value, &agentDataType) != AGENT_DATA_TYPES_OK)
AzureIoTClient 0:1f9b2707ec7d 843 {
AzureIoTClient 0:1f9b2707ec7d 844 /* Codes_SRS_CODEFIRST_99_099:[If Create_AGENT_DATA_TYPE_from_Ptr fails, CodeFirst_SendAsync shall return CODEFIRST_AGENT_DATA_TYPE_ERROR.] */
AzureIoTClient 0:1f9b2707ec7d 845 result = CODEFIRST_AGENT_DATA_TYPE_ERROR;
AzureIoTClient 0:1f9b2707ec7d 846 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 847 STRING_delete(valuePath);
AzureIoTClient 0:1f9b2707ec7d 848 break;
AzureIoTClient 0:1f9b2707ec7d 849 }
AzureIoTClient 0:1f9b2707ec7d 850 else
AzureIoTClient 0:1f9b2707ec7d 851 {
AzureIoTClient 0:1f9b2707ec7d 852 /* Codes_SRS_CODEFIRST_99_092:[CodeFirst shall publish each value by using Device_PublishTransacted.] */
AzureIoTClient 0:1f9b2707ec7d 853 /* Codes_SRS_CODEFIRST_99_136:[CodeFirst_SendAsync shall build the full path for each property and then pass it to Device_PublishTransacted.] */
AzureIoTClient 0:1f9b2707ec7d 854 if (Device_PublishTransacted(transaction, STRING_c_str(valuePath), &agentDataType) != DEVICE_OK)
AzureIoTClient 0:1f9b2707ec7d 855 {
AzureIoTClient 0:1f9b2707ec7d 856 Destroy_AGENT_DATA_TYPE(&agentDataType);
AzureIoTClient 0:1f9b2707ec7d 857
AzureIoTClient 0:1f9b2707ec7d 858 /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
AzureIoTClient 0:1f9b2707ec7d 859 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
AzureIoTClient 0:1f9b2707ec7d 860 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 861 STRING_delete(valuePath);
AzureIoTClient 0:1f9b2707ec7d 862 break;
AzureIoTClient 0:1f9b2707ec7d 863 }
AzureIoTClient 0:1f9b2707ec7d 864 else
AzureIoTClient 0:1f9b2707ec7d 865 {
AzureIoTClient 0:1f9b2707ec7d 866 STRING_delete(valuePath); /*anyway*/
AzureIoTClient 0:1f9b2707ec7d 867 }
AzureIoTClient 0:1f9b2707ec7d 868
AzureIoTClient 0:1f9b2707ec7d 869 Destroy_AGENT_DATA_TYPE(&agentDataType);
AzureIoTClient 0:1f9b2707ec7d 870 }
AzureIoTClient 0:1f9b2707ec7d 871 }
AzureIoTClient 0:1f9b2707ec7d 872 }
AzureIoTClient 0:1f9b2707ec7d 873 }
AzureIoTClient 0:1f9b2707ec7d 874 }
AzureIoTClient 0:1f9b2707ec7d 875 }
AzureIoTClient 0:1f9b2707ec7d 876
AzureIoTClient 0:1f9b2707ec7d 877 if (i < numProperties)
AzureIoTClient 0:1f9b2707ec7d 878 {
AzureIoTClient 0:1f9b2707ec7d 879 if (transaction != NULL)
AzureIoTClient 0:1f9b2707ec7d 880 {
AzureIoTClient 0:1f9b2707ec7d 881 (void)Device_CancelTransaction(transaction);
AzureIoTClient 0:1f9b2707ec7d 882 }
AzureIoTClient 0:1f9b2707ec7d 883 }
AzureIoTClient 0:1f9b2707ec7d 884 /* Codes_SRS_CODEFIRST_99_093:[After all values have been published, Device_EndTransaction shall be called.] */
AzureIoTClient 0:1f9b2707ec7d 885 else if (Device_EndTransaction(transaction, destination, destinationSize) != DEVICE_OK)
AzureIoTClient 0:1f9b2707ec7d 886 {
AzureIoTClient 0:1f9b2707ec7d 887 /* Codes_SRS_CODEFIRST_99_094:[If any Device API fail, CodeFirst_SendAsync shall return CODEFIRST_DEVICE_PUBLISH_FAILED.] */
AzureIoTClient 0:1f9b2707ec7d 888 result = CODEFIRST_DEVICE_PUBLISH_FAILED;
AzureIoTClient 0:1f9b2707ec7d 889 LOG_CODEFIRST_ERROR;
AzureIoTClient 0:1f9b2707ec7d 890 }
AzureIoTClient 0:1f9b2707ec7d 891 else
AzureIoTClient 0:1f9b2707ec7d 892 {
AzureIoTClient 0:1f9b2707ec7d 893 /* Codes_SRS_CODEFIRST_99_117:[On success, CodeFirst_SendAsync shall return CODEFIRST_OK.] */
AzureIoTClient 0:1f9b2707ec7d 894 result = CODEFIRST_OK;
AzureIoTClient 0:1f9b2707ec7d 895 }
AzureIoTClient 0:1f9b2707ec7d 896
AzureIoTClient 0:1f9b2707ec7d 897 va_end(ap);
AzureIoTClient 0:1f9b2707ec7d 898 }
AzureIoTClient 0:1f9b2707ec7d 899
AzureIoTClient 0:1f9b2707ec7d 900 return result;
AzureIoTClient 0:1f9b2707ec7d 901 }
AzureIoTClient 0:1f9b2707ec7d 902
AzureIoTClient 0:1f9b2707ec7d 903 EXECUTE_COMMAND_RESULT CodeFirst_ExecuteCommand(void* device, const char* command)
AzureIoTClient 0:1f9b2707ec7d 904 {
AzureIoTClient 0:1f9b2707ec7d 905 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 906 /*Codes_SRS_CODEFIRST_02_014: [If parameter device or command is NULL then CodeFirst_ExecuteCommand shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 0:1f9b2707ec7d 907 if (
AzureIoTClient 0:1f9b2707ec7d 908 (device == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 909 (command == NULL)
AzureIoTClient 0:1f9b2707ec7d 910 )
AzureIoTClient 0:1f9b2707ec7d 911 {
AzureIoTClient 0:1f9b2707ec7d 912 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 913 LogError("invalid argument (NULL) passed to CodeFirst_ExecuteCommand void* device = %p, const char* command = %p\r\n", device, command);
AzureIoTClient 0:1f9b2707ec7d 914 }
AzureIoTClient 0:1f9b2707ec7d 915 else
AzureIoTClient 0:1f9b2707ec7d 916 {
AzureIoTClient 0:1f9b2707ec7d 917 /*Codes_SRS_CODEFIRST_02_015: [CodeFirst_ExecuteCommand shall find the device.]*/
AzureIoTClient 0:1f9b2707ec7d 918 DEVICE_HEADER_DATA* deviceHeader = FindDevice(device);
AzureIoTClient 0:1f9b2707ec7d 919 if(deviceHeader == NULL)
AzureIoTClient 0:1f9b2707ec7d 920 {
AzureIoTClient 0:1f9b2707ec7d 921 /*Codes_SRS_CODEFIRST_02_016: [If finding the device fails, then CodeFirst_ExecuteCommand shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 0:1f9b2707ec7d 922 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 923 LogError("unable to find the device given by address %p\r\n", device);
AzureIoTClient 0:1f9b2707ec7d 924 }
AzureIoTClient 0:1f9b2707ec7d 925 else
AzureIoTClient 0:1f9b2707ec7d 926 {
AzureIoTClient 0:1f9b2707ec7d 927 /*Codes_SRS_CODEFIRST_02_017: [Otherwise CodeFirst_ExecuteCommand shall call Device_ExecuteCommand and return what Device_ExecuteCommand is returning.] */
AzureIoTClient 0:1f9b2707ec7d 928 result = Device_ExecuteCommand(deviceHeader->DeviceHandle, command);
AzureIoTClient 0:1f9b2707ec7d 929 }
AzureIoTClient 0:1f9b2707ec7d 930 }
AzureIoTClient 0:1f9b2707ec7d 931 return result;
AzureIoTClient 0:1f9b2707ec7d 932 }