This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to to set a keep alive value of MQTT while eDRX is enabled in nRF9160?

I want to set a keep alive value of MQTT while eDRX is enabled, but it doesn't work well. Any advice?

Environment
- hardware: nRF9160 DK 0.8.2
- firmware: 0.7.0-29.alpha
- nrf ver: 0.4.0
- LTE-M
- eDRX enable
- mqtt_simple works fine with mosquitto MQTT broker
- project based on mqtt_simple
- antenna power is fine
- eDRX service is available here

AT+CEDRXS?
OK
AT+CEDRXS=1,4,"1000"

I added MQTT_KEEPALIVE param to Kconfig and CONF_MQTT_KEEPALIVE param to pro.conf
I've tested several conditions
[condition]
- CONFIG_LTE_EDRX_REQ_VALUE="0110" in prj.conf // 327.68 sec interval
CONF_MQTT_KEEPALIVE=300 in prj.conf
[result]
eDRX doesn't work properly. When I send a message to a MQTT broker, the DK receives it right after that. There should be a delay due to the eDRX.

[condition]
CONFIG_LTE_EDRX_REQ_VALUE="0110" in prj.conf // 327.68 sec interval
CONF_MQTT_KEEPALIVE=400 in prj.conf
[result]
The DK does not receive any message after 360sec followed by disconnection.

This is the whole project.

<Kconfig>
menu "MQTT simple sample"
config MQTT_PUB_TOPIC
	string "MQTT publish topic"
	default "my/publish/topic"

config MQTT_SUB_TOPIC
	string "MQTT subscribe topic"
	default "my/subscribe/topic"

config MQTT_CLIENT_ID
	string "MQTT Client ID"
	default "my-client-id"

config MQTT_BROKER_HOSTNAME
	string "MQTT broker hostname"
	default "iot.eclipse.org"

config MQTT_BROKER_PORT
	int "MQTT broker port"
	default 1883

config MQTT_MESSAGE_BUFFER_SIZE
	int ""
	default 128

config MQTT_PAYLOAD_BUFFER_SIZE
	int ""
	default 128

config MQTT_KEEPALIVE
	int ""
	default 60

endmenu

menu "Zephyr Kernel"
source "$ZEPHYR_BASE/Kconfig.zephyr"
endmenu

<prj.conf>

# General config
CONFIG_TEST_RANDOM_GENERATOR=y

# Networking
CONFIG_NETWORKING=y
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y

# LTE link control
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_NETWORK_MODE_LTE_M=y
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n
# CONFIG_LTE_EDRX_REQ_ACTT_TYPE="4"
CONFIG_LTE_EDRX_REQ=y
CONFIG_LTE_EDRX_REQ_VALUE="0110"
# 0100 81.92sec
# 0101 163.84sec
# 0110 327.68sec
# 0111 655.36sec

# LTE link control
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n

# BSD library
CONFIG_BSD_LIBRARY=y

# AT Host
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_AT_HOST_LIBRARY=y

# MQTT
CONFIG_MQTT_LIB=y
CONFIG_MQTT_LIB_TLS=n

# Appliaction
CONFIG_MQTT_PUB_TOPIC="myPubTopic"
CONFIG_MQTT_SUB_TOPIC="mySubTopic"
CONFIG_MQTT_CLIENT_ID="myClientID"
CONFIG_MQTT_BROKER_HOSTNAME="xxxxxxxxxx.com"
CONFIG_MQTT_BROKER_PORT=1883
CONFIG_MQTT_KEEPALIVE=300 # ADD here

# Main thread
CONFIG_MAIN_THREAD_PRIORITY=7
CONFIG_MAIN_STACK_SIZE=4096

CONFIG_HEAP_MEM_POOL_SIZE=1024

<main.c>

#include <zephyr.h>
#include <stdio.h>
#include <uart.h>
#include <string.h>

#include <net/mqtt.h>
#include <net/socket.h>
#include <lte_lc.h>

#define MQTT_USERNAME "username"
#define MQTT_PASSWORD "password"
.
.
.

/**@brief Initialize the MQTT client structure
 */
static void client_init(struct mqtt_client *client)
{
	mqtt_client_init(client);

	broker_init();

    /* Add from here */
    static struct mqtt_utf8 password;
	static struct mqtt_utf8 user_name;

	password.utf8 = (u8_t *)MQTT_PASSWORD;
	password.size = strlen(MQTT_PASSWORD);
	user_name.utf8 = (u8_t *)MQTT_USERNAME;
	user_name.size = strlen(MQTT_USERNAME);
    /* to here */

	/* MQTT client configuration */
	client->broker = &broker;
	client->evt_cb = mqtt_evt_handler;
	client->client_id.utf8 = (u8_t *)CONFIG_MQTT_CLIENT_ID;
	client->client_id.size = strlen(CONFIG_MQTT_CLIENT_ID);
	client->password = &password; // Add here
	client->user_name = &user_name; // Add here
	client->protocol_version = MQTT_VERSION_3_1_0; // originally MQTT_VERSION_3_1_1

	/* MQTT buffers configuration */
	client->rx_buf = rx_buffer;
	client->rx_buf_size = sizeof(rx_buffer);
	client->tx_buf = tx_buffer;
	client->tx_buf_size = sizeof(tx_buffer);

	/* MQTT transport configuration */
	client->transport.type = MQTT_TRANSPORT_NON_SECURE;
}

.
.

void main(void)
{
	int err;

	printk("The MQTT simple sample started\n");

	modem_configure();

    /* ADD here */
    err = lte_lc_edrx_req(true);
    if (err) {
        printk("ERROR: set edrx %d\n", err);
        return;
    }
    /* ADD here */

	client_init(&client);

	err = mqtt_connect(&client);
	if (err != 0) {
		printk("ERROR: mqtt_connect %d\n", err);
		return;
	}

	err = fds_init(&client);
	if (err != 0) {
		printk("ERROR: fds_init %d\n", err);
		return;
	}

	while (1) {
		err = poll(&fds, 1, K_SECONDS(CONFIG_MQTT_KEEPALIVE)); 
		if (err < 0) {
			printk("ERROR: poll %d\n", errno);
			break;
		}

        err = mqtt_live(&client);
		if (err != 0) {
			printk("ERROR: mqtt_live %d\n", err);
			break;
		}

		if ((fds.revents & POLLIN) == POLLIN) {
			err = mqtt_input(&client); // if a publish event comes, mqtt_evt_handler is called here
			if (err != 0) {
				printk("ERROR: mqtt_input %d\n", err);
				break;
			}
		}

		if ((fds.revents & POLLERR) == POLLERR) {
			printk("POLLERR\n");
			break;
		}

		if ((fds.revents & POLLNVAL) == POLLNVAL) {
			printk("POLLNVAL\n");
			break;
		}
	}

}

This is a test condition.
Ideally, I want to set a longer keepalive value, like 1200(sec) to decrease power consumption.
- keep alive of MQTT: 1200 sec
- eDRX interval value: 655 sec

I have been struggling with this issue more than two weeks, but I don't really get the eDRX behavior. Any advice?

Related