in src/adapters/pnp/PnpUtils.c [174:316]
static IOTHUB_CLIENT_RESULT ProcessJsonFromTwin(DEVICE_TWIN_UPDATE_STATE updateState, const unsigned char* payload, size_t size, PROPERTY_UPDATE_CALLBACK propertyCallback)
{
JSON_Value* rootValue = NULL;
JSON_Value* versionValue = NULL;
JSON_Value* propertyValue = NULL;
JSON_Value* childValue = NULL;
JSON_Object* rootObject = NULL;
JSON_Object* desiredObject = NULL;
JSON_Object* childObject = NULL;
size_t numChildren = 0;
size_t numChildChildren = 0;
int version = 0;
char* jsonString = NULL;
const char* componentName = NULL;
const char* propertyName = NULL;
IOTHUB_CLIENT_RESULT result = IOTHUB_CLIENT_OK;
LogAssert(GetLog(), NULL != payload);
jsonString = CopyPayloadToString(payload, size);
if (NULL == jsonString)
{
OsConfigLogError(GetLog(), "ProcessJsonFromTwin: CopyPayloadToString failed");
result = IOTHUB_CLIENT_ERROR;
}
if (IOTHUB_CLIENT_OK == result)
{
rootValue = json_parse_string(jsonString);
if (NULL == rootValue)
{
OsConfigLogError(GetLog(), "ProcessJsonFromTwin: json_parse_string(root) failed");
result = IOTHUB_CLIENT_ERROR;
}
}
if (IOTHUB_CLIENT_OK == result)
{
rootObject = json_value_get_object(rootValue);
if (NULL == rootObject)
{
OsConfigLogError(GetLog(), "ProcessJsonFromTwin: json_value_get_object(root) failed, cannot get desired object");
result = IOTHUB_CLIENT_ERROR;
}
}
if (IOTHUB_CLIENT_OK == result)
{
if (DEVICE_TWIN_UPDATE_COMPLETE == updateState)
{
OsConfigLogInfo(GetLog(), "ProcessJsonFromTwin: DEVICE_TWIN_UPDATE_COMPLETE");
// For a complete update the JSON from IoT Hub contains both "desired" and "reported" (the full twin):
desiredObject = json_object_get_object(rootObject, g_desiredObjectName);
}
else
{
OsConfigLogInfo(GetLog(), "ProcessJsonFromTwin: DEVICE_TWIN_UPDATE_PARTIAL");
// For a partial update the JSON from IoT Hub skips the "desired" envelope, we need to read from root:
desiredObject = rootObject;
}
if (NULL == desiredObject)
{
OsConfigLogError(GetLog(), "ProcessJsonFromTwin: no desired object");
result = IOTHUB_CLIENT_ERROR;
}
}
if (IOTHUB_CLIENT_OK == result)
{
versionValue = json_object_get_value(desiredObject, g_desiredVersion);
if (NULL != versionValue)
{
if (JSONNumber == json_value_get_type(versionValue))
{
version = (int)json_value_get_number(versionValue);
}
else
{
OsConfigLogError(GetLog(), "ProcessJsonFromTwin: field %s type is not JSONNumber, cannot read the desired version", g_desiredVersion);
}
}
else
{
OsConfigLogError(GetLog(), "ProcessJsonFromTwin: json_object_get_value(%s) failed, cannot read the desired version", g_desiredVersion);
}
numChildren = json_object_get_count(desiredObject);
for (size_t i = 0; i < numChildren; i++)
{
componentName = json_object_get_name(desiredObject, i);
childValue = json_object_get_value_at(desiredObject, i);
if (0 == strcmp(componentName, g_desiredVersion))
{
// Ignore, nothing to do here
continue;
}
if (JSONObject == json_type(childValue))
{
childObject = json_value_get_object(childValue);
numChildChildren = json_object_get_count(childObject);
for (size_t i = 0; i < numChildChildren; i++)
{
propertyName = json_object_get_name(childObject, i);
propertyValue = json_object_get_value_at(childObject, i);
if ((NULL == propertyName) || (NULL == propertyValue))
{
OsConfigLogError(GetLog(), "ProcessJsonFromTwin: error retrieving property name and/or value from %s (child[%d])", componentName, (int)i);
continue;
}
if (0 == strcmp(propertyName, g_componentMarker))
{
// Ignore the marker
continue;
}
result = propertyCallback(componentName, propertyName, propertyValue, version);
}
}
}
}
if (NULL != rootValue)
{
json_value_free(rootValue);
}
FREE_MEMORY(jsonString);
UNUSED(propertyCallback);
OsConfigLogInfo(GetLog(), "ProcessJsonFromTwin completed with %d", result);
return result;
}