[nrfconnect] Added Wi-Fi support to nrfconnect examples. (#23715)

* [nrfconnect] Added Wi-Fi support to nrfconnect examples.

In this commit:
- Added the first support for Wi-Fi to nrfconnect examples:
lightinig-app, lock-app, light-switch-app, all-clusters-app

- Enabled CI all wi-fi samples checking for Wi-Fi target
nrf7002 - all-clusters-app on each commit, others related
to nrfconnect sources.

- Aligned Common api to NCS 2.1.1.

- Updated documentation for all samples and added Wi-Fi
nRF7002 target and descriptions

* Restyled by clang-format

* Restyled by prettier-markdown

* Some fixes after a review.

Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml
index ecfcc8a..4b9430d 100644
--- a/.github/workflows/examples-nrfconnect.yaml
+++ b/.github/workflows/examples-nrfconnect.yaml
@@ -192,6 +192,41 @@
                     nrfconnect nrf5340dk_nrf5340_cpuapp lighting-app \
                     examples/lighting-app/nrfconnect/build/zephyr/zephyr.elf \
                     /tmp/bloat_reports/
+            - name: Build example nRF Connect SDK Lock App on nRF7002 PDK
+              if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true'
+              timeout-minutes: 20
+              run: |
+                  scripts/examples/nrfconnect_example.sh lock-app nrf7002dk_nrf5340_cpuapp
+                  .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
+                    nrfconnect nrf7002dk_nrf5340_cpuapp lock-app \
+                    examples/lock-app/nrfconnect/build/zephyr/zephyr.elf \
+                    /tmp/bloat_reports/
+            - name: Build example nRF Connect SDK Light Switch App on nRF7002 PDK
+              if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true'
+              timeout-minutes: 20
+              run: |
+                  scripts/examples/nrfconnect_example.sh light-switch-app nrf7002dk_nrf5340_cpuapp
+                  .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
+                    nrfconnect nrf7002dk_nrf5340_cpuapp light-switch-app \
+                    examples/light-switch-app/nrfconnect/build/zephyr/zephyr.elf \
+                    /tmp/bloat_reports/                    
+            - name: Build example nRF Connect SDK Lighting App on nRF7002 PDK
+              if: github.event_name == 'push' || steps.changed_paths.outputs.nrfconnect == 'true'
+              timeout-minutes: 20
+              run: |
+                  scripts/examples/nrfconnect_example.sh lighting-app nrf7002dk_nrf5340_cpuapp
+                  .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
+                    nrfconnect nrf7002dk_nrf5340_cpuapp lighting-app \
+                    examples/light-switch-app/nrfconnect/build/zephyr/zephyr.elf \
+                    /tmp/bloat_reports/                    
+            - name: Build example nRF Connect SDK All Clusters App on nRF7002 PDK
+              timeout-minutes: 20
+              run: |
+                  scripts/examples/nrfconnect_example.sh all-clusters-app nrf7002dk_nrf5340_cpuapp
+                  .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
+                    nrfconnect nrf7002dk_nrf5340_cpuapp all-clusters-app \
+                    examples/all-clusters-app/nrfconnect/build/zephyr/zephyr.elf \
+                    /tmp/bloat_reports/
             - name: Run unit tests for Zephyr native_posix_64 platform
               if: github.event_name == 'push' || steps.changed_paths.outputs.tests == 'true'
               timeout-minutes: 15
diff --git a/config/nrfconnect/chip-module/Kconfig b/config/nrfconnect/chip-module/Kconfig
index e4a0a9f..ee51bfb 100644
--- a/config/nrfconnect/chip-module/Kconfig
+++ b/config/nrfconnect/chip-module/Kconfig
@@ -18,6 +18,15 @@
 
 if CHIP
 
+config CHIP_APP_LOG_LEVEL
+	int "Set logging level in application"
+	default LOG_DEFAULT_LEVEL
+	help
+	  Sets the logging level in Matter application. 
+	  This config should be used only within application.
+	  To set the logging level for Matter stack use MATTER_LOG_LEVEL 
+	  config.
+
 config CHIP_NFC_COMMISSIONING
 	bool "Enable NFC commissioning support"
 	default n
diff --git a/config/zephyr/Kconfig b/config/zephyr/Kconfig
index c7c5b35..048855d 100644
--- a/config/zephyr/Kconfig
+++ b/config/zephyr/Kconfig
@@ -154,10 +154,10 @@
 endif # CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT
 
 config CHIP_THREAD_SSED
-	  bool "Enable Thread Synchronized Sleepy End Device support"
-	  depends on OPENTHREAD_CSL_RECEIVER && CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT
-	  help
-		Enables Thread Synchronized Sleepy End Device support in Matter.
+	bool "Enable Thread Synchronized Sleepy End Device support"
+	depends on OPENTHREAD_CSL_RECEIVER && CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT
+	help
+	Enables Thread Synchronized Sleepy End Device support in Matter.
 
 config CHIP_OTA_REQUESTOR
 	bool "Enable OTA requestor"
diff --git a/docs/guides/nrfconnect_android_commissioning.md b/docs/guides/nrfconnect_android_commissioning.md
index 0e2146b..21096da 100644
--- a/docs/guides/nrfconnect_android_commissioning.md
+++ b/docs/guides/nrfconnect_android_commissioning.md
@@ -6,9 +6,9 @@
 
 This guide references the nRF52840 DK and Matter nRF Connect Lighting Example
 Application that communicates with other nodes over a Thread network, but the
-instructions can be adapted to other platforms and applications. In particular,
-some sections of this guide include deviations from the original procedure that
-are needed to test a Wi-Fi device.
+instructions can be adapted to other platforms and applications. For instance,
+some sections of this guide include steps for testing a Wi-Fi device, which are
+adapted from the original Thread-based procedure.
 
 <hr>
 
@@ -68,6 +68,7 @@
     replace this DK with another compatible device, such as the nRF5340 DK or
     nRF7002 DK. nRF52840 DK and nRF5340 DK can be used to test Matter over
     Thread, and nRF7002 DK can be used to test Matter over Wi-Fi.
+
 -   1x nRF52840 DK for running the
     [OpenThread Radio Co-Processor](https://openthread.io/platforms/co-processor)
     firmware. You can replace this DK with another compatible device, such as
diff --git a/examples/all-clusters-app/nrfconnect/CMakeLists.txt b/examples/all-clusters-app/nrfconnect/CMakeLists.txt
index e065613..abcd8fb 100644
--- a/examples/all-clusters-app/nrfconnect/CMakeLists.txt
+++ b/examples/all-clusters-app/nrfconnect/CMakeLists.txt
@@ -25,6 +25,7 @@
 # Set Kconfig root files that will be processed as a first Kconfig for used child images.
 set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root)
 set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root)
+set(hci_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.root)
 
 if(DEFINED CONF_FILE AND NOT CONF_FILE STREQUAL "prj.conf")
     set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml)
diff --git a/examples/all-clusters-app/nrfconnect/Kconfig b/examples/all-clusters-app/nrfconnect/Kconfig
index 9fcdb41..33919ac 100644
--- a/examples/all-clusters-app/nrfconnect/Kconfig
+++ b/examples/all-clusters-app/nrfconnect/Kconfig
@@ -22,6 +22,19 @@
 	  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.
 
+# Sample configuration used for Thread networking
+if NET_L2_OPENTHREAD
+
+choice OPENTHREAD_NORDIC_LIBRARY_CONFIGURATION
+	default OPENTHREAD_NORDIC_LIBRARY_MTD
+endchoice
+
+choice OPENTHREAD_DEVICE_TYPE
+	default OPENTHREAD_MTD
+endchoice
+
+endif # NET_L2_OPENTHREAD
+
 rsource "../../../config/nrfconnect/chip-module/Kconfig.features"
 rsource "../../../config/nrfconnect/chip-module/Kconfig.defaults"
 source "Kconfig.zephyr"
diff --git a/examples/all-clusters-app/nrfconnect/README.md b/examples/all-clusters-app/nrfconnect/README.md
index b0befae..8f4eb04 100644
--- a/examples/all-clusters-app/nrfconnect/README.md
+++ b/examples/all-clusters-app/nrfconnect/README.md
@@ -10,12 +10,14 @@
 The example is based on
 [Matter](https://github.com/project-chip/connectedhomeip) and Nordic
 Semiconductor's nRF Connect SDK, and was created to facilitate testing and
-certification of a Matter device communicating over a low-power, 802.15.4 Thread
-network.
+certification of a Matter device communicating over a low-power 802.15.4 Thread
+network, or Wi-Fi 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. The
-device works as a Thread Minimal End Device.
+into an existing Matter network and can be controlled by this network. In the
+case of Thread, this device works as a Thread Sleepy End Device. Support for
+both Thread and Wi-Fi is mutually exclusive and depends on the hardware
+platform, so only one protocol can be supported for a specific device.
 
 <hr>
 
@@ -24,6 +26,7 @@
     -   [Bluetooth LE rendezvous](#bluetooth-le-rendezvous)
 -   [Requirements](#requirements)
     -   [Supported devices](#supported_devices)
+    -   [IPv6 network support](#ipv6-network-support)
 -   [Device UI](#device-ui)
 -   [Setting up the environment](#setting-up-the-environment)
     -   [Using Docker container for setup](#using-docker-container-for-setup)
@@ -55,17 +58,27 @@
 [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md)
 to read more about the platform structure and dependencies.
 
-The Matter device that runs the all clusters 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.
+By default, the Matter accessory device has IPv6 networking disabled. You must
+pair it with the Matter controller over Bluetooth® LE to get the configuration
+from the controller to use the device within a Thread or Wi-Fi network. You have
+to make the device discoverable manually (for security reasons). See
+[Bluetooth LE advertising](#bluetooth-le-advertising) to learn how to do this.
+The controller must get the commissioning information from the Matter accessory
+device and provision the device into the network.
+
+You can test this application remotely over the Thread or the Wi-Fi protocol,
+which in either case requires more devices, including a Matter controller that
+you can configure either on a PC or a mobile device.
 
 ### 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**.
+LE advertising manually after powering up the device by pressing:
+
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: **Button 4**.
+
+-   On nRF7002 DK: **Button 2**.
 
 ### Bluetooth LE rendezvous
 
@@ -75,14 +88,16 @@
 
 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.
+the UART console, and shared using an NFC tag. The emulation of the NFC tag
+starts automatically when Bluetooth LE advertising is started and stays enabled
+until Bluetooth LE advertising timeout expires.
 
-#### Thread provisioning
+#### Thread or Wi-Fi 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, device is able to join the Thread network and communicate
-with other Thread devices in the network.
+sending the Thread or Wi-Fi network credentials from the Matter controller to
+the Matter device. As a result, the device joins the Thread or Wi-Fi network and
+can communicate with other devices in the network.
 
 <hr>
 
@@ -100,14 +115,24 @@
 
 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`      | <details><summary>nRF52840 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_DK_info-medium.jpg" alt="nRF52840 DK"/></details>        |
-| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK)           | `nrf5340dk_nrf5340_cpuapp` | <details><summary>nRF5340 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF5340_DK_info-medium.jpg" alt="nRF5340 DK"/></details>           |
-| [nRF52840 Dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) | `nrf52840dongle_nrf52840`  | <details><summary>nRF52840 Dongle</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_Dongle-medium.jpg" alt="nRF52840 Dongle"/></details> |
+| Hardware platform                                                                                               | Build target               | Platform image                                                                                                                                          |
+| --------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)                       | `nrf52840dk_nrf52840`      | <details><summary>nRF52840 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_DK_info-medium.jpg" alt="nRF52840 DK"/></details>        |
+| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK)                         | `nrf5340dk_nrf5340_cpuapp` | <details><summary>nRF5340 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF5340_DK_info-medium.jpg" alt="nRF5340 DK"/></details>           |
+| [nRF52840 Dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle)               | `nrf52840dongle_nrf52840`  | <details><summary>nRF52840 Dongle</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_Dongle-medium.jpg" alt="nRF52840 Dongle"/></details> |
+| [nRF7002 DK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf7002.html#nrf7002dk-nrf5340) | `nrf7002dk_nrf5340_cpuapp` | <details><summary>nRF7002DK</summary><img src="../../platform/nrfconnect/doc/images/nrf7002dk.jpg" alt="nRF7002 DK"/></details>                         |
 
 <hr>
 
+### IPv6 network support
+
+The development kits for this sample offer the following IPv6 network support
+for Matter:
+
+-   Matter over Thread is supported for `nrf52840dk_nrf52840` and
+    `nrf5340dk_nrf5340_cpuapp`.
+-   Matter over Wi-Fi is supported for `nrf7002dk_nrf5340_cpuapp`.
+
 <a name="device-ui"></a>
 
 ## Device UI
@@ -137,21 +162,42 @@
     Bluetooth LE.
 
 -   _Short Flash Off (950ms on/50ms off)_ &mdash; The device is fully
-    provisioned, but does not yet have full Thread network or service
-    connectivity.
+    provisioned, but does not yet have full connectivity for Thread or Wi-Fi
+    network.
 
--   _Solid On_ &mdash; The device is fully provisioned and has full Thread
-    network and service connectivity.
+-   _Solid On_ &mdash; The device is fully provisioned.
 
 **Button 1** can be used for the following purposes:
 
--   _Pressed for 6 s_ &mdash; Initiates the factory reset of the device.
-    Releasing the button within the 6-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_ &mdash; 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)
+    instructions.
 
-**Button 4** &mdash; Pressing the button once starts Bluetooth LE advertising
-for the predefined period of time (15 minutes by default).
+-   _Pressed for more than 3 s_ &mdash; initiates the factory reset of the
+    device. Releasing the button within the 3-second window cancels the factory
+    reset procedure.
+
+**Button 2**:
+
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: Not available.
+
+-   On nRF7002 DK:
+
+    -   If pressed for more than three seconds, it starts the NFC tag emulation,
+        enables Bluetooth LE advertising for the predefined period of time (15
+        minutes by default), and makes the device discoverable over Bluetooth
+        LE.
+
+**Button 4**:
+
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: Starts the NFC tag emulation,
+    enables Bluetooth LE advertising for the predefined period of time (15
+    minutes by default), and makes the device discoverable over Bluetooth LE.
+    This button is used during the commissioning procedure.
+
+-   On nRF7002 DK: Not available.
 
 **SEGGER J-Link USB port** can be used to get logs from the device or
 communicate with it using the
diff --git a/examples/all-clusters-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay b/examples/all-clusters-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
index 04253ef..5662367 100644
--- a/examples/all-clusters-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
+++ b/examples/all-clusters-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
@@ -37,9 +37,6 @@
 &uart1 {
 	status = "disabled";
 };
-&gpio1 {
-	status = "disabled";
-};
 &i2c0 {
 	status = "disabled";
 };
diff --git a/examples/all-clusters-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/all-clusters-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay
new file mode 100644
index 0000000..3063fbb
--- /dev/null
+++ b/examples/all-clusters-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay
@@ -0,0 +1,21 @@
+/*
+ *    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;
+	};
+};
diff --git a/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj.conf b/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf b/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf b/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/all-clusters-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/all-clusters-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/all-clusters-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml
new file mode 100644
index 0000000..3c56dc0
--- /dev/null
+++ b/examples/all-clusters-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -0,0 +1,56 @@
+mcuboot:
+    address: 0x0
+    size: 0xC000
+    region: flash_primary
+mcuboot_pad:
+    address: 0xC000
+    size: 0x200
+app:
+    address: 0xC200
+    size: 0xeee00
+mcuboot_primary:
+    orig_span: &id001
+        - mcuboot_pad
+        - app
+    span: *id001
+    address: 0xC000
+    size: 0xef000
+    region: flash_primary
+mcuboot_primary_app:
+    orig_span: &id002
+        - app
+    span: *id002
+    address: 0xC200
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
+settings_storage:
+    address: 0xfc000
+    size: 0x4000
+    region: flash_primary
+mcuboot_primary_1:
+    address: 0x0
+    size: 0x40000
+    device: flash_ctrl
+    region: ram_flash
+mcuboot_secondary:
+    address: 0x0
+    size: 0xef000
+    device: MX25R64
+    region: external_flash
+mcuboot_secondary_1:
+    address: 0xef000
+    size: 0x40000
+    device: MX25R64
+    region: external_flash
+external_flash:
+    address: 0x12f000
+    size: 0x6D1000
+    device: MX25R64
+    region: external_flash
+pcd_sram:
+    address: 0x20000000
+    size: 0x2000
+    region: sram_primary
diff --git a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp
index 40b987b..f8646a1 100644
--- a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp
+++ b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp
@@ -36,6 +36,11 @@
 #include <credentials/DeviceAttestationCredsProvider.h>
 #include <credentials/examples/DeviceAttestationCredsExample.h>
 
+#ifdef CONFIG_CHIP_WIFI
+#include <app/clusters/network-commissioning/network-commissioning.h>
+#include <platform/nrfconnect/wifi/NrfWiFiDriver.h>
+#endif
+
 #if CONFIG_CHIP_OTA_REQUESTOR
 #include "OTAUtil.h"
 #endif
@@ -44,72 +49,48 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
+
 using namespace ::chip;
+using namespace ::chip::app;
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceLayer;
 
-#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
-#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
-#define APP_EVENT_QUEUE_SIZE 10
-#define BUTTON_PUSH_EVENT 1
-#define BUTTON_RELEASE_EVENT 0
-
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
-K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), APP_EVENT_QUEUE_SIZE, alignof(AppEvent));
-
 namespace {
+constexpr uint32_t kFactoryResetTriggerTimeout              = 3000;
+constexpr uint32_t kFactoryResetCancelWindowTimeout         = 3000;
+constexpr size_t kAppEventQueueSize                         = 10;
+constexpr EndpointId kIdentifyEndpointId                    = 1;
+constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE;
 
 // NOTE! This key is for test/certification only and should not be available in production devices!
 // If CONFIG_CHIP_FACTORY_DATA is enabled, this value is read from the factory data.
 uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                                                                                    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
 
-LEDWidget sStatusLED;
-UnusedLedsWrapper<3> sUnusedLeds{ { DK_LED2, DK_LED3, DK_LED4 } };
+K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
 k_timer sFunctionTimer;
 
 chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
 
-constexpr EndpointId kIdentifyEndpointId = 1;
+Identify sIdentify = { kIdentifyEndpointId, AppTask::IdentifyStartHandler, AppTask::IdentifyStopHandler,
+                       EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED };
 
-void OnIdentifyTriggerEffect(Identify * identify)
-{
-    ChipLogProgress(Zcl, "OnIdentifyTriggerEffect");
-    switch (identify->mCurrentEffectIdentifier)
-    {
-    case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK:
-        ChipLogProgress(Zcl, "Effect: EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK");
-        break;
-    case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE:
-        ChipLogProgress(Zcl, "Effect: EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE");
-        break;
-    case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY:
-        ChipLogProgress(Zcl, "Effect: EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY");
-        break;
-    case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE:
-        ChipLogProgress(Zcl, "Effect: EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE");
-        break;
-    default:
-        ChipLogProgress(Zcl, "Effect: No identifier effect");
-        break;
-    }
-    return;
-}
+LEDWidget sStatusLED;
+LEDWidget sIdentifyLED;
+#if NUMBER_OF_LEDS == 4
+FactoryResetLEDsWrapper<2> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTORY_RESET_SIGNAL_LED1 } };
+#endif
 
-Identify sIdentify = {
-    chip::EndpointId{ kIdentifyEndpointId },
-    [](Identify *) { ChipLogProgress(Zcl, "OnIdentifyStart"); },
-    [](Identify *) { ChipLogProgress(Zcl, "OnIdentifyStop"); },
-    EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_NONE,
-    OnIdentifyTriggerEffect,
-};
+bool sIsNetworkProvisioned = false;
+bool sIsNetworkEnabled     = false;
+bool sHaveBLEConnections   = false;
 
 } // namespace
 
-constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE;
-
 namespace LedConsts {
 constexpr uint32_t kBlinkRate_ms{ 500 };
+constexpr uint32_t kIdentifyBlinkRate_ms{ 500 };
 namespace StatusLed {
 namespace Unprovisioned {
 constexpr uint32_t kOn_ms{ 100 };
@@ -123,6 +104,10 @@
 } // namespace StatusLed
 } // namespace LedConsts
 
+#ifdef CONFIG_CHIP_WIFI
+app::Clusters::NetworkCommissioning::Instance sWiFiCommissioningInstance(0, &(NetworkCommissioning::NrfWiFiDriver::Instance()));
+#endif
+
 CHIP_ERROR AppTask::Init()
 {
     // Initialize CHIP stack
@@ -160,13 +145,19 @@
         LOG_ERR("ConnectivityMgr().SetThreadDeviceType() failed");
         return err;
     }
-#endif
+#elif defined(CONFIG_CHIP_WIFI)
+    sWiFiCommissioningInstance.Init();
+#else
+    return CHIP_ERROR_INTERNAL;
+#endif // CONFIG_NET_L2_OPENTHREAD
 
     // Initialize LEDs
     LEDWidget::InitGpio();
     LEDWidget::SetStateUpdateCallback(LEDStateUpdateHandler);
 
     sStatusLED.Init(SYSTEM_STATE_LED);
+    sIdentifyLED.Init(IDENTIFY_STATE_LED);
+    sIdentifyLED.Set(false);
 
     UpdateStatusLED();
 
@@ -184,7 +175,7 @@
     }
 
     // Initialize timer user data
-    k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr);
+    k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr);
     k_timer_user_data_set(&sFunctionTimer, this);
 
     // Initialize CHIP server
@@ -241,120 +232,164 @@
     while (true)
     {
         k_msgq_get(&sAppEventQueue, &event, K_FOREVER);
-        DispatchEvent(&event);
+        DispatchEvent(event);
     }
 
     return CHIP_NO_ERROR;
 }
 
-void AppTask::ButtonEventHandler(uint32_t aButtonState, uint32_t aHasChanged)
+void AppTask::IdentifyStartHandler(Identify *)
 {
     AppEvent event;
-    event.Type = AppEvent::Type::Button;
+    event.Type    = AppEventType::IdentifyStart;
+    event.Handler = [](const AppEvent &) { sIdentifyLED.Blink(LedConsts::kIdentifyBlinkRate_ms); };
+    PostEvent(event);
+}
 
-    if (FUNCTION_BUTTON_MASK & aHasChanged)
+void AppTask::IdentifyStopHandler(Identify *)
+{
+    AppEvent event;
+    event.Type    = AppEventType::IdentifyStop;
+    event.Handler = [](const AppEvent &) { sIdentifyLED.Set(false); };
+    PostEvent(event);
+}
+
+void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)
+{
+    AppEvent button_event;
+    button_event.Type = AppEventType::Button;
+
+    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged)
     {
-        event.ButtonEvent.PinNo  = FUNCTION_BUTTON;
-        event.ButtonEvent.Action = (FUNCTION_BUTTON_MASK & aButtonState) ? BUTTON_PUSH_EVENT : BUTTON_RELEASE_EVENT;
-        event.Handler            = FunctionHandler;
-        PostEvent(&event);
+        button_event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
+        button_event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
+        button_event.Handler            = StartBLEAdvertisementHandler;
+        PostEvent(button_event);
     }
 
-    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & aButtonState & aHasChanged)
+    if (FUNCTION_BUTTON_MASK & hasChanged)
     {
-        event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
-        event.ButtonEvent.Action = BUTTON_PUSH_EVENT;
-        event.Handler            = StartBLEAdvertisementHandler;
-        PostEvent(&event);
+        button_event.ButtonEvent.PinNo = FUNCTION_BUTTON;
+        button_event.ButtonEvent.Action =
+            static_cast<uint8_t>((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased);
+        button_event.Handler = FunctionHandler;
+        PostEvent(button_event);
     }
 }
 
-void AppTask::TimerEventHandler(k_timer * aTimer)
+void AppTask::FunctionTimerTimeoutCallback(k_timer * timer)
 {
-    if (!aTimer)
+    if (!timer)
+    {
         return;
+    }
 
     AppEvent event;
-    event.Type               = AppEvent::Type::Timer;
-    event.TimerEvent.Context = k_timer_user_data_get(aTimer);
+    event.Type               = AppEventType::Timer;
+    event.TimerEvent.Context = k_timer_user_data_get(timer);
     event.Handler            = FunctionTimerEventHandler;
-    PostEvent(&event);
+    PostEvent(event);
 }
 
-void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
+void AppTask::FunctionTimerEventHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->Type != AppEvent::Type::Timer)
-        return;
-
-    // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT, initiate factory reset
-    if (Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::Normal)
+    if (event.Type != AppEventType::Timer || !Instance().mFunctionTimerActive)
     {
-        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_TRIGGER_TIMEOUT);
+        return;
+    }
 
-        // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to cancel, if required.
-        StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
-        Instance().mMode = OperatingMode::FactoryReset;
+    // If we reached here, the button was held past kFactoryResetTriggerTimeout, initiate factory reset
+    if (Instance().mFunction == FunctionEvent::SoftwareUpdate)
+    {
+        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", kFactoryResetTriggerTimeout);
 
-#ifdef CONFIG_STATE_LEDS
-        // Turn off all LEDs before starting blink to make sure blink is co-ordinated.
+        // Start timer for kFactoryResetCancelWindowTimeout to allow user to cancel, if required.
+        Instance().StartTimer(kFactoryResetCancelWindowTimeout);
+        Instance().mFunction = FunctionEvent::FactoryReset;
+
+        // Turn off all LEDs before starting blink to make sure blink is coordinated.
         sStatusLED.Set(false);
-        sUnusedLeds.Set(false);
+#if NUMBER_OF_LEDS == 4
+        sFactoryResetLEDs.Set(false);
+#endif
 
         sStatusLED.Blink(LedConsts::kBlinkRate_ms);
-        sUnusedLeds.Blink(LedConsts::kBlinkRate_ms);
+#if NUMBER_OF_LEDS == 4
+        sFactoryResetLEDs.Blink(LedConsts::kBlinkRate_ms);
 #endif
     }
-    else if (Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::FactoryReset)
+    else if (Instance().mFunction == FunctionEvent::FactoryReset)
     {
         // Actually trigger Factory Reset
-        Instance().mMode = OperatingMode::Normal;
-        ConfigurationMgr().InitiateFactoryReset();
+        Instance().mFunction = FunctionEvent::NoneSelected;
+        chip::Server::GetInstance().ScheduleFactoryReset();
+    }
+    else if (Instance().mFunction == FunctionEvent::AdvertisingStart)
+    {
+        // The button was held past kAdvertisingTriggerTimeout, start BLE advertisement if we have 2 buttons UI
+#if NUMBER_OF_BUTTONS == 2
+        StartBLEAdvertisementHandler(event);
+#endif
     }
 }
 
-void AppTask::FunctionHandler(AppEvent * aEvent)
+#ifdef CONFIG_MCUMGR_SMP_BT
+void AppTask::RequestSMPAdvertisingStart(void)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->ButtonEvent.PinNo != FUNCTION_BUTTON)
+    AppEvent event;
+    event.Type    = AppEvent::kEventType_StartSMPAdvertising;
+    event.Handler = [](AppEvent *) { GetDFUOverSMP().StartBLEAdvertising(); };
+    sAppTask.PostEvent(&event);
+}
+#endif
+
+void AppTask::FunctionHandler(const AppEvent & event)
+{
+    if (event.ButtonEvent.PinNo != FUNCTION_BUTTON)
         return;
 
+    // To trigger software update: press the FUNCTION_BUTTON button briefly (< FACTORY_RESET_TRIGGER_TIMEOUT)
     // To initiate factory reset: press the FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT + FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
     // All LEDs start blinking after FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
     // To cancel factory reset: release the FUNCTION_BUTTON once all LEDs start blinking within the
     // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
-    if (aEvent->ButtonEvent.Action == BUTTON_PUSH_EVENT)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
     {
-        if (!Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::Normal)
+        if (!Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::NoneSelected)
         {
-            StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+            Instance().StartTimer(kFactoryResetTriggerTimeout);
+
+            Instance().mFunction = FunctionEvent::SoftwareUpdate;
         }
     }
     else
     {
-        if (Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::FactoryReset)
+        // If the button was released before factory reset got initiated, trigger a software update.
+        if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
         {
-            sUnusedLeds.Set(false);
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
 
-            UpdateStatusLED();
-            CancelTimer();
-
-            // Change the function to none selected since factory reset has been canceled.
-            Instance().mMode = OperatingMode::Normal;
-
-            LOG_INF("Factory Reset has been Canceled");
+#ifdef CONFIG_MCUMGR_SMP_BT
+            GetDFUOverSMP().StartServer();
+#else
+            LOG_INF("Software update is disabled");
+#endif
         }
-        else if (Instance().mFunctionTimerActive)
+        else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
         {
-            CancelTimer();
-            Instance().mMode = OperatingMode::Normal;
+#if NUMBER_OF_LEDS == 4
+            sFactoryResetLEDs.Set(false);
+#endif
+            UpdateStatusLED();
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
+            LOG_INF("Factory Reset has been Canceled");
         }
     }
 }
 
-void AppTask::StartBLEAdvertisementHandler(AppEvent *)
+void AppTask::StartBLEAdvertisementHandler(const AppEvent &)
 {
     if (Server::GetInstance().GetFabricTable().FabricCount() != 0)
     {
@@ -374,41 +409,39 @@
     }
 }
 
-void AppTask::UpdateLedStateEventHandler(AppEvent * aEvent)
+void AppTask::UpdateLedStateEventHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->Type == AppEvent::Type::UpdateLedState)
+    if (event.Type == AppEventType::UpdateLedState)
     {
-        aEvent->UpdateLedStateEvent.LedWidget->UpdateState();
+        event.UpdateLedStateEvent.LedWidget->UpdateState();
     }
 }
 
-void AppTask::LEDStateUpdateHandler(LEDWidget & aLedWidget)
+void AppTask::LEDStateUpdateHandler(LEDWidget & ledWidget)
 {
     AppEvent event;
-    event.Type                          = AppEvent::Type::UpdateLedState;
+    event.Type                          = AppEventType::UpdateLedState;
     event.Handler                       = UpdateLedStateEventHandler;
-    event.UpdateLedStateEvent.LedWidget = &aLedWidget;
-    PostEvent(&event);
+    event.UpdateLedStateEvent.LedWidget = &ledWidget;
+    PostEvent(event);
 }
 
 void AppTask::UpdateStatusLED()
 {
 #ifdef CONFIG_STATE_LEDS
-    /* Update the status LED.
-     *
-     * If thread and service provisioned, keep the LED On constantly.
-     *
-     * If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
-     * rate of 100ms.
-     *
-     * Otherwise, blink the LED On for a very short time. */
-    if (Instance().mIsThreadProvisioned && Instance().mIsThreadEnabled)
+    // Update the status LED.
+    //
+    // If IPv6 network and service provisioned, keep the LED On constantly.
+    //
+    // If the system has BLE connection(s) until the stage above, THEN blink the LED at an even
+    // rate of 100ms.
+    //
+    // Otherwise, blink the LED for a very short time.
+    if (sIsNetworkProvisioned && sIsNetworkEnabled)
     {
         sStatusLED.Set(true);
     }
-    else if (Instance().mHaveBLEConnections)
+    else if (sHaveBLEConnections)
     {
         sStatusLED.Blink(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms);
     }
@@ -419,25 +452,52 @@
 #endif
 }
 
-void AppTask::ChipEventHandler(const ChipDeviceEvent * aEvent, intptr_t /* aArg */)
+void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */)
 {
-    if (!aEvent)
-        return;
-    switch (aEvent->Type)
+    switch (event->Type)
     {
     case DeviceEventType::kCHIPoBLEAdvertisingChange:
-        Instance().mHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
+#ifdef CONFIG_CHIP_NFC_COMMISSIONING
+        if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
+        {
+            if (NFCMgr().IsTagEmulationStarted())
+            {
+                LOG_INF("NFC Tag emulation is already started");
+            }
+            else
+            {
+                ShareQRCodeOverNFC(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
+            }
+        }
+        else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
+        {
+            NFCMgr().StopTagEmulation();
+        }
+#endif
+        sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
         UpdateStatusLED();
         break;
-    case DeviceEventType::kThreadStateChange:
-        Instance().mIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
-        Instance().mIsThreadEnabled     = ConnectivityMgr().IsThreadEnabled();
-        UpdateStatusLED();
-        break;
+#if defined(CONFIG_NET_L2_OPENTHREAD)
     case DeviceEventType::kDnssdPlatformInitialized:
 #if CONFIG_CHIP_OTA_REQUESTOR
         InitBasicOTARequestor();
+#endif // CONFIG_CHIP_OTA_REQUESTOR
+        break;
+    case DeviceEventType::kThreadStateChange:
+        sIsNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsThreadEnabled();
+#elif defined(CONFIG_CHIP_WIFI)
+    case DeviceEventType::kWiFiConnectivityChange:
+        sIsNetworkProvisioned = ConnectivityMgr().IsWiFiStationProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsWiFiStationEnabled();
+#if CONFIG_CHIP_OTA_REQUESTOR
+        if (event->WiFiConnectivityChange.Result == kConnectivity_Established)
+        {
+            InitBasicOTARequestor();
+        }
+#endif // CONFIG_CHIP_OTA_REQUESTOR
 #endif
+        UpdateStatusLED();
         break;
     default:
         break;
@@ -456,23 +516,19 @@
     Instance().mFunctionTimerActive = true;
 }
 
-void AppTask::PostEvent(AppEvent * aEvent)
+void AppTask::PostEvent(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT))
+    if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT) != 0)
     {
         LOG_INF("Failed to post event to app task event queue");
     }
 }
 
-void AppTask::DispatchEvent(AppEvent * aEvent)
+void AppTask::DispatchEvent(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->Handler)
+    if (event.Handler)
     {
-        aEvent->Handler(aEvent);
+        event.Handler(event);
     }
     else
     {
diff --git a/examples/all-clusters-app/nrfconnect/main/include/AppConfig.h b/examples/all-clusters-app/nrfconnect/main/include/AppConfig.h
index 01465d3..91b8ad9 100644
--- a/examples/all-clusters-app/nrfconnect/main/include/AppConfig.h
+++ b/examples/all-clusters-app/nrfconnect/main/include/AppConfig.h
@@ -17,11 +17,25 @@
 
 #pragma once
 
+#include "BoardUtil.h"
+
 // ---- All Clusters Application example config ----
 
 #define FUNCTION_BUTTON DK_BTN1
 #define FUNCTION_BUTTON_MASK DK_BTN1_MSK
+
+#if NUMBER_OF_BUTTONS == 2
+#define BLE_ADVERTISEMENT_START_BUTTON DK_BTN2
+#define BLE_ADVERTISEMENT_START_BUTTON_MASK DK_BTN2_MSK
+#else
 #define BLE_ADVERTISEMENT_START_BUTTON DK_BTN4
 #define BLE_ADVERTISEMENT_START_BUTTON_MASK DK_BTN4_MSK
+#endif
 
 #define SYSTEM_STATE_LED DK_LED1
+#define IDENTIFY_STATE_LED DK_LED2
+
+#if NUMBER_OF_LEDS == 4
+#define FACTORY_RESET_SIGNAL_LED DK_LED3
+#define FACTORY_RESET_SIGNAL_LED1 DK_LED4
+#endif
diff --git a/examples/all-clusters-app/nrfconnect/main/include/AppEvent.h b/examples/all-clusters-app/nrfconnect/main/include/AppEvent.h
index f6cac85..ccefe5d 100644
--- a/examples/all-clusters-app/nrfconnect/main/include/AppEvent.h
+++ b/examples/all-clusters-app/nrfconnect/main/include/AppEvent.h
@@ -19,22 +19,33 @@
 
 #include <cstdint>
 
+#include "EventTypes.h"
+
 class LEDWidget;
 
+enum class AppEventType : uint8_t
+{
+    None = 0,
+    Button,
+    ButtonPushed,
+    ButtonReleased,
+    Timer,
+    UpdateLedState,
+    IdentifyStart,
+    IdentifyStop,
+    StartSMPAdvertising
+};
+
+enum class FunctionEvent : uint8_t
+{
+    NoneSelected   = 0,
+    SoftwareUpdate = 0,
+    FactoryReset,
+    AdvertisingStart
+};
+
 struct AppEvent
 {
-    using EventHandler = void (*)(AppEvent *);
-
-    enum class Type : uint8_t
-    {
-        None,
-        Button,
-        Timer,
-        UpdateLedState,
-    };
-
-    Type Type{ Type::None };
-
     union
     {
         struct
@@ -48,9 +59,15 @@
         } TimerEvent;
         struct
         {
+            uint8_t Action;
+            int32_t Actor;
+        } LockEvent;
+        struct
+        {
             LEDWidget * LedWidget;
         } UpdateLedStateEvent;
     };
 
+    AppEventType Type{ AppEventType::None };
     EventHandler Handler;
 };
diff --git a/examples/all-clusters-app/nrfconnect/main/include/AppTask.h b/examples/all-clusters-app/nrfconnect/main/include/AppTask.h
index 04f44f4..72e87e4 100644
--- a/examples/all-clusters-app/nrfconnect/main/include/AppTask.h
+++ b/examples/all-clusters-app/nrfconnect/main/include/AppTask.h
@@ -19,13 +19,19 @@
 
 #include <platform/CHIPDeviceLayer.h>
 
+#include "AppEvent.h"
+#include "LEDWidget.h"
+
 #if CONFIG_CHIP_FACTORY_DATA
 #include <platform/nrfconnect/FactoryDataProvider.h>
 #endif
 
+#ifdef CONFIG_MCUMGR_SMP_BT
+#include "DFUOverSMP.h"
+#endif
+
 struct k_timer;
-class AppEvent;
-class LEDWidget;
+struct Identify;
 
 class AppTask
 {
@@ -37,36 +43,35 @@
     };
     CHIP_ERROR StartApp();
 
+    static void IdentifyStartHandler(Identify *);
+    static void IdentifyStopHandler(Identify *);
+
+    static void PostEvent(const AppEvent & event);
+
 private:
-    enum class OperatingMode : uint8_t
-    {
-        Normal,
-        FactoryReset,
-        Invalid
-    };
-
     CHIP_ERROR Init();
-    void DispatchEvent(AppEvent * aEvent);
 
-    // statics needed to interact with zephyr C API
-    static void CancelTimer(void);
-    static void StartTimer(uint32_t aTimeoutInMs);
-    static void FunctionTimerEventHandler(AppEvent * aEvent);
-    static void FunctionHandler(AppEvent * aEvent);
-    static void ButtonEventHandler(uint32_t aButtonsState, uint32_t aHasChanged);
-    static void TimerEventHandler(k_timer * aTimer);
-    static void PostEvent(AppEvent * aEvent);
+    static void CancelTimer();
+    static void StartTimer(uint32_t timeoutInMs);
+
+    static void DispatchEvent(const AppEvent & event);
+    static void FunctionTimerEventHandler(const AppEvent & event);
+    static void FunctionHandler(const AppEvent & event);
+    static void StartBLEAdvertisementHandler(const AppEvent & event);
+    static void UpdateLedStateEventHandler(const AppEvent & event);
+
+    static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+    static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged);
+    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
+    static void FunctionTimerTimeoutCallback(k_timer * timer);
     static void UpdateStatusLED();
-    static void LEDStateUpdateHandler(LEDWidget & aLedWidget);
-    static void UpdateLedStateEventHandler(AppEvent * aEvent);
-    static void StartBLEAdvertisementHandler(AppEvent * aEvent);
-    static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * aEvent, intptr_t aArg);
 
-    OperatingMode mMode{ OperatingMode::Normal };
-    bool mFunctionTimerActive{ false };
-    bool mIsThreadProvisioned{ false };
-    bool mIsThreadEnabled{ false };
-    bool mHaveBLEConnections{ false };
+#ifdef CONFIG_MCUMGR_SMP_BT
+    static void RequestSMPAdvertisingStart(void);
+#endif
+
+    FunctionEvent mFunction   = FunctionEvent::NoneSelected;
+    bool mFunctionTimerActive = false;
 
 #if CONFIG_CHIP_FACTORY_DATA
     chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
diff --git a/examples/all-clusters-app/nrfconnect/main/main.cpp b/examples/all-clusters-app/nrfconnect/main/main.cpp
index 8563856..400f9b3 100644
--- a/examples/all-clusters-app/nrfconnect/main/main.cpp
+++ b/examples/all-clusters-app/nrfconnect/main/main.cpp
@@ -24,7 +24,7 @@
 #include <zephyr/usb/usb_device.h>
 #endif
 
-LOG_MODULE_REGISTER(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip;
 
diff --git a/examples/all-clusters-app/nrfconnect/prj.conf b/examples/all-clusters-app/nrfconnect/prj.conf
index f56965b..ee2bee6 100644
--- a/examples/all-clusters-app/nrfconnect/prj.conf
+++ b/examples/all-clusters-app/nrfconnect/prj.conf
@@ -14,21 +14,20 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# CHIP PID: 32769 == 0x8001 (all-clusters-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
+CONFIG_STD_CPP14=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 
-# OpenThread settings
-CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
-CONFIG_OPENTHREAD_MTD=y
-CONFIG_OPENTHREAD_FTD=n
-
 # Bluetooth overrides
 CONFIG_BT_DEVICE_NAME="AllClusters"
 
@@ -42,9 +41,3 @@
 
 # Disable QSPI NOR
 CONFIG_CHIP_QSPI_NOR=n
-
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-
-# CHIP PID: 32769 == 0x8001 (all-clusters-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
diff --git a/examples/all-clusters-app/nrfconnect/prj_dfu.conf b/examples/all-clusters-app/nrfconnect/prj_dfu.conf
index 9738e9f..b91bf3f 100644
--- a/examples/all-clusters-app/nrfconnect/prj_dfu.conf
+++ b/examples/all-clusters-app/nrfconnect/prj_dfu.conf
@@ -14,21 +14,19 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# CHIP PID: 32769 == 0x8001 (all-clusters-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
+CONFIG_STD_CPP14=y
 
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 
-# OpenThread settings
-CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
-CONFIG_OPENTHREAD_MTD=y
-CONFIG_OPENTHREAD_FTD=n
-
 # Bluetooth overrides
 CONFIG_BT_DEVICE_NAME="AllClusters"
 
@@ -37,12 +35,6 @@
 CONFIG_MPU_STACK_GUARD=y
 CONFIG_RESET_ON_FATAL_ERROR=n
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-
-# CHIP PID: 32769 == 0x8001 (all-clusters-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
-
 # reduce application size by disabling including assertions in the output file.
 CONFIG_ASSERT_VERBOSE=n
 CONFIG_ASSERT_NO_FILE_INFO=y
diff --git a/examples/all-clusters-app/nrfconnect/prj_release.conf b/examples/all-clusters-app/nrfconnect/prj_release.conf
index d9905e8..5816426 100644
--- a/examples/all-clusters-app/nrfconnect/prj_release.conf
+++ b/examples/all-clusters-app/nrfconnect/prj_release.conf
@@ -14,33 +14,26 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# CHIP PID: 32769 == 0x8001 (all-clusters-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
+CONFIG_STD_CPP14=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 
-# OpenThread settings
-CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
-CONFIG_OPENTHREAD_MTD=y
-CONFIG_OPENTHREAD_FTD=n
-
 # Bluetooth overrides
 CONFIG_BT_DEVICE_NAME="AllClusters"
 
 # Enable system reset on fatal error
 CONFIG_RESET_ON_FATAL_ERROR=y
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-
-# CHIP PID: 32769 == 0x8001 (all-clusters-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
-
 # Disable all debug features
 CONFIG_SHELL=n
 CONFIG_OPENTHREAD_SHELL=n
diff --git a/examples/all-clusters-minimal-app/nrfconnect/Kconfig b/examples/all-clusters-minimal-app/nrfconnect/Kconfig
index 9fcdb41..33919ac 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/Kconfig
+++ b/examples/all-clusters-minimal-app/nrfconnect/Kconfig
@@ -22,6 +22,19 @@
 	  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.
 
+# Sample configuration used for Thread networking
+if NET_L2_OPENTHREAD
+
+choice OPENTHREAD_NORDIC_LIBRARY_CONFIGURATION
+	default OPENTHREAD_NORDIC_LIBRARY_MTD
+endchoice
+
+choice OPENTHREAD_DEVICE_TYPE
+	default OPENTHREAD_MTD
+endchoice
+
+endif # NET_L2_OPENTHREAD
+
 rsource "../../../config/nrfconnect/chip-module/Kconfig.features"
 rsource "../../../config/nrfconnect/chip-module/Kconfig.defaults"
 source "Kconfig.zephyr"
diff --git a/examples/all-clusters-minimal-app/nrfconnect/README.md b/examples/all-clusters-minimal-app/nrfconnect/README.md
index 5f2d742..a843095 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/README.md
+++ b/examples/all-clusters-minimal-app/nrfconnect/README.md
@@ -55,11 +55,17 @@
 [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md)
 to read more about the platform structure and dependencies.
 
-The Matter device that runs the all clusters 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.
+By default, the Matter accessory device has IPv6 networking disabled. You must
+pair it with the Matter controller over Bluetooth® LE to get the configuration
+from the controller to use the device within a Thread or Wi-Fi network. You have
+to make the device discoverable manually (for security reasons). See
+[Bluetooth LE advertising](#bluetooth-le-advertising) to learn how to do this.
+The controller must get the commissioning information from the Matter accessory
+device and provision the device into the network.
+
+You can test this application remotely over the Thread or the Wi-Fi protocol,
+which in either case requires more devices, including a Matter controller that
+you can configure either on a PC or a mobile device.
 
 ### Bluetooth LE advertising
 
@@ -137,8 +143,8 @@
     Bluetooth LE.
 
 -   _Short Flash Off (950ms on/50ms off)_ &mdash; The device is fully
-    provisioned, but does not yet have full Thread network or service
-    connectivity.
+    provisioned, but does not yet have full connectivity for Thread or Wi-Fi
+    network, or the related services.
 
 -   _Solid On_ &mdash; The device is fully provisioned and has full Thread
     network and service connectivity.
diff --git a/examples/all-clusters-minimal-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay b/examples/all-clusters-minimal-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
index 04253ef..5662367 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
+++ b/examples/all-clusters-minimal-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
@@ -37,9 +37,6 @@
 &uart1 {
 	status = "disabled";
 };
-&gpio1 {
-	status = "disabled";
-};
 &i2c0 {
 	status = "disabled";
 };
diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp
index b78d291..25c4190 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp
+++ b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp
@@ -40,24 +40,28 @@
 #include <logging/log.h>
 #include <zephyr.h>
 
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
+
 using namespace ::chip;
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceLayer;
 
-#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
-#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
-#define APP_EVENT_QUEUE_SIZE 10
-#define BUTTON_PUSH_EVENT 1
-#define BUTTON_RELEASE_EVENT 0
+namespace {
+constexpr uint32_t kFactoryResetTriggerTimeout              = 3000;
+constexpr uint32_t kFactoryResetCancelWindowTimeout         = 3000;
+constexpr size_t kAppEventQueueSize                         = 10;
+constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE;
 
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
-K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), APP_EVENT_QUEUE_SIZE, alignof(AppEvent));
-
-static LEDWidget sStatusLED;
-static UnusedLedsWrapper<3> sUnusedLeds{ { DK_LED2, DK_LED3, DK_LED4 } };
+K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
 static k_timer sFunctionTimer;
 
-constexpr EndpointId kNetworkCommissioningEndpointSecondary = 0xFFFE;
+LEDWidget sStatusLED;
+FactoryResetLEDsWrapper<3> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTORY_RESET_SIGNAL_LED1, FACTORY_RESET_SIGNAL_LED2 } };
+
+bool sIsNetworkProvisioned = false;
+bool sIsNetworkEnabled     = false;
+bool sHaveBLEConnections   = false;
+} // namespace
 
 namespace LedConsts {
 constexpr uint32_t kBlinkRate_ms{ 500 };
@@ -133,7 +137,7 @@
     }
 
     // Initialize timer user data
-    k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr);
+    k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr);
     k_timer_user_data_set(&sFunctionTimer, this);
 
     // Initialize CHIP server
@@ -177,120 +181,141 @@
     while (true)
     {
         k_msgq_get(&sAppEventQueue, &event, K_FOREVER);
-        DispatchEvent(&event);
+        DispatchEvent(event);
     }
 
     return CHIP_NO_ERROR;
 }
 
-void AppTask::ButtonEventHandler(uint32_t aButtonState, uint32_t aHasChanged)
+void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)
 {
     AppEvent event;
-    event.Type = AppEvent::Type::Button;
+    event.Type = AppEventType::Button;
 
-    if (FUNCTION_BUTTON_MASK & aHasChanged)
+    if (FUNCTION_BUTTON_MASK & hasChanged)
     {
-        event.ButtonEvent.PinNo  = FUNCTION_BUTTON;
-        event.ButtonEvent.Action = (FUNCTION_BUTTON_MASK & aButtonState) ? BUTTON_PUSH_EVENT : BUTTON_RELEASE_EVENT;
-        event.Handler            = FunctionHandler;
-        PostEvent(&event);
+        event.ButtonEvent.PinNo = FUNCTION_BUTTON;
+        event.ButtonEvent.Action =
+            static_cast<uint8_t>((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased);
+        event.Handler = FunctionHandler;
+        PostEvent(event);
     }
 
-    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & aButtonState & aHasChanged)
+    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged)
     {
         event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
-        event.ButtonEvent.Action = BUTTON_PUSH_EVENT;
+        event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
         event.Handler            = StartBLEAdvertisementHandler;
-        PostEvent(&event);
+        PostEvent(event);
     }
 }
 
-void AppTask::TimerEventHandler(k_timer * aTimer)
+#ifdef CONFIG_MCUMGR_SMP_BT
+void AppTask::RequestSMPAdvertisingStart(void)
 {
-    if (!aTimer)
+    AppEvent event;
+    event.Type    = AppEventType::StartSMPAdvertising;
+    event.Handler = [](const AppEvent &) { GetDFUOverSMP().StartBLEAdvertising(); };
+    PostEvent(event);
+}
+#endif
+
+void AppTask::FunctionTimerTimeoutCallback(k_timer * timer)
+{
+    if (!timer)
+    {
         return;
+    }
 
     AppEvent event;
-    event.Type               = AppEvent::Type::Timer;
-    event.TimerEvent.Context = k_timer_user_data_get(aTimer);
+    event.Type               = AppEventType::Timer;
+    event.TimerEvent.Context = k_timer_user_data_get(timer);
     event.Handler            = FunctionTimerEventHandler;
-    PostEvent(&event);
+    PostEvent(event);
 }
 
-void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
+void AppTask::FunctionTimerEventHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->Type != AppEvent::Type::Timer)
+    if (event.Type != AppEventType::Timer)
         return;
 
-    // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT, initiate factory reset
-    if (Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::Normal)
+    // If we reached here, the button was held past kFactoryResetTriggerTimeout, initiate factory reset
+    if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
     {
-        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_TRIGGER_TIMEOUT);
+        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", kFactoryResetTriggerTimeout);
 
-        // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to cancel, if required.
-        StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
-        Instance().mMode = OperatingMode::FactoryReset;
+        // Start timer for kFactoryResetCancelWindowTimeout to allow user to cancel, if required.
+        Instance().StartTimer(kFactoryResetCancelWindowTimeout);
+        Instance().mFunction = FunctionEvent::FactoryReset;
 
 #ifdef CONFIG_STATE_LEDS
         // Turn off all LEDs before starting blink to make sure blink is co-ordinated.
         sStatusLED.Set(false);
-        sUnusedLeds.Set(false);
+        sFactoryResetLEDs.Set(false);
 
         sStatusLED.Blink(LedConsts::kBlinkRate_ms);
-        sUnusedLeds.Blink(LedConsts::kBlinkRate_ms);
+        sFactoryResetLEDs.Blink(LedConsts::kBlinkRate_ms);
 #endif
     }
-    else if (Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::FactoryReset)
+    else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
     {
         // Actually trigger Factory Reset
-        Instance().mMode = OperatingMode::Normal;
-        ConfigurationMgr().InitiateFactoryReset();
+        Instance().mFunction = FunctionEvent::NoneSelected;
+
+        chip::Server::GetInstance().ScheduleFactoryReset();
     }
 }
 
-void AppTask::FunctionHandler(AppEvent * aEvent)
+void AppTask::FunctionHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->ButtonEvent.PinNo != FUNCTION_BUTTON)
+    if (event.ButtonEvent.PinNo != FUNCTION_BUTTON)
         return;
 
     // To initiate factory reset: press the FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT + FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
     // All LEDs start blinking after FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
     // To cancel factory reset: release the FUNCTION_BUTTON once all LEDs start blinking within the
     // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
-    if (aEvent->ButtonEvent.Action == BUTTON_PUSH_EVENT)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
     {
-        if (!Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::Normal)
+        if (!Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::NoneSelected)
         {
-            StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+            Instance().StartTimer(kFactoryResetTriggerTimeout);
+
+            Instance().mFunction = FunctionEvent::SoftwareUpdate;
         }
     }
     else
     {
-        if (Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::FactoryReset)
+        // If the button was released before factory reset got initiated, trigger a software update.
+        if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
         {
-            sUnusedLeds.Set(false);
+            Instance().CancelTimer();
+
+#ifdef CONFIG_MCUMGR_SMP_BT
+            GetDFUOverSMP().StartServer();
+#else
+            LOG_INF("Software update is disabled");
+#endif
+            Instance().mFunction = FunctionEvent::NoneSelected;
+        }
+        else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
+        {
+            sFactoryResetLEDs.Set(false);
 
             UpdateStatusLED();
-            CancelTimer();
-
-            // Change the function to none selected since factory reset has been canceled.
-            Instance().mMode = OperatingMode::Normal;
-
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
             LOG_INF("Factory Reset has been Canceled");
         }
         else if (Instance().mFunctionTimerActive)
         {
             CancelTimer();
-            Instance().mMode = OperatingMode::Normal;
+            Instance().mFunction = FunctionEvent::NoneSelected;
         }
     }
 }
 
-void AppTask::StartBLEAdvertisementHandler(AppEvent *)
+void AppTask::StartBLEAdvertisementHandler(const AppEvent &)
 {
     if (Server::GetInstance().GetFabricTable().FabricCount() != 0)
     {
@@ -310,41 +335,39 @@
     }
 }
 
-void AppTask::UpdateLedStateEventHandler(AppEvent * aEvent)
+void AppTask::UpdateLedStateEventHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->Type == AppEvent::Type::UpdateLedState)
+    if (event.Type == AppEventType::UpdateLedState)
     {
-        aEvent->UpdateLedStateEvent.LedWidget->UpdateState();
+        event.UpdateLedStateEvent.LedWidget->UpdateState();
     }
 }
 
-void AppTask::LEDStateUpdateHandler(LEDWidget & aLedWidget)
+void AppTask::LEDStateUpdateHandler(LEDWidget & ledWidget)
 {
     AppEvent event;
-    event.Type                          = AppEvent::Type::UpdateLedState;
+    event.Type                          = AppEventType::UpdateLedState;
     event.Handler                       = UpdateLedStateEventHandler;
-    event.UpdateLedStateEvent.LedWidget = &aLedWidget;
-    PostEvent(&event);
+    event.UpdateLedStateEvent.LedWidget = &ledWidget;
+    PostEvent(event);
 }
 
 void AppTask::UpdateStatusLED()
 {
 #ifdef CONFIG_STATE_LEDS
-    /* Update the status LED.
-     *
-     * If thread and service provisioned, keep the LED On constantly.
-     *
-     * If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
-     * rate of 100ms.
-     *
-     * Otherwise, blink the LED On for a very short time. */
-    if (Instance().mIsThreadProvisioned && Instance().mIsThreadEnabled)
+    // Update the status LED.
+    //
+    // If thread and service provisioned, keep the LED On constantly.
+    //
+    // If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
+    // rate of 100ms.
+    //
+    // Otherwise, blink the LED On for a very short time.
+    if (sIsNetworkProvisioned && sIsNetworkEnabled)
     {
         sStatusLED.Set(true);
     }
-    else if (Instance().mHaveBLEConnections)
+    else if (sHaveBLEConnections)
     {
         sStatusLED.Blink(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms);
     }
@@ -355,19 +378,34 @@
 #endif
 }
 
-void AppTask::ChipEventHandler(const ChipDeviceEvent * aEvent, intptr_t /* aArg */)
+void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */)
 {
-    if (!aEvent)
-        return;
-    switch (aEvent->Type)
+    switch (event->Type)
     {
     case DeviceEventType::kCHIPoBLEAdvertisingChange:
-        Instance().mHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
+#ifdef CONFIG_CHIP_NFC_COMMISSIONING
+        if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
+        {
+            if (NFCMgr().IsTagEmulationStarted())
+            {
+                LOG_INF("NFC Tag emulation is already started");
+            }
+            else
+            {
+                ShareQRCodeOverNFC(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
+            }
+        }
+        else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
+        {
+            NFCMgr().StopTagEmulation();
+        }
+#endif
+        sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
         UpdateStatusLED();
         break;
     case DeviceEventType::kThreadStateChange:
-        Instance().mIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
-        Instance().mIsThreadEnabled     = ConnectivityMgr().IsThreadEnabled();
+        sIsNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsThreadEnabled();
         UpdateStatusLED();
         break;
     case DeviceEventType::kDnssdPlatformInitialized:
@@ -392,23 +430,19 @@
     Instance().mFunctionTimerActive = true;
 }
 
-void AppTask::PostEvent(AppEvent * aEvent)
+void AppTask::PostEvent(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT))
+    if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT) != 0)
     {
         LOG_INF("Failed to post event to app task event queue");
     }
 }
 
-void AppTask::DispatchEvent(AppEvent * aEvent)
+void AppTask::DispatchEvent(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->Handler)
+    if (event.Handler)
     {
-        aEvent->Handler(aEvent);
+        event.Handler(event);
     }
     else
     {
diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppConfig.h b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppConfig.h
index 01465d3..e36ebba 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppConfig.h
+++ b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppConfig.h
@@ -25,3 +25,6 @@
 #define BLE_ADVERTISEMENT_START_BUTTON_MASK DK_BTN4_MSK
 
 #define SYSTEM_STATE_LED DK_LED1
+#define FACTORY_RESET_SIGNAL_LED DK_LED2
+#define FACTORY_RESET_SIGNAL_LED1 DK_LED3
+#define FACTORY_RESET_SIGNAL_LED2 DK_LED4
diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppEvent.h b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppEvent.h
index f6cac85..4589d63 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppEvent.h
+++ b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppEvent.h
@@ -19,22 +19,33 @@
 
 #include <cstdint>
 
+#include "EventTypes.h"
+
 class LEDWidget;
 
+enum class AppEventType : uint8_t
+{
+    None = 0,
+    Button,
+    ButtonPushed,
+    ButtonReleased,
+    Timer,
+    UpdateLedState,
+    IdentifyStart,
+    IdentifyStop,
+    StartSMPAdvertising
+};
+
+enum class FunctionEvent : uint8_t
+{
+    NoneSelected   = 0,
+    SoftwareUpdate = 0,
+    FactoryReset,
+    AdvertisingStart
+};
+
 struct AppEvent
 {
-    using EventHandler = void (*)(AppEvent *);
-
-    enum class Type : uint8_t
-    {
-        None,
-        Button,
-        Timer,
-        UpdateLedState,
-    };
-
-    Type Type{ Type::None };
-
     union
     {
         struct
@@ -52,5 +63,6 @@
         } UpdateLedStateEvent;
     };
 
+    AppEventType Type{ AppEventType::None };
     EventHandler Handler;
 };
diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h
index 04f44f4..94a3de3 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h
+++ b/examples/all-clusters-minimal-app/nrfconnect/main/include/AppTask.h
@@ -19,13 +19,19 @@
 
 #include <platform/CHIPDeviceLayer.h>
 
+#include "AppEvent.h"
+#include "LEDWidget.h"
+
 #if CONFIG_CHIP_FACTORY_DATA
 #include <platform/nrfconnect/FactoryDataProvider.h>
 #endif
 
+#ifdef CONFIG_MCUMGR_SMP_BT
+#include "DFUOverSMP.h"
+#endif
+
 struct k_timer;
-class AppEvent;
-class LEDWidget;
+struct Identify;
 
 class AppTask
 {
@@ -38,35 +44,30 @@
     CHIP_ERROR StartApp();
 
 private:
-    enum class OperatingMode : uint8_t
-    {
-        Normal,
-        FactoryReset,
-        Invalid
-    };
-
     CHIP_ERROR Init();
-    void DispatchEvent(AppEvent * aEvent);
 
-    // statics needed to interact with zephyr C API
-    static void CancelTimer(void);
-    static void StartTimer(uint32_t aTimeoutInMs);
-    static void FunctionTimerEventHandler(AppEvent * aEvent);
-    static void FunctionHandler(AppEvent * aEvent);
-    static void ButtonEventHandler(uint32_t aButtonsState, uint32_t aHasChanged);
-    static void TimerEventHandler(k_timer * aTimer);
-    static void PostEvent(AppEvent * aEvent);
+    static void CancelTimer();
+    static void StartTimer(uint32_t timeoutInMs);
+
+    static void PostEvent(const AppEvent & event);
+    static void DispatchEvent(const AppEvent & event);
+    static void FunctionTimerEventHandler(const AppEvent & event);
+    static void FunctionHandler(const AppEvent & event);
+    static void StartBLEAdvertisementHandler(const AppEvent & event);
+    static void UpdateLedStateEventHandler(const AppEvent & event);
+
+    static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+    static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged);
+    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
+    static void FunctionTimerTimeoutCallback(k_timer * timer);
     static void UpdateStatusLED();
-    static void LEDStateUpdateHandler(LEDWidget & aLedWidget);
-    static void UpdateLedStateEventHandler(AppEvent * aEvent);
-    static void StartBLEAdvertisementHandler(AppEvent * aEvent);
-    static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * aEvent, intptr_t aArg);
 
-    OperatingMode mMode{ OperatingMode::Normal };
-    bool mFunctionTimerActive{ false };
-    bool mIsThreadProvisioned{ false };
-    bool mIsThreadEnabled{ false };
-    bool mHaveBLEConnections{ false };
+#ifdef CONFIG_MCUMGR_SMP_BT
+    static void RequestSMPAdvertisingStart(void);
+#endif
+
+    FunctionEvent mFunction   = FunctionEvent::NoneSelected;
+    bool mFunctionTimerActive = false;
 
 #if CONFIG_CHIP_FACTORY_DATA
     chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/main.cpp b/examples/all-clusters-minimal-app/nrfconnect/main/main.cpp
index 8f71ca5..ec11d18 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/main/main.cpp
+++ b/examples/all-clusters-minimal-app/nrfconnect/main/main.cpp
@@ -24,7 +24,7 @@
 #include <usb/usb_device.h>
 #endif
 
-LOG_MODULE_REGISTER(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip;
 
diff --git a/examples/all-clusters-minimal-app/nrfconnect/prj.conf b/examples/all-clusters-minimal-app/nrfconnect/prj.conf
index 496ca24..2c2c8d2 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/prj.conf
+++ b/examples/all-clusters-minimal-app/nrfconnect/prj.conf
@@ -14,21 +14,20 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# CHIP PID: 32769 == 0x8001 (all-clusters-app-minimal)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
+CONFIG_STD_CPP14=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 
-# OpenThread settings
-CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
-CONFIG_OPENTHREAD_MTD=y
-CONFIG_OPENTHREAD_FTD=n
-
 # Bluetooth overrides
 CONFIG_BT_DEVICE_NAME="AllClusters"
 
@@ -42,9 +41,3 @@
 
 # Disable QSPI NOR
 CONFIG_CHIP_QSPI_NOR=n
-
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-
-# CHIP PID: 32769 == 0x8001 (all-clusters-minimal-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
diff --git a/examples/all-clusters-minimal-app/nrfconnect/prj_dfu.conf b/examples/all-clusters-minimal-app/nrfconnect/prj_dfu.conf
index 3812357..292d7a0 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/prj_dfu.conf
+++ b/examples/all-clusters-minimal-app/nrfconnect/prj_dfu.conf
@@ -14,21 +14,20 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# CHIP PID: 32769 == 0x8001 (all-clusters-minimal-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
+CONFIG_STD_CPP14=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 
-# OpenThread settings
-CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
-CONFIG_OPENTHREAD_MTD=y
-CONFIG_OPENTHREAD_FTD=n
-
 # Bluetooth overrides
 CONFIG_BT_DEVICE_NAME="AllClusters"
 
@@ -37,8 +36,8 @@
 CONFIG_MPU_STACK_GUARD=y
 CONFIG_RESET_ON_FATAL_ERROR=n
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-
-# CHIP PID: 32769 == 0x8001 (all-clusters-minimal-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
+# reduce application size by disabling including assertions in the output file.
+CONFIG_ASSERT_VERBOSE=n
+CONFIG_ASSERT_NO_FILE_INFO=y
+CONFIG_ASSERT_NO_COND_INFO=y
+CONFIG_ASSERT_NO_MSG_INFO=y
diff --git a/examples/all-clusters-minimal-app/nrfconnect/prj_release.conf b/examples/all-clusters-minimal-app/nrfconnect/prj_release.conf
index 27667cb..33cd3f3 100644
--- a/examples/all-clusters-minimal-app/nrfconnect/prj_release.conf
+++ b/examples/all-clusters-minimal-app/nrfconnect/prj_release.conf
@@ -14,33 +14,26 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# CHIP PID: 32769 == 0x8001 (all-clusters-app-minimal)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
+CONFIG_STD_CPP14=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 
-# OpenThread settings
-CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
-CONFIG_OPENTHREAD_MTD=y
-CONFIG_OPENTHREAD_FTD=n
-
 # Bluetooth overrides
 CONFIG_BT_DEVICE_NAME="AllClusters"
 
 # Enable system reset on fatal error
 CONFIG_RESET_ON_FATAL_ERROR=y
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-
-# CHIP PID: 32769 == 0x8001 (all-clusters-minimal-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32769
-
 # Disable all debug features
 CONFIG_SHELL=n
 CONFIG_OPENTHREAD_SHELL=n
diff --git a/examples/light-switch-app/nrfconnect/CMakeLists.txt b/examples/light-switch-app/nrfconnect/CMakeLists.txt
index b4210cb..58c380e 100644
--- a/examples/light-switch-app/nrfconnect/CMakeLists.txt
+++ b/examples/light-switch-app/nrfconnect/CMakeLists.txt
@@ -25,6 +25,7 @@
 # Set Kconfig root files that will be processed as a first Kconfig for used child images.
 set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root)
 set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root)
+set(hci_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.root)
 
 if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf")
     set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml)
diff --git a/examples/light-switch-app/nrfconnect/Kconfig b/examples/light-switch-app/nrfconnect/Kconfig
index 8b4d87b..042bdac 100644
--- a/examples/light-switch-app/nrfconnect/Kconfig
+++ b/examples/light-switch-app/nrfconnect/Kconfig
@@ -23,6 +23,23 @@
 	  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.
 
+# Sample configuration used for Thread networking
+if NET_L2_OPENTHREAD
+
+choice OPENTHREAD_NORDIC_LIBRARY_CONFIGURATION
+	default OPENTHREAD_NORDIC_LIBRARY_MTD
+endchoice
+
+choice OPENTHREAD_DEVICE_TYPE
+	default OPENTHREAD_MTD
+endchoice
+
+config CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT
+	bool
+	default y
+
+endif # NET_L2_OPENTHREAD
+
 rsource "../../../config/nrfconnect/chip-module/Kconfig.features"
 rsource "../../../config/nrfconnect/chip-module/Kconfig.defaults"
 source "Kconfig.zephyr"
diff --git a/examples/light-switch-app/nrfconnect/README.md b/examples/light-switch-app/nrfconnect/README.md
index 7d55b03..7aef1f6 100644
--- a/examples/light-switch-app/nrfconnect/README.md
+++ b/examples/light-switch-app/nrfconnect/README.md
@@ -15,12 +15,16 @@
 
 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.
+Semiconductor's nRF Connect SDK, and was created to facilitate testing and
+certification of a Matter device communicating over a low-power, 802.15.4 Thread
+network, or Wi-Fi 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. The
-device works as a Thread Sleepy End Device.
+into an existing Matter network and can be controlled by this network. In the
+case of Thread, this device works as a Thread Sleepy End Device. Support for
+both Thread and Wi-Fi is mutually exclusive and depends on the hardware
+platform, so only one protocol can be supported for a specific light switch
+device.
 
 <hr>
 
@@ -30,6 +34,7 @@
     -   [Device Firmware Upgrade](#device-firmware-upgrade)
 -   [Requirements](#requirements)
     -   [Supported devices](#supported_devices)
+    -   [IPv6 network support](#ipv6-network-support)
 -   [Device UI](#device-ui)
     -   [LEDs](#leds)
     -   [Buttons](#buttons)
@@ -46,7 +51,12 @@
     -   [Example build types](#example-build-types)
 -   [Flashing and debugging](#flashing-and-debugging)
 -   [Testing the example](#testing-the-example)
-    -   [Binding process](#binding-process)
+    -   [Commissioning the lighting device](#commissioning-the-lighting-device)
+    -   [Binding cluster and endpoints](#binding-cluster-and-endpoints)
+    -   [Unicast binding to a remote endpoint using the CHIP Tool for Windows or Linux](#unicast-binding-to-a-remote-endpoint-using-the-chip-tool-for-windows-or-linux)
+    -   [Group multicast binding to the group of remote endpoints using the CHIP Tool for Windows or Linux](#group-multicast-binding-to-the-group-of-remote-endpoints-using-the-chip-tool-for-windows-or-linux)
+    -   [Testing the communication](#testing-the-communication)
+    -   [Testing the Generic Switch](#testing-the-generic-switch)
     -   [Testing Device Firmware Upgrade](#testing-device-firmware-upgrade)
 
 <hr>
@@ -62,6 +72,27 @@
 [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md)
 to read more about the platform structure and dependencies.
 
+By default, the Matter accessory device has IPv6 networking disabled. You must
+pair it with the Matter controller over Bluetooth® LE to get the configuration
+from the controller to use the device within a Thread or Wi-Fi network. You have
+to make the device discoverable manually (for security reasons). See
+[Bluetooth LE advertising](#bluetooth-le-advertising) to learn how to do this.
+The controller must get the commissioning information from the Matter accessory
+device and provision the device into the network.
+
+You can test this application remotely over the Thread or the Wi-Fi protocol,
+which in either case requires more devices, including a Matter controller that
+you can configure either on a PC or a mobile device.
+
+The sample uses buttons for controlling the bound device's LEDs. You can test it
+in the following ways:
+
+-   Standalone, using a single DK that runs the light switch application.
+
+-   Remotely over the Thread or the Wi-Fi protocol, which in either case
+    requires more devices, including a Matter controller that you can configure
+    either on a PC or a mobile device.
+
 In Matter, the following types of light switch devices are available:
 
 -   Group 1: On/Off Light Switch, Dimmer Switch, Color Dimmer Switch, Control
@@ -98,7 +129,7 @@
 
 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
+has Thread disabled, and it should be paired with the Matter controller and get
 configuration from it. Some actions required before establishing full
 communication are described below.
 
@@ -109,7 +140,11 @@
 
 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**.
+LE advertising manually after powering up the device by pressing:
+
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: **Button 4**.
+
+-   On nRF7002 DK: **Button 2**.
 
 ### Bluetooth LE rendezvous
 
@@ -119,16 +154,16 @@
 
 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.
+the UART console, and shared using an NFC tag. The emulation of the NFC tag
+emulation starts automatically when Bluetooth LE advertising is started and
+stays enabled until Bluetooth LE advertising timeout expires.
 
-#### Thread provisioning
+#### Thread or Wi-Fi 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.
+The provisioning operation, which is the Last part of the rendezvous procedure,
+involves sending the Thread or Wi-Fi network credentials from the Matter
+controller to the Matter device. As a result, the device joins the Thread or
+Wi-Fi network and can communicate with other devices in the network.
 
 ### Device Firmware Upgrade
 
@@ -203,10 +238,20 @@
 
 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`      | <details><summary>nRF52840 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_DK_info-medium.jpg" alt="nRF52840 DK"/></details> |
-| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK)   | `nrf5340dk_nrf5340_cpuapp` | <details><summary>nRF5340 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF5340_DK_info-medium.jpg" alt="nRF5340 DK"/></details>    |
+| Hardware platform                                                                                               | Build target               | Platform image                                                                                                                                   |
+| --------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
+| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)                       | `nrf52840dk_nrf52840`      | <details><summary>nRF52840 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_DK_info-medium.jpg" alt="nRF52840 DK"/></details> |
+| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK)                         | `nrf5340dk_nrf5340_cpuapp` | <details><summary>nRF5340 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF5340_DK_info-medium.jpg" alt="nRF5340 DK"/></details>    |
+| [nRF7002 DK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf7002.html#nrf7002dk-nrf5340) | `nrf7002dk_nrf5340_cpuapp` | <details><summary>nRF7002DK</summary><img src="../../platform/nrfconnect/doc/images/nrf7002dk.jpg" alt="nRF7002 DK"/></details>                  |
+
+### IPv6 network support
+
+The development kits for this sample offer the following IPv6 network support
+for Matter:
+
+-   Matter over Thread is supported for `nrf52840dk_nrf52840` and
+    `nrf5340dk_nrf5340_cpuapp`.
+-   Matter over Wi-Fi is supported for `nrf7002dk_nrf5340_cpuapp`.
 
 ### Additional requirements for testing
 
@@ -246,11 +291,10 @@
     Bluetooth LE.
 
 -   _Short Flash Off (950ms on/50ms off)_ &mdash; The device is fully
-    provisioned, but does not yet have full Thread network or service
-    connectivity.
+    provisioned, but does not yet have full connectivity for Thread or Wi-Fi
+    network.
 
--   _Solid On_ &mdash; The device is fully provisioned and has full Thread
-    network and service connectivity.
+-   _Solid On_ &mdash; The device is fully provisioned.
 
 **LED 2** simulates the BLE DFU process. The following states are possible:
 
@@ -259,10 +303,9 @@
 -   _Rapid Even Flashing (30 ms off / 170 ms on)_ &mdash; 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.
+**All LEDs**
+
+Blink in unison when the factory reset procedure is initiated.
 
 ### Buttons
 
@@ -271,36 +314,58 @@
 
 **Button 1** can be used for the following purposes:
 
--   _Pressed for 6 s_ &mdash; 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_ &mdash; 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.
+    instructions.
+
+-   _Pressed for more than 3 s_ &mdash; initiates the factory reset of the
+    device. Releasing the button within the 3-second window cancels the factory
+    reset procedure.
 
 **Button 2** can be used for the following purposes:
 
--   _Pressed once_ &mdash; Changes the light state to the opposite one on a
-    bound lighting bulb device ([lighting-app](../../lighting-app/nrfconnect/)
-    example).
+-   On nRF52840 DK, nRF5340 DK and nRF21540 DK:
 
--   _Pressed for more than 2 s_ &mdash; 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.
+    -   If pressed for less than 0.5 seconds, it changes the light state to the
+        opposite one on the bound lighting device
+        ([lighting-app](../../lighting-app/nrfconnect/))
 
-**Button 3** can be used for the following purposes:
+    -   If pressed for more than 0.5 seconds, it changes the brightness of the
+        light on the bound lighting bulb device
+        ([lighting-app](../../lighting-app/nrfconnect/)). The brightness is
+        changing from 0% to 100% with 1% increments every 300 milliseconds as
+        long as **Button 2** is pressed.
 
--   _Pressed once_ &mdash; Changes the value of the attribute `CurrentPosition`
-    and (if subscribed) sends the event notifications to the controller.
+-   On nRF7002 DK:
 
-**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).
+    -   If the device is not commissioned to a Matter network, it starts the NFC
+        tag emulation, enables Bluetooth LE advertising for the predefined
+        period of time (15 minutes by default), and makes the device
+        discoverable over Bluetooth LE. This button is used during the
+        commissioning procedure.
+
+    -   If the device is commissioned to a Matter network, it controls the light
+        on the bound lighting device. Depending on how long you press the
+        button:
+
+            - If pressed for less than 0.5 seconds, it changes the light state to the opposite one on the bound lighting device ([lighting-app](../../lighting-app/nrfconnect/)).
+
+            - If pressed for more than 0.5 seconds, it changes the brightness of the light on the bound lighting bulb device ([lighting-app](../../lighting-app/nrfconnect/)). The brightness is changing from 0% to 100% with 1% increments every 300 milliseconds as long as **Button 2** is pressed.
+
+**Button 4**
+
+-   On nRF52840 DK, nRF5340 DK and nRF21540 DK:
+
+    Starts the NFC tag emulation, enables Bluetooth LE advertising for the
+    predefined period of time (15 minutes by default), and makes the device
+    discoverable over Bluetooth LE. This button is used during the commissioning
+    procedure.
+
+-   On nRF7002 DK:
+
+    Not available.
 
 **SEGGER J-Link USB port** can be used to get logs from the device or
 communicate with it using the
diff --git a/examples/light-switch-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/light-switch-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay
new file mode 100644
index 0000000..90f303f
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay
@@ -0,0 +1,22 @@
+/*
+ *    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;
+	};
+};
diff --git a/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj.conf b/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf b/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf b/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj.conf
index 287c782..0dbf710 100644
--- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj.conf
+++ b/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj.conf
@@ -23,7 +23,6 @@
 # Bootloader size optimization
 # Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding
 # in board files.
-CONFIG_GPIO=n
 CONFIG_CONSOLE=n
 CONFIG_SERIAL=n
 CONFIG_UART_CONSOLE=n
diff --git a/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj_release.conf
index 287c782..0dbf710 100644
--- a/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj_release.conf
+++ b/examples/light-switch-app/nrfconnect/child_image/mcuboot/prj_release.conf
@@ -23,7 +23,6 @@
 # Bootloader size optimization
 # Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding
 # in board files.
-CONFIG_GPIO=n
 CONFIG_CONSOLE=n
 CONFIG_SERIAL=n
 CONFIG_UART_CONSOLE=n
diff --git a/examples/light-switch-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/light-switch-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml
new file mode 100644
index 0000000..3c56dc0
--- /dev/null
+++ b/examples/light-switch-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -0,0 +1,56 @@
+mcuboot:
+    address: 0x0
+    size: 0xC000
+    region: flash_primary
+mcuboot_pad:
+    address: 0xC000
+    size: 0x200
+app:
+    address: 0xC200
+    size: 0xeee00
+mcuboot_primary:
+    orig_span: &id001
+        - mcuboot_pad
+        - app
+    span: *id001
+    address: 0xC000
+    size: 0xef000
+    region: flash_primary
+mcuboot_primary_app:
+    orig_span: &id002
+        - app
+    span: *id002
+    address: 0xC200
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
+settings_storage:
+    address: 0xfc000
+    size: 0x4000
+    region: flash_primary
+mcuboot_primary_1:
+    address: 0x0
+    size: 0x40000
+    device: flash_ctrl
+    region: ram_flash
+mcuboot_secondary:
+    address: 0x0
+    size: 0xef000
+    device: MX25R64
+    region: external_flash
+mcuboot_secondary_1:
+    address: 0xef000
+    size: 0x40000
+    device: MX25R64
+    region: external_flash
+external_flash:
+    address: 0x12f000
+    size: 0x6D1000
+    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
index 4eee5a5..3ba17c7 100644
--- a/examples/light-switch-app/nrfconnect/main/AppTask.cpp
+++ b/examples/light-switch-app/nrfconnect/main/AppTask.cpp
@@ -18,7 +18,8 @@
 
 #include "AppTask.h"
 #include "AppConfig.h"
-#include "LEDWidget.h"
+#include "BoardUtil.h"
+#include "LEDUtil.h"
 #include "LightSwitch.h"
 
 #include <DeviceInfoProviderImpl.h>
@@ -34,6 +35,11 @@
 #include <platform/CHIPDeviceLayer.h>
 #include <system/SystemError.h>
 
+#ifdef CONFIG_CHIP_WIFI
+#include <app/clusters/network-commissioning/network-commissioning.h>
+#include <platform/nrfconnect/wifi/NrfWiFiDriver.h>
+#endif
+
 #ifdef CONFIG_CHIP_OTA_REQUESTOR
 #include "OTAUtil.h"
 #endif
@@ -42,23 +48,23 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
+
 using namespace ::chip;
 using namespace ::chip::app;
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceLayer;
 
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
 namespace {
 constexpr EndpointId kLightDimmerSwitchEndpointId  = 1;
 constexpr EndpointId kLightGenericSwitchEndpointId = 2;
 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;
+constexpr uint32_t kFactoryResetTriggerTimeout      = 3000;
+constexpr uint32_t kFactoryResetCancelWindowTimeout = 3000;
+constexpr uint32_t kDimmerTriggeredTimeout          = 500;
+constexpr uint32_t kDimmerInterval                  = 300;
+constexpr size_t kAppEventQueueSize                 = 10;
 
 K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
 
@@ -71,28 +77,43 @@
                                                                                    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
 
 LEDWidget sStatusLED;
-LEDWidget sBleLED;
 LEDWidget sIdentifyLED;
-LEDWidget sUnusedLED;
-
-bool sIsThreadProvisioned    = false;
-bool sIsThreadEnabled        = false;
-bool sIsThreadBLEAdvertising = false;
-#ifdef CONFIG_MCUMGR_SMP_BT
-bool sIsSMPAdvertising = false;
+#if NUMBER_OF_LEDS == 4
+FactoryResetLEDsWrapper<2> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTORY_RESET_SIGNAL_LED1 } };
 #endif
-bool sHaveBLEConnections = false;
-bool sWasDimmerTriggered = false;
+
+bool sIsNetworkProvisioned = false;
+bool sIsNetworkEnabled     = false;
+bool sHaveBLEConnections   = false;
+bool sWasDimmerTriggered   = false;
 
 k_timer sFunctionTimer;
 k_timer sDimmerPressKeyTimer;
 k_timer sDimmerTimer;
 
 chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+} // namespace
 
-} /* namespace */
+namespace LedConsts {
+constexpr uint32_t kBlinkRate_ms{ 500 };
+constexpr uint32_t kIdentifyBlinkRate_ms{ 500 };
 
-AppTask AppTask::sAppTask;
+namespace StatusLed {
+namespace Unprovisioned {
+constexpr uint32_t kOn_ms{ 100 };
+constexpr uint32_t kOff_ms{ kOn_ms };
+} // namespace Unprovisioned
+namespace Provisioned {
+constexpr uint32_t kOn_ms{ 50 };
+constexpr uint32_t kOff_ms{ 950 };
+} // namespace Provisioned
+
+} // namespace StatusLed
+} // namespace LedConsts
+
+#ifdef CONFIG_CHIP_WIFI
+app::Clusters::NetworkCommissioning::Instance sWiFiCommissioningInstance(0, &(NetworkCommissioning::NrfWiFiDriver::Instance()));
+#endif
 
 CHIP_ERROR AppTask::Init()
 {
@@ -131,7 +152,9 @@
         LOG_ERR("ConnectivityMgr().SetThreadDeviceType() failed: %s", ErrorStr(err));
         return err;
     }
-#elif !defined(CONFIG_WIFI_NRF700X)
+#elif defined(CONFIG_CHIP_WIFI)
+    sWiFiCommissioningInstance.Init();
+#else
     return CHIP_ERROR_INTERNAL;
 #endif
 
@@ -140,14 +163,12 @@
     // 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");
@@ -155,9 +176,9 @@
     }
 
     // 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_init(&sFunctionTimer, AppTask::FunctionTimerTimeoutCallback, nullptr);
+    k_timer_init(&sDimmerPressKeyTimer, AppTask::FunctionTimerTimeoutCallback, nullptr);
+    k_timer_init(&sDimmerTimer, AppTask::FunctionTimerTimeoutCallback, nullptr);
     k_timer_user_data_set(&sDimmerTimer, this);
     k_timer_user_data_set(&sDimmerPressKeyTimer, this);
     k_timer_user_data_set(&sFunctionTimer, this);
@@ -222,30 +243,35 @@
     while (true)
     {
         k_msgq_get(&sAppEventQueue, &event, K_FOREVER);
-        DispatchEvent(&event);
+        DispatchEvent(event);
     }
 
     return CHIP_NO_ERROR;
 }
 
-void AppTask::ButtonPushHandler(AppEvent * aEvent)
+void AppTask::ButtonPushHandler(const AppEvent & event)
 {
-    if (aEvent->Type == AppEvent::kEventType_Button)
+    if (event.Type == AppEventType::Button)
     {
-        switch (aEvent->ButtonEvent.PinNo)
+        switch (event.ButtonEvent.PinNo)
         {
         case FUNCTION_BUTTON:
-            sAppTask.StartTimer(Timer::Function, kFactoryResetTriggerTimeout);
-            sAppTask.mFunction = TimerFunction::SoftwareUpdate;
+            Instance().StartTimer(Timer::Function, kFactoryResetTriggerTimeout);
+            Instance().mFunction = FunctionEvent::SoftwareUpdate;
             break;
-        case DIMMER_SWITCH_BUTTON:
+        case
+#if NUMBER_OF_BUTTONS == 2
+            BLE_ADVERTISEMENT_START_AND_SWITCH_BUTTON:
+            if (!ConnectivityMgr().IsBLEAdvertisingEnabled() && Server::GetInstance().GetFabricTable().FabricCount() == 0)
+            {
+                break;
+            }
+#else
+            SWITCH_BUTTON:
+#endif
             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;
-        case GENERIC_SWITCH_BUTTON:
-            LOG_INF("GenericSwitch: InitialPress");
-            LightSwitch::GetInstance().GenericSwitchInitialPress();
+            Instance().StartTimer(Timer::DimmerTrigger, kDimmerTriggeredTimeout);
             break;
         default:
             break;
@@ -253,94 +279,105 @@
     }
 }
 
-void AppTask::ButtonReleaseHandler(AppEvent * aEvent)
+void AppTask::ButtonReleaseHandler(const AppEvent & event)
 {
-
-    if (aEvent->Type == AppEvent::kEventType_Button)
+    if (event.Type == AppEventType::Button)
     {
-        switch (aEvent->ButtonEvent.PinNo)
+        switch (event.ButtonEvent.PinNo)
         {
         case FUNCTION_BUTTON:
-            if (sAppTask.mFunction == TimerFunction::SoftwareUpdate)
+            if (Instance().mFunction == FunctionEvent::SoftwareUpdate)
             {
-                sAppTask.CancelTimer(Timer::Function);
-                sAppTask.mFunction = TimerFunction::NoneSelected;
+                Instance().CancelTimer(Timer::Function);
+                Instance().mFunction = FunctionEvent::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)
+            else if (Instance().mFunction == FunctionEvent::FactoryReset)
             {
                 UpdateStatusLED();
 
-                sAppTask.CancelTimer(Timer::Function);
-                sAppTask.mFunction = TimerFunction::NoneSelected;
+                Instance().CancelTimer(Timer::Function);
+                Instance().mFunction = FunctionEvent::NoneSelected;
                 LOG_INF("Factory Reset has been canceled");
             }
             break;
-        case DIMMER_SWITCH_BUTTON:
+#if NUMBER_OF_BUTTONS == 4
+        case SWITCH_BUTTON:
+#else
+        case BLE_ADVERTISEMENT_START_AND_SWITCH_BUTTON:
+            if (!ConnectivityMgr().IsBLEAdvertisingEnabled() && Server::GetInstance().GetFabricTable().FabricCount() == 0)
+            {
+                AppEvent buttonEvent;
+                buttonEvent.Type               = AppEventType::Button;
+                buttonEvent.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_AND_SWITCH_BUTTON;
+                buttonEvent.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
+                buttonEvent.Handler            = StartBLEAdvertisementHandler;
+                PostEvent(buttonEvent);
+                break;
+            }
+#endif
             if (!sWasDimmerTriggered)
             {
                 LightSwitch::GetInstance().InitiateActionSwitch(LightSwitch::Action::Toggle);
             }
-            sAppTask.CancelTimer(Timer::Dimmer);
-            sAppTask.CancelTimer(Timer::DimmerTrigger);
+            Instance().CancelTimer(Timer::Dimmer);
+            Instance().CancelTimer(Timer::DimmerTrigger);
             sWasDimmerTriggered = false;
             break;
-        case GENERIC_SWITCH_BUTTON:
-            LOG_INF("GenericSwitch: ShortRelease");
-            LightSwitch::GetInstance().GenericSwitchReleasePress();
-            break;
         default:
             break;
         }
     }
 }
 
-void AppTask::TimerEventHandler(AppEvent * aEvent)
+void AppTask::TimerEventHandler(const AppEvent & event)
 {
-    if (aEvent->Type == AppEvent::kEventType_Timer)
+    if (event.Type == AppEventType::Timer)
     {
-        switch ((Timer) aEvent->TimerEvent.TimerType)
+        switch (static_cast<Timer>(event.TimerEvent.TimerType))
         {
         case Timer::Function:
-            if (sAppTask.mFunction == TimerFunction::SoftwareUpdate)
+            if (Instance().mFunction == FunctionEvent::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;
+                LOG_INF("Factory Reset has been triggered. Release button within %u ms to cancel.",
+                        kFactoryResetCancelWindowTimeout);
+                Instance().StartTimer(Timer::Function, kFactoryResetCancelWindowTimeout);
+                Instance().mFunction = FunctionEvent::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);
+#if NUMBER_OF_LEDS == 4
+                sFactoryResetLEDs.Set(false);
+#endif
 
-                sStatusLED.Blink(500);
-                sIdentifyLED.Blink(500);
-                sBleLED.Blink(500);
-                sUnusedLED.Blink(500);
+                sStatusLED.Blink(LedConsts::kBlinkRate_ms);
+                sIdentifyLED.Blink(LedConsts::kBlinkRate_ms);
+#if NUMBER_OF_LEDS == 4
+                sFactoryResetLEDs.Blink(LedConsts::kBlinkRate_ms);
+#endif
 #endif
             }
-            else if (sAppTask.mFunction == TimerFunction::FactoryReset)
+            else if (Instance().mFunction == FunctionEvent::FactoryReset)
             {
-                sAppTask.mFunction = TimerFunction::NoneSelected;
+                Instance().mFunction = FunctionEvent::NoneSelected;
                 LOG_INF("Factory Reset triggered");
-                ConfigurationMgr().InitiateFactoryReset();
+                chip::Server::GetInstance().ScheduleFactoryReset();
             }
             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);
+            Instance().StartTimer(Timer::Dimmer, kDimmerInterval);
+            Instance().CancelTimer(Timer::DimmerTrigger);
             break;
         case Timer::Dimmer:
             LightSwitch::GetInstance().DimmerChangeBrightness();
@@ -354,22 +391,21 @@
 void AppTask::IdentifyStartHandler(Identify *)
 {
     AppEvent event;
-    event.Type    = AppEvent::kEventType_IdentifyStart;
-    event.Handler = [](AppEvent *) { sIdentifyLED.Blink(kIdentifyBlinkRateMs); };
-    sAppTask.PostEvent(&event);
+    event.Type    = AppEventType::IdentifyStart;
+    event.Handler = [](const AppEvent &) { sIdentifyLED.Blink(LedConsts::kIdentifyBlinkRate_ms); };
+    PostEvent(event);
 }
 
 void AppTask::IdentifyStopHandler(Identify *)
 {
     AppEvent event;
-    event.Type    = AppEvent::kEventType_IdentifyStop;
-    event.Handler = [](AppEvent *) { sIdentifyLED.Set(false); };
-    sAppTask.PostEvent(&event);
+    event.Type    = AppEventType::IdentifyStop;
+    event.Handler = [](const AppEvent &) { sIdentifyLED.Set(false); };
+    PostEvent(event);
 }
 
-void AppTask::StartBLEAdvertisingHandler(AppEvent * aEvent)
+void AppTask::StartBLEAdvertisementHandler(const AppEvent &)
 {
-    /// 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");
@@ -382,22 +418,20 @@
         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 */)
+void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */)
 {
-    switch (aEvent->Type)
+    switch (event->Type)
     {
     case DeviceEventType::kCHIPoBLEAdvertisingChange:
-        sIsThreadBLEAdvertising = true;
         UpdateStatusLED();
 #ifdef CONFIG_CHIP_NFC_COMMISSIONING
-        if (aEvent->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
+        if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
         {
             if (NFCMgr().IsTagEmulationStarted())
             {
@@ -405,10 +439,10 @@
             }
             else
             {
-                ShareQRCodeOverNFC(RendezvousInformationFlags(RendezvousInformationFlag::kBLE));
+                ShareQRCodeOverNFC(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
             }
         }
-        else if (aEvent->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
+        else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
         {
             NFCMgr().StopTagEmulation();
         }
@@ -416,24 +450,29 @@
         sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
         UpdateStatusLED();
         break;
-    case DeviceEventType::kThreadStateChange:
-        sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
-        sIsThreadEnabled     = ConnectivityMgr().IsThreadEnabled();
-        UpdateStatusLED();
-        break;
+#if defined(CONFIG_NET_L2_OPENTHREAD)
     case DeviceEventType::kDnssdPlatformInitialized:
 #if CONFIG_CHIP_OTA_REQUESTOR
         InitBasicOTARequestor();
+#endif // CONFIG_CHIP_OTA_REQUESTOR
+        break;
+    case DeviceEventType::kThreadStateChange:
+        sIsNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsThreadEnabled();
+#elif defined(CONFIG_CHIP_WIFI)
+    case DeviceEventType::kWiFiConnectivityChange:
+        sIsNetworkProvisioned = ConnectivityMgr().IsWiFiStationProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsWiFiStationEnabled();
+#if CONFIG_CHIP_OTA_REQUESTOR
+        if (event->WiFiConnectivityChange.Result == kConnectivity_Established)
+        {
+            InitBasicOTARequestor();
+        }
+#endif // CONFIG_CHIP_OTA_REQUESTOR
 #endif
+        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;
     }
 }
@@ -441,127 +480,106 @@
 void AppTask::UpdateStatusLED()
 {
 #ifdef CONFIG_STATE_LEDS
-    sUnusedLED.Set(false);
+#if NUMBER_OF_LEDS == 4
+    sFactoryResetLEDs.Set(false);
+#endif
 
-    // 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)
+    // Update the status LED.
+    //
+    // If IPv6 network and service provisioned, keep the LED on constantly.
+    //
+    // If the system has BLE connection(s) up till the stage above, THEN blink the LED at an even
+    // rate of 100ms.
+    //
+    // Otherwise, blink the LED for a very short time.
+    if (sIsNetworkProvisioned && sIsNetworkEnabled)
     {
         sStatusLED.Set(true);
     }
     else if (sHaveBLEConnections)
     {
-        sStatusLED.Blink(30, 170);
+        sStatusLED.Blink(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms);
     }
     else
     {
-        sStatusLED.Set(false);
+        sStatusLED.Blink(LedConsts::StatusLed::Provisioned::kOn_ms, LedConsts::StatusLed::Provisioned::kOff_ms);
     }
-
-// Ble LED indicates BLE connectivity:
-//- blinking 200 ms means BLE advertising
-#ifdef CONFIG_MCUMGR_SMP_BT
-    if (sIsSMPAdvertising)
-    {
-        sBleLED.Blink(30, 170);
-    }
-    else
-    {
-        sBleLED.Set(false);
-    }
-#else
-    sBleLED.Set(false);
-#endif
 #endif
 }
 
-void AppTask::ButtonEventHandler(uint32_t aButtonState, uint32_t aHasChanged)
+void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)
 {
-
     AppEvent buttonEvent;
-    buttonEvent.Type = AppEvent::kEventType_Button;
+    buttonEvent.Type = AppEventType::Button;
 
-    if (FUNCTION_BUTTON_MASK & aButtonState & aHasChanged)
+    if (FUNCTION_BUTTON_MASK & buttonState & hasChanged)
     {
         buttonEvent.ButtonEvent.PinNo  = FUNCTION_BUTTON;
-        buttonEvent.ButtonEvent.Action = AppEvent::kButtonPushEvent;
+        buttonEvent.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
         buttonEvent.Handler            = ButtonPushHandler;
-        sAppTask.PostEvent(&buttonEvent);
+        PostEvent(buttonEvent);
     }
-    else if (FUNCTION_BUTTON_MASK & aHasChanged)
+    else if (FUNCTION_BUTTON_MASK & hasChanged)
     {
         buttonEvent.ButtonEvent.PinNo  = FUNCTION_BUTTON;
-        buttonEvent.ButtonEvent.Action = AppEvent::kButtonReleaseEvent;
+        buttonEvent.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonReleased);
         buttonEvent.Handler            = ButtonReleaseHandler;
-        sAppTask.PostEvent(&buttonEvent);
+        PostEvent(buttonEvent);
     }
 
-    if (DIMMER_SWITCH_BUTTON_MASK & aButtonState & aHasChanged)
+#if NUMBER_OF_BUTTONS == 2
+    uint32_t buttonMask           = BLE_ADVERTISEMENT_START_AND_SWITCH_BUTTON_MASK;
+    buttonEvent.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_AND_SWITCH_BUTTON;
+#else
+    uint32_t buttonMask           = SWITCH_BUTTON_MASK;
+    buttonEvent.ButtonEvent.PinNo = SWITCH_BUTTON;
+#endif
+
+    if (buttonMask & buttonState & hasChanged)
     {
-        buttonEvent.ButtonEvent.PinNo  = DIMMER_SWITCH_BUTTON;
-        buttonEvent.ButtonEvent.Action = AppEvent::kButtonPushEvent;
+        buttonEvent.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
         buttonEvent.Handler            = ButtonPushHandler;
-        sAppTask.PostEvent(&buttonEvent);
+        PostEvent(buttonEvent);
     }
-    else if (DIMMER_SWITCH_BUTTON_MASK & aHasChanged)
+    else if (buttonMask & hasChanged)
     {
-        buttonEvent.ButtonEvent.PinNo  = DIMMER_SWITCH_BUTTON;
-        buttonEvent.ButtonEvent.Action = AppEvent::kButtonReleaseEvent;
+        buttonEvent.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonReleased);
         buttonEvent.Handler            = ButtonReleaseHandler;
-        sAppTask.PostEvent(&buttonEvent);
+        PostEvent(buttonEvent);
     }
 
-    if (GENERIC_SWITCH_BUTTON_MASK & aButtonState & aHasChanged)
-    {
-        buttonEvent.ButtonEvent.PinNo  = GENERIC_SWITCH_BUTTON;
-        buttonEvent.ButtonEvent.Action = AppEvent::kButtonPushEvent;
-        buttonEvent.Handler            = ButtonPushHandler;
-        sAppTask.PostEvent(&buttonEvent);
-    }
-    else if (GENERIC_SWITCH_BUTTON_MASK & aHasChanged)
-    {
-        buttonEvent.ButtonEvent.PinNo  = GENERIC_SWITCH_BUTTON;
-        buttonEvent.ButtonEvent.Action = AppEvent::kButtonReleaseEvent;
-        buttonEvent.Handler            = ButtonReleaseHandler;
-        sAppTask.PostEvent(&buttonEvent);
-    }
-
-    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & aHasChanged & aButtonState)
+#if NUMBER_OF_BUTTONS == 4
+    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & hasChanged & buttonState)
     {
         buttonEvent.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
-        buttonEvent.ButtonEvent.Action = AppEvent::kButtonPushEvent;
-        buttonEvent.Handler            = StartBLEAdvertisingHandler;
-        sAppTask.PostEvent(&buttonEvent);
+        buttonEvent.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
+        buttonEvent.Handler            = StartBLEAdvertisementHandler;
+        PostEvent(buttonEvent);
     }
+#endif
 }
 
-void AppTask::StartTimer(Timer aTimer, uint32_t aTimeoutMs)
+void AppTask::StartTimer(Timer timer, uint32_t timeoutMs)
 {
-    switch (aTimer)
+    switch (timer)
     {
     case Timer::Function:
-        k_timer_start(&sFunctionTimer, K_MSEC(aTimeoutMs), K_NO_WAIT);
+        k_timer_start(&sFunctionTimer, K_MSEC(timeoutMs), K_NO_WAIT);
         break;
     case Timer::DimmerTrigger:
-        k_timer_start(&sDimmerPressKeyTimer, K_MSEC(aTimeoutMs), K_NO_WAIT);
+        k_timer_start(&sDimmerPressKeyTimer, K_MSEC(timeoutMs), K_NO_WAIT);
         break;
     case Timer::Dimmer:
-        k_timer_start(&sDimmerTimer, K_MSEC(aTimeoutMs), K_MSEC(aTimeoutMs));
+        k_timer_start(&sDimmerTimer, K_MSEC(timeoutMs), K_MSEC(timeoutMs));
         break;
     default:
         break;
     }
 }
 
-void AppTask::CancelTimer(Timer aTimer)
+void AppTask::CancelTimer(Timer timer)
 {
-    switch (aTimer)
+    switch (timer)
     {
     case Timer::Function:
         k_timer_stop(&sFunctionTimer);
@@ -577,49 +595,54 @@
     }
 }
 
-void AppTask::UpdateLedStateEventHandler(AppEvent * aEvent)
+void AppTask::UpdateLedStateEventHandler(const AppEvent & event)
 {
-    if (aEvent->Type == AppEvent::kEventType_UpdateLedState)
+    if (event.Type == AppEventType::UpdateLedState)
     {
-        aEvent->UpdateLedStateEvent.LedWidget->UpdateState();
+        event.UpdateLedStateEvent.LedWidget->UpdateState();
     }
 }
 
 void AppTask::LEDStateUpdateHandler(LEDWidget & aLedWidget)
 {
     AppEvent event;
-    event.Type                          = AppEvent::kEventType_UpdateLedState;
+    event.Type                          = AppEventType::UpdateLedState;
     event.Handler                       = UpdateLedStateEventHandler;
     event.UpdateLedStateEvent.LedWidget = &aLedWidget;
-    sAppTask.PostEvent(&event);
+    PostEvent(event);
 }
 
-void AppTask::TimerEventHandler(k_timer * aTimer)
+void AppTask::FunctionTimerTimeoutCallback(k_timer * timer)
 {
+    if (!timer)
+    {
+        return;
+    }
+
     AppEvent event;
-    if (aTimer == &sFunctionTimer)
+    if (timer == &sFunctionTimer)
     {
-        event.Type                 = AppEvent::kEventType_Timer;
+        event.Type                 = AppEventType::Timer;
         event.TimerEvent.TimerType = (uint8_t) Timer::Function;
-        event.TimerEvent.Context   = k_timer_user_data_get(aTimer);
+        event.TimerEvent.Context   = k_timer_user_data_get(timer);
         event.Handler              = TimerEventHandler;
-        sAppTask.PostEvent(&event);
+        PostEvent(event);
     }
-    if (aTimer == &sDimmerPressKeyTimer)
+    if (timer == &sDimmerPressKeyTimer)
     {
-        event.Type                 = AppEvent::kEventType_Timer;
+        event.Type                 = AppEventType::Timer;
         event.TimerEvent.TimerType = (uint8_t) Timer::DimmerTrigger;
-        event.TimerEvent.Context   = k_timer_user_data_get(aTimer);
+        event.TimerEvent.Context   = k_timer_user_data_get(timer);
         event.Handler              = TimerEventHandler;
-        sAppTask.PostEvent(&event);
+        PostEvent(event);
     }
-    if (aTimer == &sDimmerTimer)
+    if (timer == &sDimmerTimer)
     {
-        event.Type                 = AppEvent::kEventType_Timer;
+        event.Type                 = AppEventType::Timer;
         event.TimerEvent.TimerType = (uint8_t) Timer::Dimmer;
-        event.TimerEvent.Context   = k_timer_user_data_get(aTimer);
+        event.TimerEvent.Context   = k_timer_user_data_get(timer);
         event.Handler              = TimerEventHandler;
-        sAppTask.PostEvent(&event);
+        PostEvent(event);
     }
 }
 
@@ -627,25 +650,25 @@
 void AppTask::RequestSMPAdvertisingStart(void)
 {
     AppEvent event;
-    event.Type    = AppEvent::kEventType_StartSMPAdvertising;
-    event.Handler = [](AppEvent *) { GetDFUOverSMP().StartBLEAdvertising(); };
-    sAppTask.PostEvent(&event);
+    event.Type    = AppEventType::StartSMPAdvertising;
+    event.Handler = [](const AppEvent &) { GetDFUOverSMP().StartBLEAdvertising(); };
+    PostEvent(event);
 }
 #endif
 
-void AppTask::PostEvent(AppEvent * aEvent)
+void AppTask::PostEvent(const AppEvent & event)
 {
-    if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT) != 0)
+    if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT) != 0)
     {
         LOG_INF("Failed to post event to app task event queue");
     }
 }
 
-void AppTask::DispatchEvent(AppEvent * aEvent)
+void AppTask::DispatchEvent(const AppEvent & event)
 {
-    if (aEvent->Handler)
+    if (event.Handler)
     {
-        aEvent->Handler(aEvent);
+        event.Handler(event);
     }
     else
     {
diff --git a/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp b/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp
index fd435cd..3dc8efe 100644
--- a/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp
+++ b/examples/light-switch-app/nrfconnect/main/BindingHandler.cpp
@@ -22,7 +22,7 @@
 #endif
 
 #include <zephyr/logging/log.h>
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace chip;
 using namespace chip::app;
@@ -209,7 +209,7 @@
             LevelControlProcessCommand(data->CommandId, binding, nullptr, context);
             break;
         default:
-            ChipLogError(NotSpecified, "Invalid binding group command data");
+            LOG_ERR("Invalid binding group command data");
             break;
         }
     }
@@ -224,7 +224,7 @@
             LevelControlProcessCommand(data->CommandId, binding, deviceProxy, context);
             break;
         default:
-            ChipLogError(NotSpecified, "Invalid binding unicast command data");
+            LOG_ERR("Invalid binding unicast command data");
             break;
         }
     }
diff --git a/examples/light-switch-app/nrfconnect/main/include/AppConfig.h b/examples/light-switch-app/nrfconnect/main/include/AppConfig.h
index 7e71ce1..4b94870 100644
--- a/examples/light-switch-app/nrfconnect/main/include/AppConfig.h
+++ b/examples/light-switch-app/nrfconnect/main/include/AppConfig.h
@@ -20,15 +20,24 @@
 
 // ---- Lighting Example App Config ----
 
+#include "BoardUtil.h"
+
 #define FUNCTION_BUTTON DK_BTN1
 #define FUNCTION_BUTTON_MASK DK_BTN1_MSK
-#define DIMMER_SWITCH_BUTTON DK_BTN2
-#define DIMMER_SWITCH_BUTTON_MASK DK_BTN2_MSK
-#define GENERIC_SWITCH_BUTTON DK_BTN3
-#define GENERIC_SWITCH_BUTTON_MASK DK_BTN3_MSK
+#if NUMBER_OF_BUTTONS == 2
+#define BLE_ADVERTISEMENT_START_AND_SWITCH_BUTTON DK_BTN2
+#define BLE_ADVERTISEMENT_START_AND_SWITCH_BUTTON_MASK DK_BTN2_MSK
+#else
+#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
+#endif
 
 #define SYSTEM_STATE_LED DK_LED1
-#define DFU_BLE_LED DK_LED2
-#define IDENTIFY_LED DK_LED3
+#define IDENTIFY_LED DK_LED2
+
+#if NUMBER_OF_LEDS == 4
+#define FACTORY_RESET_SIGNAL_LED DK_LED3
+#define FACTORY_RESET_SIGNAL_LED1 DK_LED4
+#endif
diff --git a/examples/light-switch-app/nrfconnect/main/include/AppEvent.h b/examples/light-switch-app/nrfconnect/main/include/AppEvent.h
index 4a2bd34..b3248e3 100644
--- a/examples/light-switch-app/nrfconnect/main/include/AppEvent.h
+++ b/examples/light-switch-app/nrfconnect/main/include/AppEvent.h
@@ -19,32 +19,32 @@
 #pragma once
 #include <cstdint>
 
-#include "LEDWidget.h"
+#include "EventTypes.h"
 
-struct AppEvent;
-typedef void (*EventHandler)(AppEvent *);
+class LEDWidget;
+
+enum class AppEventType : uint8_t
+{
+    None = 0,
+    Button,
+    ButtonPushed,
+    ButtonReleased,
+    Timer,
+    UpdateLedState,
+    IdentifyStart,
+    IdentifyStop,
+    StartSMPAdvertising
+};
+
+enum class FunctionEvent : uint8_t
+{
+    NoneSelected   = 0,
+    SoftwareUpdate = 0,
+    FactoryReset
+};
 
 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
@@ -63,5 +63,6 @@
         } UpdateLedStateEvent;
     };
 
+    AppEventType Type{ AppEventType::None };
     EventHandler Handler;
 };
diff --git a/examples/light-switch-app/nrfconnect/main/include/AppTask.h b/examples/light-switch-app/nrfconnect/main/include/AppTask.h
index 06f9e1d..6d46463 100644
--- a/examples/light-switch-app/nrfconnect/main/include/AppTask.h
+++ b/examples/light-switch-app/nrfconnect/main/include/AppTask.h
@@ -40,9 +40,16 @@
 class AppTask
 {
 public:
+    static AppTask & Instance()
+    {
+        static AppTask sAppTask;
+        return sAppTask;
+    };
+
     CHIP_ERROR StartApp();
-    void PostEvent(AppEvent *);
+
     void UpdateClusterState();
+
     static void IdentifyStartHandler(Identify *);
     static void IdentifyStopHandler(Identify *);
 
@@ -53,52 +60,38 @@
         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 PostEvent(const AppEvent & event);
+    static void DispatchEvent(const AppEvent & event);
+    static void ButtonPushHandler(const AppEvent & event);
+    static void ButtonReleaseHandler(const AppEvent & event);
+    static void TimerEventHandler(const AppEvent & event);
+    static void StartBLEAdvertisementHandler(const AppEvent & event);
+    static void UpdateLedStateEventHandler(const AppEvent & event);
 
-    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 ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+    static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged);
+    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
+    static void FunctionTimerTimeoutCallback(k_timer * timer);
     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
 
+    FunctionEvent mFunction = FunctionEvent::NoneSelected;
+
 #if CONFIG_CHIP_FACTORY_DATA
     chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
 #endif
 };
-
-inline AppTask & GetAppTask()
-{
-    return AppTask::sAppTask;
-}
diff --git a/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h b/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h
index ffd8d9b..f152bdb 100644
--- a/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h
+++ b/examples/light-switch-app/nrfconnect/main/include/CHIPProjectConfig.h
@@ -27,6 +27,7 @@
 
 #pragma once
 
+#define CHIP_CONFIG_CONTROLLER_MAX_ACTIVE_DEVICES 2
 /* 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
diff --git a/examples/light-switch-app/nrfconnect/main/main.cpp b/examples/light-switch-app/nrfconnect/main/main.cpp
index e463898..4e11474 100644
--- a/examples/light-switch-app/nrfconnect/main/main.cpp
+++ b/examples/light-switch-app/nrfconnect/main/main.cpp
@@ -20,13 +20,13 @@
 
 #include <zephyr/logging/log.h>
 
-LOG_MODULE_REGISTER(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip;
 
 int main()
 {
-    CHIP_ERROR err = GetAppTask().StartApp();
+    CHIP_ERROR err = AppTask::Instance().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/prj.conf b/examples/light-switch-app/nrfconnect/prj.conf
index 45e06e2..19f3cb2 100644
--- a/examples/light-switch-app/nrfconnect/prj.conf
+++ b/examples/light-switch-app/nrfconnect/prj.conf
@@ -14,31 +14,27 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults 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
-CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y
-
-# Bluetooth overrides
-CONFIG_BT_DEVICE_NAME="MatterSwitch"
-
-# Additional configs for debbugging experience.
-CONFIG_THREAD_NAME=y
-CONFIG_MPU_STACK_GUARD=y
-CONFIG_RESET_ON_FATAL_ERROR=n
-
-# CHIP configuration
+# Enable CHIP
+CONFIG_CHIP=y
 CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
 # 32772 == 0x8004 (example light-switch-app)
 CONFIG_CHIP_DEVICE_PRODUCT_ID=32772
+CONFIG_STD_CPP14=y
+
+# Add support for LEDs and buttons on Nordic development kits
+CONFIG_DK_LIBRARY=y
+
+# General networking settings
+CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=14
+
+# Bluetooth Low Energy configuration
+CONFIG_BT_DEVICE_NAME="MatterSwitch"
+
+# Other settings
+CONFIG_THREAD_NAME=y
+CONFIG_MPU_STACK_GUARD=y
+CONFIG_RESET_ON_FATAL_ERROR=n
diff --git a/examples/light-switch-app/nrfconnect/prj_no_dfu.conf b/examples/light-switch-app/nrfconnect/prj_no_dfu.conf
index fe1305f..27475ce 100644
--- a/examples/light-switch-app/nrfconnect/prj_no_dfu.conf
+++ b/examples/light-switch-app/nrfconnect/prj_no_dfu.conf
@@ -14,26 +14,27 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32772 == 0x8004 (example light-switch-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32772
+CONFIG_STD_CPP14=y
+
 # 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
-CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y
+# General networking settings
+CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=14
 
-# Bluetooth overrides
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterSwitch"
 
-# Additional configs for debbugging experience.
+# Other settings
 CONFIG_THREAD_NAME=y
 CONFIG_MPU_STACK_GUARD=y
 CONFIG_RESET_ON_FATAL_ERROR=n
@@ -41,7 +42,5 @@
 # Disable Matter OTA DFU
 CONFIG_CHIP_OTA_REQUESTOR=n
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32772 == 0x8004 (example light-switch-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32772
+# Disable QSPI NOR
+CONFIG_CHIP_QSPI_NOR=n
diff --git a/examples/light-switch-app/nrfconnect/prj_release.conf b/examples/light-switch-app/nrfconnect/prj_release.conf
index b9ff24a..a55449c 100644
--- a/examples/light-switch-app/nrfconnect/prj_release.conf
+++ b/examples/light-switch-app/nrfconnect/prj_release.conf
@@ -14,33 +14,29 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32772 == 0x8004 (example light-switch-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32772
+CONFIG_STD_CPP14=y
+
 # 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
-CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y
+# General networking settings
+CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=14
 
-# Bluetooth overrides
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterSwitch"
 
 # Enable system reset on fatal error
 CONFIG_RESET_ON_FATAL_ERROR=y
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32772 == 0x8004 (example light-switch-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32772
-
 # Suspend devices when the CPU goes into sleep
 CONFIG_PM_DEVICE=y
 
@@ -52,7 +48,8 @@
 CONFIG_SERIAL=n
 CONFIG_LOG=n
 CONFIG_LOG_MODE_MINIMAL=n
-CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_ASSERT_VERBOSE=n
+CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_PRINTK=n
+CONFIG_PRINTK_SYNC=n
 CONFIG_THREAD_NAME=n
diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt
index 02ee050..81e2bd7 100644
--- a/examples/lighting-app/nrfconnect/CMakeLists.txt
+++ b/examples/lighting-app/nrfconnect/CMakeLists.txt
@@ -25,6 +25,7 @@
 # Set Kconfig root files that will be processed as a first Kconfig for used child images.
 set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root)
 set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root)
+set(hci_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.root)
 
 if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf" AND NOT BOARD STREQUAL "nrf52840dongle_nrf52840")
     set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml)
diff --git a/examples/lighting-app/nrfconnect/Kconfig b/examples/lighting-app/nrfconnect/Kconfig
index 94a99f9..6a35f3b 100644
--- a/examples/lighting-app/nrfconnect/Kconfig
+++ b/examples/lighting-app/nrfconnect/Kconfig
@@ -15,6 +15,20 @@
 #
 mainmenu "Matter nRF Connect Lighting Example Application"
 
+# Sample configuration used for Thread networking
+if NET_L2_OPENTHREAD
+
+choice OPENTHREAD_NORDIC_LIBRARY_CONFIGURATION
+	default OPENTHREAD_NORDIC_LIBRARY_FTD
+endchoice
+
+choice OPENTHREAD_DEVICE_TYPE
+	default OPENTHREAD_FTD
+endchoice
+
+endif # NET_L2_OPENTHREAD
+
+
 rsource "../../../config/nrfconnect/chip-module/Kconfig.features"
 rsource "../../../config/nrfconnect/chip-module/Kconfig.defaults"
 source "Kconfig.zephyr"
diff --git a/examples/lighting-app/nrfconnect/README.md b/examples/lighting-app/nrfconnect/README.md
index 0c25aba..29f15ea 100644
--- a/examples/lighting-app/nrfconnect/README.md
+++ b/examples/lighting-app/nrfconnect/README.md
@@ -10,12 +10,15 @@
 
 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 over a low-power, 802.15.4 Thread network.
+Semiconductor's nRF Connect SDK, and was created to facilitate testing and
+certification of a Matter device communicating over a low-power, 802.15.4 Thread
+network, or Wi-Fi 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. The
-device works as a Thread Router.
+into an existing Matter network and can be controlled by this network. In the
+case of Thread, this device works as a Thread Sleepy End Device. Support for
+both Thread and Wi-Fi is mutually exclusive and depends on the hardware
+platform, so only one protocol can be supported for a specific light device.
 
 <hr>
 
@@ -25,6 +28,7 @@
     -   [Device Firmware Upgrade](#device-firmware-upgrade)
 -   [Requirements](#requirements)
     -   [Supported devices](#supported_devices)
+    -   [IPv6 network support](#ipv6-network-support)
 -   [Device UI](#device-ui)
 -   [Setting up the environment](#setting-up-the-environment)
     -   [Using Docker container for setup](#using-docker-container-for-setup)
@@ -58,21 +62,37 @@
 [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md)
 to read more about the platform structure and dependencies.
 
-The Matter device that runs the lighting 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.
+By default, the Matter accessory device has IPv6 networking disabled. You must
+pair it with the Matter controller over Bluetooth® LE to get the configuration
+from the controller to use the device within a Thread or Wi-Fi network. The
+device starts advertising automatically and you can commission the device within
+15 minutes. If the advertising time elapsed you can re-enable it using buttons.
+See [Bluetooth LE advertising](#bluetooth-le-advertising) to learn how to do
+this. The controller must get the commissioning information from the Matter
+accessory device and provision the device into the network.
 
-The example can be configured to use the secure bootloader and utilize it for
-performing over-the-air Device Firmware Upgrade using Bluetooth LE.
+You can test this application remotely over the Thread or the Wi-Fi protocol,
+which in either case requires more devices, including a Matter controller that
+you can configure either on a PC or a mobile device.
+
+The sample uses buttons for changing LED states to show the state of these
+changes. You can test it in the following ways:
+
+-   Standalone, using a single DK that runs the lighting application.
+
+-   Remotely over the Thread or the Wi-Fi protocol, which in either case
+    requires more devices, including a Matter controller that you can configure
+    either on a PC or a mobile device.
 
 ### Bluetooth LE advertising
 
-To commission the device onto a Matter network, the device must be discoverable
-over Bluetooth LE that starts automatically upon the device startup, but only
-for a predefined period of time (15 minutes by default). If the Bluetooth LE
-advertising times out, you can re-enable it manually using **Button 4**.
+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:
+
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: **Button 4**.
+
+-   On nRF7002 DK: **Button 2**.
 
 ### Bluetooth LE rendezvous
 
@@ -82,16 +102,16 @@
 
 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.
+the UART console, and shared using an NFC tag. The emulation of the NFC tag
+emulation starts automatically when Bluetooth LE advertising is started and
+stays enabled until Bluetooth LE advertising timeout expires.
 
-#### Thread provisioning
+#### Thread or Wi-Fi 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, device is able to join the Thread network and communicate
-with other Thread devices in the network.
+The provisioning operation, which is the Last part of the rendezvous procedure,
+involves sending the Thread or Wi-Fi network credentials from the Matter
+controller to the Matter device. As a result, the device joins the Thread or
+Wi-Fi network and can communicate with other devices in the network.
 
 ### Device Firmware Upgrade
 
@@ -166,14 +186,24 @@
 
 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`      | <details><summary>nRF52840 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_DK_info-medium.jpg" alt="nRF52840 DK"/></details>        |
-| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK)           | `nrf5340dk_nrf5340_cpuapp` | <details><summary>nRF5340 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF5340_DK_info-medium.jpg" alt="nRF5340 DK"/></details>           |
-| [nRF52840 Dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) | `nrf52840dongle_nrf52840`  | <details><summary>nRF52840 Dongle</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_Dongle-medium.jpg" alt="nRF52840 Dongle"/></details> |
+| Hardware platform                                                                                               | Build target               | Platform image                                                                                                                                          |
+| --------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)                       | `nrf52840dk_nrf52840`      | <details><summary>nRF52840 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_DK_info-medium.jpg" alt="nRF52840 DK"/></details>        |
+| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK)                         | `nrf5340dk_nrf5340_cpuapp` | <details><summary>nRF5340 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF5340_DK_info-medium.jpg" alt="nRF5340 DK"/></details>           |
+| [nRF52840 Dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle)               | `nrf52840dongle_nrf52840`  | <details><summary>nRF52840 Dongle</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_Dongle-medium.jpg" alt="nRF52840 Dongle"/></details> |
+| [nRF7002 DK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf7002.html#nrf7002dk-nrf5340) | `nrf7002dk_nrf5340_cpuapp` | <details><summary>nRF7002DK</summary><img src="../../platform/nrfconnect/doc/images/nrf7002dk.jpg" alt="nRF7002 DK"/></details>                         |
 
 <hr>
 
+### IPv6 network support
+
+The development kits for this sample offer the following IPv6 network support
+for Matter:
+
+-   Matter over Thread is supported for `nrf52840dk_nrf52840` and
+    `nrf5340dk_nrf5340_cpuapp`.
+-   Matter over Wi-Fi is supported for `nrf7002dk_nrf5340_cpuapp`.
+
 <a name="device-ui"></a>
 
 ## Device UI
@@ -203,11 +233,10 @@
     Bluetooth LE.
 
 -   _Short Flash Off (950ms on/50ms off)_ &mdash; The device is fully
-    provisioned, but does not yet have full Thread network or service
-    connectivity.
+    provisioned, but does not yet have full connectivity for Thread or Wi-Fi
+    network.
 
--   _Solid On_ &mdash; The device is fully provisioned and has full Thread
-    network and service connectivity.
+-   _Solid On_ &mdash; The device is fully provisioned.
 
 **LED 2** simulates the light bulb and shows the state of the lighting. The
 following states are possible:
@@ -216,30 +245,46 @@
 
 -   _Off_ &mdash; The light bulb is off.
 
-**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.
+    Additionally, the LED starts blinking evenly (500 ms on/500 ms off) when the
+    Identify command of the Identify cluster is received on the endpoint 1. The
+    command’s argument can be used to specify the duration of the effect.
 
 **Button 1** can be used for the following purposes:
 
--   _Pressed for 6 s_ &mdash; Initiates the factory reset of the device.
-    Releasing the button within the 6-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_ &mdash; Initiates the OTA software update over
-    Bluetooth LE process. This feature is disabled by default, but can be
-    enabled by following the
+-   _Pressed for less than 3 s_ &mdash; 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.
+    instructions.
+
+-   _Pressed for more than 3 s_ &mdash; initiates the factory reset of the
+    device. Releasing the button within the 3-second window cancels the factory
+    reset procedure.
 
 **Button 2** &mdash; Pressing the button once changes the lighting state to the
 opposite one.
 
-**Button 4** &mdash; Pressing the button once starts the NFC tag emulation and
-enables Bluetooth LE advertising for the predefined period of time (15 minutes
-by default).
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: Changes the LED state to the
+    opposite one.
+
+-   On nRF7002 DK:
+
+    -   If pressed for less than three seconds, it changes the LED state to the
+        opposite one.
+
+    -   If pressed for more than three seconds, it starts the NFC tag emulation,
+        enables Bluetooth LE advertising for the predefined period of time (15
+        minutes by default), and makes the device discoverable over Bluetooth
+        LE.
+
+**Button 4** :
+
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: Starts the NFC tag emulation,
+    enables Bluetooth LE advertising for the predefined period of time (15
+    minutes by default), and makes the device discoverable over Bluetooth LE.
+    This button is used during the commissioning procedure.
+
+-   On nRF7002 DK: Not available.
 
 **SEGGER J-Link USB port** can be used to get logs from the device or
 communicate with it using the
diff --git a/examples/lighting-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/lighting-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay
new file mode 100644
index 0000000..481ff46
--- /dev/null
+++ b/examples/lighting-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay
@@ -0,0 +1,61 @@
+/*
+ *    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;
+	};
+
+	/*
+	* By default, PWM module is only configured for led0 (LED1 on the board).
+	* The light bulb app, however, uses LED2 to show the state of the lighting,
+	* including its brightness level.
+	*/
+	aliases {
+		pwm-led1 = &pwm_led1;
+	};
+
+	pwmleds {
+		compatible = "pwm-leds";
+		pwm_led1: pwm_led_1 {
+			pwms = < &pwm0 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
+		};
+	};
+};
+
+&pwm0 {
+	pinctrl-0 = <&pwm0_default_alt>;
+	pinctrl-1 = <&pwm0_sleep_alt>;
+	pinctrl-names = "default", "sleep";
+};
+
+&pinctrl {
+	pwm0_default_alt: pwm0_default_alt {
+		group1 {
+			psels = <NRF_PSEL(PWM_OUT1, 1, 7)>;
+			nordic,invert;
+		};
+	};
+
+	pwm0_sleep_alt: pwm0_sleep_alt {
+		group1 {
+			psels = <NRF_PSEL(PWM_OUT1, 1, 7)>;
+			low-power-enable;
+		};
+	};
+
+};
diff --git a/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj.conf b/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf b/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf b/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/lighting-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/lighting-app/nrfconnect/child_image/mcuboot/prj.conf
index 287c782..0dbf710 100644
--- a/examples/lighting-app/nrfconnect/child_image/mcuboot/prj.conf
+++ b/examples/lighting-app/nrfconnect/child_image/mcuboot/prj.conf
@@ -23,7 +23,6 @@
 # Bootloader size optimization
 # Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding
 # in board files.
-CONFIG_GPIO=n
 CONFIG_CONSOLE=n
 CONFIG_SERIAL=n
 CONFIG_UART_CONSOLE=n
diff --git a/examples/lighting-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/lighting-app/nrfconnect/child_image/mcuboot/prj_release.conf
index 287c782..0dbf710 100644
--- a/examples/lighting-app/nrfconnect/child_image/mcuboot/prj_release.conf
+++ b/examples/lighting-app/nrfconnect/child_image/mcuboot/prj_release.conf
@@ -23,7 +23,6 @@
 # Bootloader size optimization
 # Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding
 # in board files.
-CONFIG_GPIO=n
 CONFIG_CONSOLE=n
 CONFIG_SERIAL=n
 CONFIG_UART_CONSOLE=n
diff --git a/examples/lighting-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/lighting-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml
new file mode 100644
index 0000000..3c56dc0
--- /dev/null
+++ b/examples/lighting-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -0,0 +1,56 @@
+mcuboot:
+    address: 0x0
+    size: 0xC000
+    region: flash_primary
+mcuboot_pad:
+    address: 0xC000
+    size: 0x200
+app:
+    address: 0xC200
+    size: 0xeee00
+mcuboot_primary:
+    orig_span: &id001
+        - mcuboot_pad
+        - app
+    span: *id001
+    address: 0xC000
+    size: 0xef000
+    region: flash_primary
+mcuboot_primary_app:
+    orig_span: &id002
+        - app
+    span: *id002
+    address: 0xC200
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
+settings_storage:
+    address: 0xfc000
+    size: 0x4000
+    region: flash_primary
+mcuboot_primary_1:
+    address: 0x0
+    size: 0x40000
+    device: flash_ctrl
+    region: ram_flash
+mcuboot_secondary:
+    address: 0x0
+    size: 0xef000
+    device: MX25R64
+    region: external_flash
+mcuboot_secondary_1:
+    address: 0xef000
+    size: 0x40000
+    device: MX25R64
+    region: external_flash
+external_flash:
+    address: 0x12f000
+    size: 0x6D1000
+    device: MX25R64
+    region: external_flash
+pcd_sram:
+    address: 0x20000000
+    size: 0x2000
+    region: sram_primary
diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp
index 1ee7586..15ab885 100644
--- a/examples/lighting-app/nrfconnect/main/AppTask.cpp
+++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp
@@ -20,7 +20,7 @@
 
 #include "AppConfig.h"
 #include "AppEvent.h"
-#include "LEDWidget.h"
+#include "LEDUtil.h"
 #include "PWMDevice.h"
 
 #include <DeviceInfoProviderImpl.h>
@@ -41,6 +41,11 @@
 #include <lib/support/ErrorStr.h>
 #include <system/SystemClock.h>
 
+#ifdef CONFIG_CHIP_WIFI
+#include <app/clusters/network-commissioning/network-commissioning.h>
+#include <platform/nrfconnect/wifi/NrfWiFiDriver.h>
+#endif
+
 #if CONFIG_CHIP_OTA_REQUESTOR
 #include "OTAUtil.h"
 #endif
@@ -49,7 +54,7 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip;
 using namespace ::chip::app;
@@ -61,12 +66,12 @@
 constexpr int kFactoryResetTriggerTimeout      = 3000;
 constexpr int kFactoryResetCancelWindowTimeout = 3000;
 constexpr int kAppEventQueueSize               = 10;
-constexpr uint8_t kButtonPushEvent             = 1;
-constexpr uint8_t kButtonReleaseEvent          = 0;
 constexpr EndpointId kLightEndpointId          = 1;
-constexpr uint32_t kIdentifyBlinkRateMs        = 500;
 constexpr uint8_t kDefaultMinLevel             = 0;
 constexpr uint8_t kDefaultMaxLevel             = 254;
+#if NUMBER_OF_BUTTONS == 2
+constexpr uint32_t kAdvertisingTriggerTimeout = 3000;
+#endif
 
 // NOTE! This key is for test/certification only and should not be available in production devices!
 // If CONFIG_CHIP_FACTORY_DATA is enabled, this value is read from the factory data.
@@ -81,12 +86,15 @@
 
 LEDWidget sStatusLED;
 LEDWidget sIdentifyLED;
-LEDWidget sUnusedLED;
+#if NUMBER_OF_LEDS == 4
+FactoryResetLEDsWrapper<2> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTORY_RESET_SIGNAL_LED1 } };
+#endif
+
+bool sIsNetworkProvisioned = false;
+bool sIsNetworkEnabled     = false;
+bool sHaveBLEConnections   = false;
 
 const struct pwm_dt_spec sLightPwmDevice = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led1));
-bool sIsThreadProvisioned                = false;
-bool sIsThreadEnabled                    = false;
-bool sHaveBLEConnections                 = false;
 
 chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
 
@@ -103,7 +111,26 @@
 
 } // namespace
 
-AppTask AppTask::sAppTask;
+namespace LedConsts {
+constexpr uint32_t kBlinkRate_ms{ 500 };
+constexpr uint32_t kIdentifyBlinkRate_ms{ 500 };
+
+namespace StatusLed {
+namespace Unprovisioned {
+constexpr uint32_t kOn_ms{ 100 };
+constexpr uint32_t kOff_ms{ kOn_ms };
+} /* namespace Unprovisioned */
+namespace Provisioned {
+constexpr uint32_t kOn_ms{ 50 };
+constexpr uint32_t kOff_ms{ 950 };
+} /* namespace Provisioned */
+
+} /* namespace StatusLed */
+} /* namespace LedConsts */
+
+#ifdef CONFIG_CHIP_WIFI
+app::Clusters::NetworkCommissioning::Instance sWiFiCommissioningInstance(0, &(NetworkCommissioning::NrfWiFiDriver::Instance()));
+#endif
 
 CHIP_ERROR AppTask::Init()
 {
@@ -139,20 +166,40 @@
         LOG_ERR("ConnectivityMgr().SetThreadDeviceType() failed");
         return err;
     }
-#elif !defined(CONFIG_WIFI_NRF700X)
+#elif defined(CONFIG_CHIP_WIFI)
+    sWiFiCommissioningInstance.Init();
+#else
     return CHIP_ERROR_INTERNAL;
-#endif
+#endif // CONFIG_NET_L2_OPENTHREAD
 
     // Initialize LEDs
     LEDWidget::InitGpio();
     LEDWidget::SetStateUpdateCallback(LEDStateUpdateHandler);
 
     sStatusLED.Init(SYSTEM_STATE_LED);
-    sIdentifyLED.Init(DK_LED3);
-    sUnusedLED.Init(DK_LED4);
+    sIdentifyLED.Init(LIGHTING_STATE_LED);
+    sIdentifyLED.Set(false);
 
     UpdateStatusLED();
 
+    // Initialize buttons
+    int ret = dk_buttons_init(ButtonEventHandler);
+    if (ret)
+    {
+        LOG_ERR("dk_buttons_init() failed");
+        return chip::System::MapErrorZephyr(ret);
+    }
+
+    // Initialize function button timer
+    k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr);
+    k_timer_user_data_set(&sFunctionTimer, this);
+
+#ifdef CONFIG_MCUMGR_SMP_BT
+    // Initialize DFU over SMP
+    GetDFUOverSMP().Init(RequestSMPAdvertisingStart);
+    GetDFUOverSMP().ConfirmNewImage();
+#endif
+
     // Initialize lighting device (PWM)
     uint8_t minLightLevel = kDefaultMinLevel;
     Clusters::LevelControl::Attributes::MinLevel::Get(kLightEndpointId, &minLightLevel);
@@ -160,31 +207,13 @@
     uint8_t maxLightLevel = kDefaultMaxLevel;
     Clusters::LevelControl::Attributes::MaxLevel::Get(kLightEndpointId, &maxLightLevel);
 
-    int ret = mPWMDevice.Init(&sLightPwmDevice, minLightLevel, maxLightLevel, maxLightLevel);
+    ret = mPWMDevice.Init(&sLightPwmDevice, minLightLevel, maxLightLevel, maxLightLevel);
     if (ret != 0)
     {
         return chip::System::MapErrorZephyr(ret);
     }
     mPWMDevice.SetCallbacks(ActionInitiated, ActionCompleted);
 
-    // Initialize buttons
-    ret = dk_buttons_init(ButtonEventHandler);
-    if (ret)
-    {
-        LOG_ERR("dk_buttons_init() failed");
-        return chip::System::MapErrorZephyr(ret);
-    }
-
-    // Initialize function button timer
-    k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr);
-    k_timer_user_data_set(&sFunctionTimer, this);
-
-#ifdef CONFIG_MCUMGR_SMP_BT
-    // Initialize DFU over SMP
-    GetDFUOverSMP().Init(RequestSMPAdvertisingStart);
-    GetDFUOverSMP().ConfirmNewImage();
-#endif
-
     // Initialize CHIP server
 #if CONFIG_CHIP_FACTORY_DATA
     ReturnErrorOnFailure(mFactoryDataProvider.Init());
@@ -239,132 +268,195 @@
     while (true)
     {
         k_msgq_get(&sAppEventQueue, &event, K_FOREVER);
-        DispatchEvent(&event);
+        DispatchEvent(event);
     }
 
     return CHIP_NO_ERROR;
 }
 
-void AppTask::LightingActionEventHandler(AppEvent * aEvent)
-{
-    PWMDevice::Action_t action = PWMDevice::INVALID_ACTION;
-    int32_t actor              = 0;
-
-    if (aEvent->Type == AppEvent::kEventType_Lighting)
-    {
-        action = static_cast<PWMDevice::Action_t>(aEvent->LightingEvent.Action);
-        actor  = aEvent->LightingEvent.Actor;
-    }
-    else if (aEvent->Type == AppEvent::kEventType_Button)
-    {
-        action = GetAppTask().mPWMDevice.IsTurnedOn() ? PWMDevice::OFF_ACTION : PWMDevice::ON_ACTION;
-        actor  = AppEvent::kEventType_Button;
-    }
-
-    if (action != PWMDevice::INVALID_ACTION && GetAppTask().mPWMDevice.InitiateAction(action, actor, NULL))
-        LOG_INF("Action is already in progress or active.");
-}
-
-void AppTask::ButtonEventHandler(uint32_t button_state, uint32_t has_changed)
-{
-    AppEvent button_event;
-    button_event.Type = AppEvent::kEventType_Button;
-
-    if (LIGHTING_BUTTON_MASK & button_state & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = LIGHTING_BUTTON;
-        button_event.ButtonEvent.Action = kButtonPushEvent;
-        button_event.Handler            = LightingActionEventHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-
-    if (FUNCTION_BUTTON_MASK & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = FUNCTION_BUTTON;
-        button_event.ButtonEvent.Action = (FUNCTION_BUTTON_MASK & button_state) ? kButtonPushEvent : kButtonReleaseEvent;
-        button_event.Handler            = FunctionHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-
-    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & button_state & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
-        button_event.ButtonEvent.Action = kButtonPushEvent;
-        button_event.Handler            = StartBLEAdvertisementHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-}
-
-void AppTask::TimerEventHandler(k_timer * timer)
-{
-    AppEvent event;
-    event.Type               = AppEvent::kEventType_Timer;
-    event.TimerEvent.Context = k_timer_user_data_get(timer);
-    event.Handler            = FunctionTimerEventHandler;
-    sAppTask.PostEvent(&event);
-}
-
 void AppTask::IdentifyStartHandler(Identify *)
 {
     AppEvent event;
-    event.Type    = AppEvent::kEventType_IdentifyStart;
-    event.Handler = [](AppEvent *) { sIdentifyLED.Blink(kIdentifyBlinkRateMs); };
-    sAppTask.PostEvent(&event);
+    event.Type    = AppEventType::IdentifyStart;
+    event.Handler = [](const AppEvent &) {
+        Instance().mPWMDevice.SuppressOutput();
+        sIdentifyLED.Blink(LedConsts::kIdentifyBlinkRate_ms);
+    };
+    PostEvent(event);
 }
 
 void AppTask::IdentifyStopHandler(Identify *)
 {
     AppEvent event;
-    event.Type    = AppEvent::kEventType_IdentifyStop;
-    event.Handler = [](AppEvent *) { sIdentifyLED.Set(false); };
-    sAppTask.PostEvent(&event);
+    event.Type    = AppEventType::IdentifyStop;
+    event.Handler = [](const AppEvent &) {
+        sIdentifyLED.Set(false);
+        Instance().mPWMDevice.ApplyLevel();
+    };
+    PostEvent(event);
 }
 
-void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
+#if NUMBER_OF_BUTTONS == 2
+void AppTask::StartBLEAdvertisementAndLightActionEventHandler(const AppEvent & event)
 {
-    if (aEvent->Type != AppEvent::kEventType_Timer)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
+    {
+        Instance().StartTimer(kAdvertisingTriggerTimeout);
+        Instance().mFunction = FunctionEvent::AdvertisingStart;
+    }
+    else
+    {
+        if (Instance().mFunction == FunctionEvent::AdvertisingStart && Instance().mFunctionTimerActive)
+        {
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
+
+            AppEvent button_event;
+            button_event.Type               = AppEventType::Button;
+            button_event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_AND_LIGHTING_BUTTON;
+            button_event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonReleased);
+            button_event.Handler            = LightingActionEventHandler;
+            PostEvent(button_event);
+        }
+    }
+}
+#endif
+
+void AppTask::LightingActionEventHandler(const AppEvent & event)
+{
+    PWMDevice::Action_t action = PWMDevice::INVALID_ACTION;
+    int32_t actor              = 0;
+
+    if (event.Type == AppEventType::Lighting)
+    {
+        action = static_cast<PWMDevice::Action_t>(event.LightingEvent.Action);
+        actor  = event.LightingEvent.Actor;
+    }
+    else if (event.Type == AppEventType::Button)
+    {
+        action = Instance().mPWMDevice.IsTurnedOn() ? PWMDevice::OFF_ACTION : PWMDevice::ON_ACTION;
+        actor  = static_cast<int32_t>(AppEventType::Button);
+    }
+
+    if (action != PWMDevice::INVALID_ACTION && Instance().mPWMDevice.InitiateAction(action, actor, NULL))
+    {
+        LOG_INF("Action is already in progress or active.");
+    }
+}
+
+void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)
+{
+    AppEvent button_event;
+    button_event.Type = AppEventType::Button;
+
+#if NUMBER_OF_BUTTONS == 2
+    if (BLE_ADVERTISEMENT_START_AND_LIGHTING_BUTTON_MASK & hasChanged)
+    {
+        button_event.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_AND_LIGHTING_BUTTON;
+        button_event.ButtonEvent.Action =
+            static_cast<uint8_t>((BLE_ADVERTISEMENT_START_AND_LIGHTING_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed
+                                                                                                  : AppEventType::ButtonReleased);
+        button_event.Handler = StartBLEAdvertisementAndLightActionEventHandler;
+        PostEvent(button_event);
+    }
+#else
+    if (LIGHTING_BUTTON_MASK & buttonState & hasChanged)
+    {
+        button_event.ButtonEvent.PinNo  = LIGHTING_BUTTON;
+        button_event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
+        button_event.Handler            = LightingActionEventHandler;
+        PostEvent(button_event);
+    }
+
+    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged)
+    {
+        button_event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
+        button_event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
+        button_event.Handler            = StartBLEAdvertisementHandler;
+        PostEvent(button_event);
+    }
+#endif
+
+    if (FUNCTION_BUTTON_MASK & hasChanged)
+    {
+        button_event.ButtonEvent.PinNo = FUNCTION_BUTTON;
+        button_event.ButtonEvent.Action =
+            static_cast<uint8_t>((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased);
+        button_event.Handler = FunctionHandler;
+        PostEvent(button_event);
+    }
+}
+
+void AppTask::FunctionTimerTimeoutCallback(k_timer * timer)
+{
+    if (!timer)
+    {
         return;
+    }
+
+    AppEvent event;
+    event.Type               = AppEventType::Timer;
+    event.TimerEvent.Context = k_timer_user_data_get(timer);
+    event.Handler            = FunctionTimerEventHandler;
+    PostEvent(event);
+}
+
+void AppTask::FunctionTimerEventHandler(const AppEvent & event)
+{
+    if (event.Type != AppEventType::Timer)
+    {
+        return;
+    }
 
     // If we reached here, the button was held past kFactoryResetTriggerTimeout, initiate factory reset
-    if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+    if (Instance().mFunction == FunctionEvent::SoftwareUpdate)
     {
         LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", kFactoryResetTriggerTimeout);
 
         // Start timer for kFactoryResetCancelWindowTimeout to allow user to cancel, if required.
-        sAppTask.StartTimer(kFactoryResetCancelWindowTimeout);
-        sAppTask.mFunction = kFunction_FactoryReset;
+        Instance().StartTimer(kFactoryResetCancelWindowTimeout);
+        Instance().mFunction = FunctionEvent::FactoryReset;
 
         // Turn off all LEDs before starting blink to make sure blink is co-ordinated.
         sStatusLED.Set(false);
-        sIdentifyLED.Set(false);
-        sUnusedLED.Set(false);
+#if NUMBER_OF_LEDS == 4
+        sFactoryResetLEDs.Set(false);
+#endif
 
-        sStatusLED.Blink(500);
-        sIdentifyLED.Blink(500);
-        sUnusedLED.Blink(500);
+        sStatusLED.Blink(LedConsts::kBlinkRate_ms);
+#if NUMBER_OF_LEDS == 4
+        sFactoryResetLEDs.Blink(LedConsts::kBlinkRate_ms);
+#endif
     }
-    else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+    else if (Instance().mFunction == FunctionEvent::FactoryReset)
     {
         // Actually trigger Factory Reset
-        sAppTask.mFunction = kFunction_NoneSelected;
-
+        Instance().mFunction = FunctionEvent::NoneSelected;
         chip::Server::GetInstance().ScheduleFactoryReset();
     }
+    else if (Instance().mFunction == FunctionEvent::AdvertisingStart)
+    {
+        // The button was held past kAdvertisingTriggerTimeout, start BLE advertisement if we have 2 buttons UI
+#if NUMBER_OF_BUTTONS == 2
+        StartBLEAdvertisementHandler(event);
+        Instance().mFunction = FunctionEvent::NoneSelected;
+#endif
+    }
 }
 
 #ifdef CONFIG_MCUMGR_SMP_BT
 void AppTask::RequestSMPAdvertisingStart(void)
 {
     AppEvent event;
-    event.Type    = AppEvent::kEventType_StartSMPAdvertising;
-    event.Handler = [](AppEvent *) { GetDFUOverSMP().StartBLEAdvertising(); };
-    sAppTask.PostEvent(&event);
+    event.Type    = AppEventType::StartSMPAdvertising;
+    event.Handler = [](const AppEvent &) { GetDFUOverSMP().StartBLEAdvertising(); };
+    PostEvent(event);
 }
 #endif
 
-void AppTask::FunctionHandler(AppEvent * aEvent)
+void AppTask::FunctionHandler(const AppEvent & event)
 {
-    if (aEvent->ButtonEvent.PinNo != FUNCTION_BUTTON)
+    if (event.ButtonEvent.PinNo != FUNCTION_BUTTON)
         return;
 
     // To trigger software update: press the FUNCTION_BUTTON button briefly (< kFactoryResetTriggerTimeout)
@@ -372,22 +464,21 @@
     // All LEDs start blinking after kFactoryResetTriggerTimeout to signal factory reset has been initiated.
     // To cancel factory reset: release the FUNCTION_BUTTON once all LEDs start blinking within the
     // kFactoryResetCancelWindowTimeout
-    if (aEvent->ButtonEvent.Action == kButtonPushEvent)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
     {
-        if (!sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_NoneSelected)
+        if (!Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::NoneSelected)
         {
-            sAppTask.StartTimer(kFactoryResetTriggerTimeout);
-
-            sAppTask.mFunction = kFunction_SoftwareUpdate;
+            Instance().StartTimer(kFactoryResetTriggerTimeout);
+            Instance().mFunction = FunctionEvent::SoftwareUpdate;
         }
     }
     else
     {
         // If the button was released before factory reset got initiated, trigger a software update.
-        if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+        if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
         {
-            sAppTask.CancelTimer();
-            sAppTask.mFunction = kFunction_NoneSelected;
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
 
 #ifdef CONFIG_MCUMGR_SMP_BT
             GetDFUOverSMP().StartServer();
@@ -395,19 +486,20 @@
             LOG_INF("Software update is disabled");
 #endif
         }
-        else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+        else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
         {
-            sIdentifyLED.Set(false);
-            sUnusedLED.Set(false);
+#if NUMBER_OF_LEDS == 4
+            sFactoryResetLEDs.Set(false);
+#endif
             UpdateStatusLED();
-            sAppTask.CancelTimer();
-            sAppTask.mFunction = kFunction_NoneSelected;
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
             LOG_INF("Factory Reset has been Canceled");
         }
     }
 }
 
-void AppTask::StartBLEAdvertisementHandler(AppEvent *)
+void AppTask::StartBLEAdvertisementHandler(const AppEvent &)
 {
     if (Server::GetInstance().GetFabricTable().FabricCount() != 0)
     {
@@ -427,44 +519,44 @@
     }
 }
 
-void AppTask::UpdateLedStateEventHandler(AppEvent * aEvent)
+void AppTask::UpdateLedStateEventHandler(const AppEvent & event)
 {
-    if (aEvent->Type == AppEvent::kEventType_UpdateLedState)
+    if (event.Type == AppEventType::UpdateLedState)
     {
-        aEvent->UpdateLedStateEvent.LedWidget->UpdateState();
+        event.UpdateLedStateEvent.LedWidget->UpdateState();
     }
 }
 
 void AppTask::LEDStateUpdateHandler(LEDWidget & ledWidget)
 {
     AppEvent event;
-    event.Type                          = AppEvent::kEventType_UpdateLedState;
+    event.Type                          = AppEventType::UpdateLedState;
     event.Handler                       = UpdateLedStateEventHandler;
     event.UpdateLedStateEvent.LedWidget = &ledWidget;
-    sAppTask.PostEvent(&event);
+    PostEvent(event);
 }
 
 void AppTask::UpdateStatusLED()
 {
-    /* Update the status LED.
-     *
-     * If thread and service provisioned, keep the LED On constantly.
-     *
-     * If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
-     * rate of 100ms.
-     *
-     * Otherwise, blink the LED On for a very short time. */
-    if (sIsThreadProvisioned && sIsThreadEnabled)
+    // Update the status LED.
+    //
+    // If IPv6 network and service provisioned, keep the LED On constantly.
+    //
+    // If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
+    // rate of 100ms.
+    //
+    // Otherwise, blink the LED for a very short time.
+    if (sIsNetworkProvisioned && sIsNetworkEnabled)
     {
         sStatusLED.Set(true);
     }
     else if (sHaveBLEConnections)
     {
-        sStatusLED.Blink(100, 100);
+        sStatusLED.Blink(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms);
     }
     else
     {
-        sStatusLED.Blink(50, 950);
+        sStatusLED.Blink(LedConsts::StatusLed::Provisioned::kOn_ms, LedConsts::StatusLed::Provisioned::kOff_ms);
     }
 }
 
@@ -493,92 +585,94 @@
         sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
         UpdateStatusLED();
         break;
-    case DeviceEventType::kThreadStateChange:
-        sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
-        sIsThreadEnabled     = ConnectivityMgr().IsThreadEnabled();
-        UpdateStatusLED();
-        break;
+#if defined(CONFIG_NET_L2_OPENTHREAD)
     case DeviceEventType::kDnssdPlatformInitialized:
 #if CONFIG_CHIP_OTA_REQUESTOR
         InitBasicOTARequestor();
+#endif /* CONFIG_CHIP_OTA_REQUESTOR */
+        break;
+    case DeviceEventType::kThreadStateChange:
+        sIsNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsThreadEnabled();
+#elif defined(CONFIG_CHIP_WIFI)
+    case DeviceEventType::kWiFiConnectivityChange:
+        sIsNetworkProvisioned = ConnectivityMgr().IsWiFiStationProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsWiFiStationEnabled();
+#if CONFIG_CHIP_OTA_REQUESTOR
+        if (event->WiFiConnectivityChange.Result == kConnectivity_Established)
+        {
+            InitBasicOTARequestor();
+        }
+#endif /* CONFIG_CHIP_OTA_REQUESTOR */
 #endif
+        UpdateStatusLED();
         break;
     default:
         break;
     }
 }
-
 void AppTask::CancelTimer()
 {
     k_timer_stop(&sFunctionTimer);
     mFunctionTimerActive = false;
 }
 
-void AppTask::StartTimer(uint32_t aTimeoutInMs)
+void AppTask::StartTimer(uint32_t timeoutInMs)
 {
-    k_timer_start(&sFunctionTimer, K_MSEC(aTimeoutInMs), K_NO_WAIT);
+    k_timer_start(&sFunctionTimer, K_MSEC(timeoutInMs), K_NO_WAIT);
     mFunctionTimerActive = true;
 }
 
-void AppTask::ActionInitiated(PWMDevice::Action_t aAction, int32_t aActor)
+void AppTask::ActionInitiated(PWMDevice::Action_t action, int32_t actor)
 {
-    if (aAction == PWMDevice::ON_ACTION)
+    if (action == PWMDevice::ON_ACTION)
     {
         LOG_INF("Turn On Action has been initiated");
     }
-    else if (aAction == PWMDevice::OFF_ACTION)
+    else if (action == PWMDevice::OFF_ACTION)
     {
         LOG_INF("Turn Off Action has been initiated");
     }
-    else if (aAction == PWMDevice::LEVEL_ACTION)
+    else if (action == PWMDevice::LEVEL_ACTION)
     {
         LOG_INF("Level Action has been initiated");
     }
 }
 
-void AppTask::ActionCompleted(PWMDevice::Action_t aAction, int32_t aActor)
+void AppTask::ActionCompleted(PWMDevice::Action_t action, int32_t actor)
 {
-    if (aAction == PWMDevice::ON_ACTION)
+    if (action == PWMDevice::ON_ACTION)
     {
         LOG_INF("Turn On Action has been completed");
     }
-    else if (aAction == PWMDevice::OFF_ACTION)
+    else if (action == PWMDevice::OFF_ACTION)
     {
         LOG_INF("Turn Off Action has been completed");
     }
-    else if (aAction == PWMDevice::LEVEL_ACTION)
+    else if (action == PWMDevice::LEVEL_ACTION)
     {
         LOG_INF("Level Action has been completed");
     }
 
-    if (aActor == AppEvent::kEventType_Button)
+    if (actor == static_cast<int32_t>(AppEventType::Button))
     {
-        sAppTask.UpdateClusterState();
+        Instance().UpdateClusterState();
     }
 }
 
-void AppTask::PostLightingActionRequest(PWMDevice::Action_t aAction)
+void AppTask::PostEvent(const AppEvent & event)
 {
-    AppEvent event;
-    event.Type                 = AppEvent::kEventType_Lighting;
-    event.LightingEvent.Action = aAction;
-    event.Handler              = LightingActionEventHandler;
-    PostEvent(&event);
-}
-
-void AppTask::PostEvent(AppEvent * aEvent)
-{
-    if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT) != 0)
+    if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT) != 0)
     {
         LOG_INF("Failed to post event to app task event queue");
     }
 }
 
-void AppTask::DispatchEvent(AppEvent * aEvent)
+void AppTask::DispatchEvent(const AppEvent & event)
 {
-    if (aEvent->Handler)
+    if (event.Handler)
     {
-        aEvent->Handler(aEvent);
+        event.Handler(event);
     }
     else
     {
@@ -588,18 +682,21 @@
 
 void AppTask::UpdateClusterState()
 {
-    // write the new on/off value
-    EmberAfStatus status = Clusters::OnOff::Attributes::OnOff::Set(kLightEndpointId, mPWMDevice.IsTurnedOn());
+    SystemLayer().ScheduleLambda([this] {
+        // write the new on/off value
+        EmberAfStatus status = Clusters::OnOff::Attributes::OnOff::Set(kLightEndpointId, mPWMDevice.IsTurnedOn());
 
-    if (status != EMBER_ZCL_STATUS_SUCCESS)
-    {
-        LOG_ERR("Updating on/off cluster failed: %x", status);
-    }
+        if (status != EMBER_ZCL_STATUS_SUCCESS)
+        {
+            LOG_ERR("Updating on/off cluster failed: %x", status);
+        }
 
-    status = Clusters::LevelControl::Attributes::CurrentLevel::Set(kLightEndpointId, mPWMDevice.GetLevel());
+        // write the current level
+        status = Clusters::LevelControl::Attributes::CurrentLevel::Set(kLightEndpointId, mPWMDevice.GetLevel());
 
-    if (status != EMBER_ZCL_STATUS_SUCCESS)
-    {
-        LOG_ERR("Updating level cluster failed: %x", status);
-    }
+        if (status != EMBER_ZCL_STATUS_SUCCESS)
+        {
+            LOG_ERR("Updating level cluster failed: %x", status);
+        }
+    });
 }
diff --git a/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp b/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp
index 024d70a..eeb8326 100644
--- a/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp
+++ b/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp
@@ -38,15 +38,16 @@
     if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
     {
         ChipLogProgress(Zcl, "Cluster OnOff: attribute OnOff set to %u", *value);
-        GetAppTask().GetLightingDevice().InitiateAction(*value ? PWMDevice::ON_ACTION : PWMDevice::OFF_ACTION,
-                                                        AppEvent::kEventType_Lighting, value);
+        AppTask::Instance().GetPWMDevice().InitiateAction(*value ? PWMDevice::ON_ACTION : PWMDevice::OFF_ACTION,
+                                                          static_cast<int32_t>(AppEventType::Lighting), value);
     }
     else if (clusterId == LevelControl::Id && attributeId == LevelControl::Attributes::CurrentLevel::Id)
     {
         ChipLogProgress(Zcl, "Cluster LevelControl: attribute CurrentLevel set to %u", *value);
-        if (GetAppTask().GetLightingDevice().IsTurnedOn())
+        if (AppTask::Instance().GetPWMDevice().IsTurnedOn())
         {
-            GetAppTask().GetLightingDevice().InitiateAction(PWMDevice::LEVEL_ACTION, AppEvent::kEventType_Lighting, value);
+            AppTask::Instance().GetPWMDevice().InitiateAction(PWMDevice::LEVEL_ACTION, static_cast<int32_t>(AppEventType::Lighting),
+                                                              value);
         }
         else
         {
@@ -80,9 +81,10 @@
     if (status == EMBER_ZCL_STATUS_SUCCESS)
     {
         // Set actual state to the cluster state that was last persisted
-        GetAppTask().GetLightingDevice().InitiateAction(storedValue ? PWMDevice::ON_ACTION : PWMDevice::OFF_ACTION,
-                                                        AppEvent::kEventType_Lighting, reinterpret_cast<uint8_t *>(&storedValue));
+        AppTask::Instance().GetPWMDevice().InitiateAction(storedValue ? PWMDevice::ON_ACTION : PWMDevice::OFF_ACTION,
+                                                          static_cast<int32_t>(AppEventType::Lighting),
+                                                          reinterpret_cast<uint8_t *>(&storedValue));
     }
 
-    GetAppTask().UpdateClusterState();
+    AppTask::Instance().UpdateClusterState();
 }
diff --git a/examples/lighting-app/nrfconnect/main/include/AppConfig.h b/examples/lighting-app/nrfconnect/main/include/AppConfig.h
index 4f55191..536e92e 100644
--- a/examples/lighting-app/nrfconnect/main/include/AppConfig.h
+++ b/examples/lighting-app/nrfconnect/main/include/AppConfig.h
@@ -18,16 +18,28 @@
 
 #pragma once
 
+#include "BoardUtil.h"
+
 // ---- Lighting Example App Config ----
 
-#define LIGHTING_BUTTON DK_BTN2
-#define LIGHTING_BUTTON_MASK DK_BTN2_MSK
 #define FUNCTION_BUTTON DK_BTN1
 #define FUNCTION_BUTTON_MASK DK_BTN1_MSK
+
+#if NUMBER_OF_BUTTONS == 2
+#define BLE_ADVERTISEMENT_START_AND_LIGHTING_BUTTON DK_BTN2
+#define BLE_ADVERTISEMENT_START_AND_LIGHTING_BUTTON_MASK DK_BTN2_MSK
+#else
+#define LIGHTING_BUTTON DK_BTN2
+#define LIGHTING_BUTTON_MASK DK_BTN2_MSK
 #define BLE_ADVERTISEMENT_START_BUTTON DK_BTN4
 #define BLE_ADVERTISEMENT_START_BUTTON_MASK DK_BTN4_MSK
+#endif
 
-#define SYSTEM_STATE_LED DK_LED1 // led0 in device tree
-
+#define SYSTEM_STATE_LED DK_LED1
+#define LIGHTING_STATE_LED DK_LED2
+#if NUMBER_OF_LEDS == 4
+#define FACTORY_RESET_SIGNAL_LED DK_LED3
+#define FACTORY_RESET_SIGNAL_LED1 DK_LED4
+#endif
 // Time it takes in ms for the simulated actuator to move from one state to another.
 #define ACTUATOR_MOVEMENT_PERIOS_MS 2000
diff --git a/examples/lighting-app/nrfconnect/main/include/AppEvent.h b/examples/lighting-app/nrfconnect/main/include/AppEvent.h
index a5af0c9..19e8ced 100644
--- a/examples/lighting-app/nrfconnect/main/include/AppEvent.h
+++ b/examples/lighting-app/nrfconnect/main/include/AppEvent.h
@@ -20,29 +20,34 @@
 
 #include <cstdint>
 
-#include "LEDWidget.h"
+#include "EventTypes.h"
 
-struct AppEvent;
-typedef void (*EventHandler)(AppEvent *);
+class LEDWidget;
+
+enum class AppEventType : uint8_t
+{
+    None = 0,
+    Button,
+    ButtonPushed,
+    ButtonReleased,
+    Timer,
+    UpdateLedState,
+    Lighting,
+    IdentifyStart,
+    IdentifyStop,
+    StartSMPAdvertising
+};
+
+enum class FunctionEvent : uint8_t
+{
+    NoneSelected   = 0,
+    SoftwareUpdate = 0,
+    FactoryReset,
+    AdvertisingStart
+};
 
 struct AppEvent
 {
-    enum AppEventTypes
-    {
-        kEventType_Button = 0,
-        kEventType_Timer,
-        kEventType_Lighting,
-        kEventType_Install,
-        kEventType_UpdateLedState,
-        kEventType_IdentifyStart,
-        kEventType_IdentifyStop,
-#ifdef CONFIG_MCUMGR_SMP_BT
-        kEventType_StartSMPAdvertising,
-#endif
-    };
-
-    uint16_t Type;
-
     union
     {
         struct
@@ -65,5 +70,6 @@
         } UpdateLedStateEvent;
     };
 
+    AppEventType Type{ AppEventType::None };
     EventHandler Handler;
 };
diff --git a/examples/lighting-app/nrfconnect/main/include/AppTask.h b/examples/lighting-app/nrfconnect/main/include/AppTask.h
index a177273..461981e 100644
--- a/examples/lighting-app/nrfconnect/main/include/AppTask.h
+++ b/examples/lighting-app/nrfconnect/main/include/AppTask.h
@@ -44,70 +44,57 @@
 class AppTask
 {
 public:
+    static AppTask & Instance()
+    {
+        static AppTask sAppTask;
+        return sAppTask;
+    };
+
     CHIP_ERROR StartApp();
 
-    void PostLightingActionRequest(PWMDevice::Action_t aAction);
-    void PostEvent(AppEvent * event);
     void UpdateClusterState();
+    PWMDevice & GetPWMDevice() { return mPWMDevice; }
 
     static void IdentifyStartHandler(Identify *);
     static void IdentifyStopHandler(Identify *);
-    PWMDevice & GetLightingDevice() { return mPWMDevice; }
 
 private:
 #ifdef CONFIG_CHIP_PW_RPC
     friend class chip::rpc::NrfButton;
 #endif
 
-    friend AppTask & GetAppTask(void);
     CHIP_ERROR Init();
 
-    static void ActionInitiated(PWMDevice::Action_t aAction, int32_t aActor);
-    static void ActionCompleted(PWMDevice::Action_t aAction, int32_t aActor);
+    void CancelTimer();
+    void StartTimer(uint32_t timeoutInMs);
 
-    void CancelTimer(void);
-
-    void DispatchEvent(AppEvent * event);
-
-    static void UpdateStatusLED();
-    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
-    static void UpdateLedStateEventHandler(AppEvent * aEvent);
-    static void FunctionTimerEventHandler(AppEvent * aEvent);
-    static void FunctionHandler(AppEvent * aEvent);
-    static void LightingActionEventHandler(AppEvent * aEvent);
-    static void StartBLEAdvertisementHandler(AppEvent * aEvent);
+    static void PostEvent(const AppEvent & event);
+    static void DispatchEvent(const AppEvent & event);
+    static void FunctionTimerEventHandler(const AppEvent & event);
+    static void LightingActionEventHandler(const AppEvent & event);
+    static void StartBLEAdvertisementHandler(const AppEvent & event);
+    static void UpdateLedStateEventHandler(const AppEvent & event);
 
     static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+    static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged);
+    static void FunctionTimerTimeoutCallback(k_timer * timer);
 
-    static void ButtonEventHandler(uint32_t button_state, uint32_t has_changed);
-    static void TimerEventHandler(k_timer * timer);
+    static void ActionInitiated(PWMDevice::Action_t action, int32_t actor);
+    static void ActionCompleted(PWMDevice::Action_t action, int32_t actor);
+    static void UpdateStatusLED();
+    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
+    static void FunctionHandler(const AppEvent & event);
+    static void StartBLEAdvertisementAndLightActionEventHandler(const AppEvent & event);
 
 #ifdef CONFIG_MCUMGR_SMP_BT
     static void RequestSMPAdvertisingStart(void);
 #endif
 
-    void StartTimer(uint32_t aTimeoutInMs);
-
-    enum Function_t
-    {
-        kFunction_NoneSelected   = 0,
-        kFunction_SoftwareUpdate = 0,
-        kFunction_FactoryReset,
-
-        kFunction_Invalid
-    };
-
-    Function_t mFunction      = kFunction_NoneSelected;
+    FunctionEvent mFunction   = FunctionEvent::NoneSelected;
     bool mFunctionTimerActive = false;
     PWMDevice mPWMDevice;
-    static AppTask sAppTask;
 
 #if CONFIG_CHIP_FACTORY_DATA
     chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
 #endif
 };
-
-inline AppTask & GetAppTask(void)
-{
-    return AppTask::sAppTask;
-}
diff --git a/examples/lighting-app/nrfconnect/main/main.cpp b/examples/lighting-app/nrfconnect/main/main.cpp
index 9a487fc..69e83a6 100644
--- a/examples/lighting-app/nrfconnect/main/main.cpp
+++ b/examples/lighting-app/nrfconnect/main/main.cpp
@@ -31,7 +31,7 @@
 #include <zephyr/usb/usb_device.h>
 #endif
 
-LOG_MODULE_REGISTER(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip;
 
@@ -73,7 +73,7 @@
 
     if (err == CHIP_NO_ERROR)
     {
-        err = GetAppTask().StartApp();
+        err = AppTask::Instance().StartApp();
     }
 
     LOG_ERR("Exited with code %" CHIP_ERROR_FORMAT, err.Format());
diff --git a/examples/lighting-app/nrfconnect/prj.conf b/examples/lighting-app/nrfconnect/prj.conf
index 4bbb8a5..1a79698 100644
--- a/examples/lighting-app/nrfconnect/prj.conf
+++ b/examples/lighting-app/nrfconnect/prj.conf
@@ -14,32 +14,35 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32773 == 0x8005 (example lighting-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32773
+CONFIG_STD_CPP14=y
+
+# Enable CHIP pairing automatically on application start.
+CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 CONFIG_PWM=y
 
-# OpenThread configs
-CONFIG_OPENTHREAD_NORDIC_LIBRARY_FTD=y
+# General networking settings
+CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=14
 
-# Bluetooth overrides
+
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterLight"
 
-# Additional configs for debbugging experience.
+# Stack size settings
+CONFIG_IEEE802154_NRF5_RX_STACK_SIZE=1024
+
+# Other settings
 CONFIG_THREAD_NAME=y
 CONFIG_MPU_STACK_GUARD=y
 CONFIG_RESET_ON_FATAL_ERROR=n
-
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32773 == 0x8005 (example lighting-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32773
-
-# Enable CHIP pairing automatically on application start.
-CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y
diff --git a/examples/lighting-app/nrfconnect/prj_no_dfu.conf b/examples/lighting-app/nrfconnect/prj_no_dfu.conf
index 0e286be..7fc72e8 100644
--- a/examples/lighting-app/nrfconnect/prj_no_dfu.conf
+++ b/examples/lighting-app/nrfconnect/prj_no_dfu.conf
@@ -14,38 +14,40 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32773 == 0x8005 (example lighting-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32773
+CONFIG_STD_CPP14=y
+
+# Enable CHIP pairing automatically on application start.
+CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 CONFIG_PWM=y
 
-# OpenThread configs
-CONFIG_OPENTHREAD_NORDIC_LIBRARY_FTD=y
+# General networking settings
+CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=14
 
-# Bluetooth overrides
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterLight"
 
-# Additional configs for debbugging experience.
+# Other settings
 CONFIG_THREAD_NAME=y
 CONFIG_MPU_STACK_GUARD=y
 CONFIG_RESET_ON_FATAL_ERROR=n
 
+# Stack size settings
+CONFIG_IEEE802154_NRF5_RX_STACK_SIZE=1024
+
 # Disable Matter OTA DFU
 CONFIG_CHIP_OTA_REQUESTOR=n
 
 # Disable QSPI NOR
 CONFIG_CHIP_QSPI_NOR=n
-
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32773 == 0x8005 (example lighting-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32773
-
-# Enable CHIP pairing automatically on application start.
-CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y
diff --git a/examples/lighting-app/nrfconnect/prj_release.conf b/examples/lighting-app/nrfconnect/prj_release.conf
index d5302de..5ff2515 100644
--- a/examples/lighting-app/nrfconnect/prj_release.conf
+++ b/examples/lighting-app/nrfconnect/prj_release.conf
@@ -14,33 +14,35 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32773 == 0x8005 (example lighting-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32773
+CONFIG_STD_CPP14=y
+
+# Enable CHIP pairing automatically on application start.
+CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 CONFIG_PWM=y
 
-# OpenThread configs
-CONFIG_OPENTHREAD_NORDIC_LIBRARY_FTD=y
+# General networking settings
+CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=14
 
-# Bluetooth overrides
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterLight"
 
 # Enable system reset on fatal error
 CONFIG_RESET_ON_FATAL_ERROR=y
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32773 == 0x8005 (example lighting-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32773
-
-# Enable CHIP pairing automatically on application start.
-CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y
+# Stack size settings
+CONFIG_IEEE802154_NRF5_RX_STACK_SIZE=1024
 
 # Disable all debug features
 CONFIG_SHELL=n
@@ -53,4 +55,4 @@
 CONFIG_ASSERT_VERBOSE=n
 CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_PRINTK=n
-CONFIG_THREAD_NAME=n
+CONFIG_PRINTK_SYNC=n
diff --git a/examples/lock-app/nrfconnect/CMakeLists.txt b/examples/lock-app/nrfconnect/CMakeLists.txt
index aa93238..5c9bd36 100644
--- a/examples/lock-app/nrfconnect/CMakeLists.txt
+++ b/examples/lock-app/nrfconnect/CMakeLists.txt
@@ -24,6 +24,7 @@
 # Set Kconfig root files that will be processed as a first Kconfig for used child images.
 set(mcuboot_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.mcuboot.root)
 set(multiprotocol_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.multiprotocol_rpmsg.root)
+set(hci_rpmsg_KCONFIG_ROOT ${CHIP_ROOT}/config/nrfconnect/chip-module/Kconfig.hci_rpmsg.root)
 
 if(NOT CONF_FILE STREQUAL "prj_no_dfu.conf")
     set(PM_STATIC_YML_FILE ${CMAKE_CURRENT_SOURCE_DIR}/configuration/${BOARD}/pm_static_dfu.yml)
diff --git a/examples/lock-app/nrfconnect/Kconfig b/examples/lock-app/nrfconnect/Kconfig
index e9dfd7d..98ed2d5 100644
--- a/examples/lock-app/nrfconnect/Kconfig
+++ b/examples/lock-app/nrfconnect/Kconfig
@@ -35,6 +35,23 @@
 	  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.
 
+# Sample configuration used for Thread networking
+if NET_L2_OPENTHREAD
+
+choice OPENTHREAD_NORDIC_LIBRARY_CONFIGURATION
+	default OPENTHREAD_NORDIC_LIBRARY_MTD
+endchoice
+
+choice OPENTHREAD_DEVICE_TYPE
+	default OPENTHREAD_MTD
+endchoice
+
+config CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT
+	bool
+	default y
+
+endif # NET_L2_OPENTHREAD
+
 rsource "../../../config/nrfconnect/chip-module/Kconfig.features"
 rsource "../../../config/nrfconnect/chip-module/Kconfig.defaults"
 source "Kconfig.zephyr"
diff --git a/examples/lock-app/nrfconnect/README.md b/examples/lock-app/nrfconnect/README.md
index 1ed12be..050d5a7 100644
--- a/examples/lock-app/nrfconnect/README.md
+++ b/examples/lock-app/nrfconnect/README.md
@@ -12,12 +12,15 @@
 
 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
-simulated door lock over a low-power, 802.15.4 Thread network.
+Semiconductor's nRF Connect SDK, and was created to facilitate testing and
+certification of a Matter device communicating over a low-power, 802.15.4 Thread
+network, or Wi-Fi 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. The
-device works as a Thread Sleepy End Device.
+into an existing Matter network and can be controlled by this network. In the
+case of Thread, this device works as a Thread Sleepy End Device. Support for
+both Thread and Wi-Fi is mutually exclusive and depends on the hardware
+platform, so only one protocol can be supported for a specific lock device.
 
 <hr>
 
@@ -27,6 +30,7 @@
     -   [Device Firmware Upgrade](#device-firmware-upgrade)
 -   [Requirements](#requirements)
     -   [Supported devices](#supported_devices)
+    -   [IPv6 network support](#ipv6-network-support)
 -   [Device UI](#device-ui)
 -   [Setting up the environment](#setting-up-the-environment)
     -   [Using Docker container for setup](#using-docker-container-for-setup)
@@ -57,20 +61,32 @@
 [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md)
 to read more about the platform structure and dependencies.
 
-The Matter device that runs the lock 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.
+By default, the Matter accessory device has IPv6 networking disabled. You must
+pair it with the Matter controller over Bluetooth® LE to get the configuration
+from the controller to use the device within a Thread or Wi-Fi network. You have
+to make the device discoverable manually (for security reasons). See
+[Bluetooth LE advertising](#bluetooth-le-advertising) to learn how to do this.
+The controller must get the commissioning information from the Matter accessory
+device and provision the device into the network.
 
-The example can be configured to use the secure bootloader and utilize it for
-performing over-the-air Device Firmware Upgrade using Bluetooth LE.
+The sample uses buttons for changing the lock and device states, and LEDs to
+show the state of these changes. You can test it in the following ways:
+
+-   Standalone, using a single DK that runs the door lock application.
+
+-   Remotely over the Thread or the Wi-Fi protocol, which in either case
+    requires more devices, including a Matter controller that you can configure
+    either on a PC or a mobile device.
 
 ### 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**.
+LE advertising manually after powering up the device by pressing:
+
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: **Button 4**.
+
+-   On nRF7002 DK: **Button 2**.
 
 ### Bluetooth LE rendezvous
 
@@ -80,16 +96,16 @@
 
 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.
+the UART console, and shared using an NFC tag. The emulation of the NFC tag
+emulation starts automatically when Bluetooth LE advertising is started and
+stays enabled until Bluetooth LE advertising timeout expires.
 
-#### Thread provisioning
+#### Thread or Wi-Fi 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, device is able to join the Thread network and communicate
-with other Thread devices in the network.
+The provisioning operation, which is the Last part of the rendezvous procedure,
+involves sending the Thread or Wi-Fi network credentials from the Matter
+controller to the Matter device. As a result, the device joins the Thread or
+Wi-Fi network and can communicate with other devices in the network.
 
 ### Device Firmware Upgrade
 
@@ -164,13 +180,23 @@
 
 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`      | <details><summary>nRF52840 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_DK_info-medium.jpg" alt="nRF52840 DK"/></details> |
-| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK)   | `nrf5340dk_nrf5340_cpuapp` | <details><summary>nRF5340 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF5340_DK_info-medium.jpg" alt="nRF5340 DK"/></details>    |
+| Hardware platform                                                                                               | Build target               | Platform image                                                                                                                                   |
+| --------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
+| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)                       | `nrf52840dk_nrf52840`      | <details><summary>nRF52840 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF52840_DK_info-medium.jpg" alt="nRF52840 DK"/></details> |
+| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK)                         | `nrf5340dk_nrf5340_cpuapp` | <details><summary>nRF5340 DK</summary><img src="../../platform/nrfconnect/doc/images/nRF5340_DK_info-medium.jpg" alt="nRF5340 DK"/></details>    |
+| [nRF7002 DK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf7002.html#nrf7002dk-nrf5340) | `nrf7002dk_nrf5340_cpuapp` | <details><summary>nRF7002DK</summary><img src="../../platform/nrfconnect/doc/images/nrf7002dk.jpg" alt="nRF7002 DK"/></details>                  |
 
 <hr>
 
+### IPv6 network support
+
+The development kits for this sample offer the following IPv6 network support
+for Matter:
+
+-   Matter over Thread is supported for `nrf52840dk_nrf52840` and
+    `nrf5340dk_nrf5340_cpuapp`.
+-   Matter over Wi-Fi is supported for `nrf7002dk_nrf5340_cpuapp`.
+
 <a name="device-ui"></a>
 
 ## Device UI
@@ -191,11 +217,10 @@
     Bluetooth LE.
 
 -   _Short Flash Off (950ms on/50ms off)_ &mdash; The device is fully
-    provisioned, but does not yet have full Thread network or service
-    connectivity.
+    provisioned, but does not yet have full connectivity for Thread or Wi-Fi
+    network.
 
--   _Solid On_ &mdash; The device is fully provisioned and has full Thread
-    network and service connectivity.
+-   _Solid On_ &mdash; The device is fully provisioned.
 
 **LED 2** simulates the lock bolt and shows the state of the lock. The following
 states are possible:
@@ -207,25 +232,46 @@
 -   _Rapid Even Flashing (100 ms on/100 ms off during 2 s)_ &mdash; The
     simulated bolt is in motion from one position to another.
 
-**Button 1** can be used for the following purposes:
+    Additionally, the LED starts blinking evenly (500 ms on/500 ms off) when the
+    Identify command of the Identify cluster is received on the endpoint 1. The
+    command’s argument can be used to specify the duration of the effect.
 
--   _Pressed for 6 s_ &mdash; Initiates the factory reset of the device.
-    Releasing the button within the 6-second window cancels the factory reset
-    procedure. **LEDs 1-4** blink in unison when the factory reset procedure is
-    initiated.
+**Button 1** can be used for the following purposes:
 
 -   _Pressed for less than 3 s_ &mdash; 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.
+    instructions.
+
+-   _Pressed for more than 3 s_ &mdash; initiates the factory reset of the
+    device. Releasing the button within the 3-second window cancels the factory
+    reset procedure.
 
 **Button 2** &mdash; Pressing the button once changes the lock state to the
 opposite one.
 
-**Button 4** &mdash; Pressing the button once starts the NFC tag emulation and
-enables Bluetooth LE advertising for the predefined period of time (15 minutes
-by default).
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: Changes the lock state to the
+    opposite one.
+
+-   On nRF7002 DK:
+
+    -   If pressed for less than three seconds, it changes the lock state to the
+        opposite one.
+
+    -   If pressed for more than three seconds, it starts the NFC tag emulation,
+        enables Bluetooth LE advertising for the predefined period of time (15
+        minutes by default), and makes the device discoverable over Bluetooth
+        LE.
+
+**Button 4**:
+
+-   On nRF52840 DK, nRF5340 DK, and nRF21540 DK: Starts the NFC tag emulation,
+    enables Bluetooth LE advertising for the predefined period of time (15
+    minutes by default), and makes the device discoverable over Bluetooth LE.
+    This button is used during the commissioning procedure.
+
+-   On nRF7002 DK: Not available.
 
 **SEGGER J-Link USB port** can be used to get logs from the device or
 communicate with it using the
@@ -503,7 +549,8 @@
 
 Read the [CHIP Tool user guide](../../../docs/guides/chip_tool_guide.md) to see
 how to use [CHIP Tool for Linux or mac OS](../../chip-tool/README.md) to
-commission and control the application within a Matter-enabled Thread network.
+commission and control the application within a Matter-enabled Thread or Wi-Fi
+network.
 
 ### Testing using Android CHIPTool
 
@@ -511,7 +558,7 @@
 [Android commissioning guide](../../../docs/guides/nrfconnect_android_commissioning.md)
 to see how to use [CHIPTool](../../../examples/android/CHIPTool/README.md) for
 Android smartphones to commission and control the application within a
-Matter-enabled Thread network.
+Matter-enabled Thread or Wi-Fi network.
 
 ### Testing Device Firmware Upgrade
 
diff --git a/examples/lock-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay b/examples/lock-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
index a4bac9f..b211bc4 100644
--- a/examples/lock-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
+++ b/examples/lock-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
@@ -37,9 +37,6 @@
 &uart1 {
 	status = "disabled";
 };
-&gpio1 {
-	status = "disabled";
-};
 &i2c0 {
 	status = "disabled";
 };
diff --git a/examples/lock-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay b/examples/lock-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay
new file mode 100644
index 0000000..3063fbb
--- /dev/null
+++ b/examples/lock-app/nrfconnect/boards/nrf7002dk_nrf5340_cpuapp.overlay
@@ -0,0 +1,21 @@
+/*
+ *    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;
+	};
+};
diff --git a/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj.conf b/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf b/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_no_dfu.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf b/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf
new file mode 100644
index 0000000..1622ffd
--- /dev/null
+++ b/examples/lock-app/nrfconnect/child_image/hci_rpmsg/prj_release.conf
@@ -0,0 +1,25 @@
+#
+#    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 target uses Kconfig.hci_rpmsg.defaults to set options common for all
+# samples using hci_rpmsg. This file should contain only options specific for this sample
+# hci_rpmsg configuration or overrides of default values.
+
+# Disable not used modules that cannot be set in Kconfig.hci_rpmsg.defaults due to overriding
+# in board files.
+
+CONFIG_SERIAL=n
+CONFIG_UART_CONSOLE=n
diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/prj.conf b/examples/lock-app/nrfconnect/child_image/mcuboot/prj.conf
index 287c782..0dbf710 100644
--- a/examples/lock-app/nrfconnect/child_image/mcuboot/prj.conf
+++ b/examples/lock-app/nrfconnect/child_image/mcuboot/prj.conf
@@ -23,7 +23,6 @@
 # Bootloader size optimization
 # Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding
 # in board files.
-CONFIG_GPIO=n
 CONFIG_CONSOLE=n
 CONFIG_SERIAL=n
 CONFIG_UART_CONSOLE=n
diff --git a/examples/lock-app/nrfconnect/child_image/mcuboot/prj_release.conf b/examples/lock-app/nrfconnect/child_image/mcuboot/prj_release.conf
index 287c782..0dbf710 100644
--- a/examples/lock-app/nrfconnect/child_image/mcuboot/prj_release.conf
+++ b/examples/lock-app/nrfconnect/child_image/mcuboot/prj_release.conf
@@ -23,7 +23,6 @@
 # Bootloader size optimization
 # Disable not used modules that cannot be set in Kconfig.mcuboot.defaults due to overriding
 # in board files.
-CONFIG_GPIO=n
 CONFIG_CONSOLE=n
 CONFIG_SERIAL=n
 CONFIG_UART_CONSOLE=n
diff --git a/examples/lock-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml b/examples/lock-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml
new file mode 100644
index 0000000..3c56dc0
--- /dev/null
+++ b/examples/lock-app/nrfconnect/configuration/nrf7002dk_nrf5340_cpuapp/pm_static_dfu.yml
@@ -0,0 +1,56 @@
+mcuboot:
+    address: 0x0
+    size: 0xC000
+    region: flash_primary
+mcuboot_pad:
+    address: 0xC000
+    size: 0x200
+app:
+    address: 0xC200
+    size: 0xeee00
+mcuboot_primary:
+    orig_span: &id001
+        - mcuboot_pad
+        - app
+    span: *id001
+    address: 0xC000
+    size: 0xef000
+    region: flash_primary
+mcuboot_primary_app:
+    orig_span: &id002
+        - app
+    span: *id002
+    address: 0xC200
+    size: 0xeee00
+factory_data:
+    address: 0xfb000
+    size: 0x1000
+    region: flash_primary
+settings_storage:
+    address: 0xfc000
+    size: 0x4000
+    region: flash_primary
+mcuboot_primary_1:
+    address: 0x0
+    size: 0x40000
+    device: flash_ctrl
+    region: ram_flash
+mcuboot_secondary:
+    address: 0x0
+    size: 0xef000
+    device: MX25R64
+    region: external_flash
+mcuboot_secondary_1:
+    address: 0xef000
+    size: 0x40000
+    device: MX25R64
+    region: external_flash
+external_flash:
+    address: 0x12f000
+    size: 0x6D1000
+    device: MX25R64
+    region: external_flash
+pcd_sram:
+    address: 0x20000000
+    size: 0x2000
+    region: sram_primary
diff --git a/examples/lock-app/nrfconnect/main/AppTask.cpp b/examples/lock-app/nrfconnect/main/AppTask.cpp
index b7d4d02..4f5c18d 100644
--- a/examples/lock-app/nrfconnect/main/AppTask.cpp
+++ b/examples/lock-app/nrfconnect/main/AppTask.cpp
@@ -19,6 +19,7 @@
 #include "AppTask.h"
 #include "AppConfig.h"
 #include "BoltLockManager.h"
+#include "LEDUtil.h"
 #include "LEDWidget.h"
 
 #include <DeviceInfoProviderImpl.h>
@@ -27,6 +28,7 @@
 #include <app-common/zap-generated/attributes/Accessors.h>
 #include <app-common/zap-generated/cluster-id.h>
 #include <app/clusters/door-lock-server/door-lock-server.h>
+#include <app/clusters/identify-server/identify-server.h>
 #include <app/clusters/ota-requestor/OTATestEventTriggerDelegate.h>
 #include <app/server/OnboardingCodesUtil.h>
 #include <app/server/Server.h>
@@ -37,6 +39,11 @@
 #include <lib/support/ErrorStr.h>
 #include <system/SystemClock.h>
 
+#ifdef CONFIG_CHIP_WIFI
+#include <app/clusters/network-commissioning/network-commissioning.h>
+#include <platform/nrfconnect/wifi/NrfWiFiDriver.h>
+#endif
+
 #if CONFIG_CHIP_OTA_REQUESTOR
 #include "OTAUtil.h"
 #endif
@@ -45,44 +52,66 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
+LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
+
 using namespace ::chip;
 using namespace ::chip::app;
 using namespace ::chip::app::Clusters::DoorLock;
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceLayer;
 
-#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
-#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
-#define APP_EVENT_QUEUE_SIZE 10
-#define BUTTON_PUSH_EVENT 1
-#define BUTTON_RELEASE_EVENT 0
-
 namespace {
-constexpr EndpointId kLockEndpointId = 1;
+constexpr uint32_t kFactoryResetTriggerTimeout      = 3000;
+constexpr uint32_t kFactoryResetCancelWindowTimeout = 3000;
+constexpr size_t kAppEventQueueSize                 = 10;
+constexpr EndpointId kLockEndpointId                = 1;
+#if NUMBER_OF_BUTTONS == 2
+constexpr uint32_t kAdvertisingTriggerTimeout = 3000;
+#endif
 
 // NOTE! This key is for test/certification only and should not be available in production devices!
 // If CONFIG_CHIP_FACTORY_DATA is enabled, this value is read from the factory data.
 uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                                                                                    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
 
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
-K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), APP_EVENT_QUEUE_SIZE, alignof(AppEvent));
+K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
 k_timer sFunctionTimer;
 
+Identify sIdentify = { kLockEndpointId, AppTask::IdentifyStartHandler, AppTask::IdentifyStopHandler,
+                       EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED };
+
 LEDWidget sStatusLED;
 LEDWidget sLockLED;
-LEDWidget sUnusedLED;
-LEDWidget sUnusedLED_1;
+#if NUMBER_OF_LEDS == 4
+FactoryResetLEDsWrapper<2> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTORY_RESET_SIGNAL_LED1 } };
+#endif
 
-bool sIsThreadProvisioned = false;
-bool sIsThreadEnabled     = false;
-bool sHaveBLEConnections  = false;
+bool sIsNetworkProvisioned = false;
+bool sIsNetworkEnabled     = false;
+bool sHaveBLEConnections   = false;
 
 chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
-
 } // namespace
 
-AppTask AppTask::sAppTask;
+namespace LedConsts {
+constexpr uint32_t kBlinkRate_ms{ 500 };
+constexpr uint32_t kIdentifyBlinkRate_ms{ 500 };
+namespace StatusLed {
+namespace Unprovisioned {
+constexpr uint32_t kOn_ms{ 100 };
+constexpr uint32_t kOff_ms{ kOn_ms };
+} // namespace Unprovisioned
+namespace Provisioned {
+constexpr uint32_t kOn_ms{ 50 };
+constexpr uint32_t kOff_ms{ 950 };
+} // namespace Provisioned
+
+} // namespace StatusLed
+} // namespace LedConsts
+
+#ifdef CONFIG_CHIP_WIFI
+app::Clusters::NetworkCommissioning::Instance sWiFiCommissioningInstance(0, &(NetworkCommissioning::NrfWiFiDriver::Instance()));
+#endif
 
 CHIP_ERROR AppTask::Init()
 {
@@ -121,9 +150,11 @@
         LOG_ERR("ConnectivityMgr().SetThreadDeviceType() failed");
         return err;
     }
+#elif defined(CONFIG_CHIP_WIFI)
+    sWiFiCommissioningInstance.Init();
 #else
     return CHIP_ERROR_INTERNAL;
-#endif
+#endif // CONFIG_NET_L2_OPENTHREAD
 
     // Initialize LEDs
     LEDWidget::InitGpio();
@@ -133,13 +164,8 @@
     sLockLED.Init(LOCK_STATE_LED);
     sLockLED.Set(BoltLockMgr().IsLocked());
 
-    sUnusedLED.Init(DK_LED3);
-    sUnusedLED_1.Init(DK_LED4);
-
     UpdateStatusLED();
 
-    BoltLockMgr().Init(LockStateChanged);
-
     // Initialize buttons
     int ret = dk_buttons_init(ButtonEventHandler);
     if (ret)
@@ -149,7 +175,7 @@
     }
 
     // Initialize function button timer
-    k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr);
+    k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr);
     k_timer_user_data_set(&sFunctionTimer, this);
 
 #ifdef CONFIG_MCUMGR_SMP_BT
@@ -158,6 +184,8 @@
     GetDFUOverSMP().ConfirmNewImage();
 #endif
 
+    BoltLockMgr().Init(LockStateChanged);
+
     // Initialize CHIP server
 #if CONFIG_CHIP_FACTORY_DATA
     ReturnErrorOnFailure(mFactoryDataProvider.Init());
@@ -213,13 +241,55 @@
     while (true)
     {
         k_msgq_get(&sAppEventQueue, &event, K_FOREVER);
-        DispatchEvent(&event);
+        DispatchEvent(event);
     }
 
     return CHIP_NO_ERROR;
 }
 
-void AppTask::LockActionEventHandler(AppEvent * aEvent)
+void AppTask::IdentifyStartHandler(Identify *)
+{
+    AppEvent event;
+    event.Type    = AppEventType::IdentifyStart;
+    event.Handler = [](const AppEvent &) { sLockLED.Blink(LedConsts::kIdentifyBlinkRate_ms); };
+    PostEvent(event);
+}
+
+void AppTask::IdentifyStopHandler(Identify *)
+{
+    AppEvent event;
+    event.Type    = AppEventType::IdentifyStop;
+    event.Handler = [](const AppEvent &) { sLockLED.Set(BoltLockMgr().IsLocked()); };
+    PostEvent(event);
+}
+
+#if NUMBER_OF_BUTTONS == 2
+void AppTask::StartBLEAdvertisementAndLockActionEventHandler(const AppEvent & event)
+{
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
+    {
+        Instance().StartTimer(kAdvertisingTriggerTimeout);
+        Instance().mFunction = FunctionEvent::AdvertisingStart;
+    }
+    else
+    {
+        if (Instance().mFunction == FunctionEvent::AdvertisingStart)
+        {
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
+
+            AppEvent button_event;
+            button_event.Type               = AppEventType::Button;
+            button_event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_AND_LOCK_BUTTON;
+            button_event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonReleased);
+            button_event.Handler            = LockActionEventHandler;
+            PostEvent(button_event);
+        }
+    }
+}
+#endif
+
+void AppTask::LockActionEventHandler(const AppEvent & event)
 {
     if (BoltLockMgr().IsLocked())
     {
@@ -231,79 +301,103 @@
     }
 }
 
-void AppTask::ButtonEventHandler(uint32_t button_state, uint32_t has_changed)
+void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)
 {
     AppEvent button_event;
-    button_event.Type = AppEvent::kEventType_Button;
+    button_event.Type = AppEventType::Button;
 
-    if (LOCK_BUTTON_MASK & button_state & has_changed)
+#if NUMBER_OF_BUTTONS == 2
+    if (BLE_ADVERTISEMENT_START_AND_LOCK_BUTTON_MASK & hasChanged)
+    {
+        button_event.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_AND_LOCK_BUTTON;
+        button_event.ButtonEvent.Action =
+            static_cast<uint8_t>((BLE_ADVERTISEMENT_START_AND_LOCK_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed
+                                                                                              : AppEventType::ButtonReleased);
+        button_event.Handler = StartBLEAdvertisementAndLockActionEventHandler;
+        PostEvent(button_event);
+    }
+#else
+    if (LOCK_BUTTON_MASK & buttonState & hasChanged)
     {
         button_event.ButtonEvent.PinNo  = LOCK_BUTTON;
-        button_event.ButtonEvent.Action = BUTTON_PUSH_EVENT;
+        button_event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
         button_event.Handler            = LockActionEventHandler;
-        sAppTask.PostEvent(&button_event);
+        PostEvent(button_event);
     }
 
-    if (FUNCTION_BUTTON_MASK & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = FUNCTION_BUTTON;
-        button_event.ButtonEvent.Action = (FUNCTION_BUTTON_MASK & button_state) ? BUTTON_PUSH_EVENT : BUTTON_RELEASE_EVENT;
-        button_event.Handler            = FunctionHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-
-    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & button_state & has_changed)
+    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged)
     {
         button_event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
-        button_event.ButtonEvent.Action = BUTTON_PUSH_EVENT;
+        button_event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
         button_event.Handler            = StartBLEAdvertisementHandler;
-        sAppTask.PostEvent(&button_event);
+        PostEvent(button_event);
+    }
+#endif
+
+    if (FUNCTION_BUTTON_MASK & hasChanged)
+    {
+        button_event.ButtonEvent.PinNo = FUNCTION_BUTTON;
+        button_event.ButtonEvent.Action =
+            static_cast<uint8_t>((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased);
+        button_event.Handler = FunctionHandler;
+        PostEvent(button_event);
     }
 }
 
-void AppTask::TimerEventHandler(k_timer * timer)
+void AppTask::FunctionTimerTimeoutCallback(k_timer * timer)
 {
+    if (!timer)
+    {
+        return;
+    }
+
     AppEvent event;
-    event.Type               = AppEvent::kEventType_Timer;
+    event.Type               = AppEventType::Timer;
     event.TimerEvent.Context = k_timer_user_data_get(timer);
     event.Handler            = FunctionTimerEventHandler;
-    sAppTask.PostEvent(&event);
+    PostEvent(event);
 }
 
-void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
+void AppTask::FunctionTimerEventHandler(const AppEvent & event)
 {
-    if (aEvent->Type != AppEvent::kEventType_Timer)
-        return;
-
-    // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT, initiate factory reset
-    if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+    if (event.Type != AppEventType::Timer || !Instance().mFunctionTimerActive)
     {
-        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_TRIGGER_TIMEOUT);
+        return;
+    }
 
-        // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to cancel, if required.
-        sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
-        sAppTask.mFunction = kFunction_FactoryReset;
+    // If we reached here, the button was held past kFactoryResetTriggerTimeout, initiate factory reset
+    if (Instance().mFunction == FunctionEvent::SoftwareUpdate)
+    {
+        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", kFactoryResetTriggerTimeout);
 
-#ifdef CONFIG_STATE_LEDS
-        // Turn off all LEDs before starting blink to make sure blink is co-ordinated.
+        // Start timer for kFactoryResetCancelWindowTimeout to allow user to cancel, if required.
+        Instance().StartTimer(kFactoryResetCancelWindowTimeout);
+        Instance().mFunction = FunctionEvent::FactoryReset;
+
+        // Turn off all LEDs before starting blink to make sure blink is coordinated.
         sStatusLED.Set(false);
-        sLockLED.Set(false);
-        sUnusedLED_1.Set(false);
-        sUnusedLED.Set(false);
+#if NUMBER_OF_LEDS == 4
+        sFactoryResetLEDs.Set(false);
+#endif
 
-        sStatusLED.Blink(500);
-        sLockLED.Blink(500);
-        sUnusedLED.Blink(500);
-        sUnusedLED_1.Blink(500);
+        sStatusLED.Blink(LedConsts::kBlinkRate_ms);
+#if NUMBER_OF_LEDS == 4
+        sFactoryResetLEDs.Blink(LedConsts::kBlinkRate_ms);
 #endif
     }
-    else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+    else if (Instance().mFunction == FunctionEvent::FactoryReset)
     {
         // Actually trigger Factory Reset
-        sAppTask.mFunction = kFunction_NoneSelected;
-
+        Instance().mFunction = FunctionEvent::NoneSelected;
         chip::Server::GetInstance().ScheduleFactoryReset();
     }
+    else if (Instance().mFunction == FunctionEvent::AdvertisingStart)
+    {
+        // The button was held past kAdvertisingTriggerTimeout, start BLE advertisement if we have 2 buttons UI
+#if NUMBER_OF_BUTTONS == 2
+        StartBLEAdvertisementHandler(event);
+#endif
+    }
 }
 
 #ifdef CONFIG_MCUMGR_SMP_BT
@@ -316,9 +410,9 @@
 }
 #endif
 
-void AppTask::FunctionHandler(AppEvent * aEvent)
+void AppTask::FunctionHandler(const AppEvent & event)
 {
-    if (aEvent->ButtonEvent.PinNo != FUNCTION_BUTTON)
+    if (event.ButtonEvent.PinNo != FUNCTION_BUTTON)
         return;
 
     // To trigger software update: press the FUNCTION_BUTTON button briefly (< FACTORY_RESET_TRIGGER_TIMEOUT)
@@ -326,22 +420,22 @@
     // All LEDs start blinking after FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
     // To cancel factory reset: release the FUNCTION_BUTTON once all LEDs start blinking within the
     // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
-    if (aEvent->ButtonEvent.Action == BUTTON_PUSH_EVENT)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
     {
-        if (!sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_NoneSelected)
+        if (!Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::NoneSelected)
         {
-            sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+            Instance().StartTimer(kFactoryResetTriggerTimeout);
 
-            sAppTask.mFunction = kFunction_SoftwareUpdate;
+            Instance().mFunction = FunctionEvent::SoftwareUpdate;
         }
     }
     else
     {
         // If the button was released before factory reset got initiated, trigger a software update.
-        if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+        if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
         {
-            sAppTask.CancelTimer();
-            sAppTask.mFunction = kFunction_NoneSelected;
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
 
 #ifdef CONFIG_MCUMGR_SMP_BT
             GetDFUOverSMP().StartServer();
@@ -349,26 +443,20 @@
             LOG_INF("Software update is disabled");
 #endif
         }
-        else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+        else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
         {
-            sUnusedLED.Set(false);
-            sUnusedLED_1.Set(false);
-
-            // Set lock status LED back to show state of lock.
-            sLockLED.Set(BoltLockMgr().IsLocked());
-
+#if NUMBER_OF_LEDS == 4
+            sFactoryResetLEDs.Set(false);
+#endif
             UpdateStatusLED();
-            sAppTask.CancelTimer();
-
-            // Change the function to none selected since factory reset has been canceled.
-            sAppTask.mFunction = kFunction_NoneSelected;
-
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
             LOG_INF("Factory Reset has been Canceled");
         }
     }
 }
 
-void AppTask::StartBLEAdvertisementHandler(AppEvent *)
+void AppTask::StartBLEAdvertisementHandler(const AppEvent &)
 {
     if (Server::GetInstance().GetFabricTable().FabricCount() != 0)
     {
@@ -388,45 +476,45 @@
     }
 }
 
-void AppTask::UpdateLedStateEventHandler(AppEvent * aEvent)
+void AppTask::UpdateLedStateEventHandler(const AppEvent & event)
 {
-    if (aEvent->Type == AppEvent::kEventType_UpdateLedState)
+    if (event.Type == AppEventType::UpdateLedState)
     {
-        aEvent->UpdateLedStateEvent.LedWidget->UpdateState();
+        event.UpdateLedStateEvent.LedWidget->UpdateState();
     }
 }
 
 void AppTask::LEDStateUpdateHandler(LEDWidget & ledWidget)
 {
     AppEvent event;
-    event.Type                          = AppEvent::kEventType_UpdateLedState;
+    event.Type                          = AppEventType::UpdateLedState;
     event.Handler                       = UpdateLedStateEventHandler;
     event.UpdateLedStateEvent.LedWidget = &ledWidget;
-    sAppTask.PostEvent(&event);
+    PostEvent(event);
 }
 
 void AppTask::UpdateStatusLED()
 {
 #ifdef CONFIG_STATE_LEDS
-    /* Update the status LED.
-     *
-     * If thread and service provisioned, keep the LED On constantly.
-     *
-     * If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
-     * rate of 100ms.
-     *
-     * Otherwise, blink the LED On for a very short time. */
-    if (sIsThreadProvisioned && sIsThreadEnabled)
+    // Update the status LED.
+    //
+    // If IPv6 network and service provisioned, keep the LED On constantly.
+    //
+    // If the system has BLE connection(s) until the stage above, THEN blink the LED at an even
+    // rate of 100ms.
+    //
+    // Otherwise, blink the LED for a very short time.
+    if (sIsNetworkProvisioned && sIsNetworkEnabled)
     {
         sStatusLED.Set(true);
     }
     else if (sHaveBLEConnections)
     {
-        sStatusLED.Blink(100, 100);
+        sStatusLED.Blink(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms);
     }
     else
     {
-        sStatusLED.Blink(50, 950);
+        sStatusLED.Blink(LedConsts::StatusLed::Provisioned::kOn_ms, LedConsts::StatusLed::Provisioned::kOff_ms);
     }
 #endif
 }
@@ -456,15 +544,27 @@
         sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
         UpdateStatusLED();
         break;
-    case DeviceEventType::kThreadStateChange:
-        sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
-        sIsThreadEnabled     = ConnectivityMgr().IsThreadEnabled();
-        UpdateStatusLED();
-        break;
+#if defined(CONFIG_NET_L2_OPENTHREAD)
     case DeviceEventType::kDnssdPlatformInitialized:
 #if CONFIG_CHIP_OTA_REQUESTOR
         InitBasicOTARequestor();
+#endif // CONFIG_CHIP_OTA_REQUESTOR
+        break;
+    case DeviceEventType::kThreadStateChange:
+        sIsNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsThreadEnabled();
+#elif defined(CONFIG_CHIP_WIFI)
+    case DeviceEventType::kWiFiConnectivityChange:
+        sIsNetworkProvisioned = ConnectivityMgr().IsWiFiStationProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsWiFiStationEnabled();
+#if CONFIG_CHIP_OTA_REQUESTOR
+        if (event->WiFiConnectivityChange.Result == kConnectivity_Established)
+        {
+            InitBasicOTARequestor();
+        }
+#endif // CONFIG_CHIP_OTA_REQUESTOR
 #endif
+        UpdateStatusLED();
         break;
     default:
         break;
@@ -477,9 +577,9 @@
     mFunctionTimerActive = false;
 }
 
-void AppTask::StartTimer(uint32_t aTimeoutInMs)
+void AppTask::StartTimer(uint32_t timeoutInMs)
 {
-    k_timer_start(&sFunctionTimer, K_MSEC(aTimeoutInMs), K_NO_WAIT);
+    k_timer_start(&sFunctionTimer, K_MSEC(timeoutInMs), K_NO_WAIT);
     mFunctionTimerActive = true;
 }
 
@@ -505,22 +605,23 @@
         break;
     }
 
-    sAppTask.UpdateClusterState(state, source);
+    // Handle changing attribute state in the application
+    Instance().UpdateClusterState(state, source);
 }
 
-void AppTask::PostEvent(AppEvent * aEvent)
+void AppTask::PostEvent(const AppEvent & event)
 {
-    if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT))
+    if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT) != 0)
     {
         LOG_INF("Failed to post event to app task event queue");
     }
 }
 
-void AppTask::DispatchEvent(AppEvent * aEvent)
+void AppTask::DispatchEvent(const AppEvent & event)
 {
-    if (aEvent->Handler)
+    if (event.Handler)
     {
-        aEvent->Handler(aEvent);
+        event.Handler(event);
     }
     else
     {
diff --git a/examples/lock-app/nrfconnect/main/BoltLockManager.cpp b/examples/lock-app/nrfconnect/main/BoltLockManager.cpp
index 0a86081..9f82f85 100644
--- a/examples/lock-app/nrfconnect/main/BoltLockManager.cpp
+++ b/examples/lock-app/nrfconnect/main/BoltLockManager.cpp
@@ -172,15 +172,20 @@
     // context of the application thread.
 
     AppEvent event;
-    event.Type               = AppEvent::kEventType_Timer;
+    event.Type               = AppEventType::Timer;
     event.TimerEvent.Context = static_cast<BoltLockManager *>(k_timer_user_data_get(timer));
     event.Handler            = BoltLockManager::ActuatorAppEventHandler;
-    GetAppTask().PostEvent(&event);
+    AppTask::Instance().PostEvent(event);
 }
 
-void BoltLockManager::ActuatorAppEventHandler(AppEvent * aEvent)
+void BoltLockManager::ActuatorAppEventHandler(const AppEvent & event)
 {
-    BoltLockManager * lock = static_cast<BoltLockManager *>(aEvent->TimerEvent.Context);
+    BoltLockManager * lock = static_cast<BoltLockManager *>(event.TimerEvent.Context);
+
+    if (!lock)
+    {
+        return;
+    }
 
     switch (lock->mState)
     {
diff --git a/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp b/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp
index 3b737aa..24b6b77 100644
--- a/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp
+++ b/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp
@@ -123,5 +123,5 @@
     // (kUsersManagement|kAccessSchedules|kRFIDCredentials|kPINCredentials) 0x113
     logOnFailure(DoorLock::Attributes::FeatureMap::Set(endpoint, 0x101), "feature map");
 
-    GetAppTask().UpdateClusterState(BoltLockMgr().GetState(), BoltLockManager::OperationSource::kUnspecified);
+    AppTask::Instance().UpdateClusterState(BoltLockMgr().GetState(), BoltLockManager::OperationSource::kUnspecified);
 }
diff --git a/examples/lock-app/nrfconnect/main/include/AppConfig.h b/examples/lock-app/nrfconnect/main/include/AppConfig.h
index 63e523e..0bfeb53 100644
--- a/examples/lock-app/nrfconnect/main/include/AppConfig.h
+++ b/examples/lock-app/nrfconnect/main/include/AppConfig.h
@@ -18,14 +18,26 @@
 
 #pragma once
 
+#include "BoardUtil.h"
+
 // ---- Lock Example App Config ----
 
-#define LOCK_BUTTON DK_BTN2
-#define LOCK_BUTTON_MASK DK_BTN2_MSK
 #define FUNCTION_BUTTON DK_BTN1
 #define FUNCTION_BUTTON_MASK DK_BTN1_MSK
+
+#if NUMBER_OF_BUTTONS == 2
+#define BLE_ADVERTISEMENT_START_AND_LOCK_BUTTON DK_BTN2
+#define BLE_ADVERTISEMENT_START_AND_LOCK_BUTTON_MASK DK_BTN2_MSK
+#else
+#define LOCK_BUTTON DK_BTN2
+#define LOCK_BUTTON_MASK DK_BTN2_MSK
 #define BLE_ADVERTISEMENT_START_BUTTON DK_BTN4
 #define BLE_ADVERTISEMENT_START_BUTTON_MASK DK_BTN4_MSK
+#endif
 
 #define SYSTEM_STATE_LED DK_LED1
 #define LOCK_STATE_LED DK_LED2
+#if NUMBER_OF_LEDS == 4
+#define FACTORY_RESET_SIGNAL_LED DK_LED3
+#define FACTORY_RESET_SIGNAL_LED1 DK_LED4
+#endif
diff --git a/examples/lock-app/nrfconnect/main/include/AppEvent.h b/examples/lock-app/nrfconnect/main/include/AppEvent.h
index a45ccfd..f171149 100644
--- a/examples/lock-app/nrfconnect/main/include/AppEvent.h
+++ b/examples/lock-app/nrfconnect/main/include/AppEvent.h
@@ -20,27 +20,33 @@
 
 #include <cstdint>
 
-#include "LEDWidget.h"
+#include "EventTypes.h"
 
-struct AppEvent;
-typedef void (*EventHandler)(AppEvent *);
+class LEDWidget;
+
+enum class AppEventType : uint8_t
+{
+    None = 0,
+    Button,
+    ButtonPushed,
+    ButtonReleased,
+    Timer,
+    UpdateLedState,
+    IdentifyStart,
+    IdentifyStop,
+    StartSMPAdvertising
+};
+
+enum class FunctionEvent : uint8_t
+{
+    NoneSelected   = 0,
+    SoftwareUpdate = 0,
+    FactoryReset,
+    AdvertisingStart
+};
 
 struct AppEvent
 {
-    enum AppEventTypes
-    {
-        kEventType_Button = 0,
-        kEventType_Timer,
-        kEventType_Lock,
-        kEventType_Install,
-        kEventType_UpdateLedState,
-#ifdef CONFIG_MCUMGR_SMP_BT
-        kEventType_StartSMPAdvertising,
-#endif
-    };
-
-    uint16_t Type;
-
     union
     {
         struct
@@ -63,5 +69,6 @@
         } UpdateLedStateEvent;
     };
 
+    AppEventType Type{ AppEventType::None };
     EventHandler Handler;
 };
diff --git a/examples/lock-app/nrfconnect/main/include/AppTask.h b/examples/lock-app/nrfconnect/main/include/AppTask.h
index 95c3ed2..a23ad0f 100644
--- a/examples/lock-app/nrfconnect/main/include/AppTask.h
+++ b/examples/lock-app/nrfconnect/main/include/AppTask.h
@@ -34,64 +34,56 @@
 #endif
 
 struct k_timer;
+struct Identify;
 
 class AppTask
 {
 public:
+    static AppTask & Instance()
+    {
+        static AppTask sAppTask;
+        return sAppTask;
+    };
+
     CHIP_ERROR StartApp();
 
-    void PostEvent(AppEvent * event);
     void UpdateClusterState(BoltLockManager::State state, BoltLockManager::OperationSource source);
 
-private:
-    friend AppTask & GetAppTask(void);
+    static void PostEvent(const AppEvent & event);
 
+    static void IdentifyStartHandler(Identify *);
+    static void IdentifyStopHandler(Identify *);
+
+private:
     CHIP_ERROR Init();
 
-    static void LockStateChanged(BoltLockManager::State state, BoltLockManager::OperationSource source);
+    void CancelTimer();
+    void StartTimer(uint32_t timeoutInMs);
 
-    void CancelTimer(void);
-
-    void DispatchEvent(AppEvent * event);
-
-    static void UpdateStatusLED();
-    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
-    static void UpdateLedStateEventHandler(AppEvent * aEvent);
-    static void FunctionTimerEventHandler(AppEvent * aEvent);
-    static void FunctionHandler(AppEvent * aEvent);
-    static void LockActionEventHandler(AppEvent * aEvent);
-    static void StartBLEAdvertisementHandler(AppEvent * aEvent);
+    static void DispatchEvent(const AppEvent & event);
+    static void FunctionTimerEventHandler(const AppEvent & event);
+    static void FunctionHandler(const AppEvent & event);
+    static void StartBLEAdvertisementAndLockActionEventHandler(const AppEvent & event);
+    static void LockActionEventHandler(const AppEvent & event);
+    static void StartBLEAdvertisementHandler(const AppEvent & event);
+    static void UpdateLedStateEventHandler(const AppEvent & event);
 
     static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+    static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged);
+    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
+    static void FunctionTimerTimeoutCallback(k_timer * timer);
+    static void UpdateStatusLED();
 
-    static void ButtonEventHandler(uint32_t buttons_state, uint32_t has_changed);
-    static void TimerEventHandler(k_timer * timer);
+    static void LockStateChanged(BoltLockManager::State state, BoltLockManager::OperationSource source);
 
 #ifdef CONFIG_MCUMGR_SMP_BT
     static void RequestSMPAdvertisingStart(void);
 #endif
 
-    void StartTimer(uint32_t aTimeoutInMs);
-
-    enum Function_t
-    {
-        kFunction_NoneSelected   = 0,
-        kFunction_SoftwareUpdate = 0,
-        kFunction_FactoryReset,
-
-        kFunction_Invalid
-    };
-
-    Function_t mFunction      = kFunction_NoneSelected;
+    FunctionEvent mFunction   = FunctionEvent::NoneSelected;
     bool mFunctionTimerActive = false;
-    static AppTask sAppTask;
 
 #if CONFIG_CHIP_FACTORY_DATA
     chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
 #endif
 };
-
-inline AppTask & GetAppTask(void)
-{
-    return AppTask::sAppTask;
-}
diff --git a/examples/lock-app/nrfconnect/main/include/BoltLockManager.h b/examples/lock-app/nrfconnect/main/include/BoltLockManager.h
index 940346e..8811723 100644
--- a/examples/lock-app/nrfconnect/main/include/BoltLockManager.h
+++ b/examples/lock-app/nrfconnect/main/include/BoltLockManager.h
@@ -82,7 +82,7 @@
     void SetState(State state, OperationSource source);
 
     static void ActuatorTimerEventHandler(k_timer * timer);
-    static void ActuatorAppEventHandler(AppEvent * aEvent);
+    static void ActuatorAppEventHandler(const AppEvent & aEvent);
     friend BoltLockManager & BoltLockMgr();
 
     State mState                             = State::kLockingCompleted;
diff --git a/examples/lock-app/nrfconnect/main/main.cpp b/examples/lock-app/nrfconnect/main/main.cpp
index a20f860..0c3b58e 100644
--- a/examples/lock-app/nrfconnect/main/main.cpp
+++ b/examples/lock-app/nrfconnect/main/main.cpp
@@ -27,7 +27,7 @@
 
 int main()
 {
-    CHIP_ERROR err = GetAppTask().StartApp();
+    CHIP_ERROR err = AppTask::Instance().StartApp();
 
     LOG_ERR("Exited with code %" CHIP_ERROR_FORMAT, err.Format());
     return err == CHIP_NO_ERROR ? EXIT_SUCCESS : EXIT_FAILURE;
diff --git a/examples/lock-app/nrfconnect/prj.conf b/examples/lock-app/nrfconnect/prj.conf
index e6d7571..676ae5a 100644
--- a/examples/lock-app/nrfconnect/prj.conf
+++ b/examples/lock-app/nrfconnect/prj.conf
@@ -14,31 +14,24 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults 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
-CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y
-
-# Bluetooth overrides
-CONFIG_BT_DEVICE_NAME="MatterLock"
-
-# Additional configs for debbugging experience.
-CONFIG_THREAD_NAME=y
-CONFIG_MPU_STACK_GUARD=y
-CONFIG_RESET_ON_FATAL_ERROR=n
-
-# CHIP configuration
+# Enable CHIP
+CONFIG_CHIP=y
 CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
 # 32774 == 0x8006 (example lock-app)
 CONFIG_CHIP_DEVICE_PRODUCT_ID=32774
+CONFIG_STD_CPP14=y
+
+# Add support for LEDs and buttons on Nordic development kits
+CONFIG_DK_LIBRARY=y
+
+# Bluetooth Low Energy configuration
+CONFIG_BT_DEVICE_NAME="MatterLock"
+
+# Other settings
+CONFIG_THREAD_NAME=y
+CONFIG_MPU_STACK_GUARD=y
+CONFIG_RESET_ON_FATAL_ERROR=n
diff --git a/examples/lock-app/nrfconnect/prj_no_dfu.conf b/examples/lock-app/nrfconnect/prj_no_dfu.conf
index 9b0339d..839f839 100644
--- a/examples/lock-app/nrfconnect/prj_no_dfu.conf
+++ b/examples/lock-app/nrfconnect/prj_no_dfu.conf
@@ -14,26 +14,24 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32774 == 0x8006 (example lock-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32774
+CONFIG_STD_CPP14=y
+
 # 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
-CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y
-
-# Bluetooth overrides
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterLock"
 
-# Additional configs for debbugging experience.
+# Other settings
 CONFIG_THREAD_NAME=y
 CONFIG_MPU_STACK_GUARD=y
 CONFIG_RESET_ON_FATAL_ERROR=n
@@ -41,7 +39,5 @@
 # Disable Matter OTA DFU
 CONFIG_CHIP_OTA_REQUESTOR=n
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32774 == 0x8006 (example lock-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32774
+# Disable QSPI NOR
+CONFIG_CHIP_QSPI_NOR=n
diff --git a/examples/lock-app/nrfconnect/prj_release.conf b/examples/lock-app/nrfconnect/prj_release.conf
index a71e975..b41ed9e 100644
--- a/examples/lock-app/nrfconnect/prj_release.conf
+++ b/examples/lock-app/nrfconnect/prj_release.conf
@@ -14,33 +14,26 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32774 == 0x8006 (example lock-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32774
+CONFIG_STD_CPP14=y
+
 # 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
-CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT=y
-
-# Bluetooth overrides
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterLock"
 
 # Enable system reset on fatal error
 CONFIG_RESET_ON_FATAL_ERROR=y
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32774 == 0x8006 (example lock-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32774
-
 # Suspend devices when the CPU goes into sleep
 CONFIG_PM_DEVICE=y
 
@@ -52,7 +45,8 @@
 CONFIG_SERIAL=n
 CONFIG_LOG=n
 CONFIG_LOG_MODE_MINIMAL=n
-CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_ASSERT_VERBOSE=n
+CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_PRINTK=n
+CONFIG_PRINTK_SYNC=n
 CONFIG_THREAD_NAME=n
diff --git a/examples/platform/nrfconnect/Rpc.cpp b/examples/platform/nrfconnect/Rpc.cpp
index c857cc3..c996106 100644
--- a/examples/platform/nrfconnect/Rpc.cpp
+++ b/examples/platform/nrfconnect/Rpc.cpp
@@ -109,7 +109,8 @@
 public:
     pw::Status Event(const chip_rpc_ButtonEvent & request, pw_protobuf_Empty & response) override
     {
-        GetAppTask().ButtonEventHandler(request.pushed << request.idx /* button_state */, 1 << request.idx /* has_changed */);
+        AppTask::Instance().ButtonEventHandler(request.pushed << request.idx /* button_state */,
+                                               1 << request.idx /* has_changed */);
         return pw::OkStatus();
     }
 };
diff --git a/examples/platform/nrfconnect/doc/images/nrf7002dk.jpg b/examples/platform/nrfconnect/doc/images/nrf7002dk.jpg
new file mode 100644
index 0000000..1308472
--- /dev/null
+++ b/examples/platform/nrfconnect/doc/images/nrf7002dk.jpg
Binary files differ
diff --git a/examples/platform/nrfconnect/util/PWMDevice.cpp b/examples/platform/nrfconnect/util/PWMDevice.cpp
index 43e3600..b51d33c 100644
--- a/examples/platform/nrfconnect/util/PWMDevice.cpp
+++ b/examples/platform/nrfconnect/util/PWMDevice.cpp
@@ -112,16 +112,21 @@
 {
     LOG_INF("Setting brightness level to %u", aLevel);
     mLevel = aLevel;
-    UpdateLight();
+    ApplyLevel();
 }
 
 void PWMDevice::Set(bool aOn)
 {
     mState = aOn ? kState_On : kState_Off;
-    UpdateLight();
+    ApplyLevel();
 }
 
-void PWMDevice::UpdateLight()
+void PWMDevice::SuppressOutput()
+{
+    pwm_set_pulse_dt(mPwmDevice, 0);
+}
+
+void PWMDevice::ApplyLevel()
 {
     const uint8_t maxEffectiveLevel = mMaxLevel - mMinLevel;
     const uint8_t effectiveLevel    = mState == kState_On ? chip::min<uint8_t>(mLevel - mMinLevel, maxEffectiveLevel) : 0;
diff --git a/examples/platform/nrfconnect/util/include/BoardUtil.h b/examples/platform/nrfconnect/util/include/BoardUtil.h
new file mode 100644
index 0000000..ccd8e69
--- /dev/null
+++ b/examples/platform/nrfconnect/util/include/BoardUtil.h
@@ -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.
+ */
+
+#pragma once
+
+#include <zephyr/devicetree.h>
+
+#define LEDS_NODE_ID DT_PATH(leds)
+#define BUTTONS_NODE_ID DT_PATH(buttons)
+#define INCREMENT_BY_ONE(button_or_led) +1
+#define NUMBER_OF_LEDS (0 DT_FOREACH_CHILD(LEDS_NODE_ID, INCREMENT_BY_ONE))
+#define NUMBER_OF_BUTTONS (0 DT_FOREACH_CHILD(BUTTONS_NODE_ID, INCREMENT_BY_ONE))
diff --git a/examples/platform/nrfconnect/util/include/EventTypes.h b/examples/platform/nrfconnect/util/include/EventTypes.h
new file mode 100644
index 0000000..557254c
--- /dev/null
+++ b/examples/platform/nrfconnect/util/include/EventTypes.h
@@ -0,0 +1,21 @@
+/*
+ *    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
+
+struct AppEvent; // Needs to be implemented in the application code.
+using EventHandler = void (*)(const AppEvent &);
diff --git a/examples/platform/nrfconnect/util/include/LEDUtil.h b/examples/platform/nrfconnect/util/include/LEDUtil.h
index 3066f15..8f25fc7 100644
--- a/examples/platform/nrfconnect/util/include/LEDUtil.h
+++ b/examples/platform/nrfconnect/util/include/LEDUtil.h
@@ -21,13 +21,13 @@
 
 // A lightweight wrapper for unused LEDs
 template <uint8_t size>
-class UnusedLedsWrapper
+class FactoryResetLEDsWrapper
 {
 public:
     using Gpio = uint32_t;
     using Leds = std::array<std::pair<Gpio, LEDWidget>, size>;
 
-    explicit UnusedLedsWrapper(std::array<Gpio, size> aLeds)
+    explicit FactoryResetLEDsWrapper(std::array<Gpio, size> aLeds)
     {
         auto idx{ 0 };
         for (const auto & led : aLeds)
diff --git a/examples/platform/nrfconnect/util/include/PWMDevice.h b/examples/platform/nrfconnect/util/include/PWMDevice.h
index 250383e..7b1ff53 100644
--- a/examples/platform/nrfconnect/util/include/PWMDevice.h
+++ b/examples/platform/nrfconnect/util/include/PWMDevice.h
@@ -49,6 +49,8 @@
     bool InitiateAction(Action_t aAction, int32_t aActor, uint8_t * aValue);
     void SetCallbacks(PWMCallback aActionInitiatedClb, PWMCallback aActionCompletedClb);
     const device * GetDevice() { return mPwmDevice->dev; }
+    void SuppressOutput();
+    void ApplyLevel();
 
 private:
     State_t mState;
@@ -63,5 +65,4 @@
 
     void Set(bool aOn);
     void SetLevel(uint8_t aLevel);
-    void UpdateLight();
 };
diff --git a/examples/pump-app/nrfconnect/Kconfig b/examples/pump-app/nrfconnect/Kconfig
index 94a99f9..ffa1e2c 100644
--- a/examples/pump-app/nrfconnect/Kconfig
+++ b/examples/pump-app/nrfconnect/Kconfig
@@ -13,7 +13,20 @@
 #    See the License for the specific language governing permissions and
 #    limitations under the License.
 #
-mainmenu "Matter nRF Connect Lighting Example Application"
+mainmenu "Matter nRF Connect Pump Application"
+
+# Sample configuration used for Thread networking
+if NET_L2_OPENTHREAD
+
+choice OPENTHREAD_NORDIC_LIBRARY_CONFIGURATION
+	default OPENTHREAD_NORDIC_LIBRARY_MTD
+endchoice
+
+choice OPENTHREAD_DEVICE_TYPE
+	default OPENTHREAD_MTD
+endchoice
+
+endif # NET_L2_OPENTHREAD
 
 rsource "../../../config/nrfconnect/chip-module/Kconfig.features"
 rsource "../../../config/nrfconnect/chip-module/Kconfig.defaults"
diff --git a/examples/pump-app/nrfconnect/README.md b/examples/pump-app/nrfconnect/README.md
index 1ea3730..c4a02dc 100644
--- a/examples/pump-app/nrfconnect/README.md
+++ b/examples/pump-app/nrfconnect/README.md
@@ -54,13 +54,18 @@
 to read more about the platform structure and dependencies.
 
 The Matter device that runs the pump 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.
+controller device over the Thread protocol. By default, the Matter accessory
+device has IPv6 networking disabled. You must pair it with the Matter controller
+over Bluetooth® LE to get the configuration from the controller to use the
+device within a Thread or Wi-Fi network. You have to make the device
+discoverable manually (for security reasons). See
+[Bluetooth LE advertising](#bluetooth-le-advertising) to learn how to do this.
+The controller must get the commissioning information from the Matter accessory
+device and provision the device into the network.
 
-The example can be configured to use the secure bootloader and utilize it for
-performing over-the-air Device Firmware Upgrade using Bluetooth LE.
+You can test this application remotely over the Thread or the Wi-Fi protocol,
+which in either case requires more devices, including a Matter controller that
+you can configure either on a PC or a mobile device.
 
 ### Bluetooth LE advertising
 
@@ -187,8 +192,8 @@
     Bluetooth LE.
 
 -   _Short Flash Off (950ms on/50ms off)_ &mdash; The device is fully
-    provisioned, but does not yet have full Thread network or service
-    connectivity.
+    provisioned, but does not yet have full connectivity for Thread or Wi-Fi
+    network.
 
 -   _Solid On_ &mdash; The device is fully provisioned and has full Thread
     network and service connectivity.
diff --git a/examples/pump-app/nrfconnect/main/AppTask.cpp b/examples/pump-app/nrfconnect/main/AppTask.cpp
index d8ccc47..209eaa0 100644
--- a/examples/pump-app/nrfconnect/main/AppTask.cpp
+++ b/examples/pump-app/nrfconnect/main/AppTask.cpp
@@ -18,6 +18,7 @@
 
 #include "AppTask.h"
 #include "AppConfig.h"
+#include "LEDUtil.h"
 #include "LEDWidget.h"
 #include "PumpManager.h"
 
@@ -45,45 +46,54 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
+
 using namespace ::chip;
 using namespace ::chip::app::Clusters;
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceLayer;
 
-#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
-#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
-#define APP_EVENT_QUEUE_SIZE 10
-#define BUTTON_PUSH_EVENT 1
-#define BUTTON_RELEASE_EVENT 0
-
-#define PCC_CLUSTER_ENDPOINT 1
-#define ONOFF_CLUSTER_ENDPOINT 1
-
 namespace {
+constexpr uint32_t kFactoryResetTriggerTimeout      = 3000;
+constexpr uint32_t kFactoryResetCancelWindowTimeout = 3000;
+constexpr size_t kAppEventQueueSize                 = 10;
+constexpr EndpointId kPccClusterEndpoint            = 1;
+constexpr EndpointId kOnOffClusterEndpoint          = 1;
 
 // NOTE! This key is for test/certification only and should not be available in production devices!
 // If CONFIG_CHIP_FACTORY_DATA is enabled, this value is read from the factory data.
 uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                                                                                    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
 
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
-K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), APP_EVENT_QUEUE_SIZE, alignof(AppEvent));
+K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
 k_timer sFunctionTimer;
 
 LEDWidget sStatusLED;
 LEDWidget sPumpStateLED;
-LEDWidget sUnusedLED;
-LEDWidget sUnusedLED_1;
+FactoryResetLEDsWrapper<2> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTORY_RESET_SIGNAL_LED1 } };
 
-bool sIsThreadProvisioned = false;
-bool sIsThreadEnabled     = false;
-bool sHaveBLEConnections  = false;
+bool sIsNetworkProvisioned = false;
+bool sIsNetworkEnabled     = false;
+bool sHaveBLEConnections   = false;
 
 chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
 
 } // namespace
 
-AppTask AppTask::sAppTask;
+namespace LedConsts {
+constexpr uint32_t kBlinkRate_ms{ 500 };
+namespace StatusLed {
+namespace Unprovisioned {
+constexpr uint32_t kOn_ms{ 100 };
+constexpr uint32_t kOff_ms{ kOn_ms };
+} // namespace Unprovisioned
+namespace Provisioned {
+constexpr uint32_t kOn_ms{ 50 };
+constexpr uint32_t kOff_ms{ 950 };
+} // namespace Provisioned
+
+} // namespace StatusLed
+} // namespace LedConsts
 
 CHIP_ERROR AppTask::Init()
 {
@@ -130,9 +140,6 @@
     sPumpStateLED.Init(PUMP_STATE_LED);
     sPumpStateLED.Set(!PumpMgr().IsStopped());
 
-    sUnusedLED.Init(DK_LED3);
-    sUnusedLED_1.Init(DK_LED4);
-
     UpdateStatusLED();
 
     PumpMgr().Init();
@@ -147,7 +154,7 @@
     }
 
     // Initialize function button timer
-    k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr);
+    k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr);
     k_timer_user_data_set(&sFunctionTimer, this);
 
 #ifdef CONFIG_MCUMGR_SMP_BT
@@ -209,100 +216,104 @@
     while (true)
     {
         k_msgq_get(&sAppEventQueue, &event, K_FOREVER);
-        DispatchEvent(&event);
+        DispatchEvent(event);
     }
 
     return CHIP_NO_ERROR;
 }
 
-void AppTask::StartActionEventHandler(AppEvent * aEvent)
+void AppTask::StartActionEventHandler(const AppEvent & event)
 {
     PumpManager::Action_t action = PumpManager::INVALID_ACTION;
     int32_t actor                = 0;
 
-    if (aEvent->Type == AppEvent::kEventType_Start)
+    if (event.Type == AppEventType::Start)
     {
-        action = static_cast<PumpManager::Action_t>(aEvent->StartEvent.Action);
-        actor  = aEvent->StartEvent.Actor;
+        action = static_cast<PumpManager::Action_t>(event.StartEvent.Action);
+        actor  = event.StartEvent.Actor;
     }
-    else if (aEvent->Type == AppEvent::kEventType_Button)
+    else if (event.Type == AppEventType::Button)
     {
         action = PumpMgr().IsStopped() ? PumpManager::START_ACTION : PumpManager::STOP_ACTION;
-        actor  = AppEvent::kEventType_Button;
+        actor  = static_cast<uint8_t>(AppEventType::Button);
     }
 
     if (action != PumpManager::INVALID_ACTION && !PumpMgr().InitiateAction(actor, action))
         LOG_INF("Action is already in progress or active.");
 }
 
-void AppTask::ButtonEventHandler(uint32_t button_state, uint32_t has_changed)
-{
-    AppEvent button_event;
-    button_event.Type = AppEvent::kEventType_Button;
-
-    if (START_BUTTON_MASK & button_state & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = START_BUTTON;
-        button_event.ButtonEvent.Action = BUTTON_PUSH_EVENT;
-        button_event.Handler            = StartActionEventHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-
-    if (FUNCTION_BUTTON_MASK & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = FUNCTION_BUTTON;
-        button_event.ButtonEvent.Action = (FUNCTION_BUTTON_MASK & button_state) ? BUTTON_PUSH_EVENT : BUTTON_RELEASE_EVENT;
-        button_event.Handler            = FunctionHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-
-    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & button_state & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
-        button_event.ButtonEvent.Action = BUTTON_PUSH_EVENT;
-        button_event.Handler            = StartBLEAdvertisementHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-}
-
-void AppTask::TimerEventHandler(k_timer * timer)
+void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)
 {
     AppEvent event;
-    event.Type               = AppEvent::kEventType_Timer;
-    event.TimerEvent.Context = k_timer_user_data_get(timer);
-    event.Handler            = FunctionTimerEventHandler;
-    sAppTask.PostEvent(&event);
+    event.Type = AppEventType::Button;
+
+    if (START_BUTTON_MASK & buttonState & hasChanged)
+    {
+        event.ButtonEvent.PinNo  = START_BUTTON;
+        event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::Button);
+        event.Handler            = StartActionEventHandler;
+        PostEvent(event);
+    }
+
+    if (FUNCTION_BUTTON_MASK & hasChanged)
+    {
+        event.ButtonEvent.PinNo = FUNCTION_BUTTON;
+        event.ButtonEvent.Action =
+            static_cast<uint8_t>((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased);
+        event.Handler = FunctionHandler;
+        PostEvent(event);
+    }
+
+    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged)
+    {
+        event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
+        event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
+        event.Handler            = StartBLEAdvertisementHandler;
+        PostEvent(event);
+    }
 }
 
-void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
+void AppTask::FunctionTimerTimeoutCallback(k_timer * timer)
 {
-    if (aEvent->Type != AppEvent::kEventType_Timer)
+    if (!timer)
+    {
+        return;
+    }
+
+    AppEvent event;
+    event.Type               = AppEventType::Timer;
+    event.TimerEvent.Context = k_timer_user_data_get(timer);
+    event.Handler            = FunctionTimerEventHandler;
+    PostEvent(event);
+}
+
+void AppTask::FunctionTimerEventHandler(const AppEvent & event)
+{
+    if (event.Type != AppEventType::Timer)
         return;
 
-    // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT, initiate factory reset
-    if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+    // If we reached here, the button was held past kFactoryResetTriggerTimeout, initiate factory reset
+    if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
     {
-        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_TRIGGER_TIMEOUT);
+        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", kFactoryResetTriggerTimeout);
 
-        // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to cancel, if required.
-        sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
-        sAppTask.mFunction = kFunction_FactoryReset;
+        // Start timer for kFactoryResetCancelWindowTimeout to allow user to cancel, if required.
+        Instance().StartTimer(kFactoryResetCancelWindowTimeout);
+        Instance().mFunction = FunctionEvent::FactoryReset;
 
+#ifdef CONFIG_STATE_LEDS
         // Turn off all LEDs before starting blink to make sure blink is co-ordinated.
         sStatusLED.Set(false);
-        sPumpStateLED.Set(false);
-        sUnusedLED_1.Set(false);
-        sUnusedLED.Set(false);
+        sFactoryResetLEDs.Set(false);
 
-        sStatusLED.Blink(500);
-        sPumpStateLED.Blink(500);
-        sUnusedLED.Blink(500);
-        sUnusedLED_1.Blink(500);
+        sStatusLED.Blink(LedConsts::kBlinkRate_ms);
+        sFactoryResetLEDs.Blink(LedConsts::kBlinkRate_ms);
+#endif
     }
-    else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+    else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
     {
         // Actually trigger Factory Reset
-        sAppTask.mFunction = kFunction_NoneSelected;
+        Instance().mFunction = FunctionEvent::NoneSelected;
 
         chip::Server::GetInstance().ScheduleFactoryReset();
     }
@@ -312,65 +323,62 @@
 void AppTask::RequestSMPAdvertisingStart(void)
 {
     AppEvent event;
-    event.Type    = AppEvent::kEventType_StartSMPAdvertising;
-    event.Handler = [](AppEvent *) { GetDFUOverSMP().StartBLEAdvertising(); };
-    sAppTask.PostEvent(&event);
+    event.Type    = AppEventType::StartSMPAdvertising;
+    event.Handler = [](const AppEvent &) { GetDFUOverSMP().StartBLEAdvertising(); };
+    PostEvent(event);
 }
 #endif
 
-void AppTask::FunctionHandler(AppEvent * aEvent)
+void AppTask::FunctionHandler(const AppEvent & event)
 {
-    if (aEvent->ButtonEvent.PinNo != FUNCTION_BUTTON)
+    if (event.ButtonEvent.PinNo != FUNCTION_BUTTON)
         return;
 
-    // To trigger software update: press the FUNCTION_BUTTON button briefly (< FACTORY_RESET_TRIGGER_TIMEOUT)
     // To initiate factory reset: press the FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT + FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
     // All LEDs start blinking after FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
     // To cancel factory reset: release the FUNCTION_BUTTON once all LEDs start blinking within the
     // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
-    if (aEvent->ButtonEvent.Action == BUTTON_PUSH_EVENT)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
     {
-        if (!sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_NoneSelected)
+        if (!Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::NoneSelected)
         {
-            sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+            Instance().StartTimer(kFactoryResetTriggerTimeout);
 
-            sAppTask.mFunction = kFunction_SoftwareUpdate;
+            Instance().mFunction = FunctionEvent::SoftwareUpdate;
         }
     }
     else
     {
         // If the button was released before factory reset got initiated, trigger a software update.
-        if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+        if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
         {
-            sAppTask.CancelTimer();
-            sAppTask.mFunction = kFunction_NoneSelected;
+            Instance().CancelTimer();
 
 #ifdef CONFIG_MCUMGR_SMP_BT
             GetDFUOverSMP().StartServer();
 #else
             LOG_INF("Software update is disabled");
 #endif
+            Instance().mFunction = FunctionEvent::NoneSelected;
         }
-        else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+        else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
         {
-            sUnusedLED.Set(false);
-            sUnusedLED_1.Set(false);
-
-            // Set pump state LED back to show state of pump.
-            sPumpStateLED.Set(!PumpMgr().IsStopped());
+            sFactoryResetLEDs.Set(false);
 
             UpdateStatusLED();
-            sAppTask.CancelTimer();
-
-            // Change the function to none selected since factory reset has been canceled.
-            sAppTask.mFunction = kFunction_NoneSelected;
-
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
             LOG_INF("Factory Reset has been Canceled");
         }
+        else if (Instance().mFunctionTimerActive)
+        {
+            CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
+        }
     }
 }
 
-void AppTask::StartBLEAdvertisementHandler(AppEvent *)
+void AppTask::StartBLEAdvertisementHandler(const AppEvent &)
 {
     if (Server::GetInstance().GetFabricTable().FabricCount() != 0)
     {
@@ -390,45 +398,47 @@
     }
 }
 
-void AppTask::UpdateLedStateEventHandler(AppEvent * aEvent)
+void AppTask::UpdateLedStateEventHandler(const AppEvent & event)
 {
-    if (aEvent->Type == AppEvent::kEventType_UpdateLedState)
+    if (event.Type == AppEventType::UpdateLedState)
     {
-        aEvent->UpdateLedStateEvent.LedWidget->UpdateState();
+        event.UpdateLedStateEvent.LedWidget->UpdateState();
     }
 }
 
 void AppTask::LEDStateUpdateHandler(LEDWidget & ledWidget)
 {
     AppEvent event;
-    event.Type                          = AppEvent::kEventType_UpdateLedState;
+    event.Type                          = AppEventType::UpdateLedState;
     event.Handler                       = UpdateLedStateEventHandler;
     event.UpdateLedStateEvent.LedWidget = &ledWidget;
-    sAppTask.PostEvent(&event);
+    PostEvent(event);
 }
 
 void AppTask::UpdateStatusLED()
 {
-    /* Update the status LED.
-     *
-     * If thread and service provisioned, keep the LED On constantly.
-     *
-     * If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
-     * rate of 100ms.
-     *
-     * Otherwise, blink the LED On for a very short time. */
-    if (sIsThreadProvisioned && sIsThreadEnabled)
+#ifdef CONFIG_STATE_LEDS
+    // Update the status LED.
+    //
+    // If thread and service provisioned, keep the LED On constantly.
+    //
+    // If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
+    // rate of 100ms.
+    //
+    // Otherwise, blink the LED On for a very short time.
+    if (sIsNetworkProvisioned && sIsNetworkEnabled)
     {
         sStatusLED.Set(true);
     }
     else if (sHaveBLEConnections)
     {
-        sStatusLED.Blink(100, 100);
+        sStatusLED.Blink(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms);
     }
     else
     {
-        sStatusLED.Blink(50, 950);
+        sStatusLED.Blink(LedConsts::StatusLed::Provisioned::kOn_ms, LedConsts::StatusLed::Provisioned::kOff_ms);
     }
+#endif
 }
 
 void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */)
@@ -436,21 +446,8 @@
     switch (event->Type)
     {
     case DeviceEventType::kCHIPoBLEAdvertisingChange:
-        if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
-        {
 #ifdef CONFIG_CHIP_NFC_COMMISSIONING
-            NFCMgr().StopTagEmulation();
-#endif
-#ifdef CONFIG_MCUMGR_SMP_BT
-            // After CHIPoBLE advertising stop, start advertising SMP in case Thread is enabled or there are no active CHIPoBLE
-            // connections (exclude the case when CHIPoBLE advertising is stopped on the connection time)
-            if (GetDFUOverSMP().IsEnabled() &&
-                (ConnectivityMgr().IsThreadProvisioned() || ConnectivityMgr().NumBLEConnections() == 0))
-                sAppTask.RequestSMPAdvertisingStart();
-#endif
-        }
-#ifdef CONFIG_CHIP_NFC_COMMISSIONING
-        else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
+        if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
         {
             if (NFCMgr().IsTagEmulationStarted())
             {
@@ -461,13 +458,17 @@
                 ShareQRCodeOverNFC(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
             }
         }
+        else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
+        {
+            NFCMgr().StopTagEmulation();
+        }
 #endif
         sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
         UpdateStatusLED();
         break;
     case DeviceEventType::kThreadStateChange:
-        sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
-        sIsThreadEnabled     = ConnectivityMgr().IsThreadEnabled();
+        sIsNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsThreadEnabled();
         UpdateStatusLED();
         break;
     case DeviceEventType::kDnssdPlatformInitialized:
@@ -483,24 +484,24 @@
 void AppTask::CancelTimer()
 {
     k_timer_stop(&sFunctionTimer);
-    mFunctionTimerActive = false;
+    Instance().mFunctionTimerActive = false;
 }
 
 void AppTask::StartTimer(uint32_t aTimeoutInMs)
 {
     k_timer_start(&sFunctionTimer, K_MSEC(aTimeoutInMs), K_NO_WAIT);
-    mFunctionTimerActive = true;
+    Instance().mFunctionTimerActive = true;
 }
 
-void AppTask::ActionInitiated(PumpManager::Action_t aAction, int32_t aActor)
+void AppTask::ActionInitiated(PumpManager::Action_t action, int32_t actor)
 {
     // If the action has been initiated by the pump, update the pump trait
     // and start flashing the LEDs rapidly to indicate action initiation.
-    if (aAction == PumpManager::START_ACTION)
+    if (action == PumpManager::START_ACTION)
     {
         LOG_INF("Pump Start Action has been initiated");
     }
-    else if (aAction == PumpManager::STOP_ACTION)
+    else if (action == PumpManager::STOP_ACTION)
     {
         LOG_INF("Pump Stop Action has been initiated");
     }
@@ -508,51 +509,51 @@
     sPumpStateLED.Blink(50, 50);
 }
 
-void AppTask::ActionCompleted(PumpManager::Action_t aAction, int32_t aActor)
+void AppTask::ActionCompleted(PumpManager::Action_t action, int32_t actor)
 {
     // If the action has been completed by the pump, update the pump trait.
     // Turn on the pump state LED if in a STARTED state OR
     // Turn off the pump state LED if in a STOPPED state.
-    if (aAction == PumpManager::START_ACTION)
+    if (action == PumpManager::START_ACTION)
     {
         LOG_INF("Pump Start Action has been completed");
         sPumpStateLED.Set(true);
     }
-    else if (aAction == PumpManager::STOP_ACTION)
+    else if (action == PumpManager::STOP_ACTION)
     {
         LOG_INF("Pump Stop Action has been completed");
         sPumpStateLED.Set(false);
     }
 
-    if (aActor == AppEvent::kEventType_Button)
+    if (actor == static_cast<uint8_t>(AppEventType::Button))
     {
-        sAppTask.UpdateClusterState();
+        Instance().UpdateClusterState();
     }
 }
 
-void AppTask::PostStartActionRequest(int32_t aActor, PumpManager::Action_t aAction)
+void AppTask::PostStartActionRequest(int32_t actor, PumpManager::Action_t action)
 {
     AppEvent event;
-    event.Type              = AppEvent::kEventType_Start;
-    event.StartEvent.Actor  = aActor;
-    event.StartEvent.Action = aAction;
+    event.Type              = AppEventType::Start;
+    event.StartEvent.Actor  = actor;
+    event.StartEvent.Action = action;
     event.Handler           = StartActionEventHandler;
-    PostEvent(&event);
+    PostEvent(event);
 }
 
-void AppTask::PostEvent(AppEvent * aEvent)
+void AppTask::PostEvent(const AppEvent & event)
 {
-    if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT))
+    if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT) != 0)
     {
         LOG_INF("Failed to post event to app task event queue");
     }
 }
 
-void AppTask::DispatchEvent(AppEvent * aEvent)
+void AppTask::DispatchEvent(const AppEvent & event)
 {
-    if (aEvent->Handler)
+    if (event.Handler)
     {
-        aEvent->Handler(aEvent);
+        event.Handler(event);
     }
     else
     {
@@ -570,98 +571,98 @@
 
     bool onOffState = !PumpMgr().IsStopped();
 
-    status = OnOff::Attributes::OnOff::Set(ONOFF_CLUSTER_ENDPOINT, onOffState);
+    status = OnOff::Attributes::OnOff::Set(kOnOffClusterEndpoint, onOffState);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating On/Off state  %x", status);
     }
 
     int16_t maxPressure = PumpMgr().GetMaxPressure();
-    status              = PumpConfigurationAndControl::Attributes::MaxPressure::Set(PCC_CLUSTER_ENDPOINT, maxPressure);
+    status              = PumpConfigurationAndControl::Attributes::MaxPressure::Set(kPccClusterEndpoint, maxPressure);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MaxPressure  %x", status);
     }
 
     uint16_t maxSpeed = PumpMgr().GetMaxSpeed();
-    status            = PumpConfigurationAndControl::Attributes::MaxSpeed::Set(PCC_CLUSTER_ENDPOINT, maxSpeed);
+    status            = PumpConfigurationAndControl::Attributes::MaxSpeed::Set(kPccClusterEndpoint, maxSpeed);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MaxSpeed  %x", status);
     }
 
     uint16_t maxFlow = PumpMgr().GetMaxFlow();
-    status           = PumpConfigurationAndControl::Attributes::MaxFlow::Set(PCC_CLUSTER_ENDPOINT, maxFlow);
+    status           = PumpConfigurationAndControl::Attributes::MaxFlow::Set(kPccClusterEndpoint, maxFlow);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MaxFlow  %x", status);
     }
 
     int16_t minConstPress = PumpMgr().GetMinConstPressure();
-    status                = PumpConfigurationAndControl::Attributes::MinConstPressure::Set(PCC_CLUSTER_ENDPOINT, minConstPress);
+    status                = PumpConfigurationAndControl::Attributes::MinConstPressure::Set(kPccClusterEndpoint, minConstPress);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MinConstPressure  %x", status);
     }
 
     int16_t maxConstPress = PumpMgr().GetMaxConstPressure();
-    status                = PumpConfigurationAndControl::Attributes::MaxConstPressure::Set(PCC_CLUSTER_ENDPOINT, maxConstPress);
+    status                = PumpConfigurationAndControl::Attributes::MaxConstPressure::Set(kPccClusterEndpoint, maxConstPress);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MaxConstPressure  %x", status);
     }
 
     int16_t minCompPress = PumpMgr().GetMinCompPressure();
-    status               = PumpConfigurationAndControl::Attributes::MinCompPressure::Set(PCC_CLUSTER_ENDPOINT, minCompPress);
+    status               = PumpConfigurationAndControl::Attributes::MinCompPressure::Set(kPccClusterEndpoint, minCompPress);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MinCompPressure  %x", status);
     }
 
     int16_t maxCompPress = PumpMgr().GetMaxCompPressure();
-    status               = PumpConfigurationAndControl::Attributes::MaxCompPressure::Set(PCC_CLUSTER_ENDPOINT, maxCompPress);
+    status               = PumpConfigurationAndControl::Attributes::MaxCompPressure::Set(kPccClusterEndpoint, maxCompPress);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MaxCompPressure  %x", status);
     }
 
     uint16_t minConstSpeed = PumpMgr().GetMinConstSpeed();
-    status                 = PumpConfigurationAndControl::Attributes::MinConstSpeed::Set(PCC_CLUSTER_ENDPOINT, minConstSpeed);
+    status                 = PumpConfigurationAndControl::Attributes::MinConstSpeed::Set(kPccClusterEndpoint, minConstSpeed);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MinConstSpeed  %x", status);
     }
 
     uint16_t maxConstSpeed = PumpMgr().GetMaxConstSpeed();
-    status                 = PumpConfigurationAndControl::Attributes::MaxConstSpeed::Set(PCC_CLUSTER_ENDPOINT, maxConstSpeed);
+    status                 = PumpConfigurationAndControl::Attributes::MaxConstSpeed::Set(kPccClusterEndpoint, maxConstSpeed);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MaxConstSpeed  %x", status);
     }
 
     uint16_t minConstFlow = PumpMgr().GetMinConstFlow();
-    status                = PumpConfigurationAndControl::Attributes::MinConstFlow::Set(PCC_CLUSTER_ENDPOINT, minConstFlow);
+    status                = PumpConfigurationAndControl::Attributes::MinConstFlow::Set(kPccClusterEndpoint, minConstFlow);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MinConstFlow  %x", status);
     }
 
     uint16_t maxConstFlow = PumpMgr().GetMaxConstFlow();
-    status                = PumpConfigurationAndControl::Attributes::MaxConstFlow::Set(PCC_CLUSTER_ENDPOINT, maxConstFlow);
+    status                = PumpConfigurationAndControl::Attributes::MaxConstFlow::Set(kPccClusterEndpoint, maxConstFlow);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MaxConstFlow  %x", status);
     }
 
     int16_t minConstTemp = PumpMgr().GetMinConstTemp();
-    status               = PumpConfigurationAndControl::Attributes::MinConstTemp::Set(PCC_CLUSTER_ENDPOINT, minConstTemp);
+    status               = PumpConfigurationAndControl::Attributes::MinConstTemp::Set(kPccClusterEndpoint, minConstTemp);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MinConstTemp  %x", status);
     }
 
     int16_t maxConstTemp = PumpMgr().GetMaxConstTemp();
-    status               = PumpConfigurationAndControl::Attributes::MaxConstTemp::Set(PCC_CLUSTER_ENDPOINT, maxConstTemp);
+    status               = PumpConfigurationAndControl::Attributes::MaxConstTemp::Set(kPccClusterEndpoint, maxConstTemp);
     if (status != EMBER_ZCL_STATUS_SUCCESS)
     {
         ChipLogError(NotSpecified, "ERR: Updating MaxConstTemp  %x", status);
diff --git a/examples/pump-app/nrfconnect/main/PumpManager.cpp b/examples/pump-app/nrfconnect/main/PumpManager.cpp
index e7c0b62..f24bd32 100644
--- a/examples/pump-app/nrfconnect/main/PumpManager.cpp
+++ b/examples/pump-app/nrfconnect/main/PumpManager.cpp
@@ -25,7 +25,7 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 static k_timer sStartTimer;
 
@@ -130,15 +130,15 @@
     // once sStartTimer expires. Post an event to apptask queue with the actual handler
     // so that the event can be handled in the context of the apptask.
     AppEvent event;
-    event.Type               = AppEvent::kEventType_Timer;
+    event.Type               = AppEventType::Timer;
     event.TimerEvent.Context = pump;
     event.Handler            = pump->mAutoStartTimerArmed ? AutoRestartTimerEventHandler : PumpStartTimerEventHandler;
-    GetAppTask().PostEvent(&event);
+    AppTask::Instance().PostEvent(event);
 }
 
-void PumpManager::AutoRestartTimerEventHandler(AppEvent * aEvent)
+void PumpManager::AutoRestartTimerEventHandler(const AppEvent & aEvent)
 {
-    PumpManager * pump = static_cast<PumpManager *>(aEvent->TimerEvent.Context);
+    PumpManager * pump = static_cast<PumpManager *>(aEvent.TimerEvent.Context);
     int32_t actor      = 0;
 
     // Make sure auto start timer is still armed.
@@ -152,11 +152,11 @@
     pump->InitiateAction(actor, START_ACTION);
 }
 
-void PumpManager::PumpStartTimerEventHandler(AppEvent * aEvent)
+void PumpManager::PumpStartTimerEventHandler(const AppEvent & aEvent)
 {
     Action_t actionCompleted = INVALID_ACTION;
 
-    PumpManager * pump = static_cast<PumpManager *>(aEvent->TimerEvent.Context);
+    PumpManager * pump = static_cast<PumpManager *>(aEvent.TimerEvent.Context);
 
     if (pump->mState == kState_StartInitiated)
     {
diff --git a/examples/pump-app/nrfconnect/main/ZclCallbacks.cpp b/examples/pump-app/nrfconnect/main/ZclCallbacks.cpp
index 49ec8f1..6a1c433 100644
--- a/examples/pump-app/nrfconnect/main/ZclCallbacks.cpp
+++ b/examples/pump-app/nrfconnect/main/ZclCallbacks.cpp
@@ -51,5 +51,5 @@
  */
 void emberAfOnOffClusterInitCallback(EndpointId endpoint)
 {
-    GetAppTask().UpdateClusterState();
+    AppTask::Instance().UpdateClusterState();
 }
diff --git a/examples/pump-app/nrfconnect/main/include/AppConfig.h b/examples/pump-app/nrfconnect/main/include/AppConfig.h
index e2e1812..7bea410 100644
--- a/examples/pump-app/nrfconnect/main/include/AppConfig.h
+++ b/examples/pump-app/nrfconnect/main/include/AppConfig.h
@@ -29,6 +29,8 @@
 
 #define SYSTEM_STATE_LED DK_LED1
 #define PUMP_STATE_LED DK_LED2
+#define FACTORY_RESET_SIGNAL_LED DK_LED3
+#define FACTORY_RESET_SIGNAL_LED1 DK_LED4
 
 // Time it takes in ms for the simulated pump to move from one state to another.
 #define PUMP_START_PERIOS_MS 2000
diff --git a/examples/pump-app/nrfconnect/main/include/AppEvent.h b/examples/pump-app/nrfconnect/main/include/AppEvent.h
index 2f2a0d9..3dfff79 100644
--- a/examples/pump-app/nrfconnect/main/include/AppEvent.h
+++ b/examples/pump-app/nrfconnect/main/include/AppEvent.h
@@ -20,27 +20,33 @@
 
 #include <cstdint>
 
-#include "LEDWidget.h"
+#include "EventTypes.h"
 
-struct AppEvent;
-typedef void (*EventHandler)(AppEvent *);
+class LEDWidget;
+
+enum class AppEventType : uint8_t
+{
+    None = 0,
+    Button,
+    ButtonPushed,
+    ButtonReleased,
+    Timer,
+    UpdateLedState,
+    StartSMPAdvertising,
+    Start,
+    Install
+};
+
+enum class FunctionEvent : uint8_t
+{
+    NoneSelected   = 0,
+    SoftwareUpdate = 0,
+    FactoryReset,
+    AdvertisingStart
+};
 
 struct AppEvent
 {
-    enum AppEventTypes
-    {
-        kEventType_Button = 0,
-        kEventType_Timer,
-        kEventType_Start,
-        kEventType_Install,
-        kEventType_UpdateLedState,
-#ifdef CONFIG_MCUMGR_SMP_BT
-        kEventType_StartSMPAdvertising,
-#endif
-    };
-
-    uint16_t Type;
-
     union
     {
         struct
@@ -63,5 +69,6 @@
         } UpdateLedStateEvent;
     };
 
+    AppEventType Type{ AppEventType::None };
     EventHandler Handler;
 };
diff --git a/examples/pump-app/nrfconnect/main/include/AppTask.h b/examples/pump-app/nrfconnect/main/include/AppTask.h
index 29a2103..a551dae 100644
--- a/examples/pump-app/nrfconnect/main/include/AppTask.h
+++ b/examples/pump-app/nrfconnect/main/include/AppTask.h
@@ -38,62 +38,47 @@
 class AppTask
 {
 public:
+    static AppTask & Instance(void)
+    {
+        static AppTask sAppTask;
+        return sAppTask;
+    };
     CHIP_ERROR StartApp();
 
-    void PostStartActionRequest(int32_t aActor, PumpManager::Action_t aAction);
-    void PostEvent(AppEvent * event);
-    void UpdateClusterState();
+    static void PostStartActionRequest(int32_t actor, PumpManager::Action_t action);
+    static void UpdateClusterState();
+    static void PostEvent(const AppEvent & event);
 
 private:
-    friend AppTask & GetAppTask(void);
-
     CHIP_ERROR Init();
 
-    static void ActionInitiated(PumpManager::Action_t aAction, int32_t aActor);
-    static void ActionCompleted(PumpManager::Action_t aAction, int32_t aActor);
+    static void CancelTimer();
+    static void StartTimer(uint32_t timeoutInMs);
 
-    void CancelTimer(void);
+    static void ActionInitiated(PumpManager::Action_t action, int32_t actor);
+    static void ActionCompleted(PumpManager::Action_t action, int32_t actor);
 
-    void DispatchEvent(AppEvent * event);
-
-    static void UpdateStatusLED();
-    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
-    static void UpdateLedStateEventHandler(AppEvent * aEvent);
-    static void FunctionTimerEventHandler(AppEvent * aEvent);
-    static void FunctionHandler(AppEvent * aEvent);
-    static void StartActionEventHandler(AppEvent * aEvent);
-    static void StartBLEAdvertisementHandler(AppEvent * aEvent);
+    static void DispatchEvent(const AppEvent & event);
+    static void FunctionTimerEventHandler(const AppEvent & event);
+    static void FunctionHandler(const AppEvent & event);
+    static void StartBLEAdvertisementHandler(const AppEvent & event);
+    static void UpdateLedStateEventHandler(const AppEvent & event);
+    static void StartActionEventHandler(const AppEvent & event);
 
     static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
-
-    static void ButtonEventHandler(uint32_t buttons_state, uint32_t has_changed);
-    static void TimerEventHandler(k_timer * timer);
+    static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged);
+    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
+    static void FunctionTimerTimeoutCallback(k_timer * timer);
+    static void UpdateStatusLED();
 
 #ifdef CONFIG_MCUMGR_SMP_BT
     static void RequestSMPAdvertisingStart(void);
 #endif
 
-    void StartTimer(uint32_t aTimeoutInMs);
-
-    enum Function_t
-    {
-        kFunction_NoneSelected   = 0,
-        kFunction_SoftwareUpdate = 0,
-        kFunction_FactoryReset,
-
-        kFunction_Invalid
-    };
-
-    Function_t mFunction      = kFunction_NoneSelected;
+    FunctionEvent mFunction   = FunctionEvent::NoneSelected;
     bool mFunctionTimerActive = false;
-    static AppTask sAppTask;
 
 #if CONFIG_CHIP_FACTORY_DATA
     chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
 #endif
 };
-
-inline AppTask & GetAppTask(void)
-{
-    return AppTask::sAppTask;
-}
diff --git a/examples/pump-app/nrfconnect/main/include/PumpManager.h b/examples/pump-app/nrfconnect/main/include/PumpManager.h
index eb2f086..5c1bec2 100644
--- a/examples/pump-app/nrfconnect/main/include/PumpManager.h
+++ b/examples/pump-app/nrfconnect/main/include/PumpManager.h
@@ -85,9 +85,9 @@
     void StartTimer(uint32_t aTimeoutMs);
 
     static void TimerEventHandler(k_timer * timer);
-    static void AutoRestartTimerEventHandler(AppEvent * aEvent);
+    static void AutoRestartTimerEventHandler(const AppEvent & aEvent);
 
-    static void PumpStartTimerEventHandler(AppEvent * aEvent);
+    static void PumpStartTimerEventHandler(const AppEvent & aEvent);
 
     static PumpManager sPump;
 };
diff --git a/examples/pump-app/nrfconnect/main/main.cpp b/examples/pump-app/nrfconnect/main/main.cpp
index a20f860..93a0062 100644
--- a/examples/pump-app/nrfconnect/main/main.cpp
+++ b/examples/pump-app/nrfconnect/main/main.cpp
@@ -21,13 +21,13 @@
 
 #include <zephyr/logging/log.h>
 
-LOG_MODULE_REGISTER(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip;
 
 int main()
 {
-    CHIP_ERROR err = GetAppTask().StartApp();
+    CHIP_ERROR err = AppTask::Instance().StartApp();
 
     LOG_ERR("Exited with code %" CHIP_ERROR_FORMAT, err.Format());
     return err == CHIP_NO_ERROR ? EXIT_SUCCESS : EXIT_FAILURE;
diff --git a/examples/pump-app/nrfconnect/prj.conf b/examples/pump-app/nrfconnect/prj.conf
index 916358d..3195f88 100644
--- a/examples/pump-app/nrfconnect/prj.conf
+++ b/examples/pump-app/nrfconnect/prj.conf
@@ -21,22 +21,20 @@
 # 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="MatterPump"
-
-# Additional configs for debbugging experience.
-CONFIG_THREAD_NAME=y
-CONFIG_MPU_STACK_GUARD=y
-
-# CHIP configuration
+# Enable CHIP
+CONFIG_CHIP=y
 CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
 # 32784 == 0x8010 (example pump-app)
 CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
+CONFIG_STD_CPP14=y
+
+# Add support for LEDs and buttons on Nordic development kits
+CONFIG_DK_LIBRARY=y
+
+# Bluetooth Low Energy configuration
+CONFIG_BT_DEVICE_NAME="MatterPump"
+
+# Other settings
+CONFIG_THREAD_NAME=y
+CONFIG_MPU_STACK_GUARD=y
+CONFIG_RESET_ON_FATAL_ERROR=n
diff --git a/examples/pump-app/nrfconnect/prj_no_dfu.conf b/examples/pump-app/nrfconnect/prj_no_dfu.conf
index 8c102a9..67c3187 100644
--- a/examples/pump-app/nrfconnect/prj_no_dfu.conf
+++ b/examples/pump-app/nrfconnect/prj_no_dfu.conf
@@ -14,32 +14,30 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32784 == 0x8010 (example pump-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
+CONFIG_STD_CPP14=y
+
 # 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
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterPump"
 
-# Additional configs for debbugging experience.
+# Other settings
 CONFIG_THREAD_NAME=y
 CONFIG_MPU_STACK_GUARD=y
+CONFIG_RESET_ON_FATAL_ERROR=n
 
 # Disable Matter OTA DFU
 CONFIG_CHIP_OTA_REQUESTOR=n
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32784 == 0x8010 (example pump-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
+# Disable QSPI NOR
+CONFIG_CHIP_QSPI_NOR=n
diff --git a/examples/pump-app/nrfconnect/prj_release.conf b/examples/pump-app/nrfconnect/prj_release.conf
index 01c70c0..adb09f7 100644
--- a/examples/pump-app/nrfconnect/prj_release.conf
+++ b/examples/pump-app/nrfconnect/prj_release.conf
@@ -14,31 +14,28 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32784 == 0x8010 (example pump-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
+CONFIG_STD_CPP14=y
+
 # 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
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterPump"
 
 # Enable system reset on fatal error
 CONFIG_RESET_ON_FATAL_ERROR=y
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32784 == 0x8010 (example pump-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
+# Suspend devices when the CPU goes into sleep
+CONFIG_PM_DEVICE=y
 
 # Disable all debug features
 CONFIG_SHELL=n
@@ -48,7 +45,8 @@
 CONFIG_SERIAL=n
 CONFIG_LOG=n
 CONFIG_LOG_MODE_MINIMAL=n
-CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_ASSERT_VERBOSE=n
+CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_PRINTK=n
+CONFIG_PRINTK_SYNC=n
 CONFIG_THREAD_NAME=n
diff --git a/examples/pump-controller-app/nrfconnect/Kconfig b/examples/pump-controller-app/nrfconnect/Kconfig
index 94a99f9..d5eb64a 100644
--- a/examples/pump-controller-app/nrfconnect/Kconfig
+++ b/examples/pump-controller-app/nrfconnect/Kconfig
@@ -15,6 +15,19 @@
 #
 mainmenu "Matter nRF Connect Lighting Example Application"
 
+# Sample configuration used for Thread networking
+if NET_L2_OPENTHREAD
+
+choice OPENTHREAD_NORDIC_LIBRARY_CONFIGURATION
+	default OPENTHREAD_NORDIC_LIBRARY_MTD
+endchoice
+
+choice OPENTHREAD_DEVICE_TYPE
+	default OPENTHREAD_MTD
+endchoice
+
+endif # NET_L2_OPENTHREAD
+
 rsource "../../../config/nrfconnect/chip-module/Kconfig.features"
 rsource "../../../config/nrfconnect/chip-module/Kconfig.defaults"
 source "Kconfig.zephyr"
diff --git a/examples/pump-controller-app/nrfconnect/README.md b/examples/pump-controller-app/nrfconnect/README.md
index c353a93..8fb710d 100644
--- a/examples/pump-controller-app/nrfconnect/README.md
+++ b/examples/pump-controller-app/nrfconnect/README.md
@@ -54,14 +54,19 @@
 [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md)
 to read more about the platform structure and dependencies.
 
-The CHIP device that runs the pump 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 Matter device that runs the pump application is controlled by the Matter
+controller device over the Thread protocol. By default, the Matter accessory
+device has IPv6 networking disabled. You must pair it with the Matter controller
+over Bluetooth® LE to get the configuration from the controller to use the
+device within a Thread or Wi-Fi network. You have to make the device
+discoverable manually (for security reasons). See
+[Bluetooth LE advertising](#bluetooth-le-advertising) to learn how to do this.
+The controller must get the commissioning information from the Matter accessory
+device and provision the device into the network.
 
-The example can be configured to use the secure bootloader and utilize it for
-performing over-the-air Device Firmware Upgrade using Bluetooth LE.
+You can test this application remotely over the Thread or the Wi-Fi protocol,
+which in either case requires more devices, including a Matter controller that
+you can configure either on a PC or a mobile device.
 
 ### Bluetooth LE advertising
 
@@ -188,8 +193,8 @@
     Bluetooth LE.
 
 -   _Short Flash Off (950ms on/50ms off)_ &mdash; The device is fully
-    provisioned, but does not yet have full Thread network or service
-    connectivity.
+    provisioned, but does not yet have full connectivity for Thread or Wi-Fi
+    network.
 
 -   _Solid On_ &mdash; The device is fully provisioned and has full Thread
     network and service connectivity.
diff --git a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp
index ea4bf10..248b392 100644
--- a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp
+++ b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp
@@ -18,6 +18,7 @@
 
 #include "AppTask.h"
 #include "AppConfig.h"
+#include "LEDUtil.h"
 #include "LEDWidget.h"
 #include "PumpManager.h"
 
@@ -45,42 +46,52 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
+
 using namespace ::chip;
 using namespace ::chip::app;
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceLayer;
 
-#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
-#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
-#define APP_EVENT_QUEUE_SIZE 10
-#define BUTTON_PUSH_EVENT 1
-#define BUTTON_RELEASE_EVENT 0
-
 namespace {
+constexpr uint32_t kFactoryResetTriggerTimeout      = 3000;
+constexpr uint32_t kFactoryResetCancelWindowTimeout = 3000;
+constexpr size_t kAppEventQueueSize                 = 10;
 
 // NOTE! This key is for test/certification only and should not be available in production devices!
 // If CONFIG_CHIP_FACTORY_DATA is enabled, this value is read from the factory data.
 uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                                                                                    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
 
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
-K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), APP_EVENT_QUEUE_SIZE, alignof(AppEvent));
+K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
 k_timer sFunctionTimer;
 
 LEDWidget sStatusLED;
 LEDWidget sPumpStateLED;
-LEDWidget sUnusedLED;
-LEDWidget sUnusedLED_1;
+FactoryResetLEDsWrapper<2> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTORY_RESET_SIGNAL_LED1 } };
 
-bool sIsThreadProvisioned = false;
-bool sIsThreadEnabled     = false;
-bool sHaveBLEConnections  = false;
+bool sIsNetworkProvisioned = false;
+bool sIsNetworkEnabled     = false;
+bool sHaveBLEConnections   = false;
 
 chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
 
 } // namespace
 
-AppTask AppTask::sAppTask;
+namespace LedConsts {
+constexpr uint32_t kBlinkRate_ms{ 500 };
+namespace StatusLed {
+namespace Unprovisioned {
+constexpr uint32_t kOn_ms{ 100 };
+constexpr uint32_t kOff_ms{ kOn_ms };
+} // namespace Unprovisioned
+namespace Provisioned {
+constexpr uint32_t kOn_ms{ 50 };
+constexpr uint32_t kOff_ms{ 950 };
+} // namespace Provisioned
+
+} // namespace StatusLed
+} // namespace LedConsts
 
 CHIP_ERROR AppTask::Init()
 {
@@ -127,9 +138,6 @@
     sPumpStateLED.Init(PUMP_STATE_LED);
     sPumpStateLED.Set(!PumpMgr().IsStopped());
 
-    sUnusedLED.Init(DK_LED3);
-    sUnusedLED_1.Init(DK_LED4);
-
     UpdateStatusLED();
 
     PumpMgr().Init();
@@ -144,7 +152,7 @@
     }
 
     // Initialize function button timer
-    k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr);
+    k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr);
     k_timer_user_data_set(&sFunctionTimer, this);
 
 #ifdef CONFIG_MCUMGR_SMP_BT
@@ -205,100 +213,104 @@
     while (true)
     {
         k_msgq_get(&sAppEventQueue, &event, K_FOREVER);
-        DispatchEvent(&event);
+        DispatchEvent(event);
     }
 
     return CHIP_NO_ERROR;
 }
 
-void AppTask::StartActionEventHandler(AppEvent * aEvent)
+void AppTask::StartActionEventHandler(const AppEvent & event)
 {
     PumpManager::Action_t action = PumpManager::INVALID_ACTION;
     int32_t actor                = 0;
 
-    if (aEvent->Type == AppEvent::kEventType_Start)
+    if (event.Type == AppEventType::Start)
     {
-        action = static_cast<PumpManager::Action_t>(aEvent->StartEvent.Action);
-        actor  = aEvent->StartEvent.Actor;
+        action = static_cast<PumpManager::Action_t>(event.StartEvent.Action);
+        actor  = event.StartEvent.Actor;
     }
-    else if (aEvent->Type == AppEvent::kEventType_Button)
+    else if (event.Type == AppEventType::Button)
     {
         action = PumpMgr().IsStopped() ? PumpManager::START_ACTION : PumpManager::STOP_ACTION;
-        actor  = AppEvent::kEventType_Button;
+        actor  = static_cast<uint8_t>(AppEventType::Button);
     }
 
     if (action != PumpManager::INVALID_ACTION && !PumpMgr().InitiateAction(actor, action))
         LOG_INF("Action is already in progress or active.");
 }
 
-void AppTask::ButtonEventHandler(uint32_t button_state, uint32_t has_changed)
-{
-    AppEvent button_event;
-    button_event.Type = AppEvent::kEventType_Button;
-
-    if (START_BUTTON_MASK & button_state & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = START_BUTTON;
-        button_event.ButtonEvent.Action = BUTTON_PUSH_EVENT;
-        button_event.Handler            = StartActionEventHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-
-    if (FUNCTION_BUTTON_MASK & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = FUNCTION_BUTTON;
-        button_event.ButtonEvent.Action = (FUNCTION_BUTTON_MASK & button_state) ? BUTTON_PUSH_EVENT : BUTTON_RELEASE_EVENT;
-        button_event.Handler            = FunctionHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-
-    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & button_state & has_changed)
-    {
-        button_event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
-        button_event.ButtonEvent.Action = BUTTON_PUSH_EVENT;
-        button_event.Handler            = StartBLEAdvertisementHandler;
-        sAppTask.PostEvent(&button_event);
-    }
-}
-
-void AppTask::TimerEventHandler(k_timer * timer)
+void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)
 {
     AppEvent event;
-    event.Type               = AppEvent::kEventType_Timer;
-    event.TimerEvent.Context = k_timer_user_data_get(timer);
-    event.Handler            = FunctionTimerEventHandler;
-    sAppTask.PostEvent(&event);
+    event.Type = AppEventType::Button;
+
+    if (START_BUTTON_MASK & buttonState & hasChanged)
+    {
+        event.ButtonEvent.PinNo  = START_BUTTON;
+        event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::Button);
+        event.Handler            = StartActionEventHandler;
+        PostEvent(event);
+    }
+
+    if (FUNCTION_BUTTON_MASK & hasChanged)
+    {
+        event.ButtonEvent.PinNo = FUNCTION_BUTTON;
+        event.ButtonEvent.Action =
+            static_cast<uint8_t>((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased);
+        event.Handler = FunctionHandler;
+        PostEvent(event);
+    }
+
+    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged)
+    {
+        event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
+        event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
+        event.Handler            = StartBLEAdvertisementHandler;
+        PostEvent(event);
+    }
 }
 
-void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
+void AppTask::FunctionTimerTimeoutCallback(k_timer * timer)
 {
-    if (aEvent->Type != AppEvent::kEventType_Timer)
+    if (!timer)
+    {
+        return;
+    }
+
+    AppEvent event;
+    event.Type               = AppEventType::Timer;
+    event.TimerEvent.Context = k_timer_user_data_get(timer);
+    event.Handler            = FunctionTimerEventHandler;
+    PostEvent(event);
+}
+
+void AppTask::FunctionTimerEventHandler(const AppEvent & event)
+{
+    if (event.Type != AppEventType::Timer)
         return;
 
-    // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT, initiate factory reset
-    if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+    // If we reached here, the button was held past kFactoryResetTriggerTimeout, initiate factory reset
+    if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
     {
-        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_TRIGGER_TIMEOUT);
+        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", kFactoryResetTriggerTimeout);
 
-        // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to cancel, if required.
-        sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
-        sAppTask.mFunction = kFunction_FactoryReset;
+        // Start timer for kFactoryResetCancelWindowTimeout to allow user to cancel, if required.
+        Instance().StartTimer(kFactoryResetCancelWindowTimeout);
+        Instance().mFunction = FunctionEvent::FactoryReset;
 
+#ifdef CONFIG_STATE_LEDS
         // Turn off all LEDs before starting blink to make sure blink is co-ordinated.
         sStatusLED.Set(false);
-        sPumpStateLED.Set(false);
-        sUnusedLED_1.Set(false);
-        sUnusedLED.Set(false);
+        sFactoryResetLEDs.Set(false);
 
-        sStatusLED.Blink(500);
-        sPumpStateLED.Blink(500);
-        sUnusedLED.Blink(500);
-        sUnusedLED_1.Blink(500);
+        sStatusLED.Blink(LedConsts::kBlinkRate_ms);
+        sFactoryResetLEDs.Blink(LedConsts::kBlinkRate_ms);
+#endif
     }
-    else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+    else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
     {
         // Actually trigger Factory Reset
-        sAppTask.mFunction = kFunction_NoneSelected;
+        Instance().mFunction = FunctionEvent::NoneSelected;
 
         chip::Server::GetInstance().ScheduleFactoryReset();
     }
@@ -308,65 +320,62 @@
 void AppTask::RequestSMPAdvertisingStart(void)
 {
     AppEvent event;
-    event.Type    = AppEvent::kEventType_StartSMPAdvertising;
-    event.Handler = [](AppEvent *) { GetDFUOverSMP().StartBLEAdvertising(); };
-    sAppTask.PostEvent(&event);
+    event.Type    = AppEventType::StartSMPAdvertising;
+    event.Handler = [](const AppEvent &) { GetDFUOverSMP().StartBLEAdvertising(); };
+    PostEvent(event);
 }
 #endif
 
-void AppTask::FunctionHandler(AppEvent * aEvent)
+void AppTask::FunctionHandler(const AppEvent & event)
 {
-    if (aEvent->ButtonEvent.PinNo != FUNCTION_BUTTON)
+    if (event.ButtonEvent.PinNo != FUNCTION_BUTTON)
         return;
 
-    // To trigger software update: press the FUNCTION_BUTTON button briefly (< FACTORY_RESET_TRIGGER_TIMEOUT)
     // To initiate factory reset: press the FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT + FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
     // All LEDs start blinking after FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
     // To cancel factory reset: release the FUNCTION_BUTTON once all LEDs start blinking within the
     // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
-    if (aEvent->ButtonEvent.Action == BUTTON_PUSH_EVENT)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
     {
-        if (!sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_NoneSelected)
+        if (!Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::NoneSelected)
         {
-            sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+            Instance().StartTimer(kFactoryResetTriggerTimeout);
 
-            sAppTask.mFunction = kFunction_SoftwareUpdate;
+            Instance().mFunction = FunctionEvent::SoftwareUpdate;
         }
     }
     else
     {
         // If the button was released before factory reset got initiated, trigger a software update.
-        if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+        if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
         {
-            sAppTask.CancelTimer();
-            sAppTask.mFunction = kFunction_NoneSelected;
+            Instance().CancelTimer();
 
 #ifdef CONFIG_MCUMGR_SMP_BT
             GetDFUOverSMP().StartServer();
 #else
             LOG_INF("Software update is disabled");
 #endif
+            Instance().mFunction = FunctionEvent::NoneSelected;
         }
-        else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+        else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
         {
-            sUnusedLED.Set(false);
-            sUnusedLED_1.Set(false);
-
-            // Set pump state LED back to show state of pump.
-            sPumpStateLED.Set(!PumpMgr().IsStopped());
+            sFactoryResetLEDs.Set(false);
 
             UpdateStatusLED();
-            sAppTask.CancelTimer();
-
-            // Change the function to none selected since factory reset has been canceled.
-            sAppTask.mFunction = kFunction_NoneSelected;
-
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
             LOG_INF("Factory Reset has been Canceled");
         }
+        else if (Instance().mFunctionTimerActive)
+        {
+            CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
+        }
     }
 }
 
-void AppTask::StartBLEAdvertisementHandler(AppEvent *)
+void AppTask::StartBLEAdvertisementHandler(const AppEvent &)
 {
     if (Server::GetInstance().GetFabricTable().FabricCount() != 0)
     {
@@ -386,45 +395,47 @@
     }
 }
 
-void AppTask::UpdateLedStateEventHandler(AppEvent * aEvent)
+void AppTask::UpdateLedStateEventHandler(const AppEvent & event)
 {
-    if (aEvent->Type == AppEvent::kEventType_UpdateLedState)
+    if (event.Type == AppEventType::UpdateLedState)
     {
-        aEvent->UpdateLedStateEvent.LedWidget->UpdateState();
+        event.UpdateLedStateEvent.LedWidget->UpdateState();
     }
 }
 
 void AppTask::LEDStateUpdateHandler(LEDWidget & ledWidget)
 {
     AppEvent event;
-    event.Type                          = AppEvent::kEventType_UpdateLedState;
+    event.Type                          = AppEventType::UpdateLedState;
     event.Handler                       = UpdateLedStateEventHandler;
     event.UpdateLedStateEvent.LedWidget = &ledWidget;
-    sAppTask.PostEvent(&event);
+    PostEvent(event);
 }
 
 void AppTask::UpdateStatusLED()
 {
-    /* Update the status LED.
-     *
-     * If thread and service provisioned, keep the LED On constantly.
-     *
-     * If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
-     * rate of 100ms.
-     *
-     * Otherwise, blink the LED On for a very short time. */
-    if (sIsThreadProvisioned && sIsThreadEnabled)
+#ifdef CONFIG_STATE_LEDS
+    // Update the status LED.
+    //
+    // If thread and service provisioned, keep the LED On constantly.
+    //
+    // If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
+    // rate of 100ms.
+    //
+    // Otherwise, blink the LED On for a very short time.
+    if (sIsNetworkProvisioned && sIsNetworkEnabled)
     {
         sStatusLED.Set(true);
     }
     else if (sHaveBLEConnections)
     {
-        sStatusLED.Blink(100, 100);
+        sStatusLED.Blink(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms);
     }
     else
     {
-        sStatusLED.Blink(50, 950);
+        sStatusLED.Blink(LedConsts::StatusLed::Provisioned::kOn_ms, LedConsts::StatusLed::Provisioned::kOff_ms);
     }
+#endif
 }
 
 void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */)
@@ -432,21 +443,8 @@
     switch (event->Type)
     {
     case DeviceEventType::kCHIPoBLEAdvertisingChange:
-        if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
-        {
 #ifdef CONFIG_CHIP_NFC_COMMISSIONING
-            NFCMgr().StopTagEmulation();
-#endif
-#ifdef CONFIG_MCUMGR_SMP_BT
-            // After CHIPoBLE advertising stop, start advertising SMP in case Thread is enabled or there are no active CHIPoBLE
-            // connections (exclude the case when CHIPoBLE advertising is stopped on the connection time)
-            if (GetDFUOverSMP().IsEnabled() &&
-                (ConnectivityMgr().IsThreadProvisioned() || ConnectivityMgr().NumBLEConnections() == 0))
-                sAppTask.RequestSMPAdvertisingStart();
-#endif
-        }
-#ifdef CONFIG_CHIP_NFC_COMMISSIONING
-        else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
+        if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
         {
             if (NFCMgr().IsTagEmulationStarted())
             {
@@ -457,13 +455,17 @@
                 ShareQRCodeOverNFC(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
             }
         }
+        else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
+        {
+            NFCMgr().StopTagEmulation();
+        }
 #endif
         sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
         UpdateStatusLED();
         break;
     case DeviceEventType::kThreadStateChange:
-        sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
-        sIsThreadEnabled     = ConnectivityMgr().IsThreadEnabled();
+        sIsNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsThreadEnabled();
         UpdateStatusLED();
         break;
     case DeviceEventType::kDnssdPlatformInitialized:
@@ -479,24 +481,24 @@
 void AppTask::CancelTimer()
 {
     k_timer_stop(&sFunctionTimer);
-    mFunctionTimerActive = false;
+    Instance().mFunctionTimerActive = false;
 }
 
 void AppTask::StartTimer(uint32_t aTimeoutInMs)
 {
     k_timer_start(&sFunctionTimer, K_MSEC(aTimeoutInMs), K_NO_WAIT);
-    mFunctionTimerActive = true;
+    Instance().mFunctionTimerActive = true;
 }
 
-void AppTask::ActionInitiated(PumpManager::Action_t aAction, int32_t aActor)
+void AppTask::ActionInitiated(PumpManager::Action_t action, int32_t actor)
 {
     // If the action has been initiated by the pump, update the pump trait
     // and start flashing the LEDs rapidly to indicate action initiation.
-    if (aAction == PumpManager::START_ACTION)
+    if (action == PumpManager::START_ACTION)
     {
         LOG_INF("Pump Start Action has been initiated");
     }
-    else if (aAction == PumpManager::STOP_ACTION)
+    else if (action == PumpManager::STOP_ACTION)
     {
         LOG_INF("Pump Stop Action has been initiated");
     }
@@ -504,51 +506,51 @@
     sPumpStateLED.Blink(50, 50);
 }
 
-void AppTask::ActionCompleted(PumpManager::Action_t aAction, int32_t aActor)
+void AppTask::ActionCompleted(PumpManager::Action_t action, int32_t actor)
 {
     // If the action has been completed by the pump, update the pump trait.
     // Turn on the pump state LED if in a STARTED state OR
     // Turn off the pump state LED if in a STOPPED state.
-    if (aAction == PumpManager::START_ACTION)
+    if (action == PumpManager::START_ACTION)
     {
         LOG_INF("Pump Start Action has been completed");
         sPumpStateLED.Set(true);
     }
-    else if (aAction == PumpManager::STOP_ACTION)
+    else if (action == PumpManager::STOP_ACTION)
     {
         LOG_INF("Pump Stop Action has been completed");
         sPumpStateLED.Set(false);
     }
 
-    if (aActor == AppEvent::kEventType_Button)
+    if (actor == static_cast<uint8_t>(AppEventType::Button))
     {
-        sAppTask.UpdateClusterState();
+        Instance().UpdateClusterState();
     }
 }
 
-void AppTask::PostStartActionRequest(int32_t aActor, PumpManager::Action_t aAction)
+void AppTask::PostStartActionRequest(int32_t actor, PumpManager::Action_t action)
 {
     AppEvent event;
-    event.Type              = AppEvent::kEventType_Start;
-    event.StartEvent.Actor  = aActor;
-    event.StartEvent.Action = aAction;
+    event.Type              = AppEventType::Start;
+    event.StartEvent.Actor  = actor;
+    event.StartEvent.Action = action;
     event.Handler           = StartActionEventHandler;
-    PostEvent(&event);
+    PostEvent(event);
 }
 
-void AppTask::PostEvent(AppEvent * aEvent)
+void AppTask::PostEvent(const AppEvent & event)
 {
-    if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT))
+    if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT) != 0)
     {
         LOG_INF("Failed to post event to app task event queue");
     }
 }
 
-void AppTask::DispatchEvent(AppEvent * aEvent)
+void AppTask::DispatchEvent(const AppEvent & event)
 {
-    if (aEvent->Handler)
+    if (event.Handler)
     {
-        aEvent->Handler(aEvent);
+        event.Handler(event);
     }
     else
     {
diff --git a/examples/pump-controller-app/nrfconnect/main/PumpManager.cpp b/examples/pump-controller-app/nrfconnect/main/PumpManager.cpp
index a7f654b..2b6215d 100644
--- a/examples/pump-controller-app/nrfconnect/main/PumpManager.cpp
+++ b/examples/pump-controller-app/nrfconnect/main/PumpManager.cpp
@@ -25,7 +25,7 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 static k_timer sStartTimer;
 
@@ -130,15 +130,15 @@
     // once sStartTimer expires. Post an event to apptask queue with the actual handler
     // so that the event can be handled in the context of the apptask.
     AppEvent event;
-    event.Type               = AppEvent::kEventType_Timer;
+    event.Type               = AppEventType::Timer;
     event.TimerEvent.Context = pump;
     event.Handler            = pump->mAutoStartTimerArmed ? AutoRestartTimerEventHandler : PumpStartTimerEventHandler;
-    GetAppTask().PostEvent(&event);
+    AppTask::Instance().PostEvent(event);
 }
 
-void PumpManager::AutoRestartTimerEventHandler(AppEvent * aEvent)
+void PumpManager::AutoRestartTimerEventHandler(const AppEvent & aEvent)
 {
-    PumpManager * pump = static_cast<PumpManager *>(aEvent->TimerEvent.Context);
+    PumpManager * pump = static_cast<PumpManager *>(aEvent.TimerEvent.Context);
     int32_t actor      = 0;
 
     // Make sure auto start timer is still armed.
@@ -152,11 +152,11 @@
     pump->InitiateAction(actor, START_ACTION);
 }
 
-void PumpManager::PumpStartTimerEventHandler(AppEvent * aEvent)
+void PumpManager::PumpStartTimerEventHandler(const AppEvent & aEvent)
 {
     Action_t actionCompleted = INVALID_ACTION;
 
-    PumpManager * pump = static_cast<PumpManager *>(aEvent->TimerEvent.Context);
+    PumpManager * pump = static_cast<PumpManager *>(aEvent.TimerEvent.Context);
 
     if (pump->mState == kState_StartInitiated)
     {
diff --git a/examples/pump-controller-app/nrfconnect/main/ZclCallbacks.cpp b/examples/pump-controller-app/nrfconnect/main/ZclCallbacks.cpp
index 49ec8f1..6a1c433 100644
--- a/examples/pump-controller-app/nrfconnect/main/ZclCallbacks.cpp
+++ b/examples/pump-controller-app/nrfconnect/main/ZclCallbacks.cpp
@@ -51,5 +51,5 @@
  */
 void emberAfOnOffClusterInitCallback(EndpointId endpoint)
 {
-    GetAppTask().UpdateClusterState();
+    AppTask::Instance().UpdateClusterState();
 }
diff --git a/examples/pump-controller-app/nrfconnect/main/include/AppConfig.h b/examples/pump-controller-app/nrfconnect/main/include/AppConfig.h
index e63e9d8..a6a172e 100644
--- a/examples/pump-controller-app/nrfconnect/main/include/AppConfig.h
+++ b/examples/pump-controller-app/nrfconnect/main/include/AppConfig.h
@@ -29,6 +29,8 @@
 
 #define SYSTEM_STATE_LED DK_LED1
 #define PUMP_STATE_LED DK_LED2
+#define FACTORY_RESET_SIGNAL_LED DK_LED3
+#define FACTORY_RESET_SIGNAL_LED1 DK_LED4
 
 // Time it takes in ms for the simulated pump to move from one state to another.
 #define PUMP_START_PERIOS_MS 2000
diff --git a/examples/pump-controller-app/nrfconnect/main/include/AppEvent.h b/examples/pump-controller-app/nrfconnect/main/include/AppEvent.h
index 2f2a0d9..3dfff79 100644
--- a/examples/pump-controller-app/nrfconnect/main/include/AppEvent.h
+++ b/examples/pump-controller-app/nrfconnect/main/include/AppEvent.h
@@ -20,27 +20,33 @@
 
 #include <cstdint>
 
-#include "LEDWidget.h"
+#include "EventTypes.h"
 
-struct AppEvent;
-typedef void (*EventHandler)(AppEvent *);
+class LEDWidget;
+
+enum class AppEventType : uint8_t
+{
+    None = 0,
+    Button,
+    ButtonPushed,
+    ButtonReleased,
+    Timer,
+    UpdateLedState,
+    StartSMPAdvertising,
+    Start,
+    Install
+};
+
+enum class FunctionEvent : uint8_t
+{
+    NoneSelected   = 0,
+    SoftwareUpdate = 0,
+    FactoryReset,
+    AdvertisingStart
+};
 
 struct AppEvent
 {
-    enum AppEventTypes
-    {
-        kEventType_Button = 0,
-        kEventType_Timer,
-        kEventType_Start,
-        kEventType_Install,
-        kEventType_UpdateLedState,
-#ifdef CONFIG_MCUMGR_SMP_BT
-        kEventType_StartSMPAdvertising,
-#endif
-    };
-
-    uint16_t Type;
-
     union
     {
         struct
@@ -63,5 +69,6 @@
         } UpdateLedStateEvent;
     };
 
+    AppEventType Type{ AppEventType::None };
     EventHandler Handler;
 };
diff --git a/examples/pump-controller-app/nrfconnect/main/include/AppTask.h b/examples/pump-controller-app/nrfconnect/main/include/AppTask.h
index 29a2103..5681b25 100644
--- a/examples/pump-controller-app/nrfconnect/main/include/AppTask.h
+++ b/examples/pump-controller-app/nrfconnect/main/include/AppTask.h
@@ -38,62 +38,48 @@
 class AppTask
 {
 public:
+    static AppTask & Instance(void)
+    {
+        static AppTask sAppTask;
+        return sAppTask;
+    };
+
     CHIP_ERROR StartApp();
 
-    void PostStartActionRequest(int32_t aActor, PumpManager::Action_t aAction);
-    void PostEvent(AppEvent * event);
-    void UpdateClusterState();
+    static void PostStartActionRequest(int32_t actor, PumpManager::Action_t action);
+    static void UpdateClusterState();
+    static void PostEvent(const AppEvent & event);
 
 private:
-    friend AppTask & GetAppTask(void);
-
     CHIP_ERROR Init();
 
-    static void ActionInitiated(PumpManager::Action_t aAction, int32_t aActor);
-    static void ActionCompleted(PumpManager::Action_t aAction, int32_t aActor);
+    static void CancelTimer();
+    static void StartTimer(uint32_t timeoutInMs);
 
-    void CancelTimer(void);
+    static void ActionInitiated(PumpManager::Action_t action, int32_t actor);
+    static void ActionCompleted(PumpManager::Action_t action, int32_t actor);
 
-    void DispatchEvent(AppEvent * event);
-
-    static void UpdateStatusLED();
-    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
-    static void UpdateLedStateEventHandler(AppEvent * aEvent);
-    static void FunctionTimerEventHandler(AppEvent * aEvent);
-    static void FunctionHandler(AppEvent * aEvent);
-    static void StartActionEventHandler(AppEvent * aEvent);
-    static void StartBLEAdvertisementHandler(AppEvent * aEvent);
+    static void DispatchEvent(const AppEvent & event);
+    static void FunctionTimerEventHandler(const AppEvent & event);
+    static void FunctionHandler(const AppEvent & event);
+    static void StartBLEAdvertisementHandler(const AppEvent & event);
+    static void UpdateLedStateEventHandler(const AppEvent & event);
+    static void StartActionEventHandler(const AppEvent & event);
 
     static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
-
-    static void ButtonEventHandler(uint32_t buttons_state, uint32_t has_changed);
-    static void TimerEventHandler(k_timer * timer);
+    static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged);
+    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
+    static void FunctionTimerTimeoutCallback(k_timer * timer);
+    static void UpdateStatusLED();
 
 #ifdef CONFIG_MCUMGR_SMP_BT
     static void RequestSMPAdvertisingStart(void);
 #endif
 
-    void StartTimer(uint32_t aTimeoutInMs);
-
-    enum Function_t
-    {
-        kFunction_NoneSelected   = 0,
-        kFunction_SoftwareUpdate = 0,
-        kFunction_FactoryReset,
-
-        kFunction_Invalid
-    };
-
-    Function_t mFunction      = kFunction_NoneSelected;
+    FunctionEvent mFunction   = FunctionEvent::NoneSelected;
     bool mFunctionTimerActive = false;
-    static AppTask sAppTask;
 
 #if CONFIG_CHIP_FACTORY_DATA
     chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
 #endif
 };
-
-inline AppTask & GetAppTask(void)
-{
-    return AppTask::sAppTask;
-}
diff --git a/examples/pump-controller-app/nrfconnect/main/include/PumpManager.h b/examples/pump-controller-app/nrfconnect/main/include/PumpManager.h
index afc1b57..f8111e5 100644
--- a/examples/pump-controller-app/nrfconnect/main/include/PumpManager.h
+++ b/examples/pump-controller-app/nrfconnect/main/include/PumpManager.h
@@ -71,9 +71,9 @@
     void StartTimer(uint32_t aTimeoutMs);
 
     static void TimerEventHandler(k_timer * timer);
-    static void AutoRestartTimerEventHandler(AppEvent * aEvent);
+    static void AutoRestartTimerEventHandler(const AppEvent & aEvent);
 
-    static void PumpStartTimerEventHandler(AppEvent * aEvent);
+    static void PumpStartTimerEventHandler(const AppEvent & aEvent);
 
     static PumpManager sPump;
 };
diff --git a/examples/pump-controller-app/nrfconnect/main/main.cpp b/examples/pump-controller-app/nrfconnect/main/main.cpp
index a20f860..93a0062 100644
--- a/examples/pump-controller-app/nrfconnect/main/main.cpp
+++ b/examples/pump-controller-app/nrfconnect/main/main.cpp
@@ -21,13 +21,13 @@
 
 #include <zephyr/logging/log.h>
 
-LOG_MODULE_REGISTER(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip;
 
 int main()
 {
-    CHIP_ERROR err = GetAppTask().StartApp();
+    CHIP_ERROR err = AppTask::Instance().StartApp();
 
     LOG_ERR("Exited with code %" CHIP_ERROR_FORMAT, err.Format());
     return err == CHIP_NO_ERROR ? EXIT_SUCCESS : EXIT_FAILURE;
diff --git a/examples/pump-controller-app/nrfconnect/prj.conf b/examples/pump-controller-app/nrfconnect/prj.conf
index f3936ac..4a38ec1 100644
--- a/examples/pump-controller-app/nrfconnect/prj.conf
+++ b/examples/pump-controller-app/nrfconnect/prj.conf
@@ -14,29 +14,24 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32785 == 0x8011 (example pump-controller-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32785
+CONFIG_STD_CPP14=y
+
 # 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
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterPumpCtrl"
 
-# Additional configs for debbugging experience.
+# Other settings
 CONFIG_THREAD_NAME=y
 CONFIG_MPU_STACK_GUARD=y
-
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32785 == 0x8011 (example pump-controller-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32785
\ No newline at end of file
+CONFIG_RESET_ON_FATAL_ERROR=n
diff --git a/examples/pump-controller-app/nrfconnect/prj_no_dfu.conf b/examples/pump-controller-app/nrfconnect/prj_no_dfu.conf
index f946af9..dba7042 100644
--- a/examples/pump-controller-app/nrfconnect/prj_no_dfu.conf
+++ b/examples/pump-controller-app/nrfconnect/prj_no_dfu.conf
@@ -14,32 +14,31 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32785 == 0x8011 (example pump-controller-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32785
+
+CONFIG_STD_CPP14=y
+
 # 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
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterPumpCtrl"
 
-# Additional configs for debbugging experience.
+# Other settings
 CONFIG_THREAD_NAME=y
 CONFIG_MPU_STACK_GUARD=y
+CONFIG_RESET_ON_FATAL_ERROR=n
 
 # Disable Matter OTA DFU
 CONFIG_CHIP_OTA_REQUESTOR=n
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32785 == 0x8011 (example pump-controller-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32785
+# Disable QSPI NOR
+CONFIG_CHIP_QSPI_NOR=n
diff --git a/examples/pump-controller-app/nrfconnect/prj_release.conf b/examples/pump-controller-app/nrfconnect/prj_release.conf
index bf7f1a4..88ea95c 100644
--- a/examples/pump-controller-app/nrfconnect/prj_release.conf
+++ b/examples/pump-controller-app/nrfconnect/prj_release.conf
@@ -14,31 +14,29 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32785 == 0x8011 (example pump-controller-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32785
+
+CONFIG_STD_CPP14=y
+
 # 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
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterPumpCtrl"
 
 # Enable system reset on fatal error
 CONFIG_RESET_ON_FATAL_ERROR=y
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32785 == 0x8011 (example pump-controller-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32785
+# Suspend devices when the CPU goes into sleep
+CONFIG_PM_DEVICE=y
 
 # Disable all debug features
 CONFIG_SHELL=n
@@ -48,7 +46,8 @@
 CONFIG_SERIAL=n
 CONFIG_LOG=n
 CONFIG_LOG_MODE_MINIMAL=n
-CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_ASSERT_VERBOSE=n
+CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_PRINTK=n
+CONFIG_PRINTK_SYNC=n
 CONFIG_THREAD_NAME=n
diff --git a/examples/window-app/nrfconnect/README.md b/examples/window-app/nrfconnect/README.md
index 9fd8e4f..e800b65 100644
--- a/examples/window-app/nrfconnect/README.md
+++ b/examples/window-app/nrfconnect/README.md
@@ -57,14 +57,18 @@
 to read more about the platform structure and dependencies.
 
 The Matter device that runs the window shutter 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.
+Matter controller device over the Thread protocol. By default, the Matter
+accessory device has IPv6 networking disabled. You must pair it with the Matter
+controller over Bluetooth® LE to get the configuration from the controller to
+use the device within a Thread or Wi-Fi network. You have to make the device
+discoverable manually (for security reasons). See
+[Bluetooth LE advertising](#bluetooth-le-advertising) to learn how to do this.
+The controller must get the commissioning information from the Matter accessory
+device and provision the device into the network.
 
-The example can be configured to use the secure bootloader and utilize it for
-performing over-the-air Device Firmware Upgrade using Bluetooth LE. The device
-works as a Thread Synchronized Sleepy End Device.
+You can test this application remotely over the Thread or the Wi-Fi protocol,
+which in either case requires more devices, including a Matter controller that
+you can configure either on a PC or a mobile device.
 
 ### Bluetooth LE advertising
 
@@ -185,8 +189,8 @@
     Bluetooth LE.
 
 -   _Short Flash Off (950ms on/50ms off)_ &mdash; The device is fully
-    provisioned, but does not yet have full Thread network or service
-    connectivity.
+    provisioned, but does not yet have full connectivity for Thread or Wi-Fi
+    network.
 
 -   _Solid On_ &mdash; The device is fully provisioned and has full Thread
     network and service connectivity.
diff --git a/examples/window-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay b/examples/window-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
index 00c7b57..c1672db 100644
--- a/examples/window-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
+++ b/examples/window-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay
@@ -58,9 +58,6 @@
 &uart1 {
 	status = "disabled";
 };
-&gpio1 {
-	status = "disabled";
-};
 &i2c0 {
 	status = "disabled";
 };
diff --git a/examples/window-app/nrfconnect/main/AppTask.cpp b/examples/window-app/nrfconnect/main/AppTask.cpp
index 08df914..3116400 100644
--- a/examples/window-app/nrfconnect/main/AppTask.cpp
+++ b/examples/window-app/nrfconnect/main/AppTask.cpp
@@ -23,15 +23,14 @@
 
 #include <DeviceInfoProviderImpl.h>
 
-#include <app/server/OnboardingCodesUtil.h>
-#include <app/server/Server.h>
-
 #include <app-common/zap-generated/attribute-id.h>
 #include <app-common/zap-generated/attribute-type.h>
 #include <app-common/zap-generated/cluster-id.h>
+#include <app/clusters/identify-server/identify-server.h>
 #include <app/clusters/ota-requestor/OTATestEventTriggerDelegate.h>
+#include <app/server/OnboardingCodesUtil.h>
+#include <app/server/Server.h>
 #include <app/util/attribute-storage.h>
-
 #include <credentials/DeviceAttestationCredsProvider.h>
 #include <credentials/examples/DeviceAttestationCredsExample.h>
 
@@ -43,36 +42,42 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
-#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
-#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
-#define MOVEMENT_START_WINDOW_TIMEOUT 2000
-#define APP_EVENT_QUEUE_SIZE 10
-#define BUTTON_PUSH_EVENT 1
-#define BUTTON_RELEASE_EVENT 0
-
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
-K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), APP_EVENT_QUEUE_SIZE, alignof(AppEvent));
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip;
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceLayer;
 namespace {
+constexpr uint32_t kFactoryResetTriggerTimeout      = 3000;
+constexpr uint32_t kFactoryResetCancelWindowTimeout = 3000;
+constexpr size_t kAppEventQueueSize                 = 10;
+
+K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
+k_timer sFunctionTimer;
 
 // NOTE! This key is for test/certification only and should not be available in production devices!
 // If CONFIG_CHIP_FACTORY_DATA is enabled, this value is read from the factory data.
 uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                                                                                    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
 
+Identify sIdentify = { WindowCovering::Endpoint(), AppTask::IdentifyStartHandler, AppTask::IdentifyStopHandler,
+                       EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED };
+
 LEDWidget sStatusLED;
-UnusedLedsWrapper<1> sUnusedLeds{ { DK_LED4 } };
-k_timer sFunctionTimer;
+LEDWidget sIdentifyLED;
+FactoryResetLEDsWrapper<1> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED } };
 
 chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
 
+bool sIsNetworkProvisioned = false;
+bool sIsNetworkEnabled     = false;
+bool sHaveBLEConnections   = false;
 } // namespace
 
 namespace LedConsts {
 constexpr uint32_t kBlinkRate_ms{ 500 };
+constexpr uint32_t kIdentifyBlinkRate_ms{ 500 };
+
 namespace StatusLed {
 namespace Unprovisioned {
 constexpr uint32_t kOn_ms{ 100 };
@@ -135,6 +140,8 @@
     LEDWidget::SetStateUpdateCallback(LEDStateUpdateHandler);
 
     sStatusLED.Init(SYSTEM_STATE_LED);
+    sIdentifyLED.Init(LIFT_STATE_LED);
+    sIdentifyLED.Set(false);
 
     UpdateStatusLED();
 
@@ -151,7 +158,7 @@
     k_timer_user_data_set(&sFunctionTimer, this);
 
 #ifdef CONFIG_MCUMGR_SMP_BT
-    /* Initialize DFU over SMP */
+    // Initialize DFU over SMP
     GetDFUOverSMP().Init(RequestSMPAdvertisingStart);
     GetDFUOverSMP().ConfirmNewImage();
 #endif
@@ -201,7 +208,7 @@
     WindowCovering::Instance().PositionLEDUpdate(WindowCovering::MoveType::LIFT);
     WindowCovering::Instance().PositionLEDUpdate(WindowCovering::MoveType::TILT);
 
-    return err;
+    return CHIP_NO_ERROR;
 }
 
 CHIP_ERROR AppTask::StartApp()
@@ -213,47 +220,72 @@
     while (true)
     {
         k_msgq_get(&sAppEventQueue, &event, K_FOREVER);
-        DispatchEvent(&event);
+        DispatchEvent(event);
     }
 
     return CHIP_NO_ERROR;
 }
 
-void AppTask::ButtonEventHandler(uint32_t aButtonState, uint32_t aHasChanged)
+void AppTask::IdentifyStartHandler(Identify *)
 {
     AppEvent event;
-    event.Type = AppEvent::Type::Button;
+    event.Type    = AppEventType::IdentifyStart;
+    event.Handler = [](const AppEvent &) {
+        WindowCovering::Instance().GetLiftIndicator().SuppressOutput();
+        sIdentifyLED.Blink(LedConsts::kIdentifyBlinkRate_ms);
+    };
+    PostEvent(event);
+}
 
-    if (FUNCTION_BUTTON_MASK & aHasChanged)
+void AppTask::IdentifyStopHandler(Identify *)
+{
+    AppEvent event;
+    event.Type    = AppEventType::IdentifyStop;
+    event.Handler = [](const AppEvent &) {
+        sIdentifyLED.Set(false);
+        WindowCovering::Instance().GetLiftIndicator().ApplyLevel();
+    };
+    PostEvent(event);
+}
+
+void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)
+{
+    AppEvent event;
+    event.Type = AppEventType::Button;
+
+    if (FUNCTION_BUTTON_MASK & hasChanged)
     {
-        event.ButtonEvent.PinNo  = FUNCTION_BUTTON;
-        event.ButtonEvent.Action = (FUNCTION_BUTTON_MASK & aButtonState) ? BUTTON_PUSH_EVENT : BUTTON_RELEASE_EVENT;
-        event.Handler            = FunctionHandler;
-        PostEvent(&event);
+        event.ButtonEvent.PinNo = FUNCTION_BUTTON;
+        event.ButtonEvent.Action =
+            static_cast<uint8_t>((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased);
+        event.Handler = FunctionHandler;
+        PostEvent(event);
     }
 
-    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & aButtonState & aHasChanged)
+    if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged)
     {
         event.ButtonEvent.PinNo  = BLE_ADVERTISEMENT_START_BUTTON;
-        event.ButtonEvent.Action = BUTTON_PUSH_EVENT;
+        event.ButtonEvent.Action = static_cast<uint8_t>(AppEventType::ButtonPushed);
         event.Handler            = StartBLEAdvertisementHandler;
-        PostEvent(&event);
+        PostEvent(event);
     }
 
-    if (OPEN_BUTTON_MASK & aHasChanged)
+    if (OPEN_BUTTON_MASK & hasChanged)
     {
-        event.ButtonEvent.PinNo  = OPEN_BUTTON;
-        event.ButtonEvent.Action = (OPEN_BUTTON_MASK & aButtonState) ? BUTTON_PUSH_EVENT : BUTTON_RELEASE_EVENT;
-        event.Handler            = OpenHandler;
-        PostEvent(&event);
+        event.ButtonEvent.PinNo = OPEN_BUTTON;
+        event.ButtonEvent.Action =
+            static_cast<uint8_t>((OPEN_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased);
+        event.Handler = OpenHandler;
+        PostEvent(event);
     }
 
-    if (CLOSE_BUTTON_MASK & aHasChanged)
+    if (CLOSE_BUTTON_MASK & hasChanged)
     {
-        event.ButtonEvent.PinNo  = CLOSE_BUTTON;
-        event.ButtonEvent.Action = (CLOSE_BUTTON_MASK & aButtonState) ? BUTTON_PUSH_EVENT : BUTTON_RELEASE_EVENT;
-        event.Handler            = CloseHandler;
-        PostEvent(&event);
+        event.ButtonEvent.PinNo = CLOSE_BUTTON;
+        event.ButtonEvent.Action =
+            static_cast<uint8_t>((CLOSE_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased);
+        event.Handler = CloseHandler;
+        PostEvent(event);
     }
 }
 
@@ -261,103 +293,108 @@
 void AppTask::RequestSMPAdvertisingStart(void)
 {
     AppEvent event;
-    event.Type    = AppEvent::Type::StartSMPAdvertising;
-    event.Handler = [](AppEvent *) { GetDFUOverSMP().StartBLEAdvertising(); };
-    PostEvent(&event);
+    event.Type    = AppEventType::StartSMPAdvertising;
+    event.Handler = [](const AppEvent &) { GetDFUOverSMP().StartBLEAdvertising(); };
+    PostEvent(event);
 }
 #endif
 
-void AppTask::FunctionTimerTimeoutCallback(k_timer * aTimer)
+void AppTask::FunctionTimerTimeoutCallback(k_timer * timer)
 {
-    if (!aTimer)
+    if (!timer)
+    {
         return;
+    }
 
     AppEvent event;
-    event.Type               = AppEvent::Type::Timer;
-    event.TimerEvent.Context = k_timer_user_data_get(aTimer);
+    event.Type               = AppEventType::Timer;
+    event.TimerEvent.Context = k_timer_user_data_get(timer);
     event.Handler            = FunctionTimerEventHandler;
-    PostEvent(&event);
+    PostEvent(event);
 }
 
-void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
+void AppTask::FunctionTimerEventHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->Type != AppEvent::Type::Timer)
+    if (event.Type != AppEventType::Timer)
         return;
 
-    // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT, initiate factory reset
-    if (Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::Normal)
+    // If we reached here, the button was held past kFactoryResetTriggerTimeout, initiate factory reset
+    if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
     {
-        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_TRIGGER_TIMEOUT);
+        LOG_INF("Factory Reset Triggered. Release button within %ums to cancel.", kFactoryResetTriggerTimeout);
 
-        // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to cancel, if required.
-        StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
-        Instance().mMode = OperatingMode::FactoryReset;
+        // Start timer for kFactoryResetCancelWindowTimeout to allow user to cancel, if required.
+        Instance().StartTimer(kFactoryResetCancelWindowTimeout);
+        Instance().mFunction = FunctionEvent::FactoryReset;
 
 #ifdef CONFIG_STATE_LEDS
         // Turn off all LEDs before starting blink to make sure blink is co-ordinated.
         sStatusLED.Set(false);
-        sUnusedLeds.Set(false);
+        sFactoryResetLEDs.Set(false);
 
         sStatusLED.Blink(LedConsts::kBlinkRate_ms);
-        sUnusedLeds.Blink(LedConsts::kBlinkRate_ms);
+        sFactoryResetLEDs.Blink(LedConsts::kBlinkRate_ms);
 #endif
     }
-    else if (Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::FactoryReset)
+    else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
     {
         // Actually trigger Factory Reset
-        Instance().mMode = OperatingMode::Normal;
-        LOG_INF("Factory Reset triggered");
+        Instance().mFunction = FunctionEvent::NoneSelected;
+
         chip::Server::GetInstance().ScheduleFactoryReset();
     }
 }
 
-void AppTask::FunctionHandler(AppEvent * aEvent)
+void AppTask::FunctionHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->ButtonEvent.PinNo != FUNCTION_BUTTON)
+    if (event.ButtonEvent.PinNo != FUNCTION_BUTTON)
         return;
 
     // To initiate factory reset: press the FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT + FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
     // All LEDs start blinking after FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
     // To cancel factory reset: release the FUNCTION_BUTTON once all LEDs start blinking within the
     // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
-    if (aEvent->ButtonEvent.Action == BUTTON_PUSH_EVENT)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
     {
-        if (!Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::Normal)
+        if (!Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::NoneSelected)
         {
-            StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+            Instance().StartTimer(kFactoryResetTriggerTimeout);
+
+            Instance().mFunction = FunctionEvent::SoftwareUpdate;
         }
     }
     else
     {
-        if (Instance().mFunctionTimerActive && Instance().mMode == OperatingMode::FactoryReset)
+        // If the button was released before factory reset got initiated, trigger a software update.
+        if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::SoftwareUpdate)
         {
-            sUnusedLeds.Set(false);
+            Instance().CancelTimer();
 
-            UpdateStatusLED();
-            CancelTimer();
 #ifdef CONFIG_MCUMGR_SMP_BT
             GetDFUOverSMP().StartServer();
 #else
             LOG_INF("Software update is disabled");
 #endif
-            // Change the function to none selected since factory reset has been canceled.
-            Instance().mMode = OperatingMode::Normal;
+            Instance().mFunction = FunctionEvent::NoneSelected;
+        }
+        else if (Instance().mFunctionTimerActive && Instance().mFunction == FunctionEvent::FactoryReset)
+        {
+            sFactoryResetLEDs.Set(false);
 
+            UpdateStatusLED();
+            Instance().CancelTimer();
+            Instance().mFunction = FunctionEvent::NoneSelected;
             LOG_INF("Factory Reset has been Canceled");
         }
         else if (Instance().mFunctionTimerActive)
         {
             CancelTimer();
-            Instance().mMode = OperatingMode::Normal;
+            Instance().mFunction = FunctionEvent::NoneSelected;
         }
     }
 }
 
-void AppTask::StartBLEAdvertisementHandler(AppEvent *)
+void AppTask::StartBLEAdvertisementHandler(const AppEvent &)
 {
     if (Server::GetInstance().GetFabricTable().FabricCount() != 0)
     {
@@ -377,14 +414,12 @@
     }
 }
 
-void AppTask::OpenHandler(AppEvent * aEvent)
+void AppTask::OpenHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->ButtonEvent.PinNo != OPEN_BUTTON || Instance().mMode != OperatingMode::Normal)
+    if (event.ButtonEvent.PinNo != OPEN_BUTTON || Instance().mFunction != FunctionEvent::NoneSelected)
         return;
 
-    if (aEvent->ButtonEvent.Action == BUTTON_PUSH_EVENT)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
     {
         Instance().mOpenButtonIsPressed = true;
         if (Instance().mCloseButtonIsPressed)
@@ -392,7 +427,7 @@
             Instance().ToggleMoveType();
         }
     }
-    else if (aEvent->ButtonEvent.Action == BUTTON_RELEASE_EVENT)
+    else if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonReleased))
     {
         if (!Instance().mCloseButtonIsPressed)
         {
@@ -409,14 +444,12 @@
     }
 }
 
-void AppTask::CloseHandler(AppEvent * aEvent)
+void AppTask::CloseHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->ButtonEvent.PinNo != CLOSE_BUTTON || Instance().mMode != OperatingMode::Normal)
+    if (event.ButtonEvent.PinNo != CLOSE_BUTTON || Instance().mFunction != FunctionEvent::NoneSelected)
         return;
 
-    if (aEvent->ButtonEvent.Action == BUTTON_PUSH_EVENT)
+    if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed))
     {
         Instance().mCloseButtonIsPressed = true;
         if (Instance().mOpenButtonIsPressed)
@@ -424,7 +457,7 @@
             Instance().ToggleMoveType();
         }
     }
-    else if (aEvent->ButtonEvent.Action == BUTTON_RELEASE_EVENT)
+    else if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonReleased))
     {
         if (!Instance().mOpenButtonIsPressed)
         {
@@ -456,41 +489,39 @@
     mMoveTypeRecentlyChanged = true;
 }
 
-void AppTask::UpdateLedStateEventHandler(AppEvent * aEvent)
+void AppTask::UpdateLedStateEventHandler(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->Type == AppEvent::Type::UpdateLedState)
+    if (event.Type == AppEventType::UpdateLedState)
     {
-        aEvent->UpdateLedStateEvent.LedWidget->UpdateState();
+        event.UpdateLedStateEvent.LedWidget->UpdateState();
     }
 }
 
-void AppTask::LEDStateUpdateHandler(LEDWidget & aLedWidget)
+void AppTask::LEDStateUpdateHandler(LEDWidget & ledWidget)
 {
     AppEvent event;
-    event.Type                          = AppEvent::Type::UpdateLedState;
+    event.Type                          = AppEventType::UpdateLedState;
     event.Handler                       = UpdateLedStateEventHandler;
-    event.UpdateLedStateEvent.LedWidget = &aLedWidget;
-    PostEvent(&event);
+    event.UpdateLedStateEvent.LedWidget = &ledWidget;
+    PostEvent(event);
 }
 
 void AppTask::UpdateStatusLED()
 {
 #ifdef CONFIG_STATE_LEDS
-    /* Update the status LED.
-     *
-     * If thread and service provisioned, keep the LED On constantly.
-     *
-     * If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
-     * rate of 100ms.
-     *
-     * Otherwise, blink the LED On for a very short time. */
-    if (Instance().mIsThreadProvisioned && Instance().mIsThreadEnabled)
+    // Update the status LED.
+    //
+    // If thread and service provisioned, keep the LED On constantly.
+    //
+    // If the system has ble connection(s) uptill the stage above, THEN blink the LED at an even
+    // rate of 100ms.
+    //
+    // Otherwise, blink the LED On for a very short time.
+    if (sIsNetworkProvisioned && sIsNetworkEnabled)
     {
         sStatusLED.Set(true);
     }
-    else if (Instance().mHaveBLEConnections)
+    else if (sHaveBLEConnections)
     {
         sStatusLED.Blink(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms);
     }
@@ -501,15 +532,13 @@
 #endif
 }
 
-void AppTask::ChipEventHandler(const ChipDeviceEvent * aEvent, intptr_t)
+void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */)
 {
-    if (!aEvent)
-        return;
-    switch (aEvent->Type)
+    switch (event->Type)
     {
     case DeviceEventType::kCHIPoBLEAdvertisingChange:
 #ifdef CONFIG_CHIP_NFC_COMMISSIONING
-        if (aEvent->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
+        if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started)
         {
             if (NFCMgr().IsTagEmulationStarted())
             {
@@ -520,17 +549,17 @@
                 ShareQRCodeOverNFC(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
             }
         }
-        else if (aEvent->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
+        else if (event->CHIPoBLEAdvertisingChange.Result == kActivity_Stopped)
         {
             NFCMgr().StopTagEmulation();
         }
 #endif
-        Instance().mHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
+        sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
         UpdateStatusLED();
         break;
     case DeviceEventType::kThreadStateChange:
-        Instance().mIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
-        Instance().mIsThreadEnabled     = ConnectivityMgr().IsThreadEnabled();
+        sIsNetworkProvisioned = ConnectivityMgr().IsThreadProvisioned();
+        sIsNetworkEnabled     = ConnectivityMgr().IsThreadEnabled();
         UpdateStatusLED();
         break;
     case DeviceEventType::kDnssdPlatformInitialized:
@@ -549,29 +578,25 @@
     Instance().mFunctionTimerActive = false;
 }
 
-void AppTask::StartTimer(uint32_t aTimeoutInMs)
+void AppTask::StartTimer(uint32_t timeoutMs)
 {
-    k_timer_start(&sFunctionTimer, K_MSEC(aTimeoutInMs), K_NO_WAIT);
+    k_timer_start(&sFunctionTimer, K_MSEC(timeoutMs), K_NO_WAIT);
     Instance().mFunctionTimerActive = true;
 }
 
-void AppTask::PostEvent(AppEvent * aEvent)
+void AppTask::PostEvent(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT))
+    if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT))
     {
         LOG_INF("Failed to post event to app task event queue");
     }
 }
 
-void AppTask::DispatchEvent(AppEvent * aEvent)
+void AppTask::DispatchEvent(const AppEvent & event)
 {
-    if (!aEvent)
-        return;
-    if (aEvent->Handler)
+    if (event.Handler)
     {
-        aEvent->Handler(aEvent);
+        event.Handler(event);
     }
     else
     {
diff --git a/examples/window-app/nrfconnect/main/WindowCovering.cpp b/examples/window-app/nrfconnect/main/WindowCovering.cpp
index f1fd5a7..96320a6 100644
--- a/examples/window-app/nrfconnect/main/WindowCovering.cpp
+++ b/examples/window-app/nrfconnect/main/WindowCovering.cpp
@@ -27,7 +27,7 @@
 #include <zephyr/logging/log.h>
 #include <zephyr/zephyr.h>
 
-LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceLayer;
diff --git a/examples/window-app/nrfconnect/main/include/AppConfig.h b/examples/window-app/nrfconnect/main/include/AppConfig.h
index 7dadc1b..933cce3 100644
--- a/examples/window-app/nrfconnect/main/include/AppConfig.h
+++ b/examples/window-app/nrfconnect/main/include/AppConfig.h
@@ -29,3 +29,4 @@
 #define SYSTEM_STATE_LED DK_LED1
 #define LIFT_STATE_LED DK_LED2
 #define TILT_STATE_LED DK_LED3
+#define FACTORY_RESET_SIGNAL_LED DK_LED4
diff --git a/examples/window-app/nrfconnect/main/include/AppEvent.h b/examples/window-app/nrfconnect/main/include/AppEvent.h
index f6cac85..035a92c 100644
--- a/examples/window-app/nrfconnect/main/include/AppEvent.h
+++ b/examples/window-app/nrfconnect/main/include/AppEvent.h
@@ -19,22 +19,32 @@
 
 #include <cstdint>
 
+#include "EventTypes.h"
+
 class LEDWidget;
 
+enum class AppEventType : uint8_t
+{
+    None = 0,
+    Button,
+    ButtonPushed,
+    ButtonReleased,
+    Timer,
+    UpdateLedState,
+    IdentifyStart,
+    IdentifyStop,
+    StartSMPAdvertising
+};
+
+enum class FunctionEvent : uint8_t
+{
+    NoneSelected   = 0,
+    SoftwareUpdate = 0,
+    FactoryReset
+};
+
 struct AppEvent
 {
-    using EventHandler = void (*)(AppEvent *);
-
-    enum class Type : uint8_t
-    {
-        None,
-        Button,
-        Timer,
-        UpdateLedState,
-    };
-
-    Type Type{ Type::None };
-
     union
     {
         struct
@@ -52,5 +62,6 @@
         } UpdateLedStateEvent;
     };
 
+    AppEventType Type{ AppEventType::None };
     EventHandler Handler;
 };
diff --git a/examples/window-app/nrfconnect/main/include/AppTask.h b/examples/window-app/nrfconnect/main/include/AppTask.h
index a082c45..1d4adb0 100644
--- a/examples/window-app/nrfconnect/main/include/AppTask.h
+++ b/examples/window-app/nrfconnect/main/include/AppTask.h
@@ -17,6 +17,8 @@
 
 #pragma once
 
+#include "AppEvent.h"
+#include "LEDWidget.h"
 #include "WindowCovering.h"
 #include <platform/CHIPDeviceLayer.h>
 
@@ -24,9 +26,12 @@
 #include <platform/nrfconnect/FactoryDataProvider.h>
 #endif
 
+#ifdef CONFIG_MCUMGR_SMP_BT
+#include "dfu_over_smp.h"
+#endif
+
 struct k_timer;
-class AppEvent;
-class LEDWidget;
+struct Identify;
 
 class AppTask
 {
@@ -38,44 +43,42 @@
     };
     CHIP_ERROR StartApp();
 
+    static void IdentifyStartHandler(Identify *);
+    static void IdentifyStopHandler(Identify *);
+
 private:
-    enum class OperatingMode : uint8_t
-    {
-        Normal,
-        FactoryReset,
-        MoveSelection,
-        Movement,
-        Invalid
-    };
     CHIP_ERROR Init();
-    void DispatchEvent(AppEvent * aEvent);
     void ToggleMoveType();
 
-    // statics needed to interact with zephyr C API
     static void CancelTimer();
-    static void StartTimer(uint32_t aTimeoutInMs);
-    static void FunctionTimerEventHandler(AppEvent * aEvent);
-    static void MovementTimerEventHandler(AppEvent * aEvent);
-    static void FunctionHandler(AppEvent * aEvent);
-    static void ButtonEventHandler(uint32_t aButtonsState, uint32_t aHasChanged);
-    static void TimerTimeoutCallback(k_timer * aTimer);
-    static void FunctionTimerTimeoutCallback(k_timer * aTimer);
-    static void PostEvent(AppEvent * aEvent);
-    static void UpdateStatusLED();
-    static void LEDStateUpdateHandler(LEDWidget & aLedWidget);
-    static void UpdateLedStateEventHandler(AppEvent * aEvent);
-    static void StartBLEAdvertisementHandler(AppEvent * aEvent);
-    static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * aEvent, intptr_t aArg);
-    static void OpenHandler(AppEvent * aEvent);
-    static void CloseHandler(AppEvent * aEvent);
+    static void StartTimer(uint32_t timeoutMs);
 
-    OperatingMode mMode{ OperatingMode::Normal };
+    static void PostEvent(const AppEvent & event);
+    static void DispatchEvent(const AppEvent & event);
+    static void FunctionTimerEventHandler(const AppEvent & event);
+    static void FunctionHandler(const AppEvent & event);
+    static void UpdateLedStateEventHandler(const AppEvent & event);
+    static void StartBLEAdvertisementHandler(const AppEvent & event);
+    static void MovementTimerEventHandler(const AppEvent & event);
+    static void OpenHandler(const AppEvent & event);
+    static void CloseHandler(const AppEvent & event);
+
+    static void TimerTimeoutCallback(k_timer * timer);
+    static void FunctionTimerTimeoutCallback(k_timer * timer);
+    static void LEDStateUpdateHandler(LEDWidget & ledWidget);
+
+    static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+    static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged);
+    static void UpdateStatusLED();
+
+#ifdef CONFIG_MCUMGR_SMP_BT
+    static void RequestSMPAdvertisingStart(void);
+#endif
+
+    FunctionEvent mFunction{ FunctionEvent::NoneSelected };
     OperationalState mMoveType{ OperationalState::MovingUpOrOpen };
     bool mFunctionTimerActive{ false };
     bool mMovementTimerActive{ false };
-    bool mIsThreadProvisioned{ false };
-    bool mIsThreadEnabled{ false };
-    bool mHaveBLEConnections{ false };
     bool mOpenButtonIsPressed{ false };
     bool mCloseButtonIsPressed{ false };
     bool mMoveTypeRecentlyChanged{ false };
diff --git a/examples/window-app/nrfconnect/main/include/WindowCovering.h b/examples/window-app/nrfconnect/main/include/WindowCovering.h
index 99868a9..f03c691 100644
--- a/examples/window-app/nrfconnect/main/include/WindowCovering.h
+++ b/examples/window-app/nrfconnect/main/include/WindowCovering.h
@@ -49,6 +49,9 @@
         return sInstance;
     }
 
+    PWMDevice & GetLiftIndicator() { return mLiftIndicator; }
+    PWMDevice & GetTiltIndicator() { return mTiltIndicator; }
+
     void StartMove(MoveType aMoveType);
     void SetSingleStepTarget(OperationalState aDirection);
     void SetMoveType(MoveType aMoveType) { mCurrentUIMoveType = aMoveType; }
diff --git a/examples/window-app/nrfconnect/main/main.cpp b/examples/window-app/nrfconnect/main/main.cpp
index 4023350..4cbd697 100644
--- a/examples/window-app/nrfconnect/main/main.cpp
+++ b/examples/window-app/nrfconnect/main/main.cpp
@@ -19,7 +19,7 @@
 
 #include <zephyr/logging/log.h>
 
-LOG_MODULE_REGISTER(app, CONFIG_MATTER_LOG_LEVEL);
+LOG_MODULE_REGISTER(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 using namespace ::chip;
 
diff --git a/examples/window-app/nrfconnect/prj.conf b/examples/window-app/nrfconnect/prj.conf
index bb8601b..a284009 100644
--- a/examples/window-app/nrfconnect/prj.conf
+++ b/examples/window-app/nrfconnect/prj.conf
@@ -14,15 +14,17 @@
 #    limitations under the License.
 #
 
+# Enable CHIP
 CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32784 == 0x8010 (example window-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
 CONFIG_STD_CPP14=y
 
-# This sample uses Kconfig.defaults 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
+
+# PWM support
 CONFIG_PWM=y
 
 # OpenThread configs
@@ -34,15 +36,13 @@
 CONFIG_CHIP_SED_IDLE_INTERVAL=500
 CONFIG_CHIP_SED_ACTIVE_INTERVAL=500
 
-# Bluetooth overrides
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterWinCov"
 
-# Additional configs for debbugging experience.
+# Stack size settings
+CONFIG_IEEE802154_NRF5_RX_STACK_SIZE=1024
+
+# Other settings
 CONFIG_THREAD_NAME=y
 CONFIG_MPU_STACK_GUARD=y
 CONFIG_RESET_ON_FATAL_ERROR=n
-
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32784 == 0x8010 (example window-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
diff --git a/examples/window-app/nrfconnect/prj_no_dfu.conf b/examples/window-app/nrfconnect/prj_no_dfu.conf
index f2787a7..3f55608 100644
--- a/examples/window-app/nrfconnect/prj_no_dfu.conf
+++ b/examples/window-app/nrfconnect/prj_no_dfu.conf
@@ -14,17 +14,24 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32784 == 0x8010 (example window-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
+CONFIG_STD_CPP14=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 CONFIG_PWM=y
 
+# PWM support
+CONFIG_PWM=y
+
 # OpenThread configs
 CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
 CONFIG_OPENTHREAD_MTD=y
@@ -34,10 +41,13 @@
 CONFIG_CHIP_SED_IDLE_INTERVAL=500
 CONFIG_CHIP_SED_ACTIVE_INTERVAL=500
 
-# Bluetooth overrides
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterWinCov"
 
-# Additional configs for debbugging experience.
+# Stack size settings
+CONFIG_IEEE802154_NRF5_RX_STACK_SIZE=1024
+
+# Other settings
 CONFIG_THREAD_NAME=y
 CONFIG_MPU_STACK_GUARD=y
 CONFIG_RESET_ON_FATAL_ERROR=n
@@ -45,7 +55,5 @@
 # Disable Matter OTA DFU
 CONFIG_CHIP_OTA_REQUESTOR=n
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32784 == 0x8010 (example window-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
+# Disable QSPI NOR
+CONFIG_CHIP_QSPI_NOR=n
diff --git a/examples/window-app/nrfconnect/prj_release.conf b/examples/window-app/nrfconnect/prj_release.conf
index caf0ee1..c801e2f 100644
--- a/examples/window-app/nrfconnect/prj_release.conf
+++ b/examples/window-app/nrfconnect/prj_release.conf
@@ -14,17 +14,24 @@
 #    limitations under the License.
 #
 
-CONFIG_CHIP=y
-CONFIG_STD_CPP14=y
-
 # This sample uses Kconfig.defaults to set options common for all
 # samples. This file should contain only options specific for this sample
 # or overrides of default values.
 
+# Enable CHIP
+CONFIG_CHIP=y
+CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
+# 32784 == 0x8010 (example window-app)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
+CONFIG_STD_CPP14=y
+
 # Add support for LEDs and buttons on Nordic development kits
 CONFIG_DK_LIBRARY=y
 CONFIG_PWM=y
 
+# PWM support
+CONFIG_PWM=y
+
 # OpenThread configs
 CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
 CONFIG_OPENTHREAD_MTD=y
@@ -34,16 +41,14 @@
 CONFIG_CHIP_SED_IDLE_INTERVAL=500
 CONFIG_CHIP_SED_ACTIVE_INTERVAL=500
 
-# Bluetooth overrides
+# Bluetooth Low Energy configuration
 CONFIG_BT_DEVICE_NAME="MatterWinCov"
 
 # Enable system reset on fatal error
 CONFIG_RESET_ON_FATAL_ERROR=y
 
-# CHIP configuration
-CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h"
-# 32784 == 0x8010 (example window-app)
-CONFIG_CHIP_DEVICE_PRODUCT_ID=32784
+# Stack size settings
+CONFIG_IEEE802154_NRF5_RX_STACK_SIZE=1024
 
 # Suspend devices when the CPU goes into sleep
 CONFIG_PM_DEVICE=y
@@ -56,7 +61,8 @@
 CONFIG_SERIAL=n
 CONFIG_LOG=n
 CONFIG_LOG_MODE_MINIMAL=n
-CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_ASSERT_VERBOSE=n
+CONFIG_ASSERT_NO_FILE_INFO=y
 CONFIG_PRINTK=n
+CONFIG_PRINTK_SYNC=n
 CONFIG_THREAD_NAME=n