Bg96 qapi_atfwd_reg not work

i’m use platformio + bg96

/*
ThreadX BG96 - MAIN
Created on: 01.01.2019
Author: Georgi Angelov
http://www.wizio.eu/
https://github.com/Wiz-IO/platform-quectel
*/

#include <_ansi.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>

#include <qapi.h>
#include <qapi_uart.h>
#include <qapi_timer.h>
#include <qapi_atfwd.h>
#include <qapi_gpioint.h>

#include <quectel_gpio.h>
#include <quectel_utils.h>
#include <quectel_uart_apis.h>

typedef unsigned char boolean;
typedef unsigned char uint8;

#define QUEC_AT_RESULT_ERROR_V01 0 /< Result ERROR.
This is to be set in case of ERROR or CME ERROR.
The response buffer contains the entire details. */
#define QUEC_AT_RESULT_OK_V01 1 /
< Result OK. This is to be set if the final response
must send an OK result code to the terminal.
The response buffer must not contain an OK. */
#define QUEC_AT_MASK_EMPTY_V01 0 /< Denotes a feed back mechanism for AT reg and de-reg */
#define QUEC_AT_MASK_NA_V01 1 /
< Denotes presence of Name field */
#define QUEC_AT_MASK_EQ_V01 2 /< Denotes presence of equal (=) operator */
#define QUEC_AT_MASK_QU_V01 4 /
< Denotes presence of question mark (?) */
#define QUEC_AT_MASK_AR_V01 8 /**< Denotes presence of trailing argument operator */

static char *rx_buff = NULL;
static char *tx_buff = NULL;
static QT_UART_CONF_PARA uart_conf;
static int qexample_val = 0;

/**************************************************************************

  •                             FUNCTION
    

***************************************************************************/
static int qt_atoi(char *str)
{
int res = 0, i;

for (i = 0; str[i] != '\0' && str[i] != '.'; ++i)
{
    res = res*10 + (str[i] - '0');
}

return res;

}

void *_sbrk(intptr_t increment) { return (void *)-1; }

void abort(void)
{
while (1) // dont block app
{
qt_uart_dbg(uart_conf.hdlr, “\nabort”);
qapi_Timer_Sleep(100, QAPI_TIMER_UNIT_SEC, 1);
}

}

TX_BYTE_POOL *heap;
static char heap_buffer[HEAP]; // build_flags = -D HEAP=xxx
void heap_init(void)
{
if (txm_module_object_allocate(&heap, sizeof(TX_BYTE_POOL)))
abort();
if (tx_byte_pool_create(heap, “heap_byte_pool”, heap_buffer, HEAP))
abort();
}

int quectel_dbg_uart_init(qapi_UART_Port_Id_e port_id)
{
if (tx_byte_allocate(heap, (VOID *)&rx_buff, 4 * 1024, TX_NO_WAIT))
abort();
if (tx_byte_allocate(heap, (VOID *)&tx_buff, 4 * 1024, TX_NO_WAIT))
abort();
uart_conf.hdlr = NULL;
uart_conf.port_id = port_id;
uart_conf.tx_buff = tx_buff;
uart_conf.tx_len = sizeof(tx_buff);
uart_conf.rx_buff = rx_buff;
uart_conf.rx_len = sizeof(rx_buff);
uart_conf.baudrate = 115200;
uart_init(&uart_conf); // open uart
return TX_SUCCESS;
}

void atfwd_cmd_handler_cb(boolean is_reg, char atcmd_name,
uint8
at_fwd_params, uint8 mask,
uint32 at_handle)
{
char buff[32] = {0};
int tmp_val = 0;
qapi_Status_t ret = QAPI_ERROR;

qt_uart_dbg(uart_conf.hdlr,"atfwd_cmd_handler_cb is called, atcmd_name:[%s] mask:[%d]\n", atcmd_name, mask);
qt_uart_dbg(uart_conf.hdlr,"atfwd_cmd_handler_cb is called,  is_reg:[%d]\n", is_reg);


if(is_reg)  //Registration Successful,is_reg return 1 
{
	if(mask==QUEC_AT_MASK_EMPTY_V01)
	{
		qt_uart_dbg(uart_conf.hdlr,"Atcmd %s is registered\n",atcmd_name);
		return;

	}
	if( !strncasecmp(atcmd_name, "+QEXAMPLE",strlen(atcmd_name)) )
    {
        //Execute Mode
        if ((QUEC_AT_MASK_NA_V01) == mask)//AT+QEXAMPLE
        {
            ret = qapi_atfwd_send_resp(atcmd_name, "", QUEC_AT_RESULT_OK_V01);
        }
        //Read Mode
        else if ((QUEC_AT_MASK_NA_V01 | QUEC_AT_MASK_QU_V01) == mask)//AT+QEXAMPLE?
        {
            snprintf(buff, sizeof(buff), "+QEXAMPLE: %d", qexample_val);
            ret = qapi_atfwd_send_resp(atcmd_name, buff, QUEC_AT_RESULT_OK_V01);
        }
        //Test Mode
        else if ((QUEC_AT_MASK_NA_V01 | QUEC_AT_MASK_EQ_V01 | QUEC_AT_MASK_QU_V01) == mask)//AT+QEXAMPLE=?
        {
            snprintf(buff, sizeof(buff), "+QEXAMPLE: (0-2)");
            ret = qapi_atfwd_send_resp(atcmd_name, buff, QUEC_AT_RESULT_OK_V01);
        }
        //Write Mode
        else if ((QUEC_AT_MASK_NA_V01 | QUEC_AT_MASK_EQ_V01 | QUEC_AT_MASK_AR_V01) == mask)//AT+QEXAMPLE=<value>
        {
            tmp_val = qt_atoi((char*)at_fwd_params);
            if(tmp_val >= 0 && tmp_val <= 2)
            {
                qexample_val = tmp_val;
                ret = qapi_atfwd_send_resp(atcmd_name, "", QUEC_AT_RESULT_OK_V01);
            }
            else
            {
                ret = qapi_atfwd_send_resp(atcmd_name, "", QUEC_AT_RESULT_ERROR_V01);
            }  
        }
    }
    else
    {
        ret = qapi_atfwd_send_resp(atcmd_name, "", QUEC_AT_RESULT_ERROR_V01);
    }

	qt_uart_dbg(uart_conf.hdlr,"[%s] send resp, ret = %d\n", atcmd_name, ret);
}

}

attribute((section(".library"))) int TXM_MODULE_THREAD_ENTRY(void)
{
qapi_Status_t retval = QAPI_ERROR;
heap_init();
if (quectel_dbg_uart_init(QAPI_UART_PORT_002_E)) // QAPI_UART_PORT_002_E —> EVB COM2(DEBUG)
abort();
qt_uart_dbg(uart_conf.hdlr, “\nThreadX BG96 Hello World”);

retval = qapi_atfwd_reg("+QEXAMPLE", atfwd_cmd_handler_cb);
if(retval != QAPI_OK)
{
    qt_uart_dbg(uart_conf.hdlr,"qapi_atfwd_reg  fail\n");
}
else
{
    qt_uart_dbg(uart_conf.hdlr,"qapi_atfwd_reg ok!\n");
}

while (1)
{
    qt_uart_dbg(uart_conf.hdlr, "LOOP");
    tx_thread_sleep(500); // only here or qapi_Timer_Sleep()
    qapi_Timer_Sleep
}

}

COM2(DEBUG) ouput

ThreadX BG96 Hello World
atfwd_cmd_handler_cb is called, atcmd_name:[+QEXAMPLE] mask:[1]

qapi_atfwd_reg ok!

atfwd_cmd_handler_cb is called, is_reg:[0]

why is_reg is 0 ??

COM1(MAIN)

RDY

APP RDY
AT+QEXAMPLE
ERROR
AT+QEXAMPLE?
ERROR
AT+QEXAMPLE=1
ERROR

Hi woojin,

I have checked your code , the code you runned is example_atfwd.c , right ?

I have double checked this example , it work fine in my side , could you confirm that the at command you entered is a pure text character. right ?

The below is the test result in my side , any more issue , you can sent to " stephen.li@quectel.com"

+QEXAMPLE: 0
OK
at+QEXAMPLE=1

OK
at+QEXAMPLE?

+QEXAMPLE: 1
OK
AT+QEXAMPLE

OK
at+QEXAMPLE?

+QEXAMPLE: 1
OK

Test

i missed device startup wait code…

/* wait 5sec for device startup */
qapi_Timer_Sleep(5, QAPI_TIMER_UNIT_SEC, true);

added wait code. it works. !!

thank you

i missed device startup wait code…

/* wait 5sec for device startup */
qapi_Timer_Sleep(5, QAPI_TIMER_UNIT_SEC, true);

added wait code. it works. !!

thank you

BTW: my base template is not required … is as “hello world”
you can follow (copy/paste) Quectel examples - must work (maybe with small fixes)

The ThreadX “main” entry is
int TXM_MODULE_THREAD_ENTRY(void) { … }