The following instructions use the
[lighting app](https://github.com/project-chip/connectedhomeip/tree/v1.0-branch/examples/lighting-app)
example from the Matter SDK along with a Nordic nRF52840
development board.

## Environment Setup

These instructions are based on a Docker-based installation of the
[nRF Connect](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop)
toolchain. If you prefer not to use Docker, instructions for installing nRF
Connect natively on a host computer are
[on the Nordic site](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/gs_assistant.html#).

## Check out the Matter SDK

    user@host> mkdir otaprep
    user@host> cd otaprep
    user@host> git clone https://github.com/project-chip/connectedhomeip.git
    user@host> cd connectedhomeip/
    user@host> git fetch origin v1.0-branch
    user@host> git checkout FETCH_HEAD

Check the correct Docker image to be used. Use one of the images created for
the Matter SDK continuous integration.

    user@host> cat .github/workflows/examples-nrfconnect.yaml | grep chip-build
                image: connectedhomeip/chip-build-nrf-platform:0.5.99

Connect the Nordic board to the computer. Check the USB enumeration of
its serial interface:

On macOS:

    user@host> ls /dev/tty.usbmodem*
    /dev/tty.usbmodem0123456789000

On Linux, either:

    user@host> ls /dev/tty*AC*
    /dev/ttyACM0

or

    user@host> ls /dev/tty*USB*
    /dev/ttyUSB0

Run a container using the information gathered on the previous command. Pass
the flags to mount the host Matter SDK folder and the usb
serial interface into the container.

    user@host> docker run --name container_name -it --user $(id -u):$(id -g) --mount source=$(pwd),target=/workspace,type=bind connectedhomeip/chip-build-nrf-platform:0.5.99 /bin/bash

> [!NOTE]
> **Note:** The argument `--user $(id -u):$(id -g)` allows one to run the container as the current user, instead of the default (`root`). This avoids problems ownership of files generated by the build in the local Matter SDK repository. It also has two minor but harmless side effects to be aware of:  
> 1. When you first run the container, you may see the message `groups: cannot find name for group ID XXXX`, and  
> 2. The `bash` prompt in the container starts with `I have no name!`.

## Stop and start the Matter Docker container

Whenever you run a `docker run` command, you'll create a new container with
the specified image. When you do this, your old data, which was saved on a
previous container instance, is lost. Sometimes this is what you want to
happen, because it allows you to start with a fresh installation. But in this
example you most likely want to save your work and environment configuration
between sessions.

    user@host> docker stop container_name

When you are ready to run again, start the container and open a terminal
window:

    user@host> docker start container_name
    user@host> docker exec -it container_name /bin/bash

You may open additional terminal sessions to your container with:

    user@host> docker exec -it container_name /bin/bash

Or start a root session using:

    user@host> docker exec -u 0 -it container_name /bin/bash

## Initialize the SDK

In the container, initialize the Matter SDK and the
environment variables for the Nordic nRF52 toolchain. The
Matter SDK initialization often takes several minutes.

```bash
cd /workspace
```

```bash
git submodule update --init --recursive
```

```bash
source ./scripts/bootstrap.sh
```

```bash
source ./scripts/activate.sh
```

```bash
export ZEPHYR_BASE=/opt/NordicSemiconductor/nrfconnect/zephyr
```

```bash
export GNUARMEMB_TOOLCHAIN_PATH="$PW_ARM_CIPD_INSTALL_DIR"
```

```bash
scripts/run_in_build_env.sh "python3 scripts/setup/nrfconnect/update_ncs.py --update --shallow"
```

```bash
source /opt/NordicSemiconductor/nrfconnect/zephyr/zephyr-env.sh
```

## Build and Flash

Configure the VID and PID for the device:

```bash
cd examples/lighting-app/nrfconnect
```

```bash
west build -b nrf52840dk_nrf52840 -t menuconfig
```

In the interactive menu options:

1. `Modules --->`

2. `connectedhomeip --->`

3. `[*] Connected Home over IP protocol stack --->`

4. Enter the `Device vendor ID` (VID) and `Device product ID` (PID) in base-10
   integer format.

5. Ensure the `[*] Enable OTA requestor` flag is selected.

6. Press **s** to save the configuration, press **Enter** to confirm, then
   **q** to exit `menuconfig`.

## Set up test certificates

Follow the steps in [Create Matter device test certificates](https://developers.home.google.com/matter/test/certificates.md.txt)
to create CD, DAC and PAI certificates.

## Build your device

```bash
west build -b nrf52840dk_nrf52840
```

## Flash your device

This is done on the host computer, *not* in the Docker container.

If you don't already have the nRFConnect command line tools, download and
[install them](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/gs_assistant.html#).

    user@host> nrfjprog --program build/zephyr/merged.hex --chiperase -f NRF52

Open a terminal connection to your device either on the host or on the
container. Use your favorite terminal tool such as `minicom` or GNU `screen`.

    user@host> minicom -c on -D /dev/ttyACM0 115200
    user@host> screen /dev/ttyACM0 115200

## Create and upload OTA image

Once you have flashed your device, change build settings once more to create
an OTA image with an incremented device software version.

Launch Zephyr `menuconfig`:

```bash
west build -b nrf52840dk_nrf52840 -t menuconfig
```

In the interactive menu options:

1. `Modules -->`

2. `connectedhomeip -->`

3. `Connected Home over IP protocol stack -->`

4. Change `Device Software Version` to `2`.

5. Change `Device Software Version String` to `prerelease-2`.

6. Press **s** to save the configuration, press **Enter** to confirm, then
   **q** to exit `menuconfig`.

Build the new Matter OTA bundle file. The output is placed
in `build/zephyr/zephyr.bin`.

```bash
/workspace/src/app/ota_image_tool.py create -v hex_VID -p hex_PID -vn version_no -vs version_string path_to_binary -da digest_algorithm path_to_ota_file
```

Confirm the properties of your generated Matter OTA bundle
file:

```bash
/workspace/examples/lighting-app/nrfconnect# /workspace/src/app/ota_image_tool.py show firmware-ota-update-test.bin
```

    Magic: 1beef11e
    Total Size: 951784
    Header Size: 72
    Header TLV:
      [0] Vendor Id: XXXXX (0xXXXX)
      [1] Product Id: 32768 (0x8000)
      [2] Version: 2 (0x2)
      [3] Version String: prerelease-2
      [4] Payload Size: 951696 (0xe8590)
      [8] Digest Type: 1 (0x1)
      [9] Digest: 75f2e8b0c8e922b8bb3841504190bcdd83533e936a284c7254d29327d605c930

Because the Matter SDK is mounted from your container host,
the OTA Image is also available on your container host. Upload the OTA image to
the Google Home Developer Console by following the [OTA upload
instructions](https://developers.home.google.com/matter/ota/configuration#upload_the_ota_image).

Commission the device and observe the OTA process.

Open a terminal connection to the device either on the host or on the
container. Use your favorite terminal such as `minicom` or GNU `screen`:

```bash
minicom -c on -D /dev/ttyACM0 115200
```

Press the reset button of the device to see logs from boot.

In the device output, you should see the VID and PID you set, as well as
the URL for the commissioning QR code:

    I: nRF5 802154 radio initialized
    I: 4 Sectors of 4096 bytes

    (...)

    I: 681 [SVR]Server Listening...
    I: 684 [DL]Device Configuration:
    I: 687 [DL]  Serial Number: 11223344556677889900
    I: 692 [DL]  Vendor Id: XXXXX (0xXXXX)
    I: 695 [DL]  Product Id: XXXXX (0xXXXX)
    I: 699 [DL]  Hardware Version: 0
    I: 702 [DL]  Setup Pin Code (0 for UNKNOWN/ERROR): 20202021
    I: 708 [DL]  Setup Discriminator (0xFFFF for UNKNOWN/ERROR): 3840 (0xF00)
    I: 714 [DL]  Manufacturing Date: (not set)
    I: 718 [DL]  Device Type: 65535 (0xFFFF)
    I: 723 [SVR]SetupQRCode: [MT:6FCJ142C00KA0648G00]
    I: 727 [SVR]Copy/paste the below URL in a browser to see the QR Code:
    I: 733 [SVR]https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT%000000000000000000000
    I: 742 [SVR]Manual pairing code: [30900112302]
    I: 747 [DL]CHIP task running
    I: 752 [DL]CHIPoBLE advertising started
    I: 757 [DL]NFC Tag emulation started

Ensure your Hub is online, and commission the device with the
Google Home app (GHA) using the QR code from the link found in the log.

Leave the device logging its activities after commissioning.

You should see the following text in the device log:

    /* Hub OTA provider identification */
    I: 69642 [SWU]OTA Requestor received AnnounceOTAProvider
    D: 69647 [SWU]  FabricIndex: 1
    D: 69649 [SWU]  ProviderNodeID: 0x00000000XXXXXXXX
    D: 69654 [SWU]  VendorID: 0x6006
    D: 69657 [SWU]  AnnouncementReason: 0
    D: 69660 [SWU]  Endpoint: 2
    ...
    D: 69799 [SWU]Establishing session to provider node ID 0x00000000FC843D94 on fabric index 1
    ...
    D: 262265 [SWU]QueryImageResponse:
    D: 262268 [SWU]  status: 0
    D: 262271 [SWU]  imageURI: bdx://00000000FC843D94/37f09fd6-0000-0000-0000-000000000000
    D: 262278 [SWU]  softwareVersion: 2
    D: 262281 [SWU]  softwareVersionString: 2
    D: 262285 [SWU]  updateToken: 36
    D: 262288 [SWU]  userConsentNeeded: 0
    D: 262292 [SWU]Update available from version 0 to 2
    ...
    D: 262372 [SWU]Establishing session to provider node ID 0x00000000FC843D94 on fabric index 1
    ...
    D: 262409 [SWU]BDX::SendMessage

After the image is applied, the device reboots. After reboot, the compile time
of the image should match that of the one uploaded to the
Developer Console.

## Validate the OTA Software Update

The device software version can be checked using the Google Home App (GHA). Once a device is commissioned, follow these procedures:

1. Long press the device tile on GHA main screen
2. Tap the icon in the top right
3. Tap **Technical information**
4. Check the **Software version** field

![Google Home App screen showing software version field](https://developers.home.google.com/static/matter/ota/images/gha-software-version.png)