espressif/esp-aws-iot

coreMQTT: Argument cannot be NULL: pContext=0x3ffc3dd8, pSubscriptionList=0x0 AND coreMQTT: MQTT operation failed with status MQTTBadParameter (CA-328)

monkeytronics opened this issue · 1 comments

Completely Stuck.

Errors =

coreMQTT: Argument cannot be NULL: pContext=0x3ffc3dd8, pSubscriptionList=0x0 
coreMQTT: MQTT operation failed with status MQTTBadParameter

Built up demo project. Connecting and publishing to broker fine. But when I try to subscribe, it breaks with the above error. Full log :

E (30789) MONKEY_AWS_IOT_TASK: Shadow Delta Topic = $aws/things/S900001/shadow/update/delta
W (30789) MONKEY_AWS_IOT: monkey_aws_iot_subscribe
W (30789) MONKEY_AWS_IOT: monkey_aws_iot_subscribe - do
W (30799) MONKEY_AWS_IOT: monkey_aws_iot_subscribe - mqttStatus = 0
W (30909) XXXX monkey: MQTTAgent_CommandLoop: pCommand=0x3ffc687c
W (30909) XXXX monkey: processCommand::
pMqttAgentContext=0x3ffc3dd8,
pCommand=0x3ffc687c,
pEndLoop=0x3ffd0f34,
commandFunction=0x40107d0c,
0x40107d0c: MQTTAgentCommand_Subscribe at D:/MonkeySource/4-FW/2-esp32-dev-v5.1/airsmart-fw/libs/esp-aws-iot/libraries/coreMQTT-Agent/coreMQTT-Agent/source/core_mqtt_agent_command_functions.c:94

pCommandArgs=0x3ffcfb5c,
commandOutParams=0x3ffd0f04

W (30929) XXXX monkey: MQTTAgentCommand_Subscribe::
pMqttAgentContext=0x3ffc3dd8,
pVoidSubscribeArgs=0x3ffcfb5c,
pReturnFlags=0x3ffd0f04

W (30939) XXXX monkey: MQTTAgentCommand_Subscribe::
pSubscribeArgs->pSubscribeInfo=0x0
, pSubscribeArgs->numSubscriptions=1
, pReturnFlags->packetId=1

W (30949) XXXX monkey: MQTT_Subscribe::
pContext=0x3ffc3dd8,
pSubscriptionList=0x0,
subscriptionCount=1,
packetId=1

W (30969) XXXX monkey: validateSubscribeUnsubscribeParams::
pSubscriptionList = 0x0,
subscriptionCount = 1,
packetId = 1

E (30979) coreMQTT: * Argument cannot be NULL: pContext=0x3ffc3dd8, pSubscriptionList=0x0.
W (30989) MONKEY_AWS_IOT: prvSubscribeCommand_cb
W (30989) MONKEY_AWS_IOT: prvSubscribeCommand_cb - xTaskToNotify
E (30999) coreMQTT: MQTT operation failed with status MQTTBadParameter

I've done my best to trace the error back. The first error (Argument cannot be empty) comes from core_mqtt::validateSubscribeUnsubscribeParams. And the param in question is pSubscriptionList.

I've traced this back through

  • core_mqtt::MQTT_Subscribe
  • core_mqtt_agent_command_functions::MQTTAgentCommand_Subscribe
  • processCommand (pulling function from MQTT_AGENT_FUNCTION_TABLE)
  • MQTTAgent_CommandLoop
  • prvMQTTAgentTask

It's a very long chain. And it appears to me that the offending parameter is created here:

MQTTStatus_t MQTTAgent_CommandLoop( MQTTAgentContext_t * pMqttAgentContext )
{
    MQTTAgentCommand_t * pCommand;
    MQTTStatus_t operationStatus = MQTTSuccess;
    bool endLoop = false;

    /* The command queue should have been created before this task gets created. */
    if( ( pMqttAgentContext == NULL ) || ( pMqttAgentContext->agentInterface.pMsgCtx == NULL ) )
    {
        operationStatus = MQTTBadParameter;
    }

    /* Loop until an error or we receive a terminate command. */
    while( operationStatus == MQTTSuccess )
    {
        /* Wait for the next command, if any. */
        pCommand = NULL;
        ( void ) pMqttAgentContext->agentInterface.recv(    <--- what does this do????
            pMqttAgentContext->agentInterface.pMsgCtx,
            &( pCommand ),
            MQTT_AGENT_MAX_EVENT_QUEUE_WAIT_TIME
            );
        operationStatus = processCommand( pMqttAgentContext, pCommand, &endLoop );  <--- pCommand

The var pCommand is fed through the long tree of functions above, morphing into various other structs. Any idea what the above function (agentInterface.recv) is supposed to do, or why it might not be doing it?

My actual code is below. Would love to know what has gone wrong here.

MQTTStatus_t monkey_aws_iot_subscribe(  MQTTQoS_t xQoS, 
                                        char *pcTopicFilter)
{
    ESP_LOGW(TAG, "monkey_aws_iot_subscribe");
    MQTTStatus_t mqttStatus = MQTTBadParameter;

	MQTTSubscribeInfo_t xSubscribeInfo;
    MQTTAgentSubscribeArgs_t xSubscribeArgs;
    MQTTAgentCommandContext_t xApplicationDefinedContext = { 0UL };
    MQTTAgentCommandInfo_t xCommandParams = { 0UL };

    /* Create a unique number of the subscribe that is about to be sent.  The number
     * is used as the command context and is sent back to this task as a notification
     * in the callback that executed upon receipt of the subscription acknowledgment.
     * That way this task can match an acknowledgment to a subscription. */
    xTaskNotifyStateClear( NULL );


    /* Complete the subscribe information.  The topic string must persist for
     * duration of subscription! */
    xSubscribeInfo.pTopicFilter = pcTopicFilter;
    xSubscribeInfo.topicFilterLength = ( uint16_t ) strlen( pcTopicFilter );
    xSubscribeInfo.qos = xQoS;

    xSubscribeArgs.pSubscribeInfo = &xSubscribeInfo;
    xSubscribeArgs.numSubscriptions = 1;

    /* Complete an application defined context associated with this subscribe message.
     * This gets updated in the callback function so the variable must persist until
     * the callback executes. */
    xApplicationDefinedContext.ulNotificationValue = (int32_t) 0;
    xApplicationDefinedContext.xTaskToNotify = xTaskGetCurrentTaskHandle();
    xApplicationDefinedContext.pArgs = ( void * ) &xSubscribeArgs;

    xCommandParams.blockTimeMs = 500; // temppubsubandledcontrolconfigMAX_COMMAND_SEND_BLOCK_TIME_MS;
    xCommandParams.cmdCompleteCallback = prvSubscribeCommand_cb;
    xCommandParams.pCmdCompleteCallbackContext = ( void * ) &xApplicationDefinedContext;


    /* Wait for coreMQTT-Agent task network up and no OTA in progress */
    xEventGroupWaitBits  (  xNetworkEventGroup,
                            CORE_MQTT_AGENT_CONNECTED_BIT | CORE_MQTT_AGENT_OTA_NOT_IN_PROGRESS_BIT,
                            pdFALSE, // clear on exit
                            pdTRUE,  // wait for all bits
                            portMAX_DELAY );

    /* Loop in case the queue used to communicate with the MQTT agent is full and
     * attempts to post to it time out.  The queue will not become full if the
     * priority of the MQTT agent task is higher than the priority of the task
     * calling this function. */
    do
    {
        ESP_LOGW(TAG, "monkey_aws_iot_subscribe - do");
        mqttStatus = MQTTAgent_Subscribe( &xGlobalMqttAgentContext,
                                          &xSubscribeArgs,
                                          &xCommandParams );
        ESP_LOGW(TAG, "monkey_aws_iot_subscribe - mqttStatus = %d", mqttStatus);
    } while( mqttStatus != MQTTSuccess );

    // /* Wait for acks to the subscribe message - this is optional but done here
    //  * so the code below can check the notification sent by the callback matches
    //  * the ulNextSubscribeMessageID value set in the context above. */
    // BaseType_t xCommandAcknowledged = prvWaitForCommandAcknowledgment( NULL );

    // /* Check both ways the status was passed back just for demonstration
    //  * purposes. */
    // if( ( xCommandAcknowledged != pdTRUE ) ||
    //     ( xApplicationDefinedContext.xReturnStatus != MQTTSuccess ) )
    // {
    //     ESP_LOGE( TAG, "Error or timed out waiting for ack to subscribe message topic %s", pcTopicFilter );
    //     return MQTTSuccess;
    // }
    // else
    // {
    //     ESP_LOGI( TAG, "Received subscribe ack for topic %s.", pcTopicFilter );
    //     return MQTTSubAckFailure;
    // }

    // return xCommandAcknowledged;

	return MQTTSuccess;
}

static void prvSubscribeCommand_cb( MQTTAgentCommandContext_t * pxCommandContext, 
                                    MQTTAgentReturnInfo_t * pxReturnInfo )
{
    ESP_LOGW(TAG, "prvSubscribeCommand_cb");
    bool xSubscriptionAdded = false;
    MQTTAgentSubscribeArgs_t * pxSubscribeArgs = ( MQTTAgentSubscribeArgs_t * ) pxCommandContext->pArgs;

    /* Store the result in the application defined context so the task that
     * initiated the subscribe can check the operation's status. */
    pxCommandContext->xReturnStatus = pxReturnInfo->returnCode;

    /* Check if the subscribe operation is a success. */
    if( pxReturnInfo->returnCode == MQTTSuccess )
    {
        /* Add subscription so that incoming publishes are routed to the application
         * callback. */
        xSubscriptionAdded = addSubscription( ( SubscriptionElement_t * ) xGlobalMqttAgentContext.pIncomingCallbackContext,
                                              pxSubscribeArgs->pSubscribeInfo->pTopicFilter,
                                              pxSubscribeArgs->pSubscribeInfo->topicFilterLength,
                                              prvIncomingPublish_cb,
                                              ( void * ) ( pxCommandContext->pArgs ) );

        if( xSubscriptionAdded == false )
        {
            ESP_LOGE( TAG,
                      "Failed to register an incoming publish callback for topic %.*s.",
                      pxSubscribeArgs->pSubscribeInfo->topicFilterLength,
                      pxSubscribeArgs->pSubscribeInfo->pTopicFilter );
        }
    }

    if( pxCommandContext->xTaskToNotify != NULL )
    {
        ESP_LOGW(TAG, "prvSubscribeCommand_cb - xTaskToNotify");
        xTaskNotify( pxCommandContext->xTaskToNotify,
                     ( uint32_t ) ( pxReturnInfo->returnCode ),
                     eSetValueWithOverwrite );
    }
}

Closing as this is related to demo code, not the actual library itself. Root issue in this case was task priorities in demo app tasks conflicting with rest of user application.