Provisiong a 9160 on our AWS VPC

We're attempting to provision one of our nRF9160-based IoT devices to our AWS VPC.

We're following this procedure:

Provisioning our eDude on AWS

Step 1: Provision the IoT Device (nRF9160)

  1. Install Required Software

Ensure your development environment is set up with:

  • nRF Connect for Desktop (for flashing firmware)
  • nRF SDK (nRF Connect SDK) – includes Zephyr RTOS
  • AWS IoT SDK for C (optional)
  • Segger Embedded Studio or VS Code with Zephyr extension (for development)
  1. Prepare Device Credentials

You'll need to securely load AWS IoT credentials onto your nRF9160:

  1. Obtain the AWS IoT Core Certificates
    • certificate.pem.crt
    • private.pem.key
    • AmazonRootCA1.pem
    • Download the following from AWS IoT Core:
    • Convert to a format suitable for your embedded system (if needed).
  2. Flash Certificates to the Device
    • Store the certificates in non-volatile storage (e.g., CONFIG_NVS in Zephyr).
    • Example approach using Zephyr's LittleFS or Flash FS:
    • #define CERTIFICATE_PATH "/certs/device_cert.pem"
    • #define PRIVATE_KEY_PATH "/certs/private_key.pem"
    • #define ROOT_CA_PATH "/certs/AmazonRootCA1.pem"
    • If using modem security credentials, provision certificates via AT commands:
    • AT%CMNG=0,16842753,0,"-----BEGIN CERTIFICATE-----..."
    • AT%CMNG=0,16842754,0,"-----BEGIN RSA PRIVATE KEY-----..."
    • AT%CMNG=0,16842755,0,"-----BEGIN CERTIFICATE-----..."
    • Verify storage using:  AT%CMNG=1
  1. Configure nRF9160 for Secure MQTT Connection

Modify your Zephyr application’s prj.conf:

CONFIG_MQTT_LIB=y

CONFIG_MQTT_LIB_TLS=y

CONFIG_NET_SOCKETS_OFFLOAD=y

CONFIG_NRF_MODEM_LIB=y

CONFIG_NRF_CLOUD_MQTT=y

Set up AWS endpoint and credentials in Kconfig:

CONFIG_AWS_IOT_BROKER_HOST_NAME= “a3iodo1wh9ldbz-ats.iot.us-west-2.amazonaws.com"

CONFIG_AWS_IOT_SEC_TAG=12345

  • Replace "your-endpoint.amazonaws.com" with your AWS IoT Endpoint (found under IoT Core → Settings).
  • Set up AWS IoT security tag for modem storage (12345 is just an example).

Step 2: Connect nRF9160 to AWS IoT Core

Now, let's establish an MQTT connection and test message exchange.

  1. Initialize LTE & Connect to AWS IoT

Modify your Zephyr application’s main file (main.c):

#include <zephyr.h>

#include <net/mqtt.h>

#include <modem/lte_lc.h>

#include <modem/modem_key_mgmt.h>

#include <logging/log.h>

 

LOG_MODULE_REGISTER(my_mqtt_app, LOG_LEVEL_INF);

 

#define AWS_BROKER #define AWS_BROKER "a3iodo1wh9ldbz-ats.iot.us-west-2.amazonaws.com"

#define AWS_PORT 8883

#define MQTT_CLIENT_ID "nRF9160_device"

 

// MQTT buffers

static uint8_t rx_buffer[512];

static uint8_t tx_buffer[512];

 

static struct mqtt_client client;

static struct sockaddr_storage broker;

 

// Callback for MQTT events

void mqtt_event_handler(struct mqtt_client *client, const struct mqtt_evt *evt) {

    switch (evt->type) {

        case MQTT_EVT_CONNACK:

            LOG_INF("MQTT connected");

            break;

        case MQTT_EVT_DISCONNECT:

            LOG_INF("MQTT disconnected");

            break;

        case MQTT_EVT_PUBLISH:

            LOG_INF("Message received: %s", evt->param.publish.message.payload.data);

            break;

        default:

            break;

    }

}

 

// Function to configure MQTT client

void mqtt_init(void) {

    struct sockaddr_in *broker4 = (struct sockaddr_in *)&broker;

    broker4->sin_family = AF_INET;

    broker4->sin_port = htons(AWS_PORT);

    net_addr_pton(AF_INET, AWS_BROKER, &broker4->sin_addr);

 

    mqtt_client_init(&client);

    client.broker = &broker;

    client.evt_cb = mqtt_event_handler;

    client.client_id.utf8 = MQTT_CLIENT_ID;

    client.client_id.size = strlen(MQTT_CLIENT_ID);

    client.transport.type = MQTT_TRANSPORT_SECURE;

    client.rx_buf = rx_buffer;

    client.rx_buf_size = sizeof(rx_buffer);

    client.tx_buf = tx_buffer;

    client.tx_buf_size = sizeof(tx_buffer);

}

 

// Function to connect to MQTT broker

void mqtt_connect(void) {

    int err = mqtt_connect(&client);

    if (err) {

        LOG_ERR("MQTT connection failed: %d", err);

        return;

    }

    LOG_INF("MQTT connection successful");

}

 

// Entry point

void main(void) {

    LOG_INF("Initializing LTE...");

    lte_lc_init_and_connect();  // Establish LTE connection

 

    LOG_INF("Setting up MQTT...");

    mqtt_init();

    mqtt_connect();

}

  1. Publish Messages to AWS IoT

After establishing a connection, send an MQTT message:

void send_mqtt_message(void) {

    struct mqtt_publish_param param;

    char payload[] = "{ \"status\": \"active\", \"temperature\": 25 }";

 

    param.message.topic.qos = MQTT_QOS_0_AT_MOST_ONCE;

    param.message.topic.topic.utf8 = "iot/device/data";

    param.message.topic.topic.size = strlen(param.message.topic.topic.utf8);

    param.message.payload.data = payload;

    param.message.payload.len = strlen(payload);

    param.message_id = sys_rand32_get();

   

    int err = mqtt_publish(&client, &param);

    if (err) {

        LOG_ERR("Failed to publish message: %d", err);

    } else {

        LOG_INF("Message published successfully");

    }

}

  1. Subscribe to Incoming Commands

Modify the MQTT event handler to process received messages:

case MQTT_EVT_PUBLISH: {

    struct mqtt_publish_param *p = &evt->param.publish;

    LOG_INF("Received topic: %.*s", p->message.topic.topic.size, p->message.topic.topic.utf8);

    LOG_INF("Payload: %.*s", p->message.payload.len, (char *)p->message.payload.data);

    break;

}

We have successfully flashed the certificates into the modem, however, the MQTT connection attempt times out.  Not sure how to troubleshoot this.

Can offer any advice?

Related