diff --git a/examples/light-switch-app/silabs/SiWx917/.gn b/examples/light-switch-app/silabs/SiWx917/.gn
new file mode 100644
index 00000000000000..4c078f6acefdcc
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/.gn
@@ -0,0 +1,29 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_openthread_ftd = true
+
+ import("//args.gni")
+}
diff --git a/examples/light-switch-app/silabs/SiWx917/BUILD.gn b/examples/light-switch-app/silabs/SiWx917/BUILD.gn
new file mode 100644
index 00000000000000..b7bf2c938faf45
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/BUILD.gn
@@ -0,0 +1,367 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${build_root}/config/defaults.gni")
+import("${efr32_sdk_build_root}/SiWx917_sdk.gni")
+import("${efr32_sdk_build_root}/efr32_executable.gni")
+
+import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni")
+import("${chip_root}/src/platform/device.gni")
+
+if (chip_enable_pw_rpc) {
+ import("//build_overrides/pigweed.gni")
+ import("$dir_pw_build/target_types.gni")
+}
+
+assert(current_os == "freertos")
+
+efr32_project_dir = "${chip_root}/examples/light-switch-app/silabs/SiWx917"
+examples_plat_dir = "${chip_root}/examples/platform/silabs/SiWx917"
+examples_common_plat_dir = "${chip_root}/examples/platform/silabs"
+
+declare_args() {
+ # Dump memory usage at link time.
+ chip_print_memory_usage = false
+
+ # Monitor & log memory usage at runtime.
+ enable_heap_monitoring = false
+
+ # Enable Sleepy end device
+ enable_sleepy_device = false
+
+ # OTA timeout in seconds
+ OTA_periodic_query_timeout = 86400
+
+ # Wifi related stuff - they are overridden by gn -args="use_wf200=true"
+ use_wf200 = false
+ use_rs911x = false
+ use_rs911x_sockets = false
+ sl_wfx_config_softap = false
+ sl_wfx_config_scan = true
+
+ # Disable LCD on supported devices
+ disable_lcd = true
+
+ # Argument to Disable IPv4 for wifi(rs911)
+ chip_enable_wifi_ipv4 = false
+
+ # Argument to force enable WPA3 security
+ rs91x_wpa3_only = false
+
+ #default WiFi SSID
+ chip_default_wifi_ssid = ""
+
+ #default Wifi Password
+ chip_default_wifi_psk = ""
+}
+
+declare_args() {
+ # Enables LCD Qr Code on supported devices
+ show_qr_code = !disable_lcd
+}
+
+# qr code cannot be true if lcd is disabled
+assert(!(disable_lcd && show_qr_code))
+
+# Sanity check
+assert(!(chip_enable_wifi && chip_enable_openthread))
+assert(!(use_rs911x && chip_enable_openthread))
+assert(!(use_wf200 && chip_enable_openthread))
+if (chip_enable_wifi) {
+ assert(use_rs911x || use_wf200)
+ enable_openthread_cli = false
+ import("${chip_root}/src/platform/silabs/SiWx917/wifi_args.gni")
+}
+
+# ThunderBoards, Explorer Kit and MGM240L do not support LCD (No LCD)
+if (silabs_board == "BRD4166A" || silabs_board == "BRD2601B" ||
+ silabs_board == "BRD2703A" || silabs_board == "BRD4319A") {
+ show_qr_code = false
+ disable_lcd = true
+}
+
+defines = []
+
+# WiFi settings
+if (chip_enable_wifi) {
+ if (chip_default_wifi_ssid != "") {
+ defines += [
+ "CHIP_ONNETWORK_PAIRING=1",
+ "CHIP_WIFI_SSID=\"${chip_default_wifi_ssid}\"",
+ ]
+ }
+ if (chip_default_wifi_psk != "") {
+ assert(chip_default_wifi_ssid != "",
+ "ssid can't be null if psk is provided")
+ defines += [ "CHIP_WIFI_PSK=\"${chip_default_wifi_psk}\"" ]
+ }
+ wifi_sdk_dir = "${chip_root}/src/platform/silabs/SiWx917/wifi"
+ efr32_lwip_defs = [ "LWIP_NETIF_API=1" ]
+ if (lwip_ipv4) {
+ efr32_lwip_defs += [
+ "LWIP_IPV4=1",
+
+ # adds following options to provide
+ # them to .cpp source files
+ # flags ported from lwipopts file
+ # TODO: move lwipopts to one location
+ "LWIP_ARP=1",
+ "LWIP_ICMP=1",
+ "LWIP_IGMP=1",
+ "LWIP_DHCP=1",
+ "LWIP_DNS=0",
+ ]
+ } else {
+ efr32_lwip_defs += [ "LWIP_IPV4=0" ]
+ }
+ if (lwip_ipv6) {
+ efr32_lwip_defs += [ "LWIP_IPV6=1" ]
+ } else {
+ efr32_lwip_defs += [ "LWIP_IPV6=0" ]
+ }
+
+ wiseconnect_sdk_root = "${chip_root}/third_party/silabs/wisemcu-wifi-bt-sdk"
+ import("${examples_plat_dir}/SiWx917/rs911x.gni")
+}
+
+efr32_sdk("sdk") {
+ sources = [
+ "${efr32_project_dir}/include/CHIPProjectConfig.h",
+ "${examples_plat_dir}/FreeRTOSConfig.h",
+ ]
+
+ include_dirs = [
+ "${chip_root}/src/platform/silabs/SiWx917",
+ "${efr32_project_dir}/include",
+ "${examples_plat_dir}",
+ "${chip_root}/src/lib",
+ "${examples_common_plat_dir}",
+ ]
+
+ defines += [
+ "BOARD_ID=${silabs_board}",
+ "OTA_PERIODIC_TIMEOUT=${OTA_periodic_query_timeout}",
+ ]
+
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "HAL_VCOM_ENABLE=1",
+ "PW_RPC_ENABLED",
+ ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ if (use_rs911x) {
+ defines += rs911x_defs
+ include_dirs += rs911x_plat_incs
+ } else if (use_wf200) {
+ defines += wf200_defs
+ include_dirs += wf200_plat_incs
+ }
+
+ if (use_rs911x_sockets) {
+ include_dirs += [ "${examples_plat_dir}/wifi/rsi-sockets" ]
+ defines += rs911x_sock_defs
+ } else {
+ # Using LWIP instead of the native TCP/IP stack
+ defines += efr32_lwip_defs
+ }
+
+ if (sl_wfx_config_softap) {
+ defines += [ "SL_WFX_CONFIG_SOFTAP" ]
+ }
+ if (sl_wfx_config_scan) {
+ defines += [ "SL_WFX_CONFIG_SCAN" ]
+ }
+ }
+}
+
+efr32_executable("light_switch_app") {
+ output_name = "chip-efr32-light-switch-example.out"
+ public_configs = [ "${efr32_sdk_build_root}:silabs_config" ]
+ include_dirs = [ "include" ]
+ defines = []
+
+ sources = [
+ "${examples_common_plat_dir}/heap_4_silabs.c",
+ "${examples_plat_dir}/BaseApplication.cpp",
+ "${examples_plat_dir}/init_ccpPlatform.cpp",
+ "${examples_plat_dir}/matter_config.cpp",
+ "${examples_plat_dir}/siwx917_utils.cpp",
+ "src/AppTask.cpp",
+ "src/ZclCallbacks.cpp",
+ "src/binding-handler.cpp",
+ "src/main.cpp",
+ ]
+
+ if (use_wstk_leds) {
+ #sources += [ "${examples_plat_dir}/LEDWidget.cpp" ]
+ }
+
+ if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli ||
+ use_wf200 || use_rs911x) {
+ #sources += [ "${examples_plat_dir}/uart.cpp" ]
+ }
+
+ deps = [
+ ":sdk",
+ "${chip_root}/examples/light-switch-app/light-switch-common",
+ "${chip_root}/examples/providers:device_info_provider",
+ "${chip_root}/src/lib",
+ "${chip_root}/src/setup_payload",
+ ]
+
+ # Attestation Credentials
+ if (chip_build_platform_attestation_credentials_provider) {
+ deps += [ "${examples_plat_dir}:siwx917-attestation-credentials" ]
+ }
+
+ # Factory Data Provider
+ if (use_efr32_factory_data_provider) {
+ deps += [ "${examples_plat_dir}:efr32-factory-data-provider" ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ if (use_rs911x) {
+ sources += rs911x_src_plat
+
+ # All the stuff from wiseconnect
+ sources += rs911x_src_sapi
+
+ # Apparently - the rsi library needs this (though we may not use use it)
+ sources += rs911x_src_sock
+ include_dirs += rs911x_inc_plat
+
+ if (use_rs911x_sockets) {
+ #
+ # Using native sockets inside RS911x
+ #
+ include_dirs += rs911x_sock_inc
+ } else {
+ #
+ # We use LWIP - not built-in sockets
+ #
+ sources += rs911x_src_lwip
+ }
+ } else if (use_wf200) {
+ sources += wf200_plat_src
+ include_dirs += wf200_plat_incs
+ }
+
+ if (chip_enable_wifi_ipv4) {
+ defines += [ "CHIP_DEVICE_CONFIG_ENABLE_IPV4" ]
+ }
+
+ if (rs91x_wpa3_only) {
+ # TODO: Change this macro once WF200 support is provided
+ defines += [ "WIFI_ENABLE_SECURITY_WPA3=1" ]
+ }
+ }
+
+ if (!disable_lcd) {
+ sources += [
+ "${examples_plat_dir}/display/demo-ui.c",
+ "${examples_plat_dir}/display/lcd.cpp",
+ ]
+ include_dirs += [ "${examples_plat_dir}/display" ]
+ defines += [
+ "DISPLAY_ENABLED",
+ "IS_DEMO_SWITCH=1",
+ ]
+ if (show_qr_code) {
+ defines += [ "QR_CODE_ENABLED" ]
+ deps += [ "${chip_root}/examples/common/QRCode" ]
+ }
+ }
+
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "PW_RPC_ENABLED",
+ "PW_RPC_ATTRIBUTE_SERVICE=1",
+ "PW_RPC_BUTTON_SERVICE=1",
+ "PW_RPC_DESCRIPTOR_SERVICE=1",
+ "PW_RPC_DEVICE_SERVICE=1",
+ "PW_RPC_LIGHTING_SERVICE=1",
+ ]
+
+ sources += [
+ "${chip_root}/examples/common/pigweed/RpcService.cpp",
+ "${chip_root}/examples/common/pigweed/efr32/PigweedLoggerMutex.cpp",
+ "${examples_common_plat_dir}/PigweedLogger.cpp",
+ "${examples_common_plat_dir}/Rpc.cpp",
+ ]
+
+ deps += [
+ "$dir_pw_hdlc:rpc_channel_output",
+ "$dir_pw_stream:sys_io_stream",
+ "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc",
+ "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc",
+ "${examples_plat_dir}/pw_sys_io:pw_sys_io_siwx917",
+ ]
+
+ deps += pw_build_LINK_DEPS
+
+ include_dirs += [
+ "${chip_root}/examples/common",
+ "${chip_root}/examples/common/pigweed/efr32",
+ ]
+ }
+
+ if (enable_heap_monitoring) {
+ sources += [ "${examples_common_plat_dir}/MemMonitoring.cpp" ]
+ defines += [ "HEAP_MONITORING" ]
+ }
+
+ ldscript = "${examples_plat_dir}/ldscripts/${silabs_family}.ld"
+
+ inputs = [ ldscript ]
+
+ ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ]
+
+ if (chip_print_memory_usage) {
+ ldflags += [
+ "-Wl,--print-memory-usage",
+ "-fstack-usage",
+ ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ ldflags += [
+ "-Wl,--defsym",
+ "-Wl,SILABS_WIFI=1",
+ ]
+ }
+
+ output_dir = root_out_dir
+}
+
+group("efr32") {
+ deps = [ ":light_switch_app" ]
+}
+
+group("default") {
+ deps = [ ":efr32" ]
+}
diff --git a/examples/light-switch-app/silabs/SiWx917/README.md b/examples/light-switch-app/silabs/SiWx917/README.md
new file mode 100644
index 00000000000000..3a72765e663796
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/README.md
@@ -0,0 +1,468 @@
+# Matter EFR32 Light Switch Example
+
+An example showing the use of CHIP on the Silicon Labs EFR32 MG12 and MG24.
+
+
+
+- [Matter EFR32 Light Switch Example](#matter-efr32-light-switch-example)
+ - [Introduction](#introduction)
+ - [Building](#building)
+ - [Linux](#linux)
+ - [Mac OS X](#mac-os-x)
+ - [Flashing the Application](#flashing-the-application)
+ - [Viewing Logging Output](#viewing-logging-output)
+ - [Running the Complete Example](#running-the-complete-example)
+ - [Notes](#notes)
+ - [On Border Router:](#on-border-router)
+ - [On PC(Linux):](#on-pclinux)
+ - [Running RPC console](#running-rpc-console)
+ - [Memory settings](#memory-settings)
+ - [OTA Software Update](#ota-software-update)
+ - [Building options](#building-options)
+ - [Disabling logging](#disabling-logging)
+ - [Debug build / release build](#debug-build--release-build)
+ - [Disabling LCD](#disabling-lcd)
+ - [KVS maximum entry count](#kvs-maximum-entry-count)
+
+
+
+> **NOTE:** Silicon Laboratories now maintains a public matter GitHub repo with
+> frequent releases thoroughly tested and validated. Developers looking to
+> develop matter products with silabs hardware are encouraged to use our latest
+> release with added tools and documentation.
+> [Silabs Matter Github](https://github.com/SiliconLabs/matter/releases)
+
+
+
+## Introduction
+
+The EFR32 light switch example provides a baseline demonstration of a on-off
+light switch device, built using Matter and the Silicon Labs gecko SDK. It can
+be controlled by a Chip controller over an Openthread or Wifi network.
+
+The EFR32 device can be commissioned over Bluetooth Low Energy where the device
+and the Chip controller will exchange security information with the Rendez-vous
+procedure. If using Thread, Thread Network credentials are then provided to the
+EFR32 device which will then join the network.
+
+If the LCD is enabled, the LCD on the Silabs WSTK shows a QR Code containing the
+needed commissioning information for the BLE connection and starting the
+Rendez-vous procedure.
+
+The light switch example is intended to serve both as a means to explore the
+workings of Matter as well as a template for creating real products based on the
+Silicon Labs platform.
+
+
+
+## Building
+
+- Download the
+ [Simplicity Commander](https://www.silabs.com/mcu/programming-options)
+ command line tool, and ensure that `commander` is your shell search path.
+ (For Mac OS X, `commander` is located inside
+ `Commander.app/Contents/MacOS/`.)
+
+- Download and install a suitable ARM gcc tool chain:
+ [GNU Arm Embedded Toolchain 9-2019-q4-major](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads)
+
+- Install some additional tools(likely already present for CHIP developers):
+
+#### Linux
+
+ $ sudo apt-get install git ninja-build
+
+#### Mac OS X
+
+ $ brew install ninja
+
+- Supported hardware:
+
+ - > For the latest supported hardware please refer to the
+ > [Hardware Requirements](https://github.com/SiliconLabs/matter/blob/latest/docs/silabs/general/HARDWARE_REQUIREMENTS.md)
+ > in the Silicon Labs Matter Github Repo
+
+ MG12 boards:
+
+ - BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+ 868MHz@19dBm
+ - BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+ - BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+ 915MHz@19dBm
+ - BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+ MG21 boards: Currently not supported due to RAM limitation.
+
+ - BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG24 boards :
+
+ - BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+ - BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG12 boards:
+
+ - BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+ 868MHz@19dBm
+ - BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+ - BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+ 915MHz@19dBm
+ - BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+ MG21 boards: Currently not supported due to RAM limitation.
+
+ - BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG24 boards :
+
+ - BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+ - BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+* Build the example application:
+
+ cd ~/connectedhomeip
+ ./scripts/examples/gn_efr32_example.sh ./examples/light-switch-app/efr32/ ./out/light-switch-app BRD4161A
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/connectedhomeip
+ $ rm -rf ./out/
+
+ OR use GN/Ninja directly
+
+ $ cd ~/connectedhomeip/examples/light-switch-app/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug
+ $ ninja -C out/debug
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/connectedhomeip/examples/light-switch-app/efr32
+ $ rm -rf out/
+
+* Build the example with Matter shell
+
+ ./scripts/examples/gn_efr32_example.sh examples/light-switch-app/efr32/ out/light-switch-app BRD4161A chip_build_libshell=true
+
+* Build the example as Sleepy End Device (SED)
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/light-switch-app/efr32/ ./out/light-switch-app_SED BRD4161A --sed
+
+ or use gn as previously mentioned but adding the following arguments:
+
+ $ gn gen out/debug '--args=silabs_board="BRD4161A" enable_sleepy_device=true chip_openthread_ftd=false chip_build_libshell=true'
+
+* Build the example with pigweed RCP
+
+ $ ./scripts/examples/gn_efr32_example.sh examples/light-switch-app/efr32/ out/light-switch-app_rpc BRD4161A 'import("//with_pw_rpc.gni")'
+
+ or use GN/Ninja Directly
+
+ $ cd ~/connectedhomeip/examples/light-switch-app/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug --args='import("//with_pw_rpc.gni")'
+ $ ninja -C out/debug
+
+ [Running Pigweed RPC console](#running-pigweed-rpc-console)
+
+For more build options, help is provided when running the build script without
+arguments
+
+ ./scripts/examples/gn_efr32_example.sh
+
+
+
+## Flashing the Application
+
+- On the command line:
+
+ $ cd ~/connectedhomeip/examples/lighting-app/efr32
+ $ python3 out/debug/chip-efr32-light-switch-example.flash.py
+
+- Or with the Ozone debugger, just load the .out file.
+
+
+
+## Viewing Logging Output
+
+The example application is built to use the SEGGER Real Time Transfer (RTT)
+facility for log output. RTT is a feature built-in to the J-Link Interface MCU
+on the WSTK development board. It allows bi-directional communication with an
+embedded application without the need for a dedicated UART.
+
+Using the RTT facility requires downloading and installing the _SEGGER J-Link
+Software and Documentation Pack_
+([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)).
+
+Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too
+after flashing the .out file.
+
+- Download the J-Link installer by navigating to the appropriate URL and
+ agreeing to the license agreement.
+
+- [JLink_Linux_x86_64.deb](https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.deb)
+- [JLink_MacOSX.pkg](https://www.segger.com/downloads/jlink/JLink_MacOSX.pkg)
+
+* Install the J-Link software
+
+ $ cd ~/Downloads
+ $ sudo dpkg -i JLink_Linux_V*_x86_64.deb
+
+* In Linux, grant the logged in user the ability to talk to the development
+ hardware via the linux tty device (/dev/ttyACMx) by adding them to the
+ dialout group.
+
+ $ sudo usermod -a -G dialout ${USER}
+
+Once the above is complete, log output can be viewed using the JLinkExe tool in
+combination with JLinkRTTClient as follows:
+
+- Run the JLinkExe tool with arguments to autoconnect to the WSTK board:
+
+ For MG12 use:
+
+ $ JLinkExe -device EFR32MG12PXXXF1024 -if JTAG -speed 4000 -autoconnect 1
+
+ For MG21 use:
+
+ $ JLinkExe -device EFR32MG21AXXXF1024 -if SWD -speed 4000 -autoconnect 1
+
+- In a second terminal, run the JLinkRTTClient to view logs:
+
+ $ JLinkRTTClient
+
+
+
+## Running the Complete Example
+
+- It is assumed here that you already have an OpenThread border router
+ configured and running. If not see the following guide
+ [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md)
+ for more information on how to setup a border router on a raspberryPi.
+
+ Take note that the RCP code is available directly through
+ [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5)
+ under File->New->Project Wizard->Examples->Thread : ot-rcp
+
+- For this example to work, it is necessary to have a second efr32 device
+ running the
+ [lighting app example](https://github.com/project-chip/connectedhomeip/blob/master/examples/lighting-app/efr32/README.md)
+ commissioned on the same openthread network
+
+- User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR
+ Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over
+ BLE
+
+ * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2,
+ a URL can be found in the RTT logs.
+
+ [SVR] Copy/paste the below URL in a browser to see the QR Code:
+ [SVR] https://project-chip.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0
+
+ **LED 0** shows the overall state of the device and its connectivity. The
+ following states are possible:
+
+ - Short Flash On (50 ms on/950 ms off): The device is in the
+ unprovisioned (unpaired) state and is waiting for a commissioning
+ application to connect.
+
+ - Rapid Even Flashing (100 ms on/100 ms off): The device is in the
+ unprovisioned state and a commissioning application is connected through
+ Bluetooth LE.
+
+ - Short Flash Off (950ms on/50ms off): The device is fully
+ provisioned, but does not yet have full Thread network or service
+ connectivity.
+
+ - Solid On: The device is fully provisioned and has full Thread
+ network and service connectivity.
+
+ **Push Button 0**
+
+ - _Press and Release_ : Start, or restart, BLE advertisement in fast mode. It will advertise in this mode
+ for 30 seconds. The device will then switch to a slower interval advertisement.
+ After 15 minutes, the advertisement stops.
+
+ - _Pressed and hold for 6 s_ : Initiates the factory reset of the device.
+ Releasing the button within the 6-second window cancels the factory reset
+ procedure. **LEDs** blink in unison when the factory reset procedure is
+ initiated.
+
+ **Push Button 1**
+
+ - Sends a Toggle command to bound light app
+
+ **Matter shell**
+
+ **_OnOff Cluster_**
+
+ - 'switch onoff on' : Sends unicast On command to bound device
+ - 'switch onoff off' : Sends unicast Off command to bound device
+ - 'switch onoff toggle' : Sends unicast Toggle command to bound device
+
+ - 'switch groups onoff on' : Sends On group command to bound group
+ - 'switch groups onoff off' : Sends On group command to bound group
+ - 'switch groups onoff toggle' : Sends On group command to bound group
+
+ **_Binding Cluster_**
+
+ - 'switch binding unicast ' : Creates a unicast binding
+ - 'switch binding group ' : Creates a group binding
+
+* You can provision and control the Chip device using the python controller,
+ [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
+ standalone, Android or iOS app
+
+ Here is an example with the CHIPTool for unicast commands only:
+
+ ```
+ chip-tool pairing ble-thread 1 hex: 20202021 3840
+
+ chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [], "targets": null }{"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": [1], "targets": null }]' 0
+
+ chip-tool binding write binding '[{"fabricIndex": 1, "node": , "endpoint": 1, "cluster":6}]' 1 1
+ ```
+
+ Here is an example with the CHIPTool for groups commands only:
+
+ ```
+ chip-tool pairing ble-thread 1 hex: 20202021 3840
+
+ chip-tool tests TestGroupDemoConfig --nodeId 1
+
+ chip-tool tests TestGroupDemoConfig --nodeId
+
+ chip-tool binding write binding '[{"fabricIndex": 1, "group": 257}]' 1 1
+ ```
+
+ To run the example with unicast and groups commands, run the group
+ configuration commands and replace the last one with binding this command
+
+ ```
+ chip-tool binding write binding '[{"fabricIndex": 1, "group": 257},{"fabricIndex": 1, "node": , "endpoint": 1, "cluster":6} ]' 1 1
+ ```
+
+ To acquire the chip-tool node id, read the acl table right after
+ commissioning
+
+ ```
+ ./connectedhomeip/out/chip-tool/chip-tool accesscontrol read acl 0
+ ```
+
+### Notes
+
+- Depending on your network settings your router might not provide native ipv6
+ addresses to your devices (Border router / PC). If this is the case, you
+ need to add a static ipv6 addresses on both device and then an ipv6 route to
+ the border router on your PC
+
+#### On Border Router:
+
+`$ sudo ip addr add dev 2002::2/64`
+
+#### On PC(Linux):
+
+`$ sudo ip addr add dev 2002::1/64`
+
+#Add Ipv6 route on PC(Linux) \$ sudo ip route add /64
+via 2002::2
+
+
+
+## Running RPC console
+
+- As part of building the example with RPCs enabled the chip_rpc python
+ interactive console is installed into your venv. The python wheel files are
+ also created in the output folder: out/debug/chip_rpc_console_wheels. To
+ install the wheel files without rebuilding:
+
+ `pip3 install out/debug/chip_rpc_console_wheels/*.whl`
+
+- To use the chip-rpc console after it has been installed run:
+
+ `chip-console --device /dev/tty. -b 115200 -o //pw_log.out`
+
+- Then you can simulate a button press or release using the following command
+ where : idx = 0 or 1 for Button PB0 or PB1 action = 0 for PRESSED, 1 for
+ RELEASE Test toggling the LED with
+
+ `rpcs.chip.rpc.Button.Event(idx=1, pushed=True)`
+
+- You can also Get and Set the light directly using the RPCs:
+
+ `rpcs.chip.rpc.Lighting.Get()`
+
+ `rpcs.chip.rpc.Lighting.Set(on=True, level=128, color=protos.chip.rpc.LightingColor(hue=5, saturation=5))`
+
+## Memory settings
+
+While most of the RAM usage in CHIP is static, allowing easier debugging and
+optimization with symbols analysis, we still need some HEAP for the crypto and
+OpenThread. Size of the HEAP can be modified by changing the value of the
+`configTOTAL_HEAP_SIZE` define inside of the FreeRTOSConfig.h file of this
+example. Please take note that a HEAP size smaller than 13k can and will cause a
+Mbedtls failure during the BLE rendez-vous or CASE session
+
+To track memory usage you can set `enable_heap_monitoring = true` either in the
+BUILD.gn file or pass it as a build argument to gn. This will print on the RTT
+console the RAM usage of each individual task and the number of Memory
+allocation and Free. While this is not extensive monitoring you're welcome to
+modify `examples/platform/efr32/MemMonitoring.cpp` to add your own memory
+tracking code inside the `trackAlloc` and `trackFree` function
+
+## OTA Software Update
+
+For the description of Software Update process with EFR32 example applications
+see
+[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md)
+
+## Building options
+
+All of Silabs's examples within the Matter repo have all the features enabled by
+default, as to provide the best end user experience. However some of those
+features can easily be toggled on or off. Here is a short list of options :
+
+### Disabling logging
+
+chip_progress_logging, chip_detail_logging, chip_automation_logging
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false"
+
+### Debug build / release build
+
+is_debug
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "is_debug=false"
+
+### Disabling LCD
+
+show_qr_code
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "show_qr_code=false"
+
+### KVS maximum entry count
+
+kvs_max_entries
+
+ Set the maximum Kvs entries that can be stored in NVM (Default 75)
+ Thresholds: 30 <= kvs_max_entries <= 255
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50
diff --git a/examples/light-switch-app/silabs/SiWx917/args.gni b/examples/light-switch-app/silabs/SiWx917/args.gni
new file mode 100644
index 00000000000000..421090dbc97aae
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/args.gni
@@ -0,0 +1,24 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/src/platform/silabs/SiWx917/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_ota_requestor = true
+chip_enable_openthread = true
+openthread_external_platform =
+ "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32"
diff --git a/examples/light-switch-app/silabs/SiWx917/build_for_wifi_args.gni b/examples/light-switch-app/silabs/SiWx917/build_for_wifi_args.gni
new file mode 100644
index 00000000000000..b1a0be42ca9351
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/build_for_wifi_args.gni
@@ -0,0 +1,21 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+chip_enable_openthread = false
+import("${chip_root}/src/platform/silabs/SiWx917/wifi_args.gni")
+
+chip_enable_ota_requestor = true
diff --git a/examples/light-switch-app/silabs/SiWx917/build_for_wifi_gnfile.gn b/examples/light-switch-app/silabs/SiWx917/build_for_wifi_gnfile.gn
new file mode 100644
index 00000000000000..d391814190d09f
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/build_for_wifi_gnfile.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_enable_wifi = true
+ import("//build_for_wifi_args.gni")
+}
diff --git a/examples/light-switch-app/silabs/SiWx917/build_overrides b/examples/light-switch-app/silabs/SiWx917/build_overrides
new file mode 120000
index 00000000000000..995884e6163eb5
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/build_overrides
@@ -0,0 +1 @@
+../../../build_overrides
\ No newline at end of file
diff --git a/examples/light-switch-app/silabs/SiWx917/include/AppConfig.h b/examples/light-switch-app/silabs/SiWx917/include/AppConfig.h
new file mode 100644
index 00000000000000..a936fe1d8abaeb
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/include/AppConfig.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// ---- Lighting Example App Config ----
+
+#define APP_TASK_NAME "Lit"
+
+// Time it takes in ms for the simulated actuator to move from one
+// state to another.
+#define ACTUATOR_MOVEMENT_PERIOS_MS 10
+
+// EFR Logging
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void silabsInitLog(void);
+
+void efr32Log(const char * aFormat, ...);
+#define SILABS_LOG(...) efr32Log(__VA_ARGS__);
+void appError(int err);
+
+#ifdef __cplusplus
+}
+
+#include
+void appError(CHIP_ERROR error);
+#endif
diff --git a/examples/light-switch-app/silabs/SiWx917/include/AppEvent.h b/examples/light-switch-app/silabs/SiWx917/include/AppEvent.h
new file mode 100644
index 00000000000000..7a19b719edad25
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/include/AppEvent.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2018 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+ enum AppEventTypes
+ {
+ kEventType_Button = 0,
+ kEventType_Timer,
+ kEventType_Light,
+ kEventType_Install,
+ };
+
+ uint16_t Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ void * Context;
+ } TimerEvent;
+ struct
+ {
+ uint8_t Action;
+ int32_t Actor;
+ } LightEvent;
+ };
+
+ EventHandler Handler;
+};
diff --git a/examples/light-switch-app/silabs/SiWx917/include/AppTask.h b/examples/light-switch-app/silabs/SiWx917/include/AppTask.h
new file mode 100644
index 00000000000000..29a0078d1472f3
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/include/AppTask.h
@@ -0,0 +1,164 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include
+#include
+
+#include "AppEvent.h"
+#include "BaseApplication.h"
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include
+#include
+#include
+#include
+
+/**********************************************************
+ * Defines
+ *********************************************************/
+
+#define SL_SIMPLE_BUTTON_MODE_POLL 0U ///< BUTTON input capture using polling
+#define SL_SIMPLE_BUTTON_MODE_POLL_AND_DEBOUNCE 1U ///< BUTTON input capture using polling and debouncing
+#define SL_SIMPLE_BUTTON_MODE_INTERRUPT 2U ///< BUTTON input capture using interrupt
+
+#define SL_SIMPLE_BUTTON_DISABLED 2U ///< BUTTON state is disabled
+#define SL_SIMPLE_BUTTON_PRESSED 1U ///< BUTTON state is pressed
+#define SL_SIMPLE_BUTTON_RELEASED 0U ///< BUTTON state is released
+
+typedef uint8_t sl_button_mode_t; ///< BUTTON mode
+typedef uint8_t sl_button_state_t; ///< BUTTON state
+typedef struct sl_button sl_button_t;
+
+/// A BUTTON instance
+typedef struct sl_button
+{
+ void * context; ///< The context for this BUTTON instance
+ void (*init)(const sl_button_t * handle); ///< Member function to initialize BUTTON instance
+ void (*poll)(const sl_button_t * handle); ///< Member function to poll BUTTON
+ void (*enable)(const sl_button_t * handle); ///< Member function to enable BUTTON
+ void (*disable)(const sl_button_t * handle); ///< Member function to disable BUTTON
+ sl_button_state_t (*get_state)(const sl_button_t * handle); ///< Member function to retrieve BUTTON state
+} sl_button;
+
+const sl_button_t sl_button_btn0 = {
+ .context = NULL,
+ .init = NULL,
+ .poll = NULL,
+ .enable = NULL,
+ .disable = NULL,
+ .get_state = NULL,
+};
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+
+const sl_button_t sl_button_btn1 = {
+ .context = NULL,
+ .init = NULL,
+ .poll = NULL,
+ .enable = NULL,
+ .disable = NULL,
+ .get_state = NULL,
+};
+#define APP_LIGHT_SWITCH &sl_button_btn1
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+/**********************************************************
+ * AppTask Declaration
+ *********************************************************/
+
+class AppTask : public BaseApplication
+{
+
+public:
+ AppTask() = default;
+
+ static AppTask & GetAppTask() { return sAppTask; }
+
+ /**
+ * @brief AppTask task main loop function
+ *
+ * @param pvParameter FreeRTOS task parameter
+ */
+ static void AppTaskMain(void * pvParameter);
+
+ CHIP_ERROR StartAppTask();
+
+ /**
+ * @brief Event handler when a button is pressed
+ * Function posts an event for button processing
+ *
+ * @param buttonHandle APP_LIGHT_SWITCH or APP_FUNCTION_BUTTON
+ * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED,
+ * SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED
+ */
+ void ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction);
+
+ /**
+ * @brief Callback called by the identify-server when an identify command is received
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStart(Identify * identify);
+
+ /**
+ * @brief Callback called by the identify-server when an identify command is stopped or finished
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStop(Identify * identify);
+
+private:
+ static AppTask sAppTask;
+
+ /**
+ * @brief AppTask initialisation function
+ *
+ * @return CHIP_ERROR
+ */
+ CHIP_ERROR Init();
+
+ /**
+ * @brief PB0 Button event processing function
+ * Press and hold will trigger a factory reset timer start
+ * Press and release will restart BLEAdvertising if not commisionned
+ *
+ * @param aEvent button event being processed
+ */
+ static void ButtonHandler(AppEvent * aEvent);
+
+ /**
+ * @brief PB1 Button event processing function
+ * Function triggers a switch action sent to the CHIP task
+ *
+ * @param aEvent button event being processed
+ */
+ static void SwitchActionEventHandler(AppEvent * aEvent);
+};
diff --git a/examples/light-switch-app/silabs/SiWx917/include/CHIPProjectConfig.h b/examples/light-switch-app/silabs/SiWx917/include/CHIPProjectConfig.h
new file mode 100644
index 00000000000000..1b74c802fd4f09
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/include/CHIPProjectConfig.h
@@ -0,0 +1,124 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Example project configuration file for CHIP.
+ *
+ * This is a place to put application or project-specific overrides
+ * to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+// Use a default pairing code if one hasn't been provisioned in flash.
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+#endif
+
+// For convenience, Chip Security Test Mode can be enabled and the
+// requirement for authentication in various protocols can be disabled.
+//
+// WARNING: These options make it possible to circumvent basic Chip security functionality,
+// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+//
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ * 0x8005: example lighting app
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8004
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION
+ *
+ * The hardware version number assigned to device or product by the device vendor. This
+ * number is scoped to the device product id, and typically corresponds to a revision of the
+ * physical device, a change to its packaging, and/or a change to its marketing presentation.
+ * This value is generally *not* incremented for device software versions.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+ *
+ * A uint32_t identifying the software version running on the device.
+ */
+/* The SoftwareVersion attribute of the Basic cluster. */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 0x0001
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in Chip NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
+ *
+ * Enable recording UTC timestamps.
+ */
+#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE
+ *
+ * A size, in bytes, of the individual debug event logging buffer.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)
+
+/**
+ * @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL
+ *
+ * @brief
+ * Active retransmit interval, or time to wait before retransmission after
+ * subsequent failures in milliseconds.
+ *
+ * This is the default value, that might be adjusted by end device depending on its
+ * needs (e.g. sleeping period) using Service Discovery TXT record CRA key.
+ *
+ */
+#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32)
+
+#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
diff --git a/examples/light-switch-app/silabs/SiWx917/include/binding-handler.h b/examples/light-switch-app/silabs/SiWx917/include/binding-handler.h
new file mode 100644
index 00000000000000..aed08be25eb5bc
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/include/binding-handler.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "app-common/zap-generated/ids/Clusters.h"
+#include "app-common/zap-generated/ids/Commands.h"
+#include "lib/core/CHIPError.h"
+
+CHIP_ERROR InitBindingHandler();
+void SwitchWorkerFunction(intptr_t context);
+void BindingWorkerFunction(intptr_t context);
+
+struct BindingCommandData
+{
+ chip::EndpointId localEndpointId = 1;
+ chip::CommandId commandId;
+ chip::ClusterId clusterId;
+ bool isGroup = false;
+};
diff --git a/examples/light-switch-app/silabs/SiWx917/src/AppTask.cpp b/examples/light-switch-app/silabs/SiWx917/src/AppTask.cpp
new file mode 100644
index 00000000000000..9cba97f27dafc2
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/src/AppTask.cpp
@@ -0,0 +1,263 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include "AppTask.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "binding-handler.h"
+
+#ifdef ENABLE_WSTK_LEDS
+#include "LEDWidget.h"
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef DISPLAY_ENABLED
+#include "lcd.h"
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#endif // QR_CODE_ENABLED
+#endif // DISPLAY_ENABLED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+/**********************************************************
+ * Defines and Constants
+ *********************************************************/
+
+#define SYSTEM_STATE_LED &sl_led_led0
+
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+#define APP_LIGHT_SWITCH &sl_button_btn1
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+namespace {
+
+/**********************************************************
+ * Variable declarations
+ *********************************************************/
+
+EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+bool mCurrentButtonState = false;
+
+/**********************************************************
+ * Identify Callbacks
+ *********************************************************/
+
+namespace {
+void OnTriggerIdentifyEffectCompleted(chip::System::Layer * systemLayer, void * appState)
+{
+ ChipLogProgress(Zcl, "Trigger Identify Complete");
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StopStatusLEDTimer();
+#endif
+}
+} // namespace
+
+void OnTriggerIdentifyEffect(Identify * identify)
+{
+ ChipLogProgress(Zcl, "Trigger Identify Effect");
+ sIdentifyEffect = identify->mCurrentEffectIdentifier;
+
+ if (identify->mCurrentEffectIdentifier == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE)
+ {
+ ChipLogProgress(Zcl, "IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE - Not supported, use effect varriant %d",
+ identify->mEffectVariant);
+ sIdentifyEffect = static_cast(identify->mEffectVariant);
+ }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StartStatusLEDTimer();
+#endif
+
+ switch (sIdentifyEffect)
+ {
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY:
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(5), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(1), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+ break;
+ default:
+ ChipLogProgress(Zcl, "No identifier effect");
+ }
+}
+
+Identify gIdentify = {
+ chip::EndpointId{ 1 },
+ AppTask::GetAppTask().OnIdentifyStart,
+ AppTask::GetAppTask().OnIdentifyStop,
+ EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED,
+ OnTriggerIdentifyEffect,
+};
+
+} // namespace
+
+using namespace chip::TLV;
+using namespace ::chip::DeviceLayer;
+
+/**********************************************************
+ * AppTask Definitions
+ *********************************************************/
+
+AppTask AppTask::sAppTask;
+
+CHIP_ERROR AppTask::Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+#ifdef DISPLAY_ENABLED
+ GetLCD().Init((uint8_t *) "Light Switch");
+#endif
+
+ err = BaseApplication::Init(&gIdentify);
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("BaseApplication::Init() failed");
+ appError(err);
+ }
+
+ // Configure Bindings - TODO ERROR PROCESSING
+ err = InitBindingHandler();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("InitBindingHandler() failed");
+ appError(err);
+ }
+
+ return err;
+}
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+ return BaseApplication::StartAppTask(AppTaskMain);
+}
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+ AppEvent event;
+ QueueHandle_t sAppEventQueue = *(static_cast(pvParameter));
+
+ CHIP_ERROR err = sAppTask.Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("AppTask.Init() failed");
+ appError(err);
+ }
+
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+ sAppTask.StartStatusLEDTimer();
+#endif
+
+ SILABS_LOG("App Task started");
+ while (true)
+ {
+ BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, portMAX_DELAY);
+ while (eventReceived == pdTRUE)
+ {
+ sAppTask.DispatchEvent(&event);
+ eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+ }
+ }
+}
+
+void AppTask::OnIdentifyStart(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStart");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StartStatusLEDTimer();
+#endif
+}
+
+void AppTask::OnIdentifyStop(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStop");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StopStatusLEDTimer();
+#endif
+}
+
+void AppTask::SwitchActionEventHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type == AppEvent::kEventType_Button)
+ {
+ BindingCommandData * data = Platform::New();
+ data->clusterId = chip::app::Clusters::OnOff::Id;
+
+ if (mCurrentButtonState)
+ {
+ mCurrentButtonState = false;
+ data->commandId = chip::app::Clusters::OnOff::Commands::Off::Id;
+ }
+ else
+ {
+ data->commandId = chip::app::Clusters::OnOff::Commands::On::Id;
+ mCurrentButtonState = true;
+ }
+
+#ifdef DISPLAY_ENABLED
+ sAppTask.GetLCD().WriteDemoUI(mCurrentButtonState);
+#endif
+
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+ }
+}
+
+void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction)
+{
+ if (buttonHandle == NULL)
+ {
+ return;
+ }
+
+ AppEvent button_event = {};
+ button_event.Type = AppEvent::kEventType_Button;
+ button_event.ButtonEvent.Action = btnAction;
+
+ button_event.Handler = SwitchActionEventHandler;
+ sAppTask.PostEvent(&button_event);
+}
diff --git a/examples/light-switch-app/silabs/SiWx917/src/ZclCallbacks.cpp b/examples/light-switch-app/silabs/SiWx917/src/ZclCallbacks.cpp
new file mode 100644
index 00000000000000..52542ca88fb390
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/src/ZclCallbacks.cpp
@@ -0,0 +1,72 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * This file implements the handler for data model messages.
+ */
+
+#include "AppConfig.h"
+
+#include
+#include
+#include
+#include
+
+using namespace ::chip;
+using namespace ::chip::app::Clusters;
+
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
+ uint8_t * value)
+{
+ ClusterId clusterId = attributePath.mClusterId;
+ AttributeId attributeId = attributePath.mAttributeId;
+ ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));
+
+ if (clusterId == OnOffSwitchConfiguration::Id)
+ {
+ ChipLogProgress(Zcl, "OnOff Switch Configuration attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == Identify::Id)
+ {
+ ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+ }
+}
+
+/** @brief OnOff Cluster Init
+ *
+ * This function is called when a specific cluster is initialized. It gives the
+ * application an opportunity to take care of cluster initialization procedures.
+ * It is called exactly once for each endpoint where cluster is present.
+ *
+ * @param endpoint Ver.: always
+ *
+ * TODO Issue #3841
+ * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster
+ * attributes to the default value.
+ * The logic here expects something similar to the deprecated Plugins callback
+ * emberAfPluginOnOffClusterServerPostInitCallback.
+ *
+ */
+void emberAfOnOffClusterInitCallback(EndpointId endpoint)
+{
+ // TODO: implement any additional Cluster Server init actions
+}
diff --git a/examples/light-switch-app/silabs/SiWx917/src/binding-handler.cpp b/examples/light-switch-app/silabs/SiWx917/src/binding-handler.cpp
new file mode 100644
index 00000000000000..90a2463a088e33
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/src/binding-handler.cpp
@@ -0,0 +1,431 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "binding-handler.h"
+
+#include "AppConfig.h"
+#include "app/CommandSender.h"
+#include "app/clusters/bindings/BindingManager.h"
+#include "app/server/Server.h"
+#include "controller/InvokeInteraction.h"
+#include "platform/CHIPDeviceLayer.h"
+#include
+#include
+
+#if defined(ENABLE_CHIP_SHELL)
+#include "lib/shell/Engine.h"
+#include "lib/shell/commands/Help.h"
+#endif // ENABLE_CHIP_SHELL
+
+using namespace chip;
+using namespace chip::app;
+
+#if defined(ENABLE_CHIP_SHELL)
+using Shell::Engine;
+using Shell::shell_command_t;
+using Shell::streamer_get;
+using Shell::streamer_printf;
+
+Engine sShellSwitchSubCommands;
+Engine sShellSwitchOnOffSubCommands;
+
+Engine sShellSwitchGroupsSubCommands;
+Engine sShellSwitchGroupsOnOffSubCommands;
+
+Engine sShellSwitchBindingSubCommands;
+#endif // defined(ENABLE_CHIP_SHELL)
+
+namespace {
+
+void ProcessOnOffUnicastBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding,
+ Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle)
+{
+ auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
+ ChipLogProgress(NotSpecified, "OnOff command succeeds");
+ };
+
+ auto onFailure = [](CHIP_ERROR error) {
+ ChipLogError(NotSpecified, "OnOff command failed: %" CHIP_ERROR_FORMAT, error.Format());
+ };
+
+ switch (commandId)
+ {
+ case Clusters::OnOff::Commands::Toggle::Id:
+ Clusters::OnOff::Commands::Toggle::Type toggleCommand;
+ Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, toggleCommand, onSuccess, onFailure);
+ break;
+
+ case Clusters::OnOff::Commands::On::Id:
+ Clusters::OnOff::Commands::On::Type onCommand;
+ Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, onCommand, onSuccess, onFailure);
+ break;
+
+ case Clusters::OnOff::Commands::Off::Id:
+ Clusters::OnOff::Commands::Off::Type offCommand;
+ Controller::InvokeCommandRequest(exchangeMgr, sessionHandle, binding.remote, offCommand, onSuccess, onFailure);
+ break;
+ }
+}
+
+void ProcessOnOffGroupBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding)
+{
+ Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+
+ switch (commandId)
+ {
+ case Clusters::OnOff::Commands::Toggle::Id:
+ Clusters::OnOff::Commands::Toggle::Type toggleCommand;
+ Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, toggleCommand);
+ break;
+
+ case Clusters::OnOff::Commands::On::Id:
+ Clusters::OnOff::Commands::On::Type onCommand;
+ Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, onCommand);
+
+ break;
+
+ case Clusters::OnOff::Commands::Off::Id:
+ Clusters::OnOff::Commands::Off::Type offCommand;
+ Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, offCommand);
+ break;
+ }
+}
+
+void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, OperationalDeviceProxy * peer_device, void * context)
+{
+ VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "OnDeviceConnectedFn: context is null"));
+ BindingCommandData * data = static_cast(context);
+
+ if (binding.type == EMBER_MULTICAST_BINDING && data->isGroup)
+ {
+ switch (data->clusterId)
+ {
+ case Clusters::OnOff::Id:
+ ProcessOnOffGroupBindingCommand(data->commandId, binding);
+ break;
+ }
+ }
+ else if (binding.type == EMBER_UNICAST_BINDING && !data->isGroup)
+ {
+ switch (data->clusterId)
+ {
+ case Clusters::OnOff::Id:
+ VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+ ProcessOnOffUnicastBindingCommand(data->commandId, binding, peer_device->GetExchangeManager(),
+ peer_device->GetSecureSession().Value());
+ break;
+ }
+ }
+}
+
+void LightSwitchContextReleaseHandler(void * context)
+{
+ VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "LightSwitchContextReleaseHandler: context is null"));
+
+ Platform::Delete(static_cast(context));
+}
+
+#ifdef ENABLE_CHIP_SHELL
+
+/********************************************************
+ * Switch shell functions
+ *********************************************************/
+
+CHIP_ERROR SwitchHelpHandler(int argc, char ** argv)
+{
+ sShellSwitchSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR SwitchCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return SwitchHelpHandler(argc, argv);
+ }
+
+ return sShellSwitchSubCommands.ExecCommand(argc, argv);
+}
+
+/********************************************************
+ * OnOff switch shell functions
+ *********************************************************/
+
+CHIP_ERROR OnOffHelpHandler(int argc, char ** argv)
+{
+ sShellSwitchOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnOffSwitchCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return OnOffHelpHandler(argc, argv);
+ }
+
+ return sShellSwitchOnOffSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR OnSwitchCommandHandler(int argc, char ** argv)
+{
+ BindingCommandData * data = Platform::New();
+ data->commandId = Clusters::OnOff::Commands::On::Id;
+ data->clusterId = Clusters::OnOff::Id;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OffSwitchCommandHandler(int argc, char ** argv)
+{
+ BindingCommandData * data = Platform::New();
+ data->commandId = Clusters::OnOff::Commands::Off::Id;
+ data->clusterId = Clusters::OnOff::Id;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ToggleSwitchCommandHandler(int argc, char ** argv)
+{
+ BindingCommandData * data = Platform::New();
+ data->commandId = Clusters::OnOff::Commands::Toggle::Id;
+ data->clusterId = Clusters::OnOff::Id;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * bind switch shell functions
+ *********************************************************/
+
+CHIP_ERROR BindingHelpHandler(int argc, char ** argv)
+{
+ sShellSwitchBindingSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BindingSwitchCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return BindingHelpHandler(argc, argv);
+ }
+
+ return sShellSwitchBindingSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR BindingGroupBindCommandHandler(int argc, char ** argv)
+{
+ VerifyOrReturnError(argc == 2, CHIP_ERROR_INVALID_ARGUMENT);
+
+ EmberBindingTableEntry * entry = Platform::New();
+ entry->type = EMBER_MULTICAST_BINDING;
+ entry->fabricIndex = atoi(argv[0]);
+ entry->groupId = atoi(argv[1]);
+ entry->local = 1; // Hardcoded to endpoint 1 for now
+ entry->clusterId.SetValue(6); // Hardcoded to OnOff cluster for now
+
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingWorkerFunction, reinterpret_cast(entry));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BindingUnicastBindCommandHandler(int argc, char ** argv)
+{
+ VerifyOrReturnError(argc == 3, CHIP_ERROR_INVALID_ARGUMENT);
+
+ EmberBindingTableEntry * entry = Platform::New();
+ entry->type = EMBER_UNICAST_BINDING;
+ entry->fabricIndex = atoi(argv[0]);
+ entry->nodeId = atoi(argv[1]);
+ entry->local = 1; // Hardcoded to endpoint 1 for now
+ entry->remote = atoi(argv[2]);
+ entry->clusterId.SetValue(6); // Hardcode to OnOff cluster for now
+
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingWorkerFunction, reinterpret_cast(entry));
+ return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * Groups switch shell functions
+ *********************************************************/
+
+CHIP_ERROR GroupsHelpHandler(int argc, char ** argv)
+{
+ sShellSwitchGroupsSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsSwitchCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return GroupsHelpHandler(argc, argv);
+ }
+
+ return sShellSwitchGroupsSubCommands.ExecCommand(argc, argv);
+}
+
+/********************************************************
+ * Groups OnOff switch shell functions
+ *********************************************************/
+
+CHIP_ERROR GroupsOnOffHelpHandler(int argc, char ** argv)
+{
+ sShellSwitchGroupsOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return GroupsOnOffHelpHandler(argc, argv);
+ }
+
+ return sShellSwitchGroupsOnOffSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR GroupOnSwitchCommandHandler(int argc, char ** argv)
+{
+ BindingCommandData * data = Platform::New();
+ data->commandId = Clusters::OnOff::Commands::On::Id;
+ data->clusterId = Clusters::OnOff::Id;
+ data->isGroup = true;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupOffSwitchCommandHandler(int argc, char ** argv)
+{
+ BindingCommandData * data = Platform::New();
+ data->commandId = Clusters::OnOff::Commands::Off::Id;
+ data->clusterId = Clusters::OnOff::Id;
+ data->isGroup = true;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupToggleSwitchCommandHandler(int argc, char ** argv)
+{
+ BindingCommandData * data = Platform::New();
+ data->commandId = Clusters::OnOff::Commands::Toggle::Id;
+ data->clusterId = Clusters::OnOff::Id;
+ data->isGroup = true;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+/**
+ * @brief configures switch matter shell
+ *
+ */
+static void RegisterSwitchCommands()
+{
+ static const shell_command_t sSwitchSubCommands[] = {
+ { &SwitchHelpHandler, "help", "Usage: switch " },
+ { &OnOffSwitchCommandHandler, "onoff", " Usage: switch onoff " },
+ { &GroupsSwitchCommandHandler, "groups", "Usage: switch groups " },
+ { &BindingSwitchCommandHandler, "binding", "Usage: switch binding " }
+ };
+
+ static const shell_command_t sSwitchOnOffSubCommands[] = {
+ { &OnOffHelpHandler, "help", "Usage : switch ononff " },
+ { &OnSwitchCommandHandler, "on", "Sends on command to bound lighting app" },
+ { &OffSwitchCommandHandler, "off", "Sends off command to bound lighting app" },
+ { &ToggleSwitchCommandHandler, "toggle", "Sends toggle command to bound lighting app" }
+ };
+
+ static const shell_command_t sSwitchGroupsSubCommands[] = { { &GroupsHelpHandler, "help", "Usage: switch groups " },
+ { &GroupsOnOffSwitchCommandHandler, "onoff",
+ "Usage: switch groups onoff " } };
+
+ static const shell_command_t sSwitchGroupsOnOffSubCommands[] = {
+ { &GroupsOnOffHelpHandler, "help", "Usage: switch groups onoff " },
+ { &GroupOnSwitchCommandHandler, "on", "Sends on command to bound group" },
+ { &GroupOffSwitchCommandHandler, "off", "Sends off command to bound group" },
+ { &GroupToggleSwitchCommandHandler, "toggle", "Sends toggle command to group" }
+ };
+
+ static const shell_command_t sSwitchBindingSubCommands[] = {
+ { &BindingHelpHandler, "help", "Usage: switch binding " },
+ { &BindingGroupBindCommandHandler, "group", "Usage: switch binding group " },
+ { &BindingUnicastBindCommandHandler, "unicast", "Usage: switch binding group " }
+ };
+
+ static const shell_command_t sSwitchCommand = { &SwitchCommandHandler, "switch",
+ "Light-switch commands. Usage: switch " };
+
+ sShellSwitchGroupsOnOffSubCommands.RegisterCommands(sSwitchGroupsOnOffSubCommands, ArraySize(sSwitchGroupsOnOffSubCommands));
+ sShellSwitchOnOffSubCommands.RegisterCommands(sSwitchOnOffSubCommands, ArraySize(sSwitchOnOffSubCommands));
+ sShellSwitchGroupsSubCommands.RegisterCommands(sSwitchGroupsSubCommands, ArraySize(sSwitchGroupsSubCommands));
+ sShellSwitchBindingSubCommands.RegisterCommands(sSwitchBindingSubCommands, ArraySize(sSwitchBindingSubCommands));
+ sShellSwitchSubCommands.RegisterCommands(sSwitchSubCommands, ArraySize(sSwitchSubCommands));
+
+ Engine::Root().RegisterCommands(&sSwitchCommand, 1);
+}
+#endif // ENABLE_CHIP_SHELL
+
+void InitBindingHandlerInternal(intptr_t arg)
+{
+ auto & server = chip::Server::GetInstance();
+ chip::BindingManager::GetInstance().Init(
+ { &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() });
+ chip::BindingManager::GetInstance().RegisterBoundDeviceChangedHandler(LightSwitchChangedHandler);
+ chip::BindingManager::GetInstance().RegisterBoundDeviceContextReleaseHandler(LightSwitchContextReleaseHandler);
+}
+
+} // namespace
+
+/********************************************************
+ * Switch functions
+ *********************************************************/
+
+void SwitchWorkerFunction(intptr_t context)
+{
+ VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "SwitchWorkerFunction - Invalid work data"));
+
+ BindingCommandData * data = reinterpret_cast(context);
+ BindingManager::GetInstance().NotifyBoundClusterChanged(data->localEndpointId, data->clusterId, static_cast(data));
+}
+
+void BindingWorkerFunction(intptr_t context)
+{
+ VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "BindingWorkerFunction - Invalid work data"));
+
+ EmberBindingTableEntry * entry = reinterpret_cast(context);
+ AddBindingEntry(*entry);
+
+ Platform::Delete(entry);
+}
+
+CHIP_ERROR InitBindingHandler()
+{
+ // The initialization of binding manager will try establishing connection with unicast peers
+ // so it requires the Server instance to be correctly initialized. Post the init function to
+ // the event queue so that everything is ready when initialization is conducted.
+ chip::DeviceLayer::PlatformMgr().ScheduleWork(InitBindingHandlerInternal);
+#if defined(ENABLE_CHIP_SHELL)
+ RegisterSwitchCommands();
+#endif
+ return CHIP_NO_ERROR;
+}
diff --git a/examples/light-switch-app/silabs/SiWx917/src/main.cpp b/examples/light-switch-app/silabs/SiWx917/src/main.cpp
new file mode 100644
index 00000000000000..c67851a2ca78cc
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/src/main.cpp
@@ -0,0 +1,87 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#include "AppConfig.h"
+#include "init_ccpPlatform.h"
+#include
+#include
+#include
+#include
+#ifdef SI917_ATTESTATION_CREDENTIALS
+#include
+#else
+#include
+#endif
+
+#define BLE_DEV_NAME "SiLabs-Light-Switch"
+
+extern "C" void sl_button_on_change();
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::Credentials;
+
+#define UNUSED_PARAMETER(a) (a = a)
+
+volatile int apperror_cnt;
+static chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+
+// ================================================================================
+// Main Code
+// ================================================================================
+int main(void)
+{
+ init_ccpPlatform();
+ if (SI917MatterConfig::InitMatter(BLE_DEV_NAME) != CHIP_NO_ERROR)
+ {
+ appError(CHIP_ERROR_INTERNAL);
+ }
+
+ gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage());
+ chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ // Initialize device attestation config
+#ifdef SI917_ATTESTATION_CREDENTIALS
+ SetDeviceAttestationCredentialsProvider(SIWx917::GetSIWx917DacProvider());
+#else
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ SILABS_LOG("Starting App Task");
+ if (AppTask::GetAppTask().StartAppTask() != CHIP_NO_ERROR)
+ appError(CHIP_ERROR_INTERNAL);
+
+ SILABS_LOG("Starting FreeRTOS scheduler");
+ vTaskStartScheduler();
+
+ // Should never get here.
+ chip::Platform::MemoryShutdown();
+ SILABS_LOG("vTaskStartScheduler() failed");
+ appError(CHIP_ERROR_INTERNAL);
+}
+
+void sl_button_on_change()
+{
+ AppTask::GetAppTask().ButtonEventHandler(APP_LIGHT_SWITCH, SL_SIMPLE_BUTTON_PRESSED);
+}
diff --git a/examples/light-switch-app/silabs/SiWx917/third_party/connectedhomeip b/examples/light-switch-app/silabs/SiWx917/third_party/connectedhomeip
new file mode 120000
index 00000000000000..59307833b4fee9
--- /dev/null
+++ b/examples/light-switch-app/silabs/SiWx917/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../../..
\ No newline at end of file
diff --git a/examples/lock-app/silabs/SiWx917/.gn b/examples/lock-app/silabs/SiWx917/.gn
new file mode 100644
index 00000000000000..4c078f6acefdcc
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/.gn
@@ -0,0 +1,29 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_openthread_ftd = true
+
+ import("//args.gni")
+}
diff --git a/examples/lock-app/silabs/SiWx917/BUILD.gn b/examples/lock-app/silabs/SiWx917/BUILD.gn
new file mode 100644
index 00000000000000..dd196fa421303b
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/BUILD.gn
@@ -0,0 +1,390 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${build_root}/config/defaults.gni")
+import("${efr32_sdk_build_root}/SiWx917_sdk.gni")
+import("${efr32_sdk_build_root}/efr32_executable.gni")
+
+import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni")
+import("${chip_root}/src/platform/device.gni")
+
+if (chip_enable_pw_rpc) {
+ import("//build_overrides/pigweed.gni")
+ import("$dir_pw_build/target_types.gni")
+}
+
+assert(current_os == "freertos")
+
+efr32_project_dir = "${chip_root}/examples/lock-app/silabs/SiWx917"
+examples_plat_dir = "${chip_root}/examples/platform/silabs/SiWx917"
+examples_common_plat_dir = "${chip_root}/examples/platform/silabs"
+
+declare_args() {
+ # Dump memory usage at link time.
+ chip_print_memory_usage = false
+
+ # Monitor & log memory usage at runtime.
+ enable_heap_monitoring = false
+
+ # Enable Sleepy end device
+ enable_sleepy_device = false
+
+ # OTA timeout in seconds
+ OTA_periodic_query_timeout = 86400
+
+ # Wifi related stuff - they are overridden by gn -args="use_wf200=true"
+ use_wf200 = false
+ use_rs911x = false
+ use_rs911x_sockets = false
+ sl_wfx_config_softap = false
+ sl_wfx_config_scan = true
+
+ # Disable LCD on supported devices
+ disable_lcd = true
+
+ # Argument to Disable IPv4 for wifi(rs911)
+ chip_enable_wifi_ipv4 = false
+
+ # Argument to force enable WPA3 security
+ rs91x_wpa3_only = false
+
+ #default WiFi SSID
+ chip_default_wifi_ssid = ""
+
+ #default Wifi Password
+ chip_default_wifi_psk = ""
+}
+
+declare_args() {
+ # Enables LCD Qr Code on supported devices
+ show_qr_code = !disable_lcd
+}
+
+# qr code cannot be true if lcd is disabled
+assert(!(disable_lcd && show_qr_code))
+
+# Sanity check
+assert(!(chip_enable_wifi && chip_enable_openthread))
+assert(!(use_rs911x && chip_enable_openthread))
+assert(!(use_wf200 && chip_enable_openthread))
+if (chip_enable_wifi) {
+ assert(use_rs911x || use_wf200)
+ enable_openthread_cli = false
+ import("${chip_root}/src/platform/silabs/SiWx917/wifi_args.gni")
+}
+
+# ThunderBoards, Explorer Kit and MGM240L do not support LCD (No LCD)
+if (silabs_board == "BRD4166A" || silabs_board == "BRD2601B" ||
+ silabs_board == "BRD2703A" || silabs_board == "BRD4319A") {
+ show_qr_code = false
+ disable_lcd = true
+}
+
+defines = []
+
+# WiFi settings
+if (chip_enable_wifi) {
+ if (chip_default_wifi_ssid != "") {
+ defines += [
+ "CHIP_ONNETWORK_PAIRING=1",
+ "CHIP_WIFI_SSID=\"${chip_default_wifi_ssid}\"",
+ ]
+ }
+ if (chip_default_wifi_psk != "") {
+ assert(chip_default_wifi_ssid != "",
+ "ssid can't be null if psk is provided")
+ defines += [ "CHIP_WIFI_PSK=\"${chip_default_wifi_psk}\"" ]
+ }
+ wifi_sdk_dir = "${chip_root}/src/platform/silabs/SiWx917/wifi"
+ efr32_lwip_defs = [ "LWIP_NETIF_API=1" ]
+ if (lwip_ipv4) {
+ efr32_lwip_defs += [
+ "LWIP_IPV4=1",
+
+ # adds following options to provide
+ # them to .cpp source files
+ # flags ported from lwipopts file
+ # TODO: move lwipopts to one location
+ "LWIP_ARP=1",
+ "LWIP_ICMP=1",
+ "LWIP_IGMP=1",
+ "LWIP_DHCP=1",
+ "LWIP_DNS=0",
+ ]
+ } else {
+ efr32_lwip_defs += [ "LWIP_IPV4=0" ]
+ }
+ if (lwip_ipv6) {
+ efr32_lwip_defs += [ "LWIP_IPV6=1" ]
+ } else {
+ efr32_lwip_defs += [ "LWIP_IPV6=0" ]
+ }
+
+ wiseconnect_sdk_root = "${chip_root}/third_party/silabs/wisemcu-wifi-bt-sdk"
+ import("${examples_plat_dir}/SiWx917/rs911x.gni")
+}
+
+efr32_sdk("sdk") {
+ sources = [
+ "${efr32_project_dir}/include/CHIPProjectConfig.h",
+ "${examples_plat_dir}/FreeRTOSConfig.h",
+ ]
+
+ include_dirs = [
+ "${chip_root}/src/platform/silabs/SiWx917",
+ "${efr32_project_dir}/include",
+ "${examples_plat_dir}",
+ "${chip_root}/src/lib",
+ "${examples_common_plat_dir}",
+ ]
+
+ defines += [
+ "BOARD_ID=${silabs_board}",
+ "OTA_PERIODIC_TIMEOUT=${OTA_periodic_query_timeout}",
+ ]
+
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "HAL_VCOM_ENABLE=1",
+ "PW_RPC_ENABLED",
+ ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ if (use_rs911x) {
+ defines += rs911x_defs
+ include_dirs += rs911x_plat_incs
+ } else if (use_wf200) {
+ defines += wf200_defs
+ include_dirs += wf200_plat_incs
+ }
+
+ if (use_rs911x_sockets) {
+ include_dirs += [ "${examples_plat_dir}/wifi/rsi-sockets" ]
+ defines += rs911x_sock_defs
+ } else {
+ # Using LWIP instead of the native TCP/IP stack
+ defines += efr32_lwip_defs
+ }
+ if (sl_wfx_config_softap) {
+ defines += [ "SL_WFX_CONFIG_SOFTAP" ]
+ }
+ if (sl_wfx_config_scan) {
+ defines += [ "SL_WFX_CONFIG_SCAN" ]
+ }
+ }
+}
+
+efr32_executable("lock_app") {
+ output_name = "chip-efr32-lock-example.out"
+ public_configs = [ "${efr32_sdk_build_root}:silabs_config" ]
+ include_dirs = [ "include" ]
+ defines = []
+
+ sources = [
+ "${examples_common_plat_dir}/heap_4_silabs.c",
+ "${examples_plat_dir}/BaseApplication.cpp",
+ "${examples_plat_dir}/init_ccpPlatform.cpp",
+ "${examples_plat_dir}/matter_config.cpp",
+ "${examples_plat_dir}/siwx917_utils.cpp",
+ "src/AppTask.cpp",
+ "src/LockManager.cpp",
+ "src/ZclCallbacks.cpp",
+ "src/main.cpp",
+ ]
+
+ if (use_wstk_leds) {
+ #sources += [ "${examples_plat_dir}/LEDWidget.cpp" ]
+ }
+
+ if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli ||
+ use_wf200 || use_rs911x) {
+ #sources += [ "${examples_plat_dir}/uart.cpp" ]
+ }
+
+ if (chip_build_libshell) {
+ sources += [ "src/EventHandlerLibShell.cpp" ]
+ }
+
+ deps = [
+ ":sdk",
+ "${chip_root}/examples/lock-app/lock-common",
+ "${chip_root}/examples/providers:device_info_provider",
+ "${chip_root}/src/lib",
+ "${chip_root}/src/setup_payload",
+ "${chip_root}/third_party/openthread/platforms:libopenthread-platform",
+ "${chip_root}/third_party/openthread/platforms:libopenthread-platform-utils",
+ "${examples_plat_dir}:efr-matter-shell",
+ ]
+
+ # OpenThread Settings
+ if (chip_enable_openthread) {
+ deps += [
+ "${chip_root}/third_party/openthread:openthread",
+ "${chip_root}/third_party/openthread:openthread-platform",
+ "${examples_plat_dir}:efr-matter-shell",
+ ]
+ }
+
+ if (chip_enable_ota_requestor) {
+ defines += [ "EFR32_OTA_ENABLED" ]
+ #sources += [ "${examples_plat_dir}/OTAConfig.cpp" ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ if (use_rs911x) {
+ sources += rs911x_src_plat
+
+ # All the stuff from wiseconnect
+ sources += rs911x_src_sapi
+
+ # Apparently - the rsi library needs this (though we may not use use it)
+ sources += rs911x_src_sock
+ include_dirs += rs911x_inc_plat
+
+ if (use_rs911x_sockets) {
+ #
+ # Using native sockets inside RS911x
+ #
+ include_dirs += rs911x_sock_inc
+ } else {
+ #
+ # We use LWIP - not built-in sockets
+ #
+ sources += rs911x_src_lwip
+ }
+ } else if (use_wf200) {
+ sources += wf200_plat_src
+ include_dirs += wf200_plat_incs
+ }
+
+ if (chip_enable_wifi_ipv4) {
+ defines += [ "CHIP_DEVICE_CONFIG_ENABLE_IPV4" ]
+ }
+
+ if (rs91x_wpa3_only) {
+ # TODO: Change this macro once WF200 support is provided
+ defines += [ "WIFI_ENABLE_SECURITY_WPA3=1" ]
+ }
+ }
+
+ if (!disable_lcd) {
+ sources += [
+ "${examples_plat_dir}/display/demo-ui.c",
+ "${examples_plat_dir}/display/lcd.cpp",
+ ]
+ include_dirs += [ "${examples_plat_dir}/display" ]
+ defines += [
+ "DISPLAY_ENABLED",
+ "IS_DEMO_LOCK=1",
+ ]
+ if (show_qr_code) {
+ defines += [ "QR_CODE_ENABLED" ]
+ deps += [ "${chip_root}/examples/common/QRCode" ]
+ }
+ }
+
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "PW_RPC_ENABLED",
+ "PW_RPC_ATTRIBUTE_SERVICE=1",
+ "PW_RPC_BUTTON_SERVICE=1",
+ "PW_RPC_DESCRIPTOR_SERVICE=1",
+ "PW_RPC_DEVICE_SERVICE=1",
+ "PW_RPC_LOCKING_SERVICE=1",
+ "PW_RPC_OTCLI_SERVICE=1",
+ "PW_RPC_THREAD_SERVICE=1",
+ ]
+
+ sources += [
+ "${chip_root}/examples/common/pigweed/RpcService.cpp",
+ "${chip_root}/examples/common/pigweed/efr32/PigweedLoggerMutex.cpp",
+ "${examples_common_plat_dir}/PigweedLogger.cpp",
+ "${examples_common_plat_dir}/Rpc.cpp",
+ ]
+
+ deps += [
+ "$dir_pw_hdlc:rpc_channel_output",
+ "$dir_pw_stream:sys_io_stream",
+ "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc",
+ "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:locking_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:ot_cli_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:thread_service.nanopb_rpc",
+ "${examples_plat_dir}/pw_sys_io:pw_sys_io_efr32",
+ ]
+
+ deps += pw_build_LINK_DEPS
+
+ include_dirs += [
+ "${chip_root}/examples/common",
+ "${chip_root}/examples/common/pigweed/efr32",
+ ]
+ }
+
+ if (enable_heap_monitoring) {
+ sources += [ "${examples_common_plat_dir}/MemMonitoring.cpp" ]
+ defines += [ "HEAP_MONITORING" ]
+ }
+
+ ldscript = "${examples_plat_dir}/ldscripts/${silabs_family}.ld"
+
+ inputs = [ ldscript ]
+
+ ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ]
+
+ if (chip_print_memory_usage) {
+ ldflags += [
+ "-Wl,--print-memory-usage",
+ "-fstack-usage",
+ ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ ldflags += [
+ "-Wl,--defsym",
+ "-Wl,SILABS_WIFI=1",
+ ]
+ }
+
+ # Attestation Credentials
+ if (chip_build_platform_attestation_credentials_provider) {
+ deps += [ "${examples_plat_dir}:efr32-attestation-credentials" ]
+ }
+
+ # Factory Data Provider
+ if (use_efr32_factory_data_provider) {
+ deps += [ "${examples_plat_dir}:efr32-factory-data-provider" ]
+ }
+
+ output_dir = root_out_dir
+}
+group("efr32") {
+ deps = [ ":lock_app" ]
+}
+
+group("default") {
+ deps = [ ":efr32" ]
+}
diff --git a/examples/lock-app/silabs/SiWx917/README.md b/examples/lock-app/silabs/SiWx917/README.md
new file mode 100644
index 00000000000000..a681df76cc6d45
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/README.md
@@ -0,0 +1,457 @@
+# Matter EFR32 Lock Example
+
+An example showing the use of CHIP on the Silicon Labs EFR32 MG12 and MG24.
+
+
+
+- [Matter EFR32 Lock Example](#matter-efr32-lock-example)
+ - [Introduction](#introduction)
+ - [Building](#building)
+ - [Flashing the Application](#flashing-the-application)
+ - [Viewing Logging Output](#viewing-logging-output)
+ - [Running the Complete Example](#running-the-complete-example)
+ - [Notes](#notes)
+ - [Memory settings](#memory-settings)
+ - [OTA Software Update](#ota-software-update)
+ - [Building options](#building-options)
+ - [Disabling logging](#disabling-logging)
+ - [Debug build / release build](#debug-build--release-build)
+ - [Disabling LCD](#disabling-lcd)
+ - [KVS maximum entry count](#kvs-maximum-entry-count)
+
+
+
+> **NOTE:** Silicon Laboratories now maintains a public matter GitHub repo with
+> frequent releases thoroughly tested and validated. Developers looking to
+> develop matter products with silabs hardware are encouraged to use our latest
+> release with added tools and documentation.
+> [Silabs Matter Github](https://github.com/SiliconLabs/matter/releases)
+
+
+
+## Introduction
+
+The EFR32 lock example provides a baseline demonstration of a door lock control
+device, built using Matter and the Silicon Labs gecko SDK. It can be controlled
+by a Chip controller over an Openthread or Wifi network..
+
+The EFR32 device can be commissioned over Bluetooth Low Energy where the device
+and the Chip controller will exchange security information with the Rendez-vous
+procedure. If using Thread, Thread Network credentials are then provided to the
+EFR32 device which will then join the Thread network.
+
+If the LCD is enabled, the LCD on the Silabs WSTK shows a QR Code containing the
+needed commissioning information for the BLE connection and starting the
+Rendez-vous procedure.
+
+The lighting example is intended to serve both as a means to explore the
+workings of Matter as well as a template for creating real products based on the
+Silicon Labs platform.
+
+
+
+## Building
+
+- Download the
+ [Simplicity Commander](https://www.silabs.com/mcu/programming-options)
+ command line tool, and ensure that `commander` is your shell search path.
+ (For Mac OS X, `commander` is located inside
+ `Commander.app/Contents/MacOS/`.)
+
+- Download and install a suitable ARM gcc tool chain:
+ [GNU Arm Embedded Toolchain 9-2019-q4-major](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads)
+
+- Install some additional tools(likely already present for CHIP developers):
+
+Linux
+
+ sudo apt-get install git ninja-build
+
+Mac OS X
+
+ brew install ninja
+
+- Supported hardware:
+
+ - > For the latest supported hardware please refer to the
+ > [Hardware Requirements](https://github.com/SiliconLabs/matter/blob/latest/docs/silabs/general/HARDWARE_REQUIREMENTS.md)
+ > in the Silicon Labs Matter Github Repo
+
+ MG12 boards:
+
+ - BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+ 868MHz@19dBm
+ - BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+ - BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+ 915MHz@19dBm
+ - BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+ MG21 boards: Currently not supported due to RAM limitation.
+
+ - BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG24 boards :
+
+ - BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+ - BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG12 boards:
+
+ - BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+ 868MHz@19dBm
+ - BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+ - BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+ 915MHz@19dBm
+ - BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+ MG21 boards: Currently not supported due to RAM limitation.
+
+ - BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG24 boards :
+
+ - BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+ 868MHz@19dBm
+ - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+ - BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+* Build the example application:
+
+ ```
+ cd ~/connectedhomeip
+ ./scripts/examples/gn_efr32_example.sh ./examples/lock-app/efr32/ ./out/lock_app BRD4161A
+ ```
+
+- To delete generated executable, libraries and object files use:
+
+ ```
+ $ cd ~/connectedhomeip
+ $ rm -rf ./out/
+ ```
+
+ OR use GN/Ninja directly
+
+ ```
+ $ cd ~/connectedhomeip/examples/lock-app/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug --args="efr32_sdk_root=\"${EFR32_SDK_ROOT}\" silabs_board=\"${EFR32_BOARD}\""
+ $ ninja -C out/debug
+ ```
+
+- To delete generated executable, libraries and object files use:
+
+ ```
+ $ cd ~/connectedhomeip/examples/lock-app/efr32
+ $ rm -rf out/
+ ```
+
+* Build the example as Sleepy End Device (SED)
+
+ ```
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32/ ./out/lighting-app_SED BRD4161A --sed
+ ```
+
+ or use gn as previously mentioned but adding the following arguments:
+
+ ```
+ $ gn gen out/debug '--args=silabs_board="BRD4161A" enable_sleepy_device=true chip_openthread_ftd=false'
+ ```
+
+* Build the example with pigweed RCP
+
+ ```
+ $ ./scripts/examples/gn_efr32_example.sh examples/lock-app/efr32/ out/lock_app_rpc BRD4161A 'import("//with_pw_rpc.gni")'
+ ```
+
+ or use GN/Ninja Directly
+
+ ```
+ $ cd ~/connectedhomeip/examples/lock-app/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug --args='import("//with_pw_rpc.gni")'
+ $ ninja -C out/debug
+ ```
+
+ [Running Pigweed RPC console](#running-pigweed-rpc-console)
+
+For more build options, help is provided when running the build script without
+arguments
+
+ ```
+ ./scripts/examples/gn_efr32_example.sh
+ ```
+
+
+
+## Flashing the Application
+
+- On the command line:
+
+ ```
+ $ cd ~/connectedhomeip/examples/lock-app/efr32
+ $ python3 out/debug/chip-efr32-lock-example.flash.py
+ ```
+
+- Or with the Ozone debugger, just load the .out file.
+
+
+
+## Viewing Logging Output
+
+The example application is built to use the SEGGER Real Time Transfer (RTT)
+facility for log output. RTT is a feature built-in to the J-Link Interface MCU
+on the WSTK development board. It allows bi-directional communication with an
+embedded application without the need for a dedicated UART.
+
+Using the RTT facility requires downloading and installing the _SEGGER J-Link
+Software and Documentation Pack_
+([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)).
+
+Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too
+after flashing the .out file.
+
+- Download the J-Link installer by navigating to the appropriate URL and
+ agreeing to the license agreement.
+
+- [JLink_Linux_x86_64.deb](https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.deb)
+- [JLink_MacOSX.pkg](https://www.segger.com/downloads/jlink/JLink_MacOSX.pkg)
+
+* Install the J-Link software
+
+ ```
+ $ cd ~/Downloads
+ $ sudo dpkg -i JLink_Linux_V*_x86_64.deb
+ ```
+
+* In Linux, grant the logged in user the ability to talk to the development
+ hardware via the linux tty device (/dev/ttyACMx) by adding them to the
+ dialout group.
+
+ ```
+ $ sudo usermod -a -G dialout ${USER}
+ ```
+
+Once the above is complete, log output can be viewed using the JLinkExe tool in
+combination with JLinkRTTClient as follows:
+
+- Run the JLinkExe tool with arguments to autoconnect to the WSTK board:
+
+ For MG12 use:
+
+ ```
+ $ JLinkExe -device EFR32MG12PXXXF1024 -if JTAG -speed 4000 -autoconnect 1
+ ```
+
+ For MG21 use:
+
+ ```
+ $ JLinkExe -device EFR32MG21AXXXF1024 -if SWD -speed 4000 -autoconnect 1
+ ```
+
+- In a second terminal, run the JLinkRTTClient to view logs:
+
+ ```
+ $ JLinkRTTClient
+ ```
+
+
+
+## Running the Complete Example
+
+- It is assumed here that you already have an OpenThread border router
+ configured and running. If not see the following guide
+ [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md)
+ for more information on how to setup a border router on a raspberryPi.
+
+ Take note that the RCP code is available directly through
+ [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5)
+ under File->New->Project Wizard->Examples->Thread : ot-rcp
+
+- User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR
+ Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over
+ BLE
+
+ * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2,
+ a URL can be found in the RTT logs.
+
+ [SVR] Copy/paste the below URL in a browser to see the QR Code:
+ [SVR] https://project-chip.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0
+
+ **LED 0** shows the overall state of the device and its connectivity. The
+ following states are possible:
+
+ - _Short Flash On (50 ms on/950 ms off)_ ; The device is in the
+ unprovisioned (unpaired) state and is waiting for a commissioning
+ application to connect.
+
+ - _Rapid Even Flashing_ ; (100 ms on/100 ms off)_ — The device is in the
+ unprovisioned state and a commissioning application is connected through
+ Bluetooth LE.
+
+ - _Short Flash Off_ ; (950ms on/50ms off)_ — The device is fully
+ provisioned, but does not yet have full Thread network or service
+ connectivity.
+
+ - _Solid On_ ; The device is fully provisioned and has full Thread
+ network and service connectivity.
+
+ **LED 1** Simulates the Lock The following states are possible:
+
+ - _Solid On_ ; Bolt is unlocked
+ - _Blinking_ ; Bolt is moving to the desired state
+ - _Off_ ; Bolt is locked
+
+ **Push Button 0**
+
+ - _Press and Release_ : Start, or restart, BLE advertisement in fast mode. It will advertise in this mode
+ for 30 seconds. The device will then switch to a slower interval advertisement.
+ After 15 minutes, the advertisement stops.
+
+ - _Pressed and hold for 6 s_ : Initiates the factory reset of the device.
+ Releasing the button within the 6-second window cancels the factory reset
+ procedure. **LEDs** blink in unison when the factory reset procedure is
+ initiated.
+
+ **Push Button 1** Toggles the bolt state On/Off
+
+- You can provision and control the Chip device using the python controller,
+ Chip tool standalone, Android or iOS app
+
+ [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
+
+Here is some CHIPTool examples:
+
+ Pairing with chip-tool:
+ ```
+ chip-tool pairing ble-thread 1 hex: 20202021 3840
+ ```
+
+ Set a user:
+ ```
+ ./out/chip-tool doorlock set-user OperationType UserIndex UserName UserUniqueId UserStatus UserType CredentialRule node-id/group-id
+ ./out/chip-tool doorlock set-user 0 1 "mike" 5 1 0 0 1 1 --timedInteractionTimeoutMs 1000
+ ```
+
+ Set a credential:
+ ```
+ ./out/chip-tool doorlock set-credential OperationType Credential CredentialData UserIndex UserStatus UserType node-id/group-id
+ ./out/chip-tool doorlock set-credential 0 '{ "credentialType": 1, "credentialIndex": 1 }' "123456" 1 null null 1 1 --timedInteractionTimeoutMs 1000
+ ```
+
+ Changing a credential:
+ ```
+ ./out/chip-tool doorlock set-credential OperationType Credential CredentialData UserIndex UserStatus UserType node-id/group-id
+ ./out/chip-tool doorlock set-credential 2 '{ "credentialType": 1, "credentialIndex": 1 }' "123457" 1 null null 1 1 --timedInteractionTimeoutMs 1000
+ ```
+
+ Get a user:
+ ```
+ ./out/chip-tool doorlock get-user UserIndex node-id/group-id
+ ./out/chip-tool doorlock get-user 1 1 1
+ ```
+
+ Unlock door:
+ ```
+ ./out/chip-tool doorlock unlock-door node-id/group-id
+ ./out/chip-tool doorlock unlock-door 1 1 --timedInteractionTimeoutMs 1000
+ ```
+
+ Lock door:
+ ```
+ ./out/chip-tool doorlock lock-door node-id/group-id
+ ./out/chip-tool doorlock lock-door 1 1 --timedInteractionTimeoutMs 1000
+ ```
+
+### Notes
+
+- Depending on your network settings your router might not provide native ipv6
+ addresses to your devices (Border router / PC). If this is the case, you
+ need to add a static ipv6 addresses on both device and then an ipv6 route to
+ the border router on your PC
+
+#On Border Router: \$ sudo ip addr add dev 2002::2/64
+
+#On PC(Linux): \$ sudo ip addr add dev 2002::1/64
+
+#Add Ipv6 route on PC(Linux) \$ sudo ip route add /64
+via 2002::2
+
+## Memory settings
+
+While most of the RAM usage in CHIP is static, allowing easier debugging and
+optimization with symbols analysis, we still need some HEAP for the crypto and
+OpenThread. Size of the HEAP can be modified by changing the value of the
+`configTOTAL_HEAP_SIZE` define inside of the FreeRTOSConfig.h file of this
+example. Please take note that a HEAP size smaller than 13k can and will cause a
+Mbedtls failure during the BLE rendez-vous or CASE session
+
+To track memory usage you can set `enable_heap_monitoring = true` either in the
+BUILD.gn file or pass it as a build argument to gn. This will print on the RTT
+console the RAM usage of each individual task and the number of Memory
+allocation and Free. While this is not extensive monitoring you're welcome to
+modify `examples/platform/efr32/MemMonitoring.cpp` to add your own memory
+tracking code inside the `trackAlloc` and `trackFree` function
+
+## OTA Software Update
+
+For the description of Software Update process with EFR32 example applications
+see
+[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md)
+
+## Building options
+
+All of Silabs's examples within the Matter repo have all the features enabled by
+default, as to provide the best end user experience. However some of those
+features can easily be toggled on or off. Here is a short list of options :
+
+### Disabling logging
+
+`chip_progress_logging, chip_detail_logging, chip_automation_logging`
+
+ ```
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false"
+ ```
+
+### Debug build / release build
+
+`is_debug`
+
+ ```
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "is_debug=false"
+ ```
+
+### Disabling LCD
+
+`show_qr_code`
+
+ ```
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "show_qr_code=false"
+ ```
+
+### KVS maximum entry count
+
+`kvs_max_entries`
+
+ ```
+ Set the maximum Kvs entries that can be stored in NVM (Default 75)
+ Thresholds: 30 <= kvs_max_entries <= 255
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50
+ ```
diff --git a/examples/lock-app/silabs/SiWx917/args.gni b/examples/lock-app/silabs/SiWx917/args.gni
new file mode 100644
index 00000000000000..421090dbc97aae
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/args.gni
@@ -0,0 +1,24 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/src/platform/silabs/SiWx917/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_ota_requestor = true
+chip_enable_openthread = true
+openthread_external_platform =
+ "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32"
diff --git a/examples/lock-app/silabs/SiWx917/build_for_wifi_args.gni b/examples/lock-app/silabs/SiWx917/build_for_wifi_args.gni
new file mode 100644
index 00000000000000..b1a0be42ca9351
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/build_for_wifi_args.gni
@@ -0,0 +1,21 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+chip_enable_openthread = false
+import("${chip_root}/src/platform/silabs/SiWx917/wifi_args.gni")
+
+chip_enable_ota_requestor = true
diff --git a/examples/lock-app/silabs/SiWx917/build_for_wifi_gnfile.gn b/examples/lock-app/silabs/SiWx917/build_for_wifi_gnfile.gn
new file mode 100644
index 00000000000000..d391814190d09f
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/build_for_wifi_gnfile.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_enable_wifi = true
+ import("//build_for_wifi_args.gni")
+}
diff --git a/examples/lock-app/silabs/SiWx917/build_overrides b/examples/lock-app/silabs/SiWx917/build_overrides
new file mode 120000
index 00000000000000..995884e6163eb5
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/build_overrides
@@ -0,0 +1 @@
+../../../build_overrides
\ No newline at end of file
diff --git a/examples/lock-app/silabs/SiWx917/include/AppConfig.h b/examples/lock-app/silabs/SiWx917/include/AppConfig.h
new file mode 100644
index 00000000000000..3014c5be66479c
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/include/AppConfig.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// ---- Door lock Example App Config ----
+
+#define APP_TASK_NAME "Lock"
+
+// Time it takes in ms for the simulated actuator to move from one
+// state to another.
+#define ACTUATOR_MOVEMENT_PERIOS_MS 10
+
+// EFR Logging
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void silabsInitLog(void);
+
+void efr32Log(const char * aFormat, ...);
+#define SILABS_LOG(...) efr32Log(__VA_ARGS__);
+void appError(int err);
+
+#ifdef __cplusplus
+}
+
+#include
+void appError(CHIP_ERROR error);
+#endif
diff --git a/examples/lock-app/silabs/SiWx917/include/AppEvent.h b/examples/lock-app/silabs/SiWx917/include/AppEvent.h
new file mode 100644
index 00000000000000..7724687d3ef96c
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/include/AppEvent.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2018 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+ enum AppEventTypes
+ {
+ kEventType_Button = 0,
+ kEventType_Timer,
+ kEventType_Lock,
+ kEventType_Install,
+ };
+
+ uint16_t Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ void * Context;
+ } TimerEvent;
+ struct
+ {
+ uint8_t Action;
+ int32_t Actor;
+ } LockEvent;
+ };
+
+ EventHandler Handler;
+};
diff --git a/examples/lock-app/silabs/SiWx917/include/AppTask.h b/examples/lock-app/silabs/SiWx917/include/AppTask.h
new file mode 100644
index 00000000000000..e6b88fcf127766
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/include/AppTask.h
@@ -0,0 +1,187 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include
+#include
+
+#include "AppEvent.h"
+#include "BaseApplication.h"
+#include "FreeRTOS.h"
+#include "LockManager.h"
+//#include "sl_simple_button_instances.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include
+#include
+#include
+#include
+
+/**********************************************************
+ * Defines
+ *********************************************************/
+#define SL_SIMPLE_BUTTON_MODE_POLL 0U ///< BUTTON input capture using polling
+#define SL_SIMPLE_BUTTON_MODE_POLL_AND_DEBOUNCE 1U ///< BUTTON input capture using polling and debouncing
+#define SL_SIMPLE_BUTTON_MODE_INTERRUPT 2U ///< BUTTON input capture using interrupt
+
+#define SL_SIMPLE_BUTTON_DISABLED 2U ///< BUTTON state is disabled
+#define SL_SIMPLE_BUTTON_PRESSED 1U ///< BUTTON state is pressed
+#define SL_SIMPLE_BUTTON_RELEASED 0U ///< BUTTON state is released
+
+typedef uint8_t sl_button_mode_t; ///< BUTTON mode
+typedef uint8_t sl_button_state_t; ///< BUTTON state
+typedef struct sl_button sl_button_t;
+
+/// A BUTTON instance
+typedef struct sl_button
+{
+ void * context; ///< The context for this BUTTON instance
+ void (*init)(const sl_button_t * handle); ///< Member function to initialize BUTTON instance
+ void (*poll)(const sl_button_t * handle); ///< Member function to poll BUTTON
+ void (*enable)(const sl_button_t * handle); ///< Member function to enable BUTTON
+ void (*disable)(const sl_button_t * handle); ///< Member function to disable BUTTON
+ sl_button_state_t (*get_state)(const sl_button_t * handle); ///< Member function to retrieve BUTTON state
+} sl_button;
+
+const sl_button_t sl_button_btn0 = {
+ .context = NULL,
+ .init = NULL,
+ .poll = NULL,
+ .enable = NULL,
+ .disable = NULL,
+ .get_state = NULL,
+};
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+
+const sl_button_t sl_button_btn1 = {
+ .context = NULL,
+ .init = NULL,
+ .poll = NULL,
+ .enable = NULL,
+ .disable = NULL,
+ .get_state = NULL,
+};
+#define APP_LIGHT_SWITCH &sl_button_btn1
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+#define APP_ERROR_ALLOCATION_FAILED CHIP_APPLICATION_ERROR(0x07)
+#if defined(ENABLE_CHIP_SHELL)
+#define APP_ERROR_TOO_MANY_SHELL_ARGUMENTS CHIP_APPLICATION_ERROR(0x08)
+#endif // ENABLE_CHIP_SHELL
+
+/**********************************************************
+ * AppTask Declaration
+ *********************************************************/
+
+class AppTask : public BaseApplication
+{
+
+public:
+ AppTask() = default;
+
+ static AppTask & GetAppTask() { return sAppTask; }
+
+ /**
+ * @brief AppTask task main loop function
+ *
+ * @param pvParameter FreeRTOS task parameter
+ */
+ static void AppTaskMain(void * pvParameter);
+
+ CHIP_ERROR StartAppTask();
+
+ void ActionRequest(int32_t aActor, LockManager::Action_t aAction);
+ static void ActionInitiated(LockManager::Action_t aAction, int32_t aActor);
+ static void ActionCompleted(LockManager::Action_t aAction);
+
+ /**
+ * @brief Event handler when a button is pressed
+ * Function posts an event for button processing
+ *
+ * @param buttonHandle APP_LIGHT_SWITCH or APP_FUNCTION_BUTTON
+ * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED,
+ * SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED
+ */
+ void ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction);
+
+ /**
+ * @brief Callback called by the identify-server when an identify command is received
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStart(Identify * identify);
+
+ /**
+ * @brief Callback called by the identify-server when an identify command is stopped or finished
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStop(Identify * identify);
+
+private:
+ static AppTask sAppTask;
+
+ /**
+ * @brief AppTask initialisation function
+ *
+ * @return CHIP_ERROR
+ */
+ CHIP_ERROR Init();
+
+ /**
+ * @brief PB0 Button event processing function
+ * Press and hold will trigger a factory reset timer start
+ * Press and release will restart BLEAdvertising if not commisionned
+ *
+ * @param aEvent button event being processed
+ */
+ static void ButtonHandler(AppEvent * aEvent);
+
+ /**
+ * @brief PB1 Button event processing function
+ * Function triggers a switch action sent to the CHIP task
+ *
+ * @param aEvent button event being processed
+ */
+ static void SwitchActionEventHandler(AppEvent * aEvent);
+
+ /**
+ * @brief Update Cluster State
+ *
+ * @param context current context
+ */
+ static void UpdateClusterState(intptr_t context);
+
+ /**
+ * @brief Handle lock update event
+ *
+ * @param aEvent event received
+ */
+ static void LockActionEventHandler(AppEvent * aEvent);
+};
diff --git a/examples/lock-app/silabs/SiWx917/include/CHIPProjectConfig.h b/examples/lock-app/silabs/SiWx917/include/CHIPProjectConfig.h
new file mode 100644
index 00000000000000..9793e98ac9bc0a
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/include/CHIPProjectConfig.h
@@ -0,0 +1,123 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Example project configuration file for CHIP.
+ *
+ * This is a place to put application or project-specific overrides
+ * to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+// Use a default pairing code if one hasn't been provisioned in flash.
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+#endif
+
+// For convenience, Chip Security Test Mode can be enabled and the
+// requirement for authentication in various protocols can be disabled.
+//
+// WARNING: These options make it possible to circumvent basic Chip security functionality,
+// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+//
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+#define CHIP_CONFIG_REQUIRE_AUTH 1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ * 0x8006: example lock app
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8006
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION
+ *
+ * The hardware version number assigned to device or product by the device vendor. This
+ * number is scoped to the device product id, and typically corresponds to a revision of the
+ * physical device, a change to its packaging, and/or a change to its marketing presentation.
+ * This value is generally *not* incremented for device software versions.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+ *
+ * A uint32_t identifying the software version running on the device.
+ */
+/* The SoftwareVersion attribute of the Basic cluster. */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 0x0001
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in Chip NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
+ *
+ * Enable recording UTC timestamps.
+ */
+#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE
+ *
+ * A size, in bytes, of the individual debug event logging buffer.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)
+
+/**
+ * @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL
+ *
+ * @brief
+ * Active retransmit interval, or time to wait before retransmission after
+ * subsequent failures in milliseconds.
+ *
+ * This is the default value, that might be adjusted by end device depending on its
+ * needs (e.g. sleeping period) using Service Discovery TXT record CRA key.
+ *
+ */
+#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32)
diff --git a/examples/lock-app/silabs/SiWx917/include/EventHandlerLibShell.h b/examples/lock-app/silabs/SiWx917/include/EventHandlerLibShell.h
new file mode 100644
index 00000000000000..3ad9f11cbf2fdc
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/include/EventHandlerLibShell.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include
+
+class EventData
+{
+public:
+ chip::EventId eventId;
+};
+
+class AlarmEventData : public EventData
+{
+public:
+ DlAlarmCode alarmCode;
+};
+
+class DoorStateEventData : public EventData
+{
+public:
+ DlDoorState doorState;
+};
+
+CHIP_ERROR RegisterLockEvents();
+void EventWorkerFunction(intptr_t context);
diff --git a/examples/lock-app/silabs/SiWx917/include/LockManager.h b/examples/lock-app/silabs/SiWx917/include/LockManager.h
new file mode 100644
index 00000000000000..b451921f804bc4
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/include/LockManager.h
@@ -0,0 +1,218 @@
+/*
+ *
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include
+
+#include
+#include
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+
+#include
+
+struct WeekDaysScheduleInfo
+{
+ DlScheduleStatus status;
+ EmberAfPluginDoorLockWeekDaySchedule schedule;
+};
+
+struct YearDayScheduleInfo
+{
+ DlScheduleStatus status;
+ EmberAfPluginDoorLockYearDaySchedule schedule;
+};
+
+struct HolidayScheduleInfo
+{
+ DlScheduleStatus status;
+ EmberAfPluginDoorLockHolidaySchedule schedule;
+};
+
+namespace SI917DoorLock {
+namespace ResourceRanges {
+// Used to size arrays
+static constexpr uint16_t kMaxUsers = 10;
+static constexpr uint8_t kMaxCredentialsPerUser = 10;
+static constexpr uint8_t kMaxWeekdaySchedulesPerUser = 10;
+static constexpr uint8_t kMaxYeardaySchedulesPerUser = 10;
+static constexpr uint8_t kMaxHolidaySchedules = 10;
+static constexpr uint8_t kMaxCredentialSize = 8;
+
+static constexpr uint8_t kMaxCredentials = kMaxUsers * kMaxCredentialsPerUser;
+} // namespace ResourceRanges
+
+namespace LockInitParams {
+
+struct LockParam
+{
+ // Read from zap attributes
+ uint16_t numberOfUsers = 0;
+ uint8_t numberOfCredentialsPerUser = 0;
+ uint8_t numberOfWeekdaySchedulesPerUser = 0;
+ uint8_t numberOfYeardaySchedulesPerUser = 0;
+ uint8_t numberOfHolidaySchedules = 0;
+};
+
+class ParamBuilder
+{
+public:
+ ParamBuilder & SetNumberOfUsers(uint16_t numberOfUsers)
+ {
+ lockParam_.numberOfUsers = numberOfUsers;
+ return *this;
+ }
+ ParamBuilder & SetNumberOfCredentialsPerUser(uint8_t numberOfCredentialsPerUser)
+ {
+ lockParam_.numberOfCredentialsPerUser = numberOfCredentialsPerUser;
+ return *this;
+ }
+ ParamBuilder & SetNumberOfWeekdaySchedulesPerUser(uint8_t numberOfWeekdaySchedulesPerUser)
+ {
+ lockParam_.numberOfWeekdaySchedulesPerUser = numberOfWeekdaySchedulesPerUser;
+ return *this;
+ }
+ ParamBuilder & SetNumberOfYeardaySchedulesPerUser(uint8_t numberOfYeardaySchedulesPerUser)
+ {
+ lockParam_.numberOfYeardaySchedulesPerUser = numberOfYeardaySchedulesPerUser;
+ return *this;
+ }
+ ParamBuilder & SetNumberOfHolidaySchedules(uint8_t numberOfHolidaySchedules)
+ {
+ lockParam_.numberOfHolidaySchedules = numberOfHolidaySchedules;
+ return *this;
+ }
+ LockParam GetLockParam() { return lockParam_; }
+
+private:
+ LockParam lockParam_;
+};
+
+} // namespace LockInitParams
+} // namespace SI917DoorLock
+
+using namespace ::chip;
+using namespace SI917DoorLock::ResourceRanges;
+
+class LockManager
+{
+public:
+ enum Action_t
+ {
+ LOCK_ACTION = 0,
+ UNLOCK_ACTION,
+
+ INVALID_ACTION
+ } Action;
+
+ enum State_t
+ {
+ kState_LockInitiated = 0,
+ kState_LockCompleted,
+ kState_UnlockInitiated,
+ kState_UnlockCompleted,
+ } State;
+
+ CHIP_ERROR Init(chip::app::DataModel::Nullable state,
+ SI917DoorLock::LockInitParams::LockParam lockParam);
+ bool NextState();
+ bool IsActionInProgress();
+ bool InitiateAction(int32_t aActor, Action_t aAction);
+
+ typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor);
+ typedef void (*Callback_fn_completed)(Action_t);
+ void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB);
+
+ bool Lock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err);
+ bool Unlock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err);
+
+ bool GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user);
+ bool SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier,
+ const chip::CharSpan & userName, uint32_t uniqueId, DlUserStatus userStatus, DlUserType usertype,
+ DlCredentialRule credentialRule, const DlCredential * credentials, size_t totalCredentials);
+
+ bool GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType,
+ EmberAfPluginDoorLockCredentialInfo & credential);
+
+ bool SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, chip::FabricIndex creator, chip::FabricIndex modifier,
+ DlCredentialStatus credentialStatus, DlCredentialType credentialType, const chip::ByteSpan & credentialData);
+
+ DlStatus GetWeekdaySchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex,
+ EmberAfPluginDoorLockWeekDaySchedule & schedule);
+
+ DlStatus SetWeekdaySchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex, DlScheduleStatus status,
+ DlDaysMaskMap daysMask, uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute);
+
+ DlStatus GetYeardaySchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex,
+ EmberAfPluginDoorLockYearDaySchedule & schedule);
+
+ DlStatus SetYeardaySchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex, DlScheduleStatus status,
+ uint32_t localStartTime, uint32_t localEndTime);
+
+ DlStatus GetHolidaySchedule(chip::EndpointId endpointId, uint8_t holidayIndex, EmberAfPluginDoorLockHolidaySchedule & schedule);
+
+ DlStatus SetHolidaySchedule(chip::EndpointId endpointId, uint8_t holidayIndex, DlScheduleStatus status, uint32_t localStartTime,
+ uint32_t localEndTime, DlOperatingMode operatingMode);
+
+ bool IsValidUserIndex(uint16_t userIndex);
+ bool IsValidCredentialIndex(uint16_t credentialIndex, DlCredentialType type);
+ bool IsValidWeekdayScheduleIndex(uint8_t scheduleIndex);
+ bool IsValidYeardayScheduleIndex(uint8_t scheduleIndex);
+ bool IsValidHolidayScheduleIndex(uint8_t scheduleIndex);
+
+ bool setLockState(chip::EndpointId endpointId, DlLockState lockState, const Optional & pin,
+ DlOperationError & err);
+ const char * lockStateToString(DlLockState lockState) const;
+
+ bool ReadConfigValues();
+
+private:
+ friend LockManager & LockMgr();
+ State_t mState;
+
+ Callback_fn_initiated mActionInitiated_CB;
+ Callback_fn_completed mActionCompleted_CB;
+
+ void CancelTimer(void);
+ void StartTimer(uint32_t aTimeoutMs);
+
+ static void TimerEventHandler(TimerHandle_t xTimer);
+ static void AutoLockTimerEventHandler(AppEvent * aEvent);
+ static void ActuatorMovementTimerEventHandler(AppEvent * aEvent);
+
+ EmberAfPluginDoorLockUserInfo mLockUsers[kMaxUsers];
+ EmberAfPluginDoorLockCredentialInfo mLockCredentials[kMaxCredentials];
+ WeekDaysScheduleInfo mWeekdaySchedule[kMaxUsers][kMaxWeekdaySchedulesPerUser];
+ YearDayScheduleInfo mYeardaySchedule[kMaxUsers][kMaxYeardaySchedulesPerUser];
+ HolidayScheduleInfo mHolidaySchedule[kMaxHolidaySchedules];
+
+ char mUserNames[ArraySize(mLockUsers)][DOOR_LOCK_MAX_USER_NAME_SIZE];
+ uint8_t mCredentialData[kMaxCredentials][kMaxCredentialSize];
+ DlCredential mCredentials[kMaxUsers][kMaxCredentialsPerUser];
+
+ static LockManager sLock;
+ SI917DoorLock::LockInitParams::LockParam LockParams;
+};
+
+inline LockManager & LockMgr()
+{
+ return LockManager::sLock;
+}
diff --git a/examples/lock-app/silabs/SiWx917/src/AppTask.cpp b/examples/lock-app/silabs/SiWx917/src/AppTask.cpp
new file mode 100644
index 00000000000000..c4878ee9ba8a7f
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/src/AppTask.cpp
@@ -0,0 +1,440 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AppTask.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+#if defined(ENABLE_CHIP_SHELL)
+#include "EventHandlerLibShell.h"
+#endif // ENABLE_CHIP_SHELL
+
+#ifdef ENABLE_WSTK_LEDS
+#include "LEDWidget.h"
+#include "sl_simple_led_instances.h"
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef DISPLAY_ENABLED
+#include "lcd.h"
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#endif // QR_CODE_ENABLED
+#endif // DISPLAY_ENABLED
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+
+#include
+
+#ifdef ENABLE_WSTK_LEDS
+#define SYSTEM_STATE_LED &sl_led_led0
+#define LOCK_STATE_LED &sl_led_led1
+#endif // ENABLE_WSTK_LEDS
+
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+#define APP_LOCK_SWITCH &sl_button_btn1
+
+using chip::app::Clusters::DoorLock::DlLockState;
+using chip::app::Clusters::DoorLock::DlOperationError;
+using chip::app::Clusters::DoorLock::DlOperationSource;
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::DeviceLayer::Internal;
+using namespace SI917DoorLock::LockInitParams;
+
+namespace {
+#ifdef ENABLE_WSTK_LEDS
+LEDWidget sLockLED;
+#endif // ENABLE_WSTK_LEDS
+
+EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+} // namespace
+/**********************************************************
+ * Identify Callbacks
+ *********************************************************/
+
+namespace {
+void OnTriggerIdentifyEffectCompleted(chip::System::Layer * systemLayer, void * appState)
+{
+ ChipLogProgress(Zcl, "Trigger Identify Complete");
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StopStatusLEDTimer();
+#endif
+}
+
+void OnTriggerIdentifyEffect(Identify * identify)
+{
+ sIdentifyEffect = identify->mCurrentEffectIdentifier;
+
+ if (identify->mCurrentEffectIdentifier == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE)
+ {
+ ChipLogProgress(Zcl, "IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE - Not supported, use effect varriant %d",
+ identify->mEffectVariant);
+ sIdentifyEffect = static_cast(identify->mEffectVariant);
+ }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StartStatusLEDTimer();
+#endif
+
+ switch (sIdentifyEffect)
+ {
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY:
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(5), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(1), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+ break;
+ default:
+ ChipLogProgress(Zcl, "No identifier effect");
+ }
+}
+
+Identify gIdentify = {
+ chip::EndpointId{ 1 },
+ AppTask::GetAppTask().OnIdentifyStart,
+ AppTask::GetAppTask().OnIdentifyStop,
+ EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED,
+ OnTriggerIdentifyEffect,
+};
+
+} // namespace
+
+using namespace chip::TLV;
+using namespace ::chip::DeviceLayer;
+
+AppTask AppTask::sAppTask;
+
+CHIP_ERROR AppTask::Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+#ifdef DISPLAY_ENABLED
+ GetLCD().Init((uint8_t *) "Lock-App", true);
+#endif
+
+ err = BaseApplication::Init(&gIdentify);
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("BaseApplication::Init() failed");
+ appError(err);
+ }
+
+#if defined(ENABLE_CHIP_SHELL)
+ err = RegisterLockEvents();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("RegisterLockEvents() failed");
+ appError(err);
+ }
+#endif // ENABLE_CHIP_SHELL
+
+ // Initial lock state
+ chip::app::DataModel::Nullable state;
+ chip::EndpointId endpointId{ 1 };
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::Clusters::DoorLock::Attributes::LockState::Get(endpointId, state);
+
+ uint8_t numberOfCredentialsPerUser = 0;
+ if (!DoorLockServer::Instance().GetNumberOfCredentialsSupportedPerUser(endpointId, numberOfCredentialsPerUser))
+ {
+ ChipLogError(Zcl,
+ "Unable to get number of credentials supported per user when initializing lock endpoint, defaulting to 5 "
+ "[endpointId=%d]",
+ endpointId);
+ numberOfCredentialsPerUser = 5;
+ }
+
+ uint16_t numberOfUsers = 0;
+ if (!DoorLockServer::Instance().GetNumberOfUserSupported(endpointId, numberOfUsers))
+ {
+ ChipLogError(Zcl,
+ "Unable to get number of supported users when initializing lock endpoint, defaulting to 10 [endpointId=%d]",
+ endpointId);
+ numberOfUsers = 10;
+ }
+
+ uint8_t numberOfWeekdaySchedulesPerUser = 0;
+ if (!DoorLockServer::Instance().GetNumberOfWeekDaySchedulesPerUserSupported(endpointId, numberOfWeekdaySchedulesPerUser))
+ {
+ ChipLogError(
+ Zcl,
+ "Unable to get number of supported weekday schedules when initializing lock endpoint, defaulting to 10 [endpointId=%d]",
+ endpointId);
+ numberOfWeekdaySchedulesPerUser = 10;
+ }
+
+ uint8_t numberOfYeardaySchedulesPerUser = 0;
+ if (!DoorLockServer::Instance().GetNumberOfYearDaySchedulesPerUserSupported(endpointId, numberOfYeardaySchedulesPerUser))
+ {
+ ChipLogError(
+ Zcl,
+ "Unable to get number of supported yearday schedules when initializing lock endpoint, defaulting to 10 [endpointId=%d]",
+ endpointId);
+ numberOfYeardaySchedulesPerUser = 10;
+ }
+
+ uint8_t numberOfHolidaySchedules = 0;
+ if (!DoorLockServer::Instance().GetNumberOfHolidaySchedulesSupported(endpointId, numberOfHolidaySchedules))
+ {
+ ChipLogError(
+ Zcl,
+ "Unable to get number of supported holiday schedules when initializing lock endpoint, defaulting to 10 [endpointId=%d]",
+ endpointId);
+ numberOfHolidaySchedules = 10;
+ }
+
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ err = LockMgr().Init(state,
+ ParamBuilder()
+ .SetNumberOfUsers(numberOfUsers)
+ .SetNumberOfCredentialsPerUser(numberOfCredentialsPerUser)
+ .SetNumberOfWeekdaySchedulesPerUser(numberOfWeekdaySchedulesPerUser)
+ .SetNumberOfYeardaySchedulesPerUser(numberOfYeardaySchedulesPerUser)
+ .SetNumberOfHolidaySchedules(numberOfHolidaySchedules)
+ .GetLockParam());
+
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("LockMgr().Init() failed");
+ appError(err);
+ }
+
+ LockMgr().SetCallbacks(ActionInitiated, ActionCompleted);
+
+#ifdef ENABLE_WSTK_LEDS
+ // Initialize LEDs
+ sLockLED.Init(LOCK_STATE_LED);
+ sLockLED.Set(state.Value() == DlLockState::kUnlocked);
+#endif // ENABLE_WSTK_LEDS
+
+ chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState, reinterpret_cast(nullptr));
+
+ ConfigurationMgr().LogDeviceConfig();
+
+ return err;
+}
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+ return BaseApplication::StartAppTask(AppTaskMain);
+}
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+ AppEvent event;
+ QueueHandle_t sAppEventQueue = *(static_cast(pvParameter));
+
+ CHIP_ERROR err = sAppTask.Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("AppTask.Init() failed");
+ appError(err);
+ }
+
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+ sAppTask.StartStatusLEDTimer();
+#endif
+
+ SILABS_LOG("App Task started");
+
+ // Users and credentials should be checked once from nvm flash on boot
+ LockMgr().ReadConfigValues();
+
+ while (true)
+ {
+ BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, portMAX_DELAY);
+ while (eventReceived == pdTRUE)
+ {
+ sAppTask.DispatchEvent(&event);
+ eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+ }
+ }
+}
+
+void AppTask::OnIdentifyStart(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStart");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StartStatusLEDTimer();
+#endif
+}
+
+void AppTask::OnIdentifyStop(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStop");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StopStatusLEDTimer();
+#endif
+}
+
+void AppTask::LockActionEventHandler(AppEvent * aEvent)
+{
+ bool initiated = false;
+ LockManager::Action_t action;
+ int32_t actor;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (aEvent->Type == AppEvent::kEventType_Lock)
+ {
+ action = static_cast(aEvent->LockEvent.Action);
+ actor = aEvent->LockEvent.Actor;
+ }
+ else if (aEvent->Type == AppEvent::kEventType_Button)
+ {
+ if (LockMgr().NextState() == true)
+ {
+ action = LockManager::LOCK_ACTION;
+ }
+ else
+ {
+ action = LockManager::UNLOCK_ACTION;
+ }
+ actor = AppEvent::kEventType_Button;
+ }
+ else
+ {
+ err = APP_ERROR_UNHANDLED_EVENT;
+ }
+
+ if (err == CHIP_NO_ERROR)
+ {
+ initiated = LockMgr().InitiateAction(actor, action);
+
+ if (!initiated)
+ {
+ SILABS_LOG("Action is already in progress or active.");
+ }
+ }
+}
+
+void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction)
+{
+ if (buttonHandle == NULL)
+ {
+ return;
+ }
+
+ AppEvent button_event = {};
+ button_event.Type = AppEvent::kEventType_Button;
+ button_event.ButtonEvent.Action = btnAction;
+
+ SILABS_LOG("### Lock button #### ");
+ button_event.Handler = BaseApplication::ButtonHandler;
+ sAppTask.PostEvent(&button_event);
+}
+
+void AppTask::ActionInitiated(LockManager::Action_t aAction, int32_t aActor)
+{
+ if (aAction == LockManager::UNLOCK_ACTION || aAction == LockManager::LOCK_ACTION)
+ {
+ bool locked = (aAction == LockManager::LOCK_ACTION);
+ SILABS_LOG("%s Action has been initiated", (locked) ? "Lock" : "Unlock");
+#ifdef ENABLE_WSTK_LEDS
+ sLockLED.Set(!locked);
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef DISPLAY_ENABLED
+ sAppTask.GetLCD().WriteDemoUI(locked);
+#endif // DISPLAY_ENABLED
+ }
+
+ if (aActor == AppEvent::kEventType_Button)
+ {
+ sAppTask.mSyncClusterToButtonAction = true;
+ }
+}
+
+void AppTask::ActionCompleted(LockManager::Action_t aAction)
+{
+ // if the action has been completed by the lock, update the lock trait.
+ // Turn off the lock LED if in a LOCKED state OR
+ // Turn on the lock LED if in an UNLOCKED state.
+ if (aAction == LockManager::LOCK_ACTION)
+ {
+ SILABS_LOG("Lock Action has been completed")
+ }
+ else if (aAction == LockManager::UNLOCK_ACTION)
+ {
+ SILABS_LOG("Unlock Action has been completed")
+ }
+
+ if (sAppTask.mSyncClusterToButtonAction)
+ {
+ chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState, reinterpret_cast(nullptr));
+ sAppTask.mSyncClusterToButtonAction = false;
+ }
+}
+
+void AppTask::ActionRequest(int32_t aActor, LockManager::Action_t aAction)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Lock;
+ event.LockEvent.Actor = aActor;
+ event.LockEvent.Action = aAction;
+ event.Handler = LockActionEventHandler;
+ PostEvent(&event);
+}
+
+void AppTask::UpdateClusterState(intptr_t context)
+{
+ bool unlocked = LockMgr().NextState();
+ DlLockState newState = unlocked ? DlLockState::kUnlocked : DlLockState::kLocked;
+
+ DlOperationSource source = DlOperationSource::kUnspecified;
+
+ // write the new lock value
+ EmberAfStatus status =
+ DoorLockServer::Instance().SetLockState(1, newState, source) ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE;
+
+ if (status != EMBER_ZCL_STATUS_SUCCESS)
+ {
+ SILABS_LOG("ERR: updating lock state %x", status);
+ }
+}
diff --git a/examples/lock-app/silabs/SiWx917/src/EventHandlerLibShell.cpp b/examples/lock-app/silabs/SiWx917/src/EventHandlerLibShell.cpp
new file mode 100644
index 00000000000000..02979f56238a23
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/src/EventHandlerLibShell.cpp
@@ -0,0 +1,211 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EventHandlerLibShell.h"
+#include "AppTask.h"
+#include "lib/shell/Engine.h"
+#include "lib/shell/commands/Help.h"
+
+#include "app/server/Server.h"
+#include "platform/CHIPDeviceLayer.h"
+#include
+
+constexpr uint8_t lockEndpoint = 1;
+
+using namespace chip;
+using namespace chip::app;
+using namespace Clusters::DoorLock;
+using Shell::Engine;
+using Shell::shell_command_t;
+using Shell::streamer_get;
+using Shell::streamer_printf;
+
+Engine sShellDoorlockSubCommands;
+Engine sShellDoorlockEventSubCommands;
+Engine sShellDoorlockEventAlarmSubCommands;
+Engine sShellDoorlockEventDoorStateSubCommands;
+
+/********************************************************
+ * Doorlock shell functions
+ *********************************************************/
+
+CHIP_ERROR DoorlockHelpHandler(int argc, char ** argv)
+{
+ sShellDoorlockSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DoorlockCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return DoorlockHelpHandler(argc, argv);
+ }
+
+ return sShellDoorlockSubCommands.ExecCommand(argc, argv);
+}
+
+/********************************************************
+ * Event shell functions
+ *********************************************************/
+
+CHIP_ERROR EventHelpHandler(int argc, char ** argv)
+{
+ sShellDoorlockEventSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EventDoorlockCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return EventHelpHandler(argc, argv);
+ }
+
+ return sShellDoorlockEventSubCommands.ExecCommand(argc, argv);
+}
+
+/********************************************************
+ * Alarm shell functions
+ *********************************************************/
+
+CHIP_ERROR AlarmHelpHandler(int argc, char ** argv)
+{
+ sShellDoorlockEventAlarmSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR AlarmEventHandler(int argc, char ** argv)
+{
+
+ if (argc == 0)
+ {
+ return AlarmHelpHandler(argc, argv);
+ }
+ if (argc >= 2)
+ {
+ ChipLogError(Zcl, "Too many arguments provided to function %s, line %d", __func__, __LINE__);
+ return APP_ERROR_TOO_MANY_SHELL_ARGUMENTS;
+ }
+
+ AlarmEventData * data = Platform::New();
+ data->eventId = Events::DoorLockAlarm::Id;
+ data->alarmCode = static_cast(atoi(argv[0]));
+
+ DeviceLayer::PlatformMgr().ScheduleWork(EventWorkerFunction, reinterpret_cast(data));
+
+ return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * Door state shell functions
+ *********************************************************/
+
+CHIP_ERROR DoorStateHelpHandler(int argc, char ** argv)
+{
+ sShellDoorlockEventDoorStateSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DoorStateEventHandler(int argc, char ** argv)
+{
+
+ if (argc == 0)
+ {
+ return DoorStateHelpHandler(argc, argv);
+ }
+ if (argc >= 2)
+ {
+ ChipLogError(Zcl, "Too many arguments provided to function %s, line %d", __func__, __LINE__);
+ return APP_ERROR_TOO_MANY_SHELL_ARGUMENTS;
+ }
+
+ DoorStateEventData * data = Platform::New();
+ data->eventId = Events::DoorStateChange::Id;
+ data->doorState = static_cast(atoi(argv[0]));
+
+ DeviceLayer::PlatformMgr().ScheduleWork(EventWorkerFunction, reinterpret_cast(data));
+
+ return CHIP_NO_ERROR;
+}
+
+/**
+ * @brief configures lock matter shell
+ *
+ */
+
+CHIP_ERROR RegisterLockEvents()
+{
+ static const shell_command_t sDoorlockSubCommands[] = { { &DoorlockHelpHandler, "help", "Usage: doorlock " },
+ { &EventDoorlockCommandHandler, "event",
+ " Usage: doorlock event " } };
+
+ static const shell_command_t sDoorlockEventSubCommands[] = {
+ { &EventHelpHandler, "help", "Usage : doorlock event " },
+ { &AlarmEventHandler, "lock-alarm", "Sends lock alarm event to lock app" },
+ { &DoorStateEventHandler, "door-state-change", "Sends door state change event to lock app" }
+ };
+
+ static const shell_command_t sDoorlockEventAlarmSubCommands[] = { { &AlarmHelpHandler, "help",
+ "Usage : doorlock event lock-alarm AlarmCode" } };
+
+ static const shell_command_t sDoorlockEventDoorStateSubCommands[] = {
+ { &DoorStateHelpHandler, "help", "Usage : doorlock event door-state-change DoorState" }
+ };
+
+ static const shell_command_t sDoorLockCommand = { &DoorlockCommandHandler, "doorlock",
+ "doorlock commands. Usage: doorlock " };
+
+ sShellDoorlockEventAlarmSubCommands.RegisterCommands(sDoorlockEventAlarmSubCommands, ArraySize(sDoorlockEventAlarmSubCommands));
+
+ sShellDoorlockEventDoorStateSubCommands.RegisterCommands(sDoorlockEventDoorStateSubCommands,
+ ArraySize(sDoorlockEventDoorStateSubCommands));
+
+ sShellDoorlockEventSubCommands.RegisterCommands(sDoorlockEventSubCommands, ArraySize(sDoorlockEventSubCommands));
+ sShellDoorlockSubCommands.RegisterCommands(sDoorlockSubCommands, ArraySize(sDoorlockSubCommands));
+
+ Engine::Root().RegisterCommands(&sDoorLockCommand, 1);
+
+ return CHIP_NO_ERROR;
+}
+
+void EventWorkerFunction(intptr_t context)
+{
+ VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "EventWorkerFunction - Invalid work data"));
+
+ EventData * data = reinterpret_cast(context);
+
+ switch (data->eventId)
+ {
+ case Events::DoorLockAlarm::Id: {
+ AlarmEventData * alarmData = reinterpret_cast(context);
+ DoorLockServer::Instance().SendLockAlarmEvent(lockEndpoint, alarmData->alarmCode);
+ break;
+ }
+
+ case Events::DoorStateChange::Id: {
+ DoorStateEventData * doorStateData = reinterpret_cast(context);
+ DoorLockServer::Instance().SetDoorState(lockEndpoint, doorStateData->doorState);
+ break;
+ }
+
+ default: {
+ ChipLogError(Zcl, "Invalid Event Id %s, line %d", __func__, __LINE__);
+ break;
+ }
+ }
+}
diff --git a/examples/lock-app/silabs/SiWx917/src/LockManager.cpp b/examples/lock-app/silabs/SiWx917/src/LockManager.cpp
new file mode 100644
index 00000000000000..0ef26ec0337b6b
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/src/LockManager.cpp
@@ -0,0 +1,709 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LockManager.h"
+
+#include "AppConfig.h"
+#include "AppTask.h"
+#include
+#include
+#include
+#include
+
+LockManager LockManager::sLock;
+
+TimerHandle_t sLockTimer;
+
+using namespace ::chip::DeviceLayer::Internal;
+using namespace SI917DoorLock::LockInitParams;
+
+CHIP_ERROR LockManager::Init(chip::app::DataModel::Nullable state, LockParam lockParam)
+{
+
+ LockParams = lockParam;
+
+ if (LockParams.numberOfUsers > kMaxUsers)
+ {
+ SILABS_LOG("Max number of users is greater than %d, the maximum amount of users currently supported on this platform",
+ kMaxUsers);
+ return APP_ERROR_ALLOCATION_FAILED;
+ }
+
+ if (LockParams.numberOfCredentialsPerUser > kMaxCredentialsPerUser)
+ {
+ SILABS_LOG("Max number of credentials per user is greater than %d, the maximum amount of users currently supported on this "
+ "platform",
+ kMaxCredentialsPerUser);
+ return APP_ERROR_ALLOCATION_FAILED;
+ }
+
+ if (LockParams.numberOfWeekdaySchedulesPerUser > kMaxWeekdaySchedulesPerUser)
+ {
+ SILABS_LOG(
+ "Max number of schedules is greater than %d, the maximum amount of schedules currently supported on this platform",
+ kMaxWeekdaySchedulesPerUser);
+ return APP_ERROR_ALLOCATION_FAILED;
+ }
+
+ if (LockParams.numberOfYeardaySchedulesPerUser > kMaxYeardaySchedulesPerUser)
+ {
+ SILABS_LOG(
+ "Max number of schedules is greater than %d, the maximum amount of schedules currently supported on this platform",
+ kMaxYeardaySchedulesPerUser);
+ return APP_ERROR_ALLOCATION_FAILED;
+ }
+
+ if (LockParams.numberOfHolidaySchedules > kMaxHolidaySchedules)
+ {
+ SILABS_LOG(
+ "Max number of schedules is greater than %d, the maximum amount of schedules currently supported on this platform",
+ kMaxHolidaySchedules);
+ return APP_ERROR_ALLOCATION_FAILED;
+ }
+
+ // Create FreeRTOS sw timer for lock timer.
+ sLockTimer = xTimerCreate("lockTmr", // Just a text name, not used by the RTOS kernel
+ 1, // == default timer period (mS)
+ false, // no timer reload (==one-shot)
+ (void *) this, // init timer id = lock obj context
+ TimerEventHandler // timer callback handler
+ );
+
+ if (sLockTimer == NULL)
+ {
+ SILABS_LOG("sLockTimer timer create failed");
+ return APP_ERROR_CREATE_TIMER_FAILED;
+ }
+
+ if (state.Value() == DlLockState::kUnlocked)
+ mState = kState_UnlockCompleted;
+ else
+ mState = kState_LockCompleted;
+
+ return CHIP_NO_ERROR;
+}
+
+bool LockManager::IsValidUserIndex(uint16_t userIndex)
+{
+ return (userIndex < kMaxUsers);
+}
+
+bool LockManager::IsValidCredentialIndex(uint16_t credentialIndex, DlCredentialType type)
+{
+ if (DlCredentialType::kProgrammingPIN == type)
+ {
+ return (0 == credentialIndex); // 0 is required index for Programming PIN
+ }
+ return (credentialIndex < kMaxCredentialsPerUser);
+}
+
+bool LockManager::IsValidWeekdayScheduleIndex(uint8_t scheduleIndex)
+{
+ return (scheduleIndex < kMaxWeekdaySchedulesPerUser);
+}
+
+bool LockManager::IsValidYeardayScheduleIndex(uint8_t scheduleIndex)
+{
+ return (scheduleIndex < kMaxYeardaySchedulesPerUser);
+}
+
+bool LockManager::IsValidHolidayScheduleIndex(uint8_t scheduleIndex)
+{
+ return (scheduleIndex < kMaxHolidaySchedules);
+}
+
+bool LockManager::ReadConfigValues()
+{
+ size_t outLen;
+ SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_LockUser, reinterpret_cast(&mLockUsers),
+ sizeof(EmberAfPluginDoorLockUserInfo) * ArraySize(mLockUsers), outLen);
+
+ SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_Credential, reinterpret_cast(&mLockCredentials),
+ sizeof(EmberAfPluginDoorLockCredentialInfo) * ArraySize(mLockCredentials), outLen);
+
+ SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_LockUserName, reinterpret_cast(mUserNames),
+ sizeof(mUserNames), outLen);
+
+ SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_CredentialData, reinterpret_cast(mCredentialData),
+ sizeof(mCredentialData), outLen);
+
+ SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_UserCredentials, reinterpret_cast(mCredentials),
+ sizeof(DlCredential) * LockParams.numberOfUsers * LockParams.numberOfCredentialsPerUser,
+ outLen);
+
+ SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_WeekDaySchedules, reinterpret_cast(mWeekdaySchedule),
+ sizeof(EmberAfPluginDoorLockWeekDaySchedule) * LockParams.numberOfWeekdaySchedulesPerUser *
+ LockParams.numberOfUsers,
+ outLen);
+
+ SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_YearDaySchedules, reinterpret_cast(mYeardaySchedule),
+ sizeof(EmberAfPluginDoorLockYearDaySchedule) * LockParams.numberOfYeardaySchedulesPerUser *
+ LockParams.numberOfUsers,
+ outLen);
+
+ SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_HolidaySchedules, reinterpret_cast(&(mHolidaySchedule)),
+ sizeof(EmberAfPluginDoorLockHolidaySchedule) * LockParams.numberOfHolidaySchedules, outLen);
+
+ return true;
+}
+
+void LockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
+{
+ mActionInitiated_CB = aActionInitiated_CB;
+ mActionCompleted_CB = aActionCompleted_CB;
+}
+
+bool LockManager::IsActionInProgress()
+{
+ return (mState == kState_LockInitiated || mState == kState_UnlockInitiated);
+}
+
+bool LockManager::NextState()
+{
+ return (mState == kState_UnlockCompleted);
+}
+
+bool LockManager::InitiateAction(int32_t aActor, Action_t aAction)
+{
+ bool action_initiated = false;
+ State_t new_state;
+
+ // Initiate Turn Lock/Unlock Action only when the previous one is complete.
+ if (mState == kState_LockCompleted && aAction == UNLOCK_ACTION)
+ {
+ action_initiated = true;
+
+ new_state = kState_UnlockInitiated;
+ }
+ else if (mState == kState_UnlockCompleted && aAction == LOCK_ACTION)
+ {
+ action_initiated = true;
+
+ new_state = kState_LockInitiated;
+ }
+
+ if (action_initiated)
+ {
+
+ StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
+
+ // Since the timer started successfully, update the state and trigger callback
+ mState = new_state;
+
+ if (mActionInitiated_CB)
+ {
+ mActionInitiated_CB(aAction, aActor);
+ }
+ }
+
+ return action_initiated;
+}
+
+void LockManager::StartTimer(uint32_t aTimeoutMs)
+{
+ if (xTimerIsTimerActive(sLockTimer))
+ {
+ SILABS_LOG("app timer already started!");
+ CancelTimer();
+ }
+
+ // timer is not active, change its period to required value (== restart).
+ // FreeRTOS- Block for a maximum of 100 ticks if the change period command
+ // cannot immediately be sent to the timer command queue.
+ if (xTimerChangePeriod(sLockTimer, (aTimeoutMs / portTICK_PERIOD_MS), 100) != pdPASS)
+ {
+ SILABS_LOG("sLockTimer timer start() failed");
+ appError(APP_ERROR_START_TIMER_FAILED);
+ }
+}
+
+void LockManager::CancelTimer(void)
+{
+ if (xTimerStop(sLockTimer, 0) == pdFAIL)
+ {
+ SILABS_LOG("sLockTimer stop() failed");
+ appError(APP_ERROR_STOP_TIMER_FAILED);
+ }
+}
+
+void LockManager::TimerEventHandler(TimerHandle_t xTimer)
+{
+ // Get lock obj context from timer id.
+ LockManager * lock = static_cast(pvTimerGetTimerID(xTimer));
+
+ // The timer event handler will be called in the context of the timer task
+ // once sLockTimer expires. Post an event to apptask queue with the actual handler
+ // so that the event can be handled in the context of the apptask.
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.Context = lock;
+ event.Handler = ActuatorMovementTimerEventHandler;
+ AppTask::GetAppTask().PostEvent(&event);
+}
+
+void LockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
+{
+ Action_t actionCompleted = INVALID_ACTION;
+
+ LockManager * lock = static_cast(aEvent->TimerEvent.Context);
+
+ if (lock->mState == kState_LockInitiated)
+ {
+ lock->mState = kState_LockCompleted;
+ actionCompleted = LOCK_ACTION;
+ }
+ else if (lock->mState == kState_UnlockInitiated)
+ {
+ lock->mState = kState_UnlockCompleted;
+ actionCompleted = UNLOCK_ACTION;
+ }
+
+ if (actionCompleted != INVALID_ACTION)
+ {
+ if (lock->mActionCompleted_CB)
+ {
+ lock->mActionCompleted_CB(actionCompleted);
+ }
+ }
+}
+
+bool LockManager::Lock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err)
+{
+ return setLockState(endpointId, DlLockState::kLocked, pin, err);
+}
+
+bool LockManager::Unlock(chip::EndpointId endpointId, const Optional & pin, DlOperationError & err)
+{
+ return setLockState(endpointId, DlLockState::kUnlocked, pin, err);
+}
+
+bool LockManager::GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
+{
+ VerifyOrReturnValue(userIndex > 0, false); // indices are one-indexed
+
+ userIndex--;
+
+ VerifyOrReturnValue(IsValidUserIndex(userIndex), false);
+
+ ChipLogProgress(Zcl, "Door Lock App: LockManager::GetUser [endpoint=%d,userIndex=%hu]", endpointId, userIndex);
+
+ const auto & userInDb = mLockUsers[userIndex];
+
+ user.userStatus = userInDb.userStatus;
+ if (DlUserStatus::kAvailable == user.userStatus)
+ {
+ ChipLogDetail(Zcl, "Found unoccupied user [endpoint=%d]", endpointId);
+ return true;
+ }
+
+ user.userName = chip::CharSpan(userInDb.userName.data(), userInDb.userName.size());
+ user.credentials = chip::Span(mCredentials[userIndex], userInDb.credentials.size());
+ user.userUniqueId = userInDb.userUniqueId;
+ user.userType = userInDb.userType;
+ user.credentialRule = userInDb.credentialRule;
+ // So far there's no way to actually create the credential outside Matter, so here we always set the creation/modification
+ // source to Matter
+ user.creationSource = DlAssetSource::kMatterIM;
+ user.createdBy = userInDb.createdBy;
+ user.modificationSource = DlAssetSource::kMatterIM;
+ user.lastModifiedBy = userInDb.lastModifiedBy;
+
+ ChipLogDetail(Zcl,
+ "Found occupied user "
+ "[endpoint=%d,name=\"%.*s\",credentialsCount=%u,uniqueId=%lx,type=%u,credentialRule=%u,"
+ "createdBy=%d,lastModifiedBy=%d]",
+ endpointId, static_cast(user.userName.size()), user.userName.data(), user.credentials.size(),
+ user.userUniqueId, to_underlying(user.userType), to_underlying(user.credentialRule), user.createdBy,
+ user.lastModifiedBy);
+
+ return true;
+}
+
+bool LockManager::SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier,
+ const chip::CharSpan & userName, uint32_t uniqueId, DlUserStatus userStatus, DlUserType usertype,
+ DlCredentialRule credentialRule, const DlCredential * credentials, size_t totalCredentials)
+{
+ ChipLogProgress(Zcl,
+ "Door Lock App: LockManager::SetUser "
+ "[endpoint=%d,userIndex=%d,creator=%d,modifier=%d,userName=%s,uniqueId=%ld "
+ "userStatus=%u,userType=%u,credentialRule=%u,credentials=%p,totalCredentials=%u]",
+ endpointId, userIndex, creator, modifier, userName.data(), uniqueId, to_underlying(userStatus),
+ to_underlying(usertype), to_underlying(credentialRule), credentials, totalCredentials);
+
+ VerifyOrReturnValue(userIndex > 0, false); // indices are one-indexed
+
+ userIndex--;
+
+ VerifyOrReturnValue(IsValidUserIndex(userIndex), false);
+
+ auto & userInStorage = mLockUsers[userIndex];
+
+ if (userName.size() > DOOR_LOCK_MAX_USER_NAME_SIZE)
+ {
+ ChipLogError(Zcl, "Cannot set user - user name is too long [endpoint=%d,index=%d]", endpointId, userIndex);
+ return false;
+ }
+
+ if (totalCredentials > LockParams.numberOfCredentialsPerUser)
+ {
+ ChipLogError(Zcl, "Cannot set user - total number of credentials is too big [endpoint=%d,index=%d,totalCredentials=%u]",
+ endpointId, userIndex, totalCredentials);
+ return false;
+ }
+
+ chip::Platform::CopyString(mUserNames[userIndex], userName);
+ userInStorage.userName = chip::CharSpan(mUserNames[userIndex], userName.size());
+ userInStorage.userUniqueId = uniqueId;
+ userInStorage.userStatus = userStatus;
+ userInStorage.userType = usertype;
+ userInStorage.credentialRule = credentialRule;
+ userInStorage.lastModifiedBy = modifier;
+ userInStorage.createdBy = creator;
+
+ for (size_t i = 0; i < totalCredentials; ++i)
+ {
+ mCredentials[userIndex][i] = credentials[i];
+ mCredentials[userIndex][i].CredentialType = 1;
+ mCredentials[userIndex][i].CredentialIndex = i + 1;
+ }
+
+ userInStorage.credentials = chip::Span(mCredentials[userIndex], totalCredentials);
+
+ // Save user information in NVM flash
+ SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_LockUser, reinterpret_cast(&mLockUsers),
+ sizeof(EmberAfPluginDoorLockUserInfo) * LockParams.numberOfUsers);
+
+ SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_UserCredentials, reinterpret_cast(mCredentials),
+ sizeof(DlCredential) * LockParams.numberOfUsers * LockParams.numberOfCredentialsPerUser);
+
+ SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_LockUserName, reinterpret_cast(mUserNames),
+ sizeof(mUserNames));
+
+ ChipLogProgress(Zcl, "Successfully set the user [mEndpointId=%d,index=%d]", endpointId, userIndex);
+
+ return true;
+}
+
+bool LockManager::GetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType,
+ EmberAfPluginDoorLockCredentialInfo & credential)
+{
+
+ if (DlCredentialType::kProgrammingPIN == credentialType)
+ {
+ VerifyOrReturnValue(IsValidCredentialIndex(credentialIndex, credentialType),
+ false); // programming pin index is only index allowed to contain 0
+ }
+ else
+ {
+ VerifyOrReturnValue(IsValidCredentialIndex(--credentialIndex, credentialType), false); // otherwise, indices are one-indexed
+ }
+
+ ChipLogProgress(Zcl, "Lock App: LockManager::GetCredential [credentialType=%u], credentialIndex=%d",
+ to_underlying(credentialType), credentialIndex);
+
+ const auto & credentialInStorage = mLockCredentials[credentialIndex];
+
+ credential.status = credentialInStorage.status;
+ ChipLogDetail(Zcl, "CredentialStatus: %d, CredentialIndex: %d ", (int) credential.status, credentialIndex);
+
+ if (DlCredentialStatus::kAvailable == credential.status)
+ {
+ ChipLogDetail(Zcl, "Found unoccupied credential ");
+ return true;
+ }
+ credential.credentialType = credentialInStorage.credentialType;
+ credential.credentialData = credentialInStorage.credentialData;
+ credential.createdBy = credentialInStorage.createdBy;
+ credential.lastModifiedBy = credentialInStorage.lastModifiedBy;
+ // So far there's no way to actually create the credential outside Matter, so here we always set the creation/modification
+ // source to Matter
+ credential.creationSource = DlAssetSource::kMatterIM;
+ credential.modificationSource = DlAssetSource::kMatterIM;
+
+ ChipLogDetail(Zcl, "Found occupied credential [type=%u,dataSize=%u]", to_underlying(credential.credentialType),
+ credential.credentialData.size());
+
+ return true;
+}
+
+bool LockManager::SetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, chip::FabricIndex creator,
+ chip::FabricIndex modifier, DlCredentialStatus credentialStatus, DlCredentialType credentialType,
+ const chip::ByteSpan & credentialData)
+{
+
+ if (DlCredentialType::kProgrammingPIN == credentialType)
+ {
+ VerifyOrReturnValue(IsValidCredentialIndex(credentialIndex, credentialType),
+ false); // programming pin index is only index allowed to contain 0
+ }
+ else
+ {
+ VerifyOrReturnValue(IsValidCredentialIndex(--credentialIndex, credentialType), false); // otherwise, indices are one-indexed
+ }
+
+ ChipLogProgress(Zcl,
+ "Door Lock App: LockManager::SetCredential "
+ "[credentialStatus=%u,credentialType=%u,credentialDataSize=%u,creator=%d,modifier=%d]",
+ to_underlying(credentialStatus), to_underlying(credentialType), credentialData.size(), creator, modifier);
+
+ auto & credentialInStorage = mLockCredentials[credentialIndex];
+
+ credentialInStorage.status = credentialStatus;
+ credentialInStorage.credentialType = credentialType;
+ credentialInStorage.createdBy = creator;
+ credentialInStorage.lastModifiedBy = modifier;
+
+ memcpy(mCredentialData[credentialIndex], credentialData.data(), credentialData.size());
+ credentialInStorage.credentialData = chip::ByteSpan{ mCredentialData[credentialIndex], credentialData.size() };
+
+ // Save credential information in NVM flash
+ SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_Credential, reinterpret_cast(&mLockCredentials),
+ sizeof(EmberAfPluginDoorLockCredentialInfo) * LockParams.numberOfCredentialsPerUser);
+
+ SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_CredentialData, reinterpret_cast(&mCredentialData),
+ sizeof(mCredentialData));
+
+ ChipLogProgress(Zcl, "Successfully set the credential [credentialType=%u]", to_underlying(credentialType));
+
+ return true;
+}
+
+DlStatus LockManager::GetWeekdaySchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex,
+ EmberAfPluginDoorLockWeekDaySchedule & schedule)
+{
+
+ VerifyOrReturnValue(weekdayIndex > 0, DlStatus::kFailure); // indices are one-indexed
+ VerifyOrReturnValue(userIndex > 0, DlStatus::kFailure); // indices are one-indexed
+
+ weekdayIndex--;
+ userIndex--;
+
+ VerifyOrReturnValue(IsValidWeekdayScheduleIndex(weekdayIndex), DlStatus::kFailure);
+ VerifyOrReturnValue(IsValidUserIndex(userIndex), DlStatus::kFailure);
+
+ const auto & scheduleInStorage = mWeekdaySchedule[userIndex][weekdayIndex];
+ if (DlScheduleStatus::kAvailable == scheduleInStorage.status)
+ {
+ return DlStatus::kNotFound;
+ }
+
+ schedule = scheduleInStorage.schedule;
+
+ return DlStatus::kSuccess;
+}
+
+DlStatus LockManager::SetWeekdaySchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex,
+ DlScheduleStatus status, DlDaysMaskMap daysMask, uint8_t startHour, uint8_t startMinute,
+ uint8_t endHour, uint8_t endMinute)
+{
+
+ VerifyOrReturnValue(weekdayIndex > 0, DlStatus::kFailure); // indices are one-indexed
+ VerifyOrReturnValue(userIndex > 0, DlStatus::kFailure); // indices are one-indexed
+
+ weekdayIndex--;
+ userIndex--;
+
+ VerifyOrReturnValue(IsValidWeekdayScheduleIndex(weekdayIndex), DlStatus::kFailure);
+ VerifyOrReturnValue(IsValidUserIndex(userIndex), DlStatus::kFailure);
+
+ auto & scheduleInStorage = mWeekdaySchedule[userIndex][weekdayIndex];
+
+ scheduleInStorage.schedule.daysMask = daysMask;
+ scheduleInStorage.schedule.startHour = startHour;
+ scheduleInStorage.schedule.startMinute = startMinute;
+ scheduleInStorage.schedule.endHour = endHour;
+ scheduleInStorage.schedule.endMinute = endMinute;
+ scheduleInStorage.status = status;
+
+ // Save schedule information in NVM flash
+ SILABSConfig::WriteConfigValueBin(
+ SILABSConfig::kConfigKey_WeekDaySchedules, reinterpret_cast(mWeekdaySchedule),
+ sizeof(EmberAfPluginDoorLockWeekDaySchedule) * LockParams.numberOfWeekdaySchedulesPerUser * LockParams.numberOfUsers);
+
+ return DlStatus::kSuccess;
+}
+
+DlStatus LockManager::GetYeardaySchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex,
+ EmberAfPluginDoorLockYearDaySchedule & schedule)
+{
+ VerifyOrReturnValue(yearDayIndex > 0, DlStatus::kFailure); // indices are one-indexed
+ VerifyOrReturnValue(userIndex > 0, DlStatus::kFailure); // indices are one-indexed
+
+ yearDayIndex--;
+ userIndex--;
+
+ VerifyOrReturnValue(IsValidYeardayScheduleIndex(yearDayIndex), DlStatus::kFailure);
+ VerifyOrReturnValue(IsValidUserIndex(userIndex), DlStatus::kFailure);
+
+ const auto & scheduleInStorage = mYeardaySchedule[userIndex][yearDayIndex];
+ if (DlScheduleStatus::kAvailable == scheduleInStorage.status)
+ {
+ return DlStatus::kNotFound;
+ }
+
+ schedule = scheduleInStorage.schedule;
+
+ return DlStatus::kSuccess;
+}
+
+DlStatus LockManager::SetYeardaySchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex,
+ DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime)
+{
+ VerifyOrReturnValue(yearDayIndex > 0, DlStatus::kFailure); // indices are one-indexed
+ VerifyOrReturnValue(userIndex > 0, DlStatus::kFailure); // indices are one-indexed
+
+ yearDayIndex--;
+ userIndex--;
+
+ VerifyOrReturnValue(IsValidYeardayScheduleIndex(yearDayIndex), DlStatus::kFailure);
+ VerifyOrReturnValue(IsValidUserIndex(userIndex), DlStatus::kFailure);
+
+ auto & scheduleInStorage = mYeardaySchedule[userIndex][yearDayIndex];
+
+ scheduleInStorage.schedule.localStartTime = localStartTime;
+ scheduleInStorage.schedule.localEndTime = localEndTime;
+ scheduleInStorage.status = status;
+
+ // Save schedule information in NVM flash
+ SILABSConfig::WriteConfigValueBin(
+ SILABSConfig::kConfigKey_YearDaySchedules, reinterpret_cast(mYeardaySchedule),
+ sizeof(EmberAfPluginDoorLockYearDaySchedule) * LockParams.numberOfYeardaySchedulesPerUser * LockParams.numberOfUsers);
+
+ return DlStatus::kSuccess;
+}
+
+DlStatus LockManager::GetHolidaySchedule(chip::EndpointId endpointId, uint8_t holidayIndex,
+ EmberAfPluginDoorLockHolidaySchedule & schedule)
+{
+ VerifyOrReturnValue(holidayIndex > 0, DlStatus::kFailure); // indices are one-indexed
+
+ holidayIndex--;
+
+ VerifyOrReturnValue(IsValidHolidayScheduleIndex(holidayIndex), DlStatus::kFailure);
+
+ const auto & scheduleInStorage = mHolidaySchedule[holidayIndex];
+ if (DlScheduleStatus::kAvailable == scheduleInStorage.status)
+ {
+ return DlStatus::kNotFound;
+ }
+
+ schedule = scheduleInStorage.schedule;
+
+ return DlStatus::kSuccess;
+}
+
+DlStatus LockManager::SetHolidaySchedule(chip::EndpointId endpointId, uint8_t holidayIndex, DlScheduleStatus status,
+ uint32_t localStartTime, uint32_t localEndTime, DlOperatingMode operatingMode)
+{
+ VerifyOrReturnValue(holidayIndex > 0, DlStatus::kFailure); // indices are one-indexed
+
+ holidayIndex--;
+
+ VerifyOrReturnValue(IsValidHolidayScheduleIndex(holidayIndex), DlStatus::kFailure);
+
+ auto & scheduleInStorage = mHolidaySchedule[holidayIndex];
+
+ scheduleInStorage.schedule.localStartTime = localStartTime;
+ scheduleInStorage.schedule.localEndTime = localEndTime;
+ scheduleInStorage.schedule.operatingMode = operatingMode;
+ scheduleInStorage.status = status;
+
+ // Save schedule information in NVM flash
+ SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_HolidaySchedules,
+ reinterpret_cast(&(mHolidaySchedule)),
+ sizeof(EmberAfPluginDoorLockHolidaySchedule) * LockParams.numberOfHolidaySchedules);
+
+ return DlStatus::kSuccess;
+}
+
+const char * LockManager::lockStateToString(DlLockState lockState) const
+{
+ switch (lockState)
+ {
+ case DlLockState::kNotFullyLocked:
+ return "Not Fully Locked";
+ case DlLockState::kLocked:
+ return "Locked";
+ case DlLockState::kUnlocked:
+ return "Unlocked";
+ case DlLockState::kUnknownEnumValue:
+ break;
+ }
+
+ return "Unknown";
+}
+
+bool LockManager::setLockState(chip::EndpointId endpointId, DlLockState lockState, const Optional & pin,
+ DlOperationError & err)
+{
+
+ // Assume pin is required until told otherwise
+ bool requirePin = true;
+ chip::app::Clusters::DoorLock::Attributes::RequirePINforRemoteOperation::Get(endpointId, &requirePin);
+
+ // If a pin code is not given
+ if (!pin.HasValue())
+ {
+ ChipLogDetail(Zcl, "Door Lock App: PIN code is not specified [endpointId=%d]", endpointId);
+
+ // If a pin code is not required
+ if (!requirePin)
+ {
+ ChipLogDetail(Zcl, "Door Lock App: setting door lock state to \"%s\" [endpointId=%d]", lockStateToString(lockState),
+ endpointId);
+
+ DoorLockServer::Instance().SetLockState(endpointId, lockState);
+
+ return true;
+ }
+
+ ChipLogError(Zcl, "Door Lock App: PIN code is not specified, but it is required [endpointId=%d]", endpointId);
+
+ return false;
+ }
+
+ // Check the PIN code
+ for (uint8_t i = 0; i < kMaxCredentials; i++)
+ {
+ if (mLockCredentials[i].credentialType != DlCredentialType::kPin ||
+ mLockCredentials[i].status == DlCredentialStatus::kAvailable)
+ {
+ continue;
+ }
+
+ if (mLockCredentials[i].credentialData.data_equal(pin.Value()))
+ {
+ ChipLogDetail(Zcl,
+ "Lock App: specified PIN code was found in the database, setting lock state to \"%s\" [endpointId=%d]",
+ lockStateToString(lockState), endpointId);
+
+ DoorLockServer::Instance().SetLockState(endpointId, lockState);
+
+ return true;
+ }
+ }
+
+ ChipLogDetail(Zcl,
+ "Door Lock App: specified PIN code was not found in the database, ignoring command to set lock state to \"%s\" "
+ "[endpointId=%d]",
+ lockStateToString(lockState), endpointId);
+
+ err = DlOperationError::kInvalidCredential;
+ return false;
+}
diff --git a/examples/lock-app/silabs/SiWx917/src/ZclCallbacks.cpp b/examples/lock-app/silabs/SiWx917/src/ZclCallbacks.cpp
new file mode 100644
index 00000000000000..9c1812a90c0a04
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/src/ZclCallbacks.cpp
@@ -0,0 +1,156 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * This file implements the handler for data model messages.
+ */
+
+#include "AppConfig.h"
+#include "LockManager.h"
+#include
+
+#include
+#include
+#include
+#include
+
+using namespace ::chip::app::Clusters;
+using namespace ::chip::DeviceLayer::Internal;
+
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
+ uint8_t * value)
+{
+ ClusterId clusterId = attributePath.mClusterId;
+ AttributeId attributeId = attributePath.mAttributeId;
+ ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));
+
+ if (clusterId == DoorLock::Id && attributeId == DoorLock::Attributes::LockState::Id)
+ {
+ DoorLock::DlLockState lockState = *(reinterpret_cast(value));
+ ChipLogProgress(Zcl, "Door lock cluster: " ChipLogFormatMEI " state %d", ChipLogValueMEI(clusterId),
+ to_underlying(lockState));
+ }
+}
+
+/** @brief DoorLock Cluster Init
+ *
+ * This function is called when a specific cluster is initialized. It gives the
+ * application an opportunity to take care of cluster initialization procedures.
+ * It is called exactly once for each endpoint where cluster is present.
+ *
+ * @param endpoint Ver.: always
+ *
+ */
+void emberAfDoorLockClusterInitCallback(EndpointId endpoint) {}
+
+bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const Optional & pinCode, DlOperationError & err)
+{
+ ChipLogProgress(Zcl, "Door Lock App: Lock Command endpoint=%d", endpointId);
+ bool status = LockMgr().Lock(endpointId, pinCode, err);
+ if (status == true)
+ {
+ LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::LOCK_ACTION);
+ }
+ return status;
+}
+
+bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const Optional & pinCode,
+ DlOperationError & err)
+{
+ ChipLogProgress(Zcl, "Door Lock App: Unlock Command endpoint=%d", endpointId);
+ bool status = LockMgr().Unlock(endpointId, pinCode, err);
+ if (status == true)
+ {
+ LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION);
+ }
+
+ return status;
+}
+
+bool emberAfPluginDoorLockGetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, DlCredentialType credentialType,
+ EmberAfPluginDoorLockCredentialInfo & credential)
+{
+ return LockMgr().GetCredential(endpointId, credentialIndex, credentialType, credential);
+}
+
+bool emberAfPluginDoorLockSetCredential(chip::EndpointId endpointId, uint16_t credentialIndex, chip::FabricIndex creator,
+ chip::FabricIndex modifier, DlCredentialStatus credentialStatus,
+ DlCredentialType credentialType, const chip::ByteSpan & credentialData)
+{
+ return LockMgr().SetCredential(endpointId, credentialIndex, creator, modifier, credentialStatus, credentialType,
+ credentialData);
+}
+
+bool emberAfPluginDoorLockGetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user)
+{
+ return LockMgr().GetUser(endpointId, userIndex, user);
+}
+
+bool emberAfPluginDoorLockSetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator,
+ chip::FabricIndex modifier, const chip::CharSpan & userName, uint32_t uniqueId,
+ DlUserStatus userStatus, DlUserType usertype, DlCredentialRule credentialRule,
+ const DlCredential * credentials, size_t totalCredentials)
+{
+
+ return LockMgr().SetUser(endpointId, userIndex, creator, modifier, userName, uniqueId, userStatus, usertype, credentialRule,
+ credentials, totalCredentials);
+}
+
+DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex,
+ EmberAfPluginDoorLockWeekDaySchedule & schedule)
+{
+ return LockMgr().GetWeekdaySchedule(endpointId, weekdayIndex, userIndex, schedule);
+}
+
+DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex,
+ EmberAfPluginDoorLockYearDaySchedule & schedule)
+{
+ return LockMgr().GetYeardaySchedule(endpointId, yearDayIndex, userIndex, schedule);
+}
+
+DlStatus emberAfPluginDoorLockGetSchedule(chip::EndpointId endpointId, uint8_t holidayIndex,
+ EmberAfPluginDoorLockHolidaySchedule & holidaySchedule)
+{
+ return LockMgr().GetHolidaySchedule(endpointId, holidayIndex, holidaySchedule);
+}
+
+DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t weekdayIndex, uint16_t userIndex,
+ DlScheduleStatus status, DlDaysMaskMap daysMask, uint8_t startHour, uint8_t startMinute,
+ uint8_t endHour, uint8_t endMinute)
+{
+ return LockMgr().SetWeekdaySchedule(endpointId, weekdayIndex, userIndex, status, daysMask, startHour, startMinute, endHour,
+ endMinute);
+}
+
+DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t yearDayIndex, uint16_t userIndex,
+ DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime)
+{
+ return LockMgr().SetYeardaySchedule(endpointId, yearDayIndex, userIndex, status, localStartTime, localEndTime);
+}
+
+DlStatus emberAfPluginDoorLockSetSchedule(chip::EndpointId endpointId, uint8_t holidayIndex, DlScheduleStatus status,
+ uint32_t localStartTime, uint32_t localEndTime, DlOperatingMode operatingMode)
+{
+ return LockMgr().SetHolidaySchedule(endpointId, holidayIndex, status, localStartTime, localEndTime, operatingMode);
+}
+
+void emberAfPluginDoorLockOnAutoRelock(chip::EndpointId endpointId)
+{
+ // Apply the relock state in the application control
+ LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::LOCK_ACTION);
+}
diff --git a/examples/lock-app/silabs/SiWx917/src/main.cpp b/examples/lock-app/silabs/SiWx917/src/main.cpp
new file mode 100644
index 00000000000000..c3cbf82681bfdc
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/src/main.cpp
@@ -0,0 +1,85 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#include "AppConfig.h"
+#include "init_ccpPlatform.h"
+#include
+#include
+#include
+#include
+#ifdef EFR32_ATTESTATION_CREDENTIALS
+#include
+#else
+#include
+#endif
+
+#define BLE_DEV_NAME "SiLabs-Door-Lock"
+extern "C" void sl_button_on_change();
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::Credentials;
+
+#define UNUSED_PARAMETER(a) (a = a)
+
+volatile int apperror_cnt;
+static chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+
+// ================================================================================
+// Main Code
+// ================================================================================
+int main(void)
+{
+ init_ccpPlatform();
+
+ if (SI917MatterConfig::InitMatter(BLE_DEV_NAME) != CHIP_NO_ERROR)
+ appError(CHIP_ERROR_INTERNAL);
+
+ gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage());
+ chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ // Initialize device attestation config
+#ifdef SI917_ATTESTATION_CREDENTIALS
+ SetDeviceAttestationCredentialsProvider(SI917::GetSI917DacProvider());
+#else
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ SILABS_LOG("Starting App Task");
+ if (AppTask::GetAppTask().StartAppTask() != CHIP_NO_ERROR)
+ appError(CHIP_ERROR_INTERNAL);
+
+ SILABS_LOG("Starting FreeRTOS scheduler");
+ vTaskStartScheduler();
+
+ // Should never get here.
+ chip::Platform::MemoryShutdown();
+ SILABS_LOG("vTaskStartScheduler() failed");
+ appError(CHIP_ERROR_INTERNAL);
+}
+
+void sl_button_on_change()
+{
+ AppTask::GetAppTask().ButtonEventHandler(APP_FUNCTION_BUTTON, SL_SIMPLE_BUTTON_PRESSED);
+}
diff --git a/examples/lock-app/silabs/SiWx917/third_party/connectedhomeip b/examples/lock-app/silabs/SiWx917/third_party/connectedhomeip
new file mode 120000
index 00000000000000..59307833b4fee9
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../../..
\ No newline at end of file
diff --git a/examples/lock-app/silabs/SiWx917/with_pw_rpc.gni b/examples/lock-app/silabs/SiWx917/with_pw_rpc.gni
new file mode 100644
index 00000000000000..faa281a6a4597c
--- /dev/null
+++ b/examples/lock-app/silabs/SiWx917/with_pw_rpc.gni
@@ -0,0 +1,32 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# add this gni as import in your build args to use pigweed in the example
+# 'import("//with_pw_rpc.gni")'
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/efr32/lib/pw_rpc/pw_rpc.gni")
+import("${chip_root}/examples/platform/silabs/efr32/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_pw_rpc = true
+chip_enable_openthread = true
+chip_openthread_ftd = true
+
+cpp_standard = "gnu++17"
+
+# To fit in flash
+chip_detail_logging = false
+show_qr_code = false
diff --git a/examples/platform/silabs/SiWx917/matter_config.cpp b/examples/platform/silabs/SiWx917/matter_config.cpp
index caa6a34b218482..e34c1fc180ed4f 100644
--- a/examples/platform/silabs/SiWx917/matter_config.cpp
+++ b/examples/platform/silabs/SiWx917/matter_config.cpp
@@ -57,7 +57,7 @@ using namespace ::chip::DeviceLayer;
#include "SiWx917DeviceDataProvider.h"
#if EFR32_OTA_ENABLED
-void EFR32MatterConfig::InitOTARequestorHandler(System::Layer * systemLayer, void * appState)
+void SI917MatterConfig::InitOTARequestorHandler(System::Layer * systemLayer, void * appState)
{
#if 0 // TODO : OTA is not planned now for CCP
OTAConfig::Init();
diff --git a/examples/window-app/silabs/SiWx917/.gn b/examples/window-app/silabs/SiWx917/.gn
new file mode 100644
index 00000000000000..4c078f6acefdcc
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/.gn
@@ -0,0 +1,29 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_openthread_ftd = true
+
+ import("//args.gni")
+}
diff --git a/examples/window-app/silabs/SiWx917/BUILD.gn b/examples/window-app/silabs/SiWx917/BUILD.gn
new file mode 100644
index 00000000000000..5aea21172c38f0
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/BUILD.gn
@@ -0,0 +1,336 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${build_root}/config/defaults.gni")
+import("${chip_root}/src/platform/device.gni")
+import("${efr32_sdk_build_root}/SiWx917_sdk.gni")
+import("${efr32_sdk_build_root}/efr32_executable.gni")
+
+assert(current_os == "freertos")
+
+project_dir = "${chip_root}/examples/window-app"
+efr32_project_dir = "${project_dir}/silabs/SiWx917"
+examples_plat_dir = "${chip_root}/examples/platform/silabs/SiWx917"
+examples_common_plat_dir = "${chip_root}/examples/platform/silabs"
+
+declare_args() {
+ # Dump memory usage at link time.
+ chip_print_memory_usage = false
+
+ # Monitor & log memory usage at runtime.
+ enable_heap_monitoring = false
+
+ # Enable Sleepy end device
+ enable_sleepy_device = false
+
+ # OTA timeout in seconds
+ OTA_periodic_query_timeout = 86400
+
+ # Wifi related stuff - they are overridden by gn -args="use_wf200=true"
+ use_wf200 = false
+ use_rs911x = false
+ use_rs911x_sockets = false
+ sl_wfx_config_softap = false
+ sl_wfx_config_scan = true
+
+ # Disable LCD on supported devices
+ disable_lcd = true
+
+ # Argument to Disable IPv4 for wifi(rs911)
+ chip_enable_wifi_ipv4 = false
+
+ # Argument to force enable WPA3 security
+ rs91x_wpa3_only = false
+
+ #default WiFi SSID
+ chip_default_wifi_ssid = ""
+
+ #default Wifi Password
+ chip_default_wifi_psk = ""
+}
+
+declare_args() {
+ # Enables LCD Qr Code on supported devices
+ show_qr_code = !disable_lcd
+}
+
+# qr code cannot be true if lcd is disabled
+assert(!(disable_lcd && show_qr_code))
+
+# Sanity check
+assert(!(chip_enable_wifi && chip_enable_openthread))
+assert(!(use_rs911x && chip_enable_openthread))
+assert(!(use_wf200 && chip_enable_openthread))
+if (chip_enable_wifi) {
+ assert(use_rs911x || use_wf200)
+ enable_openthread_cli = false
+ import("${chip_root}/src/platform/silabs/SiWx917/wifi_args.gni")
+}
+
+# ThunderBoards, Explorer Kit and MGM240L do not support LCD (No LCD)
+if (silabs_board == "BRD4166A" || silabs_board == "BRD2601B" ||
+ silabs_board == "BRD2703A" || silabs_board == "BRD4319A") {
+ show_qr_code = false
+ disable_lcd = true
+}
+
+defines = []
+
+# WiFi settings
+if (chip_enable_wifi) {
+ # disabling LCD for MG24 for wifi
+ if (silabs_board == "BRD4186C" || silabs_board == "BRD4187C") {
+ show_qr_code = false
+ disable_lcd = true
+ }
+ if (chip_default_wifi_ssid != "") {
+ defines += [
+ "CHIP_ONNETWORK_PAIRING=1",
+ "CHIP_WIFI_SSID=\"${chip_default_wifi_ssid}\"",
+ ]
+ }
+ if (chip_default_wifi_psk != "") {
+ assert(chip_default_wifi_ssid != "",
+ "ssid can't be null if psk is provided")
+ defines += [ "CHIP_WIFI_PSK=\"${chip_default_wifi_psk}\"" ]
+ }
+ wifi_sdk_dir = "${chip_root}/src/platform/silabs/SiWx917/wifi"
+ efr32_lwip_defs = [ "LWIP_NETIF_API=1" ]
+ if (lwip_ipv4) {
+ efr32_lwip_defs += [
+ "LWIP_IPV4=1",
+
+ # adds following options to provide
+ # them to .cpp source files
+ # flags ported from lwipopts file
+ # TODO: move lwipopts to one location
+ "LWIP_ARP=1",
+ "LWIP_ICMP=1",
+ "LWIP_IGMP=1",
+ "LWIP_DHCP=1",
+ "LWIP_DNS=0",
+ ]
+ } else {
+ efr32_lwip_defs += [ "LWIP_IPV4=0" ]
+ }
+ if (lwip_ipv6) {
+ efr32_lwip_defs += [ "LWIP_IPV6=1" ]
+ } else {
+ efr32_lwip_defs += [ "LWIP_IPV6=0" ]
+ }
+
+ wiseconnect_sdk_root = "${chip_root}/third_party/silabs/wisemcu-wifi-bt-sdk"
+ import("${examples_plat_dir}/SiWx917/rs911x.gni")
+}
+
+efr32_sdk("sdk") {
+ sources = [
+ "${efr32_project_dir}/include/CHIPProjectConfig.h",
+ "${examples_plat_dir}/FreeRTOSConfig.h",
+ ]
+
+ include_dirs = [
+ "${chip_root}/src/platform/silabs/SiWx917",
+ "${efr32_project_dir}/include",
+ "${examples_plat_dir}",
+ "${chip_root}/src/lib",
+ "${examples_common_plat_dir}",
+ ]
+
+ defines += [
+ "BOARD_ID=${silabs_board}",
+ "OTA_PERIODIC_TIMEOUT=${OTA_periodic_query_timeout}",
+ ]
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ if (use_rs911x) {
+ defines += rs911x_defs
+ include_dirs += rs911x_plat_incs
+ } else if (use_wf200) {
+ defines += wf200_defs
+ include_dirs += wf200_plat_incs
+ }
+
+ if (use_rs911x_sockets) {
+ include_dirs += [ "${examples_plat_dir}/wifi/rsi-sockets" ]
+ defines += rs911x_sock_defs
+ } else {
+ # Using LWIP instead of the native TCP/IP stack
+ defines += efr32_lwip_defs
+ }
+
+ if (sl_wfx_config_softap) {
+ defines += [ "SL_WFX_CONFIG_SOFTAP" ]
+ }
+ if (sl_wfx_config_scan) {
+ defines += [ "SL_WFX_CONFIG_SCAN" ]
+ }
+ }
+}
+
+efr32_executable("window_app") {
+ output_name = "chip-efr32-window-example.out"
+ public_configs = [ "${efr32_sdk_build_root}:silabs_config" ]
+ output_dir = root_out_dir
+ include_dirs = [
+ "include",
+ "${project_dir}/common/include",
+ ]
+ defines = []
+
+ sources = [
+ "${examples_common_plat_dir}/heap_4_silabs.c",
+ "${examples_plat_dir}/init_ccpPlatform.cpp",
+ "${examples_plat_dir}/matter_config.cpp",
+ "${examples_plat_dir}/siwx917_utils.cpp",
+ "${project_dir}/common/src/WindowApp.cpp",
+ "${project_dir}/common/src/ZclCallbacks.cpp",
+ "src/WindowAppImpl.cpp",
+ "src/main.cpp",
+ ]
+
+ if (use_wstk_leds) {
+ #sources += [ "${examples_plat_dir}/LEDWidget.cpp" ]
+ }
+
+ if (chip_build_libshell || enable_openthread_cli || use_wf200 || use_rs911x) {
+ #sources += [ "${examples_plat_dir}/uart.cpp" ]
+ }
+
+ deps = [
+ ":sdk",
+ "${chip_root}/examples/providers:device_info_provider",
+ "${chip_root}/examples/window-app/common:window-common",
+ "${chip_root}/src/lib",
+ "${chip_root}/src/setup_payload",
+ ]
+
+ # OpenThread Settings
+ if (chip_enable_openthread) {
+ deps += [
+ "${chip_root}/third_party/openthread:openthread",
+ "${chip_root}/third_party/openthread:openthread-platform",
+ "${examples_plat_dir}:efr-matter-shell",
+ ]
+ }
+
+ # if (chip_enable_ota_requestor) {
+ # defines += [ "EFR32_OTA_ENABLED" ]
+ # sources += [ "${examples_plat_dir}/OTAConfig.cpp" ]
+ # }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ if (use_rs911x) {
+ sources += rs911x_src_plat
+
+ # All the stuff from wiseconnect
+ sources += rs911x_src_sapi
+
+ # Apparently - the rsi library needs this (though we may not use use it)
+ sources += rs911x_src_sock
+ include_dirs += rs911x_inc_plat
+
+ if (use_rs911x_sockets) {
+ #
+ # Using native sockets inside RS911x
+ #
+ include_dirs += rs911x_sock_inc
+ } else {
+ #
+ # We use LWIP - not built-in sockets
+ #
+ sources += rs911x_src_lwip
+ }
+ } else if (use_wf200) {
+ sources += wf200_plat_src
+ include_dirs += wf200_plat_incs
+ }
+
+ if (chip_enable_wifi_ipv4) {
+ defines += [ "CHIP_DEVICE_CONFIG_ENABLE_IPV4" ]
+ }
+
+ if (rs91x_wpa3_only) {
+ # TODO: Change this macro once WF200 support is provided
+ defines += [ "WIFI_ENABLE_SECURITY_WPA3=1" ]
+ }
+ }
+
+ if (!disable_lcd) {
+ sources += [
+ "${examples_plat_dir}/display/demo-ui.c",
+ "${examples_plat_dir}/display/lcd.cpp",
+ "src/LcdPainter.cpp",
+ ]
+ include_dirs += [ "${examples_plat_dir}/display" ]
+ defines += [ "DISPLAY_ENABLED" ]
+
+ if (show_qr_code) {
+ deps += [ "${chip_root}/examples/common/QRCode" ]
+ defines += [ "QR_CODE_ENABLED" ]
+ }
+ }
+
+ if (enable_heap_monitoring) {
+ defines += [ "HEAP_MONITORING" ]
+
+ sources += [ "${examples_common_plat_dir}/MemMonitoring.cpp" ]
+ }
+
+ ldscript = "${examples_plat_dir}/ldscripts/${silabs_family}.ld"
+
+ inputs = [ ldscript ]
+
+ ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ]
+
+ if (chip_print_memory_usage) {
+ ldflags += [
+ "-Wl,--print-memory-usage",
+ "-fstack-usage",
+ ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ ldflags += [
+ "-Wl,--defsym",
+ "-Wl,SILABS_WIFI=1",
+ ]
+ }
+
+ # Attestation Credentials
+ if (chip_build_platform_attestation_credentials_provider) {
+ deps += [ "${examples_plat_dir}:SiWx917-attestation-credentials" ]
+ }
+
+ # Factory Data Provider
+ if (use_efr32_factory_data_provider) {
+ deps += [ "${examples_plat_dir}:efr32-factory-data-provider" ]
+ }
+}
+
+group("efr32") {
+ deps = [ ":window_app" ]
+}
+
+group("default") {
+ deps = [ ":efr32" ]
+}
diff --git a/examples/window-app/silabs/SiWx917/README.md b/examples/window-app/silabs/SiWx917/README.md
new file mode 100644
index 00000000000000..dda149285a8f91
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/README.md
@@ -0,0 +1,386 @@
+# Matter EFR32 Window Covering Example
+
+An example showing the use of CHIP on the Silicon Labs EFR32 MG12 and MG24.
+
+
+
+- [Matter EFR32 Window Covering Example](#matter-efr32-window-covering-example)
+ - [Introduction](#introduction)
+ - [Building](#building)
+ - [Flashing the Application](#flashing-the-application)
+ - [Viewing Logging Output](#viewing-logging-output)
+ - [Running the Complete Example](#running-the-complete-example)
+ - [Notes](#notes)
+ - [OTA Software Update](#ota-software-update)
+ - [Building options](#building-options)
+ - [Disabling logging](#disabling-logging)
+ - [Debug build / release build](#debug-build--release-build)
+ - [Disabling LCD](#disabling-lcd)
+ - [KVS maximum entry count](#kvs-maximum-entry-count)
+
+
+
+> **NOTE:** Silicon Laboratories now maintains a public matter GitHub repo with
+> frequent releases thoroughly tested and validated. Developers looking to
+> develop matter products with silabs hardware are encouraged to use our latest
+> release with added tools and documentation.
+> [Silabs Matter Github](https://github.com/SiliconLabs/matter/releases)
+
+
+
+## Introduction
+
+The EFR32 window-covering example provides a baseline demonstration of a Window
+Covering device, built using Matter and the Silicon Labs gecko SDK. It can be
+controlled by a Chip controller over an Openthread or Wifi network.
+
+The EFR32 device can be commissioned over Bluetooth Low Energy where the device
+and the Chip controller will exchange security information with the Rendez-vous
+procedure. In the case of Thread, the Thread Network credentials are provided to
+the EFR32 device which will then join the Thread network.
+
+If the LCD is enabled, the LCD on the Silabs WSTK shows a QR Code containing the
+needed commissioning information for the BLE connection and starting the
+Rendez-vous procedure. Once the device is commissioned, the displays shows a
+representation of the window covering state.
+
+The window-covering example is intended to serve both as a means to explore the
+workings of Matter as well as a template for creating real products based on the
+Silicon Labs platform.
+
+
+
+## Building
+
+- Download the
+ [Simplicity Commander](https://www.silabs.com/mcu/programming-options)
+ command line tool, and ensure that `commander` is your shell search path.
+ (For Mac OS X, `commander` is located inside
+ `Commander.app/Contents/MacOS/`.)
+
+- Download and install a suitable ARM gcc tool chain:
+ [GNU Arm Embedded Toolchain 9-2019-q4-major](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads)
+
+- Install some additional tools(likely already present for CHIP developers):
+
+ # Linux
+ $ sudo apt-get install git ninja-build
+
+ # Mac OS X
+ $ brew install ninja
+
+- Supported hardware:
+
+ - > For the latest supported hardware please refer to the
+ > [Hardware Requirements](https://github.com/SiliconLabs/matter/blob/latest/docs/silabs/general/HARDWARE_REQUIREMENTS.md)
+ > in the Silicon Labs Matter Github Repo
+
+ MG12 boards:
+
+ - BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+ 868MHz@19dBm
+ - BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+ - BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+ 915MHz@19dBm
+ - BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+ MG21 boards: Currently not supported due to RAM limitation.
+
+ - BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG24 boards :
+
+ - BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+ - BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+* Build the example application:
+
+ cd ~/connectedhomeip
+ ./scripts/examples/gn_efr32_example.sh ./examples/window-app/efr32/ ./out/window-app BRD4161A
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/connectedhomeip
+ $ rm -rf ./out/
+
+ OR use GN/Ninja directly
+
+ $ cd ~/connectedhomeip/examples/window-app/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug
+ $ ninja -C out/debug
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/connectedhomeip/examples/window-app/efr32
+ $ rm -rf out/
+
+* Build the example as Sleepy End Device (SED)
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/window-app/efr32/ ./out/window-app_SED BRD4161A --sed
+
+ or use gn as previously mentioned but adding the following arguments:
+
+ $ gn gen out/debug '--args=silabs_board="BRD4161A" enable_sleepy_device=true chip_openthread_ftd=false'
+
+* Build the example with pigweed RCP
+
+ $ ./scripts/examples/gn_efr32_example.sh examples/window-app/efr32/ out/window_app_rpc BRD4161A 'import("//with_pw_rpc.gni")'
+
+ or use GN/Ninja Directly
+
+ $ cd ~/connectedhomeip/examples/window-app/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug --args='import("//with_pw_rpc.gni")'
+ $ ninja -C out/debug
+
+ [Running Pigweed RPC console](#running-pigweed-rpc-console)
+
+For more build options, help is provided when running the build script without
+arguments
+
+ ./scripts/examples/gn_efr32_example.sh
+
+
+
+## Flashing the Application
+
+- On the command line:
+
+ $ cd ~/connectedhomeip/examples/window-app/efr32
+ $ python3 out/debug/chip-efr32-window-example.flash.py
+
+- Or with the Ozone debugger, just load the .out file.
+
+
+
+## Viewing Logging Output
+
+The example application is built to use the SEGGER Real Time Transfer (RTT)
+facility for log output. RTT is a feature built-in to the J-Link Interface MCU
+on the WSTK development board. It allows bi-directional communication with an
+embedded application without the need for a dedicated UART.
+
+Using the RTT facility requires downloading and installing the _SEGGER J-Link
+Software and Documentation Pack_
+([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)).
+
+Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too
+after flashing the .out file.
+
+- Download the J-Link installer by navigating to the appropriate URL and
+ agreeing to the license agreement.
+
+- [JLink_Linux_x86_64.deb](https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.deb)
+- [JLink_MacOSX.pkg](https://www.segger.com/downloads/jlink/JLink_MacOSX.pkg)
+
+* Install the J-Link software
+
+ $ cd ~/Downloads
+ $ sudo dpkg -i JLink_Linux_V*_x86_64.deb
+
+* In Linux, grant the logged in user the ability to talk to the development
+ hardware via the linux tty device (/dev/ttyACMx) by adding them to the
+ dialout group.
+
+ $ sudo usermod -a -G dialout ${USER}
+
+Once the above is complete, log output can be viewed using the JLinkExe tool in
+combination with JLinkRTTClient as follows:
+
+- Run the JLinkExe tool with arguments to autoconnect to the WSTK board:
+
+ For MG12 use:
+
+ $ JLinkExe -device EFR32MG12PXXXF1024 -if JTAG -speed 4000 -autoconnect 1
+
+ For MG21 use:
+
+ $ JLinkExe -device EFR32MG21AXXXF1024 -if SWD -speed 4000 -autoconnect 1
+
+- In a second terminal, run the JLinkRTTClient to view logs:
+
+ $ JLinkRTTClient
+
+
+
+## Running the Complete Example
+
+- It is assumed here that you already have an OpenThread border router
+ configured and running. If not see the following guide
+ [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md)
+ for more information on how to setup a border router on a raspberryPi.
+
+ Take note that the RCP code is available directly through
+ [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5)
+ under File->New->Project Wizard->Examples->Thread : ot-rcp
+
+- User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR
+ Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over
+ BLE
+
+ * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2,
+ a URL can be found in the RTT logs.
+
+ [SVR] Copy/paste the below URL in a browser to see the QR Code:
+ [SVR] https://project-chip.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0
+
+ **LED 0** shows the overall state of the device and its connectivity. The
+ following states are possible:
+
+ - _Short Flash On (50 ms on/950 ms off)_ ; The device is in the
+ unprovisioned (unpaired) state and is waiting for a commissioning
+ application to connect.
+
+ - _Rapid Even Flashing_ ; (100 ms on/100 ms off)_ — The device is in the
+ unprovisioned state and a commissioning application is connected through
+ Bluetooth LE.
+
+ - _Short Flash Off_ ; (950ms on/50ms off)_ — The device is fully
+ provisioned, but does not yet have full Thread network or service
+ connectivity.
+
+ - _Solid On_ ; The device is fully provisioned and has full Thread
+ network and service connectivity.
+
+ **LED 1** Shows the state of the window covering
+
+ - _Solid On_ ; The window cover if fully open
+ - _Off_ ; The window cover if fully closed
+ - _Blinking slowly_ ; The window cover is half-open, either by tilt, or lift
+ - _Blinking quickly_ ; The window cover is being automatically open or closed
+
+ **Push Button 0** Increase either tilt or lift, and factory reset
+
+ - Pressed and release: The lift/tilt increases by 10%
+
+ - Pressed and hold for 6 s: Initiates the factory reset of the device.
+ Releasing the button within the 6-second window cancels the factory reset
+ procedure. **LEDs** blink in unison when the factory reset procedure is
+ initiated.
+
+ **Push Button 1** Decreases either tilt or lift, or switch the cover type
+
+ - Pressed and release: The lift/tilt decreases by 10%
+
+ - Press and hold for 3 s: Cycle between window covering type (Rollershade, Drapery, Tilt Blind - Lift and Tilt).
+
+ **Push Button0 and Button1** Switch between lift and tilt
+
+ - Pressing and release both buttons at the same time: switches between lift and tilt modes. Most window covering types support either lift only, or tilt only, but type 0x08 support both (default)
+
+ - Pressing and hold both buttons at the same time: Cycles between window covering 1, and window covering 2.
+
+* Once the device is provisioned, it will join the Thread network is
+ established, look for the RTT log
+
+ ```
+ [DL] Device Role: CHILD
+ [DL] Partition Id:0x6A7491B7
+ [DL] \_OnPlatformEvent default: event->Type = 32778
+ [DL] OpenThread State Changed (Flags: 0x00000001)
+ [DL] Thread Unicast Addresses:
+ [DL] 2001:DB8::E1A2:87F1:7D5D:FECA/64 valid preferred
+ [DL] FDDE:AD00:BEEF::FF:FE00:2402/64 valid preferred rloc
+ [DL] FDDE:AD00:BEEF:0:383F:5E81:A05A:B168/64 valid preferred
+ [DL] FE80::D8F2:592E:C109:CF00/64 valid preferred
+ [DL] LwIP Thread interface addresses updated
+ [DL] FE80::D8F2:592E:C109:CF00 IPv6 link-local address, preferred)
+ [DL] FDDE:AD00:BEEF:0:383F:5E81:A05A:B168 Thread mesh-local address, preferred)
+ [DL] 2001:DB8::E1A2:87F1:7D5D:FECA IPv6 global unicast address, preferred)
+ ```
+
+ (you can verify that the device is on the thread network with the command
+ `router table` using a serial terminal (screen / minicom etc.) on the board
+ running the window-app example. You can also get the address list with the
+ command ipaddr again in the serial terminal )
+
+ You can provision the Chip device using Chip tool Android or iOS app or
+ through CLI commands on your OT BR
+
+ The
+ [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
+ can now be used to send ZCL commands to the window covering device. For
+ instance, to set the window covering lift by percentage:
+
+ ```
+ chip-tool pairing ble-thread 1 hex: 20202021 3840
+
+ chip-tool onoff on 1 1
+
+ chip-tool windowcovering go-to-tilt-percentage 50 0 1 1
+ ```
+
+ To see the supported window covering cluster commands, use:
+
+ ```
+ chip-tool windowcovering
+ ```
+
+### Notes
+
+- Depending on your network settings your router might not provide native ipv6
+ addresses to your devices (Border router / PC). If this is the case, you
+ need to add a static ipv6 addresses on both device and then an ipv6 route to
+ the border router on your PC
+
+ # On Border Router :
+ $ sudo ip addr add dev 2002::2/64
+
+ # On PC (Linux) :
+ $ sudo ip addr add dev 2002::1/64
+
+ # Add Ipv6 route on PC (Linux)
+ $ sudo ip route add /64 via 2002::2
+
+
+
+## OTA Software Update
+
+For the description of Software Update process with EFR32 example applications
+see
+[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md)
+
+## Building options
+
+All of Silabs's examples within the Matter repo have all the features enabled by
+default, as to provide the best end user experience. However some of those
+features can easily be toggled on or off. Here is a short list of options :
+
+### Disabling logging
+
+chip_progress_logging, chip_detail_logging, chip_automation_logging
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false"
+
+### Debug build / release build
+
+is_debug
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "is_debug=false"
+
+### Disabling LCD
+
+show_qr_code
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "show_qr_code=false"
+
+### KVS maximum entry count
+
+kvs_max_entries
+
+ Set the maximum Kvs entries that can be stored in NVM (Default 75)
+ Thresholds: 30 <= kvs_max_entries <= 255
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50
diff --git a/examples/window-app/silabs/SiWx917/args.gni b/examples/window-app/silabs/SiWx917/args.gni
new file mode 100644
index 00000000000000..421090dbc97aae
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/args.gni
@@ -0,0 +1,24 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/src/platform/silabs/SiWx917/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_ota_requestor = true
+chip_enable_openthread = true
+openthread_external_platform =
+ "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32"
diff --git a/examples/window-app/silabs/SiWx917/build_for_wifi_args.gni b/examples/window-app/silabs/SiWx917/build_for_wifi_args.gni
new file mode 100644
index 00000000000000..770c3ab66ebb62
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/build_for_wifi_args.gni
@@ -0,0 +1,20 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import("//build_overrides/chip.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+chip_enable_openthread = false
+import("${chip_root}/src/platform/silabs/SiWx917/wifi_args.gni")
+
+chip_enable_ota_requestor = true
diff --git a/examples/window-app/silabs/SiWx917/build_for_wifi_gnfile.gn b/examples/window-app/silabs/SiWx917/build_for_wifi_gnfile.gn
new file mode 100644
index 00000000000000..d391814190d09f
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/build_for_wifi_gnfile.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2020 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_enable_wifi = true
+ import("//build_for_wifi_args.gni")
+}
diff --git a/examples/window-app/silabs/SiWx917/build_overrides b/examples/window-app/silabs/SiWx917/build_overrides
new file mode 120000
index 00000000000000..995884e6163eb5
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/build_overrides
@@ -0,0 +1 @@
+../../../build_overrides
\ No newline at end of file
diff --git a/examples/window-app/silabs/SiWx917/include/AppConfig.h b/examples/window-app/silabs/SiWx917/include/AppConfig.h
new file mode 100644
index 00000000000000..661819aea7648b
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/include/AppConfig.h
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// ---- Window Example App Config ----
+#define APP_TASK_NAME "APP"
+
+// EFR Logging
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LCD_SIZE 128
+#define LCD_MARGIN_SIZE 1
+#define LCD_BORDER_SIZE 2
+#define LCD_FRAME_SIZE (2 * LCD_MARGIN_SIZE + LCD_BORDER_SIZE)
+#define LCD_COVER_SIZE (LCD_SIZE - 2 * LCD_FRAME_SIZE)
+#define LIFT_OPEN_LIMIT 0
+#define LIFT_CLOSED_LIMIT (LCD_COVER_SIZE - 1)
+#define LIFT_DELTA 1000 // 10%
+#define TILT_OPEN_LIMIT 1
+#define TILT_CLOSED_LIMIT (LCD_COVER_SIZE / 10 - 1)
+#define TILT_DELTA 1000 // 10%
+
+#define WINDOW_COVER_COUNT 2
+
+#ifndef WINDOW_COVER_ENDPOINT1
+#define WINDOW_COVER_ENDPOINT1 1
+#endif
+
+#ifndef WINDOW_COVER_ENDPOINT2
+#define WINDOW_COVER_ENDPOINT2 2
+#endif
+
+#ifndef LONG_PRESS_TIMEOUT
+#define LONG_PRESS_TIMEOUT 3000
+#endif
+
+#ifndef COVER_LIFT_TILT_TIMEOUT
+#define COVER_LIFT_TILT_TIMEOUT 500
+#endif
+
+void silabsInitLog(void);
+
+void efr32Log(const char * aFormat, ...);
+#define SILABS_LOG(...) efr32Log(__VA_ARGS__);
+
+#ifdef __cplusplus
+}
+
+#include
+void appError(CHIP_ERROR error);
+#endif
diff --git a/examples/window-app/silabs/SiWx917/include/CHIPProjectConfig.h b/examples/window-app/silabs/SiWx917/include/CHIPProjectConfig.h
new file mode 100644
index 00000000000000..6a12dbc3794c8f
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/include/CHIPProjectConfig.h
@@ -0,0 +1,153 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Example project configuration file for CHIP.
+ *
+ * This is a place to put application or project-specific overrides
+ * to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+// Use a default pairing code if one hasn't been provisioned in flash.
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+#endif
+// For convenience, Chip Security Test Mode can be enabled and the
+// requirement for authentication in various protocols can be disabled.
+//
+// WARNING: These options make it possible to circumvent basic Chip security functionality,
+// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+//
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ * 0x8009: example window app
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8010
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION
+ *
+ * The hardware version number assigned to device or product by the device vendor. This
+ * number is scoped to the device product id, and typically corresponds to a revision of the
+ * physical device, a change to its packaging, and/or a change to its marketing presentation.
+ * This value is generally *not* incremented for device software versions.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+ *
+ * A uint32_t identifying the software version running on the device.
+ */
+/* The SoftwareVersion attribute of the Basic cluster. */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 0x0001
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in Chip NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
+ *
+ * Enable recording UTC timestamps.
+ */
+#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE
+ *
+ * A size, in bytes, of the individual debug event logging buffer.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)
+
+/**
+ * CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL
+ *
+ * The interval (in units of 0.625ms) at which the device will send BLE advertisements while
+ * in fast advertising mode.
+ *
+ * 40 (25ms).
+ */
+#define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL 40
+
+/**
+ * CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL
+ *
+ * The interval (in units of 0.625ms) at which the device will send BLE advertisements while
+ * in slow advertisement mode.
+ *
+ * 800 (500ms).
+ */
+#define CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL 800
+
+/**
+ * CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT
+ *
+ * The amount of time in miliseconds after which BLE should change his advertisements
+ * from fast interval to slow interval.
+ *
+ * 30000 (30 secondes).
+ */
+#define CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT (30 * 1000)
+
+/**
+ * @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL
+ *
+ * @brief
+ * Active retransmit interval, or time to wait before retransmission after
+ * subsequent failures in milliseconds.
+ *
+ * This is the default value, that might be adjusted by end device depending on its
+ * needs (e.g. sleeping period) using Service Discovery TXT record CRA key.
+ *
+ */
+#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32)
+
+#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
diff --git a/examples/window-app/silabs/SiWx917/include/LcdPainter.h b/examples/window-app/silabs/SiWx917/include/LcdPainter.h
new file mode 100644
index 00000000000000..4a30bdede2c3ea
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/include/LcdPainter.h
@@ -0,0 +1,113 @@
+/*
+ *
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// clang-format off
+#include "app-common/app-common/zap-generated/enums.h"
+#include "app-common/app-common/zap-generated/cluster-enums.h"
+// clang-format on
+
+#include
+
+#include
+
+enum class LcdIcon
+{
+ None = 0,
+ One,
+ Two,
+ Lift,
+ Tilt
+};
+
+class PixelPainter
+{
+public:
+ PixelPainter(uint16_t lift, uint16_t tilt);
+ virtual ~PixelPainter() = default;
+ virtual uint8_t Color(uint32_t x, uint32_t y) = 0;
+
+protected:
+ uint16_t mLift;
+ uint16_t mTilt;
+};
+
+class CompositePainter : public PixelPainter
+{
+public:
+ CompositePainter(uint16_t lift, uint16_t tilt, PixelPainter * painter1, PixelPainter * painter2, PixelPainter * painter3);
+ uint8_t Color(uint32_t x, uint32_t y);
+
+private:
+ PixelPainter * mPainter1;
+ PixelPainter * mPainter2;
+ PixelPainter * mPainter3;
+};
+
+class FramePainter : public PixelPainter
+{
+ using PixelPainter::PixelPainter;
+ uint8_t Color(uint32_t x, uint32_t y);
+};
+
+class IconPainter : public PixelPainter
+{
+public:
+ IconPainter(uint16_t lift, uint16_t tilt, LcdIcon icon);
+ uint8_t Color(uint32_t x, uint32_t y);
+
+private:
+ uint8_t mIconSize;
+ uint8_t mIconOffset;
+ LcdIcon mIcon;
+};
+
+class VerticalShadePainter : public PixelPainter
+{
+public:
+ using PixelPainter::PixelPainter;
+ uint8_t Color(uint32_t x, uint32_t y);
+};
+
+class HorizontalShadePainter : public PixelPainter
+{
+public:
+ using PixelPainter::PixelPainter;
+ uint8_t Color(uint32_t x, uint32_t y);
+};
+
+class VerticalBlindPainter : public PixelPainter
+{
+public:
+ VerticalBlindPainter(uint16_t lift, uint16_t tilt);
+ uint8_t Color(uint32_t x, uint32_t y);
+
+private:
+ constexpr static uint8_t sBandCount = 12;
+ uint8_t mBandSize;
+};
+
+class LcdPainter
+{
+public:
+ static void Paint(SilabsLCD & lcd, chip::app::Clusters::WindowCovering::Type type, uint16_t lift, uint16_t tilt, LcdIcon icon);
+
+private:
+ static PixelPainter * GetCoverPainter(chip::app::Clusters::WindowCovering::Type type, uint16_t lift, uint16_t tilt);
+};
diff --git a/examples/window-app/silabs/SiWx917/include/WindowAppImpl.h b/examples/window-app/silabs/SiWx917/include/WindowAppImpl.h
new file mode 100644
index 00000000000000..86158e3d4da14b
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/include/WindowAppImpl.h
@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+
+#ifdef ENABLE_WSTK_LEDS
+#include "LEDWidget.h"
+#include "sl_simple_led_instances.h"
+#endif // ENABLE_WSTK_LEDS
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#ifdef DISPLAY_ENABLED
+#include
+#endif
+
+#define SL_SIMPLE_BUTTON_MODE_POLL 0U ///< BUTTON input capture using polling
+#define SL_SIMPLE_BUTTON_MODE_POLL_AND_DEBOUNCE 1U ///< BUTTON input capture using polling and debouncing
+#define SL_SIMPLE_BUTTON_MODE_INTERRUPT 2U ///< BUTTON input capture using interrupt
+
+#define SL_SIMPLE_BUTTON_DISABLED 2U ///< BUTTON state is disabled
+#define SL_SIMPLE_BUTTON_PRESSED 1U ///< BUTTON state is pressed
+#define SL_SIMPLE_BUTTON_RELEASED 0U ///< BUTTON state is released
+
+typedef uint8_t sl_button_mode_t; ///< BUTTON mode
+typedef uint8_t sl_button_state_t; ///< BUTTON state
+typedef struct sl_button sl_button_t;
+
+/// A BUTTON instance
+typedef struct sl_button
+{
+ void * context; ///< The context for this BUTTON instance
+ void (*init)(const sl_button_t * handle); ///< Member function to initialize BUTTON instance
+ void (*poll)(const sl_button_t * handle); ///< Member function to poll BUTTON
+ void (*enable)(const sl_button_t * handle); ///< Member function to enable BUTTON
+ void (*disable)(const sl_button_t * handle); ///< Member function to disable BUTTON
+ sl_button_state_t (*get_state)(const sl_button_t * handle); ///< Member function to retrieve BUTTON state
+} sl_button;
+
+const sl_button_t sl_button_btn0 = {
+ .context = NULL,
+ .init = NULL,
+ .poll = NULL,
+ .enable = NULL,
+ .disable = NULL,
+ .get_state = NULL,
+};
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+
+const sl_button_t sl_button_btn1 = {
+ .context = NULL,
+ .init = NULL,
+ .poll = NULL,
+ .enable = NULL,
+ .disable = NULL,
+ .get_state = NULL,
+};
+#define APP_LIGHT_SWITCH &sl_button_btn1
+
+class WindowAppImpl : public WindowApp
+{
+public:
+ static WindowAppImpl sInstance;
+
+ WindowAppImpl();
+ CHIP_ERROR Init() override;
+ CHIP_ERROR Start() override;
+ void Finish() override;
+ void PostEvent(const WindowApp::Event & event) override;
+ void PostAttributeChange(chip::EndpointId endpoint, chip::AttributeId attributeId) override;
+ friend void sl_button_on_change(const sl_button_t * handle);
+ void OnButtonChange(const sl_button_t * handle);
+
+protected:
+ struct Timer : public WindowApp::Timer
+ {
+ TimerHandle_t mHandler = nullptr;
+
+ Timer(const char * name, uint32_t timeoutInMs, Callback callback, void * context);
+ void IsrStart();
+ void Start() override;
+ void Stop() override;
+
+ private:
+ static void TimerCallback(TimerHandle_t xTimer);
+ };
+
+ struct Button : public WindowApp::Button
+ {
+ Button(Button::Id id, const char * name);
+ };
+
+ WindowApp::Timer * CreateTimer(const char * name, uint32_t timeoutInMs, WindowApp::Timer::Callback callback,
+ void * context) override;
+ WindowApp::Button * CreateButton(WindowApp::Button::Id id, const char * name) override;
+ void ProcessEvents();
+ void DispatchEvent(const WindowApp::Event & event) override;
+ void UpdateLEDs();
+ void UpdateLCD();
+ void OnMainLoop() override;
+
+ static void OnTaskCallback(void * parameter);
+ static void OnIconTimeout(WindowApp::Timer & timer);
+
+private:
+ void DispatchEventAttributeChange(chip::EndpointId endpoint, chip::AttributeId attribute);
+ TaskHandle_t mHandle = nullptr;
+ QueueHandle_t mQueue = nullptr;
+
+#ifdef ENABLE_WSTK_LEDS
+ LEDWidget mStatusLED;
+ LEDWidget mActionLED;
+#endif // ENABLE_WSTK_LEDS
+
+ // Get QR Code and emulate its content using NFC tag
+ char mQRCodeBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
+#ifdef DISPLAY_ENABLED
+ Timer mIconTimer;
+ LcdIcon mIcon = LcdIcon::None;
+#endif
+};
diff --git a/examples/window-app/silabs/SiWx917/src/LcdPainter.cpp b/examples/window-app/silabs/SiWx917/src/LcdPainter.cpp
new file mode 100644
index 00000000000000..e1a8041f075c79
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/src/LcdPainter.cpp
@@ -0,0 +1,226 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+using namespace chip::app::Clusters::WindowCovering;
+
+constexpr uint32_t sTiltIcon[] = {
+ 0xffffffff, 0xffffffff, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0000003, 0xc1ffffc3, 0xc1ffffc3,
+ 0xc1ffffc3, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003,
+ 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003, 0xc003c003,
+ 0xc003c003, 0xc003c003, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0000003, 0xffffffff, 0xffffffff,
+};
+
+constexpr uint32_t sLiftIcon[] = {
+ 0xffffffff, 0xffffffff, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0f00003, 0xc0f00003,
+ 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003,
+ 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0f00003, 0xc0ffffc3,
+ 0xc0ffffc3, 0xc0ffffc3, 0xc0000003, 0xc0000003, 0xc0000003, 0xc0000003, 0xffffffff, 0xffffffff,
+};
+
+constexpr uint32_t sOneIcon[] = {
+ 0xffffffff, 0xffffffff, 0xc0000003, 0xc0000003, 0xc0000003, 0xc00fe003, 0xc01fe003, 0xc03fe003,
+ 0xc07fe003, 0xc0fbe003, 0xc1f3e003, 0xc3e3e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003,
+ 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc003e003, 0xc3ffffc3,
+ 0xc3ffffc3, 0xc3ffffc3, 0xc3ffffc3, 0xc0000003, 0xc0000003, 0xc0000003, 0xffffffff, 0xffffffff,
+};
+
+constexpr uint32_t sTwoIcon[] = {
+ 0xffffffff, 0xffffffff, 0xc0000003, 0xc0000003, 0xc0000003, 0xc07ffe03, 0xc0ffff03, 0xc1ffff83,
+ 0xc3ffffc3, 0xc3f00fc3, 0xc3e007c3, 0xc3e007c3, 0xc00007c3, 0xc00007c3, 0xc0000fc3, 0xc00fff83,
+ 0xc03fff03, 0xc07ffe03, 0xc0fc0003, 0xc1f80003, 0xc1f00003, 0xc3e00003, 0xc3e00003, 0xc3ffffc3,
+ 0xc3ffffc3, 0xc3ffffc3, 0xc3ffffc3, 0xc0000003, 0xc0000003, 0xc0000003, 0xffffffff, 0xffffffff,
+};
+
+PixelPainter::PixelPainter(uint16_t lift, uint16_t tilt) : mLift(lift), mTilt(tilt) {}
+
+CompositePainter::CompositePainter(uint16_t lift, uint16_t tilt, PixelPainter * painter1, PixelPainter * painter2,
+ PixelPainter * painter3) :
+ PixelPainter(lift, tilt),
+ mPainter1(painter1), mPainter2(painter2), mPainter3(painter3)
+{}
+
+uint8_t CompositePainter::Color(uint32_t x, uint32_t y)
+{
+ int8_t pixel = -1;
+ if (mPainter1)
+ {
+ pixel = mPainter1->Color(x, y);
+ if (pixel >= 0)
+ {
+ return pixel;
+ }
+ }
+ if (mPainter2)
+ {
+ pixel = mPainter2->Color(x, y);
+ if (pixel >= 0)
+ {
+ return pixel;
+ }
+ }
+ if (mPainter3)
+ {
+ pixel = mPainter3->Color(x, y);
+ if (pixel >= 0)
+ {
+ return pixel;
+ }
+ }
+ return pixel;
+}
+
+uint8_t FramePainter::Color(uint32_t x, uint32_t y)
+{
+ if (x < LCD_FRAME_SIZE || x >= (LCD_SIZE - LCD_FRAME_SIZE) || y < LCD_FRAME_SIZE || y >= (LCD_SIZE - LCD_FRAME_SIZE))
+ {
+ if (x < LCD_MARGIN_SIZE || x >= (LCD_SIZE - LCD_MARGIN_SIZE) || y < LCD_MARGIN_SIZE || y >= (LCD_SIZE - LCD_MARGIN_SIZE))
+ {
+ return 0;
+ }
+ else
+ {
+ return (x < (LCD_MARGIN_SIZE + LCD_BORDER_SIZE)) || (x >= (LCD_SIZE - LCD_BORDER_SIZE - LCD_MARGIN_SIZE)) ||
+ (y < (LCD_MARGIN_SIZE + LCD_BORDER_SIZE)) || (y >= (LCD_SIZE - LCD_BORDER_SIZE - LCD_MARGIN_SIZE));
+ }
+ }
+ return -1;
+}
+
+IconPainter::IconPainter(uint16_t lift, uint16_t tilt, LcdIcon icon) : PixelPainter(lift, tilt), mIcon(icon)
+{
+ mIconSize = sizeof(sTiltIcon) / sizeof(uint32_t);
+ mIconOffset = (LCD_SIZE - mIconSize) / 2;
+}
+
+uint8_t IconPainter::Color(uint32_t x, uint32_t y)
+{
+ const uint32_t * icon = nullptr;
+ switch (mIcon)
+ {
+ case LcdIcon::One:
+ icon = sOneIcon;
+ break;
+ case LcdIcon::Two:
+ icon = sTwoIcon;
+ break;
+ case LcdIcon::Lift:
+ icon = sLiftIcon;
+ break;
+ case LcdIcon::Tilt:
+ icon = sTiltIcon;
+ break;
+ default:
+ return -1;
+ }
+ if (x >= mIconOffset && x < (mIconOffset + mIconSize) && y >= mIconOffset && y < (mIconOffset + mIconSize))
+ {
+ uint32_t x0 = x - mIconOffset;
+ uint32_t y0 = y - mIconOffset;
+ return (icon[y0] & (1 << (31 - x0))) > 0;
+ }
+ return -1;
+}
+
+uint8_t VerticalShadePainter::Color(uint32_t x, uint32_t y)
+{
+ return (y % 2) && y < (uint32_t)(LCD_FRAME_SIZE + mLift);
+}
+
+uint8_t HorizontalShadePainter::Color(uint32_t x, uint32_t y)
+{
+ return (x % 2) && x < (uint32_t)(LCD_FRAME_SIZE + mLift);
+}
+
+VerticalBlindPainter::VerticalBlindPainter(uint16_t lift, uint16_t tilt) : PixelPainter(lift, tilt)
+{
+ mBandSize = (LCD_COVER_SIZE / sBandCount);
+}
+
+uint8_t VerticalBlindPainter::Color(uint32_t x, uint32_t y)
+{
+ if (x % 2)
+ {
+ return 0;
+ }
+ else
+ {
+ uint32_t closedCount = (mLift + 1) / mBandSize;
+ uint32_t bandCount = (y - LCD_FRAME_SIZE) / mBandSize;
+ // ChipLogProgress(Zcl, "BLIND: ccount:%u, ccount:%u", clusterId);
+ if (bandCount <= closedCount)
+ {
+ return y <= (LCD_FRAME_SIZE + mBandSize * bandCount + mTilt);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
+
+PixelPainter * LcdPainter::GetCoverPainter(Type type, uint16_t lift, uint16_t tilt)
+{
+ switch (type)
+ {
+ case Type::kRollerShade:
+ case Type::kRollerShade2Motor:
+ case Type::kRollerShadeExterior:
+ case Type::kRollerShadeExterior2Motor:
+ return new VerticalShadePainter(lift, tilt);
+ case Type::kDrapery:
+ case Type::kAwning:
+ return new HorizontalShadePainter(lift, tilt);
+ case Type::kShutter:
+ case Type::kTiltBlindTiltOnly:
+ case Type::kTiltBlindLiftAndTilt:
+ return new VerticalBlindPainter(lift, tilt);
+ case Type::kProjectorScreen:
+ case Type::kUnknown:
+ default:
+ return new VerticalShadePainter(lift, tilt);
+ }
+
+ return nullptr;
+}
+
+void LcdPainter::Paint(SilabsLCD & lcd, Type type, uint16_t lift, uint16_t tilt, LcdIcon icon)
+{
+ FramePainter framePaint = FramePainter(lift, tilt);
+ IconPainter iconPaint = IconPainter(lift, tilt, icon);
+ PixelPainter * coverPaint = GetCoverPainter(type, lift, tilt);
+ CompositePainter compositePaint = CompositePainter(lift, tilt, &framePaint, &iconPaint, coverPaint);
+ void * context = lcd.Context();
+
+ lcd.Clear();
+
+ for (int i = 0; i < LCD_SIZE; i++)
+ {
+ for (int j = 0; j < LCD_SIZE; j++)
+ {
+ if (compositePaint.Color(i, j))
+ {
+ lcd.DrawPixel(context, i, j);
+ }
+ }
+ }
+ lcd.Update();
+ delete coverPaint;
+}
diff --git a/examples/window-app/silabs/SiWx917/src/WindowAppImpl.cpp b/examples/window-app/silabs/SiWx917/src/WindowAppImpl.cpp
new file mode 100644
index 00000000000000..8cb6774f9d8da4
--- /dev/null
+++ b/examples/window-app/silabs/SiWx917/src/WindowAppImpl.cpp
@@ -0,0 +1,547 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef QR_CODE_ENABLED
+#include
+#else
+#include "SiWx917DeviceDataProvider.h"
+#include
+#include
+#endif // QR_CODE_ENABLED
+
+#ifdef ENABLE_WSTK_LEDS
+#include
+#endif // ENABLE_WSTK_LEDS
+extern "C" void sl_button_on_change();
+
+#ifdef SL_WIFI
+#include "wfx_host_events.h"
+#include
+#include
+#endif
+
+#ifdef DISPLAY_ENABLED
+#include
+SilabsLCD slLCD;
+#endif
+
+#define APP_TASK_STACK_SIZE (4096)
+#define APP_TASK_PRIORITY 2
+#define APP_EVENT_QUEUE_SIZE 10
+#define EXAMPLE_VENDOR_ID 0xcafe
+
+#define LCD_ICON_TIMEOUT 1000
+
+using namespace chip::app::Clusters::WindowCovering;
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+#define APP_STATE_LED &sl_led_led0
+#define APP_ACTION_LED &sl_led_led1
+
+#ifdef SL_WIFI
+chip::app::Clusters::NetworkCommissioning::Instance
+ sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(chip::DeviceLayer::NetworkCommissioning::SlWiFiDriver::GetInstance()));
+#endif
+//------------------------------------------------------------------------------
+// Timers
+//------------------------------------------------------------------------------
+
+WindowAppImpl::Timer::Timer(const char * name, uint32_t timeoutInMs, Callback callback, void * context) :
+ WindowApp::Timer(name, timeoutInMs, callback, context)
+{
+ mHandler = xTimerCreate(name, // Just a text name, not used by the RTOS kernel
+ timeoutInMs, // == default timer period (mS)
+ false, // no timer reload (==one-shot)
+ (void *) this, // init timer id = app task obj context
+ TimerCallback // timer callback handler
+ );
+ if (mHandler == NULL)
+ {
+ SILABS_LOG("Timer create failed");
+ appError(CHIP_ERROR_INTERNAL);
+ }
+}
+
+void WindowAppImpl::Timer::Start()
+{
+ if (xTimerIsTimerActive(mHandler))
+ {
+ Stop();
+ }
+
+ // Timer is not active
+ if (xTimerStart(mHandler, 100) != pdPASS)
+ {
+ SILABS_LOG("Timer start() failed");
+ appError(CHIP_ERROR_INTERNAL);
+ }
+
+ mIsActive = true;
+}
+
+void WindowAppImpl::Timer::IsrStart()
+{
+ portBASE_TYPE taskWoken = pdFALSE; // For FreeRTOS timer (below).
+ // Start/restart the button debounce timer (Note ISR version of FreeRTOS
+ // api call here).
+ xTimerStartFromISR(mHandler, &taskWoken);
+ if (taskWoken != pdFALSE)
+ {
+ taskYIELD();
+ }
+ mIsActive = true;
+}
+
+void WindowAppImpl::Timer::Stop()
+{
+ mIsActive = false;
+ if (xTimerStop(mHandler, 0) == pdFAIL)
+ {
+ SILABS_LOG("Timer stop() failed");
+ appError(CHIP_ERROR_INTERNAL);
+ }
+}
+
+void WindowAppImpl::Timer::TimerCallback(TimerHandle_t xTimer)
+{
+ Timer * timer = (Timer *) pvTimerGetTimerID(xTimer);
+ if (timer)
+ {
+ timer->Timeout();
+ }
+}
+
+//------------------------------------------------------------------------------
+// Main Task
+//------------------------------------------------------------------------------
+
+StackType_t sAppStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)];
+StaticTask_t sAppTaskStruct;
+
+uint8_t sAppEventQueueBuffer[APP_EVENT_QUEUE_SIZE * sizeof(WindowApp::Event)];
+StaticQueue_t sAppEventQueueStruct;
+
+WindowAppImpl WindowAppImpl::sInstance;
+
+WindowApp & WindowApp::Instance()
+{
+ return WindowAppImpl::sInstance;
+}
+
+#ifdef DISPLAY_ENABLED
+WindowAppImpl::WindowAppImpl() : mIconTimer("Timer:icon", LCD_ICON_TIMEOUT, OnIconTimeout, this) {}
+#else
+WindowAppImpl::WindowAppImpl() {}
+#endif
+
+void WindowAppImpl::OnTaskCallback(void * parameter)
+{
+#ifdef SL_WIFI
+ /*
+ * Wait for the WiFi to be initialized
+ */
+ SILABS_LOG("APP: Wait WiFi Init");
+ while (!wfx_hw_ready())
+ {
+ vTaskDelay(10);
+ }
+ SILABS_LOG("APP: Done WiFi Init");
+ /* We will init server when we get IP */
+ sWiFiNetworkCommissioningInstance.Init();
+ /* added for commissioning with wifi */
+#endif
+
+ sInstance.Run();
+}
+
+void WindowAppImpl::OnIconTimeout(WindowApp::Timer & timer)
+{
+#ifdef DISPLAY_ENABLED
+ sInstance.mIcon = LcdIcon::None;
+ sInstance.UpdateLCD();
+#endif
+}
+
+CHIP_ERROR WindowAppImpl::Init()
+{
+ WindowApp::Init();
+
+ // Initialize App Task
+ mHandle = xTaskCreateStatic(OnTaskCallback, APP_TASK_NAME, ArraySize(sAppStack), NULL, 1, sAppStack, &sAppTaskStruct);
+ if (NULL == mHandle)
+ {
+ SILABS_LOG("Failed to allocate app task");
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ // Initialize App Queue
+ mQueue = xQueueCreateStatic(APP_EVENT_QUEUE_SIZE, sizeof(WindowApp::Event), sAppEventQueueBuffer, &sAppEventQueueStruct);
+ if (NULL == mQueue)
+ {
+ SILABS_LOG("Failed to allocate app event queue");
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ // Initialize LEDs
+#ifdef ENABLE_WSTK_LEDS
+ LEDWidget::InitGpio();
+ mStatusLED.Init(APP_STATE_LED);
+ mActionLED.Init(APP_ACTION_LED);
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef DISPLAY_ENABLED
+ slLCD.Init();
+#endif
+
+#ifndef QR_CODE_ENABLED
+ // Create buffer for QR code that can fit max size and null terminator.
+ char qrCodeBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
+ chip::MutableCharSpan QRCode(qrCodeBuffer);
+
+ if (EFR32::EFR32DeviceDataProvider::GetDeviceDataProvider().GetSetupPayload(QRCode) == CHIP_NO_ERROR)
+ {
+ PrintQrCodeURL(QRCode);
+ }
+ else
+ {
+ SILABS_LOG("Getting QR code failed!");
+ }
+#endif // QR_CODE_ENABLED
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR WindowAppImpl::Start()
+{
+ SILABS_LOG("Starting FreeRTOS scheduler");
+ vTaskStartScheduler();
+
+ return CHIP_NO_ERROR;
+}
+
+void WindowAppImpl::Finish()
+{
+ WindowApp::Finish();
+ chip::Platform::MemoryShutdown();
+ // Should never get here.
+ SILABS_LOG("vTaskStartScheduler() failed");
+ appError(CHIP_ERROR_INTERNAL);
+}
+
+void WindowAppImpl::PostEvent(const WindowApp::Event & event)
+{
+ if (mQueue)
+ {
+ BaseType_t status;
+ if (xPortIsInsideInterrupt())
+ {
+ BaseType_t higherPrioTaskWoken = pdFALSE;
+ status = xQueueSendFromISR(mQueue, &event, &higherPrioTaskWoken);
+
+#ifdef portYIELD_FROM_ISR
+ portYIELD_FROM_ISR(higherPrioTaskWoken);
+#elif portEND_SWITCHING_ISR // portYIELD_FROM_ISR or portEND_SWITCHING_ISR
+ portEND_SWITCHING_ISR(higherPrioTaskWoken);
+#else // portYIELD_FROM_ISR or portEND_SWITCHING_ISR
+#error "Must have portYIELD_FROM_ISR or portEND_SWITCHING_ISR"
+#endif // portYIELD_FROM_ISR or portEND_SWITCHING_ISR
+ }
+ else
+ {
+ status = xQueueSend(mQueue, &event, 1);
+ }
+
+ if (!status)
+ {
+ SILABS_LOG("Failed to post event to app task event queue");
+ }
+ }
+}
+
+void WindowAppImpl::PostAttributeChange(chip::EndpointId endpoint, chip::AttributeId attributeId)
+{
+ Instance().PostEvent(WindowApp::Event(WindowApp::EventId::AttributeChange, endpoint, attributeId));
+}
+
+void WindowAppImpl::ProcessEvents()
+{
+ WindowApp::Event event = EventId::None;
+
+ BaseType_t received = xQueueReceive(mQueue, &event, pdMS_TO_TICKS(10));
+ while (pdTRUE == received)
+ {
+ DispatchEvent(event);
+ received = xQueueReceive(mQueue, &event, 0);
+ }
+}
+
+WindowApp::Timer * WindowAppImpl::CreateTimer(const char * name, uint32_t timeoutInMs, WindowApp::Timer::Callback callback,
+ void * context)
+{
+ return new Timer(name, timeoutInMs, callback, context);
+}
+
+WindowApp::Button * WindowAppImpl::CreateButton(WindowApp::Button::Id id, const char * name)
+{
+ return new Button(id, name);
+}
+
+void WindowAppImpl::DispatchEventAttributeChange(chip::EndpointId endpoint, chip::AttributeId attribute)
+{
+ switch (attribute)
+ {
+ /* RO OperationalStatus */
+ case Attributes::OperationalStatus::Id:
+ UpdateLEDs();
+ break;
+ /* RO Type: not supposed to dynamically change -> Cycling Window Covering Demo */
+ case Attributes::Type::Id:
+ /* ============= Positions for Position Aware ============= */
+ case Attributes::CurrentPositionLiftPercent100ths::Id:
+ case Attributes::CurrentPositionTiltPercent100ths::Id:
+ UpdateLCD();
+ break;
+ /* ### ATTRIBUTEs CHANGEs IGNORED ### */
+ /* RO EndProductType: not supposed to dynamically change */
+ case Attributes::EndProductType::Id:
+ /* RO ConfigStatus: set by WC server */
+ case Attributes::ConfigStatus::Id:
+ /* RO SafetyStatus: set by WC server */
+ case Attributes::SafetyStatus::Id:
+ /* RW Mode: User can change */
+ case Attributes::Mode::Id:
+ default:
+ break;
+ }
+}
+
+void WindowAppImpl::DispatchEvent(const WindowApp::Event & event)
+{
+ WindowApp::DispatchEvent(event);
+ switch (event.mId)
+ {
+ case EventId::AttributeChange:
+ DispatchEventAttributeChange(event.mEndpoint, event.mAttributeId);
+ break;
+ case EventId::ResetWarning:
+ SILABS_LOG("Factory Reset Triggered. Release button within %ums to cancel.", LONG_PRESS_TIMEOUT);
+ // Turn off all LEDs before starting blink to make sure blink is
+ // co-ordinated.
+ UpdateLEDs();
+ break;
+ case EventId::ResetCanceled:
+ SILABS_LOG("Factory Reset has been Canceled");
+ UpdateLEDs();
+ break;
+ case EventId::ProvisionedStateChanged:
+ UpdateLEDs();
+ UpdateLCD();
+ break;
+
+ case EventId::WinkOn:
+ case EventId::WinkOff:
+ mState.isWinking = (EventId::WinkOn == event.mId);
+ UpdateLEDs();
+ break;
+ case EventId::ConnectivityStateChanged:
+ case EventId::BLEConnectionsChanged:
+ UpdateLEDs();
+ break;
+#ifdef DISPLAY_ENABLED
+ case EventId::CoverTypeChange:
+ UpdateLCD();
+ break;
+ case EventId::CoverChange:
+ mIconTimer.Start();
+ mIcon = (GetCover().mEndpoint == 1) ? LcdIcon::One : LcdIcon::Two;
+ UpdateLCD();
+ break;
+ case EventId::TiltModeChange:
+ mIconTimer.Start();
+ mIcon = mTiltMode ? LcdIcon::Tilt : LcdIcon::Lift;
+ UpdateLCD();
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+void WindowAppImpl::UpdateLEDs()
+{
+ Cover & cover = GetCover();
+ if (mResetWarning)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ mStatusLED.Set(false);
+ mStatusLED.Blink(500);
+
+ mActionLED.Set(false);
+ mActionLED.Blink(500);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else
+ {
+ if (mState.isWinking)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ mStatusLED.Blink(200, 200);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else
+#if CHIP_ENABLE_OPENTHREAD
+ if (mState.isThreadProvisioned && mState.isThreadEnabled)
+#else
+ if (mState.isWiFiProvisioned && mState.isWiFiEnabled)
+#endif
+
+ {
+#ifdef ENABLE_WSTK_LEDS
+ mStatusLED.Blink(950, 50);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else if (mState.haveBLEConnections)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ mStatusLED.Blink(100, 100);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else
+ {
+#ifdef ENABLE_WSTK_LEDS
+ mStatusLED.Blink(50, 950);
+#endif // ENABLE_WSTK_LEDS
+ }
+
+ // Action LED
+ NPercent100ths current;
+ LimitStatus liftLimit = LimitStatus::Intermediate;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ Attributes::CurrentPositionLiftPercent100ths::Get(cover.mEndpoint, current);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ if (!current.IsNull())
+ {
+ AbsoluteLimits limits = { .open = WC_PERCENT100THS_MIN_OPEN, .closed = WC_PERCENT100THS_MAX_CLOSED };
+ liftLimit = CheckLimitState(current.Value(), limits);
+ }
+
+ if (OperationalState::Stall != cover.mLiftOpState)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ mActionLED.Blink(100);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else if (LimitStatus::IsUpOrOpen == liftLimit)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ mActionLED.Set(true);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else if (LimitStatus::IsDownOrClose == liftLimit)
+ {
+#ifdef ENABLE_WSTK_LEDS
+ mActionLED.Set(false);
+#endif // ENABLE_WSTK_LEDS
+ }
+ else
+ {
+#ifdef ENABLE_WSTK_LEDS
+ mActionLED.Blink(1000);
+#endif // ENABLE_WSTK_LEDS
+ }
+ }
+}
+
+void WindowAppImpl::UpdateLCD()
+{
+ // Update LCD
+#ifdef DISPLAY_ENABLED
+#if CHIP_ENABLE_OPENTHREAD
+ if (mState.isThreadProvisioned)
+#else
+ if (mState.isWiFiProvisioned)
+#endif // CHIP_ENABLE_OPENTHREAD
+ {
+ Cover & cover = GetCover();
+ chip::app::DataModel::Nullable lift;
+ chip::app::DataModel::Nullable tilt;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ Type type = TypeGet(cover.mEndpoint);
+
+ Attributes::CurrentPositionLift::Get(cover.mEndpoint, lift);
+ Attributes::CurrentPositionTilt::Get(cover.mEndpoint, tilt);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+#ifdef DISPLAY_ENABLED
+ if (!tilt.IsNull() && !lift.IsNull())
+ {
+ LcdPainter::Paint(slLCD, type, lift.Value(), tilt.Value(), mIcon);
+ }
+#endif
+ }
+#ifdef QR_CODE_ENABLED
+ else
+ {
+ chip::MutableCharSpan qrCode(mQRCodeBuffer);
+ if (GetQRCode(qrCode, chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)) == CHIP_NO_ERROR)
+ {
+ slLCD.SetQRCode((uint8_t *) qrCode.data(), qrCode.size());
+ slLCD.ShowQRCode(true, true);
+ }
+ }
+#endif // QR_CODE_ENABLED
+#endif // DISPLAY_ENABLED
+}
+
+void WindowAppImpl::OnMainLoop()
+{
+#ifdef ENABLE_WSTK_LEDS
+ mStatusLED.Animate();
+ mActionLED.Animate();
+#endif // ENABLE_WSTK_LEDS
+}
+
+//------------------------------------------------------------------------------
+// Buttons
+//------------------------------------------------------------------------------
+WindowAppImpl::Button::Button(WindowApp::Button::Id id, const char * name) : WindowApp::Button(id, name) {}
+
+void WindowAppImpl::OnButtonChange(const sl_button_t * handle)
+{
+ WindowApp::Button * btn = static_cast