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?

Parents
  • At least in mfw 1.3.7, the credentials in AT%CMNG are organized in "sec_tag" and "type".

    • AT%CMNG=0,16842753,0,"-----BEGIN CERTIFICATE-----..."
    • AT%CMNG=0,16842754,0,"-----BEGIN RSA PRIVATE KEY-----..."
    • AT%CMNG=0,16842755,0,"-----BEGIN CERTIFICATE-----..."

    writes to type 0 => "root ca" to several "sec_tag". No idea, where this was found.

    • AT%CMNG=0,16842753,2,"-----BEGIN CERTIFICATE-----..."
    • AT%CMNG=0,16842753,1,"-----BEGIN RSA PRIVATE KEY-----..."
    • AT%CMNG=0,16842753,0,"-----BEGIN CERTIFICATE-----..."

    (assuming the 1. entry of type 2 sets the client certificate, and the 3. of type 0 the trusted server certificate root).

    Anyway, please read the documentation and use the samples to start with.

  • Thanks Achim.  Please point me to the appropriate documentation.

  • The "AT%CMNG" above is a link to the documentation of that command. Did you try to read it?

    I'm not common to the MQTT nor AWS samples, I used samples/net/https_client to start with. That uses the C API instead of the AT commands but is logically the same. For MQTT/AWS maybe someone from Nordic helps (I'm an other user).

    You mainly store all credentials you need for a connection with one "sec_tag", which is then also passed to the socket (similar line "setsockopt(fd, SOL_TLS, TLS_SEC_TAG_LIST, tls_sec_tag, sizeof(tls_sec_tag));" in the https_client sample). For certificate based connections that's the "Root CA certificate/0" (sometimes called the "trust anchor"). If you want to authenticate your client also using a client certificate, you need to provide also the "Client certificate/1" and the corresponding "Client private key/2". Usually the "client certificate" must be signed by a CA the server trusts. Though I'm not common to MQTT/AWS the exact procedure, how that is handled for AWS, is unknown by me.     

  • Hi Achim.  I think we have a misunderstanding.

    We believe we have successfully flashed our certificates into the 9160, so we weren't looking for help with the AT%CMNG command.

    What we're looknig for is making sure that all the other variables needed to make MQTT work between the 9160 and our AWS VPC are configured correctly in our firmware.

    We're also looking for ways to troubleshoot the AWS side of things.  I now understand that that's not your expertise, so I'll try AWS tech support next.

    Thanks again for your help, I really appreciate it.

  • Hello  , 

    I am Øyvind from the Nordic Tech support team. Are you able to provide logs output from your device when it times out? Do you receive any other error? Have you verified that your device is connected to LTE network? Have you followed all steps in Setting up AWS and configuring permissions? Have a look at Lifecycle events, where you can e.g. see the reason why the client is disconnecting on the server side

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

    could you please elaborate more on exactly what version of the nRF Connect SDK you are working with? From the description you have provided, these steps seems a little outdated, also with regards to handling certificates. 

    Kind regards,
    Øyvind Sandberg

  • Hi Oyvind,

    Thanks for looking into this case for us, however we have solved our problem.  We now have one of our nRF9160 based devices successfully sending MQTT messages to an IoT Thing that we created in our AWS VPC.  So, no further help required for now.

    Thanks

  • Hey! That is great news! Happy to hear that you have solved the issue.

    Kind regards,
    Øyvind

Reply Children
No Data
Related