From 8907d5127e268bf3675f89e0f2646088528e494f Mon Sep 17 00:00:00 2001 From: divya pillai Date: Wed, 1 Oct 2025 08:52:00 +0200 Subject: [PATCH] doc: Updates to Asset tracker template docs Updates to Asset tracker template docs. Signed-off-by: divya pillai --- README.md | 14 +- docs/common/architecture.md | 6 +- docs/common/configuration.md | 36 ++-- docs/common/customization.md | 36 ++-- docs/common/fota.md | 239 +++++++++++++------------ docs/common/getting_started.md | 6 +- docs/common/image.png | Bin 23549 -> 0 bytes docs/common/location_services.md | 2 +- docs/common/low_power.md | 73 ++++---- docs/common/provisioning.md | 49 +++-- docs/common/release.md | 39 ++-- docs/common/test_and_ci_setup.md | 2 +- docs/common/tooling_troubleshooting.md | 96 +++++----- docs/images/device_information.png | Bin 39459 -> 41437 bytes docs/index.md | 93 +++++++++- docs/modules/cloud.md | 13 +- docs/modules/location.md | 16 +- docs/modules/main.md | 7 +- docs/modules/storage.md | 22 ++- docs/stylesheets/style.css | 4 + mkdocs.yml | 13 +- 21 files changed, 452 insertions(+), 314 deletions(-) delete mode 100644 docs/common/image.png create mode 100644 docs/stylesheets/style.css diff --git a/README.md b/README.md index eda82234..6d0a47d0 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,17 @@ ## Overview -The Asset Tracker Template is a modular framework for developing IoT applications on nRF91-based devices. Built on [nRF Connect SDK](https://www.nordicsemi.com/Products/Development-software/nRF-Connect-SDK) and [Zephyr RTOS](https://docs.zephyrproject.org/latest/), it provides an event-driven architecture for battery-powered IoT use cases with cloud connectivity, location tracking, and sensor data collection. +The Asset Tracker Template is a modular framework for developing IoT applications on nRF91-based devices. +It is built on the [nRF Connect SDK](https://www.nordicsemi.com/Products/Development-software/nRF-Connect-SDK) and [Zephyr RTOS](https://docs.zephyrproject.org/latest/), and provides a modular, event-driven architecture suitable for battery-powered IoT use cases. +The framework supports features such as cloud connectivity, location tracking, and sensor data collection. -The system uses modules that communicate through [zbus](https://docs.nordicsemi.com/bundle/ncs-latest/page/zephyr/services/zbus/index.html) channels for loose coupling and maintainability. It's suitable for asset tracking, environmental monitoring, and other IoT applications requiring modularity and power efficiency. +The system is organized into modules, each responsible for a specific functionality, such as managing network connectivity, handling cloud communication, or collecting environmental data. +Modules communicate through [zbus](https://docs.zephyrproject.org/latest/services/zbus/index.html) channels, ensuring loose coupling and maintainability. **Supported hardware**: [Thingy:91 X](https://www.nordicsemi.com/Products/Development-hardware/Nordic-Thingy-91-X), [nRF9151 DK](https://www.nordicsemi.com/Products/Development-hardware/nRF9151-DK) -> **Note**: If you're new to nRF91 series and cellular IoT, consider taking the [Nordic Developer Academy Cellular Fundamentals Course](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals). +> [!NOTE] +> If you're new to nRF91 series and cellular IoT, consider taking the [Nordic Developer Academy Cellular Fundamentals Course](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals). ## Quick Start @@ -29,9 +33,9 @@ For detailed setup instructions using the [nRF Connect for VS Code extension](ht For pre-built binaries, refer to the latest tag and release artifacts documentaion; [release artifacts](docs/common/release.md). > [!TIP] -> Use the [Download nRF Connect for Desktop Quick Start application](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop/download#infotabs) for a guided setup and provisioning process. +> Download and run the [Quick Start app](https://docs.nordicsemi.com/bundle/nrf-connect-quickstart/page/index.html) in the [nRF Connect for Desktop](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Connect-for-desktop) for a guided setup and provisioning process. > -> You can also refer to [Exercise 1](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals/lessons/lesson-1-cellular-fundamentals/topic/lesson-1-exercise-1/) in [Nordic Developer Academy Cellular Fundamentals Course](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals). +> You can also refer to [Exercise 1](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals/lessons/lesson-1-cellular-fundamentals/topic/lesson-1-exercise-1/) in [Nordic Developer Academy Cellular Fundamentals Course](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals) for more details. ### Prerequisites diff --git a/docs/common/architecture.md b/docs/common/architecture.md index 3cca1c8a..acebbb4f 100644 --- a/docs/common/architecture.md +++ b/docs/common/architecture.md @@ -13,6 +13,7 @@ This document provides an overview of the architecture and explains how the diff The Asset Tracker Template is built around a modular architecture where each module is responsible for a specific functionality. The template consists of the following modules: - **[Main module](../modules/main.md)**: The central coordinator that implements the business logic and controls the overall application flow. +- **[Storage module](../modules/storage.md)**: Forwards or stores data from enabled modules. - **[Network module](../modules/network.md)**: Manages LTE connectivity and tracks network status. - **[Cloud module](../modules/cloud.md)**: Handles communication with nRF Cloud using CoAP. - **[Location module](../modules/location.md)**: Provides location services using GNSS, Wi-Fi, and cellular positioning. @@ -224,9 +225,8 @@ In the image, the black dots and arrow indicate initial transitions. In this case, the initial state is set to `STATE_RUNNING`. In the state machine definition, initial transitions are configured, such that the state machine ends up in `STATE_DISCONNECTED_SEARCHING` when first initialized. From there, transitions follows the arrows according to the messages received and the state machine logic. -!!! important "Important" - - In a hierarchical state machine, the run function of the current state is executed first, and then the run function of the parent state is executed, unless a state transition happens, or the child state marks the message as handled using `smf_state_handled()`. +> [!IMPORTANT] +> In a hierarchical state machine, the run function of the current state is executed first, and then the run function of the parent state is executed, unless a state transition happens, or the child state marks the message as handled using `smf_state_handled()`. ### State machine context diff --git a/docs/common/configuration.md b/docs/common/configuration.md index bbd25701..2a9e4740 100644 --- a/docs/common/configuration.md +++ b/docs/common/configuration.md @@ -53,19 +53,19 @@ curl -X PATCH "https://api.nrfcloud.com/v1/devices/$DEVICE_ID/state" \ *For shadow structure details, see `Asset-Tracker-Template/app/src/cbor/device_shadow.cddl`* -### Configuration Flow +### Configuration flow -* **Initial Setup** +* **Initial setup** - The device starts with default interval from `CONFIG_APP_MODULE_TRIGGER_TIMEOUT_SECONDS`. - Upon cloud connection, the device automatically requests shadow configuration. -* **Runtime Configuration** +* **Runtime configuration** - Cloud module receives and processes shadow updates. - Device maintains last known configuration during offline periods. -* **Impact on Device Behavior** +* **Impact on device behavior** The `update_interval` configuration controls the frequency of: @@ -78,7 +78,7 @@ curl -X PATCH "https://api.nrfcloud.com/v1/devices/$DEVICE_ID/state" \ The Asset Tracker supports multiple location methods that can be prioritized based on your needs. Configuration is done through board-specific configuration files. -### Available Location Methods +### Available location methods The following are the available location methods: @@ -86,9 +86,9 @@ The following are the available location methods: - Wi-Fi® positioning - Cellular positioning -### Configuration Examples +### Configuration examples -* **Thingy91x Configuration** (Wi-Fi available): +* **Thingy91x configuration** (Wi-Fi available): ``` CONFIG_LOCATION_REQUEST_DEFAULT_METHOD_FIRST_WIFI=y @@ -97,21 +97,21 @@ The following are the available location methods: CONFIG_LOCATION_REQUEST_DEFAULT_WIFI_TIMEOUT=10000 ``` -* **nRF9151 DK Configuration** (Wi-Fi unavailable): +* **nRF9151 DK configuration** (Wi-Fi unavailable): ``` CONFIG_LOCATION_REQUEST_DEFAULT_METHOD_FIRST_GNSS=y CONFIG_LOCATION_REQUEST_DEFAULT_METHOD_SECOND_CELLULAR=y ``` -## Storage Mode Configuration +## Storage mode configuration The storage module handles collected data in two modes: **Passthrough** (forward immediately, default) or **Buffer** (store and transmit in batches for lower power consumption). See [Storage Module Documentation](../modules/storage.md) for details. **Basic configuration** in `prj.conf`: -Passthrough mode is the default mode, to enable buffer mode use: +Passthrough mode is the default mode. To enable buffer mode use: ```bash CONFIG_APP_STORAGE_INITIAL_MODE_BUFFER=y @@ -124,7 +124,7 @@ CONFIG_APP_STORAGE_MAX_RECORDS_PER_TYPE=8 # Records per data type CONFIG_APP_STORAGE_BATCH_BUFFER_SIZE=256 # Batch buffer size ``` -For minimal use include the `overlay-storage-minimal.conf` overlay +For minimal use, include the `overlay-storage-minimal.conf` overlay. **Runtime control** (shell commands when `CONFIG_APP_STORAGE_SHELL=y`): @@ -156,7 +156,7 @@ The Asset Tracker supports both LTE Cat NB1 (NB-IoT) and LTE Cat M1 (LTE-M) cell - Mobile applications. - Lower latency requirements. -#### Network Mode Selection +#### Network mode selection The following network modes are available (`LTE_NETWORK_MODE`): @@ -168,7 +168,7 @@ The following network modes are available (`LTE_NETWORK_MODE`): - **LTE-M and NB-IoT**: Both LTE-M and NB-IoT enabled. - **LTE-M, NB-IoT and GPS**: Both LTE modes with GPS . -#### Network Mode Preference +#### Network mode preference When multiple network modes are enabled (LTE-M and NB-IoT), you can set preferences (`LTE_MODE_PREFERENCE`): @@ -188,11 +188,11 @@ CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS=y CONFIG_LTE_MODE_PREFERENCE_LTE_M_PLMN_PRIO=y ``` -### PSM (Power Saving Mode) +### Power Saving Mode (PSM) PSM allows the device to enter deep sleep while maintaining network registration. Configuration is done through Kconfig options: -#### PSM Parameters +#### PSM parameters * **Periodic TAU (Tracking Area Update)** @@ -223,7 +223,7 @@ The following are the Key aspects: - Stays active for the duration specified by RAT. -### APN (Access Point Name) +### Access Point Name (APN) The Access Point Name (APN) is a network identifier used by the device to connect to the cellular network's packet data network. Configuration options: @@ -243,7 +243,7 @@ Common scenarios for APN configuration: > [!NOTE] > In most cases, the default APN provided by the carrier should work without additional configuration. -## LED Status Indicators +## LED status indicators The Asset Tracker Template uses LED colors to indicate different device states: @@ -252,7 +252,7 @@ The Asset Tracker Template uses LED colors to indicate different device states: - **Blue** (Blinking, 10 repetitions): Device is in lower power mode state between samples. - **Purple** (Blinking, 10 repetitions): FOTA download in progress. -### Example: Setting LED Colors +### Example: Setting LED colors You can control the LED colors through the LED module using zbus messages. The following is an example of how to set different LED patterns: diff --git a/docs/common/customization.md b/docs/common/customization.md index ce2f6078..f52ac09f 100644 --- a/docs/common/customization.md +++ b/docs/common/customization.md @@ -33,7 +33,7 @@ To add a new zbus event, complete the following procedure: }; ``` -2. Implement publishing of VBUS connected and disconnected events by modifying the existing `event_callback()` function in `power.c`: +1. Implement publishing of VBUS connected and disconnected events by modifying the existing `event_callback()` function in `power.c`: ```c if (pins & BIT(NPM13XX_EVENT_VBUS_DETECTED)) { LOG_DBG("VBUS detected"); @@ -70,7 +70,7 @@ To add a new zbus event, complete the following procedure: } ``` -3. Make sure the channel is included in the subscriber module (for example, `main.c`). Add the channel to the channel list: +1. Make sure the channel is included in the subscriber module (for example, `main.c`). Add the channel to the channel list: ```c # define CHANNEL_LIST(X) \ @@ -84,7 +84,7 @@ To add a new zbus event, complete the following procedure: X(POWER_CHAN, struct power_msg) \ ``` -4. Implement a handler for the new events in the subscriber module (for example, in the main module's state machine in `running_run`): +1. Implement a handler for the new events in the subscriber module (for example, in the main module's state machine in `running_run`): ```c if (state_object->chan == &POWER_CHAN) { @@ -136,7 +136,7 @@ To add a new zbus event, complete the following procedure: } ``` -5. Test the implementation by connecting and disconnecting VBUS to verify the LED patterns change as expected. +1. Test the implementation by connecting and disconnecting VBUS to verify the LED patterns change as expected. ## Add environmental sensor @@ -171,7 +171,7 @@ Thingy:91 X is used as an example, as it is a supported board in the template wi }; ``` -2. Update the environmental module's state structure to include the magnetometer device reference and data storage: +1. Update the environmental module's state structure to include the magnetometer device reference and data storage: ```c struct environmental_state_object { @@ -187,7 +187,7 @@ Thingy:91 X is used as an example, as it is a supported board in the template wi }; ``` -3. Initialize the device reference using the devicetree label: +1. Initialize the device reference using the devicetree label: ```c struct environmental_state_object environmental_state = { @@ -196,7 +196,7 @@ Thingy:91 X is used as an example, as it is a supported board in the template wi }; ``` -4. Update the sensor sampling function signature to include the magnetometer device: +1. Update the sensor sampling function signature to include the magnetometer device: ```c static void sample_sensors(const struct device *const bme680, const struct device *const bmm350) @@ -208,7 +208,7 @@ Thingy:91 X is used as an example, as it is a supported board in the template wi sample_sensors(state_object->bme680, state_object->bmm350); ``` -5. Implement sensor data acquisition using the Zephyr Sensor API: +1. Implement sensor data acquisition using the Zephyr Sensor API: ```c err = sensor_sample_fetch(bmm350); @@ -241,7 +241,7 @@ Thingy:91 X is used as an example, as it is a supported board in the template wi }; ``` -6. Update the `environmental_msg` structure in `environmental.h` to include the magnetic field data: +1. Update the `environmental_msg` structure in `environmental.h` to include the magnetic field data: ```c struct environmental_msg { @@ -254,9 +254,9 @@ Thingy:91 X is used as an example, as it is a supported board in the template wi }; ``` - The magnetometer data is now part of the environmental message and will be automatically handled by the storage module through the existing `ENVIRONMENTAL` data type. No changes to `storage_data_types.h` or `storage_data_types.c` are needed since the existing `environmental_check()` and `environmental_extract()` functions will handle the entire structure including the magnetic field data. + The magnetometer data is now part of the environmental message and will be automatically handled by the storage module through the existing `ENVIRONMENTAL` data type. No changes to `storage_data_types.h` or `storage_data_types.c` are needed since the existing `environmental_check()` and `environmental_extract()` functions will handle the entire structure, including the magnetic field data. -7. Add cloud integration in the `send_storage_data_to_cloud()` function in `cloud.c` to send magnetometer data to nRF Cloud. Add this code after the existing environmental sensor data handling: +1. Add cloud integration in the `send_storage_data_to_cloud()` function in `cloud.c` to send magnetometer data to nRF Cloud. Add this code after the existing environmental sensor data handling: ```c #if defined(CONFIG_APP_ENVIRONMENTAL) @@ -316,14 +316,14 @@ To add your own module, complete the following steps: mkdir -p app/src/modules/dummy ``` -2. Create the following files in the module directory: +1. Create the following files in the module directory: - `dummy.h` - Module interface definitions. - `dummy.c` - Module implementation. - `Kconfig.dummy` - Module configuration options. - `CMakeLists.txt` - Build system configuration. -3. In `dummy.h`, define the module's interface: +1. In `dummy.h`, define the module's interface: ```c #ifndef _DUMMY_H_ @@ -363,7 +363,7 @@ To add your own module, complete the following steps: #endif /* _DUMMY_H_ */ ``` -4. In `dummy.c`, implement the module's functionality: +1. In `dummy.c`, implement the module's functionality: ```c #include @@ -521,7 +521,7 @@ To add your own module, complete the following steps: K_LOWEST_APPLICATION_THREAD_PRIO, 0, 0); ``` -5. In `Kconfig.dummy`, define module configuration options: +1. In `Kconfig.dummy`, define module configuration options: ```kconfig menuconfig APP_DUMMY @@ -557,20 +557,20 @@ To add your own module, complete the following steps: endif # APP_DUMMY ``` -6. In `CMakeLists.txt`, configure the build system to include the source files of the module: +1. In `CMakeLists.txt`, configure the build system to include the source files of the module: ```cmake target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dummy.c) target_include_directories(app PRIVATE .) ``` -7. Add the module to the main application's CMakeLists.txt: +1. Add the module to the main application's CMakeLists.txt: ```cmake add_subdirectory(src/modules/dummy) ``` -8. Increase `CONFIG_TASK_WDT_CHANNELS` in the `prj.conf` file to accommadate for the new module's task watchdog integration. +1. Increase the value of the `CONFIG_TASK_WDT_CHANNELS` Kconfig option in the `prj.conf` file to accommadate for the new module's task watchdog integration. The dummy module is now ready to use. It provides the following functionality: diff --git a/docs/common/fota.md b/docs/common/fota.md index 494ef2a3..bb4316fa 100644 --- a/docs/common/fota.md +++ b/docs/common/fota.md @@ -1,18 +1,18 @@ -# Firmware Updates (FOTA) +# Firmware updates (FOTA) This guide covers how to perform Firmware Over The Air (FOTA) updates using nRF Cloud, including both the web UI and REST API methods. -## Firmware Versioning +## Firmware versioning -### Version Components +### Version components -Firmware versions are defined in `app/VERSION`: +Firmware versions are defined in the `app/VERSION` file: - **VERSION_MAJOR**: Major version - **VERSION_MINOR**: Minor version - **PATCHLEVEL**: Patch level - **VERSION_TWEAK**: Additional component (typically 0) -- **EXTRAVERSION**: Extra string (e.g., "dev", "rc1") +- **EXTRAVERSION**: Extra string (for example, "dev", "rc1") Example resulting in version `1.2.3-dev`: @@ -24,67 +24,80 @@ VERSION_TWEAK = 0 EXTRAVERSION = dev ``` -### Preparing Firmware +### Preparing firmware -1. **Update `app/VERSION`** - Increment the appropriate version component -2. **Build the firmware** +Complete the following steps for preparing firmware: - Using the command line: +1. Update the `app/VERSION` file. Increment the appropriate version component. +1. Build the firmware. - ```bash - west build -p -b thingy91x/nrf9151/ns # Make sure you build for the appropriate board - ``` + Using the command line: - Or use the nRF Connect for VS Code extension - see the [Getting Started](getting_started.md) guide for details on building with the extension. + ```bash + west build -p -b thingy91x/nrf9151/ns # Make sure you build for the appropriate board + ``` -3. **Locate update bundles**: - - `build/app/zephyr/dfu_application.zip` - Application firmware update - - `build/app/zephyr/dfu_mcuboot.zip` - Bootloader update + Or use the nRF Connect for VS Code extension. See the [Getting Started](getting_started.md) guide for details on building with the extension. -### Version Verification +1. Locate update bundles: -**Important**: The `fwversion` field in a firmware bundle is independent from the device's reported version. + - `build/app/zephyr/dfu_application.zip` - Application firmware update + - `build/app/zephyr/dfu_mcuboot.zip` - Bootloader update + +### Version verification + +> [!IMPORTANT] +> The `fwversion` field in a firmware bundle is independent from the device's reported version. To verify a successful update: -- **Application updates**: Check that the FOTA job shows **Completed** status AND the **App Version** field in device information reflects the new version -- **Modem updates**: Check that the FOTA job shows **Completed** status AND the **Modem Firmware** field in device information shows the new version +- **Application updates**: Check that the FOTA job shows `Completed` status and the **App Version** field in device information reflects the new version. +- **Modem updates**: Check that the FOTA job shows `Completed` status and the **Modem Firmware** field in device information shows the new version. ![Device information showing app version](../images/device_information.png) -## Performing FOTA Updates +## Performing FOTA updates + +You can update the FOTA updates using nRF Cloud Web UI or REST API. ### Option 1: nRF Cloud Web UI This is the recommended method for manual updates and testing. -1. **Navigate to Firmware Updates** in the nRF Cloud portal under **Device Management** -2. **Create Update Bundle**: - - Click "Add bundle" - - Upload your bundle file: - - For application updates: `dfu_application.zip` - - For bootloader updates: `dfu_mcuboot.zip` - - Set **Update Type** (e.g., LTE) - - Enter a **Name** for the bundle - - Enter a **Version** string (can be any identifier - this is the `fwversion` shown in the bundle list) - - Click "Create/Upload Bundle" - -3. **Create FOTA Update**: - - Enter a **Name** and a **Description** of the update - - Select target device(s) via device or group selection - - Click on **Deploy now** - - Click "Create FOTA Update" - -4. **Monitor Progress**: - - View job status in the "Overall Progress" section of the update - - Status will progress: Queued → In Progress → Downloading → Completed - - The device will automatically download and apply the update once it becomes online - -5. **Verify Update**: - - Navigate to your device page, **Device Management** → **Devices** and select your device - - Click on **Device info** under the **Device Information** card - - Check the **App Version** (for app updates) or **Modem Firmware** (for modem updates) field - - Confirm the version matches your new firmware +1. Navigate to [nRF Cloud](https://nrfcloud.com) and log in to your account. +1. Select **Firmware Updates** in the **Device Management** tab on the left. +1. Create Update Bundle: + + 1. Click "Add bundle". + 1. Upload your bundle file: + + - For application updates: `dfu_application.zip` + - For bootloader updates: `dfu_mcuboot.zip` + + 1. Set **Update Type** (for example, LTE). + 1. Enter a **Name** for the bundle. + 1. Enter a **Version** string (can be any identifier - this is the `fwversion` shown in the bundle list). + 1. Click **Create/Upload Bundle**. + +1. Create FOTA Update: + + 1. Enter a **Name** and a **Description** of the update. + 1. Select target device(s) through device or group selection. + 1. Click on **Deploy now**. + 1. Click **Create FOTA Update**. + +1. Monitor Progress: + + - View job status in the **Overall Progress** section of the update. + - Status will progress: Queued → In Progress → Downloading → Completed. + - The device will automatically download and apply the update once it becomes online. + +1. Verify Update: + + 1. Navigate to your device page, click **Devices** under **Device Management** in the navigation pane on the left, and select your device + 1. Click on **Device info** under the **Device Information** card. + 1. Check the **App Version** (for app updates) or **Modem Firmware** (for modem updates) field. + 1. Confirm the version matches your new firmware. ### Option 2: REST API @@ -97,74 +110,74 @@ export API_KEY= export DEVICE_ID= ``` -Find your API key in **User Account** settings in nRF Cloud. See [nRF Cloud REST API](https://api.nrfcloud.com/) for reference. +Find your API key in **User Account** settings in [nRF Cloud](https://nrfcloud.com/). See [nRF Cloud REST API](https://api.nrfcloud.com/) for reference. #### Complete Update Workflow -1. **Create manifest and upload bundle**: - - ```bash - # Set path to your application binary - export BIN_FILE="build/app/zephyr/zephyr.signed.bin" - export FW_VERSION="1.2.3" - - # Create manifest.json with firmware details - cat > manifest.json << EOF - { - "name": "My Firmware", - "description": "Firmware description", - "fwversion": "${FW_VERSION}", - "format-version": 1, - "files": [ - { - "file": "$(basename ${BIN_FILE})", - "type": "application", - "size": $(stat -f%z ${BIN_FILE}) - } - ] - } - EOF - - # Create zip containing firmware and manifest - zip -j firmware.zip ${BIN_FILE} manifest.json - - # Upload to nRF Cloud and extract bundle ID - UPLOAD_RESPONSE=$(curl -X POST "https://api.nrfcloud.com/v1/firmwares" \ - -H "Authorization: Bearer ${API_KEY}" \ - -H "Content-Type: application/zip" \ - --data-binary @firmware.zip) - - # Extract the bundle ID from the response (UUID from the URI path) - export BUNDLE_ID=$(echo $UPLOAD_RESPONSE | jq -r '.uris[0]' | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') - ``` - -2. **Create and apply FOTA job**: - - ```bash - # Create job - JOB_RESPONSE=$(curl -X POST "https://api.nrfcloud.com/v1/fota-jobs" \ - -H "Authorization: Bearer ${API_KEY}" \ - -H "Content-Type: application/json" \ - -d "{\"deviceIds\": [\"${DEVICE_ID}\"], \"bundleId\": \"${BUNDLE_ID}\"}") - - export JOB_ID=$(echo $JOB_RESPONSE | jq -r '.jobId') - - # Apply job - curl -X POST "https://api.nrfcloud.com/v1/fota-jobs/${JOB_ID}/apply" \ - -H "Authorization: Bearer ${API_KEY}" - ``` - -3. **Monitor job status**: - - ```bash - curl -X GET "https://api.nrfcloud.com/v1/fota-jobs/${JOB_ID}" \ - -H "Authorization: Bearer ${API_KEY}" \ - -H "Accept: application/json" - ``` - - Job status values: `QUEUED`, `IN_PROGRESS`, `DOWNLOADING`, `SUCCEEDED`, `FAILED`, `TIMED_OUT`, `CANCELLED`, `REJECTED` - -4. **Verify the update** by checking the device information in nRF Cloud (App Version or Modem Firmware field) +1. Create manifest and upload bundle: + + ```bash + # Set path to your application binary + export BIN_FILE="build/app/zephyr/zephyr.signed.bin" + export FW_VERSION="1.2.3" + + # Create manifest.json with firmware details + cat > manifest.json << EOF + { + "name": "My Firmware", + "description": "Firmware description", + "fwversion": "${FW_VERSION}", + "format-version": 1, + "files": [ + { + "file": "$(basename ${BIN_FILE})", + "type": "application", + "size": $(stat -f%z ${BIN_FILE}) + } + ] + } + EOF + + # Create zip containing firmware and manifest + zip -j firmware.zip ${BIN_FILE} manifest.json + + # Upload to nRF Cloud and extract bundle ID + UPLOAD_RESPONSE=$(curl -X POST "https://api.nrfcloud.com/v1/firmwares" \ + -H "Authorization: Bearer ${API_KEY}" \ + -H "Content-Type: application/zip" \ + --data-binary @firmware.zip) + + # Extract the bundle ID from the response (UUID from the URI path) + export BUNDLE_ID=$(echo $UPLOAD_RESPONSE | jq -r '.uris[0]' | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') + ``` + +1. Create and apply FOTA job: + + ```bash + # Create job + JOB_RESPONSE=$(curl -X POST "https://api.nrfcloud.com/v1/fota-jobs" \ + -H "Authorization: Bearer ${API_KEY}" \ + -H "Content-Type: application/json" \ + -d "{\"deviceIds\": [\"${DEVICE_ID}\"], \"bundleId\": \"${BUNDLE_ID}\"}") + + export JOB_ID=$(echo $JOB_RESPONSE | jq -r '.jobId') + + # Apply job + curl -X POST "https://api.nrfcloud.com/v1/fota-jobs/${JOB_ID}/apply" \ + -H "Authorization: Bearer ${API_KEY}" + ``` + +1. Monitor job status: + + ```bash + curl -X GET "https://api.nrfcloud.com/v1/fota-jobs/${JOB_ID}" \ + -H "Authorization: Bearer ${API_KEY}" \ + -H "Accept: application/json" + ``` + + Job status values: `QUEUED`, `IN_PROGRESS`, `DOWNLOADING`, `SUCCEEDED`, `FAILED`, `TIMED_OUT`, `CANCELLED`, `REJECTED` + +1. Verify the update by checking the device information in [nRF Cloud](https://nrfcloud.com/) (**App Version** or **Modem Firmware** field). #### API Reference diff --git a/docs/common/getting_started.md b/docs/common/getting_started.md index 7d32535f..602aedca 100644 --- a/docs/common/getting_started.md +++ b/docs/common/getting_started.md @@ -1,4 +1,4 @@ -# Getting Started +# Getting started To get started with Asset tracker template, you need to set up the development environment, build the application, and run it on supported hardware. You can use any of the following tools, depending on your preferred development environment: @@ -20,6 +20,8 @@ Once you have created the project, you can access various development actions th For more details on how to use the VS Code extension, refer to the [nRF Connect for VS Code documentation](https://docs.nordicsemi.com/bundle/nrf-connect-vscode/page/index.html). +For pre-built binaries, refer to the latest tag and the [release artifacts](release.md) documentation. + ## Prerequisites * **The nRF Util command line tool and the SDK manager command** @@ -126,7 +128,7 @@ west build -p -b thingy91x/nrf9151/ns -- -DEXTRA_CONF_FILE="overlay-memfault.con To connect to [nRF Cloud](https://nrfcloud.com), the device must be provisioned to your account. You can provision the device using one of the following methods: -* **Quickstart application**: Use the [Download nRF Connect for Desktop](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop/download#infotabs) Quick Start application for a streamlined setup process. +* **Quickstart application**: Use the [Quick Start app](https://docs.nordicsemi.com/bundle/nrf-connect-quickstart/page/index.html) in the [nRF Connect for Desktop](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Connect-for-desktop)`_ for a streamlined setup process. * **Manual provisioning**: Follow the detailed steps in the [Provisioning](provisioning.md) documentation. The provisioning process establishes the necessary credentials and certificates for secure communication between your device and nRF Cloud. diff --git a/docs/common/image.png b/docs/common/image.png deleted file mode 100644 index af72860435ad78582f67d0f59a17fad9503c2948..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23549 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 [!NOTE] -> After suspending the UART you're using for the shell, you won't be able to send further commands until the device is reset or the UART is resumed through other means. +> After suspending the UART you are using for the shell, you will not be able to send further commands until the device is reset or the UART is resumed through other means. -## Optimization Best Practices +## Optimization best practices -1. **Disable devices** - Disable UART and peripherals that consume a lot of power -2. **Increase update intervals** - Reduce sampling/transmission frequency -3. **Enable buffer mode** - Batch data transmissions -4. **Minimize payload size** - Reduce transmission duration by using effective serialization formats (CBOR, Protobuf) -5. **Validate with PPK2** - Measure actual power consumption +1. **Disable peripherals** - Disable UART and peripherals that consume a lot of power. +2. **Increase update intervals** - Reduce sampling/transmission frequency. +3. **Enable buffer mode** - Batch data transmissions. +4. **Minimize payload size** - Reduce transmission duration by using effective serialization formats (CBOR, Protobuf). +5. **Validate with PPK2** - Measure actual power consumption. -## Additional Resources +## Additional resources - [Cellular IoT Fundamentals Developer Academy Course](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals/) - [Tooling and Troubleshooting Guide](tooling_troubleshooting.md) diff --git a/docs/common/provisioning.md b/docs/common/provisioning.md index 306796e4..5493c22e 100644 --- a/docs/common/provisioning.md +++ b/docs/common/provisioning.md @@ -6,27 +6,40 @@ Device provisioning establishes credentials for secure communication with nRF Cl 1. Get the device attestation token: - ```bash - at at%attesttoken - ``` + ```bash + at at%attesttoken + ``` - *Note: Token is printed automatically on first boot of unprovisioned devices.* + > [!NOTE] + > Token is printed automatically on first boot of unprovisioned devices. -2. In nRF Cloud: **Security Services** → **Claimed Devices** → **Claim Device** -3. Paste token, set rule to "nRF Cloud Onboarding", click **Claim Device** +1. Log in to the [nRF Cloud](https://nrfcloud.com/#/) portal. +1. Select **Security Services** in the left sidebar. + + A panel opens to the right. + +1. Select **Claimed Devices**. +1. Click **Claim Device** + + A pop-up opens. + +1. Copy and paste the attestation token into the **Claim token** text box. +1. Set rule to nRF Cloud Onboarding and click **Claim Device**.
If "nRF Cloud Onboarding" rule is not showing: Create a new rule using the following configuration: - Claim Device + Claim Device
-4. Once connected, the device should be available under **Device Management** → **Devices**. +1. Once connected, the device must be available under the **Devices** section in the **Device Management** navigation pane on the left. ### REST API Alternative +You can also use the REST API as an alternative for provisioning by running the following command: + ```bash curl 'https://api.provisioning.nrfcloud.com/v1/claimed-devices' \ -H 'Content-Type: application/json' \ @@ -38,20 +51,28 @@ curl 'https://api.provisioning.nrfcloud.com/v1/claimed-devices' \ To update device credentials: -> In an end-product it's recommended to reprovision the device at a reasonable interval depending on the application use case, for security reasons. +> In an end product it is recommended to reprovision the device at a reasonable interval depending on the application use case for security reasons. ### Manual -1. In nRF Cloud: **Security Services** → **Claimed Devices** → find device → **Add Command** -2. Select **Cloud Access Key Generation** → **Create Command** -3. Trigger on device: +1. Log in to the [nRF Cloud](https://nrfcloud.com/#/) portal. +1. Select **Security Services** in the left sidebar. + + A panel opens to the right. +1. Select **Claimed Devices**. +1. Find the device and click **Add Command**. +1. Select **Cloud Access Key Generation** and click **Create Command**. +1. Trigger on device: + - **Shell**: `att_cloud_provision now` - **Cloud**: Update device shadow with `{"desired": {"command": [1, 1]}}`. -*For detailed information on sending commands to devices via REST API, including command structure and available command types, see [Sending commands through REST API](configuration.md#sending-commands-through-rest-api) in the configuration documentation.* +For detailed information on sending commands to devices through REST API, including command structure and available command types, see [Sending commands through REST API](configuration.md#sending-commands-through-rest-api) in the configuration documentation. ### REST API Alternative +You can also use the REST API as an alternative for reprovisioning by running the following command: + ```bash curl 'https://api.provisioning.nrfcloud.com/v1/claimed-devices/YOUR_DEVICE_ID/provisioning' \ -H 'Content-Type: application/json' \ @@ -59,4 +80,4 @@ curl 'https://api.provisioning.nrfcloud.com/v1/claimed-devices/YOUR_DEVICE_ID/pr -d '{"request": {"cloudAccessKeyGeneration": {"secTag": 16842753}}}' ``` -*For detailed API documentation, see [nRF Cloud REST API](https://api.nrfcloud.com/docs).* +For detailed API documentation, see [nRF Cloud REST API](https://api.nrfcloud.com/docs). diff --git a/docs/common/release.md b/docs/common/release.md index 5fb96e49..25485e29 100644 --- a/docs/common/release.md +++ b/docs/common/release.md @@ -1,16 +1,17 @@ -# Release Artifacts +# Release artifacts -This document provides a comprehensive overview of all firmware deliverables and artifacts generated by the Asset Tracker Template. Each firmware variant is optimized for specific use cases and hardware platforms. +This document provides a comprehensive overview of all firmware deliverables and artifacts generated by the Asset Tracker Template. +Each firmware variant is optimized for specific use cases and hardware platforms. -## Firmware Deliverables +## Firmware deliverables The Asset Tracker Template generates multiple firmware artifacts for different hardware platforms and configurations. Each artifact is built to serve specific development, testing, or production needs. -### Primary Release Artifacts +### Primary release artifacts -#### Standard Firmware Variants +#### Standard firmware variants -| **Artifact Name** | **Hardware Platform** | **Description** | **Use Case** | +| **Artifact name** | **Hardware platform** | **Description** | **Use case** | |-------------------|----------------------|----------------|--------------| | `att-thingy91x-{VERSION}.hex` | Thingy:91 X (nRF9151) | Standard production firmware with all core features enabled | Production deployment on Thingy:91 X devices | | `att-thingy91-{VERSION}.hex` | Thingy:91 (nRF9160) | Legacy production firmware for older Thingy:91 devices | Production deployment on original Thingy:91 devices | @@ -18,45 +19,45 @@ The Asset Tracker Template generates multiple firmware artifacts for different h | `att-nrf9160dk-{VERSION}.hex` | nRF9160 DK | Development kit firmware for nRF9160-based boards | Development and testing on nRF9160 DK | | `att-nrf9161dk-{VERSION}.hex` | nRF9161 DK | Development kit firmware for nRF9161-based boards | Development and testing on nRF9161 DK | -#### Debug and Development Variants +#### Debug and development variants -| **Artifact Name** | **Hardware Platform** | **Description** | **Use Case** | +| **Artifact name** | **Hardware platform** | **Description** | **Use case** | |-------------------|----------------------|----------------|--------------| | `att-thingy91x-{VERSION}-debug.hex` | Thingy:91 X (nRF9151) | Debug build with enhanced logging and diagnostic features. **Note: This build uploads diagnostic and crash data to Memfault using Nordic's account and is intended for internal use only.** | Development debugging and issue investigation | | `att-thingy91x-{VERSION}-mqtt.hex` | Thingy:91 X (nRF9151) | Firmware with MQTT cloud connectivity instead of CoAP | Testing MQTT-based cloud communication | -#### Specialized Configuration Variants +#### Specialized configuration variants -| **Artifact Name** | **Hardware Platform** | **Description** | **Use Case** | +| **Artifact name** | **Hardware platform** | **Description** | **Use case** | |-------------------|----------------------|----------------|--------------| -| `att-thingy91x-{VERSION}-mtrace.hex` | Thingy:91 X (nRF9151) | Firmware with modem trace output enabled via UART 1 | Cellular connectivity debugging and analysis | -| `att-nrf9151dk-{VERSION}-mtrace.hex` | nRF9151 DK | Firmware with modem trace output enabled via UART 1 | Cellular connectivity debugging and analysis | -| `att-nrf9161dk-{VERSION}-mtrace.hex` | nRF9161 DK | Firmware with modem trace output enabled via UART 1 | Cellular connectivity debugging and analysis | +| `att-thingy91x-{VERSION}-mtrace.hex` | Thingy:91 X (nRF9151) | Firmware with modem trace output enabled through UART 1 | Cellular connectivity debugging and analysis | +| `att-nrf9151dk-{VERSION}-mtrace.hex` | nRF9151 DK | Firmware with modem trace output enabled through UART 1 | Cellular connectivity debugging and analysis | +| `att-nrf9161dk-{VERSION}-mtrace.hex` | nRF9161 DK | Firmware with modem trace output enabled through UART 1 | Cellular connectivity debugging and analysis | | `att-nrf9151dk-{VERSION}-ext-gnss.hex` | nRF9151 DK | Firmware configured for external GNSS antenna | Testing with external GNSS antenna setup | -### Configuration Overlays +### Configuration overlays The firmware variants are built using different configuration overlays that modify the base functionality: -| **Overlay File** | **Purpose** | **Key Features** | +| **Overlay file** | **Purpose** | **Key features** | |------------------|-------------|------------------| | `overlay-etb.conf` | Embedded Trace Buffer (ETB) support | Hardware-level debugging and trace collection | | `overlay-memfault.conf` | Memfault integration | Crash reporting and device monitoring | | `overlay-storage-minimal.conf` | Minimal storage configuration | Reduced memory footprint with passthrough-only storage | | `overlay-upload-modem-traces-to-memfault.conf` | Modem trace to Memfault | Automatic upload of modem traces for analysis | -### Hardware Platform Support +### Hardware platform support -#### Thingy:91 X (Primary Platform) +#### Thingy:91 X (Primary platform) - **SoC**: nRF9151 - **Features**: Full sensor suite, battery operation, compact form factor - **Target Use**: Production IoT deployments, prototyping - **Memory Reports**: ROM and RAM usage reports generated for optimization -#### Development Kits +#### Development kits - **nRF9151 DK**: Primary development platform for nRF9151-based projects -- **nRF9160 DK**: Legacy development support for nRF9160-based projects +- **nRF9160 DK**: Legacy development support for nRF9160-based projects - **nRF9161 DK**: Latest development platform with enhanced features - **Thingy:91**: Legacy compact development platform diff --git a/docs/common/test_and_ci_setup.md b/docs/common/test_and_ci_setup.md index 53c32d34..8a7966a5 100644 --- a/docs/common/test_and_ci_setup.md +++ b/docs/common/test_and_ci_setup.md @@ -1,4 +1,4 @@ -# Testing and CI Setup +# Testing and CI setup The Asset Tracker Template features a comprehensive testing infrastructure with tests run both on real hardware (on target) and emulation. Code analysis is performed through compliance checks and SonarCloud analysis. diff --git a/docs/common/tooling_troubleshooting.md b/docs/common/tooling_troubleshooting.md index 34aa0610..6fb49c06 100644 --- a/docs/common/tooling_troubleshooting.md +++ b/docs/common/tooling_troubleshooting.md @@ -8,6 +8,8 @@ For more knowledge on debugging and troubleshooting [nRF Connect SDK](https://gi - [nRF Connect SDK Debugging Guide](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/test_and_optimize/debugging.html) - [Zephyr Debugging Guide](https://docs.zephyrproject.org/latest/develop/debug/index.html) +
+ ## Table of Contents - [Shell Commands](#shell-commands) @@ -33,6 +35,8 @@ For more knowledge on debugging and troubleshooting [nRF Connect SDK](https://gi - [Application logs and modem traces over RTT - Parallel capture](#application-logs-and-modem-traces-over-rtt---parallel-capture) - [Common Issues and Solutions](#common-issues-and-solutions) +
+ ## Shell Commands The template provides several shell commands for controlling and monitoring device behavior. Connect to the device's UART interface using either: @@ -363,15 +367,13 @@ For more information, refer the following documentation: - [TF-M Documentation](https://tf-m-user-guide.trustedfirmware.org/) - [nRF Connect SDK TF-M Guide](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/security/tfm/index.html) -!!! note "Note" - - On hardfault, the fault frame might not be printed due to the device rebooting before the log buffer is flushed. - To circumvent this issue add the following configurations: - - ```bash - CONFIG_LOG_MODE_IMMEDIATE=y - CONFIG_RESET_ON_FATAL_ERROR=n - ``` +> [!NOTE] +> On hardfault, the fault frame might not be printed due to the device rebooting before the log buffer is flushed. +> To circumvent this issue add the following configurations: +> ```bash +> CONFIG_LOG_MODE_IMMEDIATE=y +> CONFIG_RESET_ON_FATAL_ERROR=n +> ``` When enabling immediate logging, it might be necessary to increase the stack size of certain threads due to logging being executed in context which increases stack usage. @@ -395,8 +397,10 @@ To build the application with support for Memfault, you need to build with the M If you also want to upload the [Embedded Trace Buffer](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/libraries/debug/etb_trace.html), you can include the overlay `overlay-etb.conf`. -!!! important "important" - Enabling Memfault will increase your device's data usage. This is especially true when using the modem trace upload feature, which can send upwards of 1 MB of modem trace data in case of application crashes. Consider this when planning your data usage and costs. +> [!IMPORTANT] +> Enabling Memfault will increase your device's data usage. +> This is especially true when using the modem trace upload feature, which can send upwards of 1 MB of modem trace data in case of application crashes. +> Consider this when planning your data usage and costs. For detailed build instructions and how to configure the project key, refer to the [Getting Started Guide](getting_started.md) where build instructions for building with Memfault are given. To build with all available Memfault functionality: @@ -409,8 +413,9 @@ Screen capture from a coredump received in Memfault: ![Memfault UI](../images/memfault.png) -!!! important "important" - In order to properly use Memfault and be able to decode metrics and coredumps sent from the device, you need to upload the ELF file located in the build folder of the template once you have built the application. This is covered in the [Remote Debugging with Memfault](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-2-debugging/topic/exercise-4-remote-debugging-with-memfault/) developer Academy excersise. +> [!IMPORTANT] +> In order to properly use Memfault and be able to decode metrics and coredumps sent from the device, you need to upload the ELF file located in the build folder of the template once you have built the application. +> This is covered in the [Remote Debugging with Memfault](https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/lessons/lesson-2-debugging/topic/exercise-4-remote-debugging-with-memfault/) developer Academy excersise. #### Test shell commands @@ -480,7 +485,7 @@ nrfutil trace lte --input-file modem_trace.bin --output-pcapng rtt-trace.pcapng ### Dumping modem traces over UART after capture -The device can be configured to continuously capture modem traces to external flash memory. After capture, a shell command can be used to dump the stored traces over UART to the [Cellular Monitor](https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop) application for storage and analysis. +You can configure the device to continuously capture modem traces to external flash memory. After capture, you can use a shell command to dump the stored traces over UART using the [Cellular Monitor app](https://docs.nordicsemi.com/bundle/nrf-connect-cellularmonitor/page/index.html) for storage and analysis. Add to `prj.conf`: @@ -497,29 +502,28 @@ CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_FLASH_PARTITION_SIZE=0xFF000 CONFIG_NRF_MODEM_LIB_SHELL_TRACE=y ``` -!!! important "Important" - - **Flash Partition Configuration:** - - The flash partition size configuration allocates 255 sectors of 4 kB each (approximately 1 MB) for trace storage. - Adjust `CONFIG_NRF_MODEM_LIB_TRACE_FLASH_SECTORS` and `CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_FLASH_PARTITION_SIZE` according to your available flash memory. - - **Trace Buffer Limitations:** - - Depending on the trace level, network, and IP activity, the trace buffer might get full. Due to a current limitation in Zephyr, the maximum size of the buffer is approximately 1 MB. - - **Trace Level Configuration:** - - To mitigate buffer overflow issues, the trace level can be adjusted through the `CONFIG_NRF_MODEM_LIB_TRACE_LEVEL` choice symbol: - - - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_OFF`**: Disable output - - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_COREDUMP_ONLY`**: Coredump only - - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_IP_ONLY`**: IP only - - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_LTE_AND_IP`**: LTE and IP (recommended for most use cases) - - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_FULL`**: LTE, IP, GNSS, and coredump (highest data volume) - - Adjusting the trace level will set how often the trace buffer is filled up. When the trace buffer gets full, the oldest entry will be overwritten. - To disable this, disable `CONFIG_NRF_MODEM_TRACE_FLASH_NOSPACE_ERASE_OLDEST`. +> [!IMPORTANT] +> **Flash Partition Configuration:** +> +> The flash partition size configuration allocates 255 sectors of 4 kB each (approximately 1 MB) for trace storage. +> Adjust the `CONFIG_NRF_MODEM_LIB_TRACE_FLASH_SECTORS` and `CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_FLASH_PARTITION_SIZE` Kconfig options according to your available flash memory. +> +> **Trace Buffer Limitations:** +> +> Depending on the trace level, network, and IP activity, the trace buffer might get full. Due to a current limitation in Zephyr, the maximum size of the buffer is approximately 1 MB. +> +> **Trace Level Configuration:** +> +> To mitigate buffer overflow issues, the trace level can be adjusted through the `CONFIG_NRF_MODEM_LIB_TRACE_LEVEL` choice symbol: +> +> - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_OFF`**: Disable output +> - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_COREDUMP_ONLY`**: Coredump only +> - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_IP_ONLY`**: IP only +> - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_LTE_AND_IP`**: LTE and IP (recommended for most use cases) +> - **`CONFIG_NRF_MODEM_LIB_TRACE_LEVEL_FULL`**: LTE, IP, GNSS, and coredump (highest data volume) +> +> Adjusting the trace level will set how often the trace buffer is filled up. When the trace buffer gets full, the oldest entry will be overwritten. +> To disable this, disable `CONFIG_NRF_MODEM_TRACE_FLASH_NOSPACE_ERASE_OLDEST`. The following `modem_trace` shell commands are available: @@ -536,23 +540,23 @@ Subcommands: dump_uart : Dump stored traces to UART. ``` -To capture traces: +Complete the following to capture traces: 1. Connect to the device using a serial terminal. -2. Start capturing traces in the [Cellular Monitor](https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop) application on UART 1 or call the following nRF Util command: +1. Start capturing traces using the [Cellular Monitor app](https://docs.nordicsemi.com/bundle/nrf-connect-cellularmonitor/page/index.html) on UART 1 or call the following nRF Util command: ```bash nrfutil trace lte --input-serialport /dev/tty.usbmodemxxxxxx --output-raw raw-file.bin ``` -3. Execute the dump command: +1. Execute the dump command: ```bash uart:~$ modem_trace stop uart:~$ modem_trace dump_uart ``` -4. When the traces have been captured they can be converted to PCAP in [Cellular Monitor](https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop) for analysis. +1. When the traces have been captured, they can be converted to PCAP in the Cellular Monitor app for analysis. ### Application logs and modem traces over RTT - Parallel capture @@ -577,9 +581,13 @@ JLinkRTTLogger -Device NRF9160_XXAA -If SWD -Speed 50000 -RTTChannel 2 modem_tra JLinkRTTLogger -Device NRF9160_XXAA -If SWD -Speed 50000 -RTTChannel 0 terminal.txt ``` -!!! note "Note" - - You may need to adjust the RTT channel numbers depending on your configuration. The default channel mapping is: terminal: 0, shell: 1, modem trace: 2. +> [!NOTE] +> You may need to adjust the RTT channel numbers depending on your configuration. +> The following is the default channel mapping: +> +> * Terminal: 0 +> * Shell: 1 +> * Modem trace: 2 For more information, see [nRF Connect SDK Modem Tracing](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrfxlib/nrf_modem/doc/modem_trace.html). diff --git a/docs/images/device_information.png b/docs/images/device_information.png index b79ecf81d913ef4a8e4a2d3fc7b18a92310e1be4..4b9c09ed5a68e212b97d24a58edf21b46531c240 100644 GIT binary patch literal 41437 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 TZC>0r1`zOc^>bP0l+XkKD);18 diff --git a/docs/index.md b/docs/index.md index 724c7cbe..ced84fa8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,6 @@ # Asset Tracker Template -The Asset Tracker Template is a framework for developing IoT applications on nRF91-based devices. It is built on the [nRF Connect SDK](https://www.nordicsemi.com/Products/Development-software/nRF-Connect-SDK) and [Zephyr RTOS](https://docs.zephyrproject.org/latest/), and provides a modular, event-driven architecture suitable for battery-powered IoT use cases. The framework supports features such as cloud connectivity, location tracking, and sensor data collection. +The Asset Tracker Template is a modular framework for developing IoT applications on nRF91-based devices. It is built on the [nRF Connect SDK](https://www.nordicsemi.com/Products/Development-software/nRF-Connect-SDK) and [Zephyr RTOS](https://docs.zephyrproject.org/latest/), and provides a modular, event-driven architecture suitable for battery-powered IoT use cases. The framework supports features such as cloud connectivity, location tracking, and sensor data collection. The system is organized into modules, each responsible for a specific functionality, such as managing network connectivity, handling cloud communication, or collecting environmental data. Modules communicate through [zbus](https://docs.nordicsemi.com/bundle/ncs-latest/page/zephyr/services/zbus/index.html) channels, ensuring loose coupling and maintainability. @@ -16,6 +16,8 @@ The framework is designed for customization, allowing you to: More information on how to customize the template can be found in the [Customization](common/customization.md) document. +The Asset Tracker Template is an add-on and released separately from the [Asset-Tracker-Template](https://github.com/nrfconnect/Asset-Tracker-Template) repository. + **Supported and verified hardware**: * [Thingy:91 X](https://www.nordicsemi.com/Products/Development-hardware/Nordic-Thingy-91-X) @@ -23,6 +25,95 @@ More information on how to customize the template can be found in the [Customiza If you are not familiar with the nRF91 Series SiPs and cellular in general, it is recommended to go through the [Nordic Developer Academy Cellular Fundamentals Course](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals) to get a better understanding of the technology and how to customize the template for your needs. +## Quick Start + +For detailed setup instructions using the [nRF Connect for VS Code extension](https://docs.nordicsemi.com/bundle/nrf-connect-vscode/page/index.html) and advanced configuration options, see the [Getting Started Guide](docs/common/getting_started.md). + +For pre-built binaries, refer to the latest tag and release artifacts documentation; [release artifacts](docs/common/release.md). + +> [!TIP] +> Download and run the [Quick Start app](https://docs.nordicsemi.com/bundle/nrf-connect-quickstart/page/index.html) in the [nRF Connect for Desktop](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Connect-for-desktop) for a guided setup and provisioning process. +> +> You can also refer to [Exercise 1](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals/lessons/lesson-1-cellular-fundamentals/topic/lesson-1-exercise-1/) in [Nordic Developer Academy Cellular Fundamentals Course](https://academy.nordicsemi.com/courses/cellular-iot-fundamentals). + +### Prerequisites + +* nRF Connect SDK development environment ([setup guide](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/installation.html)) + +### Build and Run + +
+1. Initialize workspace: + + ```shell + # Install nRF Util + pip install nrfutil + + # or follow install [documentation](https://docs.nordicsemi.com/bundle/nrfutil/page/guides/installing.html) + + # Install toolchain + nrfutil toolchain-manager install --ncs-version v3.1.0 + + # Launch toolchain + nrfutil toolchain-manager launch --ncs-version v3.1.0 --shell + + # Initialize workspace + west init -m https://github.com/nrfconnect/Asset-Tracker-Template.git --mr main asset-tracker-template + cd asset-tracker-template/project/app + west update + ``` +
+ +
+2. Build and flash: + + **For Thingy:91 X:** + + ```shell + west build --pristine --board thingy91x/nrf9151/ns + west thingy91x-dfu # For Thingy:91 X serial bootloader + # Or with external debugger: + west flash --erase + ``` + + **For nRF9151 DK:** + + ```shell + west build --pristine --board nrf9151dk/nrf9151/ns + west flash --erase + ``` +
+ +
+ +3. Provision device: +
    +
  1. Get the device attestation token over terminal shell: + + ```bash + at at%attesttoken + ``` + +Token is printed automatically on first boot of unprovisioned devices.
  2. +
  3. Select **Security Services** in the left sidebar.
  4. +
  5. Select **Claimed Devices**.
  6. +
  7. Click **Claim Device**.
  8. +
  9. Copy and paste the attestation token into the **Claim token** text box.
  10. +
  11. Set rule to nRF Cloud Onboarding and click **Claim Device**.
  12. + +
    +If "nRF Cloud Onboarding" rule is not showing: + +Create a new rule using the following configuration:
    + +Claim Device +
    + +
  13. Wait for the device to provision credentials and connect to nRF Cloud over CoAP. Once connected, the device must be available under the **Devices** section in the **Device Management** navigation pane on the left.
  14. + +See [Provisioning](docs/common/provisioning.md) for more details. +
+
## Key Technical Features diff --git a/docs/modules/cloud.md b/docs/modules/cloud.md index 8a9e68d0..7238b6b5 100644 --- a/docs/modules/cloud.md +++ b/docs/modules/cloud.md @@ -16,18 +16,13 @@ The following sections cover the module’s main messages, configurations, and s ### Integration with storage module -The cloud module subscribes to `STORAGE_CHAN` and `STORAGE_DATA_CHAN` to support both buffered and passthrough data flows: +The cloud module subscribes to the `STORAGE_CHAN` and `STORAGE_DATA_CHAN` channels to support both buffered and passthrough data flows: -- **Buffered flow (batch)**: The cloud module handles `STORAGE_BATCH_AVAILABLE`, - `STORAGE_BATCH_EMPTY`, `STORAGE_BATCH_BUSY`, and `STORAGE_BATCH_ERROR` on `STORAGE_CHAN` and - consumes batch items using `storage_batch_read()` until the batch is exhausted, then issues - `STORAGE_BATCH_CLOSE`. +- **Buffered flow (batch)**: The cloud module handles `STORAGE_BATCH_AVAILABLE`, `STORAGE_BATCH_EMPTY`, `STORAGE_BATCH_BUSY`, and `STORAGE_BATCH_ERROR` on the `STORAGE_CHAN` channel and consumes batch items using the `storage_batch_read()` function until the batch is exhausted, then issues `STORAGE_BATCH_CLOSE`. -- **Passthrough/flush flow**: The cloud module receives `STORAGE_DATA` on `STORAGE_DATA_CHAN` and - forwards the contained data to nRF Cloud. +- **Passthrough/flush flow**: The cloud module receives `STORAGE_DATA` on `STORAGE_DATA_CHAN` and forwards the contained data to nRF Cloud. -The periodic request interval for buffered data can be configured with -`CONFIG_APP_STORAGE_DATA_SEND_INTERVAL_SECONDS` in `Kconfig.main`. +The periodic request interval for buffered data can be configured with the `CONFIG_APP_STORAGE_DATA_SEND_INTERVAL_SECONDS` Kconfig option in the `Kconfig.main` file. ## Messages diff --git a/docs/modules/location.md b/docs/modules/location.md index c7941fa2..2a3a77a7 100644 --- a/docs/modules/location.md +++ b/docs/modules/location.md @@ -10,9 +10,11 @@ The module performs the following tasks: - Updating system time using GNSS time data when available. - Publishing location status updates to other modules. -The location module works in conjunction with the network module, as GNSS functionality can only be initialized after the modem is initialized and enabled. It uses the Location library's event handler to process various location-related events and publish status updates through the zbus messaging system. +The location module works in conjunction with the network module, as GNSS functionality can only be initialized after the modem is initialized and enabled. +It uses the Location library's event handler to process various location-related events and publish status updates through the zbus messaging system. -In the following sections, the module's main messages, configurations, and state machine are covered. Refer to the source files (`location.c`, `location.h`, and `Kconfig.location`) for implementation details. +In the following sections, the module's main messages, configurations, and state machine are covered. +Refer to the source files (`location.c`, `location.h`, and `Kconfig.location`) for implementation details. ## Messages @@ -20,21 +22,21 @@ The location module publishes and receives messages over the zbus channel `LOCAT ### Input Messages -- **LOCATION_SEARCH_TRIGGER** +- `LOCATION_SEARCH_TRIGGER`: Triggers a location search request. The module will attempt to get the current location using configured methods. ### Output Messages -- **LOCATION_SEARCH_STARTED** +- `LOCATION_SEARCH_STARTED`: Indicates that a location search has been initiated. -- **LOCATION_SEARCH_DONE** +- `LOCATION_SEARCH_DONE`: Indicates that a location search has completed (successfully or with error/timeout). -- **LOCATION_CLOUD_REQUEST** +- `LOCATION_CLOUD_REQUEST`: Contains cellular neighbor cell and/or Wi-Fi access point information that should be sent to cloud services for location resolution. -- **LOCATION_AGNSS_REQUEST** +- `LOCATION_AGNSS_REQUEST`: Indicates that A-GNSS assistance data is needed for GNSS positioning. The message types used by the location module are defined in `location.h`: diff --git a/docs/modules/main.md b/docs/modules/main.md index 3d9ed5a3..e09c4b5b 100644 --- a/docs/modules/main.md +++ b/docs/modules/main.md @@ -14,6 +14,7 @@ The Main module uses the following zbus channels, both for subscribing to incomi |---------------------|-----------------------------------------------------------------------------------------------| | **BUTTON_CHAN** | Processes user button presses for manually triggering data samples. | | **CLOUD_CHAN** | Receive connectivity status (connected, disconnected) and cloud response data. Trigger device shadow polling to retrieve configuration updates. | +| **STORAGE_CHAN** | Control the storage module and receive control or status responses. | | **ENVIRONMENTAL_CHAN** | Request sensor data from the environmental module. | | **FOTA_CHAN** | Poll for FOTA updates and manage the FOTA process. Apply FOTA updates to install the new firmware image. | | **LED_CHAN** | Update LED pattern to indicate system state. | @@ -31,11 +32,11 @@ The Main module can be configured using the following Kconfig options: * **CONFIG_APP_SENSOR_SAMPLING_INTERVAL_SECONDS:** Default sensor data sampling interval. Triggers sensor sampling and location search. - In passthrough mode, also triggers cloud shadow and FOTA status polling and data sending. + In passthrough mode, it also triggers cloud shadow and FOTA status polling and data sending. * **CONFIG_APP_CLOUD_SYNC_INTERVAL_SECONDS:** - Interval for cloud synchronization activities including polling and data sending. Triggers cloud shadow and FOTA status polling. - Data sending only applies when storage module is in buffer mode. + Interval for cloud synchronization activities, including polling and data sending. Triggers cloud shadow and FOTA status polling. + Data sending only applies when the storage module is in buffer mode. * **CONFIG_APP_REQUEST_NETWORK_QUALITY:** When enabled, requests network quality metrics during regular sampling. diff --git a/docs/modules/storage.md b/docs/modules/storage.md index 051eb627..73689b71 100644 --- a/docs/modules/storage.md +++ b/docs/modules/storage.md @@ -22,8 +22,8 @@ The storage module implements a state machine with the following states and tran - **PASSTHROUGH**: Forwards data immediately as `STORAGE_DATA` on `STORAGE_DATA_CHAN`. - **BUFFER**: Stores data in backend, serves flush and batch requests. Has sub-states `IDLE` and `PIPE_ACTIVE`. -Initial state: `PASSTHROUGH` (default) or `BUFFER` (if `CONFIG_APP_STORAGE_INITIAL_MODE_BUFFER=y`). -Runtime switching: Send `STORAGE_MODE_*_REQUEST` on `STORAGE_CHAN`. +- Initial state: `PASSTHROUGH` (default) or `BUFFER` (if `CONFIG_APP_STORAGE_INITIAL_MODE_BUFFER=y`). +- Runtime switching: Send `STORAGE_MODE_*_REQUEST` on `STORAGE_CHAN`. ### Backend @@ -115,10 +115,9 @@ CONFIG_APP_STORAGE_SHELL_STATS=n # CONFIG_APP_NETWORK=n ``` -!!! note "Note" - - - If you later enable buffer or batch, increase the value of the `CONFIG_APP_STORAGE_BATCH_BUFFER_SIZE` Kconfig option, so that at least one header plus the largest item fits. - - The actual RAM consumed by ring buffers and slabs scales with which data types are enabled and the value of the `CONFIG_APP_STORAGE_MAX_RECORDS_PER_TYPE` Kconfig option. +> [!NOTE] +> - If you later enable buffer or batch, increase the value of the `CONFIG_APP_STORAGE_BATCH_BUFFER_SIZE` Kconfig option, so that at least one header plus the largest item fits. +> - The actual RAM consumed by ring buffers and slabs scales with which data types are enabled and the value of the `CONFIG_APP_STORAGE_MAX_RECORDS_PER_TYPE` Kconfig option. ## Messages @@ -237,7 +236,7 @@ The following includes the key configuration categories: ### Development Features -- **`CONFIG_APP_STORAGE_SHELL`** (default: y): Enable shell commands for storage interaction. +- **`CONFIG_APP_STORAGE_SHELL`** (default: `y`): Enable shell commands for storage interaction. - **`CONFIG_APP_STORAGE_SHELL_STATS`**: Enable statistics commands (increases code size). @@ -324,10 +323,9 @@ int storage_batch_read(struct storage_data_item *out_item, k_timeout_t timeout); It reads stored data through the batch interface, handling header parsing and data extraction automatically. All other operations (requesting batch access, session management, etc.) go through zbus messages. -!!! important "Important" - - This function should only be called after receiving a `STORAGE_BATCH_AVAILABLE` message in response to a `STORAGE_BATCH_REQUEST`. - When done consuming all items, send `STORAGE_BATCH_CLOSE` with the same `session_id`. +> [!IMPORTANT] +> This function should only be called after receiving a `STORAGE_BATCH_AVAILABLE` message in response to a `STORAGE_BATCH_REQUEST`. +> When done consuming all items, send `STORAGE_BATCH_CLOSE` with the same `session_id`. ## Usage @@ -343,7 +341,7 @@ struct storage_msg msg = { .type = STORAGE_MODE_BUFFER_REQUEST }; err = zbus_chan_pub(&STORAGE_CHAN, &msg, K_SECONDS(1)); ``` -Responses: `STORAGE_MODE_PASSTHROUGH`/`STORAGE_MODE_BUFFER` (success) or `STORAGE_MODE_CHANGE_REJECTED` (e.g., batch active). +Responses: `STORAGE_MODE_PASSTHROUGH`/`STORAGE_MODE_BUFFER` (success) or `STORAGE_MODE_CHANGE_REJECTED` (for example, batch active). ### Data Retrieval diff --git a/docs/stylesheets/style.css b/docs/stylesheets/style.css new file mode 100644 index 00000000..4ef7d409 --- /dev/null +++ b/docs/stylesheets/style.css @@ -0,0 +1,4 @@ +/* Hide in MkDocs */ +.hidden-content { + display: none; +} diff --git a/mkdocs.yml b/mkdocs.yml index 01d3b418..417917d9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -52,14 +52,15 @@ plugins: nav: - Overview: index.md - - Getting Started: common/getting_started.md + - Getting started: common/getting_started.md - Architecture: common/architecture.md - Configuration: common/configuration.md - Customization: common/customization.md - - Location Services: common/location_services.md - - Achieving Low Power: common/low_power.md - - nRF Cloud Fota: common/fota.md - - Testing and CI Setup: common/test_and_ci_setup.md + - Provisioning: common/provisioning.md + - Location services: common/location_services.md + - Achieving low power: common/low_power.md + - Firmware Updates (FOTA): common/fota.md + - Testing and CI setup: common/test_and_ci_setup.md - Tooling and Troubleshooting: common/tooling_troubleshooting.md - Application modules: - Main module: modules/main.md @@ -72,5 +73,5 @@ nav: - Network module: modules/network.md - Power module: modules/power.md - Storage module: modules/storage.md - - Release Artifacts: common/release.md + - Release artifacts: common/release.md - Release notes: common/release_notes.md