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

How to code one-shot mqtt publish function?

I'm trying to make a one-shot mqtt function. The process is below

- connect
- publish
- disconnect

Then I coded like below. I show only the core code.

static u8_t payload_buf[CONFIG_MQTT_PAYLOAD_BUFFER_SIZE];

/**@brief Initialize the file descriptor structure used by poll.
 */
static int fds_init(struct mqtt_client *c)
{
	if (c->transport.type == MQTT_TRANSPORT_NON_SECURE) {
		fds.fd = c->transport.tcp.sock;
	} else {
#if defined(CONFIG_MQTT_LIB_TLS)
		fds.fd = c->transport.tls.sock;
#else
		return -ENOTSUP;
#endif
	}

	fds.events = POLLIN;

	return 0;
}

int8_t poll_and_check_rcv_data(u32_t interval_msec){
	int8_t err = poll(&fds, 1, interval_msec); // Check if any data comes through LTE-M. When it is waiting for an incoming data, it sleeps
	if (err < 0) {
		SEGGER_RTT_printf(0,"ERROR: poll %d\n", errno);
		return -1;
	}

	/* Check if data is received through LTE-M */
	if ((fds.revents & POLLIN) == POLLIN) { // If get data
		err = mqtt_input(&client);
		if (err < 0) {
			SEGGER_RTT_printf(0,"ERROR: poll %d\n", errno);
			return -1;
		}
	}
	if ((fds.revents & POLLERR) == POLLERR) {
		SEGGER_RTT_printf(0,"POLLERR\n");
		return -1;
	}
	if ((fds.revents & POLLNVAL) == POLLNVAL) {
		SEGGER_RTT_printf(0,"POLLNVAL\n");
		return -1;
	}

	return 0;
}


int8_t send_one_shot_mqtt_msg(enum mqtt_qos qos, u8_t *data, size_t len, char *topic){
	int err = 0;

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

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

	err = poll_and_check_rcv_data(K_SECONDS(10)); // Wait for CONNACK
	if (err != 0) {
		SEGGER_RTT_printf(0,"ERROR: poll_and_check_rcv_data %d\n", err);
		return -1;
	}

	err = data_publish(&client, qos, data, len, topic);
	if(err < 0){
		SEGGER_RTT_printf(0,"fail sending reset message\n");
	}
	
	err = poll_and_check_rcv_data(K_SECONDS(5));
	if (err != 0) {
		SEGGER_RTT_printf(0,"ERROR: poll_and_check_rcv_data %d\n", err);
		return -1;
	}

	err = mqtt_disconnect(&client);
	if (err) {
		SEGGER_RTT_printf(0,"Could not disconnect MQTT client. Error: %d\n", err);
		return -1;
	}
	
	err = poll_and_check_rcv_data(K_SECONDS(3));
	if (err != 0) {
		SEGGER_RTT_printf(0,"ERROR: poll_and_check_rcv_data %d\n", err);
		return -1;
	}

	return 0;
}

void main(void)
{
	/* LTE set up*/
#if defined(CONFIG_PROVISION_CERTIFICATES)
	provision_certificates();
#endif
	modem_configure();
	
	while (1) {
	    k_sleep(K_SECONDS(60));
	    snprintf(payload_buf, 15, "{\"bat\":%d}", 10);
    	err = send_one_shot_mqtt_msg(MQTT_QOS_1_AT_LEAST_ONCE, payload_buf, strlen(payload_buf), CONFIG_MQTT_PUB_TOPIC);
    	if (err != 0){
    		SEGGER_RTT_printf(0,"Error: send_one_shot_mqtt_msg: %u\n", err);
    		return -1;
    	}
	}
}

Do I have to execute fds_init in send_one_shot_mqtt_msg everytime it publish a message on MQTT?

Should I omit fds_init? 

I really don't understand what fds_init does. 

I would appreciate it if you help me.

Parents Reply Children
Related