Exploring Connectivity Options for AWS IoT: Do We Need IoT SIM Cards?

Hi,

      I am currently working with the nRF9160DK board, using SDK version 2.5.1, and I have encountered an issue regarding connectivity to the AWS IoT cloud.

I have successfully connected my board to MQTT and have been able to publish and subscribe to topics using a regular SIM card with a data pack,so I confirmed that internet connection is done. However, when attempting to connect to AWS IoT using the same SIM card in the provided sample code, I am experiencing connectivity issues.

I have ensured that I configured all necessary parameters in the sample code given, including:

  • CONFIG_AWS_IOT_BROKER_HOST_NAME
  • CONFIG_MQTT_HELPER_SEC_TAG
  • CONFIG_AWS_IOT_CLIENT_ID_STATIC

Despite this, I am not receiving the expected output,
After flashing the sample, we can receive those two lines in the image. I'm not getting the remaining lines.


and I'm uncertain whether the SIM card compatibility could be a factor, or if there might be an issue with my code implementation.

Could you please provide guidance on whether an IoT-specific SIM card (LTE-M or NB-IoT) is required for connecting to AWS IoT? Additionally, I would appreciate any insights or troubleshooting tips you may have regarding this connectivity issue.

Thank you in advance for your assistance.

  • Hi,

    Did you run unmodified AWS IoT sample?

    Can you provide full log which you get when running the sample?

    Best regards,
    Dejan

  • Hi,
        Yeah i used unmodified aws iot sample but just added few things like certificate related changes like below

    • CONFIG_AWS_IOT_BROKER_HOST_NAME
    • CONFIG_MQTT_HELPER_SEC_TAG
    • CONFIG_AWS_IOT_CLIENT_ID_STATIC
      my output

      my sample code main.c
      /*
       * Copyright (c) 2020 Nordic Semiconductor ASA
       *
       * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
       */
      
      #include <zephyr/kernel.h>
      #include <zephyr/sys/reboot.h>
      #include <zephyr/dfu/mcuboot.h>
      #include <zephyr/logging/log.h>
      #include <zephyr/logging/log_ctrl.h>
      #include <zephyr/net/conn_mgr_connectivity.h>
      #include <zephyr/net/conn_mgr_monitor.h>
      #include <net/aws_iot.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <hw_id.h>
      #include <modem/modem_info.h>
      
      #include "json_payload.h"
      
      /* Register log module */
      LOG_MODULE_REGISTER(aws_iot_sample, CONFIG_AWS_IOT_SAMPLE_LOG_LEVEL);
      
      /* Macros used to subscribe to specific Zephyr NET management events. */
      #define L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED)
      #define CONN_LAYER_EVENT_MASK (NET_EVENT_CONN_IF_FATAL_ERROR)
      
      #define MODEM_FIRMWARE_VERSION_SIZE_MAX 50
      
      /* Macro called upon a fatal error, reboots the device. */
      #define FATAL_ERROR()					\
      	LOG_ERR("Fatal error! Rebooting the device.");	\
      	LOG_PANIC();					\
      	IF_ENABLED(CONFIG_REBOOT, (sys_reboot(0)))
      
      /* Zephyr NET management event callback structures. */
      static struct net_mgmt_event_callback l4_cb;
      static struct net_mgmt_event_callback conn_cb;
      
      /* Forward declarations. */
      static void shadow_update_work_fn(struct k_work *work);
      static void connect_work_fn(struct k_work *work);
      static void aws_iot_event_handler(const struct aws_iot_evt *const evt);
      
      /* Work items used to control some aspects of the sample. */
      static K_WORK_DELAYABLE_DEFINE(shadow_update_work, shadow_update_work_fn);
      static K_WORK_DELAYABLE_DEFINE(connect_work, connect_work_fn);
      
      /* Static functions */
      
      static int app_topics_subscribe(void)
      {
      	int err;
      	static const char custom_topic[] = "iot/example";
      	static const char custom_topic_2[] = "iot/example_2";
      
      	const struct aws_iot_topic_data topics_list[CONFIG_AWS_IOT_APP_SUBSCRIPTION_LIST_COUNT] = {
      		[0].str = custom_topic,
      		[0].len = strlen(custom_topic),
      		[1].str = custom_topic_2,
      		[1].len = strlen(custom_topic_2)
      	};
      
      	err = aws_iot_subscription_topics_add(topics_list, ARRAY_SIZE(topics_list));
      	if (err) {
      		LOG_ERR("aws_iot_subscription_topics_add, error: %d", err);
      		FATAL_ERROR();
      		return err;
      	}
      
      	return 0;
      }
      
      static int aws_iot_client_init(void)
      {
      	int err;
      	struct aws_iot_config config = { 0 };
      
      #if defined(CONFIG_AWS_IOT_SAMPLE_DEVICE_ID_USE_HW_ID)
      	char device_id[HW_ID_LEN] = { 0 };
      
      	/* Get unique hardware ID, can be used as AWS IoT MQTT broker device/client ID. */
      	err = hw_id_get(device_id, ARRAY_SIZE(device_id));
      	if (err) {
      		LOG_ERR("Failed to retrieve device ID, error: %d", err);
      		FATAL_ERROR();
      		return err;
      	}
      
      	/* To use HW ID as MQTT device/client ID set the CONFIG_AWS_IOT_CLIENT_ID_APP option.
      	 * Otherwise the ID set by CONFIG_AWS_IOT_CLIENT_ID_STATIC is used.
      	 */
      	config.client_id = device_id;
      	config.client_id_len = strlen(device_id);
      
      	LOG_INF("Hardware ID: %s", device_id);
      #endif /* CONFIG_AWS_IOT_SAMPLE_DEVICE_ID_USE_HW_ID */
      
      	err = aws_iot_init(&config, aws_iot_event_handler);
      	if (err) {
      		LOG_ERR("AWS IoT library could not be initialized, error: %d", err);
      		FATAL_ERROR();
      		return err;
      	}
      
      	/* Add application specific non-shadow topics to the AWS IoT library.
      	 * These topics will be subscribed to when connecting to the broker.
      	 */
      	err = app_topics_subscribe();
      	if (err) {
      		LOG_ERR("Adding application specific topics failed, error: %d", err);
      		FATAL_ERROR();
      		return err;
      	}
      
      	return 0;
      }
      
      /* System Workqueue handlers. */
      
      static void shadow_update_work_fn(struct k_work *work)
      {
      	int err;
      	char message[CONFIG_AWS_IOT_SAMPLE_JSON_MESSAGE_SIZE_MAX] = "NRF Device";
      	struct payload payload = {
      		.state.reported.uptime = k_uptime_get(),
      		.state.reported.app_version = CONFIG_AWS_IOT_SAMPLE_APP_VERSION,
      	};
      	struct aws_iot_data tx_data = {
      		.qos = MQTT_QOS_0_AT_MOST_ONCE,
      		.topic.type = AWS_IOT_SHADOW_TOPIC_UPDATE,
      	};
      
      	if (IS_ENABLED(CONFIG_MODEM_INFO)) {
      		char modem_version_temp[MODEM_FIRMWARE_VERSION_SIZE_MAX];
      
      		err = modem_info_get_fw_version(modem_version_temp,
      						ARRAY_SIZE(modem_version_temp));
      		if (err) {
      			LOG_ERR("modem_info_get_fw_version, error: %d", err);
      			FATAL_ERROR();
      			return;
      		}
      
      		payload.state.reported.modem_version = modem_version_temp;
      	}
      
      	err = json_payload_construct(message, sizeof(message), &payload);
      	if (err) {
      		LOG_ERR("json_payload_construct, error: %d", err);
      		FATAL_ERROR();
      		return;
      	}
      
      	tx_data.ptr = message;
      	tx_data.len = strlen(message);
      
      	LOG_INF("Publishing message: %s to AWS IoT shadow", message);
      
      	err = aws_iot_send(&tx_data);
      	if (err) {
      		LOG_ERR("aws_iot_send, error: %d", err);
      		FATAL_ERROR();
      		return;
      	}
      
      	(void)k_work_reschedule(&shadow_update_work,
      				K_SECONDS(CONFIG_AWS_IOT_SAMPLE_PUBLICATION_INTERVAL_SECONDS));
      }
      
      static void connect_work_fn(struct k_work *work)
      {
      	int err;
      
      	LOG_INF("Connecting to AWS IoT");
      
      	err = aws_iot_connect(NULL);
      	if (err) {
      		LOG_ERR("aws_iot_connect, error: %d", err);
      	}
      
      	LOG_INF("Next connection retry in %d seconds",
      		CONFIG_AWS_IOT_SAMPLE_CONNECTION_RETRY_TIMEOUT_SECONDS);
      
      	(void)k_work_reschedule(&connect_work,
      				K_SECONDS(CONFIG_AWS_IOT_SAMPLE_CONNECTION_RETRY_TIMEOUT_SECONDS));
      }
      
      /* Functions that are executed on specific connection-related events. */
      
      static void on_aws_iot_evt_connected(const struct aws_iot_evt *const evt)
      {
      	(void)k_work_cancel_delayable(&connect_work);
      
      	/* If persistent session is enabled, the AWS IoT library will not subscribe to any topics.
      	 * Topics from the last session will be used.
      	 */
      	if (evt->data.persistent_session) {
      		LOG_WRN("Persistent session is enabled, using subscriptions "
      			"from the previous session");
      	}
      
      	/* Mark image as working to avoid reverting to the former image after a reboot. */
      #if defined(CONFIG_BOOTLOADER_MCUBOOT)
      	boot_write_img_confirmed();
      #endif
      
      	/* Start sequential updates to AWS IoT. */
      	(void)k_work_reschedule(&shadow_update_work, K_NO_WAIT);
      }
      
      static void on_aws_iot_evt_disconnected(void)
      {
      	(void)k_work_cancel_delayable(&shadow_update_work);
      	(void)k_work_reschedule(&connect_work, K_SECONDS(5));
      }
      
      static void on_aws_iot_evt_fota_done(const struct aws_iot_evt *const evt)
      {
      	int err;
      
      	/* Tear down MQTT connection. */
      	(void)aws_iot_disconnect();
      	(void)k_work_cancel_delayable(&connect_work);
      
      	/* If modem FOTA has been carried out, the modem needs to be reinitialized.
      	 * This is carried out by bringing the network interface down/up.
      	 */
      	if (evt->data.image & DFU_TARGET_IMAGE_TYPE_ANY_MODEM) {
      		LOG_INF("Modem FOTA done, reinitializing the modem");
      
      		err = conn_mgr_all_if_down(true);
      		if (err) {
      			LOG_ERR("conn_mgr_all_if_down, error: %d", err);
      			FATAL_ERROR();
      			return;
      		}
      
      		err = conn_mgr_all_if_up(true);
      		if (err) {
      			LOG_ERR("conn_mgr_all_if_up, error: %d", err);
      			FATAL_ERROR();
      			return;
      		}
      
      	} else if (evt->data.image & DFU_TARGET_IMAGE_TYPE_ANY_APPLICATION) {
      		LOG_INF("Application FOTA done, rebooting");
      		IF_ENABLED(CONFIG_REBOOT, (sys_reboot(0)));
      	} else {
      		LOG_WRN("Unexpected FOTA image type");
      	}
      }
      
      static void on_net_event_l4_connected(void)
      {
      	(void)k_work_reschedule(&connect_work, K_SECONDS(5));
      }
      
      static void on_net_event_l4_disconnected(void)
      {
      	(void)aws_iot_disconnect();
      	(void)k_work_cancel_delayable(&connect_work);
      	(void)k_work_cancel_delayable(&shadow_update_work);
      }
      
      /* Event handlers */
      
      static void aws_iot_event_handler(const struct aws_iot_evt *const evt)
      {
      	switch (evt->type) {
      	case AWS_IOT_EVT_CONNECTING:
      		LOG_INF("AWS_IOT_EVT_CONNECTING");
      		break;
      	case AWS_IOT_EVT_CONNECTED:
      		LOG_INF("AWS_IOT_EVT_CONNECTED");
      		on_aws_iot_evt_connected(evt);
      		break;
      	case AWS_IOT_EVT_READY:
      		LOG_INF("AWS_IOT_EVT_READY");
      		break;
      	case AWS_IOT_EVT_DISCONNECTED:
      		LOG_INF("AWS_IOT_EVT_DISCONNECTED");
      		on_aws_iot_evt_disconnected();
      		break;
      	case AWS_IOT_EVT_DATA_RECEIVED:
      		LOG_INF("AWS_IOT_EVT_DATA_RECEIVED");
      
      		LOG_INF("Received message: \"%.*s\" on topic: \"%.*s\"", evt->data.msg.len,
      									 evt->data.msg.ptr,
      									 evt->data.msg.topic.len,
      									 evt->data.msg.topic.str);
      		break;
      	case AWS_IOT_EVT_PUBACK:
      		LOG_INF("AWS_IOT_EVT_PUBACK, message ID: %d", evt->data.message_id);
      		break;
      	case AWS_IOT_EVT_PINGRESP:
      		LOG_INF("AWS_IOT_EVT_PINGRESP");
      		break;
      	case AWS_IOT_EVT_FOTA_START:
      		LOG_INF("AWS_IOT_EVT_FOTA_START");
      		break;
      	case AWS_IOT_EVT_FOTA_ERASE_PENDING:
      		LOG_INF("AWS_IOT_EVT_FOTA_ERASE_PENDING");
      		break;
      	case AWS_IOT_EVT_FOTA_ERASE_DONE:
      		LOG_INF("AWS_FOTA_EVT_ERASE_DONE");
      		break;
      	case AWS_IOT_EVT_FOTA_DONE:
      		LOG_INF("AWS_IOT_EVT_FOTA_DONE");
      		on_aws_iot_evt_fota_done(evt);
      		break;
      	case AWS_IOT_EVT_FOTA_DL_PROGRESS:
      		LOG_INF("AWS_IOT_EVT_FOTA_DL_PROGRESS, (%d%%)", evt->data.fota_progress);
      		break;
      	case AWS_IOT_EVT_ERROR:
      		LOG_INF("AWS_IOT_EVT_ERROR, %d", evt->data.err);
      		break;
      	case AWS_IOT_EVT_FOTA_ERROR:
      		LOG_INF("AWS_IOT_EVT_FOTA_ERROR");
      		break;
      	default:
      		LOG_WRN("Unknown AWS IoT event type: %d", evt->type);
      		break;
      	}
      }
      
      static void l4_event_handler(struct net_mgmt_event_callback *cb,
      			     uint32_t event,
      			     struct net_if *iface)
      {
      	switch (event) {
      	case NET_EVENT_L4_CONNECTED:
      		LOG_INF("Network connectivity established");
      		on_net_event_l4_connected();
      		break;
      	case NET_EVENT_L4_DISCONNECTED:
      		LOG_INF("Network connectivity lost");
      		on_net_event_l4_disconnected();
      		break;
      	default:
      		/* Don't care */
      		return;
      	}
      }
      
      static void connectivity_event_handler(struct net_mgmt_event_callback *cb,
      				       uint32_t event,
      				       struct net_if *iface)
      {
      	if (event == NET_EVENT_CONN_IF_FATAL_ERROR) {
      		LOG_ERR("NET_EVENT_CONN_IF_FATAL_ERROR");
      		FATAL_ERROR();
      		return;
      	}
      }
      
      int main(void)
      {
      	LOG_INF("The AWS IoT sample started, version: %s", CONFIG_AWS_IOT_SAMPLE_APP_VERSION);
      
      	int err;
      
      	/* Setup handler for Zephyr NET Connection Manager events. */
      	net_mgmt_init_event_callback(&l4_cb, l4_event_handler, L4_EVENT_MASK);
      	net_mgmt_add_event_callback(&l4_cb);
      
      	/* Setup handler for Zephyr NET Connection Manager Connectivity layer. */
      	net_mgmt_init_event_callback(&conn_cb, connectivity_event_handler, CONN_LAYER_EVENT_MASK);
      	net_mgmt_add_event_callback(&conn_cb);
      
      	/* Connecting to the configured connectivity layer.
      	 * Wi-Fi or LTE depending on the board that the sample was built for.
      	 */
      	LOG_INF("Bringing network interface up and connecting to the network");
      
      	err = conn_mgr_all_if_up(true);
      	if (err) {
      		LOG_ERR("conn_mgr_all_if_up, error: %d", err);
      		FATAL_ERROR();
      		return err;
      	}
      
      	err = aws_iot_client_init();
      	if (err) {
      		LOG_ERR("aws_iot_client_init, error: %d", err);
      		FATAL_ERROR();
      		return err;
      	}
      
      	/* Resend connection status if the sample is built for QEMU x86.
      	 * This is necessary because the network interface is automatically brought up
      	 * at SYS_INIT() before main() is called.
      	 * This means that NET_EVENT_L4_CONNECTED fires before the
      	 * appropriate handler l4_event_handler() is registered.
      	 */
      	if (IS_ENABLED(CONFIG_BOARD_QEMU_X86)) {
      		conn_mgr_mon_resend_status();
      	}
      
      	return 0;
      }
      


    and prj.conf

    # Copyright (c) 2020 Nordic Semiconductor ASA
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    
    # General
    CONFIG_LOG=y
    CONFIG_LOG_BUFFER_SIZE=2048
    CONFIG_HW_ID_LIBRARY=y
    CONFIG_ASSERT=y
    CONFIG_JSON_LIBRARY=y
    
    # Heap and stacks
    CONFIG_HEAP_MEM_POOL_SIZE=8192
    CONFIG_MAIN_STACK_SIZE=4096
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
    
    # Network
    CONFIG_NETWORKING=y
    CONFIG_NET_NATIVE=y
    CONFIG_NET_IPV4=y
    CONFIG_NET_CONNECTION_MANAGER=y
    
    # AWS IoT library
    CONFIG_AWS_IOT_CLIENT_ID_MAX_LEN=50
    CONFIG_AWS_IOT=y
    CONFIG_AWS_IOT_CLIENT_ID_STATIC="iotconsole-0fa49f1f-46d5-4d99-8753-fe7983a9352f"
    CONFIG_AWS_IOT_BROKER_HOST_NAME="a3dnd3kgq72p80-ats.iot.us-east-2.amazonaws.com"
    CONFIG_AWS_IOT_SEC_TAG=78534251
    CONFIG_AWS_IOT_APP_SUBSCRIPTION_LIST_COUNT=2
    CONFIG_AWS_IOT_TOPIC_UPDATE_DELTA_SUBSCRIBE=y
    CONFIG_AWS_IOT_TOPIC_GET_ACCEPTED_SUBSCRIBE=y
    CONFIG_AWS_IOT_TOPIC_GET_REJECTED_SUBSCRIBE=y
    CONFIG_AWS_IOT_LAST_WILL=y
    
    # MQTT - Maximum MQTT keepalive timeout specified by AWS IoT Core
    CONFIG_MQTT_KEEPALIVE=1200
    CONFIG_MQTT_CLEAN_SESSION=y
    

    and additionally i added like this my certificates here is it right or wrong way.
    where could be the issue ?


    If sim not problem is it problem from certificate side or anything else?

  • Hi,

    Which SIM card do you use? Which network operator (and in which country) does your device connect to?

    How did you generate your certificates?

    Best regards,
    Dejan

  • Hi,

    I'm using an AT&T SIM CARD in the US, in East Peoria. Actually, the certificates weren't set up by me; they were configured by the application team. They created this AWS account for publishing and subscribing from the application side, so I didn't do anything with the AWS certificates. They just shared the related information such as client ID, endpoint, CA certificates, client certificate, and private key. I believe this should be sufficient. Is there anything else we need to do separately to connect our nrf9160 board? If so, could you please share any YouTube videos or documents that we need to follow to create certificates specifically for the nrf9160 DK board?

  • Hi,

    Could you provide application log after you add CONFIG_LTE_LINK_CONTROL_LOG_LEVEL_DBG=y to your application's configuration file?

    Best regards,
    Dejan

Related