static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen, IoT_Publish_Message_Params *params, void *pData) { int32_t tokenCount; uint8_t i; void *pJsonHandler = NULL; char temporaryClientToken[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; IOT_UNUSED(pClient); IOT_UNUSED(topicNameLen); IOT_UNUSED(pData); if(params->payloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) { IOT_WARN("Payload larger than RX Buffer"); return; } memcpy(shadowRxBuf, params->payload, params->payloadLen); shadowRxBuf[params->payloadLen] = '\0'; // jsmn_parse relies on a string if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) { IOT_WARN("Received JSON is not valid"); return; } if(isAckForMyThingName(topicName)) { uint32_t tempVersionNumber = 0; if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { if(tempVersionNumber > shadowJsonVersionNum) { shadowJsonVersionNum = tempVersionNumber; } } } if(extractClientToken(shadowRxBuf, temporaryClientToken)) { for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { if(!AckWaitList[i].isFree) { if(strcmp(AckWaitList[i].clientTokenID, temporaryClientToken) == 0) { Shadow_Ack_Status_t status; if(strstr(topicName, "accepted") != NULL) { status = SHADOW_ACK_ACCEPTED; } else if(strstr(topicName, "rejected") != NULL) { status = SHADOW_ACK_REJECTED; } else { continue; } /* status == SHADOW_ACK_ACCEPTED || status == SHADOW_ACK_REJECTED */ if(AckWaitList[i].callback != NULL) { AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, status, shadowRxBuf, AckWaitList[i].pCallbackContext); } unsubscribeFromAcceptedAndRejected(i); AckWaitList[i].isFree = true; return; } } } } }
static int AckStatusCallback(MQTTCallbackParams params) { int32_t tokenCount; int32_t i; void *pJsonHandler; char temporaryClientToken[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE]; if (params.MessageParams.PayloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) { return GENERIC_ERROR; } memcpy(shadowRxBuf, params.MessageParams.pPayload, params.MessageParams.PayloadLen); shadowRxBuf[params.MessageParams.PayloadLen] = '\0'; // jsmn_parse relies on a string if (!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) { WARN("Received JSON is not valid"); return GENERIC_ERROR; } if (isAckForMyThingName(params.pTopicName)) { uint32_t tempVersionNumber = 0; if (extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) { if (tempVersionNumber > shadowJsonVersionNum) { shadowJsonVersionNum = tempVersionNumber; } } } if (extractClientToken(shadowRxBuf, temporaryClientToken)) { for (i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) { if (!AckWaitList[i].isFree) { if (strcmp(AckWaitList[i].clientTokenID, temporaryClientToken) == 0) { Shadow_Ack_Status_t status; if (strstr(params.pTopicName, "accepted") != NULL) { status = SHADOW_ACK_ACCEPTED; } else if (strstr(params.pTopicName, "rejected") != NULL) { status = SHADOW_ACK_REJECTED; } if (status == SHADOW_ACK_ACCEPTED || status == SHADOW_ACK_REJECTED) { if (AckWaitList[i].callback != NULL) { AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, status, shadowRxBuf, AckWaitList[i].pCallbackContext); } unsubscribeFromAcceptedAndRejected(i); AckWaitList[i].isFree = true; return NONE_ERROR; } } } } } return GENERIC_ERROR; }
IoT_Error_t iot_shadow_action(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent, fpActionCallback_t callback, void *pCallbackContext, uint32_t timeout_seconds, bool isSticky) { IoT_Error_t ret_val = SUCCESS; bool isCallbackPresent = false; bool isClientTokenPresent = false; bool isAckWaitListFree = false; uint8_t indexAckWaitList; if(pThingName == NULL || pJsonDocumentToBeSent == NULL){ return NULL_VALUE_ERROR; } if (callback != NULL) { isCallbackPresent = true; } char extractedClientToken[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; isClientTokenPresent = extractClientToken(pJsonDocumentToBeSent, extractedClientToken); if (isClientTokenPresent && isCallbackPresent) { if (getNextFreeIndexOfAckWaitList(&indexAckWaitList)) { isAckWaitListFree = true; } if(isAckWaitListFree) { if (!isSubscriptionPresent(pThingName, action)) { ret_val = subscribeToShadowActionAcks(pThingName, action, isSticky); } else { incrementSubscriptionCnt(pThingName, action, isSticky); } } else { ret_val = FAILURE; } } if (ret_val == SUCCESS) { ret_val = publishToShadowAction(pThingName, action, pJsonDocumentToBeSent); } if (isClientTokenPresent && isCallbackPresent && ret_val == SUCCESS && isAckWaitListFree) { addToAckWaitList(indexAckWaitList, pThingName, action, extractedClientToken, callback, pCallbackContext, timeout_seconds); } return ret_val; }
IoT_Error_t aws_iot_shadow_internal_action(const char *pThingName, ShadowActions_t action, const char *pJsonDocumentToBeSent, fpActionCallback_t callback, void *pCallbackContext, uint32_t timeout_seconds, bool isSticky) { IoT_Error_t ret_val = AWS_SUCCESS; bool isClientTokenPresent = false; bool isAckWaitListFree = false; uint8_t indexAckWaitList; char extractedClientToken[MAX_SIZE_CLIENT_ID_WITH_SEQUENCE]; FUNC_ENTRY; if(NULL == pThingName || NULL == pJsonDocumentToBeSent) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } isClientTokenPresent = extractClientToken(pJsonDocumentToBeSent, extractedClientToken); if(isClientTokenPresent && (NULL != callback)) { if(getNextFreeIndexOfAckWaitList(&indexAckWaitList)) { isAckWaitListFree = true; } if(isAckWaitListFree) { if(!isSubscriptionPresent(pThingName, action)) { ret_val = subscribeToShadowActionAcks(pThingName, action, isSticky); } else { incrementSubscriptionCnt(pThingName, action, isSticky); } } else { ret_val = AWS_FAILURE; } } if(AWS_SUCCESS == ret_val) { ret_val = publishToShadowAction(pThingName, action, pJsonDocumentToBeSent); } if(isClientTokenPresent && (NULL != callback) && (AWS_SUCCESS == ret_val) && isAckWaitListFree) { addToAckWaitList(indexAckWaitList, pThingName, action, extractedClientToken, callback, pCallbackContext, timeout_seconds); } FUNC_EXIT_RC(ret_val); }