in sdk/src/azure/iot/az_iot_hub_client_twin.c [110:230]
AZ_NODISCARD az_result az_iot_hub_client_twin_parse_received_topic(
az_iot_hub_client const* client,
az_span received_topic,
az_iot_hub_client_twin_response* out_response)
{
_az_PRECONDITION_NOT_NULL(client);
_az_PRECONDITION_VALID_SPAN(client->_internal.iot_hub_hostname, 1, false);
_az_PRECONDITION_VALID_SPAN(received_topic, 1, false);
_az_PRECONDITION_NOT_NULL(out_response);
(void)client;
az_result result = AZ_OK;
int32_t twin_index = az_span_find(received_topic, az_iot_hub_twin_topic_prefix);
// Check if is related to twin or not
if (twin_index >= 0)
{
_az_LOG_WRITE(AZ_LOG_MQTT_RECEIVED_TOPIC, received_topic);
int32_t twin_feature_index = -1;
az_span twin_feature_span
= az_span_slice(received_topic, twin_index, az_span_size(received_topic));
if ((twin_feature_index = az_span_find(twin_feature_span, az_iot_hub_twin_response_sub_topic))
>= 0)
{
// Is a res case
int32_t index = 0;
az_span remainder;
az_span status_str = _az_span_token(
az_span_slice(
received_topic,
twin_feature_index + az_span_size(az_iot_hub_twin_response_sub_topic),
az_span_size(received_topic)),
AZ_SPAN_FROM_STR("/"),
&remainder,
&index);
// Get status and convert to enum
uint32_t status_int = 0;
_az_RETURN_IF_FAILED(az_span_atou32(status_str, &status_int));
out_response->status = (az_iot_status)status_int;
if (index == -1)
{
return AZ_ERROR_UNEXPECTED_END;
}
// Get request id prop value
az_iot_message_properties props;
az_span prop_span = az_span_slice(remainder, 1, az_span_size(remainder));
_az_RETURN_IF_FAILED(
az_iot_message_properties_init(&props, prop_span, az_span_size(prop_span)));
_az_RETURN_IF_FAILED(az_iot_message_properties_find(
&props, az_iot_hub_client_request_id_span, &out_response->request_id));
if (out_response->status >= AZ_IOT_STATUS_BAD_REQUEST) // 400+
{
// Is an error response
out_response->response_type = AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_TYPE_REQUEST_ERROR;
out_response->version = AZ_SPAN_EMPTY;
}
else if (out_response->status == AZ_IOT_STATUS_NO_CONTENT) // 204
{
// Is a reported prop response
out_response->response_type = AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_TYPE_REPORTED_PROPERTIES;
result = az_iot_message_properties_find(
&props, az_iot_hub_twin_version_prop, &out_response->version);
if (result == AZ_ERROR_ITEM_NOT_FOUND)
{
out_response->version = AZ_SPAN_EMPTY;
}
else
{
_az_RETURN_IF_FAILED(result);
}
}
else // 200 or 202
{
// Is a twin GET response
out_response->response_type = AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_TYPE_GET;
out_response->version = AZ_SPAN_EMPTY;
}
result = AZ_OK;
}
else if (
(twin_feature_index = az_span_find(twin_feature_span, az_iot_hub_twin_patch_sub_topic))
>= 0)
{
// Is a /PATCH case (desired props)
az_iot_message_properties props;
az_span prop_span = az_span_slice(
received_topic,
twin_feature_index + az_span_size(az_iot_hub_twin_patch_sub_topic)
+ (int32_t)sizeof(az_iot_hub_client_twin_question),
az_span_size(received_topic));
_az_RETURN_IF_FAILED(
az_iot_message_properties_init(&props, prop_span, az_span_size(prop_span)));
_az_RETURN_IF_FAILED(az_iot_message_properties_find(
&props, az_iot_hub_twin_version_prop, &out_response->version));
out_response->response_type = AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_TYPE_DESIRED_PROPERTIES;
out_response->request_id = AZ_SPAN_EMPTY;
out_response->status = AZ_IOT_STATUS_OK;
result = AZ_OK;
}
else
{
result = AZ_ERROR_IOT_TOPIC_NO_MATCH;
}
}
else
{
result = AZ_ERROR_IOT_TOPIC_NO_MATCH;
}
return result;
}