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

Best way to organize firmware to periodically update AWS IoT Server with nRF9160

Hello, guys.

In our current project, we need to periodically update AWS IoT Server with the data from local sensors. So far, thanks to the cloud_client example and your documentation from here, we were able to connect to AWS IoT server and transfer a message. Now, unlike cloud_client example which is constantly connected to the cloud thanks to the following code structure within the main loop:

connect:
	err = cloud_connect(cloud_backend);
	if (err) {
		printk("cloud_connect, error: %d\n", err);
	}

	struct pollfd fds[] = {
		{
			.fd = cloud_backend->config->socket,
			.events = POLLIN
		}
	};

	while (true) {
		/* The timeout is set to (keepalive / 3), so that the worst case
		 * time between two messages from device to broker is
		 * ((4 / 3) * keepalive + connection overhead), which is within
		 * MQTT specification of (1.5 * keepalive) before the broker
		 * must close the connection.
		 */
		err = poll(fds, ARRAY_SIZE(fds),
			K_SECONDS(CONFIG_MQTT_KEEPALIVE / 3));

		if (err < 0) {
			printk("poll() returned an error: %d\n", err);
			continue;
		}

		if (err == 0) {
			cloud_ping(cloud_backend);
			continue;
		}

		if ((fds[0].revents & POLLIN) == POLLIN) {
			cloud_input(cloud_backend);
		}

		if ((fds[0].revents & POLLNVAL) == POLLNVAL) {
			printk("Socket error: POLLNVAL\n");
			printk("The cloud socket was unexpectedly closed.\n");
			return;
		}

		if ((fds[0].revents & POLLHUP) == POLLHUP) {
			printk("Socket error: POLLHUP\n");
			printk("Connection was closed by the cloud.\n");
			return;
		}

		if ((fds[0].revents & POLLERR) == POLLERR) {
			printk("Socket error: POLLERR\n");
			printk("Cloud connection was unexpectedly closed.\n");
			return;
		}
	}
	cloud_disconnect(cloud_backend);
	goto connect;

we would like our device to be in sleep mode, to wake up periodically, connect to the cloud and receive/transmit messages. We used timers to implement non-trivial task execution on periodic basis. The approach is taken from here. Since the required work cannot be done at interrupt level, the timer’s expiry function submits a work item to the system workqueue, whose thread performs the work:

void periodic_timer_handler(struct k_timer *dummy)
{
    k_delayed_work_submit(&bintech_work, K_NO_WAIT);
}

Is this good approach? Should we use another periodic timer to keep connection alive as long as we need it (i.e. to simulate

while (true)
) loop from above?

Do you see any better way to implement this periodic Server update activities?

What we noticed so far is that we have a problem to execute configure_modem() function if we move it to the system workqueue with k_delayed_work_submit(). If we run a function from the main(), however, it executes successfully. Is there anything we are missing here?

Thanks for your time and efforts!

Sincerely,

Bojan.

Parents
  • Hello,

     

    What we noticed so far is that we have a problem to execute configure_modem() function if we move it to the system workqueue with k_delayed_work_submit(). If we run a function from the main(), however, it executes successfully. Is there anything we are missing here?

     Have a look at the post here. In short, you should not run configure_modem() from the system work queue since it uses the CFUN command that blocks for several seconds.

Reply
  • Hello,

     

    What we noticed so far is that we have a problem to execute configure_modem() function if we move it to the system workqueue with k_delayed_work_submit(). If we run a function from the main(), however, it executes successfully. Is there anything we are missing here?

     Have a look at the post here. In short, you should not run configure_modem() from the system work queue since it uses the CFUN command that blocks for several seconds.

Children
Related