欢迎使用 软件

Matter Developer Guide

Overview

This document provides full guidance of Telink Matter solution which
includes such to/uploads/zip/202308171929092D5GN/pics as environment setup, Matter device firmware building
and flashing, Border Router setup including RCP building and flashing,
building and usage of chip-tool etc.

Solution Structure

Ecosystems compatibility and limitations

Compatibility

Telink Matter solution is compatible with next ecosystems:

  • apple home Apple Home (iOS)

  • google home Google Home (iOS/Android)

  • alexa Amazon Alexa (iOS/Android)

  • smart things Samsung Smart Things (iOS/Android)

Limitations

  • Apple (iOS): When Matter device is added to Apple Home or other ecosystem
    Home app (which uses Apple Home APIs), two fabrics are added, one for the Home
    app and other for the Apple keychain. So if users want to completely remove
    device they have manually remove device (fabric 1) from Apple keychain
    (via Apple settings menu) as well as remove device (fabric 2) from Home app.

  • Google: official list of unsupported features.

  • Amazon: Alexa requires rotation device id, which is already enabled by default
    in Telink Matter solution. Also requires Thread Networks Scaning durind
    commissioning (BLE session), added Thread Networks prescanning before start BLE
    due to non-cuncurrent mode limitation.

  • Samsung: inherits Apple/Google (depends on OS) limitations, because works via
    OS APIs.

Required Equipment

  • TLSR9518ADK80D as Matter device.
  • TLSR9518ADK80D as RCP (Radio CoProcessor).
  • RaspberryPi4 or higher, as part of border router. In case you want to use RaspberryPi3, additional work is needed. See "Using Raspberry Pi3 with internal UART" for more details.
  • SD card for RPi. At least 8 GB.
  • Host PC with Debian based distro (like Ubuntu v20.04 LTS and later)
    which will be used as a build machine and as host for Matter device.
  • Telink JTAG programmer to program Matter device and RCP.
  • Wi-Fi Router that act as Wi-Fi Access Point.

Environment setup

Brief environment setup

Docker setup

To avoid routine with Zephyr environment setup in section 3.2.1 and 3.2.3,
user can just pull and run existing docker image that contains ready to use
environment.

Run the Docker container (this will take a while to complete the first time):

For Matter v1.0-branch branch use the following line:

docker run -it --rm -v $PWD:/host -w /host connectedhomeip/chip-build-telink:$(wget -q -O - https://raw.githubusercontent.com/project-chip/connectedhomeip/v1.0-branch/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}')

Docker image 'connectedhomeip/chip-build-telink:0.6.06'

For Matter master branch use the following line:

docker run -it --rm -v $PWD:/host -w /host ghcr.io/project-chip/chip-build-telink:$(wget -q -O - https://raw.githubusercontent.com/project-chip/connectedhomeip/master/.github/workflows/examples-telink.yaml 2> /dev/null | grep chip-build-telink | awk -F: '{print $NF}')

Docker image 'ghcr.io/project-chip/chip-build-telink:1'

Compatible docker image version can be found in next file:

.github/workflows/examples-telink.yaml

Matter setup

  1. Setup dependencies:

    In the new terminal go through Step 1 in
    3.2.2 Matter project setup to setup dependencies.

  2. Matter project:

    In the Docker container go through Step 2-4 in
    3.2.2 Matter project setup to clone Matter
    repository into a clean folder, update submodules for Telink platform and run bootstrap.

Then, follow instruction in Chapter 4. Matter Firmware to build firmware.

Manual environment setup

Zephyr project setup

Please execute APT update and upgrade before the following steps.

sudo apt update
sudo apt upgrade
  1. Install dependencies:

    wget https://apt.kitware.com/kitware-archive.sh
    sudo bash kitware-archive.sh
    sudo apt install --no-install-recommends git cmake ninja-build gperf \
    ccache dfu-util device-tree-compiler \
    python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file \
    make gcc gcc-multilib g++-multilib libsdl2-dev

    Zephyr requires minimum version for main dependencies for now, such as
    CMake (3.20.0), Python3 (3.6), Devicetree compiler (1.4.6).

    cmake --version
    python3 --version
    dtc --version

    Please verify versions installed on your system before next steps;
    Otherwise please switch APT mirror to stable and latest one, or update
    these dependencies manually.

  2. Install west:

    pip3 install --user -U west
    echo 'export PATH=~/.local/bin:"$PATH"' >> ~/.bashrc
    source ~/.bashrc

    Make sure ~/.local/bin is on $PATH environment variable:

  3. Get the Zephyr source code:

    west init ~/zephyrproject
    cd ~/zephyrproject
    west update
    west blobs fetch hal_telink
    west zephyr-export

    Command west blobs fetch hal_telink is needed only for Matter master branch.

    It usually costs extra time to get the Zephyr source code using
    west init ~/zephyrproject and west update within Chinese
    mainland. Moreover, some project may fail to update from foreign
    servers.
    Please find alternative methods to download the latest source code.

  4. Install additional Python dependencies for Zephyr:

    pip3 install --user -r ~/zephyrproject/zephyr/scripts/requirements.txt
  5. Setup toolchain:

    Download Zephyr toolchain (about 1~2 GB) into local directory to allow
    you to flash most boards.
    It may take extra time within Chinese mainland.

    For v1.0-branch used Zephyr SDK v0.13.2:

    wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.13.2/zephyr-sdk-0.13.2-linux-x86_64-setup.run
    chmod +x zephyr-sdk-0.13.2-linux-x86_64-setup.run
    ./zephyr-sdk-0.13.2-linux-x86_64-setup.run -- -d ~/.local/zephyr-sdk-0.13.2

    For master used Zephyr SDK v0.16.1:

    Minimal SDK:

    wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64_minimal.tar.xz
    wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing
    tar xvf zephyr-sdk-0.16.1_linux-x86_64_minimal.tar.xz
    cd zephyr-sdk-0.16.1
    ./setup.sh -t riscv64-zephyr-elf -h -c

    Full SDK:

    wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64.tar.xz
    wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing
    tar xvf zephyr-sdk-0.16.1_linux-x86_64.tar.xz
    cd zephyr-sdk-0.16.1
    ./setup.sh -t riscv64-zephyr-elf -h -c

    Download Zephyr SDK and install it in recommended path as below.

    $HOME/zephyr-sdk[-x.y.z]
    $HOME/.local/zephyr-sdk[-x.y.z]
    $HOME/.local/opt/zephyr-sdk[-x.y.z]
    $HOME/bin/zephyr-sdk[-x.y.z]
    /opt/zephyr-sdk[-x.y.z]
    /usr/zephyr-sdk[-x.y.z]
    /usr/local/zephyr-sdk[-x.y.z]

    Where [-x.y.z] is optional text, and can be any text, for example,
    -0.13.2.
    You cannot move the SDK directory after you have installed it.

  6. Build Hello World Sample

    Please verify the official Zephyr project configure is correct using
    the Hello World sample before continue to set up custom project.

    cd ~/zephyrproject/zephyr
    west build -p auto -b tlsr9518adk80d samples/hello_world

    Build the hello_world example with west build command from the root
    of the Zephyr repository.
    You can find firmware called zephyr.bin under build/zephyr
    directory.

  7. Add environment Zephyr script to ~/.bashrc.

    Here is the difference between prior added and added:

    + source ~/zephyrproject/zephyr/zephyr-env.sh

    You can add the above line using editor such as vi/vim or execute the
    following command in bash.

    echo "source ~/zephyrproject/zephyr/zephyr-env.sh" >> ~/.bashrc

    Execute the following line to active updated shell environment
    immediately.

    source ~/.bashrc
  8. Add Telink Zephyr remote repository:

    Download Telink repo to local as develop branch and update this
    branch.
    For Matter 1.0-release branch use telink_matter_v1.0-branch!

    cd ~/zephyrproject/zephyr
    git remote add telink https://github.com/telink-semi/zephyr
    git fetch telink develop
    git checkout develop
    cd ..
    west update
    west blobs fetch hal_telink

    Command west blobs fetch hal_telink is needed only for Matter master branch.
    This update may cost extra time within Chinese mainland.

More info you could find here: https://docs.zephyrproject.org/latest/getting_started/index.html

Matter project setup

  1. Setup dependencies:

    sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \
    libglib2.0-dev libavahi-client-dev ninja-build python3-venv python3-dev \
    python3-pip unzip libgirepository1.0-dev libcairo2-dev libreadline-dev
  2. Clone Matter project:

    Clone Matter project to your local directory, e.g., /home/${YOUR_USERNAME}/workspace/matter.

    git clone https://github.com/project-chip/connectedhomeip

    This clone may cost extra time within Chinese mainland.

  3. Update submodules:

    Enter the repo root directory and Update submodule:

    cd ./connectedhomeip
    ./scripts/checkout_submodules.py --platform telink
  4. Do bootstrap:

    Download and install packages into local for Matter. It usually takes
    long time when we run it the first time.

    source ./scripts/activate.sh

    This step will generate an invisible folder called .environment
    under the Matter root directory connectedhomeip.
    It may cost extra time or encounter failure within Chinese mainland.

INFO: In case of any troubles with Matter build environment you may try:

  • Remove the environment (in root directory of Matter project):

    rm -rf .environment
  • Redo bootstrap once again:

    source ./scripts/activate.sh
  1. Install ZAP CLI tool (only for master branch):

    According to Matter documentation, ZAP is installed by bootstrap.sh script.
    More info you could find here:
    https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md

Telink tools setup

  1. Download toolchain:

    Download and unzip Telink toolchain into your local directory, e.g. ~,
    to allow you flash Zephyr into Telink board.

    wget http://wiki.telink-semi.cn/tools_and_sdk/Tools/IDE/telink_riscv_linux_toolchain.zip
    unzip telink_riscv_linux_toolchain.zip

    You may spend several minutes on the download because this zipped file
    is around hundreds MB.
    The download may cost extra time outside Chinese mainland.

  2. Setup dependencies:

    sudo dpkg --add-architecture i386
    sudo apt-get update
    sudo apt-get install -y libc6:i386 libncurses5:i386 libstdc++6:i386
  3. Run ICEman.sh script to change udev rules:

    The following step 3 and 4 are set for flashing firmware to
    developement boards on Ubuntu platform.
    If you would like to flash firmware on Windows platform, please igonre
    the following setup.

    sudo sh ${TELINK_TOOLCHAIN_BASE_DIR}/ice/ICEman.sh

    ${TELINK_TOOLCHAIN_BASE_DIR} is Telink SDK root directory, e.g.
    ~/telink_riscv_linux_toolchain.

    If you meet issues related to path or permissions, or disconnection
    from your ubuntu host at current shell, you can enter the above
    directory and then try to execute this script:

    cd ${TELINK_TOOLCHAIN_BASE_DIR}/ice
    source ICEman.sh
  4. In ~/.bashrc add SPI_burn and ICEman to PATH.

    Here is the difference between prior added and added:

    + export PATH=${TELINK_TOOLCHAIN_BASE_DIR}/flash/bin:"$PATH"
    + export PATH=${TELINK_TOOLCHAIN_BASE_DIR}/ice:"$PATH"

Matter firmware

Bootloader configuration

The bootloader build is enabled automatically when the CONFIG_CHIP_OTA_REQUESTOR=y is set.
The bootloader configuration file is located by following path:

connectedhomeip/config/telink/app/bootloader.conf

This file contains the following options:

  • CONFIG_BOOT_BOOTSTRAP - set to y in case if restoring the slot0 partition is expected from slot1 partition in case if slot0 is not bootable or damaged
  • CONFIG_BOOT_SWAP_USING_MOVE - set to y in case if SWAP_MOVE logic need to be used
  • CONFIG_BOOT_SWAP_USING_SCRATCH - set to y in case if SWAP_MOVE using scratch logic need to be used. Enabling this option expecting the availability of scratch partition in DTS
  • CONFIG_BOOT_VALIDATE_SLOT0 - set to y in case if the whole slot0 image need to be validated. With this option disabled the only image magic is validated

The other MCUBoot configuration option are also allowed in this file. For finest tune please refer to official MCUBoot doc.

Flash Layout

For Matter v1.0-branch branch:
telink_matter_v1.0-branch:

...
&flash {
  reg = <0x20000000 0x200000>;

  partitions {
    compatible = "fixed-partitions";
    #address-cells = <1>;
    #size-cells = <1>;

    boot_partition: partition@0 {
      label = "mcuboot";
      reg = <0x00000000 0x10000>;
    };
    slot0_partition: partition@10000 {
      label = "image-0";
      reg = <0x10000 0xE0000>;
    };
    scratch_partition: partition@f0000 {
      label = "image-scratch";
      reg = <0xf0000 0x4000>;
    };
    factory_partition: partition@f4000 {
      label = "factory-data";
      reg = <0xf4000 0x1000>;
    };
    storage_partition: partition@f5000 {
      label = "storage";
      reg = <0xf5000 0xa000>;
    /* region <0xff000 0x1000> is reserved for Telink B91 SDKs data */
    };
    slot1_partition: partition@100000 {
      label = "image-1";
      reg = <0x100000 0xE0000>;
    };
  };
};
...

For Matter master branch:
In that case it's implemented as overlay over standard zephyr .dts layout which is located in Matter repository
overlay:

...
&flash {
  reg = <0x20000000 0x200000>;

  partitions {
    /delete-node/ partition@0;
    /delete-node/ partition@18000;
    /delete-node/ partition@84000;
    /delete-node/ partition@f0000;
    /delete-node/ partition@f4000;
    boot_partition: partition@0 {
      label = "mcuboot";
      reg = <0x00000000 0x13000>;
    };
    slot0_partition: partition@13000 {
      label = "image-0";
      reg = <0x13000 0xf1000>;
    };
    factory_partition: partition@104000 {
      label = "factory-data";
      reg = <0x104000 0x1000>;
    };
    storage_partition: partition@105000 {
      label = "storage";
      reg = <0x105000 0x8000>;
    };
    slot1_partition: partition@10d000 {
      label = "image-1";
      reg = <0x10d000 0xf1000>;
    };
    /* region <0x1fe000 0x2000> is reserved for Telink B91 SDKs data */
  };
};
...

Device configuration

Basic device configuration

Device-to-device communication without border router available in case if
one or several devices configured as FTD (Full Thread Device) for example
Light Bulb.

Application configuration file location (relative path):

examples/app/telink/prj.conf

MTD (Minimal Thread Device) configuration example:

# OpenThread configs
CONFIG_OPENTHREAD_MTD=y

FTD (Full Thread Device) configuration example:

# OpenThread configs
CONFIG_OPENTHREAD_MTD=n

Note: Option not set has the same effect

Low power device configuration

Low power configuration options:

  • CONFIG_PM - y or n - should be y to enable the basic Low Power mode
  • CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT = y or n - should be y to enable the support for Thread Sleepy End Device, depends on CONFIG_OPENTHREAD_MTD=y

Optional tuning:

  • CONFIG_CHIP_ENABLE_PM_DURING_BLE - y or n - should be y to enable the basic Low Power mode during BLE operation, by default the option is equal to CONFIG_PM
  • CONFIG_TELINK_BUTTON_MANAGER_IRQ_MODE - y or n - should be y to enable buttons processing in an IRQ mode instead of polling mode, by default the option is equal to CONFIG_PM
  • CONFIG_TELINK_ENABLE_APPLICATION_STATUS_LED - y or n - should be n to disable Status LED, by default the option is opposite to CONFIG_PM
  • CONFIG_CHIP_SED_IDLE_INTERVAL = 0..65535 - default: 1000 - used to tune Thread Sleepy End Device wake interval

The configuration option CONFIG_TELINK_BUTTON_MANAGER_IRQ_MODE requires reconnection of the buttons by the following schematic and requires the external buttons usage in case of using the TLSR9218ADK80d EVK:

Name Pin
BUTTON_1 PC2 (pin 16 of J20)
BUTTON_2 PC0 (pin 18 of J20)
BUTTON_3 PC3 (pin 20 of J20)
BUTTON_4 PC1 (pin 22 of J20)

The second side buttons pins need to be connected together and connected to the GND. In case of using TLSR9218ADK80d EVK any GND pin on the back side of the board can be choosed.

This kind of connection pulls up the GPIO internally and the button event comes by FALLING EDGE on GPIO.

The current consumption with this configuration can be achieved as low as:

  • BLE@ 2.3db 1s ADV: 78uA (Need remeasure)
  • Thread @2.3db 1s poll: 67.7uA (Need remeasure)

Custom RF power values

Setting max RF power configuration example:

# Custom RF power values
CONFIG_B91_BLE_CTRL_RF_POWER_P9P11DBM=y
CONFIG_OPENTHREAD_DEFAULT_TX_POWER=9

Note: CONFIG_OPENTHREAD_DEFAULT_TX_POWER is a value in dBm, valid range: -30 .. 9, by default it's zero.

Note: CONFIG_CHIP_OPENTHREAD_TX_POWER may used in older version.

Build and flash

In Matter root folder or /root/chip/ if using Docker image:

  1. Activate Matter environment

    source scripts/activate.sh
  2. Go to directory with example:

    cd examples/${app}/telink

    ${app}: all-clusters-app, all-clusters-minimal-app, lock-app, lighting-app, light-switch-app, ota-requestor-app, pump-app,
    pump-controller-app, temperature-measurement-app, thermostat, contact-sensor-app, window-app

  3. Remove previous build if exists:

    rm -rf build/
  4. Build the example:

    west build

    You can find target built file called zephyr.bin under
    build/zephyr directory.

  5. Flash the example (for ubuntu platform):

    west flash --erase
  6. In case of build errors or crashes you migt use zephyr version which was CI tested against Chip Project master:

    Go to https://github.com/project-chip/connectedhomeip/blob/master/integrations/docker/images/stage-2/chip-build-telink/Dockerfile
    and look for ZEPHYR_REVISION = ${commit_ID}

    then use this information to setup zephyr:

    cd ~/zephyrproject/zephyr/
    git checkout ${commit_ID}
    cd ..
    west update
    west blobs fetch hal_telink

Logging and Shell CLI

To get output from device, connect UART to following pins:

Name Pin
RX PB3 (pin 15 of J34)
TX PB2 (pin 18 of J34)
GND GND (pin 23 of J50)

Baud rate: 115200 bits/s

How to configure logging in Matter

Logging is enabled by default. To disable Logging in Your application set this config:

In Matter config/telink/app/zephyr.conf, set the CONFIG_SERIAL=n:

    # Logging (set CONFIG_SERIAL to 'y' to enable logging and 'n' to disable logging)
    CONFIG_SERIAL=n

Set logging level

To configure the logging level, set the value of the CONFIG_LOG_MAX_LEVEL parameter in Matter config/telink/app/zephyr.conf:

    # Set the actual log level
    # - 0 OFF, logging is turned off
    # - 1 ERROR, maximal level set to LOG_LEVEL_ERR
    # - 2 WARNING, maximal level set to LOG_LEVEL_WRN
    # - 3 INFO, maximal level set to LOG_LEVEL_INFO
    # - 4 DEBUG, maximal level set to LOG_LEVEL_DBG
    CONFIG_LOG_MAX_LEVEL=3

Logging level by default is INFO (information).

How to enable Zephyr Shell in Matter

It's possible to interact with the device via UART with Unix-like shell commands.

To include Shell in Your application set these two configs.

  • In Matter config/telink/app/zephyr.conf, set the CONFIG_SHELL=y:
    # Shell settings
    CONFIG_SHELL=y
  • Set CONFIG_CHIP_LIB_SHELL=y to examples/lighting-app/telink/prj.conf
    # CHIP shell
    CONFIG_CHIP_LIB_SHELL=y

Now after the board starts You may print help and press Enter in UART terminal to see list of available CLI commands.

List of Matter commands

Every invoked command must be preceded by the matter prefix.

See the following subsections for the description of each Matter-specific
command.

Command - device

Handles a group of commands that are used to manage the device. You must use
this command together with one of the additional subcommands listed below.

Subcommand - factoryreset

Performs device factory reset that is hardware reset preceded by erasing of the
whole Matter settings stored in a non-volatile memory.

uart:~$ matter device factoryreset
Performing factory reset ...

Command - onboardingcodes

Handles a group of commands that are used to view information about device
onboarding codes. The onboardingcodes command takes one required parameter for
the rendezvous type, then an optional parameter for printing a specific type of
onboarding code.

The full format of the command is:

onboardingcodes none|softap|ble|onnetwork [qrcode|qrcodeurl|manualpairingcode]

To print all the onboardingcodes:

uart:~$ matter onboardingcodes none
QRCode: MT:W0GU2OTB00KA0648G00
QRCodeUrl: https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT%3AW0GU2OTB00KA0648G00
ManualPairingCode: 34970112332

To print a specific type of onboarding code:

Subcommand - qrcode

Prints the device onboarding QR code payload
Takes no arguments.

uart:~$ matter onboardingcodes none qrcode
MT:W0GU2OTB00KA0648G00

Subcommand - qrcodeurl

Prints the URL to view the device onboarding QR code
in a web browser. Takes no arguments.

uart:~$ matter onboardingcodes none qrcodeurl
https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT%3AW0GU2OTB00KA0648G00

Subcommand - manualpairingcode

Prints the pairing code for the manual onboarding of a device. Takes no
arguments.

uart:~$ matter onboardingcodes none manualpairingcode
34970112332

Command - config

Handles a group of commands that are used to view device configuration
information. You can use this command without any subcommand to print all
available configuration data or to add a specific subcommand.

VendorId:        65521 (0xFFF1)
ProductId:       32768 (0x8000)
HardwareVersion: 1 (0x1)
FabricId:
PinCode:         020202021
Discriminator:   f00
DeviceId:

The config command can also take the subcommands listed below.

Subcommand - pincode

Prints the PIN code for device setup. Takes no arguments.

uart:~$ matter config pincode
020202021

Subcommand - discriminator

Prints the device setup discriminator. Takes no arguments.

uart:~$ matter config discriminator
f00

Subcommand - vendorid

Prints the vendor ID of the device. Takes no arguments.

uart:~$ matter config vendorid
65521 (0xFFFF1)

Subcommand - productid

Prints the product ID of the device. Takes no arguments.

uart:~$ matter config productid
32768 (0x8000)

Subcommand - hardwarever

Prints the hardware version of the device. Takes no arguments.

uart:~$ matter config hardwarever
0 (0x0)

Command - ble

Handles a group of commands that are used to control the device Bluetooth LE
transport state. You must use this command together with one of the additional
subcommands listed below.

Subcommand - help

Prints help information about ble commands group.

uart:~$ matter ble help
  help            Usage: ble <subcommand>
  adv             Enable or disable advertisement. Usage: ble adv <start|stop|state>

Subcommand - adv start

Enables Bluetooth LE advertising.

uart:~$ matter ble adv start
Starting BLE advertising

Subcommand - adv stop

Disables Bluetooth LE advertising.

uart:~$ matter ble adv stop
Stopping BLE advertising

Subcommand - adv status

Prints the information about the current Bluetooth LE advertising status.

uart:~$ matter ble adv state
BLE advertising is disabled

Command - dns

Handles a group of commands that are used to trigger performing DNS queries. You
must use this command together with one of the additional subcommands listed
below.

Subcommand - browse

Browses for DNS services of _matterc_udp type and prints the received
response. Takes no argument.

uart:~$ matter dns browse
Browsing ...
DNS browse succeeded:
   Hostname: 0E824F0CA6DE309C
   Vendor ID: 9050
   Product ID: 20043
   Long discriminator: 3840
   Device type: 0
   Device name:
   Commissioning mode: 0
   IP addresses:
      fd08:b65e:db8e:f9c7:2cc2:2043:1366:3b31

Subcommand - resolve

Resolves the specified Matter node service given by the \ and
\.

uart:~$ matter dns resolve <fabric-id> <node-id>
Resolving ...
DNS resolve for 000000014A77CBB3-0000000000BC5C01 succeeded:
   IP address: fd08:b65e:db8e:f9c7:8052:1a8e:4dd4:e1f3
   Port: 5540

List of Telink CLI commands

Command -telink

Handles a group of Telink commands that are used to manage the device. You must use
this command together with one of the additional subcommands listed below.

Subcommand -reboot

Performs board reboot that is hardware reboot calling sys_reboot().

uart:~$ telink reboot
Performing reboot ...

Light-switch-app CLI commands

Light-switch control commands should be available via Shell interface if the
CONFIG_CHIP_LIB_SHELL=y is set in examples/light-switch-app/telink/prj.conf

Also CONFIG_SHELL=y should be set in config/telink/app/zephyr.conf to use Shell in Matter

matter switch help

To list all the available light-switch commands call:

uart:~$ matter switch help
  help            Usage: switch <subcommand>
  onoff            Usage: switch onoff <subcommand>
  groups          Usage: switch groups <subcommand>
  binding         Usage: switch binding <subcommand>

UI

Buttons

The following buttons are available on TLSR9518ADK80D board:

Name Function Description
Button 1 Factory reset Perform factory reset to forget currently commissioned Thread network and back to decommissioned state (to activate, press and hold the button for 2 seconds or push the button 3 times (depends on used branch))
Button 2 Lighting control Manually triggers the lighting state (only for lightning-app)
LightSwitch control Triggers the light switch state (only for light-switch-app)
Lock state control Manually triggers the bolt lock state (only for lock-app)
ContactSensor control Triggers the contact sensor state (only for contact-sensor-app)
Pump control Manually triggers the pump state (only for pump-app, pump-controller-app)
Window Open/Toggle move type Single press manually triggers the Window Covering Open command, double toggles Lift-Tilt move type (only for window-app)
Button 3 Thread start / Window Close Commission thread with static credentials and enables the Thread on device / manually triggers the Window Covering Close command (only for window-app)
Button 4 Start BLE (optional) Initiate BLE stack and start BLE advertisement

Note: Some apps will turn on BLE advertising automatically when powered on.
Dependency in app's prj.conf from:

# Enable CHIP pairing automatically on application start.
CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y

Attention to be paid when you have more than one board flashed at the
same time.

Factory reset using power on sequence

If device has no HW Button 1 - Factory reset there is a possibility to perform this action using power on sequence.

  1. Switch off device
  2. Switch on device and in time till 5 seconds after switching on switch it off it. Repeat this step 5 times and it triggers factory reset.

On lighting application main light (not indication LED) is indication starting factory reset procedure by 3-times blinking with interval 1 second.

By default this feature is disabled to enable it add into prj.conf:

CONFIG_CHIP_ENABLE_POWER_ON_FACTORY_RESET=y

LEDs

Indicate current state of Thread network

Red LED indicates current state of Thread network. It is able to be in
following states:

State Description
Blinks with short pulses Device is not commissioned to Thread, Thread is disabled
Blinks with frequent pulses Device is commissioned, Thread enabled. Device trying to JOIN thread network
Blinks with wide pulses Device commissioned and joined to thread network as CHILD

Indicate identify of device

Green LED used to identify the device. The LED starts blinking when the Identify command of
the Identify cluster is received. The command's argument can be used to specify the the effect.
It is able to be in following effects:

Effect Description
Blinks (200 ms on/200 ms off) Blink (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK)
Breathe (during 1000 ms) Breathe (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE)
Blinks (50 ms on/950 ms off) Okay (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY)
Blinks (1000 ms on/1000 ms off) Channel Change (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE)
Blinks (950 ms on/50 ms off) Finish (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT)
LED off Stop (EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT)

Indicate current state of lightbulb

By default, only Blue LED is used to show current state of lightbulb (only for lightning-app).

To get current state of lightbulb in RGB mode, connect 3-color LED module to following pins:

Name Pin
Red PE2 (pin 8 of J34)
Green PE0 (pin 5 of J34)
Blue PB4 (pin 20 of J34)
GND GND (pin 24 of J50)

To enable RGB functionality in Your application set this config:

In Matter examples/lighting-app/telink/include/AppConfig.h, set the define USE_RGB_PWM:

    define USE_RGB_PWM 1

Indicate current state of Contact Sensor, Lock, Pump (Controller) App, Window Cover

White LED shows current state of Contact Sensor, Bolt Lock and Pump.
Short blinks in Lock app indicate transition state from Locked to Unlocked and vise versa.
For both Pump apps white LED shows the on-off-state of pump.

Blue LED indicates current Window Cover Lift position (PWM in range of 0-254).
To indicate the Tilt state in the same way connect external LED to board pin PE0.

Bridge Solution

A Bridge serves to allow the use of non-Matter IoT devices (e.g. devices on a Zigbee or Z-Wave net­
work, or any other non-Matter connectivity technology) in a Matter Fabric, with the goal to enable
the consumer to keep using these non-Matter devices together with their Matter devices.
The Telink Bridge Example demonstrates a simple lighting bridge and the use of
dynamic endpoints.

The Bridge device performs the translation between Matter and other protocols so that the Matter nodes
can communicate with the Bridged Devices.
A Bridge may also contain native Matter functionality, for example,
it may itself be a Temperature sensor having both Thread and Zigbee connection.

As said in Matter Specification, this is illustrated in the figure below: the non-Matter devices are exposed as Bridged Devices to
Nodes on the Fabric. The Matter Nodes can communicate with both the (native) Matter devices as
well as the Bridged Devices (by virtue of the Bridge which performs the translation between Matter
and the other protocol).

Bridge Structure

Border Router

Open Thread border router is composed device which contains two main parts:

  • Raspberry Pi contains all necessary services and firmware to act as a
    Border Router (BR)
  • Radio Co-Processor is responsible for Thread communication

Radio Co-Processor (RCP)

Two devices can be used for creating RCP device.

Build and flash TLSR9518ADK80D board

In this case the RCP is an additional TLSR9518ADK80D board (B91 Generic Starter Kit).

  1. Build from zephyr project root folder

    1.1 Using DuPount cables

    rm -rf build_ot_coprocessor
    
    west build -b tlsr9518adk80d -d build_ot_coprocessor zephyr/samples/net/openthread/coprocessor -- -DOVERLAY_CONFIG=overlay-rcp.conf

    1.2 Using USB connection

    rm -rf build_ot_coprocessor
    
    west build -b tlsr9518adk80d -d build_ot_coprocessor zephyr/samples/net/openthread/coprocessor -- -DDTC_OVERLAY_FILE="usb.overlay" -DOVERLAY_CONFIG=overlay-rcp-usb-telink.conf
  2. Flash firmware

    west flash --erase -d build_ot_coprocessor

Build and flash TLSR9518ADG80D dongle

This option bases on an additional TLSR9518AGK80D board (B91 Dongle) that can be used instead of adding TLSR9518ADK80D board (B91 Generic Starter Kit). It uses only USB connection with BR. Dongle must be inserted into BR.

  1. Build from zephyr project root folder

    rm -rf build_ot_coprocessor
    
    west build -b tlsr9518adk80d -d build_ot_coprocessor zephyr/samples/net/openthread/coprocessor -DDTC_OVERLAY_FILE="usb.overlay boards/tlsr9518adk80d-dongle.overlay" -DOVERLAY_CONFIG=overlay-rcp-usb-telink.conf
  2. Flash firmware

    west flash --erase -d build_ot_coprocessor

Note

USB mode requires to modify OTBR_AGENT_OPTS in the RPi image by changing device port to /dev/ttyACM0 like in the following:

OTBR_AGENT_OPTS="-I wpan0 -B eth0 spinel+hdlc+uart:///dev/ttyACM0?uart-flow-control trel://
eth0"

See Setup BR, point 7.

It can be done in the current image - the reboot is required after the change.

Raspberry Pi

Setup

Write image

  1. Install Imager

    sudo apt install rpi-imager
  2. Insert your SD card into PC

  3. Open Imager and press "CHOOSE OS" button

    Imager step 3 - Choose OS

  4. Choose "Raspberry Pi OS (other)" > "Raspberry Pi OS Lite (64-bit)"

    Imager step 4

  5. Press "CHOOSE STORAGE" button and choose your SD card

    Imager step 5 - Storage button

    Imager step 5 - Choose SD card

  6. Press "SETTINGS" button and apply required image configuration

    Imager step 6 - Settings button

    Imager step 6 - Select required settings

  7. Press Write

    Imager step 7 - Press Write

  8. Confirm that you want to continue writhing.

    WARNING: All data from SD card will be erased.

    Imager step 8 - Confirmation message

  9. Wait for write completion. If everything is ok, you will see following
    message.

    Imager step 9 - Write complete

Setup border router software

WARNING: Before you continue, make sure your configured hardware platform
is connected to the internet using Ethernet.
The bootstrap script disables the platform's Wi-Fi interface and the setup
script requires internet connectivity to download and install several
packages.

  1. Insert SD card and attach ethernet cable and power supply to Raspberry Pi.
    Check Raspberry Pi address on your router. Enter ssh session to your Raspberry Pi
    using credentials from Write image step 6.

  2. Setup serial port with RTS/CTS flow control. Add the next line to the end of file
    /boot/config.txt

    dtoverlay=uart3,ctsrts
  3. Install required software (Git, NodeJs)

    sudo apt update
    sudo apt install git npm
  4. Clone OpenThread Border Router:

    git clone https://github.com/openthread/ot-br-posix
  5. Do bootstrap:

    cd ot-br-posix
    ./script/bootstrap
  6. Setup:

    WEB_GUI=1 INFRA_IF_NAME=eth0 ./script/setup
  7. Modify /etc/default/otbr-agent file by replacing default string with
    following difference:

    - OTBR_AGENT_OPTS="-I wpan0 -B eth0 spinel+hdlc+uart:///dev/ttyACM0 trel://eth0"
    + OTBR_AGENT_OPTS="-I wpan0 -B eth0 spinel+hdlc+uart:///dev/ttyAMA1?uart-flow-control trel://eth0"
  8. Attach RCP according to connection map:

    RCP Telink B91 J20 header Raspberry Pi 4 J8 header
    TX - PC6 (pin 11) UART3 RX (pin 29)
    RX - PC7 (pin 12) UART3 TX (pin 7)
    RTS - PC5 (pin 14) UART3 CTS (pin 31)
    CTS - PC4 (pin 13) UART3 RTS (pin 26)
    GND (e.g., pin 23 of J50 or pin 3 of J56) GND (e.g., pin 6 or 9)
  9. Reboot the Raspberry Pi

    sudo reboot

More info you can find here: https://openthread.io/guides/border-router/build

Setup from prebuild image

  1. Download binaries

  2. Unzip rpi_ot_br_posix.iso.zip archive.

  3. Insert SD card into PC.

  4. Use dd command to copy image to SD card:

    sudo dd if=<path_to_image> of=<path_to_sd_card_device> bs=4M conv=noerror,sync status=progress

    Example: (replace 'sdx' with proper device)

    sudo dd if=~/Tmp/rpi_ot_br_posix.iso of=/dev/sdx bs=4M conv=noerror,sync status=progress

    WARNING: KEEP IN MIND that careless using of dd with root privileges may brick your system !!

  5. Wait till copy process finishing.

  6. Insert SD into Raspberry Pi.

  7. Flash Telink B91 RCP using zephyr.bin

  8. Connect RCP to Raspberry Pi.

  9. Plug Raspberry Pi to power source.

  10. Wait for a few minutes till it loads… Done.

Usage

Form Thread network via GUI

  1. Open your Internet browser.

  2. In address line type IP address of your Border Router.

  3. If everything is ok, you shall see Border Router Home page.

  4. Go to the "Form" page:

    Form step 4 - Go to form page

  5. Input desirable Thread credentials. You may leave it default as well.

  6. Press the "Form" button.

    Form step 6 - Start form new network

  7. Confirm that you want to Form the Thread Network by pressing the "OKAY"
    button.

    Form step 7 - Confirmation

  8. Wait till "Form operation successful" message.

    Form step 8 - Success

Form Thread network via CLI

  1. Connect to OpenThread Border Router via SSH (default password: raspberry):

    ssh pi@${OTBR_IP_ADDRESS}
  2. Set Thread network operational dataset:

    sudo ot-ctl dataset set active
    0e080000000000010000000300000f35060004001fffe0020811111111222222220708
    fd7302e133ca932d051000112233445566778899aabbccddeeff030e4f70656e546872
    65616444656d6f010212340410445f2b5ca6f2a93a55ce570a70efeecb0c0402a0fff8
  3. Init Thread network operational dataset:

    sudo ot-ctl dataset init active
  4. Commit Thread network operational dataset:

    sudo ot-ctl dataset commit active
  5. Bring interfaces up:

    sudo ifconfig wpan0 up
  6. Start Thread network:

    sudo ot-ctl thread start

Get active dataset

  1. Connect to OpenThread Border Router via SSH (default password: raspberry):

    ssh pi@${OTBR_IP_ADDRESS}
  2. Get Thread network operational dataset:

    sudo ot-ctl dataset active -x
  3. As output, you will get dataset which looks like that:

    0e080000000000010000000300000f35060004001fffe0020811111111222222220708
    fd7302e133ca932d051000112233445566778899aabbccddeeff030e4f70656e546872
    65616444656d6f010212340410445f2b5ca6f2a93a55ce570a70efeecb0c0402a0fff8
  4. Store it for further commissioning steps

WARNING: Thread border router creates new active dataset on each Form
operation.

Using Raspberry Pi3 with internal UART

Due to there's only one full featured UART port availabe on RPi 3, some additional actions are needed:

  1. Disable console and logging over UART

    Login into RPi via ssh and activate configuration tool:

    sudo raspi-config

    Select "3 Interface options"
    Select "I6 Serial Port"

    • For "Would you like a login shell to be accessible over serial?" answer "No"
    • For "Would you like the serial port hardware to be enabled?" answer "Yes"

    Close the tool by selecting "Finnish"

  2. Switch BLE chip to use miniUART instead of full featured UART

    put:

    dtoverlay=pi3-miniuart-bt

    at the end of /boot/config.txt file

    reboot the board.

    sudo reboot
  3. Configure GPIOs to act as HW flow control (RTS and CTS)

    There are variety of tools to do that. The method tested and working is described below:

    Login into Rpi console and fetch the tool:

    git clone https://github.com/mholling/rpirtscts.git

    Compile the tool:

    cd rpirtscts/
    make

    Use the tool:

    sudo ./rpirtscts on

    The output should show which pins are used for HW flow control:

    assuming 40-pin GPIO header
    Enabling CTS0 and RTS0 on GPIOs 16 and 17
  4. Shut down the board

    sudo halt

    Wait until "activity" (green) light stops flashing and power off the RPi board.

  5. Connect Telink RCP to 40-pin headder of RPi

    RCP Telink B91 J20 header Raspberry Pi 4 J8 header
    TX - PC6 (pin 11) UART RX (pin 10)
    RX - PC7 (pin 12) UART TX (pin 8)
    RTS - PC5 (pin 14) UART CTS (pin 36)
    CTS - PC4 (pin 13) UART RTS (pin 11)
    GND (e.g., pin 23 of J50 or pin 3 of J56) GND (e.g., pin 6 or 9)

    For convenience of having all connection at one side of the board power and ground can be aaplied via JTAG connector.

    PAY EXTREME ATTENTION TO JTAG PINS NUMBERING. 1st pin of JTAG is marked with triangle maker (and swuare soldering pad at the bottom)
    Round dot and "1 2" numbers refer to J34 pins!

    RCP Telink B91 J5G header Raspberry Pi 4 J8 header
    +5V - (pin 8) +5V - (pin 2) or (pin 4)
    GND - (pin 9) GND - (pin 6) ot (pin 9)
  6. Start the board and login into the console.

    alter the file: /etc/default/otbr-agent

    - OTBR_AGENT_OPTS="-I wpan0 -B eth0 spinel+hdlc+uart:///dev/ttyACM0 trel://eth0"
    + OTBR_AGENT_OPTS="-I wpan0 -B eth0 spinel+hdlc+uart:///dev/ttyAMA0?uart-flow-control trel://eth0"
  7. Reboot the board and try to from Thread network.

Using Raspberry Pi3 with USB dongle

(not recommended due to stability issues)

With additional USB->UART converter it is possible to build OT Border router with RPi 3.

  1. Prepare Raspberry PI 3 OT boarder router as above but DO NOT form thread network yet!

  2. Connect Telink board to USB dongle:

    RCP Telink B91 J20 header USB -> UART Dongle
    TX - PC6 (pin 11) RX
    RX - PC7 (pin 12) TX
    RTS - PC5 (pin 14) CTS
    CTS - PC4 (pin 13) RTS
    GND (e.g., pin 23 of J50 or pin 3 of J56) GND
  3. Login into RPI via ssh and connect USB dongle.

  4. Check device file assigned to your dongle:

    $ dmesg
    
    usb 1-1.3: new full-speed USB device number 7 using dwc_otg
    [ 4112.930175] usb 1-1.3: New USB device found, idVendor=0403, idProduct=6001, bcdDevice= 6.00
    [ 4112.930202] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
    [ 4112.930213] usb 1-1.3: Product: FT232R USB UART
    [ 4112.930222] usb 1-1.3: Manufacturer: FTDI
    [ 4112.930231] usb 1-1.3: SerialNumber: AQ03MIVH
    [ 4112.943040] ftdi_sio 1-1.3:1.0: FTDI USB Serial Device converter detected
    [ 4112.943184] usb 1-1.3: Detected FT232RL
    [ 4112.944703] usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB0

in our case it's ttyUSB0

  1. Modify /etc/default/otbr-agent file by replacing default string with
    following difference:

    - OTBR_AGENT_OPTS="-I wpan0 -B eth0 spinel+hdlc+uart:///dev/ttyACM0 trel://eth0"
    + OTBR_AGENT_OPTS="-I wpan0 -B eth0 spinel+hdlc+uart:///dev/ttyUSB0?uart-flow-control trel://eth0"

replacing "ttyUSB0" with device file you obtained in step 4.

  1. Reboot the board

    sudo reboot

Wait until reboot. Now it should be possible to use border router.

chip-tool

Build

WARNING: It is really important to build chip tool on same commit as
Matter firmware to avoid compatibility issues.

  1. Activate environment under Matter project root directory:

    source scripts/activate.sh
  2. Update submodules:

    ./scripts/checkout_submodules.py --allow-changing-global-git-config --shallow --platform linux
  3. Go to the example folder:

    cd examples/chip-tool
  4. Remove previous build if necessary:

    rm -rf out/
  5. Build:

    gn gen out
    ninja -C out
  6. chip-tool binary located here:

    ${MATTER_CHIP_TOOL_EXAMPLE_FOLDER}/out/chip-tool

More info you could find here: https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md

Usage

Commissioning

BLE-Thread commissioning

  1. Commission device with the latest active dataset (See
    Get active dataset paragraph on Border router
    section):

    ./chip-tool pairing ble-thread ${NODE_ID} hex:${DATASET} ${PIN_CODE} ${DISCRIMINATOR}

NODE_ID could be any non-zero value which in not used before. It is
handler that will be used to perform other chip-tool operations that refer
to specific Matter device.

DATASETs will be re-generated by Thread border router after new Thread
networks was formed.
They and slight different in the middle of the hex string so DO NOT use
the dataset in following command directly.
Please go back to the Get active dataset and replace
DATASET with the current dataset if you forget it.

Example:

$ ./chip-tool pairing ble-thread 1234 
hex:0e080000000000010000000300000f35060004001fffe002081111111122222222070
8fd61f77bd3df233e051000112233445566778899aabbccddeeff030e4f70656e54687265
616444656d6f010212340410445f2b5ca6f2a93a55ce570a70efeecb0c0402a0fff8 
20202021 3840

Commission could take some time. If commissioning is successful, you should
have the following message:

Device commissioning completed with success

Clean initialization of state

In case of failures, the device configuration can be cleared using the following command:

sudo rm -rf /tmp/chip_*

It is highly recommended to use BLE 5.0 HCI conteoler on the host machine running chip-tool.
You can check HCI version:

hciconfig -a

Thread on network commissioning

It is possible to commision example Matter device without BLE conectivity, basing only on Thread.

  1. Make sure OTBR (Open Thread Border Router) is up and running and network has been formed:
    See Border Router section of this guide for details.

  2. Join Matter Demo device using Button_3 (Joining Thread with hardcoded credentials):

  3. Make sure red LED is lit with short pauses:

    Beside LED indication, you can check is device joined using OTBR Web GUI (Topology)

  4. Use chip-tool to perform "onnetwork" commisioning:

    ./chip-tool pairing onnetwork ${NODE_ID) ${PIN_CODE}

    Example:

    ./chip-tool pairing onnetwork 1001 20202021

    PIN_CODE can be obtained from Demo Device logs.
    See Matter Firmware section of this guide for details.

    Example logs:

    I: 536 [DL]Device Configuration:
    I: 542 [DL]  Serial Number: 11223344556677889900
    I: 547 [DL]  Vendor Id: 65521 (0xFFF1)
    I: 550 [DL]  Product Id: 32772 (0x8004)
    I: 554 [DL]  Product Name: not-specified
    I: 560 [DL]  Hardware Version: 0
    I: 566 [DL]  Setup Pin Code (0 for UNKNOWN/ERROR): 20202021
    I: 573 [DL]  Setup Discriminator (0xFFFF for UNKNOWN/ERROR): 3840 (0xF00)
    I: 583 [DL]  Manufacturing Date: (not set)
    I: 660 [DL]  Device Type: 65535 (0xFFFF)

    PIN_CODE == 20202021 in this case.

Troubleshooting:

  1. Make sure OTBR local interface is reachanle by IPV6:
    Obtain IPv6:LocalAddress (OTBR Web GUI->Status) and ping it.

example:

$ ping6 fd11:22:0:0:7b6a:4020:5b68:b403
PING fd11:22:0:0:7b6a:4020:5b68:b403(fd11:22::7b6a:4020:5b68:b403) 56 data bytes
64 bytes from fd11:22::7b6a:4020:5b68:b403: icmp_seq=1 ttl=64 time=0.540 ms
64 bytes from fd11:22::7b6a:4020:5b68:b403: icmp_seq=2 ttl=64 time=0.601 ms
64 bytes from fd11:22::7b6a:4020:5b68:b403: icmp_seq=3 ttl=64 time=0.587 ms

goto 4. in case of ping failure.

  1. Check are you able to ping Matter Device from OTBR.

To obtain IP address of matter example device, rebuild and reflash the FW with zephyr console enabled (refer to Matter Firware section for more details)

In zephyr console:

uart:~$  ot ipaddr

fd11:22:0:0:1092:f710:43ba:bdb4
fdec:6dcd:f157:35fd:0:ff:fe00:9819
fdec:6dcd:f157:35fd:b409:ae04:2a3:fd74
fe80:0:0:0:1cef:9af0:c6a2:ab51
Done

choose address that coresponds with OTBR IPv6:LocalAddress. In this case:

fd11:22:0:0:1092:f710:43ba:bdb4

ping it from OTBR console:

pi@raspberrypi:~ $ ping6 fd11:22:0:0:1092:f710:43ba:bdb4
PING fd11:22:0:0:1092:f710:43ba:bdb4(fd11:22::1092:f710:43ba:bdb4) 56 data bytes
64 bytes from fd11:22::1092:f710:43ba:bdb4: icmp_seq=1 ttl=64 time=24.5 ms
64 bytes from fd11:22::1092:f710:43ba:bdb4: icmp_seq=2 ttl=64 time=23.2 ms
64 bytes from fd11:22::1092:f710:43ba:bdb4: icmp_seq=3 ttl=64 time=22.2 ms

In cae of failure:
check OTBR instalation and Thread NW forming. Check /var/log/messages for errors.

  1. Check are you able to ping Matter Device from host PC.

Use Matter Demo Device address obtained in 2. and ping it from host PC (machiner rynning chip-tool).

If ping from host PC works, chip-tool onnetwork pairing shall be working too. Remove cached data:

sudo rm -rf /tmp/chip_*

and check again:

./chip-tool pairing onnetwork ${NODE_ID) ${PIN_CODE}

In case of ping failure, it sometimes helps to unplug and plug back Ethernet connector from OTBR, but this manual is to serious to give such advice.

  1. Check routing on your host PC (PC running chip-tool):
$ sudo ip -6 route

::1 dev lo proto kernel metric 256 pref medium
2001:db7::/64 dev enp3s0 proto ra metric 100 pref medium
fd11:22::/64 via fe80::ba27:ebff:fe66:30f4 dev enp3s0 proto ra metric 100 pref medium
fe80::/64 dev tun0 proto kernel metric 256 pref medium
fe80::/64 dev enp3s0 proto kernel metric 1024 pref medium
default dev lo proto ra metric 1024 pref medium

You should see a route towards IPv6:LocalAddress subnet of OTBR

examample:

fd11:22::/64 via fe80::ba27:ebff:fe66:30f4 dev enp3s0 proto ra metric 100 pref medium

where fe80::ba27:ebff:fe66:30f4 corresponds to "link" address of eth0 interface of OTBR
(address can be obtained with 'ifconfig' command issued on OTBR ssh terminal):

 $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.15.128  netmask 255.255.255.0  broadcast 192.168.15.255
        inet6 fe80::ba27:ebff:fe66:30f4  prefixlen 64  scopeid 0x20<link>
        inet6 2001:db7::ba27:ebff:fe66:30f4  prefixlen 64  scopeid 0x0<global>
        ether b8:27:eb:66:30:f4  txqueuelen 1000  (Ethernet)
        RX packets 297312  bytes 35495992 (33.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14017  bytes 7107662 (6.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

In case there's no such route entry, asure _meshcop._udp service publish by OTBR is availabe on your PC:

avahi-browse -r -t _meshcop._udp

shall return an entry coresponding to OTBR:

+ enp3s0 IPv6 OpenThread BorderRouter #8F53                 _meshcop._udp        local
+ enp3s0 IPv4 OpenThread BorderRouter #8F53                 _meshcop._udp        local
= enp3s0 IPv6 OpenThread BorderRouter #8F53                 _meshcop._udp        local
   hostname = [raspberrypi-2.local]
   address = [192.168.15.128]
   port = [49153]
   txt = ["omr=@\253\017\000\"\000\000\000\000" "dn=DefaultDomain" "bb=\240\191" "sq=\005" "pt=j\021\023\015" "at=\000\000\000\000\000\001\000\000" "sb=\000\000\001\177" "xa=n\190\155[\218\029\143S" "tv=1.3.0" "xp=\017\017\017\017\"\"\"\"" "nn=OpenThreadDemo" "mn=BorderRouter" "vn=OpenThread" "rv=1"]
= enp3s0 IPv4 OpenThread BorderRouter #8F53                 _meshcop._udp        local
   hostname = [raspberrypi-2.local]
   address = [192.168.15.128]
   port = [49153]
   txt = ["omr=@\253\017\000\"\000\000\000\000" "dn=DefaultDomain" "bb=\240\191" "sq=\005" "pt=j\021\023\015" "at=\000\000\000\000\000\001\000\000" "sb=\000\000\001\177" "xa=n\190\155[\218\029\143S" "tv=1.3.0" "xp=\017\017\017\017\"\"\"\"" "nn=OpenThreadDemo" "mn=BorderRouter" "vn=OpenThread" "rv=1"]

see https://openthread.io/guides/border-router/mdns-discovery#avahi_utilities for more details.

Lightbulb control

  1. Switch on the light:

    ./chip-tool onoff on ${NODE_ID} 1
    Argument Description
    onoff Cluster name
    on Command to the cluster
    ${NODE_ID} Unique node ID of device. Shall be greater than 0
    1 ID of endpoint
  2. Switch off the light:

    ./chip-tool onoff off ${NODE_ID} 1
    Argument Description
    onoff Cluster name
    off Command to the cluster
    ${NODE_ID} Unique node ID of device. Shall be greater than 0
    1 ID of endpoint
  3. Read the light state:

    ./chip-tool onoff read on-off ${NODE_ID} 1
    Argument Description
    onoff Cluster name
    read Command to the cluster
    ${NODE_ID} Unique node ID of device. Shall be greater than 0
    1 ID of endpoint
  4. Change brightness of light:

    ./chip-tool levelcontrol move-to-level 32 0 0 0 ${NODE_ID} 1
    Argument Description
    levelcontrol Cluster name
    move-to-level Command to the cluster
    32 Brightness value
    0 Transition time
    0 Option mask
    0 Option override
    ${NODE_ID} Unique node ID of device. Shall be greater than 0
    1 ID of endpoint
  5. Read brightness level:

    ./chip-tool levelcontrol read current-level ${NODE_ID} 1
    Argument Description
    levelcontrol Cluster name
    read Command to the cluster
    current-level Attribute to read
    ${NODE_ID} Unique node ID of device. Shall be greater than 0
    1 ID of endpoint
  6. Change color of light (only for RGB led mode, see Indicate current state of lightbulb for more details):

    ./chip-tool colorcontrol move-to-hue-and-saturation 120 250 0 0 0 ${NODE_ID} 1
    Argument Description
    colorcontrol Cluster name
    move-to-hue-and-saturation Command to the cluster
    120 Hue value
    250 Saturation value
    0 Transition time
    0 Option mask
    0 Option override
    ${NODE_ID} Unique node ID of device. Shall be greater than 0
    1 ID of endpoint

Binding cluster and endpoints

Binding links clusters and endpoints on both devices, which enables them to
communicate with each other.

To perform binding, you need a controller that can write the binding table
to the light switch device and write proper ACL to the endpoint light bulb
on the Lighting Example application.
For example, you can use the CHIP Tool as the controller.
The ACL should contain information about all clusters that can be called by
the light switch application.
See the section about interacting with ZCL clusters in the CHIP Tool's user
guide for more information about ACLs.

You can perform the binding process to a single remote endpoint (unicast
binding) or to a group of remote endpoints (group multicast).

Note: To use a light switch without brightness dimmer, apply only the
first binding command with cluster no. 6.

Unicast binding to a remote endpoint using the CHIP Tool

In this scenario, commands are provided for a light switch device with the
nodeId = <light-switch-node-id> and a light bulb device with
nodeId = <lighting-node-id>, both commissioned to the same Matter network.

To perform the unicast binding process, complete the following steps:

  1. Add an ACL to the development kit that is programmed with the Lighting
    Application Example by running the following command:

    ./chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": [<light-switch-node-id>], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 1, "deviceType": null}]}]' <lighting-node-id> 0

    In this command:

    • [...] is JSON format message for attr-value so <light-switch-node-id> must be a real number when the command is
      executed.
    • <lighting-node-id> can be a shell variable as ${NODE_ID} used
      for commissioning before.
    • {"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}
      is an ACL for the communication with the CHIP Tool.
    • {"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [<light-switch-node-id>], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 1, "deviceType": null}]}
      is an ACL for binding (cluster no. 6 is the On/Off cluster, and the
      cluster no. 8 is the Level Control cluster).

    This command adds permissions on the lighting application device that
    allows it to receive commands from the light switch device.

  2. Add a binding table to the Light Switch binding cluster:

    ./chip-tool binding write binding '[{"fabricIndex": 1, "node": <lighting-node-id>, "endpoint": 1, "cluster": 6}]' <light-switch-node-id> 1

    In this command:

    • [...] is JSON format message for attr-value so <lighting-node-id> must be real numbers when the command is executed.
    • <light-switch-node-id> can be a shell variable such as ${SWITCH_NODE_ID} used by chip-tool to do commissioning with Lighting Switch App.
    • {"fabricIndex": 1, "node": <lighting-node-id>, "endpoint": 1, "cluster": 6} is a binding for the On/Off cluster.

Group multicast binding to the group of remote endpoints using the CHIP Tool

The group multicast binding lets you control more than one lighting device
at a time using a single light switch.

The group multicast binding targets all development kits that are
programmed with the Lighting Application Example and added to the same
multicast group.
After the binding is established, the light switch device can send multicast requests, and all the devices in the bound groups can run the
received command.

In this scenario, commands are provided for a light switch device with the
nodeId = <light-switch-node-id> and light bulb devices with
nodeId = <lighting-node-id>, all commissioned to the same Matter network.

To perform the multicast binding process, complete the following steps:

  1. Add the light switch device to the multicast group by running the
    following command:

    ./chip-tool tests TestGroupDemoConfig --nodeId <light-switch-node-id>
    • <light-switch-node-id> can be a shell variable such as ${SWITCH_NODE_ID} used by chip-tool to do commissioning with Lighting Switch App.
  2. Add all light bulbs to the same multicast group by applying command
    below for each of the light bulbs, using the appropriate
    <lighting-node-id> (the user-defined ID of the node being commissioned
    except <light-switch-node-id> due to use this <light-switch-node-id>
    for light-switch) for each of them:

    ./chip-tool tests TestGroupDemoConfig --nodeId <lighting-node-id>
    • <lighting-node-id> can be shell variables as ${NODE_ID}s used
      for commissioning before.
  3. Add Binding commands for group multicast:

    ./chip-tool binding write binding '[{"fabricIndex": 1, "group": 257}]' <light-switch-node-id> 1
    • <light-switch-node-id> can be a shell variable such as
      ${SWITCH_NODE_ID} used for commissioning before.

Testing the communication

To test the communication between the light switch device and the bound
devices, use light switch buttons.

OTA with Linux OTA Provider

OTA feature enabled by default only for ota-requestor-app example.
To enable OTA feature for another Telink example:

  • set CONFIG_CHIP_OTA_REQUESTOR=y in corresponding "prj.conf" configuration file.

After build application with enabled OTA feature, use next binary files:

  • zephyr.bin - main binary to flash PCB (Use 2MB PCB).
  • zephyr-ota.bin - binary for OTA Provider

All binaries has the same SW version. To test OTA "zephyr-ota.bin" should have higher SW version than base SW.
Set CONFIG_CHIP_DEVICE_SOFTWARE_VERSION=2 in corresponding "prj.conf" configuration file.

  • For Matter v1.0-branch branch used by default swap mode that run with the scratch partition (BOOT_SWAP_USING_SCRATCH).

  • For Matter master branch used by default swap mode that can run without a scratch partition (BOOT_SWAP_USING_MOVE).

To change swap mode back to BOOT_SWAP_USING_SCRATCH for master branch:

  1. Set the CONFIG_BOOT_SWAP_USING_MOVE=n and CONFIG_BOOT_SWAP_USING_SCRATCH=y config in the bootloader.conf file.

  2. Add scratch_partition into tlsr9518adk80d.overlay.
    See Flash Layout and the following table for more details.

    The following are the possible scratch partition layouts. Can be replaced with the one from the overlay file. The bigger scratch partition is the faster the swapping is done. Be aware that the bigger scratch partition is the smaller partitions for the code (slot0 and slot1) are.

    64kB:

    ...
    &flash {
        reg = <0x20000000 0x200000>;
    
        partitions {
            /delete-node/ partition@0;
            /delete-node/ partition@18000;
            /delete-node/ partition@104000;
            /delete-node/ partition@105000;
            /delete-node/ partition@10d000;
            /delete-node/ partition@84000;
            /delete-node/ partition@f0000;
            /delete-node/ partition@f4000;
            boot_partition: partition@0 {
                label = "mcuboot";
                reg = <0x00000000 0x13000>;
            };
            slot0_partition: partition@13000 {
                label = "image-0";
                reg = <0x13000 0xe9000>;
            };
            scratch_partition: partition@fc000 {
                label = "image-scratch";
                reg = <0xfc000 0x10000>;
            };
            factory_partition: partition@10c000 {
                label = "factory-data";
                reg = <0x10c000 0x1000>;
            };
            storage_partition: partition@10d000 {
                label = "storage";
                reg = <0x10d000 0x8000>;
            };
            slot1_partition: partition@115000 {
                label = "image-1";
                reg = <0x115000 0xe9000>;
            };
            /* region <0x1fe000 0x2000> is reserved for Telink B91 SDK's data */
        };
    };
    ...

    32kB:

    ...
    &flash {
        reg = <0x20000000 0x200000>;
    
        partitions {
            /delete-node/ partition@0;
            /delete-node/ partition@18000;
            /delete-node/ partition@104000;
            /delete-node/ partition@105000;
            /delete-node/ partition@10d000;
            /delete-node/ partition@84000;
            /delete-node/ partition@f0000;
            /delete-node/ partition@f4000;
            boot_partition: partition@0 {
                label = "mcuboot";
                reg = <0x00000000 0x13000>;
            };
            slot0_partition: partition@13000 {
                label = "image-0";
                reg = <0x13000 0xed000>;
            };
            scratch_partition: partition@100000 {
                label = "image-scratch";
                reg = <0x100000 0x8000>;
            };
            factory_partition: partition@108000 {
                label = "factory-data";
                reg = <0x108000 0x1000>;
            };
            storage_partition: partition@109000 {
                label = "storage";
                reg = <0x109000 0x8000>;
            };
            slot1_partition: partition@111000 {
                label = "image-1";
                reg = <0x111000 0xed000>;
            };
            /* region <0x1fe000 0x2000> is reserved for Telink B91 SDK's data */
        };
    };
    ...

    16kB:

    ...
    &flash {
        reg = <0x20000000 0x200000>;
    
        partitions {
            /delete-node/ partition@0;
            /delete-node/ partition@18000;
            /delete-node/ partition@104000;
            /delete-node/ partition@105000;
            /delete-node/ partition@10d000;
            /delete-node/ partition@84000;
            /delete-node/ partition@f0000;
            /delete-node/ partition@f4000;
            boot_partition: partition@0 {
                label = "mcuboot";
                reg = <0x00000000 0x13000>;
            };
            slot0_partition: partition@13000 {
                label = "image-0";
                reg = <0x13000 0xf1000>;
            };
            scratch_partition: partition@104000 {
                label = "image-scratch";
                reg = <0x104000 0x4000>;
            };
            factory_partition: partition@108000 {
                label = "factory-data";
                reg = <0x108000 0x1000>;
            };
            storage_partition: partition@109000 {
                label = "storage";
                reg = <0x109000 0x4000>;
            };
            slot1_partition: partition@10d000 {
                label = "image-1";
                reg = <0x10d000 0xf1000>;
            };
            /* region <0x1fe000 0x2000> is reserved for Telink B91 SDK's data */
        };
    };
    ...
  3. Check and fix offset (seek) in case if partitions moved (changed) in CMakeLists.txt and generate_factory_data.cmake

  4. Additionally to decrease (slightly) the swapping time a firmware verification for slot0 can be disabled by setting the CONFIG_BOOT_VALIDATE_SLOT0=n for build_mcuboot in the "connectedhomeip/config/telink/app/bootloader.conf" file. Not recommended.
    For the additional options of the MCUBoot please refer to Bootloader section in the chapter 4 of this manual.

Usage of OTA:

  1. Build the Linux OTA Provider

    ./scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/ota-provider-app chip_config_network_layer_ble=false
  2. Run the Linux OTA Provider with OTA image.

    ./chip-ota-provider-app -f zephyr-ota.bin

    here:

    • zephyr-ota.bin is the firmware needs to be updated to

    Please keep this terminal window till the end of test, for chip-tool use separate terminal window.

  3. Open another terminal and provision the Linux OTA Provider using chip-tool

    ./chip-tool pairing onnetwork ${OTA_PROVIDER_NODE_ID} 20202021

    here:

    • \${OTA_PROVIDER_NODE_ID} is the node id of Linux OTA Provider.
      It is similar to NODE_ID for lighting-app.
      You need to set it to any non-zero value which in not used before.
  4. Commission device (SeeCommissioning):

    ./chip-tool pairing ble-thread ${DEVICE_NODE_ID} hex:${DATASET} ${PIN_CODE} ${DISCRIMINATOR}
  5. Configure the Matter device with the default OTA Provider by running the following command:

    ./chip-tool otasoftwareupdaterequestor write default-otaproviders '[{"fabricIndex": 1, "providerNodeID": ${OTA_PROVIDER_NODE_ID}, "endpoint": 0}]' ${DEVICE_NODE_ID} 0
  6. Configure the OTA Provider with the access control list (ACL) that grants
    Operate privileges to all nodes in the fabric. This is necessary to allow
    the nodes to send cluster commands to the OTA Provider:

    ./chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' ${OTA_PROVIDER_NODE_ID} 0
  7. Initiate the DFU procedure in one of the following ways:

    • If you have built the device firmware with -DCONFIG_CHIP_LIB_SHELL=y
      option, which enables Matter shell commands, run the following command
      on the device shell:

      matter ota query
    • Otherwise, use chip-tool to send the Announce OTA Provider command to
      the device (the numeric arguments are Provider Node ID, Provider Vendor
      ID, Announcement Reason, Provider Endpoint ID, Requestor Node ID and
      Requestor Endpoint ID, respectively):

      ./chip-tool otasoftwareupdaterequestor announce-otaprovider ${OTA_PROVIDER_NODE_ID} 0 0 0 ${DEVICE_NODE_ID} 0

      Once the device is made aware of the OTA Provider node, it automatically
      queries the OTA Provider for a new firmware image.

When the firmware image download is complete, the device is automatically
rebooted to apply the update.

chip-device-ctrl.py

Build

  1. Activate environment under Matter project root directory:

    source scripts/activate.sh
  2. Build:

    scripts/build_python.sh -m platform

Usage

Run

  1. Activate python environment:

    source out/python_env/bin/activate
  2. Launch:

    sudo out/python_env/bin/chip-device-ctrl

Commissioning

  1. Set active dataset (Note:
    They are different once a new Thread network is generated.
    Please ensure to replace the dataset in the following command with the
    latest one.
    See Get active dataset paragraph on Border router
    section):

    chip-device-ctrl > set-pairing-thread-credential 0e08000000000001000000
    0300001335060004001fffe002084fe76e9a8b5edaf50708fde46f999f0698e20510d47
    f5027a414ffeebaefa92285cc84fa030f4f70656e5468726561642d653439630102e49c
    0410b92f8c7fbb4f9f3e08492ee3915fbd2f0c0402a0fff8
  2. connect via BLE:

    chip-device-ctrl > connect -ble 3840 20202021 ${NODE_ID}
  3. Wait till commissioning completion. If everything is ok you shall see
    following message.

    Commissioning complete

Lightbulb control

  1. Toggle light:

    chip-device-ctrl > zcl OnOff Toggle ${NODE_ID} 1 0

    Configuring factory data for the Telink examples

Factory data is a set of device parameters written to the non-volatile memory
during the manufacturing process. This guide describes the process of creating
and programming factory data using Matter and the Telink platform from
Telink Semiconductor.

The factory data parameter set includes different types of information, for
example about device certificates, cryptographic keys, device identifiers, and
hardware. All those parameters are vendor-specific and must be inserted into a
device's persistent storage during the manufacturing process. The factory data
parameters are read at the boot time of a device. Then, they can be used in the
Matter stack and user application (for example during commissioning).

All of the factory data parameters are protected against modifications by the
software, and the firmware data parameter set must be kept unchanged during the
lifetime of the device. When implementing your firmware, you must make sure that
the factory data parameters are not re-written or overwritten during the Device
Firmware Update or factory resets, except in some vendor-defined cases.

For the Telink platform, the factory data is stored by default in a
separate partition of the internal flash memory.



Overview

You can implement the factory data set described in the
factory data component table in various ways,
as long as the final HEX/BIN file contains all mandatory components defined in the
table. In this guide, the generating factory data
and the
building an example with factory data
sections describe one of the implementations of the factory data set created by
the Telink platform's maintainers. At the end of the process, you get a HEX
file that contains the factory data partition in the CBOR format.

The factory data accessor is a component that reads and decodes factory data
parameters from the device's persistent storage and creates an interface to
provide all of them to the Matter stack and to the user application.

The default implementation of the factory data accessor assumes that the factory
data stored in the device's flash memory is provided in the CBOR format.
However, it is possible to generate the factory data set without using the
Telink scripts and implement another parser and a factory data accessor. This
is possible if the newly provided implementation is consistent with the
Factory Data Provider.
For more information about preparing a factory data accessor, see the section
about
using own factory data implementation.

Note: Encryption and security of the factory data partition is not provided
yet for this feature.

Factory data component table

The following table lists the parameters of a factory data set:

Key name Full name Length Format Conformance Description
count number of factory binaries 4 B uint32 optional The number of manufacturing partition binaries to generate. Default is 1.
output output directory N/A ASCII string optional Output path where generated data will be stored.
spake2-path spake2 path N/A ASCII string mandatory Provide Spake2+ tool path
chip-tool-path chip tool path N/A ASCII string mandatory Provide chip-tool path
chip-cert-path chip cert path N/A ASCII string mandatory Provide chip-cert path
overwrite overwrite N/A bool optional If output directory exist this argument allows to generate new factory data and overwrite it.
in-tree in Matter tree N/A bool optional Use it only when building factory data from Matter source code.
passcode SPAKE passcode 4 B uint32 optional A pairing passcode is a 27-bit unsigned integer which serves as a proof of possession during the commissioning. Its value must be restricted to the values from 0x0000001 to 0x5F5E0FE (00000001 to 99999998 in decimal), excluding the following invalid passcode values: 00000000, 11111111, 22222222, 33333333, 44444444, 55555555, 66666666, 77777777, 88888888, 99999999, 12345678, 87654321.
spake2-it SPAKE2+ iteration counter 4 B uint32 mandatory A SPAKE2+ iteration counter is the amount of PBKDF2 (a key derivation function) interactions in a cryptographic process used during SPAKE2+ Verifier generation.
discriminator Discriminator 2 B uint16 mandatory A 12-bit value matching the field of the same name in the setup code. The discriminator is used during the discovery process.
commissioning-flow commisioning flow 4 B uint32 optional Device commissioning flow, 0:Standard, 1:User-Intent, 2:Custom. Default is 0. choices=[0, 1, 2]
discovery-mode discovery mode 4 B uint32 optional Commissionable device discovery networking technology. 0:WiFi-SoftAP, 1:BLE, 2:On-network. Default is BLE. choices=[0, 1, 2]
vendor-id vendor ID 2 B uint16 mandatory A CSA-assigned ID for the organization responsible for producing the device.
vendor-name vendor name <1, 32> B ASCII string mandatory A human-readable vendor name that provides a simple string containing identification of device's vendor for the application and Matter stack purposes.
product-id product ID 2 B uint16 mandatory A unique ID assigned by the device vendor to identify the product. It defaults to a CSA-assigned ID that designates a non-production or test product.
product-name product name <1, 32> B ASCII string mandatory A human-readable product name that provides a simple string containing identification of the product for the application and the Matter stack purposes.
hw-ver hardware version 2 B uint16 mandatory A hardware version number that specifies the version number of the hardware of the device. The value meaning and the versioning scheme is defined by the vendor.
hw-ver-str hardware version string <1, 64> B uint16 mandatory A hardware version string parameter that specifies the version of the hardware of the device as a more user-friendly value than that presented by the hardware version integer value. The value meaning and the versioning scheme is defined by the vendor.
mfg-date manufacturing date <8, 10> B ISO 8601 mandatory A manufacturing date specifies the date that the device was manufactured. The date format used is ISO 8601, for example YYYY-MM-DD.
serial-num serial number <1, 32> B ASCII string mandatory A serial number parameter defines an unique number of manufactured device. The maximum length of the serial number is 32 characters.
enable-rotating-device-id enable rotating device id N/A bool optional Enable Rotating device id in the generated binaries
rd-id-uid rotating device ID unique ID <16, 32> B byte string mandatory The unique ID for rotating device ID, which consists of a randomly-generated 128-bit (or longer) octet string. This parameter should be protected against reading or writing over-the-air after initial introduction into the device, and stay fixed during the lifetime of the device.
cert certificate path N/A ASCII string optional The input certificate file in PEM format.
key certificate key path N/A ASCII string optional The input key file in PEM format.
cert-dclrn certificate declaration path N/A ASCII string mandatory The certificate declaration file in DER format.
dac-cert DAC certificate path N/A ASCII string optional The input DAC certificate file in PEM format.
dac-key DAC certificate key path N/A ASCII string optional The input DAC private key file in PEM format.
lifetime certificate lifetime 4 B uint32 optional Lifetime of the generated certificate. Default is 4294967295 if not specified, this indicate that certificate does not have well defined expiration date.
valid-from certificate start date <8, 19> B ISO 8601 optional The start date for the certificate validity period in format YYYY-MM-DD [ HH:MM:SS ]. Default is current date.
paa PAA N/A bool optional Use input certificate cert as PAA certificate.
pai PAI N/A bool optional Use input certificate cert as PAI certificate.
offset factory partition offset 4 B uint32 mandatory Partition offset - an address in devices NVM memory, where factory data will be stored
size factory partition size 2 B uint16 mandatory The maximum partition size

Factory data format

The factory data set must be saved into a HEX/BIN file that can be written to the
flash memory of the Matter device.

In the Telink example, the factory data set is represented in the CBOR
format and is stored in a HEX/BIN file. The file is then programmed to a device.

All parameters of the factory data set are either mandatory or optional:

  • Mandatory parameters must always be provided, as they are required for
    example to perform commissioning to the Matter network.
  • Optional parameters can be used for development and testing purposes. For
    example, the user data parameter consists of all data that is needed by a
    specific manufacturer and that is not included in the mandatory parameters.

In the factory data set, the following formats are used:

  • uint16 and uint32 - These are the numeric formats representing,
    respectively, two-bytes length unsigned integer and four-bytes length
    unsigned integer. This value is stored in a HEX file in the big-endian
    order.
  • Byte string - This parameter represents the sequence of integers between 0
    and 255(inclusive), without any encoding.
  • ASCII string is a string representation in ASCII encoding without
    null-terminating.
  • ISO 8601 format is a
    date format that
    represents a date provided in the YYYY-MM-DD or YYYYMMDD format.
  • All certificates stored in factory data are provided in the
    X.509 format.

Enabling factory data support

By default, the factory data support is disabled in all Telink examples and
the Telink device uses predefined parameters from the Matter core, which
you should not change. To start using factory data stored in the flash memory
and the Factory Data Provider from the Telink platform, build an
example with the following option:

west build -- -DCONFIG_CHIP_FACTORY_DATA=y

Generating factory data

This section describes how to generate factory data partition image.

Dependencies

Please make sure you have had the following tools before using the generator
tool.

Build Matter tools

Detailed description

  1. Using the following commands to generate chip-tool, spake2p and chip-cert at
    path/to/connectedhomeip/build/out/host.

    cd path/to/connectedhomeip
    source scripts/activate.sh
    gn gen build/out/host
    ninja -C build/out/host
  2. Add the tools path to \$PATH

    export PATH="$PATH:path/to/connectedhomeip/build/out/host"

    Preparing factory data partition on a device

The factory data partition is an area in the device’s persistent storage where a factory data set is stored.
This area is configured in DTS file
For Matter v1.0-branch branch:
zephyr/boards/riscv/tlsr9518adk80d/tlsr9518adk80d.dts
For Matter master branch:
connectedhomeip/tree/master/src/platform/telink/tlsr9518adk80d.overlay
within which all partitions are declared.

To prepare an example that supports factory data, add a partition called factory-data
to the tlsr9518adk80d.dts/tlsr9518adk80d.overlay file. The partition size should be a multiple of one
flash page (for B91 SoCs, a single page size equals 4 kB).

See Flash Layout for an example of a factory data partition in the
tlsr9518adk80d.dts/tlsr9518adk80d.overlay file.

factory-data partition size has been set to one flash page (4 kB).

Script usage

To use this script, complete the following steps:

  1. Navigate to the connectedhomeip root directory.

  2. Run the script with -h option to see all possible options:

    python scripts/tools/telink/mfg_tool.py -h
  3. Prepare a list of arguments:

    a. Fill up all mandatory arguments:

    --serial-num, --vendor-id, --product-id, --vendor-name, --product-name, --mfg-date, --hw-ver, --hw-ver-str, --enable-rotating-device-id, --spake2-path, --chip-tool-path, --chip-cert-path, --offset, --size

    b. Add output file path:

    --output <output_dir>

    c. Add path to Certificate Declaration (mandatory):

    -cd <path to Certificate Declaration in der format>

    d. Specify which certificate will be used:

    • User:

      --dac-cert <path to DAC certificate in pem format>
      --dac-key <path to DAC key in pem format>
      --cert <path to PAI certificate in pem format>
      --key <path to PAI key in pem format>
      --pai
    • Generate DAC and PAI:

      --cert <path to PAA certificate in pem format>
      --key <path to PAA key in pem format>
      --paa

    e. Add the new unique ID for rotating device ID using one of the
    following options:

    • Provide an existing ID:

      --rdid--uid <rotating device ID unique ID>
    • Generate a new ID and provide it ():

      --enable-rotating-device-id

    f. (optional) Specify your own passcode:

    --passcode <passcode>

    g. (optional) Specify your own discriminator:

    --discriminator <discriminator>

    h. (optional) Add the request to overwrite existing output files:

    --overwrite

    i. Specify partition offset and size:

    --offset <partition_address_in_memory>
    --size <partition_size>

    In this command:

    • __ is an address in the device's persistent
      storage area where a partition data set is to be stored.
    • __ is a size of partition in the device's persistent storage
      area. New data is checked according to this value to see if it fits the size.

    Important note:

    For Matter v1.0-branch branch use:

    --offset 0xf4000 --size 0x1000

    For Matter master branch use:

    --offset 0x104000 --size 0x1000
  4. Run the script using the prepared list of arguments:

    python3 mfg_tool.py <arguments>

    For example, a final invocation of the Python script can look similar to the
    following one:

    $ python3 scripts/tools/telink/mfg_tool.py \
        --vendor-id 0xFFF2 --product-id 0x8001 \
        --serial-num AABBCCDDEEFF11223344556677889900 \
        --vendor-name "Telink Semiconductor" \
        --product-name "not-specified" \
        --mfg-date 2022-12-12 \
        --hw-ver 1 \
        --hw-ver-str "prerelase" \
        --enable-rotating-device-id \
        --pai \
        --key /path/to/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Key.pem \
        --cert /path/to/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Cert.pem \
        -cd /path/to/connectedhomeip/credentials/test/certification-declaration/Chip-Test-CD-FFF2-8001.der  \
        --spake2-path /path/to/spake2p \
        --chip-tool-path /path/to/chip-tool \
        --chip-cert-path /path/to/chip-cert
        --out ./factory_data

    As the result of the above example files listed below will be created:

    factory_data
    ├── device_sn.csv
    └── fff2_8001
        └── aabbccddeeff11223344556677889900
            ├── factory_data.bin
            ├── factory_data.hex
            ├── internal
            │   ├── DAC_cert.der
            │   ├── DAC_cert.pem
            │   ├── DAC_key.pem
            │   ├── DAC_private_key.bin
            │   ├── DAC_public_key.bin
            │   └── pai_cert.der
            ├── onb_codes.csv
            ├── pin_disc.csv
            ├── qrcode.png
            └── summary.json
  5. (optional example) Generate 5 factory partitions [Optional argument : --count]

    This will generate 5 unique Factory Data Partition images, for 5 devices we can consider "production batch". For each partition unique data like key, certificate, serial number etc. will be generated.

    $ python3 mfg_tool.py --count 5 -v 0xFFF2 -p 0x8001 \
        --serial-num AABBCCDDEEFF11223344556677889900 \
        --vendor-name "Telink Semiconductor" \
        --product-name "not-specified" \
        --mfg-date 2022-02-02 \
        --hw-ver 1 \
        --hw-ver-str "prerelase" \
        --enable-rotating-device-id \
        --pai \
        --key /path/to/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Key.pem \
        --cert /path/to/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Cert.  pem \
        -cd /path/to/connectedhomeip/credentials/test/certification-declaration/    Chip-Test-CD-FFF2-8001.der  \
        --spake2-path /path/to/spake2p \
        --chip-tool-path /path/to/chip-tool \
        --chip-cert-path /path/to/chip-cert

    As the result of the above example files listed below will be created:

    out
    ├── device_sn.csv
    └── fff2_8001
        ├── aabbccddeeff11223344556677889900
        │   ├── factory_data.bin
        │   ├── factory_data.hex
        │   ├── internal
        │   │   ├── DAC_cert.der
        │   │   ├── DAC_cert.pem
        │   │   ├── DAC_key.pem
        │   │   ├── DAC_private_key.bin
        │   │   ├── DAC_public_key.bin
        │   │   └── pai_cert.der
        │   ├── onb_codes.csv
        │   ├── pin_disc.csv
        │   ├── qrcode.png
        │   └── summary.json
        ├── aabbccddeeff11223344556677889901
        │   ├── factory_data.bin
        │   ├── factory_data.hex
        │   ├── internal
        │   │   ├── DAC_cert.der
        │   │   ├── DAC_cert.pem
        │   │   ├── DAC_key.pem
        │   │   ├── DAC_private_key.bin
        │   │   ├── DAC_public_key.bin
        │   │   └── pai_cert.der
        │   ├── onb_codes.csv
        │   ├── pin_disc.csv
        │   ├── qrcode.png
        │   └── summary.json
        ├── aabbccddeeff11223344556677889902
        │   ├── factory_data.bin
        │   ├── factory_data.hex
        │   ├── internal
        │   │   ├── DAC_cert.der
        │   │   ├── DAC_cert.pem
        │   │   ├── DAC_key.pem
        │   │   ├── DAC_private_key.bin
        │   │   ├── DAC_public_key.bin
        │   │   └── pai_cert.der
        │   ├── onb_codes.csv
        │   ├── pin_disc.csv
        │   ├── qrcode.png
        │   └── summary.json
        └── aabbccddeeff11223344556677889903
            ├── factory_data.bin
            ├── factory_data.hex
            ├── internal
            │   ├── DAC_cert.der
            │   ├── DAC_cert.pem
            │   ├── DAC_key.pem
            │   ├── DAC_private_key.bin
            │   ├── DAC_public_key.bin
            │   └── pai_cert.der
            ├── onb_codes.csv
            ├── pin_disc.csv
            ├── qrcode.png
            └── summary.json

Note: By default, overwriting the existing output directory is disabled. This means
that you cannot create a new directory with the same name in the exact
location as an existing file. To allow overwriting, add the --overwrite
option to the argument list of the Python script.


Building an example with factory data

You can manually generate the factory data set using the instructions described
in the Generating factory data section. Another way
is to use the Telink platform build system that creates factory data
content automatically using Kconfig options and includes the content in the
final firmware binary.

To enable generating the factory data set automatically, go to the example's
directory and build the example with the following option:

west build -- -DCONFIG_CHIP_FACTORY_DATA=y -DCONFIG_CHIP_FACTORY_DATA_BUILD=y

Alternatively, you can also add CONFIG_CHIP_FACTORY_DATA_BUILD=y Kconfig
setting to the example's prj.conf file.

Each factory data parameter has a default value. These are described in the
Kconfig file. Setting a new value
for the factory data parameter can be done either by providing it as a build
argument list or by using interactive Kconfig interfaces.

Providing factory data parameters as a build argument list

This way for providing factory data can be used with third-party build script,
as it uses only one command. All parameters can be edited manually by providing
them as an additional option for the west command:

west build -- -DCONFIG_CHIP_FACTORY_DATA=y --DCONFIG_CHIP_FACTORY_DATA_BUILD=y --DCONFIG_CHIP_DEVICE_DISCRIMINATOR=0xF11

Alternatively, you can add the relevant Kconfig option lines to the example's
prj.conf file.

Programming factory data

The HEX/BIN file containing factory data can be programmed into the device's flash
memory using BDT Tool and the Telink burning key.

Another way to program the factory data to a device is to use the Telink
platform build system described in
Building an example with factory data,
and build an example with the additional option
-DCONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE=y:

$ west build -- \
-DCONFIG_CHIP_FACTORY_DATA=y \
-DCONFIG_CHIP_FACTORY_DATA_BUILD=y \
-DCONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE=y

For better understanding various posibilities, see the table below:

Mode (described in the table below (1) (2) (3) (4)
CONFIG_CHIP_FACTORY_DATA n y y y
CONFIG_CHIP_FACTORY_DATA_BUILD don't care don't care y n
CONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE don't care n y y
Mode Description
(1) hardcoded values will be taken
(2) Factory data partition image won't be merged into final binary. Partition image has to be flashed in the other way or runtime error will be reported on the startup, since factory data accessor expects partition to be in place
(3) Factory data partition image will be created by build system and merged into main binary. Recommended for development purposes.
(4) Build system expects externaly generated factory data partition image (egz. generated by the script described in "Script Usage" chapter) at the path used in connectedhomeip/config/telink/chip-module/CMakeLists.txt (egz. ${PROJECT_BINARY_DIR}/factory/factory_data.bin )

You can also build an example with auto-generation of new CD, DAC and PAI
certificates. The newly generated certificates will be added to factory data set
automatically. To generate new certificates disable using default certificates
by building an example with the additional option
-DCHIP_FACTORY_DATA_USE_DEFAULT_CERTS=n:

$ west build -- \
-DCONFIG_CHIP_FACTORY_DATA=y \
-DCONFIG_CHIP_FACTORY_DATA_BUILD=y \
-DCONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE=y \
-DCONFIG_CHIP_FACTORY_DATA_USE_DEFAULT_CERTS=n

Note: To generate new certificates using the Telink platform build
system, you need the chip-cert executable in your system variable PATH. To
learn how to get chip-cert, go to the note at the end of
Creating a factory data partition with the second script
section, and then add the newly built executable to the system variable PATH.
The Cmake build system will find this executable automatically.

After that, use the following command from the example's directory to write
firmware and newly generated factory data at the same time:

west flash

Using own factory data implementation

The factory data generation process described above
is only an example valid for the Telink platform. You can well create a HEX
file containing all Factory data component table in any
format and then implement a parser to read out all parameters and pass them to a
provider. Each manufacturer can implement a factory data set on its own by
implementing a parser and a factory data accessor inside the Matter stack. Use
the Telink Provider
and FactoryDataParser as
examples.

You can read the factory data set from the device's flash memory in different
ways, depending on the purpose and the format. In the Telink example, the
factory data is stored in the CBOR format. The device uses the
Factory Data Parser to read
out raw data, decode it, and store it in the FactoryData structure. The
Factor Data Provider
implementation uses this parser to get all needed factory data parameters and
provide them to the Matter core.

In the Telink example, the FactoryDataProvider is a template class that
inherits from DeviceAttestationCredentialsProvider,
CommissionableDataProvider, and DeviceInstanceInfoProvider classes. Your
custom implementation must also inherit from these classes and implement their
functions to get all factory data parameters from the device's flash memory.
These classes are virtual and need to be overridden by the derived class. To
override the inherited classes, complete the following steps:

  1. Override the following methods:

        // ===== Members functions that implement the DeviceAttestationCredentialsProvider
        CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override;
        CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override;
        CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override;
        CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override;
        CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override;
    
        // ===== Members functions that implement the CommissionableDataProvider
        CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
        CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override;
        CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
        CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
        CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
        CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override;
        CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override;
    
        // ===== Members functions that implement the DeviceInstanceInfoProvider
        CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override;
        CHIP_ERROR GetVendorId(uint16_t & vendorId) override;
        CHIP_ERROR GetProductName(char * buf, size_t bufSize) override;
        CHIP_ERROR GetProductId(uint16_t & productId) override;
        CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override;
        CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
        CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
        CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override;
        CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
  2. Move the newly created parser and provider files to your project directory.

  3. Add the files to the CMakeList.txt file.

  4. Disable building both the default and the Telink implementations of
    factory data providers to start using your own implementation of factory data
    parser and provider. This can be done in one of the following ways:

    • Add CONFIG_CHIP_FACTORY_DATA_CUSTOM_BACKEND=y Kconfig setting to prj.conf
      file.
    • Or build an example with following option:
        west build -- -DCONFIG_CHIP_FACTORY_DATA_CUSTOM_BACKEND=y

    Acknowledgements{-}

Published by
Telink Semiconductor

Bldg 3, 1500 Zuchongzhi Rd,
Zhangjiang Hi-Tech Park, Shanghai, China

© Telink Semiconductor
All Right Reserved

Legal Disclaimer{-}

This document is provided as-is. Telink Semiconductor reserves the right to make improvements without further notice to this document or any products herein. This document may contain technical inaccuracies or typographical errors. Telink Semiconductor disclaims any and all liability for any errors, inaccuracies or incompleteness contained herein.

Copyright © 2023 Telink Semiconductor (Shanghai) Co., Ltd.

Information{-}

For further information on the technology, product and business term, please contact Telink Semiconductor Company www.telink-semi.com

For sales or technical support, please send email to the address of:

telinkcnsales@telink-semi.com

telinkcnsupport@telink-semi.com

Revision History{-}


Version Change Description


V0.1.0 Preliminary release

V0.2.0 Added section about docker image

V0.2.1 Removed temporary step for Matter project setup

V0.2.2 Added Light-Switch-App

V0.2.3 Fixed markdown lint warnings

V0.2.4 Updated Raspberry Pi image

V0.2.5 Updated docker image

V0.2.6 Updated minimum Ubuntu version to 20.04 LTS

V0.2.7 Updated repos url and added Form Thread network via CLI

V0.2.8 Added OTA section

V0.2.9 Added factory data section

V0.2.10 Added thermostat app and modified URL in factory data section

V0.2.11 Added Flash Layout information

V0.2.12 Update factory data Section

V0.2.13 Update .dts modification

V0.2.14 Update Zephyr branch

V0.2.15 Update power management relative project configs

V0.2.16 Update Zephyr SDK version

V0.2.17 Update docker image repo

V0.2.18 Added bootloader configuration information

V0.2.19 Add power on Factory reset