diff --git a/config/nrfconnect/app/sample-defaults.conf b/config/nrfconnect/app/sample-defaults.conf
index 7145c2d7b704c9..22625d175148f1 100644
--- a/config/nrfconnect/app/sample-defaults.conf
+++ b/config/nrfconnect/app/sample-defaults.conf
@@ -41,9 +41,12 @@ CONFIG_NET_SOCKETS_POSIX_NAMES=n
CONFIG_MAIN_STACK_SIZE=8192
CONFIG_INIT_STACKS=y
+# Enable Zephyr IPv6 multicast
+CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=14
+CONFIG_NET_IPV6_MLD=y
+
# Disable certain parts of Zephyr IPv6 stack
CONFIG_NET_IPV6_NBR_CACHE=n
-CONFIG_NET_IPV6_MLD=n
# Network buffers
CONFIG_NET_PKT_RX_COUNT=16
diff --git a/examples/light-switch-app/nrfconnect/.gitignore b/examples/light-switch-app/nrfconnect/.gitignore
new file mode 100644
index 00000000000000..84c048a73cc2e5
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/examples/light-switch-app/nrfconnect/CMakeLists.txt b/examples/light-switch-app/nrfconnect/CMakeLists.txt
new file mode 100644
index 00000000000000..3610cbfc72b526
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/CMakeLists.txt
@@ -0,0 +1,103 @@
+#
+# Copyright (c) 2022 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.
+#
+
+cmake_minimum_required(VERSION 3.20.0)
+
+get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip REALPATH)
+get_filename_component(NRFCONNECT_COMMON ${CHIP_ROOT}/examples/platform/nrfconnect REALPATH)
+get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH)
+
+include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake)
+
+# Load NCS/Zephyr build system
+set(CONF_FILE ${CHIP_ROOT}/config/nrfconnect/app/sample-defaults.conf prj.conf)
+
+if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD}.conf)
+ list(APPEND CONF_FILE boards/${BOARD}.conf)
+endif()
+
+set(BUILD_WITH_DFU "MATTER" CACHE STRING "Build target with Device Firmware Upgrade support")
+
+if(NOT BUILD_WITH_DFU STREQUAL "OFF")
+ if(BUILD_WITH_DFU STREQUAL "BLE")
+ if(BOARD STREQUAL "nrf5340dk_nrf5340_cpuapp")
+ list(INSERT OVERLAY_CONFIG 0 ${CHIP_ROOT}/config/nrfconnect/app/overlay-multi_image_smp_dfu_support.conf)
+ else()
+ list(INSERT OVERLAY_CONFIG 0 ${CHIP_ROOT}/config/nrfconnect/app/overlay-single_image_smp_dfu_support.conf)
+ endif()
+ elseif(NOT BUILD_WITH_DFU STREQUAL "MATTER")
+ message(FATAL_ERROR "Selected invalid BUILD_WITH_DFU value: ${BUILD_WITH_DFU}")
+ endif()
+
+ list(INSERT OVERLAY_CONFIG 0 ${CHIP_ROOT}/config/nrfconnect/app/overlay-mcuboot_qspi_nor_support.conf)
+ list(INSERT OVERLAY_CONFIG 0 ${CHIP_ROOT}/config/nrfconnect/app/overlay-ota_requestor.conf)
+
+ if(BOARD STREQUAL "nrf5340dk_nrf5340_cpuapp")
+ # DFU over Matter doesn't support multi-image update yet, but using this configs should not harm it anyway.
+ set(mcuboot_OVERLAY_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/configuration/mcuboot_multi_image_dfu.conf CACHE INTERNAL "")
+ else()
+ set(mcuboot_OVERLAY_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/configuration/mcuboot_single_image_dfu.conf CACHE INTERNAL "")
+ endif()
+
+ set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static.yml)
+endif()
+
+list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/nrfconnect/chip-module)
+find_package(Zephyr HINTS $ENV{ZEPHYR_BASE})
+
+# -Wmaybe-uninitialized has too many false positives, including on std::optional
+# and chip::Optional. Make it nonfatal.
+#
+# See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80635
+target_compile_options(app PRIVATE -Werror -Wno-error=maybe-uninitialized)
+
+project(chip-nrfconnect-light-switch-example)
+
+include(${CHIP_ROOT}/config/nrfconnect/app/enable-gnu-std.cmake)
+include(${CHIP_ROOT}/config/nrfconnect/app/flashing.cmake)
+include(${CHIP_ROOT}/src/app/chip_data_model.cmake)
+
+target_include_directories(app PRIVATE
+ main/include
+ ${GEN_DIR}/app-common
+ ${GEN_DIR}/light-switch-app
+ ${NRFCONNECT_COMMON}/util/include
+ ${NRFCONNECT_COMMON}/app/include)
+
+target_sources(app PRIVATE
+ main/AppTask.cpp
+ main/main.cpp
+ main/LightSwitch.cpp
+ main/ShellCommands.cpp
+ main/BindingHandler.cpp
+ ${GEN_DIR}/light-switch-app/zap-generated/callback-stub.cpp
+ ${GEN_DIR}/light-switch-app/zap-generated/IMClusterCommandHandler.cpp
+ ${NRFCONNECT_COMMON}/util/LEDWidget.cpp
+ ${NRFCONNECT_COMMON}/util/ThreadUtil.cpp)
+
+
+if(CONFIG_CHIP_OTA_REQUESTOR)
+ target_sources(app PRIVATE ${NRFCONNECT_COMMON}/util/OTAUtil.cpp)
+endif()
+
+if(BUILD_WITH_DFU STREQUAL "BLE")
+ target_sources(app PRIVATE ${NRFCONNECT_COMMON}/util/DFUOverSMP.cpp)
+endif()
+
+chip_configure_data_model(app
+ INCLUDE_SERVER
+ ZAP_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../light-switch-common/light-switch-app.zap
+)
diff --git a/examples/light-switch-app/nrfconnect/Kconfig b/examples/light-switch-app/nrfconnect/Kconfig
new file mode 100644
index 00000000000000..9bee833c7681de
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/Kconfig
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 2022 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.
+#
+mainmenu "Matter nRF Connect Light Switch Example Application"
+
+config STATE_LEDS
+ bool "Use LEDs to indicate the device state"
+ default y
+ help
+ Use LEDs to render the current state of the device such as the progress of commissioning of
+ the device into a network or the factory reset initiation. Note that setting this option to
+ 'n' does not disable the LED indicating the state of the simulated bolt.
+
+source "Kconfig.zephyr"
diff --git a/examples/light-switch-app/nrfconnect/README.md b/examples/light-switch-app/nrfconnect/README.md
new file mode 100644
index 00000000000000..a11642be5d72a6
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/README.md
@@ -0,0 +1,721 @@
+# Matter nRF Connect Light Switch Example Application
+
+The nRF Connect Light Switch Example demonstrates how to remotely control a
+lighting devices such as light bulbs or LEDs. The application should be used
+together with the
+[lighting app example](../../lighting-app/nrfconnect/README.md). The light
+switch uses buttons to test changing the lighting application example LED state
+and works as a brightness dimmer. You can use this example as a reference for
+creating your own application.
+
+
+
+
+
+
+The example is based on
+[Matter](https://github.com/project-chip/connectedhomeip) and Nordic
+Semiconductor's nRF Connect SDK, and supports remote access and control of a
+lighting examples over a low-power, 802.15.4 Thread network.
+
+The example behaves as a Matter accessory, that is a device that can be paired
+into an existing Matter network and can be controlled by this network.
+
+
+
+- [Overview](#overview)
+ - [Bluetooth LE advertising](#bluetooth-le-advertising)
+ - [Bluetooth LE rendezvous](#bluetooth-le-rendezvous)
+ - [Device Firmware Upgrade](#device-firmware-upgrade)
+- [Requirements](#requirements)
+ - [Supported devices](#supported_devices)
+- [Device UI](#device-ui)
+ - [LEDs](#leds)
+ - [Buttons](#buttons)
+ - [Matter CLI](#matter-cli-commands)
+- [Setting up the environment](#setting-up-the-environment)
+ - [Using Docker container for setup](#using-docker-container-for-setup)
+ - [Using native shell for setup](#using-native-shell-for-setup)
+- [Building](#building)
+ - [Removing build artifacts](#removing-build-artifacts)
+ - [Building with release configuration](#building-with-release-configuration)
+ - [Building with low-power configuration](#building-with-low-power-configuration)
+ - [Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+- [Configuring the example](#configuring-the-example)
+- [Flashing and debugging](#flashing-and-debugging)
+- [Testing the example](#testing-the-example)
+ - [Binding process](#binding-process)
+ - [Testing Device Firmware Upgrade](#testing-device-firmware-upgrade)
+
+
+
+
+
+## Overview
+
+This example is running on the nRF Connect platform, which is based on Nordic
+Semiconductor's
+[nRF Connect SDK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/index.html)
+and [Zephyr RTOS](https://zephyrproject.org/). Visit Matter's
+[nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md)
+to read more about the platform structure and dependencies.
+
+A light switch device is a simple embedded controller, which has the ability to
+control lighting devices, such as light bulbs or LEDs. After commissioning into
+a Matter network, the light switch device does not know what it can control. In
+other words, it has no information about another device being connected to the
+same network. You must provide this information to the light switch through the
+process called binding, which links clusters and endpoints on both devices, so
+that the devices can interact with each other.
+
+The Matter device that runs the light switch application is controlled by the
+Matter controller device over the Thread protocol. By default, the Matter device
+has Thread disabled, and it should be paired with Matter controller and get
+configuration from it. Some actions required before establishing full
+communication are described below.
+
+The example also comes with a test mode, which allows to start Thread with the
+default settings by pressing button manually. However, this mode does not
+guarantee that the device will be able to communicate with the Matter controller
+and other devices.
+
+The example can be configured to use the secure bootloader and utilize it for
+performing over-the-air Device Firmware Upgrade using Bluetooth LE.
+
+### Bluetooth LE advertising
+
+In this example, to commission the device onto a Matter network, it must be
+discoverable over Bluetooth LE. For security reasons, you must start Bluetooth
+LE advertising manually after powering up the device by pressing **Button 4**.
+
+### Bluetooth LE rendezvous
+
+In this example, the commissioning procedure is done over Bluetooth LE between a
+Matter device and the Matter controller, where the controller has the
+commissioner role.
+
+To start the rendezvous, the controller must get the commissioning information
+from the Matter device. The data payload is encoded within a QR code, printed to
+the UART console, and shared using an NFC tag. NFC tag emulation starts
+automatically when Bluetooth LE advertising is started and stays enabled until
+Bluetooth LE advertising timeout expires.
+
+#### Thread provisioning
+
+Last part of the rendezvous procedure, the provisioning operation involves
+sending the Thread network credentials from the Matter controller to the Matter
+device. As a result, the device is able to join the Thread network and
+communicate with other Thread devices in the network.
+
+### Device Firmware Upgrade
+
+The example supports over-the-air (OTA) device firmware upgrade (DFU) using one
+of the two available methods:
+
+- Matter OTA DFU that is mandatory for Matter-compliant devices. This option
+ is enabled by default.
+- [Simple Management Protocol](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/device_mgmt/index.html#device-mgmt)
+ over Bluetooth LE from Nordic Semiconductor's nRF Connect SDK. This is an
+ optional proprietary method that is not part of the Matter specification and
+ can be enabled to work alongside the default Matter OTA DFU.
+
+For both methods, the
+[MCUboot](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/mcuboot/index.html)
+bootloader solution is used to replace the old firmware image with the new one.
+
+#### Matter Over-the-Air DFU
+
+The Matter over-the-air DFU distinguishes two types of nodes: OTA Provider and
+OTA Requestor.
+
+An OTA Provider is a node that hosts a new firmware image and is able to respond
+on an OTA Requestor's queries regarding availability of new firmware images or
+requests to start sending the update packages.
+
+An OTA Requestor is a node that wants to download a new firmware image and sends
+requests to an OTA Provider to start the update process.
+
+#### Simple Management Protocol
+
+Simple Management Protocol (SMP) is a basic transfer encoding that is used for
+device management purposes, including application image management. SMP supports
+using different transports, such as Bluetooth LE, UDP, or serial USB/UART.
+
+In this example, the Matter device runs the SMP Server to download the
+application update image using the Bluetooth LE transport.
+
+See the
+[Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+section to learn how to enable SMP and use it for the DFU purpose in this
+example.
+
+#### Bootloader
+
+MCUboot is a secure bootloader used for swapping firmware images of different
+versions and generating proper build output files that can be used in the device
+firmware upgrade process.
+
+The bootloader solution requires an area of flash memory to swap application
+images during the firmware upgrade. Nordic Semiconductor devices use an external
+memory chip for this purpose. The memory chip communicates with the
+microcontroller through the QSPI bus.
+
+See the
+[Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+section to learn how to change MCUboot and flash configuration in this example.
+
+
+
+
+
+## Requirements
+
+The application requires a specific revision of the nRF Connect SDK to work
+correctly. See [Setting up the environment](#setting-up-the-environment) for
+more information.
+
+
+
+### Supported devices
+
+The example supports building and running on the following devices:
+
+| Hardware platform | Build target | Platform image |
+| ----------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
+| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` | nRF52840 DK
|
+| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` | nRF5340 DK
|
+
+### Additional requirements for testing
+
+If you want to test the Light Switch Example application with other devices, you
+also need to flash and program the following examples using the compatible
+development kits:
+
+- [Lighting Example Application](../../lighting-app/nrfconnect/README.md)
+
+Read the [CHIP Tool user guide](../../../docs/guides/chip_tool_guide.md) to
+learn how to commission the lighting device to the same Matter network using the
+CHIP Tool.
+
+
+
+
+
+## Device UI
+
+This section lists the User Interface elements that you can use to control and
+monitor the state of the device. These correspond to PCB components on the
+platform image.
+
+### LEDs
+
+This section describes all behaviors of LEDs located on platform image.
+
+**LED 1** 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 2** simulates the BLE DFU process. The following states are possible:
+
+- _Off_ — BLE is not advertising and DFU can not be performed.
+
+- _Rapid Even Flashing (30 ms off / 170 ms on)_ — BLE is advertising,
+ DFU process can be started.
+
+**LED 3** can be used to identify the device. The LED starts blinking evenly
+(500 ms on/500 ms off) when the Identify command of the Identify cluster is
+received. The command's argument can be used to specify the duration of the
+effect.
+
+### Buttons
+
+This section describes a reaction to pressing or holding buttons located on the
+platform image.
+
+**Button 1** can be used for the following purposes:
+
+- _Pressed for 6 s_ — Initiates the factory reset of the device.
+ Releasing the button within the 3-second window cancels the factory reset
+ procedure. **LEDs 1-4** blink in unison when the factory reset procedure is
+ initiated.
+
+- _Pressed for less than 3 s_ — Initiates the OTA software update
+ process. This feature is disabled by default, but can be enabled by
+ following the
+ [Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support)
+ instruction.
+
+**Button 2** can be used for the following purposes:
+
+- _Pressed once_ — Changes the light state to the opposite one on a
+ bound lighting bulb device ([lighting-app](../../lighting-app/nrfconnect/)
+ example).
+
+- _Pressed for more than 2 s_ — Changes the brightness of the light on a
+ bound lighting bulb device ([lighting-app](../../lighting-app/nrfconnect/)
+ example) (dimmer functionality). The brightness is changing from 0% to 100%
+ with 1% increments every 300 milliseconds as long as **Button 2** is
+ pressed.
+
+**Button 4** can be used to start the NFC tag emulation and enable Bluetooth LE
+advertising for the predefined period of time (15 minutes by default).
+
+**SEGGER J-Link USB port** can be used to get logs from the device or
+communicate with it using the
+[command line interface](../../../docs/guides/nrfconnect_examples_cli.md).
+
+**NFC port with antenna attached** can be used to start the
+[rendezvous](#bluetooth-le-rendezvous) by providing the commissioning
+information from the Matter device in a data payload that can be shared using
+NFC.
+
+### Matter CLI commands
+
+The Matter CLI allows to run commands via serial interface after USB cable
+connection to Nordic Semiconductor's kit.
+
+To enable the Matter CLI, you must compile the Light Switch Example application
+with the additional option **-DCONFIG_CHIP_LIB_SHELL=y**. Run the following
+command with _build-target_ replaced with the build target name of Nordic
+Semiconductor's kit you are using (for example, `nrf52840dk_nrf52840`):
+
+ west build -b build-target -- -DCONFIG_CHIP_LIB_SHELL=y
+
+You can use the following commands to control a device that is programmed with
+the Light Switch Example application by using the Matter CLI:
+
+ uart:~$ switch onoff on : sends unicast On command to bound device
+ uart:~$ switch onoff off : sends unicast Off command to bound device
+ uart:~$ switch onoff toggle : sends unicast Toggle command to bound device
+
+You can use the following commands a group of devices that are programmed with
+the Light Switch Example application by using the Matter CLI:
+
+ uart:~$ switch groups onoff on : sends multicast On command to all bound devices in a group
+ uart:~$ switch groups onoff off : sends multicast Off command to all bound devices in a group
+ uart:~$ switch groups onoff toggle : sends multicast Toggle command to all bound devices in a group
+
+Check the [CLI user guide](../../../docs/guides/nrfconnect_examples_cli.md) to
+learn how to use other CLI commands of the application.
+
+
+
+## Setting up the environment
+
+Before building the example, check out the Matter repository and sync submodules
+using the following command:
+
+ $ git submodule update --init
+
+The example requires a specific revision of the nRF Connect SDK. You can either
+install it along with the related tools directly on your system or use a Docker
+image that has the tools pre-installed.
+
+If you are a macOS user, you won't be able to use the Docker container to flash
+the application onto a Nordic development kit due to
+[certain limitations of Docker for macOS](https://docs.docker.com/docker-for-mac/faqs/#can-i-pass-through-a-usb-device-to-a-container).
+Use the [native shell](#using-native-shell) for building instead.
+
+### Using Docker container for setup
+
+To use the Docker container for setup, complete the following steps:
+
+1. If you do not have the nRF Connect SDK installed yet, create a directory for
+ it by running the following command:
+
+ $ mkdir ~/nrfconnect
+
+2. Download the latest version of the nRF Connect SDK Docker image by running
+ the following command:
+
+ $ docker pull nordicsemi/nrfconnect-chip
+
+3. Start Docker with the downloaded image by running the following command,
+ customized to your needs as described below:
+
+ $ docker run --rm -it -e RUNAS=$(id -u) -v ~/nrfconnect:/var/ncs -v ~/connectedhomeip:/var/chip \
+ -v /dev/bus/usb:/dev/bus/usb --device-cgroup-rule "c 189:* rmw" nordicsemi/nrfconnect-chip
+
+ In this command:
+
+ - _~/nrfconnect_ can be replaced with an absolute path to the nRF Connect
+ SDK source directory.
+ - _~/connectedhomeip_ must be replaced with an absolute path to the CHIP
+ source directory.
+ - _-v /dev/bus/usb:/dev/bus/usb --device-cgroup-rule "c 189:_ rmw"\*
+ parameters can be omitted if you are not planning to flash the example
+ onto hardware. These parameters give the container access to USB devices
+ connected to your computer such as the nRF52840 DK.
+ - _--rm_ can be omitted if you do not want the container to be
+ auto-removed when you exit the container shell session.
+ - _-e RUNAS=\$(id -u)_ is needed to start the container session as the
+ current user instead of root.
+
+4. Update the nRF Connect SDK to the most recent supported revision, by running
+ the following command:
+
+ $ cd /var/chip
+ $ python3 scripts/setup/nrfconnect/update_ncs.py --update
+
+Now you can proceed with the [Building](#building) instruction.
+
+### Using native shell for setup
+
+To use the native shell for setup, complete the following steps:
+
+1. Download and install the following additional software:
+
+ - [nRF Command Line Tools](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Command-Line-Tools)
+ - [GN meta-build system](https://gn.googlesource.com/gn/)
+
+2. If you do not have the nRF Connect SDK installed, follow the
+ [guide](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/gs_assistant.html#)
+ in the nRF Connect SDK documentation to install the latest stable nRF
+ Connect SDK version. Since command-line tools will be used for building the
+ example, installing SEGGER Embedded Studio is not required.
+
+ If you have the SDK already installed, continue to the next step and update
+ the nRF Connect SDK after initializing environment variables.
+
+3. Initialize environment variables referred to by the CHIP and the nRF Connect
+ SDK build scripts. Replace _nrfconnect-dir_ with the path to your nRF
+ Connect SDK installation directory, and _toolchain-dir_ with the path to GNU
+ Arm Embedded Toolchain.
+
+ $ source nrfconnect-dir/zephyr/zephyr-env.sh
+ $ export ZEPHYR_TOOLCHAIN_VARIANT=gnuarmemb
+ $ export GNUARMEMB_TOOLCHAIN_PATH=toolchain-dir
+
+4. Update the nRF Connect SDK to the most recent supported revision by running
+ the following command (replace _matter-dir_ with the path to Matter
+ repository directory):
+
+ $ cd matter-dir
+ $ python3 scripts/setup/nrfconnect/update_ncs.py --update
+
+Now you can proceed with the [Building](#building) instruction.
+
+
+
+
+
+## Building
+
+Complete the following steps, regardless of the method used for setting up the
+environment:
+
+1. Navigate to the example's directory:
+
+ $ cd examples/light-switch-app/nrfconnect
+
+2. Run the following command to build the example, with _build-target_ replaced
+ with the build target name of the Nordic Semiconductor's kit you own, for
+ example `nrf52840dk_nrf52840`:
+
+ $ west build -b build-target
+
+ You only need to specify the build target on the first build. See
+ [Requirements](#requirements) for the build target names of compatible kits.
+
+The output `zephyr.hex` file will be available in the `build/zephyr/` directory.
+
+### Removing build artifacts
+
+If you're planning to build the example for a different kit or make changes to
+the configuration, remove all build artifacts before building. To do so, use the
+following command:
+
+ $ rm -r build
+
+### Building with release configuration
+
+To build the example with release configuration that disables the diagnostic
+features like logs and command-line interface, run the following command:
+
+ $ west build -b build-target -- -DOVERLAY_CONFIG=third_party/connectedhomeip/config/nrfconnect/app/release.conf
+
+Remember to replace _build-target_ with the build target name of the Nordic
+Semiconductor's kit you own.
+
+### Building with low-power configuration
+
+You can build the example using the low-power configuration, which enables
+Thread's Sleepy End Device mode and disables debug features, such as the UART
+console or the **LED 1** usage.
+
+To build for the low-power configuration, run the following command with
+_build-target_ replaced with the build target name of the Nordic Semiconductor's
+kit you own (for example `nrf52840dk_nrf52840`):
+
+ $ west build -b build-target -- -DOVERLAY_CONFIG=overlay-low_power.conf
+
+For example, use the following command for `nrf52840dk_nrf52840`:
+
+ $ west build -b nrf52840dk_nrf52840 -- -DOVERLAY_CONFIG=overlay-low_power.conf
+
+### Building with Device Firmware Upgrade support
+
+Support for DFU using Matter OTA is enabled by default.
+
+To enable DFU over Bluetooth LE, run the following command with _build-target_
+replaced with the build target name of the Nordic Semiconductor kit you are
+using (for example `nrf52840dk_nrf52840`):
+
+ $ west build -b build-target -- -DBUILD_WITH_DFU=BLE
+
+To completely disable support for both DFU methods, run the following command
+with _build-target_ replaced with the build target name of the Nordic
+Semiconductor kit you are using (for example `nrf52840dk_nrf52840`):
+
+ $ west build -b build-target -- -DBUILD_WITH_DFU=OFF
+
+> **Note**:
+>
+> There are two types of Device Firmware Upgrade modes: single-image DFU and
+> multi-image DFU. Single-image mode supports upgrading only one firmware image,
+> the application image, and should be used for single-core nRF52840 DK devices.
+> Multi-image mode allows to upgrade more firmware images and is suitable for
+> upgrading the application core and network core firmware in two-core nRF5340
+> DK devices.
+
+#### Changing Device Firmware Upgrade configuration
+
+To change the default DFU configuration, edit the following overlay files
+corresponding to the selected configuration:
+
+- `overlay-mcuboot_qspi_nor_support.conf` - general file enabling MCUboot and
+ QSPI NOR support, used by all DFU configurations
+- `overlay-single_image_smp_dfu_support.conf` - file enabling single-image DFU
+ over Bluetooth LE using SMP
+- `overlay-multi_image_smp_dfu_support.conf` - file enabling multi-image DFU
+ over Bluetooth LE using SMP
+- `overlay-ota_requestor.conf` - file enabling Matter OTA Requestor support.
+
+The files are located in the `config/nrfconnect/app` directory. You can also
+define the desired options in your example's `prj.conf` file.
+
+#### Changing bootloader configuration
+
+To change the default MCUboot configuration, edit the
+`mcuboot_single_image_dfu.conf` or `mcuboot_multi_image_dfu.conf` overlay files
+depending on whether the build target device supports multi-image DFU (nRF5340
+DK) or single-image DFU (nRF52840 DK). The files are located in the
+`configuration` directory.
+
+Make sure to keep the configuration consistent with changes made to the
+application configuration. This is necessary for the configuration to work, as
+the bootloader image is a separate application from the user application and it
+has its own configuration file.
+
+#### Changing flash memory settings
+
+In the default configuration, the MCUboot uses the
+[Partition Manager](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#partition-manager)
+to configure flash partitions used for the bootloader application image slot
+purposes. You can change these settings by defining
+[static partitions](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/scripts/partition_manager/partition_manager.html#ug-pm-static).
+This example uses this option to define using an external flash.
+
+To modify the flash settings of your board (that is, your _build-target_, for
+example `nrf52840dk_nrf52840`), edit the `pm_static.yml` file located in the
+`configuration/build-target/` directory.
+
+
+
+
+
+## Configuring the example
+
+The Zephyr ecosystem is based on Kconfig files and the settings can be modified
+using the menuconfig utility.
+
+To open the menuconfig utility, run the following command from the example
+directory:
+
+ $ west build -b build-target -t menuconfig
+
+Remember to replace _build-target_ with the build target name of the Nordic
+Semiconductor's kit you own.
+
+Changes done with menuconfig will be lost if the `build` directory is deleted.
+To make them persistent, save the configuration options in the `prj.conf` file.
+For more information, see the
+[Configuring nRF Connect SDK examples](../../../docs/guides/nrfconnect_examples_configuration.md)
+page.
+
+
+
+
+
+## Flashing and debugging
+
+To flash the application to the device, use the west tool and run the following
+command from the example directory:
+
+ $ west flash --erase
+
+If you have multiple development kits connected, west will prompt you to pick
+the correct one.
+
+To debug the application on target, run the following command from the example
+directory:
+
+ $ west debug
+
+
+
+
+
+## Testing the example
+
+After building and flashing the example, you can test its functionalities. For
+this purpose, you need to prepare a second device that is programmed with the
+[Lighting Example](../../lighting-app/nrfconnect/), perform the binding process,
+and add Access Control Lists (ACLs).
+
+### Commissioning the lighting device
+
+To commission the Lighting Example Application to the same Matter network, read
+the [CHIP Tool user guide](../../../docs/guides/chip_tool_guide.md).
+
+### Binding cluster and endpoints
+
+Binding links clusters and endpoints on both devices, which enables them to
+communicate with each other.
+
+To perform binding, you need a controller that can write the binding table to
+the light switch device and write proper ACL to the endpoint light bulb on the
+[Lighting Example application](../../lighting-app/nrfconnect/)). For example,
+you can use the [CHIP Tool for Windows or Linux](../../chip-tool/README.md) as
+the controller. The ACL should contain information about all clusters that can
+be called by the light switch application. See the section about
+[interacting with ZCL clusters](../../../docs/guides/chip_tool_guide.md#interacting-with-zcl-clusters)
+in the CHIP Tool's user guide for more information about ACLs.
+
+You can perform the binding process to a single remote endpoint (unicast
+binding) or to a group of remote endpoints (group multicast).
+
+> **Note:** To use a light switch without brightness dimmer, apply only the
+> first binding command with cluster no. 6.
+
+#### Unicast binding to a remote endpoint using the CHIP Tool for Windows or Linux
+
+In this scenario, commands are provided for a light switch device with the
+`nodeId = 2` and a light bulb device with `nodeId = 1`, both commissioned to the
+same Matter network.
+
+To perform the unicast binding process, complete the following steps:
+
+1. Build the CHIP Tool according to the steps from the
+ [CHIP Tool user guide](../../../docs/guides/chip_tool_guide.md#building).
+2. Go to the CHIP Tool build directory.
+3. Add an ACL to the development kit that is programmed with the
+ [Lighting Application Example](../../lighting-app/nrfconnect/) by running
+ the following command:
+
+ chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": [2], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 1, "deviceType": null}]}]' 1 0
+
+ In this command:
+
+ - `{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}`
+ is an ACL for the communication with the CHIP Tool.
+ - `{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [2], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 1, "deviceType": null}]}`
+ is an ACL for binding (cluster no. 6 is the On/Off cluster and the
+ cluster no. 8 is the Level Control cluster).
+
+ This command adds permissions on the lighting application device that allows
+ it to receive commands from the light switch device.
+
+4. Add a binding table to the Light Switch binding cluster:
+
+ chip-tool binding write binding '[{"fabricIndex": 1, "node": 1, "endpoint": 1, "cluster": 6}, {"fabricIndex": 1, "node": 1, "endpoint": 1, "cluster": 8}]' 2 1
+
+ In this command:
+
+ - `{"fabricIndex": 1, "node": <1>, "endpoint": 1, "cluster": 6}` is a
+ binding for the On/Off cluster.
+ - `{"fabricIndex": 1, "node": <1>, "endpoint": 1, "cluster": 8}` is a
+ binding for the Level Control cluster.
+
+> **Note:** When a light switch device reboots, the binding table is restored
+> from flash memory and the device tries to bind a known device that is
+> programmed with the Lighting Application Example.
+
+#### Group multicast binding to the group of remote endpoints using the CHIP Tool for Windows or Linux
+
+The group multicast binding lets you control more than one lighting device at a
+time using a single light switch.
+
+The group multicast binding targets all development kits that are programmed
+with the [Lighting Application Example](../../lighting-app/nrfconnect/) and
+added to the same multicast group. After the binding is established, the light
+switch device can send multicast requests, and all of the devices in the bound
+groups can run the received command.
+
+In this scenario, commands are provided for a light switch device with the
+`nodeId = 2` and a light bulb device with `nodeId = 1`, both commissioned to the
+same Matter network.
+
+To perform the unicast binding process, complete the following steps:
+
+1. Build the CHIP Tool according to the steps from the
+ [CHIP Tool user guide](../../../docs/guides/chip_tool_guide.md#building).
+2. Go to the CHIP Tool build directory.
+3. Add an ACL to the [lighting endpoint](../../lighting-app/nrfconnect/)
+ permissions by running the following command:
+
+ chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": [2], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 1, "deviceType": null}]}]' 1 0
+
+ In this command:
+
+ - `{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}`
+ is an ACL for the communication with the CHIP Tool.
+ - `{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [2], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 1, "deviceType": null}]}`
+ is an ACL for binding (cluster `no. 6` is the On/Off cluster and the
+ cluster `no. 8` is the Level Control cluster).
+
+ This allows the lighting application device to receive commands from the
+ light switch device.
+
+4. Add the light switch device to the multicast group by running the following
+ command:
+
+ chip-tool tests TestGroupDemoConfig --nodeId 1
+
+5. Add all light bulbs to the same multicast group by applying command below
+ for each of the light bulbs, using the appropriate `` (the
+ user-defined ID of the node being commissioned except `2` due to use this
+ `` for light-switch) for each of them:
+
+ chip-tool tests TestGroupDemoConfig --nodeId
+
+6. Add Binding commands for group multicast:
+
+ chip-tool binding write binding '[{"fabricIndex": 1, "group": 257}]' 2 1
+
+### Testing the communication
+
+To test the communication between the light switch device and the bound devices,
+use [light switch buttons](#buttons) or
+[Matter CLI commands](#matter-cli-commands), as described in the
+[Device UI](#device-ui) section.
+
+### Testing Device Firmware Upgrade
+
+Read the
+[DFU tutorial](../../../docs/guides/nrfconnect_examples_software_update.md) to
+see how to upgrade your device firmware.
diff --git a/examples/light-switch-app/nrfconnect/boards/nrf52840dk_nrf52840.conf b/examples/light-switch-app/nrfconnect/boards/nrf52840dk_nrf52840.conf
new file mode 100644
index 00000000000000..fb419f0c7aa921
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/boards/nrf52840dk_nrf52840.conf
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2022 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.
+#
+
+CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
diff --git a/examples/light-switch-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay b/examples/light-switch-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
new file mode 100644
index 00000000000000..b03d3f032eb0e1
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+/ {
+ chosen {
+ nordic,pm-ext-flash = &mx25r64;
+ };
+
+ /*
+ * In some default configurations within the nRF Connect SDK,
+ * e.g. on nRF52840, the chosen zephyr,entropy node is &cryptocell.
+ * This devicetree overlay ensures that default is overridden wherever it
+ * is set, as this application uses the RNG node for entropy exclusively.
+ */
+
+ chosen {
+ zephyr,entropy = &rng;
+ };
+
+};
diff --git a/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.conf b/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.conf
new file mode 100644
index 00000000000000..ce2e61edce82ca
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.conf
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2022 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.
+#
+
+CONFIG_XOROSHIRO_RANDOM_GENERATOR=y
diff --git a/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay
new file mode 100644
index 00000000000000..16973a1b1570ee
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+/ {
+ chosen {
+ nordic,pm-ext-flash = &mx25r64;
+ };
+
+ soc {
+ /* Add a flash controller which has the compatible
+ * 'zephyr,sim-flash'. This will ensure that the flash
+ * simulator can use it. None of the other properties in this
+ * node is used for anything.
+ */
+ nordic_ram_flash_controller: nordic_ram-flash-controller@0 {
+ compatible = "zephyr,sim-flash";
+ reg = <0x00000000 DT_SIZE_K(40)>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ erase-value = <0xff>;
+ label = "nordic_ram_flash_flash_controller";
+
+ /* This node label must match that used in the flash
+ * simulator.
+ */
+ flash_sim0: flash_sim@0 {
+ status = "okay";
+ compatible = "soc-nv-flash";
+ label = "simulated_flash";
+ erase-block-size = <4096>;
+ write-block-size = <4>;
+ reg = <0x00000000 DT_SIZE_K(256)>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* This partition must be defined for
+ * MCUboot to find the partition ID
+ * of the primary slot for image 1,
+ * which is stored in this partition.
+ */
+ slot2_partition: partition@0 {
+ label = "image-2";
+ reg = <0x00000000 0x00000A000>;
+ };
+ };
+ };
+ };
+ };
+
+};
diff --git a/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg.conf b/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg.conf
new file mode 100644
index 00000000000000..329d787b50feab
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/child_image/multiprotocol_rpmsg.conf
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+CONFIG_BT_PERIPHERAL=y
+CONFIG_BT_CENTRAL=n
+CONFIG_BT_MAX_CONN=1
+CONFIG_BT_BUF_ACL_RX_SIZE=502
+CONFIG_BT_BUF_ACL_TX_SIZE=251
+CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
diff --git a/examples/light-switch-app/nrfconnect/configuration/mcuboot_multi_image_dfu.conf b/examples/light-switch-app/nrfconnect/configuration/mcuboot_multi_image_dfu.conf
new file mode 100644
index 00000000000000..2c4579fd928b52
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/configuration/mcuboot_multi_image_dfu.conf
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2022 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.
+#
+
+# QSPI configuration
+CONFIG_NORDIC_QSPI_NOR=y
+CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
+CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16
+
+CONFIG_BOOT_MAX_IMG_SECTORS=256
+
+# The following configurations are required to support simultaneous multi image update
+CONFIG_PCD_APP=y
+CONFIG_UPDATEABLE_IMAGE_NUMBER=2
+CONFIG_BOOT_UPGRADE_ONLY=y
+# The network core cannot access external flash directly. The flash simulator must be used to
+# provide a memory region that is used to forward the new firmware to the network core.
+CONFIG_FLASH_SIMULATOR=y
+CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y
+CONFIG_FLASH_SIMULATOR_STATS=n
+
+# bootloader size optimization
+CONFIG_LOG=n
+CONFIG_CONSOLE=n
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
+CONFIG_CONSOLE_HANDLER=n
+CONFIG_BOOT_BANNER=n
+CONFIG_TIMESLICING=n
+CONFIG_RESET_ON_FATAL_ERROR=n
+CONFIG_MULTITHREADING=n
+CONFIG_TICKLESS_KERNEL=n
+CONFIG_TIMEOUT_64BIT=n
+CONFIG_USE_SEGGER_RTT=n
+CONFIG_GPIO=n
+CONFIG_NRF_ENABLE_ICACHE=n
diff --git a/examples/light-switch-app/nrfconnect/configuration/mcuboot_single_image_dfu.conf b/examples/light-switch-app/nrfconnect/configuration/mcuboot_single_image_dfu.conf
new file mode 100644
index 00000000000000..56e61619aef7d4
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/configuration/mcuboot_single_image_dfu.conf
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2022 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.
+#
+
+# QSPI configuration
+CONFIG_NORDIC_QSPI_NOR=y
+CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
+CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16
+
+CONFIG_BOOT_MAX_IMG_SECTORS=256
+
+# bootloader size optimization
+CONFIG_LOG=n
+CONFIG_CONSOLE=n
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
+CONFIG_CONSOLE_HANDLER=n
+CONFIG_BOOT_BANNER=n
+CONFIG_TIMESLICING=n
+CONFIG_RESET_ON_FATAL_ERROR=n
+CONFIG_MULTITHREADING=n
+CONFIG_TICKLESS_KERNEL=n
+CONFIG_TIMEOUT_64BIT=n
+CONFIG_USE_SEGGER_RTT=n
+CONFIG_GPIO=n
+CONFIG_NRF_ENABLE_ICACHE=n
diff --git a/examples/light-switch-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static.yml b/examples/light-switch-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static.yml
new file mode 100644
index 00000000000000..9c26550c0902be
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/configuration/nrf52840dk_nrf52840/pm_static.yml
@@ -0,0 +1,38 @@
+mcuboot:
+ address: 0x0
+ size: 0x7000
+ region: flash_primary
+mcuboot_pad:
+ address: 0x7000
+ size: 0x200
+app:
+ address: 0x7200
+ size: 0xf0e00
+mcuboot_primary:
+ orig_span: &id001
+ - mcuboot_pad
+ - app
+ span: *id001
+ address: 0x7000
+ size: 0xf1000
+ region: flash_primary
+mcuboot_primary_app:
+ orig_span: &id002
+ - app
+ span: *id002
+ address: 0x7200
+ size: 0xf0e00
+settings_storage:
+ address: 0xf8000
+ size: 0x8000
+ region: flash_primary
+mcuboot_secondary:
+ address: 0x0
+ size: 0xf1000
+ device: MX25R64
+ region: external_flash
+external_flash:
+ address: 0xf1000
+ size: 0x70f000
+ device: MX25R64
+ region: external_flash
diff --git a/examples/light-switch-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static.yml b/examples/light-switch-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static.yml
new file mode 100644
index 00000000000000..9f9f677d8af4fc
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/configuration/nrf5340dk_nrf5340_cpuapp/pm_static.yml
@@ -0,0 +1,52 @@
+mcuboot:
+ address: 0x0
+ size: 0xC000
+ region: flash_primary
+mcuboot_pad:
+ address: 0xC000
+ size: 0x200
+app:
+ address: 0xC200
+ size: 0xebe00
+mcuboot_primary:
+ orig_span: &id001
+ - mcuboot_pad
+ - app
+ span: *id001
+ address: 0xC000
+ size: 0xec000
+ region: flash_primary
+mcuboot_primary_app:
+ orig_span: &id002
+ - app
+ span: *id002
+ address: 0xC200
+ size: 0xebe00
+settings_storage:
+ address: 0xf8000
+ size: 0x8000
+ region: flash_primary
+mcuboot_primary_1:
+ address: 0x0
+ size: 0x40000
+ device: flash_ctrl
+ region: ram_flash
+mcuboot_secondary:
+ address: 0x0
+ size: 0xec000
+ device: MX25R64
+ region: external_flash
+mcuboot_secondary_1:
+ address: 0xec000
+ size: 0x40000
+ device: MX25R64
+ region: external_flash
+external_flash:
+ address: 0x12C000
+ size: 0x6D4000
+ device: MX25R64
+ region: external_flash
+pcd_sram:
+ address: 0x20000000
+ size: 0x2000
+ region: sram_primary
diff --git a/examples/light-switch-app/nrfconnect/main/AppTask.cpp b/examples/light-switch-app/nrfconnect/main/AppTask.cpp
new file mode 100644
index 00000000000000..49605a58fdcf3a
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/AppTask.cpp
@@ -0,0 +1,588 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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 "BindingHandler.h"
+#include "LEDWidget.h"
+#include "LightSwitch.h"
+#include "ThreadUtil.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef CONFIG_CHIP_OTA_REQUESTOR
+#include "OTAUtil.h"
+#endif
+
+#include
+#include
+#include
+
+using namespace ::chip;
+using namespace ::chip::app;
+using namespace ::chip::Credentials;
+using namespace ::chip::DeviceLayer;
+
+LOG_MODULE_DECLARE(app);
+namespace {
+constexpr EndpointId kLightSwitchEndpointId = 1;
+constexpr EndpointId kLightEndpointId = 1;
+constexpr uint32_t kFactoryResetTriggerTimeout = 3000;
+constexpr uint32_t kFactoryResetCancelWindow = 3000;
+constexpr uint32_t kDimmerTriggeredTimeout = 500;
+constexpr uint32_t kDimmerInterval = 300;
+constexpr uint32_t kIdentifyBlinkRateMs = 500;
+constexpr size_t kAppEventQueueSize = 10;
+
+K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
+
+Identify sIdentify = { kLightEndpointId, AppTask::IdentifyStartHandler, AppTask::IdentifyStopHandler,
+ EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED };
+
+LEDWidget sStatusLED;
+LEDWidget sBleLED;
+LEDWidget sIdentifyLED;
+LEDWidget sUnusedLED;
+
+bool sIsThreadProvisioned = false;
+bool sIsThreadEnabled = false;
+bool sIsThreadBLEAdvertising = false;
+bool sIsSMPAdvertising = false;
+bool sHaveBLEConnections = false;
+bool sWasDimmerTriggered = false;
+
+k_timer sFunctionTimer;
+k_timer sDimmerPressKeyTimer;
+k_timer sDimmerTimer;
+
+} /* namespace */
+
+AppTask AppTask::sAppTask;
+
+CHIP_ERROR AppTask::Init()
+{
+ // Initialize CHIP
+ LOG_INF("Init CHIP stack");
+
+ CHIP_ERROR err = Platform::MemoryInit();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("Platform::MemoryInit() failed");
+ return err;
+ }
+
+ err = PlatformMgr().InitChipStack();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("PlatformMgr().InitChipStack() failed");
+ return err;
+ }
+
+ err = ThreadStackMgr().InitThreadStack();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("ThreadStackMgr().InitThreadStack() failed: %s", ErrorStr(err));
+ return err;
+ }
+
+#ifdef CONFIG_OPENTHREAD_MTD_SED
+ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice);
+#elif CONFIG_OPENTHREAD_MTD
+ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice);
+#else
+ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_FullEndDevice);
+#endif
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("ConnectivityMgr().SetThreadDeviceType() failed: %s", ErrorStr(err));
+ return err;
+ }
+
+ LightSwitch::GetInstance().Init(kLightSwitchEndpointId);
+
+ // Initialize UI components
+ LEDWidget::InitGpio();
+ LEDWidget::SetStateUpdateCallback(LEDStateUpdateHandler);
+ sStatusLED.Init(SYSTEM_STATE_LED);
+ sBleLED.Init(DFU_BLE_LED);
+ sIdentifyLED.Init(IDENTIFY_LED);
+ sUnusedLED.Init(DK_LED4);
+ UpdateStatusLED();
+
+ int ret = dk_buttons_init(ButtonEventHandler);
+
+ if (ret)
+ {
+ LOG_ERR("dk_buttons_init() failed");
+ return System::MapErrorZephyr(ret);
+ }
+
+ // Initialize Timers
+ k_timer_init(&sFunctionTimer, AppTask::TimerEventHandler, nullptr);
+ k_timer_init(&sDimmerPressKeyTimer, AppTask::TimerEventHandler, nullptr);
+ k_timer_init(&sDimmerTimer, AppTask::TimerEventHandler, nullptr);
+ k_timer_user_data_set(&sDimmerTimer, this);
+ k_timer_user_data_set(&sDimmerPressKeyTimer, this);
+ k_timer_user_data_set(&sFunctionTimer, this);
+
+ // Initialize DFU
+#ifdef CONFIG_MCUMGR_SMP_BT
+ GetDFUOverSMP().Init(RequestSMPAdvertisingStart);
+ GetDFUOverSMP().ConfirmNewImage();
+#endif
+
+ // Print initial configs
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+ ReturnErrorOnFailure(Server::GetInstance().Init());
+#if CONFIG_CHIP_OTA_REQUESTOR
+ InitBasicOTARequestor();
+#endif
+ ConfigurationMgr().LogDeviceConfig();
+ PrintOnboardingCodes(RendezvousInformationFlags(RendezvousInformationFlag::kBLE));
+
+ // Add CHIP event handler and start CHIP thread.
+ // Note that all the initialization code should happen prior to this point
+ // to avoid data races between the main and the CHIP threads.
+ PlatformMgr().AddEventHandler(ChipEventHandler, 0);
+
+ err = PlatformMgr().StartEventLoopTask();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("PlatformMgr().StartEventLoopTask() failed");
+ return err;
+ }
+
+ return err;
+}
+
+CHIP_ERROR AppTask::StartApp()
+{
+ ReturnErrorOnFailure(Init());
+
+ AppEvent event{};
+
+ while (true)
+ {
+ k_msgq_get(&sAppEventQueue, &event, K_FOREVER);
+ DispatchEvent(&event);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+void AppTask::ButtonPushHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type == AppEvent::kEventType_Button)
+ {
+ switch (aEvent->ButtonEvent.PinNo)
+ {
+ case FUNCTION_BUTTON:
+ sAppTask.StartTimer(Timer::Function, kFactoryResetTriggerTimeout);
+ sAppTask.mFunction = TimerFunction::SoftwareUpdate;
+ break;
+ case SWITCH_BUTTON:
+ LOG_INF("Button has been pressed, keep in this state for at least 500 ms to change light sensitivity of binded "
+ "lighting devices.");
+ sAppTask.StartTimer(Timer::DimmerTrigger, kDimmerTriggeredTimeout);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void AppTask::ButtonReleaseHandler(AppEvent * aEvent)
+{
+
+ if (aEvent->Type == AppEvent::kEventType_Button)
+ {
+ switch (aEvent->ButtonEvent.PinNo)
+ {
+ case FUNCTION_BUTTON:
+ if (sAppTask.mFunction == TimerFunction::SoftwareUpdate)
+ {
+ sAppTask.CancelTimer(Timer::Function);
+ sAppTask.mFunction = TimerFunction::NoneSelected;
+
+#ifdef CONFIG_MCUMGR_SMP_BT
+ GetDFUOverSMP().StartServer();
+ sIsSMPAdvertising = true;
+ UpdateStatusLED();
+#else
+ LOG_INF("Software update is disabled");
+#endif
+ }
+ else if (sAppTask.mFunction == TimerFunction::FactoryReset)
+ {
+ UpdateStatusLED();
+
+ sAppTask.CancelTimer(Timer::Function);
+ sAppTask.mFunction = TimerFunction::NoneSelected;
+ LOG_INF("Factory Reset has been canceled");
+ }
+ break;
+ case SWITCH_BUTTON:
+ if (!sWasDimmerTriggered)
+ {
+ LightSwitch::GetInstance().InitiateActionSwitch(LightSwitch::Action::Toggle);
+ }
+ sAppTask.CancelTimer(Timer::Dimmer);
+ sAppTask.CancelTimer(Timer::DimmerTrigger);
+ sWasDimmerTriggered = false;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void AppTask::TimerEventHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type == AppEvent::kEventType_Timer)
+ {
+ switch ((Timer) aEvent->TimerEvent.TimerType)
+ {
+ case Timer::Function:
+ if (sAppTask.mFunction == TimerFunction::SoftwareUpdate)
+ {
+ LOG_INF("Factory Reset has been triggered. Release button within %u ms to cancel.", kFactoryResetCancelWindow);
+ sAppTask.StartTimer(Timer::Function, kFactoryResetCancelWindow);
+ sAppTask.mFunction = TimerFunction::FactoryReset;
+
+#ifdef CONFIG_STATE_LEDS
+ // reset all LEDs to synchronize factory reset blinking
+ sStatusLED.Set(false);
+ sIdentifyLED.Set(false);
+ sBleLED.Set(false);
+ sUnusedLED.Set(false);
+
+ sStatusLED.Blink(500);
+ sIdentifyLED.Blink(500);
+ sBleLED.Blink(500);
+ sUnusedLED.Blink(500);
+#endif
+ }
+ else if (sAppTask.mFunction == TimerFunction::FactoryReset)
+ {
+ sAppTask.mFunction = TimerFunction::NoneSelected;
+ LOG_INF("Factory Reset triggered");
+ ConfigurationMgr().InitiateFactoryReset();
+ }
+ break;
+ case Timer::DimmerTrigger:
+ LOG_INF("Dimming started...");
+ sWasDimmerTriggered = true;
+ LightSwitch::GetInstance().InitiateActionSwitch(LightSwitch::Action::On);
+ sAppTask.StartTimer(Timer::Dimmer, kDimmerInterval);
+ sAppTask.CancelTimer(Timer::DimmerTrigger);
+ break;
+ case Timer::Dimmer:
+ LightSwitch::GetInstance().DimmerChangeBrightness();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void AppTask::IdentifyStartHandler(Identify *)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_IdentifyStart;
+ event.Handler = [](AppEvent *) { sIdentifyLED.Blink(kIdentifyBlinkRateMs); };
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::IdentifyStopHandler(Identify *)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_IdentifyStop;
+ event.Handler = [](AppEvent *) { sIdentifyLED.Set(false); };
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::StartBLEAdvertisingHandler(AppEvent * aEvent)
+{
+ /// Don't allow on starting Matter service BLE advertising after Thread provisioning.
+ if (Server::GetInstance().GetFabricTable().FabricCount() != 0)
+ {
+ LOG_INF("Matter service BLE advertising not started - device is already commissioned");
+ return;
+ }
+
+ if (ConnectivityMgr().IsBLEAdvertisingEnabled())
+ {
+ LOG_INF("BLE advertising is already enabled");
+ return;
+ }
+
+ LOG_INF("Enabling BLE advertising...");
+ if (Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() != CHIP_NO_ERROR)
+ {
+ LOG_ERR("OpenBasicCommissioningWindow() failed");
+ }
+}
+
+void AppTask::ChipEventHandler(const ChipDeviceEvent * aEvent, intptr_t /* arg */)
+{
+ switch (aEvent->Type)
+ {
+ case DeviceEventType::kCHIPoBLEAdvertisingChange:
+ sIsThreadBLEAdvertising = true;
+ UpdateStatusLED();
+#ifdef CONFIG_CHIP_NFC_COMMISSIONING
+ if (aEvent->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
+ {
+ if (NFCMgr().IsTagEmulationStarted())
+ {
+ LOG_INF("NFC Tag emulation is already started");
+ }
+ else
+ {
+ ShareQRCodeOverNFC(RendezvousInformationFlags(RendezvousInformationFlag::kBLE));
+ }
+ }
+ else if (aEvent->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
+ {
+ NFCMgr().StopTagEmulation();
+ }
+#endif
+ sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
+ UpdateStatusLED();
+ break;
+ case DeviceEventType::kThreadStateChange:
+ sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
+ sIsThreadEnabled = ConnectivityMgr().IsThreadEnabled();
+ UpdateStatusLED();
+ break;
+ default:
+ if ((ConnectivityMgr().NumBLEConnections() == 0) && (!sIsThreadProvisioned || !sIsThreadEnabled))
+ {
+ LOG_ERR("Commissioning with a Thread network has not been done. An error occurred...");
+ sIsThreadBLEAdvertising = false;
+ sHaveBLEConnections = false;
+ UpdateStatusLED();
+ }
+ break;
+ }
+}
+
+void AppTask::UpdateStatusLED()
+{
+#ifdef CONFIG_STATE_LEDS
+ sUnusedLED.Set(false);
+
+ // Status LED indicates:
+ // - blinking 1 s - advertising, ready to commission
+ // - blinking 200 ms - commissioning in progress
+ // - constant lightning means commissioned with Thread network
+ if (sIsThreadBLEAdvertising && !sHaveBLEConnections)
+ {
+ sStatusLED.Blink(50, 950);
+ }
+ else if (sIsThreadProvisioned && sIsThreadEnabled)
+ {
+ sStatusLED.Set(true);
+ }
+ else if (sHaveBLEConnections)
+ {
+ sStatusLED.Blink(30, 170);
+ }
+ else
+ {
+ sStatusLED.Set(false);
+ }
+
+ // Ble LED indicates BLE connectivity:
+ //- blinking 200 ms means BLE advertising
+ if (sIsSMPAdvertising)
+ {
+ sBleLED.Blink(30, 170);
+ }
+ else
+ {
+ sBleLED.Set(false);
+ }
+#endif
+}
+
+void AppTask::ButtonEventHandler(uint32_t aButtonState, uint32_t aHasChanged)
+{
+
+ AppEvent buttonEvent;
+ buttonEvent.Type = AppEvent::kEventType_Button;
+
+ if (FUNCTION_BUTTON_MASK & aButtonState & aHasChanged)
+ {
+ buttonEvent.ButtonEvent.PinNo = FUNCTION_BUTTON;
+ buttonEvent.ButtonEvent.Action = AppEvent::kButtonPushEvent;
+ buttonEvent.Handler = ButtonPushHandler;
+ sAppTask.PostEvent(&buttonEvent);
+ }
+ else if (FUNCTION_BUTTON_MASK & aHasChanged)
+ {
+ buttonEvent.ButtonEvent.PinNo = FUNCTION_BUTTON;
+ buttonEvent.ButtonEvent.Action = AppEvent::kButtonReleaseEvent;
+ buttonEvent.Handler = ButtonReleaseHandler;
+ sAppTask.PostEvent(&buttonEvent);
+ }
+
+ if (SWITCH_BUTTON_MASK & aButtonState & aHasChanged)
+ {
+ buttonEvent.ButtonEvent.PinNo = SWITCH_BUTTON;
+ buttonEvent.ButtonEvent.Action = AppEvent::kButtonPushEvent;
+ buttonEvent.Handler = ButtonPushHandler;
+ sAppTask.PostEvent(&buttonEvent);
+ }
+ else if (SWITCH_BUTTON_MASK & aHasChanged)
+ {
+ buttonEvent.ButtonEvent.PinNo = SWITCH_BUTTON;
+ buttonEvent.ButtonEvent.Action = AppEvent::kButtonReleaseEvent;
+ buttonEvent.Handler = ButtonReleaseHandler;
+ sAppTask.PostEvent(&buttonEvent);
+ }
+
+ if (BLE_ADVERTISEMENT_START_BUTTON_MASK & aHasChanged & aButtonState)
+ {
+ buttonEvent.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_BUTTON;
+ buttonEvent.ButtonEvent.Action = AppEvent::kButtonPushEvent;
+ buttonEvent.Handler = StartBLEAdvertisingHandler;
+ sAppTask.PostEvent(&buttonEvent);
+ }
+}
+
+void AppTask::StartTimer(Timer aTimer, uint32_t aTimeoutMs)
+{
+ switch (aTimer)
+ {
+ case Timer::Function:
+ k_timer_start(&sFunctionTimer, K_MSEC(aTimeoutMs), K_NO_WAIT);
+ break;
+ case Timer::DimmerTrigger:
+ k_timer_start(&sDimmerPressKeyTimer, K_MSEC(aTimeoutMs), K_NO_WAIT);
+ break;
+ case Timer::Dimmer:
+ k_timer_start(&sDimmerTimer, K_MSEC(aTimeoutMs), K_MSEC(aTimeoutMs));
+ break;
+ default:
+ break;
+ }
+}
+
+void AppTask::CancelTimer(Timer aTimer)
+{
+ switch (aTimer)
+ {
+ case Timer::Function:
+ k_timer_stop(&sFunctionTimer);
+ break;
+ case Timer::DimmerTrigger:
+ k_timer_stop(&sDimmerPressKeyTimer);
+ break;
+ case Timer::Dimmer:
+ k_timer_stop(&sDimmerTimer);
+ break;
+ default:
+ break;
+ }
+}
+
+void AppTask::UpdateLedStateEventHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type == AppEvent::kEventType_UpdateLedState)
+ {
+ aEvent->UpdateLedStateEvent.LedWidget->UpdateState();
+ }
+}
+
+void AppTask::LEDStateUpdateHandler(LEDWidget & aLedWidget)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_UpdateLedState;
+ event.Handler = UpdateLedStateEventHandler;
+ event.UpdateLedStateEvent.LedWidget = &aLedWidget;
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::TimerEventHandler(k_timer * aTimer)
+{
+ AppEvent event;
+ if (aTimer == &sFunctionTimer)
+ {
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.TimerType = (uint8_t) Timer::Function;
+ event.TimerEvent.Context = k_timer_user_data_get(aTimer);
+ event.Handler = TimerEventHandler;
+ sAppTask.PostEvent(&event);
+ }
+ if (aTimer == &sDimmerPressKeyTimer)
+ {
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.TimerType = (uint8_t) Timer::DimmerTrigger;
+ event.TimerEvent.Context = k_timer_user_data_get(aTimer);
+ event.Handler = TimerEventHandler;
+ sAppTask.PostEvent(&event);
+ }
+ if (aTimer == &sDimmerTimer)
+ {
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.TimerType = (uint8_t) Timer::Dimmer;
+ event.TimerEvent.Context = k_timer_user_data_get(aTimer);
+ event.Handler = TimerEventHandler;
+ sAppTask.PostEvent(&event);
+ }
+}
+
+#ifdef CONFIG_MCUMGR_SMP_BT
+void AppTask::RequestSMPAdvertisingStart(void)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_StartSMPAdvertising;
+ event.Handler = [](AppEvent *) { GetDFUOverSMP().StartBLEAdvertising(); };
+ sAppTask.PostEvent(&event);
+}
+#endif
+
+void AppTask::PostEvent(AppEvent * aEvent)
+{
+ if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT) != 0)
+ {
+ LOG_INF("Failed to post event to app task event queue");
+ }
+}
+
+void AppTask::DispatchEvent(AppEvent * aEvent)
+{
+ if (aEvent->Handler)
+ {
+ aEvent->Handler(aEvent);
+ }
+ else
+ {
+ LOG_INF("Event received with no handler. Dropping event.");
+ }
+}
diff --git a/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp b/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp
new file mode 100644
index 00000000000000..7fb16ad754d005
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp
@@ -0,0 +1,269 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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 "BindingHandler.h"
+#ifdef CONFIG_CHIP_LIB_SHELL
+#include "ShellCommands.h"
+#endif
+
+#include
+LOG_MODULE_DECLARE(app);
+
+using namespace chip;
+using namespace chip::app;
+
+void BindingHandler::Init()
+{
+#ifdef CONFIG_CHIP_LIB_SHELL
+ SwitchCommands::RegisterSwitchCommands();
+#endif
+ DeviceLayer::PlatformMgr().ScheduleWork(InitInternal);
+}
+
+void BindingHandler::OnOffProcessCommand(CommandId aCommandId, const EmberBindingTableEntry & aBinding, DeviceProxy * aDevice,
+ void * aContext)
+{
+ CHIP_ERROR ret = CHIP_NO_ERROR;
+
+ auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
+ LOG_DBG("Binding command applied successfully!");
+ };
+
+ auto onFailure = [](CHIP_ERROR error) {
+ LOG_INF("Binding command was not applied! Reason: %" CHIP_ERROR_FORMAT, error.Format());
+ };
+
+ switch (aCommandId)
+ {
+ case Clusters::OnOff::Commands::Toggle::Id:
+ Clusters::OnOff::Commands::Toggle::Type toggleCommand;
+ if (aDevice)
+ {
+ ret = Controller::InvokeCommandRequest(aDevice->GetExchangeManager(), aDevice->GetSecureSession().Value(),
+ aBinding.remote, toggleCommand, onSuccess, onFailure);
+ }
+ else
+ {
+
+ NodeId sourceNodeId = Server::GetInstance().GetFabricTable().FindFabricWithIndex(aBinding.fabricIndex)->GetNodeId();
+ Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+ ret = Controller::InvokeGroupCommandRequest(&exchangeMgr, aBinding.fabricIndex, aBinding.groupId, sourceNodeId,
+ toggleCommand);
+ }
+ break;
+
+ case Clusters::OnOff::Commands::On::Id:
+ Clusters::OnOff::Commands::On::Type onCommand;
+ if (aDevice)
+ {
+ ret = Controller::InvokeCommandRequest(aDevice->GetExchangeManager(), aDevice->GetSecureSession().Value(),
+ aBinding.remote, onCommand, onSuccess, onFailure);
+ }
+ else
+ {
+ NodeId sourceNodeId = Server::GetInstance().GetFabricTable().FindFabricWithIndex(aBinding.fabricIndex)->GetNodeId();
+ Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+ ret = Controller::InvokeGroupCommandRequest(&exchangeMgr, aBinding.fabricIndex, aBinding.groupId, sourceNodeId,
+ onCommand);
+ }
+ break;
+
+ case Clusters::OnOff::Commands::Off::Id:
+ Clusters::OnOff::Commands::Off::Type offCommand;
+ if (aDevice)
+ {
+ ret = Controller::InvokeCommandRequest(aDevice->GetExchangeManager(), aDevice->GetSecureSession().Value(),
+ aBinding.remote, offCommand, onSuccess, onFailure);
+ }
+ else
+ {
+ NodeId sourceNodeId = Server::GetInstance().GetFabricTable().FindFabricWithIndex(aBinding.fabricIndex)->GetNodeId();
+ Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+ ret = Controller::InvokeGroupCommandRequest(&exchangeMgr, aBinding.fabricIndex, aBinding.groupId, sourceNodeId,
+ onCommand);
+ }
+ break;
+ default:
+ LOG_DBG("Invalid binding command data - commandId is not supported");
+ break;
+ }
+ if (CHIP_NO_ERROR != ret)
+ {
+ LOG_ERR("Invoke OnOff Command Request ERROR: %s", ErrorStr(ret));
+ }
+}
+
+void BindingHandler::LevelControlProcessCommand(CommandId aCommandId, const EmberBindingTableEntry & aBinding,
+ DeviceProxy * aDevice, void * aContext)
+{
+ auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
+ LOG_DBG("Binding command applied successfully!");
+ };
+
+ auto onFailure = [](CHIP_ERROR error) {
+ LOG_INF("Binding command was not applied! Reason: %" CHIP_ERROR_FORMAT, error.Format());
+ };
+
+ CHIP_ERROR ret = CHIP_NO_ERROR;
+
+ switch (aCommandId)
+ {
+ case Clusters::LevelControl::Commands::MoveToLevel::Id: {
+ Clusters::LevelControl::Commands::MoveToLevel::Type moveToLevelCommand;
+ BindingData * data = reinterpret_cast(aContext);
+ moveToLevelCommand.level = data->Value;
+ if (aDevice)
+ {
+ ret = Controller::InvokeCommandRequest(aDevice->GetExchangeManager(), aDevice->GetSecureSession().Value(),
+ aBinding.remote, moveToLevelCommand, onSuccess, onFailure);
+ }
+ else
+ {
+ NodeId sourceNodeId = Server::GetInstance().GetFabricTable().FindFabricWithIndex(aBinding.fabricIndex)->GetNodeId();
+ Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+ ret = Controller::InvokeGroupCommandRequest(&exchangeMgr, aBinding.fabricIndex, aBinding.groupId, sourceNodeId,
+ moveToLevelCommand);
+ }
+ }
+ break;
+ default:
+ LOG_DBG("Invalid binding command data - commandId is not supported");
+ break;
+ }
+ if (CHIP_NO_ERROR != ret)
+ {
+ LOG_ERR("Invoke Group Command Request ERROR: %s", ErrorStr(ret));
+ }
+}
+
+void BindingHandler::LightSwitchChangedHandler(const EmberBindingTableEntry & binding, DeviceProxy * deviceProxy, void * context)
+{
+ VerifyOrReturn(context != nullptr, LOG_ERR("Invalid context for Light switch handler"););
+ BindingData * data = static_cast(context);
+
+ if (binding.type == EMBER_MULTICAST_BINDING && data->IsGroup)
+ {
+ switch (data->ClusterId)
+ {
+ case Clusters::OnOff::Id:
+ OnOffProcessCommand(data->CommandId, binding, nullptr, context);
+ break;
+ case Clusters::LevelControl::Id:
+ LevelControlProcessCommand(data->CommandId, binding, nullptr, context);
+ break;
+ default:
+ ChipLogError(NotSpecified, "Invalid binding group command data");
+ break;
+ }
+ }
+ else if (binding.type == EMBER_UNICAST_BINDING && !data->IsGroup)
+ {
+ switch (data->ClusterId)
+ {
+ case Clusters::OnOff::Id:
+ OnOffProcessCommand(data->CommandId, binding, deviceProxy, context);
+ break;
+ case Clusters::LevelControl::Id:
+ LevelControlProcessCommand(data->CommandId, binding, deviceProxy, context);
+ break;
+ default:
+ ChipLogError(NotSpecified, "Invalid binding unicast command data");
+ break;
+ }
+ }
+}
+
+void BindingHandler::InitInternal(intptr_t aArg)
+{
+ LOG_INF("Initialize binding Handler");
+ auto & server = Server::GetInstance();
+ if (CHIP_NO_ERROR !=
+ BindingManager::GetInstance().Init(
+ { &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() }))
+ {
+ LOG_ERR("BindingHandler::InitInternal failed");
+ }
+
+ BindingManager::GetInstance().RegisterBoundDeviceChangedHandler(LightSwitchChangedHandler);
+ PrintBindingTable();
+}
+
+bool BindingHandler::IsGroupBound()
+{
+ BindingTable & bindingTable = BindingTable::GetInstance();
+
+ for (auto & entry : bindingTable)
+ {
+ if (EMBER_MULTICAST_BINDING == entry.type)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void BindingHandler::PrintBindingTable()
+{
+ BindingTable & bindingTable = BindingTable::GetInstance();
+
+ LOG_INF("Binding Table size: [%d]:", bindingTable.Size());
+ uint8_t i = 0;
+ for (auto & entry : bindingTable)
+ {
+ switch (entry.type)
+ {
+ case EMBER_UNICAST_BINDING:
+ LOG_INF("[%d] UNICAST:", i++);
+ LOG_INF("\t\t+ Fabric: %d\n \
+ \t+ LocalEndpoint %d \n \
+ \t+ ClusterId %d \n \
+ \t+ RemoteEndpointId %d \n \
+ \t+ NodeId %d",
+ (int) entry.fabricIndex, (int) entry.local, (int) entry.clusterId.Value(), (int) entry.remote,
+ (int) entry.nodeId);
+ break;
+ case EMBER_MULTICAST_BINDING:
+ LOG_INF("[%d] GROUP:", i++);
+ LOG_INF("\t\t+ Fabric: %d\n \
+ \t+ LocalEndpoint %d \n \
+ \t+ RemoteEndpointId %d \n \
+ \t+ GroupId %d",
+ (int) entry.fabricIndex, (int) entry.local, (int) entry.remote, (int) entry.groupId);
+ break;
+ case EMBER_UNUSED_BINDING:
+ LOG_INF("[%d] UNUSED", i++);
+ break;
+ case EMBER_MANY_TO_ONE_BINDING:
+ LOG_INF("[%d] MANY TO ONE", i++);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void BindingHandler::SwitchWorkerHandler(intptr_t aContext)
+{
+ VerifyOrReturn(aContext != 0, LOG_ERR("Invalid Swich data"));
+
+ BindingData * data = reinterpret_cast(aContext);
+ LOG_INF("Notify Bounded Cluster | endpoint: %d cluster: %d", data->EndpointId, data->ClusterId);
+ BindingManager::GetInstance().NotifyBoundClusterChanged(data->EndpointId, data->ClusterId, static_cast(data));
+
+ Platform::Delete(data);
+}
diff --git a/examples/light-switch-app/nrfconnect/main/LightSwitch.cpp b/examples/light-switch-app/nrfconnect/main/LightSwitch.cpp
new file mode 100644
index 00000000000000..275dcdceccf1f4
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/LightSwitch.cpp
@@ -0,0 +1,84 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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 "LightSwitch.h"
+#include "AppEvent.h"
+#include "BindingHandler.h"
+
+#include
+#include
+#include
+
+using namespace chip;
+using namespace chip::app;
+
+void LightSwitch::Init(chip::EndpointId aLightSwitchEndpoint)
+{
+ BindingHandler::Init();
+ mLightSwitchEndpoint = aLightSwitchEndpoint;
+}
+
+void LightSwitch::InitiateActionSwitch(Action mAction)
+{
+ BindingHandler::BindingData * data = Platform::New();
+ if (data)
+ {
+ data->EndpointId = mLightSwitchEndpoint;
+ data->ClusterId = Clusters::OnOff::Id;
+ switch (mAction)
+ {
+ case Action::Toggle:
+ data->CommandId = Clusters::OnOff::Commands::Toggle::Id;
+ break;
+ case Action::On:
+ data->CommandId = Clusters::OnOff::Commands::On::Id;
+ break;
+ case Action::Off:
+ data->CommandId = Clusters::OnOff::Commands::Off::Id;
+ break;
+ default:
+ Platform::Delete(data);
+ return;
+ }
+ data->IsGroup = BindingHandler::IsGroupBound();
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data));
+ Platform::Delete(data);
+ }
+}
+
+void LightSwitch::DimmerChangeBrightness()
+{
+ static uint16_t sBrightness;
+ BindingHandler::BindingData * data = Platform::New();
+ if (data)
+ {
+ data->EndpointId = mLightSwitchEndpoint;
+ data->CommandId = Clusters::LevelControl::Commands::MoveToLevel::Id;
+ data->ClusterId = Clusters::LevelControl::Id;
+ // add to brightness 3 to approximate 1% step of brightness after each call dimmer change.
+ sBrightness += kOnePercentBrightnessApproximation;
+ if (sBrightness > kMaximumBrightness)
+ {
+ sBrightness = 0;
+ }
+ data->Value = (uint8_t) sBrightness;
+ data->IsGroup = BindingHandler::IsGroupBound();
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data));
+ Platform::Delete(data);
+ }
+}
diff --git a/examples/light-switch-app/nrfconnect/main/ShellCommands.cpp b/examples/light-switch-app/nrfconnect/main/ShellCommands.cpp
new file mode 100644
index 00000000000000..4dc0a3db58258c
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/ShellCommands.cpp
@@ -0,0 +1,225 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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 "ShellCommands.h"
+#include "LightSwitch.h"
+#include
+
+#include "BindingHandler.h"
+
+#ifdef CONFIG_CHIP_LIB_SHELL
+
+using namespace chip;
+using namespace chip::app;
+
+namespace SwitchCommands {
+using Shell::Engine;
+using Shell::shell_command_t;
+using Shell::streamer_get;
+using Shell::streamer_printf;
+
+Engine sShellSwitchSubCommands;
+Engine sShellSwitchOnOffSubCommands;
+Engine sShellSwitchGroupsSubCommands;
+Engine sShellSwitchGroupsOnOffSubCommands;
+
+static CHIP_ERROR SwitchHelpHandler(int argc, char ** argv)
+{
+ sShellSwitchSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+static CHIP_ERROR SwitchCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return SwitchHelpHandler(argc, argv);
+ }
+ return sShellSwitchSubCommands.ExecCommand(argc, argv);
+}
+
+static CHIP_ERROR TableCommandHelper(int argc, char ** argv)
+{
+ BindingHandler::PrintBindingTable();
+ return CHIP_NO_ERROR;
+}
+
+namespace Unicast {
+
+static CHIP_ERROR OnOffHelpHandler(int argc, char ** argv)
+{
+ sShellSwitchOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+static CHIP_ERROR OnOffCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return OnOffHelpHandler(argc, argv);
+ }
+ return sShellSwitchOnOffSubCommands.ExecCommand(argc, argv);
+}
+
+static CHIP_ERROR OnCommandHandler(int argc, char ** argv)
+{
+ BindingHandler::BindingData * data = Platform::New();
+ data->EndpointId = LightSwitch::GetInstance().GetLightSwitchEndpointId();
+ data->CommandId = Clusters::OnOff::Commands::On::Id;
+ data->ClusterId = Clusters::OnOff::Id;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+static CHIP_ERROR OffCommandHandler(int argc, char ** argv)
+{
+ BindingHandler::BindingData * data = Platform::New();
+ data->EndpointId = LightSwitch::GetInstance().GetLightSwitchEndpointId();
+ data->CommandId = Clusters::OnOff::Commands::Off::Id;
+ data->ClusterId = Clusters::OnOff::Id;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+static CHIP_ERROR ToggleCommandHandler(int argc, char ** argv)
+{
+ BindingHandler::BindingData * data = Platform::New();
+ data->EndpointId = LightSwitch::GetInstance().GetLightSwitchEndpointId();
+ data->CommandId = Clusters::OnOff::Commands::Toggle::Id;
+ data->ClusterId = Clusters::OnOff::Id;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+} // namespace Unicast
+
+namespace Group {
+
+CHIP_ERROR SwitchHelpHandler(int argc, char ** argv)
+{
+ sShellSwitchGroupsSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR SwitchCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return SwitchHelpHandler(argc, argv);
+ }
+
+ return sShellSwitchGroupsSubCommands.ExecCommand(argc, argv);
+}
+
+static CHIP_ERROR OnOffHelpHandler(int argc, char ** argv)
+{
+ sShellSwitchGroupsOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+ return CHIP_NO_ERROR;
+}
+
+static CHIP_ERROR OnOffCommandHandler(int argc, char ** argv)
+{
+ if (argc == 0)
+ {
+ return OnOffHelpHandler(argc, argv);
+ }
+
+ return sShellSwitchGroupsOnOffSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR OnCommandHandler(int argc, char ** argv)
+{
+ BindingHandler::BindingData * data = Platform::New();
+ data->EndpointId = LightSwitch::GetInstance().GetLightSwitchEndpointId();
+ data->CommandId = Clusters::OnOff::Commands::On::Id;
+ data->ClusterId = Clusters::OnOff::Id;
+ data->IsGroup = true;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OffCommandHandler(int argc, char ** argv)
+{
+ BindingHandler::BindingData * data = Platform::New();
+ data->EndpointId = LightSwitch::GetInstance().GetLightSwitchEndpointId();
+ data->CommandId = Clusters::OnOff::Commands::Off::Id;
+ data->ClusterId = Clusters::OnOff::Id;
+ data->IsGroup = true;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ToggleCommandHandler(int argc, char ** argv)
+{
+ BindingHandler::BindingData * data = Platform::New();
+ data->EndpointId = LightSwitch::GetInstance().GetLightSwitchEndpointId();
+ data->CommandId = Clusters::OnOff::Commands::Toggle::Id;
+ data->ClusterId = Clusters::OnOff::Id;
+ data->IsGroup = true;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data));
+ return CHIP_NO_ERROR;
+}
+
+} // namespace Group
+
+void RegisterSwitchCommands()
+{
+ static const shell_command_t sSwitchSubCommands[] = {
+ { &SwitchHelpHandler, "help", "Switch commands" },
+ { &Unicast::OnOffCommandHandler, "onoff", "Usage: switch onoff [on|off|toggle]" },
+ { &Group::SwitchCommandHandler, "groups", "Usage: switch groups onoff [on|off|toggle]" },
+ { &TableCommandHelper, "table", "Print a binding table" }
+ };
+
+ static const shell_command_t sSwitchOnOffSubCommands[] = {
+ { &Unicast::OnOffHelpHandler, "help", "Usage : switch ononff [on|off|toggle]" },
+ { &Unicast::OnCommandHandler, "on", "Sends on command to bound lighting app" },
+ { &Unicast::OffCommandHandler, "off", "Sends off command to bound lighting app" },
+ { &Unicast::ToggleCommandHandler, "toggle", "Sends toggle command to bound lighting app" }
+ };
+
+ static const shell_command_t sSwitchGroupsSubCommands[] = {
+ { &Group::SwitchHelpHandler, "help", "switch a group of bounded lightning apps" },
+ { &Group::OnOffCommandHandler, "onoff", "Usage: switch groups onoff [on|off|toggle]" }
+ };
+
+ static const shell_command_t sSwichGroupsOnOffSubCommands[] = {
+ { &Group::OnOffHelpHandler, "help", "Usage: switch groups onoff [on|off|toggle]" },
+ { &Group::OnCommandHandler, "on", "Sends on command to bound Group" },
+ { &Group::OffCommandHandler, "off", "Sends off command to bound Group" },
+ { &Group::ToggleCommandHandler, "toggle", "Sends toggle command to bound Group" }
+ };
+
+ static const shell_command_t sSwitchCommand = { &SwitchCommandHandler, "switch",
+ "Light-switch commands. Usage: switch [onoff|groups]" };
+
+ sShellSwitchGroupsOnOffSubCommands.RegisterCommands(sSwichGroupsOnOffSubCommands, ArraySize(sSwichGroupsOnOffSubCommands));
+ sShellSwitchOnOffSubCommands.RegisterCommands(sSwitchOnOffSubCommands, ArraySize(sSwitchOnOffSubCommands));
+ sShellSwitchGroupsSubCommands.RegisterCommands(sSwitchGroupsSubCommands, ArraySize(sSwitchGroupsSubCommands));
+ sShellSwitchSubCommands.RegisterCommands(sSwitchSubCommands, ArraySize(sSwitchSubCommands));
+
+ Engine::Root().RegisterCommands(&sSwitchCommand, 1);
+}
+
+} // namespace SwitchCommands
+#endif
diff --git a/examples/light-switch-app/nrfconnect/main/include/AppConfig.h b/examples/light-switch-app/nrfconnect/main/include/AppConfig.h
new file mode 100644
index 00000000000000..4981ca6aadfc04
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/include/AppConfig.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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 FUNCTION_BUTTON DK_BTN1
+#define FUNCTION_BUTTON_MASK DK_BTN1_MSK
+#define SWITCH_BUTTON DK_BTN2
+#define SWITCH_BUTTON_MASK DK_BTN2_MSK
+#define BLE_ADVERTISEMENT_START_BUTTON DK_BTN4
+#define BLE_ADVERTISEMENT_START_BUTTON_MASK DK_BTN4_MSK
+
+#define SYSTEM_STATE_LED DK_LED1
+#define DFU_BLE_LED DK_LED2
+#define IDENTIFY_LED DK_LED3
diff --git a/examples/light-switch-app/nrfconnect/main/include/AppEvent.h b/examples/light-switch-app/nrfconnect/main/include/AppEvent.h
new file mode 100644
index 00000000000000..4a2bd347290703
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/include/AppEvent.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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 "LEDWidget.h"
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+
+ constexpr static uint8_t kButtonPushEvent = 1;
+ constexpr static uint8_t kButtonReleaseEvent = 0;
+
+ enum AppEventTypes : uint8_t
+ {
+ kEventType_StartBLEAdvertising,
+ kEventType_Button,
+ kEventType_Timer,
+ kEventType_UpdateLedState,
+ kEventType_IdentifyStart,
+ kEventType_IdentifyStop,
+#ifdef CONFIG_MCUMGR_SMP_BT
+ kEventType_StartSMPAdvertising,
+#endif
+ };
+
+ uint8_t Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t PinNo;
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ uint8_t TimerType;
+ void * Context;
+ } TimerEvent;
+ struct
+ {
+ LEDWidget * LedWidget;
+ } UpdateLedStateEvent;
+ };
+
+ EventHandler Handler;
+};
diff --git a/examples/light-switch-app/nrfconnect/main/include/AppTask.h b/examples/light-switch-app/nrfconnect/main/include/AppTask.h
new file mode 100644
index 00000000000000..2f72dd5758b6c2
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/include/AppTask.h
@@ -0,0 +1,96 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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 "AppEvent.h"
+#include "LEDWidget.h"
+
+#include
+#include
+
+#ifdef CONFIG_MCUMGR_SMP_BT
+#include "DFUOverSMP.h"
+#endif
+
+#include
+
+struct k_timer;
+struct Identify;
+
+class AppTask
+{
+public:
+ CHIP_ERROR StartApp();
+ void PostEvent(AppEvent *);
+ void UpdateClusterState();
+ static void IdentifyStartHandler(Identify *);
+ static void IdentifyStopHandler(Identify *);
+
+private:
+ enum class Timer : uint8_t
+ {
+ Function,
+ DimmerTrigger,
+ Dimmer
+ };
+ enum class TimerFunction : uint8_t
+ {
+ NoneSelected = 0,
+ SoftwareUpdate,
+ FactoryReset
+ };
+ TimerFunction mFunction = TimerFunction::NoneSelected;
+
+ enum class Button : uint8_t
+ {
+ Function,
+ Dimmer,
+ };
+
+ friend AppTask & GetAppTask();
+ static AppTask sAppTask;
+
+ CHIP_ERROR Init();
+
+ void DispatchEvent(AppEvent *);
+
+ static void ButtonPushHandler(AppEvent *);
+ static void ButtonReleaseHandler(AppEvent *);
+ static void TimerEventHandler(AppEvent *);
+ static void StartBLEAdvertisingHandler(AppEvent *);
+ static void UpdateLedStateEventHandler(AppEvent *);
+
+ static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent *, intptr_t);
+ static void UpdateStatusLED();
+ static void ButtonEventHandler(uint32_t, uint32_t);
+ static void LEDStateUpdateHandler(LEDWidget &);
+
+ static void StartTimer(Timer, uint32_t);
+ static void CancelTimer(Timer);
+ static void TimerEventHandler(k_timer *);
+
+#ifdef CONFIG_MCUMGR_SMP_BT
+ static void RequestSMPAdvertisingStart(void);
+#endif
+};
+
+inline AppTask & GetAppTask()
+{
+ return AppTask::sAppTask;
+}
diff --git a/examples/light-switch-app/nrfconnect/main/include/BindingHandler.h b/examples/light-switch-app/nrfconnect/main/include/BindingHandler.h
new file mode 100644
index 00000000000000..02aed9d7aedc49
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/include/BindingHandler.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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
+#include
+#include
+
+class BindingHandler
+{
+public:
+ static void Init();
+ static void SwitchWorkerHandler(intptr_t);
+ static void PrintBindingTable();
+ static bool IsGroupBound();
+
+ struct BindingData
+ {
+ chip::EndpointId EndpointId;
+ chip::CommandId CommandId;
+ chip::ClusterId ClusterId;
+ uint8_t Value;
+ bool IsGroup{ false };
+ };
+
+private:
+ static void OnOffProcessCommand(chip::CommandId, const EmberBindingTableEntry &, chip::DeviceProxy *, void *);
+ static void LevelControlProcessCommand(chip::CommandId, const EmberBindingTableEntry &, chip::DeviceProxy *, void *);
+ static void LightSwitchChangedHandler(const EmberBindingTableEntry &, chip::DeviceProxy *, void *);
+ static void InitInternal(intptr_t);
+};
diff --git a/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h b/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h
new file mode 100644
index 00000000000000..b5a27150a26404
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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. */
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+#define CHIP_DEVICE_CONFIG_SED_SLOW_POLLING_INTERVAL 2000_ms32
diff --git a/examples/light-switch-app/nrfconnect/main/include/LightSwitch.h b/examples/light-switch-app/nrfconnect/main/include/LightSwitch.h
new file mode 100644
index 00000000000000..222bb5216f4fae
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/include/LightSwitch.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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
+
+class LightSwitch
+{
+public:
+ enum class Action : uint8_t
+ {
+ Toggle, /// Switch state on lighting-app device
+ On, /// Turn on light on lighting-app device
+ Off /// Turn off light on lighting-app device
+ };
+
+ void Init(chip::EndpointId aLightSwitchEndpoint);
+ void InitiateActionSwitch(Action);
+ void DimmerChangeBrightness();
+ chip::EndpointId GetLightSwitchEndpointId() { return mLightSwitchEndpoint; }
+
+ static LightSwitch & GetInstance()
+ {
+ static LightSwitch sLightSwitch;
+ return sLightSwitch;
+ }
+
+private:
+ constexpr static auto kOnePercentBrightnessApproximation = 3;
+ constexpr static auto kMaximumBrightness = 254;
+
+ chip::EndpointId mLightSwitchEndpoint;
+};
diff --git a/examples/light-switch-app/nrfconnect/main/include/ShellCommands.h b/examples/light-switch-app/nrfconnect/main/include/ShellCommands.h
new file mode 100644
index 00000000000000..915d90437bdcb0
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/include/ShellCommands.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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
+
+#ifdef CONFIG_CHIP_LIB_SHELL
+#include
+#include
+#include
+
+namespace SwitchCommands {
+
+void RegisterSwitchCommands();
+
+} // namespace SwitchCommands
+
+#endif
diff --git a/examples/light-switch-app/nrfconnect/main/main.cpp b/examples/light-switch-app/nrfconnect/main/main.cpp
new file mode 100644
index 00000000000000..68db7f7f258fa8
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/main/main.cpp
@@ -0,0 +1,33 @@
+/*
+ *
+ * Copyright (c) 2022 Project CHIP Authors
+ * 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
+
+LOG_MODULE_REGISTER(app);
+
+using namespace ::chip;
+
+int main()
+{
+ CHIP_ERROR err = GetAppTask().StartApp();
+
+ LOG_ERR("Exited with code %" CHIP_ERROR_FORMAT, err.Format());
+ return err == CHIP_NO_ERROR ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/examples/light-switch-app/nrfconnect/overlay-low_power.conf b/examples/light-switch-app/nrfconnect/overlay-low_power.conf
new file mode 100644
index 00000000000000..c962425f6ef937
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/overlay-low_power.conf
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2022 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.
+#
+
+# Enable MTD Sleepy End Device
+CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y
+
+# Disable UART console
+CONFIG_SHELL=n
+CONFIG_LOG=n
+CONFIG_UART_CONSOLE=n
+CONFIG_SERIAL=n
+
+# Suspend devices when the CPU goes to sleep
+CONFIG_PM_DEVICE=y
+
+# Disable auxiliary state LEDs
+CONFIG_STATE_LEDS=n
diff --git a/examples/light-switch-app/nrfconnect/prj.conf b/examples/light-switch-app/nrfconnect/prj.conf
new file mode 100644
index 00000000000000..e40660a99c276f
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/prj.conf
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2022 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.
+#
+
+# This sample uses sample-defaults.conf to set options common for all
+# samples. This file should contain only options specific for this sample
+# or overrides of default values.
+
+# Add support for LEDs and buttons on Nordic development kits
+CONFIG_DK_LIBRARY=y
+
+# OpenThread configs
+CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
+CONFIG_OPENTHREAD_MTD=y
+CONFIG_OPENTHREAD_FTD=n
+
+# Bluetooth overrides
+CONFIG_BT_DEVICE_NAME="MatterSwitch"
+
+# Additional configs for debbugging experience.
+CONFIG_THREAD_NAME=y
+CONFIG_MPU_STACK_GUARD=y
+
+# CHIP configuration
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32772 == 0x8004 (example light-switch-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32772
diff --git a/examples/light-switch-app/nrfconnect/third_party/connectedhomeip b/examples/light-switch-app/nrfconnect/third_party/connectedhomeip
new file mode 120000
index 00000000000000..c866b86874994d
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../..
\ No newline at end of file