Test OTA on Espressif ESP32

The following instructions use the lighting app example from the Matter SDK along with an M5Stack ESP32 development board.

Build environment setup

First, clone the Matter SDK.

In this example, we check out the minimum supported commit for Google Home’s Matter Release 5:

$ mkdir otaprep
$ cd otaprep
git clone https://github.com/project-chip/connectedhomeip.git
cd connectedhomeip
git fetch origin v1.0-branch
git checkout FETCH_HEAD
git submodule update --init --recursive
source ./scripts/activate.sh

Next, we check the version used in the ESP32 GitHub Workflow to determine which Docker image best suits our build:

$ cat .github/workflows/examples-esp32.yaml | grep chip-build | head -n 1
            image: connectedhomeip/chip-build-esp32:0.5.99

We run a container from the Docker image, passing flags to mount the Matter SDK in the container and to provide access to the ESP32 device.

$ docker run --name container_name -it --user $(id -u):$(id -g) --mount source=$(pwd),target=/workspace,type=bind --device=/dev/ttyUSB0 connectedhomeip/chip-build-esp32:0.5.99 /bin/bash

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, we initialize the Matter SDK and ESP IDF:

cd /workspace
git submodule update --init --recursive
source ./scripts/activate.sh
source /opt/espressif/esp-idf/export.sh

Build and flash

The next task is to build the image and flash the development kit to receive the Matter OTA firmware update.

To do this, you must create an image.

First configure the build using the menuconfig utility from the ESP IDF.

cd examples/lighting-app/esp32
idf.py menuconfig

In the interactive menu, configure the following settings:

  1. Component config --->

  2. CHIP Device Layer --->

  3. Device Identification Options --->

  4. Set Vendor ID to your Connectivity Standards Alliance (Alliance)-assigned VID.

  5. Set Product ID to the PID you set on the Matter integration in the Google Home Developer Console.

Enable the OTA Requestor flag:

  1. Component config -->

  2. CHIP Core -->

  3. System options --->

  4. Enable the OTA Requestor flag [*] Enable OTA Requestor

  5. Press ESC twice to return to the top level menu.

Enable the Matter OTA Image creation flag:

  1. Component config -->

  2. CHIP Device Layer --->

  3. Matter OTA Image --->

  4. [*] Generate OTA IMAGE

Set the version number:

  1. Application manager --->

  2. Select [*] Get the project version from Kconfig

  3. Set Project version (NEW) to 1.0

  4. Press s to save the configuration, press Enter twice, then q to exit menuconfig.

Set up test certificates

Follow the steps in Create Matter device test certificates to create CD, DAC, and PAI certificates.

Build your device

Now run the build and flash the device:

idf.py build
idf.py -p /dev/ttyUSB0 erase_flash
idf.py -p /dev/ttyUSB0 flash

Create and upload the OTA image

Now change the build settings again to create an OTA image. Use the same image, but with an incremented version number.

Run menuconfig.

idf.py menuconfig

In the interactive menu, update the following:

  1. Application manager --->
  2. Select [*] Get the project version from Kconfig
  3. Set Project version (NEW) to 2.0
  4. Press s to save the configuration, press Enter twice, then press q to exit menuconfig.

Build and retrieve the image. The example below demonstrates both the location of the image for OTA and the output when parsing with the ota_image_tool.py.

cd build
/workspace/src/app/ota_image_tool.py show ./chip-lighting-app-ota.bin
Magic: 1beef11e
Total Size: 1243360
Header Size: 64
Header TLV:
  [0] Vendor Id: XXXXX (0x000)
  [1] Product Id: XXXXX (0x000)
  [2] Version: 2 (0x2)
  [3] Version String: v2.0
  [4] Payload Size: 1243280 (0x12f890)
  [8] Digest Type: 1 (0x1)
  [9] Digest: e367f4d71e2ccd554b9a399c864abbf2c039382ef1def1b986fb2f59a99923a8

Because the Matter SDK is mounted from your container host, the OTA image is available on your container host.

Upload the OTA image to the Developer Console by following the OTA upload instructions.

Commission to Google Home and observe OTA

Ensure your device is connected to the host Linux machine with USB. The following example shows the use of GNU screen to read the device logs:

screen -L /dev/ttyUSB0 115200

This displays the output from the device to your terminal and writes the same output to the default screen log file named screenlog.0.

You may open the screenlog.0 file in another text editor or display it in another shell with cat, tail, more, or grep.

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

In the device output, you should see the VID and PID you set earlier, as well as a URL to the QR code image that you'll use to commission the device.

[0;32mI (2388) chip[DIS]: Advertise commission parameter vendorID=XXXXX productID=XXXX discriminator=3840/15 cm=1[0m

[0;32mI (1928) chip[SVR]: SetupQRCode: [MT:E59-000000000000000][0m

https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT%3AE59-000000000000000

Ensure your Hub is online in your home.

Commission the device with the Google Home app (GHA) using the QR code from the link that appears in the log file.

Let the device run uninterrupted for several minutes after commissioning. You should observe log output related to OTA Requestor, OTA image download, and OTAImageProcessor.

After the image is installed, observe that the compile time of the image matches that of the one uploaded to the console, and is later than the compile time that was reported at first boot. Executing grep with the following pattern in regex mode on screenlog.0 can illustrate the OTA process:

$ grep -E "(Compile time|OTA)" screenlog.0
I (76) boot:  1 otadata          OTA data         01 00 0000f000 00002000
I (91) boot:  3 ota_0            OTA app          00 10 00020000 00177000
I (99) boot:  4 ota_1            OTA app          00 11 001a0000 00177000
I (645) cpu_start: Compile time:     Oct 15 2022 06:21:59
I (135558) chip[SWU]: OTA Requestor received AnnounceOTAProvider
I (540658) chip[SWU]: OTA image downloaded to offset 0x1a0000
I (541348) OTAImageProcessor: Applying, Boot partition set offset:0x1a0000
I (76) boot:  1 otadata          OTA data         01 00 0000f000 00002000
I (91) boot:  3 ota_0            OTA app          00 10 00020000 00177000
I (99) boot:  4 ota_1            OTA app          00 11 001a0000 00177000
I (645) cpu_start: Compile time:     Oct 15 2022 07:35:31
I (76) boot:  1 otadata          OTA data         01 00 0000f000 00002000
I (91) boot:  3 ota_0            OTA app          00 10 00020000 00177000
I (99) boot:  4 ota_1            OTA app          00 11 001a0000 00177000
I (645) cpu_start: Compile time:     Oct 15 2022 07:35:31

After initial execution, you may repeat the steps in the section Create and upload OTA image without uploading a new image. This time, set the versions back to 1.

Run menuconfig, and in the interactive menu options:

  1. Component config -->

  2. CHIP Device Layer --->

  3. Device Identification Options

  4. Set Version String to v1.0.

  5. Set Device Software Version Number to 1.

  6. Press s to save the configuration, then q to exit menuconfig.

Remove the device from your home in the GHA.

Build the image, if it's not already built:

idf.py build

Flash it:

idf.py -p /dev/ttyUSB0 erase_flash
idf.py -p /dev/ttyUSB0 flash

Repeat the steps in Commission to Google Home and observe OTA as needed.

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