欢迎使用

Matter开发指南

概述

Matter概述

Matter的出现

  • 困境

    物联网(IoT)产品“碎片化”的问题不仅让消费者和开发者们头疼不已,也阻碍了家庭智能硬件产品的进一步发展。目前,主导物联网产品发展的科技巨头们,都有各自独立的智能家居生态系统,如 Amazon Alexa,Apple HomeKit和Google Home 等等。

  • 对于消费者

    消费者在挑选智能产品的过程中,不仅需要关注产品的功能、特性和价格,还需要去考虑它是否兼容家中已有的生态系统,这造成了他们在选择上的困难以及使用中的不便。

  • 对于商家

    第三方开发者们在开发一款智能产品之前,也必须考虑该产品需要支持哪一种生态系统,以便于满足该产品目标用户的需求。如果开发者们不满足于将自己的产品限制于某一种生态系统中,想要满足不同的消费者的多样化的需求并拓展自己的市场占有率,他们可能需要改造已有的设备来支持更多的生态系统,或者重新开发支持更多智能生态系统的设备,而这两种选项都可能会让他们面临极大的困境。一方面,不得不花费更多的时间和精力去完成产品的软件层和不同智能生态系统的适配工作;另一方面,甚至要为了满足某些生态系统的要求,去改动底层硬件或者外观的设计。

因此,各方都希望能形成一套共同接受并遵循的“标准”去解决以上的“碎片化”的问题,便于智能家居品牌和制造商的开发,同时也便于消费者的选择。为了满足这一共同需求,包括Amazon,Apple,Google等许多物联网生态系统构建者们,与Zigbee联盟走到了一起,在 2019 年 12 月 宣布成立了 Connected Home over IP(CHIP)项目工作组,致力于打造一个基于开源生态的全新智能家居协议。2021 年 5 月,随着 Zigbee 联盟更名为连接标准联盟(Connectivity Standards Alliance),项目工作组协商制定出这个局域网内的应用层标准协议的初稿,并将 CHIP 改名为:Matter。

Matter总览

Matter

Matter 设备将工作在统一的应用层中,且仅仅依赖传输层中的 IPv6 标准所构成的 TCP/IP 和 UDP 协议,从而兼容不同的物理介质和数据链路标准。因为 IP 网络是一个 Mesh 结构,所以 Matter 也将呈现为 Mesh 拓扑结构(由不同通信技术的子网络组成)。

在计划于今年秋季正式发布的第一版 Matter 协议中,它将首先支持以 Ethernet, Wi-Fi 和 Thread 网络进行设备间通信;并利用蓝牙低功耗(BLE)技术作为 Matter 设备入网的通道,以简化 Matter 设备的配置步骤。其中,Thread 协议基于 IEEE 802.15.4 技术,其网络中的设备无法直接与 Wi-Fi 或以太网设备通信,因此在 Matter 拓扑结构中需要增加 Thread 边界路由器,使 Thread 网络中的 Matter 设备与其他网络中的设备可以互联。比如,一个仅支持 Thread 网络的 Matter 设备,可以通过 Border Router(如HomePod Mini),来和其他的仅支持 Wi-Fi 网络的设备(如iPhone)进行通信。

在 Matter 网络中,将拥有统一的数据模型和交互模型。Matter 协议把网络当作共享资源处理,没有制定排他性的网络所有权和访问权,这就使得多个不同协议的网络可以共存于同一组 IP 网络中。在以往,两个智能设备需要处于同一个物理网络中的才可以实现互相通讯,而 Matter 协议将构建起多个虚拟网络,允许不同物理网络中的智能设备实现互相通讯。这里的一个虚拟网络是一群 Matter 设备的集合,被称作一个 Fabric。在实现中,一个 Fabric 往往对应一个智能生态系统所构成的网络。

一个物理设备被叫做 Node(相当于HomeKit中的Accessory),一个 Node 可以被加入到一个或多个 Fabrics 之中。Node 下面用逻辑功能单元 Endpoint 来表示不同功能模块,比如下图中 Endpoint 1 和 Endpoint 2 来表示一个空调的不同功能模块;Endpoint 0 是必须保留的根端点,用来描述设备特性。Endpoint 中用若干个 Cluster(继承于Zigbee Cluster Library,ZCL)来表述具体功能,如开关,风力,温度测量和温度控制。而 Matter 设备之间的交互(Interaction),则是由一个设备的某个 Endpoint 和另一个设备的某个 Endpoint 之间的通讯来完成的。

Node示例

除此之外,Matter 协议所构建的网络还具有以下特性:

  • Multi-Admin,支持把 Matter 设备同时加入到不同生态系统中的能力,被不同 Fabrics 中的管理员(Administrator)所管理,从而实现广泛的兼容性。

  • 通过分布式合规设备总账(Distributed Compliance Ledger, DCL)来共享 Matter 厂商及设备的信息。每个生态系统都可以向 DCL 查询 Matter 配网,OTA 等过程中所需要的信息。

  • 允许使用者在无需连接到云端的情况下,进行本地设备的控制。

  • 已经大量存在的非 Matter 的智能设备,也有机会通过 Matter Bridge 设备被添加到 Matter Fabric 之中。这个 Matter Bridge 设备负责和非 Matter 设备通信,它会将非 Matter 设备虚拟成对应的 Endpoint,就像一个 Node 里面有多个不同功能的 Endpoints,从而让 Matter 网络中的 Matter 设备可以和非 Matter 设备实现通信。

Matter功能

Matter协议主要是面向智能家居市场,其主要支持的设备类型有:

  • 照明,开关等照明设备

  • 加热,制冷等空气处理设备

  • 探测器,报警器等安全设备

  • 门禁,门锁等进入控制设备

  • 音箱,电视等影音娱乐设备

  • 窗户,窗帘等采光通风设备

  • 热点,网桥等网络中继设备

随着 Matter 协议的发展和演化,在未来还会支持更多的智能设备。

Matter的未来

Matter 项目获得如此高的关注,并不仅仅是因为它概念和标准上的先进,而是源于三位智能家居巨头的承诺。在 Matter 项目立项之初,Amazon,Apple 和 Google 就承诺使用该协议的设备将可以兼容他们的生态。在 Matter 协议推出之后,IoT 产品的开发者们将能够做到一次开发同时支持多个生态系统(Amazon Alexa,Apple HomeKit和Google Home等)的接入协议,这将大大简化开发者的工作,使得智能设备能无缝地连接到任何 Matter 兼容的智能生态系统中。消费者也可以更容易地选购产品,而不用特别担心买到的设备和已有的生态系统的适配问题。

Telink Matter概述

泰凌微电子积极参与了Matter协议中的Matter设备的功能开发,Matter 设备的测试与认证,以及Matter 标准中文解读等方面的工作。作为致力于低功耗高性能无线连接 SoC 芯片解决方案的提供商,我们推出了基于 TLSR9 系列芯片的 Matter Over Thread 解决方案,可以用于开发 Matter Thread 终端设备。

Telink Matter目前支持的应用

⽬前 Telink Matter ⽀持的例程如下:

  1. connectedhomeip/example/lighting-app/telink

    lighting-app灯泡应用

  2. connectedhomeip/example/ligth-switch-app/telink

    light-switch-app开关应用

为了便于客户体验上述应用,我们提供了预制的 lighting-app 固件,light-switch-app 固件和对应的 chip-tool ⼯具,可以在下⾯的微盘地址中找到:

https://drive.weixin.qq.com/s?k=AKwA0AfNAA81RCKlJR

所使用到的仓库和分支

最新的 Docker Image 仍然在更新中,截至目前其中使用的Zephyr环境为V3.1.99,如果您想要了解,可以查看:

https://hub.docker.com/r/connectedhomeip/chip-build-telink

Matter 的 custom branch 分⽀ telink_matter 已经合并进了官⽅的 master 分⽀,因此可以使⽤以下仓库:

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

此文档的目的

本文档提供 Telink Matter 解决方案的完整指导,包括环境搭建、Matter 设备固件构建和烧录、边界路由器设置(包括RCP构建和烧录)、chip-tool 的构建和使用等,帮助用户了解 Telink Matter 相关事宜,更好的体验 Telink Matter 应用的功能。

硬件和工具准备

所需硬件和工具

Telink-Matter

  • TLSR9518ADK80D 作为 Matter 设备
  • TLSR9518ADK80D 作为 RCP
  • Raspberry Pi 3B 或者更高版本,作为边界路由的一部分
  • SD卡 给Raspberry Pi 3B 使用,至少需要 16GB
  • 主机 PC 需要系统为Ubuntu v20.04 LTS,作为一个构建机器和 Matter 设备的主机
  • Telink烧录器 用于烧录 Matter 设备和 RCP 固件
  • Wi-Fi路由器 充当 Wi-Fi 接入点

TLSR9518评估板介绍

按键功能

TLSR9518评估板上的四个机械按键布局和功能如下:

机械按键布局

按钮序号 功能 描述
Key1 恢复出厂设置 清除当前配网的 Thread 网络并返回未配网状态
Key2 灯光控制 对于灯泡,可以手动控制开关灯。对于开关,可以控制连接灯泡的开关灯
Key3 组建 Thread 网络 设备以默认配置加入Thread网络,仅用于测试目的
Key4 触发 BLE 广播 进入配网状态,设备开始BLE广播,进入可被发现的状态

LED灯状态

红灯指示设备当前的网络状态:

状态 描述
红灯短亮并闪烁 设备未配网于 Thread 网络,Thread 未使能
红灯频繁闪烁 设备已配网,Thread 使能,设备正在尝试加入 Thread 网络
红灯长亮并闪烁 设备已配网且已作为 child 加入 Thread 网络

蓝灯表示灯的状态:

  • 亮度 0 - 255 (最大值)

连接UART模块串口输出

UART 模块可以帮助我们获得 Matter 设备的串口调试信息,我们可以按照以下管脚位置进⾏接线:

UART模块 TLSR9518评估板
TXD PB3(pin 15 of J34)
RXD PB2(pin 18 of J34)
GND GND(e.g.pin 23 of J50 or pin 3 of J56)

串口的配置信息:115200,8N1。

使用自带PIN脚进行VBAT供电

在没有 USB 线的情况下,TLSR9518评估板可以用自带 PIN 脚进行供电,但是需要做一些改动。

TLSR9518 评估板按下图做改动:

通过VBAT脚直接供电

  1. 移除上图中红色框标注的跳线帽。
  2. J51 的 VBAT 脚接入 3.3V 电源。
  3. J51 的 GND 脚接地。

体验Matter的实现和功能

环境搭建

获取 Matter 源码

  1. 安装依赖项:

    $ sudo apt-get install git gcc g++ python 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
  2. 克隆 Matter 项目:

    将 Matter 项目克隆到本地目录,例如 /home/${YOUR_USERNAME}/workspace/matter。

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

    其中 ${YOUR_USERNAME} 是您的用户名文件夹

  3. 切换到v1.0分支并更新子模块

    cd ./connectedhomeip
    git checkout v1.0-branch
    git submodule update --init --recursive

Docker 镜像安装 Zephyr 工程环境

Matter的应用的实现依赖于Zephyr RTOS,如果您对Zephyr比较熟悉,可以根据Zephyr 3.0.0去配置本地环境。
我们提供了 Docker 镜像,⽅便获取 Telink Matter ⼯程所需要的 Zephyr 环境。

  1. 获取 Docker 镜像:

    sudo docker pull connectedhomeip/chip-build-telink
  2. 运行 Docker 容器:

    在运行 Docker 容器之前,请确认已经通过 3.1.1 获取 Matter 源码 中的步骤 1-3 将 Matter 存储库克隆到一个干净的文件夹中。

    使用以下命令来运行 Docker 容器:

    sudo docker run -it --rm -v ${MATTER_BASE}:/root/chip -v /dev/bus/usb:/dev/bus/usb --device-cgroup-rule "c 189:* rmw" connectedhomeip/chip-build-telink

    其中 ${MATTER_BASE} 是 Matter 项目根目录的绝对路径,例如:

    /home/${YOUR_USERNAME}/connectedhomeip

    其中 connectedhomeip 是Matter项目文件夹名称

    此处使用的命令会将 Matter 项目根目录映射到 Docker 容器中的 /root/chip,因此即使退出容器,您也会得到生成的 bin 文件。

    Docker 容器启动后,请通过以下命令进入当前 Matter 根目录:

    cd /root/chip
  3. 运行引导程序

    执行 bootstrap,准备 Matter 的环境,第一次运行通常需要很长时间。

    source scripts/bootstrap.sh

    注意:每次切换 commit、改变环境都要重新运行引导程序

    此步骤将生成一个在 Matter 根目录 connectedhomeip 下的叫做 .environment 的隐藏文件夹。在中国大陆它可能会花费额外的时间或遭遇失败。

    提示:如果 Matter 构建环境有任何问题,您可以尝试:

  4. 移除环境(在 Matter 项目的根目录中):

    rm -rf .environment
  5. 再次重做引导程序:

    source scripts/bootstrap.sh

您可以在这里找到更多信息:https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/BUILDING.md

编译固件

闪存布局

对 Matter v1.0-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>;
    };
  };
};
...

对 Matter master 分支:
在这种情况下,它被实现为覆盖标准 zephyr .dts 布局
telink_matter:

...
&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 */
  };
};
...

注意:表格内的信息仅具有参考价值,最准确的内存占用情况请下载最新的 Matter 代码进行确认。

设备的配置

如果一个或多个设备被配置为 FTD (Full Thread Device),例如灯泡,则设备到设备之间的通信可以不需要边界路由器。

注意:默认情况下,所有设备都配置为 MTD(Minimal Thread Device)。

应用程序的配置文件位于:

examples/app/telink/prj.conf

MTD 配置示例:

# OpenThread configs
CONFIG_OPENTHREAD_MTD=y
CONFIG_OPENTHREAD_FTD=n

FTD 配置示例:

# OpenThread configs
CONFIG_OPENTHREAD_MTD=n
CONFIG_OPENTHREAD_FTD=y

编译

在 Matter 根目录执行以下操作,如果使用 Docker 镜像的话则在 /root/chip 中进行操作:

  1. 启动 Matter 环境:

    source scripts/activate.sh
  2. 转到示例所在目录:

    cd examples/*app*/telink

    app:lighting-app 或 light-switch-app

  3. 若已经存在构建,则删除原有构建时产生的目录:

    rm -rf build/
  4. 构建示例:

    west build

    您可以在 build/zephyr 目录下找到名为 zephyr.bin 的目标构建文件。

    注意:若您不采用我们提供的 docker,而是选择手动配置 Zephyr 的工程,请确保您的PC中已经安装并配置了 gn 构建工具,否则可能出现构建错误。另外,请记得执行 zephyr 路径下的 zephyr-env.sh,否则,可能出现west build不存在的报错。

编译chip-tool

  1. 启动 Matter 环境:

    source scripts/activate.sh
  2. 转到示例所在目录:

    cd examples/chip-tool
  3. 若已经存在构建,则删除原有构建时产生的目录:

    rm -rf out/
  4. 构建 chip-tool

    gn gen out
    ninja -C out

    构建完成的文件可以在 {MATTER_CHIP_TOOL_EXAMPLE_FOLDER}/out/chip-tool 找到。

如果想了解更多和chip-tool相关的内容,可以点击以下链接进行查看:https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md

固件烧录

本烧录说明的实现适用于 Windows 和 Ubuntu 平台,烧录一块 B91 EVB 所需要准备的硬件,至少需要有:

  1. 一块 B91 EVB 评估板;
  2. 一块 Burning Evk 烧录器;
  3. 两根 Mini-USB 线;

如需同时烧录多块 B91 EVB 评估板,请准备多套以上的硬件。另外,可能需要足够接口的 USB Hub。

BDT 和 LinuxBDT 下载

BDT 是烧录调试工具,可以通过下面链接获取到最新的烧录工具:

Windows 10: http://wiki.telink-semi.cn/tools_and_sdk/Tools/BDT/BDT.zip

Ubuntu 20.04: http://wiki.telink-semi.cn/tools_and_sdk/Tools/BDT/LinuxBDT.tar.bz2

BDT 的连接方式

请按照下面的图示进行硬件连接,如图是完成硬件连接后状态:

硬件连接实例

注意:务必采用默认的跳帽配置。

BDT 在 Windows 平台上的使用步骤

  1. ⽤ USB 线连接烧录器到电脑的 USB ⼝。

  2. 下载 BDT 烧录软件,解压到本地⽂件夹,双击可执⾏⽂件"Telink BDT.exe"。如果⼀切正常,可以看到如下的窗⼝显⽰,在系统标题栏中可以看到已被连接的烧录器的设备信息(⻅图中红⾊框)。

    BDT正常启动并连接后的页面

  3. 点击工具栏中的"SWS"按钮,如果看到下图中的信息,则表明所有的硬件连接都没有问题。

    按下SWS按钮后显示的信息

  4. 设置 Flash 擦除的区域大小。点击工具栏中的"Setting"按钮,在弹出的"Setting"窗口中可以看到默认的 Flash 擦除的区域大小是 512kB。

    默认的Flash擦除的区域大小

    将 Flash 擦除的区域大小设置为"2040",如下图所示:

    设置Flash擦除的区域大小

    注意:对于外挂 2MB Flash 的 TLSR9518 开发板,Flash 最后的 8kB 空间预留用于保存重要的 SoC 信息,因此最多可以擦除 2040kB 的 Flash 区域。

  5. 点击工具栏中的"Erase"按钮,等待 Flash 擦除操作完成。

    Flash擦除操作

  6. 选择需要烧录的 BIN 文件。点击"File"菜单里的"Open"子菜单,在弹出的文件选择对话框中选中需要烧录的 BIN 文件。选中后的 BIN文件将显示在底部的状态栏中。

    选择BIN文件

  7. 点击工具栏中的"Download"按钮,等待 Flash 烧录完成。

    Flash烧录操作

对于更多命令的详细说明,请参考 BDT\release_v5.6.0\doc 文件夹下的文档。

BDT 在 Windows 平台上的常见问题

  1. 烧录器插入电脑后,可以被 Windows 设备管理器正确识别,但是烧录工具软件没有识别到,即在系统标题栏中看不到烧录器的设备信息(见图3.3)。请检查电脑是否用了 AMD 平台的处理器,换一台 Intel 平台处理器的电脑重新尝试。

  2. 最常见的问题是,在点击工具栏中的"SWS"按钮后,出现下图中的错误信息:

按下SWS按钮后的错误信息

主要有两种原因:

  • 硬件连接不正确。请参照前面的说明仔细核对所有的硬件连接,确认没有遗漏或错误的连接。

  • 烧录器的固件版本太低。请按照以下步骤查看烧录器固件的版本:

  1. 点击 Help 菜单下的 Upgrade 子菜单。

  2. 在弹出的 Upgrade Evk 窗口中,点击"Read FW version"按钮。在旁边的"Firmware Version"区域将会显示烧录器的固件版本号,例如下图所示。如果固件版本号低于 V3.4,可以确认是由于固件版本过低导致了通讯错误。请继续下面的步骤去完成固件升级。

    查看烧录器固件版本

  3. 点击窗口中的"Load..."按钮,在 BDT 工具所在目录下的 config 目录下的 fw 子目录找到最新的烧录器固件,如下图中的 Firmware_v3.5.bin 文件。

    升级烧录器固件

  4. 点击 Upgrade 按钮完成烧录器固件升级。

  5. 插拔烧录器的 USB 线,使烧录器重新上电。

LinuxBDT 在 Ubuntu 平台上的使用步骤

在 Ubuntu 20.04上, 打开终端,下载 LinuxBDT

wget http://wiki.telink-semi.cn/tools_and_sdk/Tools/BDT/LinuxBDT.tar.bz2

对下载到本地的 LinuxBDT.tar.bz2 进行解压缩:

tar -xvf LinuxBDT.tar.bz2

打开 LinuxBDT 文件夹,可以使用图形化的烧录调试工具 bdt_gui 或者命令行的 bdt,去操纵 Burning Evk 对 B91 EVB 进行烧录。
bdt_gui的使用方法和 windows 平台下的 BDT.exe 相似,因此下面主要介绍命令行 bdt 的使用步骤。

  1. 用 Mini-USB 线连接烧录器到电脑的 USB 口

  2. 检测 Burning Evk 与⽬标板 B91 EVB 的连接是否正常

    进入烧录工具 LinuxBDT 的根目录下的,执行下面命令。

    ./bdt 9518 sws

    可以查看已连接的烧录器和 B91 EVB,如下图:

    检测连接

  3. 激活MCU

    B91 EVB 上已有固件在运行时,直接使用 Burning Evk 烧录器进行擦除或者烧录,可能会遇到 "Swire err!" 错误。为了避免类似错误,请执行以下命令先激活MCU。

    ./bdt 9518 ac

    激活MCU

  4. 擦除Flash扇区

    为避免旧的固件所占的尺寸大于新的固件,导致新刷入的固件后,Flash上存在以往的数据残留,请先执行下面的擦除命令。

    ./bdt 9518 wf 0 -s 2040k -e
    • MCU 种类 -- 9518
    • 可选命令 -- wf (for write flash)
    • 将要被擦除的起始地址 -- 0
    • 可选命令 -- -s (指定将要擦除的扇区大小)
    • 将要擦除的扇区大小 -- 512k (64k, 128k, 256k, 512k... B91 EVB 最多2040k)
    • 可选命令 -- -e (erase flash)

    等待约数十秒,擦除成功后,会显示:

    擦除Flash

  5. 将固件下载到MCU的Flash中

        ./bdt 9518 wf 0 -i ~/workspace/matter/binaries_220922_718934487/lighting-app.bin 
    • MCU 种类-- 9518
    • 可选命令 -- wf (for write flash)
    • 将要被写入的起始地址 -- 0
    • 可选命令 -- -i (指定将要写入的固件)
    • 将要写入的固件的路径 -- 如这里的 ~/workspace/matter/binaries_220922_718934487/lighting-app.bin

    执行上述命令可以所选的固件刷入Flash当中,成功后的输出如下:

    烧入固件

  6. 重置MCU

    ./bdt 9518 rst -f
    • MCU 种类-- 9518
    • 可选命令 -- rst (for reset)
    • 可选命令 -- -f (for Flash or OTP)

    使用上述重置命令成功后的输出如下:

    重置MCU

    重置B91 EVB 评估板后,整个MCU将被重新上电,随即开始运行刚刚烧录的固件。

对于更多命令的详细说明,请参考 LinuxBDT/doc 文件夹下的文档。

边界路由配置

边界路由需要的硬件和固件

OTBR 边界路由需要由以下两个部分组成:

  1. Raspberry Pi 3B+:树莓派 3B 或更高版本。

    树莓派的预置镜像可以在下面的微盘中找到:

    https://drive.weixin.qq.com/s?k=AKwA0AfNAA88YrOXfp

  2. Radio Co-Processor:RCP 负责 Thread 通讯,由一个 TLSR9518ADK80D 评估板来实现。

    RCP 固件也在上述的微盘地址中,解压后即可。

边界路由的树莓派镜像烧录

在 Windows 下可以通过 Win32 Disk Image 进行树莓派镜像的烧录,具体步骤如下:

  1. 下载 Win32 Disk Image 的安装包。下面是安装包的下载地址:

    https://sourceforge.net/projects/win32diskimager/files/Archive/

  2. 安装 Win32 Disk Image。如果上面的网址中下载了 zip 文件,则不需要安装,只需要把压缩文件解压到电脑某个目录中。

  3. 把 Mirco SD 卡插入读卡器中,再将读卡器插入 Windows 电脑。

    注意:请确保用到的 Mirco SD 卡的容量是 16G 或以上。

  4. 打开 Win32 Disk Image。在"映像文件"中选择树莓派的镜像文件,在"设备"中选择 Micro SD 卡所在的驱动盘符。

    选择盘符

  5. 点击写入按钮,等待镜像写入完成。

    写入镜像

树莓派和RCP的连接方式

按照下面的管脚位置进行接线:

RCP 树莓派
TX(PB2 pin 18 of J34) RXD1(GPIO15 pin 10)
RX(PB3 pin 15 of J34) TXD1(GPIO14 pin 8)
GND (e.g. pin 23 of J50 or pin 3 of J56) GND (e.g. pin 6 or 9)

注意:波特率为57600

RCP 和树莓派上的管脚位置可以参考下图:

RCP-树莓派管脚位置

Thread网络建立和通过BLE配网

建立Thread网络并获取Dataset

  1. 在浏览器中输入树莓派的 IP 地址,点击 Form 按钮,默认设置不用更改, 点击 FORM 建立 Thread 网络。

    建立Thread网络

  2. Thread 网络建立后可以在 Status 下查看状态

    Thread网络建立后状态

  3. 获取 DATASET。请以 SSH 方式登录树莓派(预置镜像中的用户名 username:pi,密码 password:raspberry),执行以下命令:

    $sudo ot-ctl dataset active -x

    DATASET 是类似于以下形式的一串十六进制的字符串,将其保存好。

    DATASET

    注意:每次形成新的 Thread 网络,上面的 DATASET 将会被重新生成。即使每次生成 Thread 网络所设置的参数相同,其中间的部分...0708fd0b448cf7918bcf051000...也会不同。

配网过程

  1. 在主机上进行配网之前,请检查主机与树莓派之间的网络连接状态。

    • 如果主机与树莓派之间是由带防火墙的路由器做转发,暂时关闭路由器上的防火墙,尤其是其禁止端口监听、端口扫描等功能。

    • 如果使用运营商的光猫作为路由,可能会导致 mDNS 服务无法发现的错误,尝试将主机与树莓派用仅开启 DHCP 服务的其他路由器进行网线直连。

    • 确保主机是独立的 Ubuntu 主机;若使用 Windows 上的 VirtualBox 等虚拟机充当主机,则需要给它提供并配置额外的蓝牙适配器。

  2. 检查 Matter 固件版本与 chip-tool 的是否相符

    编译 Matter 设备的固件和 chip-tool 需要相同的 Zephyr 环境,否则进行配网时会出错。

    重要提醒:若要使用自己构建的 chip-tool 和 Matter 设备的固件,必须保证它们使用了相同的 commit 的 connectedhomeip 工程目录进行构建,以避免出现兼容性问题。

  3. 在主机上的 shell 中配置好以下命令:

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

    注意:运行 chip-tool 需退出镜像,并检查 chip-tool 的执行权限。

    NODE_ID 可以是 RCP 初始化之后,未使用过的任何非零值,chip-tool 将使用它来操作特定的 Matter 设备。

    DATASET 即为树莓派上获取的字符串。

    示例:

    配对和配网

  4. Matter 设备上电后,红灯闪烁,进入 BLE 广播状态,在主机上的 shell 中输入上面命令并运行,会让 Matter 设备与 RCP 所在的边界路由开始配对并配网。

    这个过程会持续一段时间,如果一切顺利,Matter 设备加入 Thread 网络后,你将能够从主机的 shell 中看到类似下面的信息:

    配网成功

使用chip-tool进行控制

在配网成功之后,可以使用 chip-tool 对 Matter 设备进行控制,主要的几个控制命令如下。

开关灯

./chip-tool onoff command_name [param1 param2 ...]
  • command_name 是命令的名字,此处开关灯可以用到 on(开灯)、off(关灯)、toggle(切换状态)

  • [param1 param 2 ...] 是所使用的多个参数,此处开关灯用到的是节点 ID <node_id> 和 端点 ID <endpoint_id>

  • <node_id> 是之前设备进行配网时使用的节点 ID,可以用 ${NODE_ID} 这样的 shell 变量表示

  • <endpoint_id> 是实现了 OnOff Cluster 的端点的 ID

开灯命令示例:

./chip-tool onoff on ${NODE_ID} 1

关灯命令示例:

./chip-tool onoff off ${NODE_ID} 1

灯泡状态翻转命令示例:

./chip-tool onoff toggle ${NODE_ID} 1

查看亮灯情况

标准的读取属性的命令为:

./chip-tool onoff read attribute-name [param1 param2 ...]
  • attribute-name 是要读取的属性名

  • [param1 param 2 ...] 是所使用的多个参数

读取亮灯情况的命令示例:

./chip-tool onoff read on-off ${NODE_ID} 1
  • 属性名为 on-off

  • 此处的两个参数为节点 ID 和端点 ID

查看亮度

同样使用读取属性的命令,标准的读取属性的命令为:

./chip-tool onoff read attribute-name [param1 param2 ...]
  • attribute-name 是要读取的属性名

  • [param1 param 2 ...] 是所使用的多个参数

读取亮度属性的命令示例:

./chip-tool levelcontrol read current-level ${NODE_ID} 1
  • 属性名为 current-level

  • 此处的两个参数为节点 ID 和端点 ID

改变亮度

标准的命令为:

./chip-tool levelcontrol move-to-level <level> <transition_time> <option_mask> <option_override> <node_id> <endpoint_id>
  • <level> 是亮度值

  • <transition_time> 是过渡时间

  • <option_mask> 是 option mask

  • <option_override> 是 option override

  • <node_id> 是之前设备进行配网时使用的节点 ID

  • <endpoint_id> 是实现了 LevelControl Cluster 的端点的 ID

改变亮度的示例命令:

./chip-tool levelcontrol move-to-level 32 0 0 0 ${NODE_ID} 1

连接灯和开关

对于配网在同一 Matter 网络的 light-switch 开关和 lighting 灯泡,可以通过以下步骤进行绑定。

使用 chip-tool 将单一设备绑定:

  1. 使用 chip-tool 将访问控制列表 ACL(Accsee Control List) 写入 accesscontrol Cluster,为灯泡设备添加合适的访问控制列表,执行如下命令:

    ./chip-tool accesscontrol write acl <acl_data> <node_id> <endpoint_id>
    • <acl_data> 是格式为 JSON 数组的 ACL 数据。

    • <node_id> 是要接收 ACL 的节点的 ID。

    • <endpoint_id> 是实现 accesscontrol Cluster 的端点的 ID。

    命令示例:

    ./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

    在上面的命令中:

    • <lighting-node-id> 是之前灯泡设备进行配网时使用的节点 ID,可以用 ${NODE_ID} 这样的 shell 变量表示。

    • <light-switch-node-id>是之前开关设备进行配网时使用的节点 ID,此处需要用数字表示。

    • {"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null} 是和 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}]} 是一个绑定的访问控制列表(cluster NO.6 是 On/Off cluster,cluster NO.8 是 Level Control cluster)。

    此命令为照明应用设备添加权限,允许其接收来自开关设备的命令。

  2. 将绑定表添加到开关以通知设备端点:

    ./chip-tool binding write binding  <binding_data> <node_id> <endpoint_id>
    • <binding_data> 是格式为 JSON 数组的绑定数据。

    • <node_id> 是要接受绑定的节点的 ID。

    • <endpoint_id> 是实现 binding Cluster 的端点的 ID。

    命令示例:

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

    在上面的命令中:

    • <light-switch-node-id> 是之前开关设备进行配网时使用的节点 ID,可以用 ${SWITCH_NODE_ID} 这样的 shell 变量表示。

    • <lighting-node-id> 是之前灯泡设备进行配网时使用的节点 ID,此处需要用数字表示。

    • {"fabricIndex": 1, "node": <lighting-node-id>, "endpoint": 1, "cluster": 6} 是 绑定 On/Off Cluster。

    • {"fabricIndex": 1, "node": <lighting-node-id>, "endpoint": 1, "cluster": 8} 是 绑定 Level Control Cluster。

使用 chip-tool 绑定多个设备:

  1. 通过运行以下命令将开关设备添加到多播组:

    ./chip-tool tests <test_name>
    • <test_name> 是特定测试的名称

    命令示例:

    ./chip-tool tests TestGroupDemoConfig --nodeId <light-switch-node-id>
    • <light-switch-node-id> 是之前开关设备进行配网使用的节点 ID,可以用 ${SWITCH_NODE_ID} 这样的 shell 变量表示。
  2. 通过对每个灯泡应用下面的命令将所有灯泡加入到同一个组中,对每个灯泡使用相应的 <lighting-node-id> (用户进行配网时定义的节点 ID):

    ./chip-tool tests TestGroupDemoConfig --nodeId <lighting-node-id>
    • <lighting-node-id> 可以用 ${NODE_ID} 这样的 shell 变量表示。
  3. 添加绑定命令:

    ./chip-tool binding write binding  <binding_data> <node_id> <endpoint_id>
    • <binding_data> 是格式为 JSON 数组的绑定数据。

    • <node_id> 是要接受绑定的节点的 ID。

    • <endpoint_id> 是实现 binding Cluster 的端点的 ID。

    命令示例:

    ./chip-tool binding write binding '[{"fabricIndex": 1, "group": 257}]' <light-switch-node-id> 1
    • <light-switch-node-id> 可以用 ${SWITCH_NODE_ID} 这样的 shell 变量表示。

体验OTA功能

启用 OTA 模块

OTA 模块只在 ota-requestor-app 示例中默认启用,若要在其他 Telink Matter 示例中启用 OTA 模块,需要按照以下步骤:

  • 在相应的 prj.conf 配置文件中设置 "CONFIG_CHIP_OTA_REQUESTOR=y"

在通过以上配置启用 OTA 模块后,编译得到固件:

  • zephyr.bin - 烧录到开发板上的 bin 文件
  • zephyr-ota.bin - 用于 OTA Provide的 bin 文件

所有的 bin 文件都拥有相同的 SW 版本,为了测试 OTA,"zephyr-ota.bin"应该有比基础的 SW 更高的 SW 版本。在对应的 prj.conf 配置文件中设置 "CONFIG_CHIP_DEVICE_SOFTWARE_VERSION=2"

OTA 的用法

  1. 构建 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. 运行 Linux OTA Provider

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

    此处的 zephyr-ota.bin 是用来升级的固件。

  3. 打开另一个终端,用chip-tool准备 Linux OTA Provider

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

    在这个命令中:

    • ${OTA_PROVIDER_NODE_ID}是 Linux OTA Provider的 node id,类似于 lighting-app的 NODE_ID,应该是一个之前没使用过的非零值。
  4. 配置 ota-provider-app的 ACL 来允许访问

    ./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
    • 此处的 ${OTA_PROVIDER_NODE_ID}是 Linux OTA Provider 的 node id。
  5. 使用 chip-tool 通知 ota-provider-app 开始 OTA 进程。

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

    在这个命令中:

    • ${OTA_PROVIDER_NODE_ID}是 Linux OTA Provider 的 node id
    • ${DEVICE_NODE_ID} 是配对设备的 node id

如何基于/利用Github上的开源SDK进行开发

架构

Telink Matter 架构

  • Application:包含特定Matter设备的业务逻辑

  • ZCL Data Model:数据模型层,将应用程序与周围的环境连接起来,Matter中借鉴了ZCL(ZigBee Cluster Library)的数据格式

  • Matter Library:负责Matter信息的通信,加密/解密,与数据模型的交互,配网管理等工作

  • Matter Platform Layer:连接Matter软件库和特定的硬件平台

  • Telink B91 BLE SDK:BLE SDK主要负责B91评估板配网过程

  • Zephyr:Zepyhr实时操作系统

  • Zephyr Thread Subsystem:Zephyr包含的OpenThread的实现

  • B91 IEEE80214 Driver:OpenThread用于实现通讯的Zephyr的驱动

  • B91 RF driver:Zephyr OpenThread和Telink BLE SDK用于实现射频通讯

数据模型

Data model

这里以一个具备开关灯和亮度调节功能的灯泡设备为例,介绍 Matter 的数据模型。

  • Node 即为节点,表示物理设备,此处的灯泡设备就是一个节点。

  • Endpoint 是端点,表示设备类的逻辑功能单元,通讯就是靠本地的端点和设备上的端点进行交互来完成的。每个节点都有许多端点,在每个端点中又有许多 Cluster,这些 Cluster 就说明了这个端点的功能。图中以灯泡为例,Endpoint 0 是需要保留的,提供整个Matter节点的一些基础功能,例如 Basic Information Cluster(提供节点的一些基本信息,如固件版本、制造商等等),Access Control Cluster(允许为此节点配置访问控制列表),Network Commissioning Cluster(允许在此节点上配置网络,如Wi-Fi、以太网、Thread网络)。在 Endpoint 1 里有 On/Off 和Level Control 两个 Cluster,它们共同组成了 Endpoint 1 的功能。

  • Cluster 用来实现具体的功能,不同的 Cluster 可以组合实现不同的功能。图中的两个Cluster:On/Off 实现开关灯功能,Level Control 实现调节亮度的功能。Cluster 里定义了一些属性、命令和事件。

    • Cluster 使用的是 Client/Sever 的通讯模型,属性通常在 Server,说明了设备的属性,例如灯的开关状态、灯的亮度等。

    • Client 和 Server 之间通过预设好的命令进行控制,通常是 Client 发起请求,Server 进行应答的模式。例如,On/Off Cluster 用 On 命令来控制开灯,用 Off 命令来控制关灯,Level Control Cluster 也有 MoveToLevel、Move 等命令。

    • 在某些情况下,当Server上的属性发生了变化,Server会通过事件(Event)主动通知Client,以便同步状态。

代码逻辑和重点源码

初始化函数

AppTask::Init()中的初始化大致可以分成3个部分。

第一部分是如下的代码,主要是对硬件相关的初始化。Init()函数一开始打印出软件版本信息,然后初始化了用于显示系统状态的LED灯,接着是对按键的初始化,最后完成对LightingManager实例的初始化,并设置回调函数。

CHIP_ERROR AppTask::Init()
{
    LOG_INF("Current Software Version: %u, %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION,
            CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING);

    // Initialize status LED
    LEDWidget::InitGpio(SYSTEM_STATE_LED_PORT);
    sStatusLED.Init(SYSTEM_STATE_LED_PIN);

    UpdateStatusLED();

    InitButtons();

    // Init lighting manager
    uint8_t minLightLevel = kDefaultMinLevel;
    Clusters::LevelControl::Attributes::MinLevel::Get(1, &minLightLevel);

    uint8_t maxLightLevel = kDefaultMaxLevel;
    Clusters::LevelControl::Attributes::MaxLevel::Get(1, &maxLightLevel);

    CHIP_ERROR err = LightingMgr().Init(LIGHTING_PWM_DEVICE, LIGHTING_PWM_CHANNEL, minLightLevel, maxLightLevel, maxLightLevel);
    if (err != CHIP_NO_ERROR)
    {
        LOG_ERR("Failed to int lighting manager");
        return err;
    }
    LightingMgr().SetCallbacks(ActionInitiated, ActionCompleted);
    ...
}

第二部分代码如下:

CHIP_ERROR AppTask::Init()
{
    ...
    // Initialize CHIP server
#if CONFIG_CHIP_FACTORY_DATA
    ReturnErrorOnFailure(mFactoryDataProvider.Init());
    SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
    SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
    SetCommissionableDataProvider(&mFactoryDataProvider);
    // Read EnableKey from the factory data.
    MutableByteSpan enableKey(sTestEventTriggerEnableKey);
    err = mFactoryDataProvider.GetEnableKey(enableKey);
    if (err != CHIP_NO_ERROR)
    {
        LOG_ERR("mFactoryDataProvider.GetEnableKey() failed. Could not delegate a test event trigger");
        memset(sTestEventTriggerEnableKey, 0, sizeof(sTestEventTriggerEnableKey));
    }
#else
    SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
#endif

    static CommonCaseDeviceServerInitParams initParams;
    // static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) };
    (void) initParams.InitializeStaticResourcesBeforeServerInit();
    // initParams.testEventTriggerDelegate = &testEventTriggerDelegate;
    ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams));

    gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage());
    chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);

#if CONFIG_CHIP_OTA_REQUESTOR
    InitBasicOTARequestor();
#endif
    ...
}

当CONFIG_CHIP_FACTORY_DATA配置项使能的时候,工厂数据将用于提供设备证明过程所需的信息(例如PAI和DAC),还有其他设备信息,具体请参考第三章中“厂商数据”,还有src/platform/telink目录中FactoryDataProvider.cpp的代码。

第三部分是下面的代码。

CHIP_ERROR AppTask::Init()
{
    ...
    ConfigurationMgr().LogDeviceConfig();
    PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));

    // Add CHIP event handler and start CHIP thread.
    // Note that all the initialization code should happen prior to this point to avoid data races
    // between the main and the CHIP threads.
    PlatformMgr().AddEventHandler(ChipEventHandler, 0);

    err = ConnectivityMgr().SetBLEDeviceName("TelinkLight");
    if (err != CHIP_NO_ERROR)
    {
        LOG_ERR("Fail to set BLE device name");
    }

    return err;
}

ConfigurationMgr().LogDeviceConfig()在日志中打印出设备配置信息,例如下面的打印输出。

I: 1979 [DL]Device Configuration:
I: 2020 [DL]  Serial Number: TEST_SN
I: 2023 [DL]  Vendor Id: 65521 (0xFFF1)
I: 2026 [DL]  Product Id: 32773 (0x8005)
I: 2067 [DL]  Hardware Version: 0
I: 2108 [DL]  Setup Pin Code (0 for UNKNOWN/ERROR): 20202021
I: 2150 [DL]  Setup Discriminator (0xFFFF for UNKNOWN/ERROR): 3840 (0xF00)
I: 2194 [DL]  Manufacturing Date: (not set)
I: 2197 [DL]  Device Type: 65535 (0xFFFF)

PrintOnboardingCodes()函数输出用于配网的二维码和手动配对码,下面是一个实际例子。

I: 2276 [SVR]SetupQRCode: [MT:6FCJ142C00KA0648G00]
I: 2281 [SVR]Copy/paste the below URL in a browser to see the QR Code:
I: 2287 [SVR]https://project-chip.github.io/connectedhomeip/qrcode.html?data=MT%3A6FCJ142C00KA0648G00
I: 2297 [SVR]Manual pairing code: [34970112332]

PlatformMgr().AddEventHandler()函数注册了一个回调函数AppTask::ChipEventHandler(),用于对特定的设备事件进行响应。

ConnectivityMgr().SetBLEDeviceName()函数设置了设备在做蓝牙广播是的设备名。

回调函数

Matter 代码中预留了很多的回调函数,好处是可以在不修改源码的情况下,最大程度地支持代码扩展。这里以 ligting-app 为例,介绍代码中数据模型涉及的两个重要回调函数,它们的实现都在examples/lighting-app/telink/src/ZclCallback.cpp这个文件中。

第一个重要的回调函数是MatterPostAttributeChangeCallback()函数,他的默认实现在zzz_generated/lighting-app/zap-generated/callback-stub.cpp这个文件中。如下面的代码所示,Matter 提供的默认实现是一个不包含任何代码的空函数。当用户提供了新的实现代码后,新的回调函数将替换该默认实现。

void __attribute__((weak)) MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type,
                                                             uint16_t size, uint8_t * value)
{}

只要一个属性(可以是任何Cluster的属性)的内容被更新后,MatterPostAttributeChangeCallback()这个回调函数就会被调用。在ligting-app中,我们实现了如下的回调函数,作用是将属性的最新状态同步到硬件中。例如,用户通过chip-tool更新了On/Off Cluster的OnOff属性值后,开发板上的LED状态需要更新为OnOff属性对应的状态,这个动作就是在回调函数中完成的(具体是调用了下面代码中的LightingMgr().InitiateAction()函数)。同样的,如果用户通过chip-tool跟新了Level Control Cluster的Current Level属性值后,下面的代码也通过调用LightingMgr().InitiateAction()更新了LED的亮度。

如果用户需要对其他属性的状态变化进行响应,可以在这个回调函数中添加代码进行处理。

void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, uint8_t * value) {
   ClusterId clusterId     = attributePath.mClusterId;
   AttributeId attributeId = attributePath.mAttributeId;

   if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id){
       LightingMgr().InitiateAction(*value ? LightingManager::ON_ACTION : LightingManager::OFF_ACTION,
                                    AppEvent::kEventType_Lighting, size, value);
   }
   else if (clusterId == LevelControl::Id && attributeId == LevelControl::Attributes::CurrentLevel::Id){
       if (size == 1) {
           LightingMgr().InitiateAction(LightingManager::LEVEL_ACTION, AppEvent::kEventType_Lighting, size, value);
       }
       else {
           ChipLogError(Zcl, "wrong length for level: %d", size);
       }
   }
}

第二个重要的回调函数是emberAfOnOffClusterInitCallback()函数,它的默认实现也同样在zzz_generated/lighting-app/zap-generated/callback-stub.cpp这个文件中。如下面的代码所示,Matter提供的默认实现也是一个不包含任何实际代码的空函数。当用户提供了新的实现代码后,新的回调函数将替换该默认实现。

void __attribute__((weak)) emberAfOnOffClusterInitCallback(EndpointId endpoint)
{
    // To prevent warning
    (void) endpoint;
}

emberAfOnOffClusterInitCallback()函数在初始化所有Cluster时被间接调用到。下面是我们在ligting-app中实现的新回调函数。

void emberAfOnOffClusterInitCallback(EndpointId endpoint)
{
    GetAppTask().UpdateClusterState();
}

如下面的代码所示,UpdateClusterState()函数的作用是更新On/Off Cluster中OnOff属性值和Level Control Cluster中Current Level属性值。

注意:emberAfWriteAttribute()函数被调用后,将最终触发MatterPostAttributeChangeCallback()回调函数被调用,进而把硬件状态更新为Cluster的属性值对应的状态。

void AppTask::UpdateClusterState()
{
    uint8_t onoff = LightingMgr().IsTurnedOn();

    // write the new on/off value
    EmberAfStatus status =
        emberAfWriteAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, &onoff, ZCL_BOOLEAN_ATTRIBUTE_TYPE);
    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        LOG_ERR("Updating on/off cluster failed: %x", status);
    }

    uint8_t level = LightingMgr().GetLevel();

    status =
        emberAfWriteAttribute(1, ZCL_LEVEL_CONTROL_CLUSTER_ID, ZCL_CURRENT_LEVEL_ATTRIBUTE_ID, &level, ZCL_INT8U_ATTRIBUTE_TYPE);

    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        LOG_ERR("Updating level cluster failed: %x", status);
    }
}

例程代码

目前支持的两个例程:

  • examples/lighting-app/telink

  • examples/light-switch-app/telink

文件 描述
src/main.cpp 主入口函数。包含Matter栈的初始化和其他组件,如Thread,BLE功能
src/AppTask.cpp 包含应用程序的主循环和事件处理程序
src/LightingManager.cpp lighting-app的管理类。包含管理亮灯状态的方法
src/ZclCallbacks.cpp 包含ZCL数据模型的回调函数的事件处理程序
src/binding-handler.cpp light-switch-app具体相关的事件处理程序
prj.conf 包含关于具体例程的Zephyr配置
CMakeLists.txt 包含要生成的源代码列表及其路径

硬件平台代码

Telink B91评估板的相关代码:

  • examples/patform/telink
文件 描述
project_include/OpenThreadConfig.h 包含OpenThread的配置的定义
util/src/ButtonManager.cpp 包含负责TLSR9518ADK80D按键设置的代码
util/src/LEDWidget.cpp LED管理器的相关代码
util/src/ThreadUtil.cpp 用静态密钥配置Thread网络的相关代码

Matter配置代码

Matter 的配置代码:

  • config/telink
文件 描述
app/enable-gnu-std.cmake 包括负责支持 gnu++17 标准的CMake
app/zephyr.conf Telink Matter SDK的Zephyr配置文件
chip-gn/ 包含gn特定文件的文件夹,以构建Telink Matter SDK
chip-module/CMakeLists.txt CMake配置文件,包含Telink Matter SDK的设置规则和依赖项。还包含gn设置到CMake的映射,以链接SDK与Zephyr
chip-module/Kconig 包含Matter SDK的Zephyr的Telink特定配置,也包括Matter的一般Zepyhr配置

Matter平台代码

Matter 的平台代码:

  • src/platform/telink
文件 描述
crypto/ 包含硬件加密所需源代码的文件夹
BLEManagerImpl.cpp 包含BLE Manager for Matter SDK实现的代码,基于Telink单连接BLE SDK
BUILD.gn 用于构建的gn文件
../Zephyr Zephyr平台层

Telink BLE 单连接SDK代码

Telink BLE 单连接SDK:

  • third_party/telink_sdk
文件 描述
BUILD.gn 构建Telink BLE SDK的gn文件
repo/ 包含Telink BLE SDK源代码的目录

Matter 开发详解

从“Matter中国区开发者大会”直播回放的 07:10:40 开始,有关于 Matter 开发的详细介绍,并在最后介绍了一个简单的 Hello Matter Sensor 实现。

电脑端观看地址:
https://wvk.h5.xeknow.com/sl/3x3C8A

手机端观看请扫描下方二维码:

“Matter中国区开发者大会”直播回放

附录1 - 生态配置

Google Matter Demo

Google Matter Demo概述

本章节以Telink Matter的lighting-app为例,将B91 EVK开发板作为一个Matter设备添加到Google Nest Hub Gen2上。
用户可以通过Google手机上的Google Home App控制开发板上的灯,可控内容为灯的亮灭,灯的亮度。

Google Matter所需的硬件

  • TLSR9518ADK80D 作为Matter灯设备
  • Google Nest Hub Gen2 作为Matter网络的Border Router
  • 可连接谷歌服务器的无线路由器 提供WiFi接入点,为Google Nest Hub Gen2提供数据校验
  • Google Pixel6手机 作为Commissioner,用户控制灯入网、开关的平台

Google Matter所需的软件

  • Google手机系统Android13且更新最新安全补丁
  • Google Nest Hub Gen 2nd Gen固件版本1.56.324896
  • Google Home软件版本2.2.60.2
  • Telink Matter lighting-app固件(编译环境Zephyr telink_matter_v1.0-branch和Matter v1.0-branch)

Google Matter拓扑结构

nesthub-topology

Google Matter连接步骤

  1. 将无线路由器上电,配置WiFi网络参数。

    注意:此时的无线路由器需要配置VPN,能正常访问 www.google.com

  2. 打开Google手机蓝牙,Google手机与Google Nest Hub Gen2连接到同一路由器的WiFi网络,在Google Home App中添加Google Nest Hub Gen2。

    Google Nest Hub Gen2配置教程 https://support.google.com/googlenest/answer/7029485?hl=en&co=GENIE.Platform%3DAndroid&oco=0

  3. 将B91 EVK开发板连接电源,开发板的串口通过USB-TTL工具连接到电脑,然后将开发板上电。

    开发板实物连接图

    开发板的PB2-TXD,PB3-RXD,串口配置信息115200,8N1,电脑端打开MobaXterm查看设备输出log。

  4. 当观察到开发板的红灯短亮并闪烁,从MobaXterm中找到设备二维码的网址(见图中红色框)。

    log中的二维码网址

  5. 复制网址到浏览器获取二维码。

    matter设备commission二维码

  6. 打开Google Home App,在主界面左上角的“+”号。

    点击主界面的加号

  7. 选择Set up device。

    选择Set up device

  8. 选择New device。

    选择New device

  9. 选择一个要加入的home。

    选择home

  10. 选择Matter-enabled device设备类型。

    选择设备类型

  11. 扫描浏览器上的二维码。

    扫描二维码

  12. 等待设备与Google Nest Hub Gen2之间完成commissioning。

    等待一段时间

  13. 设置设备名称。

    设置设备名称

  14. 成功添加Matter设备到Google Nest Hub Gen2,2rd floor light就是新添加的B91 EVK开发板。

    成功添加设备

  15. 进入操控界面,可以控制灯的亮灭和亮度。

    进入操控界面

Apple Matter Demo

Apple Matter Demo概述

本章节以Telink Matter的lighting-app为例,将B91 EVK开发板作为一个Matter灯设备添加到Apple HomePod Mini上。用户可以通过iPhone上的Home App控制开发板上的灯,可控内容为灯的亮灭,灯的亮度。

Apple Matter所需的硬件

  • TLSR9518ADK80D 作为Matter灯设备
  • Apple HomePod Mini 作为Matter网络的Border Router
  • 无线路由器 提供WiFi接入点,为Apple HomePod Mini提供数据校验
  • iPhone手机 作为Commissioner,用户控制灯入网、开关的平台

Apple Matter所需的软件

  • iPhone手机系统iOS16.1.2
  • Apple HomePod Mini固件版本16.2
  • Telink Matter lighting-app固件(编译环境Zephyr telink_matter_v1.0-branch和Matter v1.0-branch)

Apple Matter拓扑结构

homepod-topology

Apple Matter连接步骤

  1. 将无线路由器上电,配置WiFi网络参数。

  2. 打开iPhone手机蓝牙,并将iPhone手机连接到配置好的WiFi网络下,将Apple HomePod Mini上电。等待顶部触控板白灯开始旋转后,将iPhone手机靠近Apple HomePod Mini。出现图中悬浮窗,点击设置。

    开始配置homepod

  3. 将Apple HomePod Mini放入取景框。

    扫描homepod

  4. 等待Apple HomePod Mini设置完成。

    等待homepod配置完成

  5. 按照手机提示操作,成功添加Apple HomePod Mini到Home App。

    成功添加homepod

  6. 将B91 EVK开发板连接电源,开发板的串口通过USB-TTL工具连接到电脑,然后将开发板上电。

    开发板连接实物图

    开发板的PB2-TXD,PB3-RXD,串口配置信息115200,8N1,电脑端打开MobaXterm查看设备输出log。

  7. 当观察到开发板的红灯短亮并闪烁,从MobaXterm中找到设备二维码的网址(见图中红色框)。

    log中的二维码网址

  8. 复制网址到浏览器获取二维码。

    matter设备commission二维码

  9. 打开Apple Home App,在主界面右上角“+”号,选择添加或扫描配件。

    点击主界面的加号

  10. 扫描浏览器上的二维码。

    扫描二维码

  11. 点击“添加到‘Apple家庭’”。

    开始添加设备

  12. 出现弹窗,点击仍然添加。

    等待一段时间

  13. 设置设备名称。

    设置设备名称

  14. 成功添加B91 EVK到Apple HomePod Mini,light-1就是新添加的Matter灯设备。

    成功添加设备

  15. 进入操控界面,可以控制灯的亮灭和亮度。

    进入操控界面

附录2 - 环境搭建

需要 Ubuntu 版本为 20.04 LTS

安装Zephyr工程环境

注意:以下步骤和 Zephyr 官方文档 Getting Started Guide for Zephyr v3.0.0 的步骤不完全相同,因为我们是从 telink-semi 的仓库中下载 Zephyr 工程。

在进行接下去的操作前,先执行 APT 更新和升级:

sudo apt update
sudo apt upgrade
  1. 安装依赖项

    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 目前要求的主要依赖项的最低版本为:
    CMake (3.20.0), Python3 (3.6), Devicetree compiler (1.4.6).

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

    在进行下一步之前,请验证系统上安装的版本,否则请将APT镜像切换到稳定且最新的镜像,或手动更新这些依赖项。

  2. 安装 west

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

    确认 ~/.local/bin 在 $PATH 环境变量上。

  3. 获取 Zephyr 源码

    west init -m https://github.com/telink-semi/zephyr --mr telink_matter_v1.0-branch ~/zephyrproject
    cd ~/zephyrproject/zephyr
    west update
    west zephyr-export

    在中国大陆运行 west initwest update 来获取 Zephyr 源码通常会耗费额外的时间,此外,某些项目可能无法从外部服务器更新。
    请寻找其他方法来下载最新的源码。

  4. 安装 Zephyr 所需额外的 Python 依赖

    pip3 install --user -r ~/zephyrproject/zephyr/scripts/requirements.txt
  5. 安装 toolchain

    下载 Zephyr toolchain(约1.2GB)到本地目录,在中国大陆可能会耗费额外时间。

    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 ~/zephyr-sdk-0.13.2

    注意:在您安装好以后不能移动 SDK 文件夹。

  6. 验证安装完成

    在继续安装 Matter 工程环境之前,请先构建 Hello World 示例来验证 Zephyr 工程环境安装无误。

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

    在 Zephyr 根目录文件夹中用 west build 命令构建 hello_world 示例,构建完成后可以在 build_helloWorld/zephyr 文件夹下找到名为 zephyr.bin 的文件。

  7. 将Zephyr的环境脚本加入Shell之中

    注意:请将 zephyr 环境配置脚本追加到 ~/.bashrc 中,否则你可能会在之后的构建中遇到'west build'错误。

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

    然后执行以下命令让 shell 环境立刻更新:

    source ~/.bashrc

安装 Matter 工程环境

  1. 安装依赖项

    sudo apt-get install git gcc g++ python 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

    除了这些必需的工具,如果您的 PC 没有 GN 元构建系统,请安装。这个系统生成 Matter 工程用来构建应用程序的 Ninja 文件。

    mkdir ~/gn && cd ~/gn
    wget -O gn.zip https://chrome-infra-packages.appspot.com/dl/gn/gn/linux-amd64/+/latest
    unzip gn.zip
    echo 'export PATH=~/gn:"$PATH"' >> ~/.bashrc
    source ~/.bashrc
  2. 获取 Matter 工程并切换到 v1.0 分支

    在你想要访问的路径下,下载 Matter 工程,例如 /home/${YOUR_USERNAME}/。

    git clone https://github.com/project-chip/connectedhomeip
    cd ./connectedhomeip
    git checkout -b v1.0-branch origin/v1.0-branch 

    在中国大陆执行上面的 clone 命令可能会耗费额外时间。

  3. 更新子模块

    进入工程根目录并更新子模块:

    cd ./connectedhomeip
    git submodule update --init --recursive

    此更新在中国大陆可能会耗费额外时间。

    注意:GitHub上的官方存储库 connectedhomeip 在频繁更新,因此 Matter 固件和最新提交构建的 chip-tool 之间可能存在兼容性问题。如果在使用 chip-tool 进行配网时出现问题,可以尝试切换 commit 并重新执行第三步和第四步来解决这个问题。

  4. 执行 bootstrap

    下载和安装软件包,第一次执行的时候通常需要比较长的时间。

    source scripts/bootstrap.sh

    注意:每次切换 commit、改变环境都要重新运行引导程序

    此步骤将生成一个在 Matter 根目录 connectedhomeip 下的叫做 .environment 的隐藏文件夹。在中国大陆它可能会花费额外的时间或遭遇失败。

构建 Matter 示例

  1. 激活 Matter 环境

    source scripts/activate.sh
  2. 转到示例所在目录

    cd examples/${app}/telink

    ${app}: lighting-app 或者 light-switch-app 等

  3. 如果此前已经存在构建,则删除

    rm -rf build/
  4. 构建示例

    west build

    你可以在 build/zephyr 文件夹下找到名为 zephyr.bin 的目标构建文件。

附录3 - CD证书

对某些使用自己PAA证书的厂商会需要生成自己的认证证书(Certification Declaration ,CD),用于设备通过CSA认证之前的认证测试。

第一步:使用v1.0-branch的chip-cert工具,源码路径: connectedhomeip/src/tools/chip-cert,用以下命令生成chip-cert:

./scripts/activate.sh
gn gen out/host
ninja -C out/host chip-cert

第二步: 使用chip-cert工具生成认证证书。

./chip-cert gen-cd -C ../../../../credentials/test/certification-declaration/Chip-Test-CD-Signing-Cert.pem -K ../../../../credentials/test/certification-declaration/Chip-Test-CD-Signing-Key.pem --out telink_cd.bin -f 1 -V 1141  -p 8005 -d 0100 -c "ZIG0000000000000000" -l 0 -i 0 -n 0001 -t 1

厂商可能需要设置的参数为:

命令 描述
-V 1141 Vendor ID,厂商标识,0x1411为Telink VID
-p 8005 Product ID,产品标识,基于具体产品设置的标识
-d 0100 Device ID,设备标识,基于产品类型的标识,具体设备对应的标识在Matter标准中有详细规定,示例中设置的0x100为可调光的灯
-t 1 Certification-type,证书类型,Matter协议中规定的证书类型分三种:\ -t 0 - 开发和测试阶段使用,Matter默认类型 \ -t 1 - 临时使用,过认证时可使用这个类型 \ -t 2 - 认证通过后,会从CSA得到正式的认证证书

生成后的认证证书为bin格式,可以用以下命令验证认证证书的合法性:

./chip-cert print-cd ./telink_cd.bin

第三步:替换Matter工程中的认证证书(CD)

首先将二进制的证书转化为数组格式

xxd -i telink_cd.bin > telink_cd.h

当前Matter工程中,认证证书保存在宏定义CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION的数组中,只要用生成的telink_cd.h替换词宏定义即可。

宏定义CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION路径:
connectedhomeip/src/platform/telink/CHIPDevicePlatformConfig.h

附录4 - 厂商数据

厂商数据是在制造过程中写入非易失性存储器的一组设备参数。
本章节描述了使用 Telink Matter 来创建和编写厂商数据的过程。

厂商数据参数集包括不同类型的信息,例如关于设备证书、加密密钥、设备标识符,以及硬件。
所有的这些参数都是特定于厂商的,并且在制造过程中,必须添写到设备的持久性存储器中。
厂商数据参数将会在设备启动时被读取,然后它们可以被用在 Matter 栈和用户应用程序中(例如在配网过程中)。

所有的厂商数据参数都受保护,以免于被软件修改。
在设备使用周期内,固件的数据参数集必须保持不变。
在实现固件时,除了某些厂商定义的情况,您必须确保在设备固件更新或恢复出厂设置期间,厂商数据不被重写或覆盖。

对于 Telink 平台,厂商数据默认存储在内部闪存的一个单独的分区中。

概述

您可以用多种方式实现厂商数据组件表,只要最终的 HEX/BIN 文件包含表中定义的所有强制的组件。
在本节中,生成厂商数据构建带有厂商数据的示例描述了其中一种由Telink平台维护者创建的厂商数据集的实现方式。
在此过程结束时,您将得到一个包含 CBOR 格式的厂商数据分区的十六进制文件。

厂商数据访问器是一个组件,它从设备的持久存储中读取和解析厂商数据参数,并创建一个接口,将它们全部提供给 Matter 栈和用户应用程序。

厂商数据访问器的默认的实现认定存储在设备闪存中的厂商数据是以 CBOR 格式提供的。
但是,也可以不使用Telink脚本来生成厂商数据集,而是实现另一个解析器和厂商数据访问器。
如果新提供的实现和厂商数据提供程序中所规定的一致,则这是可能的。

注意:本功能还没有提供厂商数据分区的加密和安全性。

厂商数据组件表

下表列出了厂商数据集的参数:

Key name Full name Length Format Conformance Description
count number of factory binaries 4 B uint32 optional 要产生的生成分区二进制文件的数量。默认值为 1。
output output directory N/A ASCII string optional 存储生成数据的输出路径。
spake2-path spake2 path N/A ASCII string mandatory 提供 Spake2+ 工具路径
chip-tool-path chip tool path N/A ASCII string mandatory 提供 chip-tool 路径
chip-cert-path chip cert path N/A ASCII string mandatory 提供 chip-cert 路径
overwrite overwrite N/A bool optional 如果输出目录存在,此参数允许生成新的工厂数据并覆盖它。
in-tree in Matter tree N/A bool optional 仅在从 Matter 源代码构建工厂数据时使用它。
passcode SPAKE passcode 4 B uint32 optional 配对密码是一个 27 位无符号整数,用作配网期间的所有权证明。它的值必须限制在从“0x0000001”到“0x5F5E0FE”(十进制的“00000001”到“99999998”)之间的值,不包括以下无效密码值: 00000000, 11111111, 22222222, 33333333, 44444444, 55555555, 66666666, 77777777, 88888888, 99999999, 12345678, 87654321
spake2-it SPAKE2+ iteration counter 4 B uint32 mandatory SPAKE2+ 迭代计数器是在生成 SPAKE2+ 验证程序期间使用的加密过程中 PBKDF2(密钥派生函数)交互的数量。
discriminator Discriminator 2 B uint16 mandatory 与设置代码中同名字段匹配的 12 位值。 鉴别码在发现过程中使用。
commissioning-flow commisioning flow 4 B uint32 optional 设备配网流程, 0:Standard, 1:User-Intent, 2:Custom. 默认值为 0,选项为 [0, 1, 2]
discovery-mode discovery mode 4 B uint32 optional 可配网设备网络发现技术。 0:WiFi-SoftAP, 1:BLE, 2:On-network. 默认为 BLE, 选项为 [0, 1, 2]
vendor-id vendor ID 2 B uint16 mandatory CSA为负责生产设备的组织分配的ID。
vendor-name vendor name <1, 32> B ASCII string mandatory 一个人类可读的供应商名称,它提供一个简单的字符串,其中包含用于应用程序和Matter栈目的的设备供应商标识。
product-id product ID 2 B uint16 mandatory 设备供应商分配的唯一ID,用于标识产品。它默认为CSA分配的ID,用于指定非生产或测试产品。
product-name product name <1, 32> B ASCII string mandatory 一个人类可读的产品名称,它提供一个简单的字符串,其中包含用于应用程序和Matter栈目的的产品标识。
hw-ver hardware version 2 B uint16 mandatory 硬件版本号,指定了设备的硬件的版本号码。值的含义和版本控制方案由供应商定义。
hw-ver-str hardware version string <1, 64> B uint16 mandatory 一个硬件版本字符串参数,指定设备的硬件版本,作为比硬件版本整型值更用户友好的值。值的含义和版本控制方案由供应商定义。
mfg-date manufacturing date <8, 10> B ISO 8601 mandatory 制造日期指定设备制造的日期。使用的日期格式是 ISO 8601,例如 YYYY-MM-DD
serial-num serial number <1, 32> B ASCII string mandatory 序列号参数定义了制造设备的唯一编号。序列号的最大长度为32个字符。
enable-rotating-device-id enable rotating device id N/A bool optional 在生成的二进制文件中启用轮换设备id
rd-id-uid rotating device ID unique ID <16, 32> B byte string mandatory 轮换设备ID的唯一ID,由随机生成的128位(或更长)八位字节字符串组成。在初次引入设备后,该参数应防止通过空中读取或写入,并在设备的生命周期内保持固定。
cert certificate path N/A ASCII string optional 输入的证书文件为PEM格式。
key certificate key path N/A ASCII string optional PEM格式的输入密钥文件。
cert-dclrn certificate declaration path N/A ASCII string mandatory DER格式的证书声明文件。
dac-cert DAC certificate path N/A ASCII string optional 输入的DAC证书文件为PEM格式。
dac-key DAC certificate key path N/A ASCII string optional 输入的DAC私钥文件为PEM格式。
lifetime certificate lifetime 4 B uint32 optional 生成的证书的有效期。默认值是4294967295(如果没有指定),这表示证书没有明确定义的过期日期。
valid-from certificate start date <8, 19> B ISO 8601 optional 证书有效期的开始日期,格式为 YYYY-MM-DD [ HH:MM:SS ]。默认为当前日期。
paa PAA N/A bool optional 使用输入证书 cert 作为PAA证书。
pai PAI N/A bool optional 使用输入证书 cert 作为PAI证书。
offset factory partition offset 4 B uint32 mandatory 分区偏移量-设备NVM内存中的地址,工厂数据将存储在这里
size factory partition size 2 B uint16 mandatory 最大分区大小

厂商数据格式

厂商数据集必须保存到一个十六进制或二进制文件中,该文件可以写入到Matter设备的闪存中。

在Telink示例中,厂商数据集以 CBOR 格式表示,并存储在十六进制或二进制文件中。
然后,该文件将被烧录到一个设备上。
JSON 格式被用作一种中间的、人类可读的数据表示。
该格式由JSON模式文件规定。

厂商数据集的所有参数都是强制参数或可选参数:

  • 必须始终提供强制性参数,因为示例在进行配网进入Matter网络时需要它们。

  • 可选参数可用于开发和测试目的。例如,用户数据参数包含了特定制造商所需要的且不包含在强制性参数中的所有数据。

在厂商数据集中,使用了以下格式:

  • uint16uint32 -- 这些是分别表示两字节长度无符号整数,和四字节长度无符号整数的数字格式。此值以大端顺序存储在十六进制文件中

  • Byte string -- 该参数表示在0到255之间(包括255)的整数序列,没有任何编码。由于JSON格式不允许使用字节字符串,因此将 hex: 前缀添加到参数中,并将其转换为十六进制字符串。
    例如,一个ASCII字符串 abba 在JSON文件中被表示为十六进制:hex:61626261,然后以 0x61626261 存储在十六进制文件中。
    JSON文件中的十六进制字符串长度是字节字符串加上前缀大小的两倍。

  • ASCII string 是ASCII编码中的字符串表示形式,没有空终止。

  • ISO 8601 格式是一种日期格式,表示以YYYY-MM-DDYYYYMMDD格式提供的日期。

  • 存储在厂商数据中的所有证书都以X.509格式提供。

启用厂商数据支持

默认情况下,在所有的 Telink 示例中都禁用了厂商数据支持,并且 Telink 设备使用了来自 Matter 核心的预定义参数,您不应该更改这些参数。
要开始使用存储在闪存和 Telink 平台中的厂商数据和 Telink 平台的 Factory Data Provider,请使用以下选项构建一个示例:

west build -- -DCONFIG_CHIP_FACTORY_DATA=y

生成厂商数据

本节介绍使用以下 Telink Python 脚本生成厂商数据。

依赖项

在使用生成器工具之前,请确保您已具备以下工具。

构建 Matter 工具

详细描述

  1. 使用以下命令在 path/to/connectedhomeip/build/out/host 生成 chip-tool, spake2p and chip-cert

    cd path/to/connectedhomeip
    source scripts/activate.sh
    gn gen build/out/host
    ninja -C build/out/host
  2. 在 \$PATH 中加入工具路径

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

在设备上准备工厂数据分区

工厂数据分区是设备持久存储中存储工厂数据集的区域。这个区域在 DTS 文件里配置。

对于 Matter v1.0-branch 分支:
zephyr/boards/riscv/tlsr9518adk80d/tlsr9518adk80d.dts

对于 Matter master 分支:
connectedhomeip/tree/master/src/platform/telink/tlsr9518adk80d.overlay
其中声明了所有分区。

要准备一个支持工厂数据的示例,请在 tlsr9518adk80d.dts/tlsr9518adk80d.overlay 文件添加一个名为 factory-data 的分区。分区大小应该是一个 flash page 的倍数(对于B91 SoC,单个 page 大小等于 4kB)。

可以参考 闪存布局 中的工厂数据分区作为示例,详细在 tlsr9518adk80d.dts/tlsr9518adk80d.overlay 文件中。

factory-data 分区大小被设置为一个 flash page 大小(4kB)。

脚本使用

若要使用此脚本,请完成以下步骤:

  1. 进入 connectedhomeip 根目录。

  2. 使用 -h 选项运行脚本,以查看所有可能的选项:

    python scripts/tools/telink/mfg_tool.py -h
  3. 准备一个参数列表:

    a. 填写所有强制性参数:

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

    b. 添加输出文件路径:

    --output <output_dir>

    c. 添加证书声明路径(必选):

    -cd <path to Certificate Declaration in der format>

    d. 指定使用哪个证书:

    • 用户:

      --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
    • 生成DAC和PAI:

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

    e. (可选)使用以下选项之一为轮换设备 ID 添加新的唯一 ID:

    • 提供一个已存在的 ID:

      --rdid--uid <rotating device ID unique ID>
    • 生成一个新的 ID 并提供:

      --enable-rotating-device-id

    f. (可选)指定您自己的密码:

    --passcode <passcode>

    g. (可选)指定您自己的鉴别码:

    --discriminator <discriminator>

    h. (可选)添加覆盖现有输出文件的请求:

    --overwrite

    i. 指定分区偏移量和大小:

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

    In this command:

    • 是设备的持久存储区域中的地址,分区数据集将存储在其中。
    • 是设备持久存储区域中分区的大小。根据这个值检查新数据,看它的大小是否适合。

    重要提示:

    对 Matter v1.0-branch 分支使用:

    --offset 0xf4000 --size 0x1000

    对 Matter master 分支使用:

    --offset 0x104000 --size 0x1000
  4. 使用已准备好的参数列表运行该脚本:

    python3 mfg_tool.py <arguments>

    例如,对Python脚本的最终调用看起来类似于下面的用法:

    $ 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" \
        --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

    作为上述示例的结果,下面列出的文件将被创建:

    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. (可选示例)生成5个工厂分区 [可选参数 :--count]

    python3 mfg_tool.py --count 5 -v 0xFFF2 -p 0x8001 \
    --serial-num AABBCCDDEEFF11223344556677889900 \
    --vendor-name "Telink Semiconductor" \
    --product-name "not-specified" \
    --mfg-date 2022-12-02 \
    --hw-ver 1 \
    --hw-ver-str "prerelase" \
    --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
    ├── 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

注意:默认情况下,覆盖现有输出目录是禁用的。这意味着您不能在与现有文件相同的位置创建具有相同名称的新目录。要允许覆盖,请将 --overwrite 选项添加到 Python 脚本的参数列表中。

使用厂商数据构建示例

您可以使用生成厂商数据部分中描述的说明手动生成厂商数据集。另一种方法是使用 Telink 平台构建系统,该系统使用 Kconfig 选项自动创建厂商数据内容,并将内容包含在最终的二进制固件中。

要启用自动生成厂商数据集,请转到示例的目录,并使用以下选项构建示例:

west build -- -DCONFIG_CHIP_FACTORY_DATA=y

或者,您还可以将 CONFIG_CHIP_FACTORY_DATA=y 的Kconfig设置添加到示例的 prj.conf 文件中。

构建成功后会得到开启了厂商数据分区的示例固件,烧录时需要同时烧录此固件以及脚本使用一节中 mfg_tool.py 生成的厂商数据固件。

设置厂商数据

包含厂商数据的HEX/BIN文件可以使用BDT工具和Telink burning key烧录到设备的闪存中。

  • 对于 master 分支来说,厂商数据的烧录地址为 0x104000。
  • 对于 v1.0 分支来说,厂商数据的烧录地址为 0xf4000。

烧录时使用 Telink BDT 工具的多地址烧录即可:

  1. 选择 Tool 中的Multi-address download

    BDT多地址烧录选择

  2. 此处以 mater 分支上的固件为示例:

    BDT多地址烧录

使用自己的厂商数据实现

上面介绍的厂商数据生成过程仅是对Telink平台有效的示例。
您可以创建一个包含任意格式的所有厂商数据组件表的HEX文件,然后实现一个解析器来读取所有参数并将它们传递给提供程序。
每个制造商都可以通过在Matter栈中实现解析器和厂商数据访问器来自行实现厂商数据集。
使用Telink厂商数据提供程序厂商数据解析器作为示例。

根据用途和格式的不同,您可以用不同的方式从设备的闪存中读取厂商数据集。
在Telink示例中,厂商数据以 CBOR 格式存储。
设备使用厂商数据解析器读取输出原始数据,将其解码并存储在 FactoryData 结构中。
厂商数据提供程序实现使用这个解析器获取所有需要的厂商数据参数,并将它们提供给Matter核心。

在Telink示例中, FactoryDataProvider是一个模板类,继承自DeviceAttestationCredentialsProvider, CommissionableDataProvider, 和 DeviceInstanceInfoProvider 类。
您的自定义实现还必须继承这些类并实现它们的功能来从设备的闪存中获取所有厂商数据集。
这些类是虚类,需要由派生类重写。
要覆盖继承的类,请完成以下步骤:

  1. 覆盖以下方法:

        // ===== 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. 将新创建的解析器和提供程序文件移动到项目目录中。

  3. 把文件添加到 CMakeList.txt 中。

  4. 禁用厂商数据提供程序的默认实现和Telink实现,以开始使用您自己的厂商数据解析器和提供程序实现。
    这可以通过以下方式之一来实现:

    • 把Kconfig设置 CONFIG_CHIP_FACTORY_DATA_CUSTOM_BACKEND=y 加到 prj.conf 文件中。
    • 用以下选项构建一个示例:

      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 © 2022 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 emails to the address of:

telinkcnsales@telink-semi.com

telinkcnsupport@telink-semi.com

Revision History{-}


Version Change Description


V1.0.0 Preliminary release

V1.0.1 Change multicast binding steps

V1.0.2 Add Usage of LinuxBDT

V1.0.3 Add Usage of OTA feature, update some details

V1.0.4 Add factory data

V1.0.5 Update Telink Matter examples and Add video link of Developer Conference

V1.0.6 Add detailed descriptions on some important initialization functions

V1.0.7 Add Apple and Google Matter Demo into appendix

V1.0.8 Add manual build instructions into appendix2

V1.0.9 Add Certification Declaration configuration into appendix3

V1.0.10 Move factory data section into appendix4, update the latest RPi image link