diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index ecfcc8a2fa5b48..4b9430d38a4b96 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -192,6 +192,41 @@ jobs: 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 e4a0a9f3a1abab..ee51bfb15f4b99 100644 --- a/config/nrfconnect/chip-module/Kconfig +++ b/config/nrfconnect/chip-module/Kconfig @@ -18,6 +18,15 @@ rsource "../../zephyr/Kconfig" 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 c7c5b356a160d9..048855d23e2263 100644 --- a/config/zephyr/Kconfig +++ b/config/zephyr/Kconfig @@ -154,10 +154,10 @@ config CHIP_SED_ACTIVE_INTERVAL 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 0e2146ba980b8f..21096da4d2bab6 100644 --- a/docs/guides/nrfconnect_android_commissioning.md +++ b/docs/guides/nrfconnect_android_commissioning.md @@ -6,9 +6,9 @@ example for the nRF Connect platform into a Matter fabric. 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.
@@ -68,6 +68,7 @@ accessory using Android CHIPTool: 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 e065613e4ef577..abcd8fb5060011 100644 --- a/examples/all-clusters-app/nrfconnect/CMakeLists.txt +++ b/examples/all-clusters-app/nrfconnect/CMakeLists.txt @@ -25,6 +25,7 @@ include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) # 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 9fcdb41ab33208..33919ac5fc2337 100644 --- a/examples/all-clusters-app/nrfconnect/Kconfig +++ b/examples/all-clusters-app/nrfconnect/Kconfig @@ -22,6 +22,19 @@ config STATE_LEDS 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 b0befaebaa1a8d..8f4eb0422a4326 100644 --- a/examples/all-clusters-app/nrfconnect/README.md +++ b/examples/all-clusters-app/nrfconnect/README.md @@ -10,12 +10,14 @@ creating your own application. 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.
@@ -24,6 +26,7 @@ device works as a Thread Minimal End Device. - [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 @@ and [Zephyr RTOS](https://zephyrproject.org/). Visit Matter's [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md) to read more about the platform structure and dependencies. -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 @@ commissioner role. To start the rendezvous, the controller must get the commissioning information from the Matter device. The data payload is encoded within a QR code, printed to -the UART console. +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.
@@ -100,14 +115,24 @@ more information. The example supports building and running on the following devices: -| Hardware platform | Build target | Platform image | -| ------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` |
nRF52840 DKnRF52840 DK
| -| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` |
nRF5340 DKnRF5340 DK
| -| [nRF52840 Dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) | `nrf52840dongle_nrf52840` |
nRF52840 DonglenRF52840 Dongle
| +| Hardware platform | Build target | Platform image | +| --------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` |
nRF52840 DKnRF52840 DK
| +| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` |
nRF5340 DKnRF5340 DK
| +| [nRF52840 Dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) | `nrf52840dongle_nrf52840` |
nRF52840 DonglenRF52840 Dongle
| +| [nRF7002 DK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf7002.html#nrf7002dk-nrf5340) | `nrf7002dk_nrf5340_cpuapp` |
nRF7002DKnRF7002 DK
|
+### 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`. + ## Device UI @@ -137,21 +162,42 @@ following states are possible: Bluetooth LE. - _Short Flash Off (950ms on/50ms off)_ — The device is fully - provisioned, but does not yet have full Thread network or service - connectivity. + provisioned, but does not yet have full connectivity for Thread or Wi-Fi + network. -- _Solid On_ — The device is fully provisioned and has full Thread - network and service connectivity. +- _Solid On_ — The device is fully provisioned. **Button 1** can be used for the following purposes: -- _Pressed for 6 s_ — Initiates the factory reset of the device. - Releasing the button within the 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_ — 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. + +- _Pressed for more than 3 s_ — 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. -**Button 4** — Pressing the button once starts Bluetooth LE advertising -for the predefined period of time (15 minutes by default). +- 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 04253ef9667617..566236731653a5 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 00000000000000..3063fbbcdee779 --- /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 00000000000000..1622ffd00dbb91 --- /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 00000000000000..1622ffd00dbb91 --- /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 00000000000000..1622ffd00dbb91 --- /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 00000000000000..3c56dc0ddb1968 --- /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 40b987b620332d..f8646a19f7bd94 100644 --- a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp @@ -36,6 +36,11 @@ #include #include +#ifdef CONFIG_CHIP_WIFI +#include +#include +#endif + #if CONFIG_CHIP_OTA_REQUESTOR #include "OTAUtil.h" #endif @@ -44,72 +49,48 @@ #include #include +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 @@ constexpr uint32_t kOff_ms{ 950 }; } // 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 @@ CHIP_ERROR AppTask::Init() 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 @@ CHIP_ERROR AppTask::Init() } // 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 @@ CHIP_ERROR AppTask::StartApp() 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); +} + +void AppTask::IdentifyStopHandler(Identify *) +{ + AppEvent event; + event.Type = AppEventType::IdentifyStop; + event.Handler = [](const AppEvent &) { sIdentifyLED.Set(false); }; + PostEvent(event); +} - if (FUNCTION_BUTTON_MASK & aHasChanged) +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(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((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) + if (event.Type != AppEventType::Timer || !Instance().mFunctionTimerActive) + { 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().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. + // 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(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::StartBLEAdvertisementHandler(AppEvent *) } } -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 @@ void AppTask::UpdateStatusLED() #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; - UpdateStatusLED(); - break; - case DeviceEventType::kThreadStateChange: - Instance().mIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned(); - Instance().mIsThreadEnabled = ConnectivityMgr().IsThreadEnabled(); +#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; +#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 @@ void AppTask::StartTimer(uint32_t aTimeoutInMs) 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 01465d3bb17a62..91b8ad96cbc05b 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 f6cac85b182b32..ccefe5d52bbdac 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 +#include "EventTypes.h" + class LEDWidget; -struct AppEvent +enum class AppEventType : uint8_t { - using EventHandler = void (*)(AppEvent *); - - enum class Type : uint8_t - { - None, - Button, - Timer, - UpdateLedState, - }; + None = 0, + Button, + ButtonPushed, + ButtonReleased, + Timer, + UpdateLedState, + IdentifyStart, + IdentifyStop, + StartSMPAdvertising +}; - Type Type{ Type::None }; +enum class FunctionEvent : uint8_t +{ + NoneSelected = 0, + SoftwareUpdate = 0, + FactoryReset, + AdvertisingStart +}; +struct AppEvent +{ union { struct @@ -47,10 +58,16 @@ struct AppEvent void * Context; } 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 04f44f41e49551..72e87e480f9fc1 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 +#include "AppEvent.h" +#include "LEDWidget.h" + #if CONFIG_CHIP_FACTORY_DATA #include #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 @@ class AppTask }; CHIP_ERROR StartApp(); -private: - enum class OperatingMode : uint8_t - { - Normal, - FactoryReset, - Invalid - }; + static void IdentifyStartHandler(Identify *); + static void IdentifyStopHandler(Identify *); + + static void PostEvent(const AppEvent & event); +private: 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 mFactoryDataProvider; diff --git a/examples/all-clusters-app/nrfconnect/main/main.cpp b/examples/all-clusters-app/nrfconnect/main/main.cpp index 8563856d1cffd6..400f9b30e0dd01 100644 --- a/examples/all-clusters-app/nrfconnect/main/main.cpp +++ b/examples/all-clusters-app/nrfconnect/main/main.cpp @@ -24,7 +24,7 @@ #include #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 f56965b831a7cf..ee2bee67b64ce4 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 @@ CONFIG_CHIP_OTA_REQUESTOR=n # 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 9738e9fc77ae7a..b91bf3fa8298a6 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_THREAD_NAME=y 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 d9905e84464429..5816426f0fc09e 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 9fcdb41ab33208..33919ac5fc2337 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/Kconfig +++ b/examples/all-clusters-minimal-app/nrfconnect/Kconfig @@ -22,6 +22,19 @@ config STATE_LEDS 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 5f2d742502ed81..a8430950ab9c5c 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/README.md +++ b/examples/all-clusters-minimal-app/nrfconnect/README.md @@ -55,11 +55,17 @@ and [Zephyr RTOS](https://zephyrproject.org/). Visit Matter's [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md) to read more about the platform structure and dependencies. -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 @@ following states are possible: Bluetooth LE. - _Short Flash Off (950ms on/50ms off)_ — The device is fully - provisioned, but does not yet have full Thread network or service - connectivity. + provisioned, but does not yet have full connectivity for Thread or Wi-Fi + network, or the related services. - _Solid On_ — 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 04253ef9667617..566236731653a5 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 b78d291f1b74c0..25c4190544a18a 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 #include +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 - -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 kNetworkCommissioningEndpointSecondary = 0xFFFE; -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 @@ CHIP_ERROR AppTask::Init() } // 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 @@ CHIP_ERROR AppTask::StartApp() 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((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(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(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(); - - // Change the function to none selected since factory reset has been canceled. - Instance().mMode = OperatingMode::Normal; +#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(); + 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::StartBLEAdvertisementHandler(AppEvent *) } } -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 @@ void AppTask::UpdateStatusLED() #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 @@ void AppTask::StartTimer(uint32_t aTimeoutInMs) 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 01465d3bb17a62..e36ebba4e03d81 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 f6cac85b182b32..4589d636a4decf 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 +#include "EventTypes.h" + class LEDWidget; -struct AppEvent +enum class AppEventType : uint8_t { - using EventHandler = void (*)(AppEvent *); - - enum class Type : uint8_t - { - None, - Button, - Timer, - UpdateLedState, - }; + None = 0, + Button, + ButtonPushed, + ButtonReleased, + Timer, + UpdateLedState, + IdentifyStart, + IdentifyStop, + StartSMPAdvertising +}; - Type Type{ Type::None }; +enum class FunctionEvent : uint8_t +{ + NoneSelected = 0, + SoftwareUpdate = 0, + FactoryReset, + AdvertisingStart +}; +struct AppEvent +{ union { struct @@ -52,5 +63,6 @@ struct AppEvent } 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 04f44f41e49551..94a3de35f04038 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 +#include "AppEvent.h" +#include "LEDWidget.h" + #if CONFIG_CHIP_FACTORY_DATA #include #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 @@ class AppTask 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 mFactoryDataProvider; diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/main.cpp b/examples/all-clusters-minimal-app/nrfconnect/main/main.cpp index 8f71ca55e41070..ec11d180c8c911 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 #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 496ca240bc3ecd..2c2c8d2fc81c28 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 @@ CONFIG_CHIP_OTA_REQUESTOR=n # 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 3812357495deb6..292d7a086d4e89 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_THREAD_NAME=y 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 27667cbafad79b..33cd3f38589653 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 b4210cbc069083..58c380e4d83c9f 100644 --- a/examples/light-switch-app/nrfconnect/CMakeLists.txt +++ b/examples/light-switch-app/nrfconnect/CMakeLists.txt @@ -25,6 +25,7 @@ include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) # 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 8b4d87b0a956f0..042bdac8f72b68 100644 --- a/examples/light-switch-app/nrfconnect/Kconfig +++ b/examples/light-switch-app/nrfconnect/Kconfig @@ -23,6 +23,23 @@ config STATE_LEDS 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 7d55b031e6b73d..7aef1f6742fcb4 100644 --- a/examples/light-switch-app/nrfconnect/README.md +++ b/examples/light-switch-app/nrfconnect/README.md @@ -15,12 +15,16 @@ creating your own application. The example is based on [Matter](https://github.com/project-chip/connectedhomeip) and Nordic -Semiconductor's nRF Connect SDK, and supports remote access and control of a -lighting examples over a low-power, 802.15.4 Thread network. +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.
@@ -30,6 +34,7 @@ device works as a Thread Sleepy End Device. - [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 @@ device works as a Thread Sleepy End Device. - [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)
@@ -62,6 +72,27 @@ and [Zephyr RTOS](https://zephyrproject.org/). Visit Matter's [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md) to read more about the platform structure and dependencies. +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 @@ features. For this reason, it sends event notifications `InitialPress` and 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 @@ performing over-the-air Device Firmware Upgrade using Bluetooth LE. 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 @@ commissioner role. To start the rendezvous, the controller must get the commissioning information from the Matter device. The data payload is encoded within a QR code, printed to -the UART console, and shared using an NFC tag. NFC tag emulation starts -automatically when Bluetooth LE advertising is started and stays enabled until -Bluetooth LE advertising timeout expires. +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 @@ more information. The example supports building and running on the following devices: -| Hardware platform | Build target | Platform image | -| ----------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` |
nRF52840 DKnRF52840 DK
| -| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` |
nRF5340 DKnRF5340 DK
| +| Hardware platform | Build target | Platform image | +| --------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` |
nRF52840 DKnRF52840 DK
| +| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` |
nRF5340 DKnRF5340 DK
| +| [nRF7002 DK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf7002.html#nrf7002dk-nrf5340) | `nrf7002dk_nrf5340_cpuapp` |
nRF7002DKnRF7002 DK
| + +### 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 @@ following states are possible: Bluetooth LE. - _Short Flash Off (950ms on/50ms off)_ — The device is fully - provisioned, but does not yet have full Thread network or service - connectivity. + provisioned, but does not yet have full connectivity for Thread or Wi-Fi + network. -- _Solid On_ — The device is fully provisioned and has full Thread - network and service connectivity. +- _Solid On_ — The device is fully provisioned. **LED 2** simulates the BLE DFU process. The following states are possible: @@ -259,10 +303,9 @@ following states are possible: - _Rapid Even Flashing (30 ms off / 170 ms on)_ — BLE is advertising, DFU process can be started. -**LED 3** can be used to identify the device. The LED starts blinking evenly -(500 ms on/500 ms off) when the Identify command of the Identify cluster is -received. The command's argument can be used to specify the duration of the -effect. +**All LEDs** + +Blink in unison when the factory reset procedure is initiated. ### Buttons @@ -271,36 +314,58 @@ platform image. **Button 1** can be used for the following purposes: -- _Pressed for 6 s_ — Initiates the factory reset of the device. - Releasing the button within the 3-second window cancels the factory reset - procedure. **LEDs 1-4** blink in unison when the factory reset procedure is - initiated. - - _Pressed for less than 3 s_ — Initiates the OTA software update process. This feature is disabled by default, but can be enabled by following the [Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support) - instruction. + instructions. + +- _Pressed for more than 3 s_ — 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_ — 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: + + - 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. + +- On nRF7002 DK: + + - 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** -- _Pressed for more than 2 s_ — Changes the brightness of the light on a - bound lighting bulb device ([lighting-app](../../lighting-app/nrfconnect/) - example) (dimmer functionality). The brightness is changing from 0% to 100% - with 1% increments every 300 milliseconds as long as **Button 2** is - pressed. +- On nRF52840 DK, nRF5340 DK and nRF21540 DK: -**Button 3** can be used for the following purposes: + 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. -- _Pressed once_ — 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). + 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 00000000000000..90f303f82cc4e0 --- /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 00000000000000..1622ffd00dbb91 --- /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 00000000000000..1622ffd00dbb91 --- /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 00000000000000..1622ffd00dbb91 --- /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 287c7829c6a5cf..0dbf7106e88e22 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 @@ CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" # 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 287c7829c6a5cf..0dbf7106e88e22 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 @@ CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" # 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 00000000000000..3c56dc0ddb1968 --- /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 4eee5a57bfef8d..3ba17c73a5c147 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 @@ -34,6 +35,11 @@ #include #include +#ifdef CONFIG_CHIP_WIFI +#include +#include +#endif + #ifdef CONFIG_CHIP_OTA_REQUESTOR #include "OTAUtil.h" #endif @@ -42,23 +48,23 @@ #include #include +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 @@ uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = 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 */ - -AppTask AppTask::sAppTask; +} // 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 }; +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 @@ CHIP_ERROR AppTask::Init() 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 @@ CHIP_ERROR AppTask::Init() // 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 @@ CHIP_ERROR AppTask::Init() } // 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 @@ CHIP_ERROR AppTask::StartApp() 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::ButtonPushHandler(AppEvent * aEvent) } } -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(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(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::TimerEventHandler(AppEvent * aEvent) 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 @@ void AppTask::StartBLEAdvertisingHandler(AppEvent * aEvent) 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 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * aEvent, intptr_t /* arg * } 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 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * aEvent, intptr_t /* arg * 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 +#endif // CONFIG_CHIP_OTA_REQUESTOR break; - default: - if ((ConnectivityMgr().NumBLEConnections() == 0) && (!sIsThreadProvisioned || !sIsThreadEnabled)) + 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) { - LOG_ERR("Commissioning with a Thread network has not been done. An error occurred..."); - sIsThreadBLEAdvertising = false; - sHaveBLEConnections = false; - UpdateStatusLED(); + InitBasicOTARequestor(); } +#endif // CONFIG_CHIP_OTA_REQUESTOR +#endif + UpdateStatusLED(); + break; + default: break; } } @@ -441,127 +480,106 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * aEvent, intptr_t /* arg * 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(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(AppEventType::ButtonReleased); buttonEvent.Handler = ButtonReleaseHandler; - sAppTask.PostEvent(&buttonEvent); + PostEvent(buttonEvent); } - if (DIMMER_SWITCH_BUTTON_MASK & aButtonState & aHasChanged) - { - buttonEvent.ButtonEvent.PinNo = DIMMER_SWITCH_BUTTON; - buttonEvent.ButtonEvent.Action = AppEvent::kButtonPushEvent; - buttonEvent.Handler = ButtonPushHandler; - sAppTask.PostEvent(&buttonEvent); - } - else if (DIMMER_SWITCH_BUTTON_MASK & aHasChanged) - { - buttonEvent.ButtonEvent.PinNo = DIMMER_SWITCH_BUTTON; - buttonEvent.ButtonEvent.Action = AppEvent::kButtonReleaseEvent; - buttonEvent.Handler = ButtonReleaseHandler; - sAppTask.PostEvent(&buttonEvent); - } +#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 (GENERIC_SWITCH_BUTTON_MASK & aButtonState & aHasChanged) + if (buttonMask & buttonState & hasChanged) { - buttonEvent.ButtonEvent.PinNo = GENERIC_SWITCH_BUTTON; - buttonEvent.ButtonEvent.Action = AppEvent::kButtonPushEvent; + buttonEvent.ButtonEvent.Action = static_cast(AppEventType::ButtonPushed); buttonEvent.Handler = ButtonPushHandler; - sAppTask.PostEvent(&buttonEvent); + PostEvent(buttonEvent); } - else if (GENERIC_SWITCH_BUTTON_MASK & aHasChanged) + else if (buttonMask & hasChanged) { - buttonEvent.ButtonEvent.PinNo = GENERIC_SWITCH_BUTTON; - buttonEvent.ButtonEvent.Action = AppEvent::kButtonReleaseEvent; + buttonEvent.ButtonEvent.Action = static_cast(AppEventType::ButtonReleased); buttonEvent.Handler = ButtonReleaseHandler; - sAppTask.PostEvent(&buttonEvent); + 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(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::CancelTimer(Timer aTimer) } } -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::TimerEventHandler(k_timer * aTimer) 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 fd435cd0014243..3dc8efee96963e 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 -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 @@ void BindingHandler::LightSwitchChangedHandler(const EmberBindingTableEntry & bi 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 @@ void BindingHandler::LightSwitchChangedHandler(const EmberBindingTableEntry & bi 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 7e71ce1fa1381f..4b94870dc35166 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 4a2bd347290703..b3248e3e0c29d6 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 -#include "LEDWidget.h" +#include "EventTypes.h" -struct AppEvent; -typedef void (*EventHandler)(AppEvent *); +class LEDWidget; -struct AppEvent +enum class AppEventType : uint8_t { + None = 0, + Button, + ButtonPushed, + ButtonReleased, + Timer, + UpdateLedState, + IdentifyStart, + IdentifyStop, + StartSMPAdvertising +}; - 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; +enum class FunctionEvent : uint8_t +{ + NoneSelected = 0, + SoftwareUpdate = 0, + FactoryReset +}; +struct AppEvent +{ union { struct @@ -63,5 +63,6 @@ struct AppEvent } 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 06f9e1d574cb0a..6d464638f11e7a 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 @@ struct Identify; 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 @@ class AppTask DimmerTrigger, Dimmer }; - enum class TimerFunction : uint8_t - { - NoneSelected = 0, - SoftwareUpdate, - FactoryReset, - }; - TimerFunction mFunction = TimerFunction::NoneSelected; - enum class Button : uint8_t { Function, Dimmer, }; - friend AppTask & GetAppTask(); - static AppTask sAppTask; - CHIP_ERROR Init(); - void DispatchEvent(AppEvent *); - - static void ButtonPushHandler(AppEvent *); - static void ButtonReleaseHandler(AppEvent *); - static void TimerEventHandler(AppEvent *); - static void StartBLEAdvertisingHandler(AppEvent *); - static void UpdateLedStateEventHandler(AppEvent *); - - static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent *, intptr_t); + static void 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 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 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 ffd8d9b208940c..f152bdb75be4d2 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 e463898978fb91..4e114745604035 100644 --- a/examples/light-switch-app/nrfconnect/main/main.cpp +++ b/examples/light-switch-app/nrfconnect/main/main.cpp @@ -20,13 +20,13 @@ #include -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 45e06e243f28bf..19f3cb266a6abc 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. +# 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 - -# CHIP configuration -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -# 32772 == 0x8004 (example light-switch-app) -CONFIG_CHIP_DEVICE_PRODUCT_ID=32772 diff --git a/examples/light-switch-app/nrfconnect/prj_no_dfu.conf b/examples/light-switch-app/nrfconnect/prj_no_dfu.conf index fe1305f9c5eb8b..27475ce596444c 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 @@ 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" -# 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 b9ff24ac0eceb2..a55449c991b17c 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_UART_CONSOLE=n 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 02ee050825841e..81e2bd7f42c0cc 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -25,6 +25,7 @@ include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) # 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 94a99f971ac195..6a35f3b1115437 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 0c25aba55ff94b..29f15ea497d37f 100644 --- a/examples/lighting-app/nrfconnect/README.md +++ b/examples/lighting-app/nrfconnect/README.md @@ -10,12 +10,15 @@ a reference for creating your own application. The example is based on [Matter](https://github.com/project-chip/connectedhomeip) and Nordic -Semiconductor's nRF Connect SDK, and supports remote access and control of a -lighting 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.
@@ -25,6 +28,7 @@ device works as a Thread Router. - [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 @@ and [Zephyr RTOS](https://zephyrproject.org/). Visit Matter's [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md) to read more about the platform structure and dependencies. -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 @@ commissioner role. To start the rendezvous, the controller must get the commissioning information from the Matter device. The data payload is encoded within a QR code, printed to -the UART console, and shared using an NFC tag. NFC tag emulation starts -automatically when Bluetooth LE advertising is started and stays enabled until -Bluetooth LE advertising timeout expires. +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 @@ more information. The example supports building and running on the following devices: -| Hardware platform | Build target | Platform image | -| ------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` |
nRF52840 DKnRF52840 DK
| -| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` |
nRF5340 DKnRF5340 DK
| -| [nRF52840 Dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) | `nrf52840dongle_nrf52840` |
nRF52840 DonglenRF52840 Dongle
| +| Hardware platform | Build target | Platform image | +| --------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` |
nRF52840 DKnRF52840 DK
| +| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` |
nRF5340 DKnRF5340 DK
| +| [nRF52840 Dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) | `nrf52840dongle_nrf52840` |
nRF52840 DonglenRF52840 Dongle
| +| [nRF7002 DK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf7002.html#nrf7002dk-nrf5340) | `nrf7002dk_nrf5340_cpuapp` |
nRF7002DKnRF7002 DK
|
+### 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`. + ## Device UI @@ -203,11 +233,10 @@ following states are possible: Bluetooth LE. - _Short Flash Off (950ms on/50ms off)_ — The device is fully - provisioned, but does not yet have full Thread network or service - connectivity. + provisioned, but does not yet have full connectivity for Thread or Wi-Fi + network. -- _Solid On_ — The device is fully provisioned and has full Thread - network and service connectivity. +- _Solid On_ — 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 @@ following states are possible: - _Off_ — 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_ — 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_ — 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_ — 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_ — initiates the factory reset of the + device. Releasing the button within the 3-second window cancels the factory + reset procedure. **Button 2** — Pressing the button once changes the lighting state to the opposite one. -**Button 4** — 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 00000000000000..481ff46231e7d1 --- /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 = ; + nordic,invert; + }; + }; + + pwm0_sleep_alt: pwm0_sleep_alt { + group1 { + psels = ; + 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 00000000000000..1622ffd00dbb91 --- /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 00000000000000..1622ffd00dbb91 --- /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 00000000000000..1622ffd00dbb91 --- /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 287c7829c6a5cf..0dbf7106e88e22 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 @@ CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" # 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 287c7829c6a5cf..0dbf7106e88e22 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 @@ CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" # 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 00000000000000..3c56dc0ddb1968 --- /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 1ee75869d3ddfc..15ab885139e20b 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 @@ -41,6 +41,11 @@ #include #include +#ifdef CONFIG_CHIP_WIFI +#include +#include +#endif + #if CONFIG_CHIP_OTA_REQUESTOR #include "OTAUtil.h" #endif @@ -49,7 +54,7 @@ #include #include -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 @@ namespace { 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 @@ Identify sIdentify = { kLightEndpointId, AppTask::IdentifyStartHandler, AppTask: 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 @@ DeferredAttributePersistenceProvider gDeferredAttributePersister(Server::GetInst } // 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,36 +166,24 @@ CHIP_ERROR AppTask::Init() 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 lighting device (PWM) - uint8_t minLightLevel = kDefaultMinLevel; - Clusters::LevelControl::Attributes::MinLevel::Get(kLightEndpointId, &minLightLevel); - - uint8_t maxLightLevel = kDefaultMaxLevel; - Clusters::LevelControl::Attributes::MaxLevel::Get(kLightEndpointId, &maxLightLevel); - - int 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); + int ret = dk_buttons_init(ButtonEventHandler); if (ret) { LOG_ERR("dk_buttons_init() failed"); @@ -176,7 +191,7 @@ CHIP_ERROR AppTask::Init() } // 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 @@ -185,6 +200,20 @@ CHIP_ERROR AppTask::Init() GetDFUOverSMP().ConfirmNewImage(); #endif + // Initialize lighting device (PWM) + uint8_t minLightLevel = kDefaultMinLevel; + Clusters::LevelControl::Attributes::MinLevel::Get(kLightEndpointId, &minLightLevel); + + uint8_t maxLightLevel = kDefaultMaxLevel; + Clusters::LevelControl::Attributes::MaxLevel::Get(kLightEndpointId, &maxLightLevel); + + ret = mPWMDevice.Init(&sLightPwmDevice, minLightLevel, maxLightLevel, maxLightLevel); + if (ret != 0) + { + return chip::System::MapErrorZephyr(ret); + } + mPWMDevice.SetCallbacks(ActionInitiated, ActionCompleted); + // Initialize CHIP server #if CONFIG_CHIP_FACTORY_DATA ReturnErrorOnFailure(mFactoryDataProvider.Init()); @@ -239,132 +268,195 @@ CHIP_ERROR AppTask::StartApp() while (true) { k_msgq_get(&sAppEventQueue, &event, K_FOREVER); - DispatchEvent(&event); + DispatchEvent(event); } return CHIP_NO_ERROR; } -void AppTask::LightingActionEventHandler(AppEvent * aEvent) +void AppTask::IdentifyStartHandler(Identify *) +{ + AppEvent 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 = AppEventType::IdentifyStop; + event.Handler = [](const AppEvent &) { + sIdentifyLED.Set(false); + Instance().mPWMDevice.ApplyLevel(); + }; + PostEvent(event); +} + +#if NUMBER_OF_BUTTONS == 2 +void AppTask::StartBLEAdvertisementAndLightActionEventHandler(const AppEvent & event) +{ + if (event.ButtonEvent.Action == static_cast(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(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 (aEvent->Type == AppEvent::kEventType_Lighting) + if (event.Type == AppEventType::Lighting) { - action = static_cast(aEvent->LightingEvent.Action); - actor = aEvent->LightingEvent.Actor; + action = static_cast(event.LightingEvent.Action); + actor = event.LightingEvent.Actor; } - else if (aEvent->Type == AppEvent::kEventType_Button) + else if (event.Type == AppEventType::Button) { - action = GetAppTask().mPWMDevice.IsTurnedOn() ? PWMDevice::OFF_ACTION : PWMDevice::ON_ACTION; - actor = AppEvent::kEventType_Button; + action = Instance().mPWMDevice.IsTurnedOn() ? PWMDevice::OFF_ACTION : PWMDevice::ON_ACTION; + actor = static_cast(AppEventType::Button); } - if (action != PWMDevice::INVALID_ACTION && GetAppTask().mPWMDevice.InitiateAction(action, actor, NULL)) + 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 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 (LIGHTING_BUTTON_MASK & button_state & has_changed) +#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((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 = kButtonPushEvent; + button_event.ButtonEvent.Action = static_cast(AppEventType::ButtonPushed); button_event.Handler = LightingActionEventHandler; - sAppTask.PostEvent(&button_event); + PostEvent(button_event); } - if (FUNCTION_BUTTON_MASK & has_changed) + if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged) { - 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); + button_event.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_BUTTON; + button_event.ButtonEvent.Action = static_cast(AppEventType::ButtonPushed); + button_event.Handler = StartBLEAdvertisementHandler; + PostEvent(button_event); } +#endif - if (BLE_ADVERTISEMENT_START_BUTTON_MASK & button_state & has_changed) + if (FUNCTION_BUTTON_MASK & hasChanged) { - button_event.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_BUTTON; - button_event.ButtonEvent.Action = kButtonPushEvent; - button_event.Handler = StartBLEAdvertisementHandler; - sAppTask.PostEvent(&button_event); + button_event.ButtonEvent.PinNo = FUNCTION_BUTTON; + button_event.ButtonEvent.Action = + static_cast((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::IdentifyStartHandler(Identify *) +void AppTask::FunctionTimerEventHandler(const AppEvent & event) { - AppEvent event; - event.Type = AppEvent::kEventType_IdentifyStart; - event.Handler = [](AppEvent *) { sIdentifyLED.Blink(kIdentifyBlinkRateMs); }; - sAppTask.PostEvent(&event); -} - -void AppTask::IdentifyStopHandler(Identify *) -{ - AppEvent event; - event.Type = AppEvent::kEventType_IdentifyStop; - event.Handler = [](AppEvent *) { sIdentifyLED.Set(false); }; - sAppTask.PostEvent(&event); -} - -void AppTask::FunctionTimerEventHandler(AppEvent * aEvent) -{ - if (aEvent->Type != AppEvent::kEventType_Timer) + 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 @@ void AppTask::FunctionHandler(AppEvent * aEvent) // 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(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 @@ void AppTask::FunctionHandler(AppEvent * aEvent) 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::StartBLEAdvertisementHandler(AppEvent *) } } -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 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */ 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(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::DispatchEvent(AppEvent * aEvent) 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 024d70a33f60f0..eeb83262bfb804 100644 --- a/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp +++ b/examples/lighting-app/nrfconnect/main/ZclCallbacks.cpp @@ -38,15 +38,16 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & 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(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(AppEventType::Lighting), + value); } else { @@ -80,9 +81,10 @@ void emberAfOnOffClusterInitCallback(EndpointId endpoint) 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(&storedValue)); + AppTask::Instance().GetPWMDevice().InitiateAction(storedValue ? PWMDevice::ON_ACTION : PWMDevice::OFF_ACTION, + static_cast(AppEventType::Lighting), + reinterpret_cast(&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 4f55191d9ae7c3..536e92e37bfd37 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 a5af0c939539cc..19e8cede4dab5a 100644 --- a/examples/lighting-app/nrfconnect/main/include/AppEvent.h +++ b/examples/lighting-app/nrfconnect/main/include/AppEvent.h @@ -20,29 +20,34 @@ #include -#include "LEDWidget.h" +#include "EventTypes.h" -struct AppEvent; -typedef void (*EventHandler)(AppEvent *); +class LEDWidget; -struct AppEvent +enum class AppEventType : uint8_t { - 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 - }; + None = 0, + Button, + ButtonPushed, + ButtonReleased, + Timer, + UpdateLedState, + Lighting, + IdentifyStart, + IdentifyStop, + StartSMPAdvertising +}; - uint16_t Type; +enum class FunctionEvent : uint8_t +{ + NoneSelected = 0, + SoftwareUpdate = 0, + FactoryReset, + AdvertisingStart +}; +struct AppEvent +{ union { struct @@ -65,5 +70,6 @@ struct AppEvent } 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 a1772735cedbf8..461981e44835f7 100644 --- a/examples/lighting-app/nrfconnect/main/include/AppTask.h +++ b/examples/lighting-app/nrfconnect/main/include/AppTask.h @@ -44,70 +44,57 @@ struct Identify; 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); + 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); - void DispatchEvent(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 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 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 ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); - - static void ButtonEventHandler(uint32_t button_state, uint32_t has_changed); - static void TimerEventHandler(k_timer * timer); + 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 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 9a487fcc8c2895..69e83a6935d05a 100644 --- a/examples/lighting-app/nrfconnect/main/main.cpp +++ b/examples/lighting-app/nrfconnect/main/main.cpp @@ -31,7 +31,7 @@ #include #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 @@ int main() 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 4bbb8a5a2a7076..1a796988571cf5 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 0e286be102e3fc..7fc72e8fcbd704 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 d5302def6aa3bd..5ff25156b6861b 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_LOG_MODE_MINIMAL=n 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 aa932382b8fe10..5c9bd36fbc31c6 100644 --- a/examples/lock-app/nrfconnect/CMakeLists.txt +++ b/examples/lock-app/nrfconnect/CMakeLists.txt @@ -24,6 +24,7 @@ include(${CHIP_ROOT}/config/nrfconnect/app/check-nrfconnect-version.cmake) # 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 e9dfd7de6eff89..98ed2d5ce9a9b8 100644 --- a/examples/lock-app/nrfconnect/Kconfig +++ b/examples/lock-app/nrfconnect/Kconfig @@ -35,6 +35,23 @@ config STATE_LEDS 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 1ed12be7e8ce79..050d5a7e0389d9 100644 --- a/examples/lock-app/nrfconnect/README.md +++ b/examples/lock-app/nrfconnect/README.md @@ -12,12 +12,15 @@ a reference for creating your own application. The example is based on [Matter](https://github.com/project-chip/connectedhomeip) and Nordic -Semiconductor's nRF Connect SDK, and supports remote access and control of a -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.
@@ -27,6 +30,7 @@ device works as a Thread Sleepy End Device. - [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 @@ and [Zephyr RTOS](https://zephyrproject.org/). Visit Matter's [nRF Connect platform overview](../../../docs/guides/nrfconnect_platform_overview.md) to read more about the platform structure and dependencies. -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 @@ commissioner role. To start the rendezvous, the controller must get the commissioning information from the Matter device. The data payload is encoded within a QR code, printed to -the UART console, and shared using an NFC tag. NFC tag emulation starts -automatically when Bluetooth LE advertising is started and stays enabled until -Bluetooth LE advertising timeout expires. +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 @@ more information. The example supports building and running on the following devices: -| Hardware platform | Build target | Platform image | -| ----------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` |
nRF52840 DKnRF52840 DK
| -| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` |
nRF5340 DKnRF5340 DK
| +| Hardware platform | Build target | Platform image | +| --------------------------------------------------------------------------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| [nRF52840 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) | `nrf52840dk_nrf52840` |
nRF52840 DKnRF52840 DK
| +| [nRF5340 DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK) | `nrf5340dk_nrf5340_cpuapp` |
nRF5340 DKnRF5340 DK
| +| [nRF7002 DK](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_nrf7002.html#nrf7002dk-nrf5340) | `nrf7002dk_nrf5340_cpuapp` |
nRF7002DKnRF7002 DK
|
+### 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`. + ## Device UI @@ -191,11 +217,10 @@ following states are possible: Bluetooth LE. - _Short Flash Off (950ms on/50ms off)_ — The device is fully - provisioned, but does not yet have full Thread network or service - connectivity. + provisioned, but does not yet have full connectivity for Thread or Wi-Fi + network. -- _Solid On_ — The device is fully provisioned and has full Thread - network and service connectivity. +- _Solid On_ — 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 @@ states are possible: - _Rapid Even Flashing (100 ms on/100 ms off during 2 s)_ — 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_ — 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_ — 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_ — initiates the factory reset of the + device. Releasing the button within the 3-second window cancels the factory + reset procedure. **Button 2** — Pressing the button once changes the lock state to the opposite one. -**Button 4** — 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 @@ learn how to use command-line interface of the application. 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 @@ Read the [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 a4bac9fffc2f9d..b211bc4f356ff5 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 00000000000000..3063fbbcdee779 --- /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 00000000000000..1622ffd00dbb91 --- /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 00000000000000..1622ffd00dbb91 --- /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 00000000000000..1622ffd00dbb91 --- /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 287c7829c6a5cf..0dbf7106e88e22 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 @@ CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" # 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 287c7829c6a5cf..0dbf7106e88e22 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 @@ CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" # 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 00000000000000..3c56dc0ddb1968 --- /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 b7d4d02a42e75c..4f5c18d869a73e 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 @@ -27,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +39,11 @@ #include #include +#ifdef CONFIG_CHIP_WIFI +#include +#include +#endif + #if CONFIG_CHIP_OTA_REQUESTOR #include "OTAUtil.h" #endif @@ -45,44 +52,66 @@ #include #include +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 @@ CHIP_ERROR AppTask::Init() 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 @@ CHIP_ERROR AppTask::Init() 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 @@ CHIP_ERROR AppTask::Init() } // 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 @@ CHIP_ERROR AppTask::Init() GetDFUOverSMP().ConfirmNewImage(); #endif + BoltLockMgr().Init(LockStateChanged); + // Initialize CHIP server #if CONFIG_CHIP_FACTORY_DATA ReturnErrorOnFailure(mFactoryDataProvider.Init()); @@ -213,13 +241,55 @@ CHIP_ERROR AppTask::StartApp() 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(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(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::LockActionEventHandler(AppEvent * aEvent) } } -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((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(AppEventType::ButtonPushed); button_event.Handler = LockActionEventHandler; - sAppTask.PostEvent(&button_event); + PostEvent(button_event); } - if (FUNCTION_BUTTON_MASK & has_changed) + if (BLE_ADVERTISEMENT_START_BUTTON_MASK & buttonState & hasChanged) { - 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); + button_event.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_BUTTON; + button_event.ButtonEvent.Action = static_cast(AppEventType::ButtonPushed); + button_event.Handler = StartBLEAdvertisementHandler; + PostEvent(button_event); } +#endif - if (BLE_ADVERTISEMENT_START_BUTTON_MASK & button_state & has_changed) + if (FUNCTION_BUTTON_MASK & hasChanged) { - button_event.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_BUTTON; - button_event.ButtonEvent.Action = BUTTON_PUSH_EVENT; - button_event.Handler = StartBLEAdvertisementHandler; - sAppTask.PostEvent(&button_event); + button_event.ButtonEvent.PinNo = FUNCTION_BUTTON; + button_event.ButtonEvent.Action = + static_cast((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) + if (event.Type != AppEventType::Timer || !Instance().mFunctionTimerActive) + { 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().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. + // 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 @@ void AppTask::RequestSMPAdvertisingStart(void) } #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 @@ void AppTask::FunctionHandler(AppEvent * aEvent) // 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(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 @@ void AppTask::FunctionHandler(AppEvent * aEvent) 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::StartBLEAdvertisementHandler(AppEvent *) } } -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 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */ 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 @@ void AppTask::CancelTimer() 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 @@ void AppTask::LockStateChanged(BoltLockManager::State state, BoltLockManager::Op 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 0a860818b0e5ce..9f82f856063aa6 100644 --- a/examples/lock-app/nrfconnect/main/BoltLockManager.cpp +++ b/examples/lock-app/nrfconnect/main/BoltLockManager.cpp @@ -172,15 +172,20 @@ void BoltLockManager::ActuatorTimerEventHandler(k_timer * timer) // context of the application thread. AppEvent event; - event.Type = AppEvent::kEventType_Timer; + event.Type = AppEventType::Timer; event.TimerEvent.Context = static_cast(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(aEvent->TimerEvent.Context); + BoltLockManager * lock = static_cast(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 3b737aa2b472f6..24b6b7709fd9b8 100644 --- a/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp +++ b/examples/lock-app/nrfconnect/main/ZclCallbacks.cpp @@ -123,5 +123,5 @@ void emberAfDoorLockClusterInitCallback(EndpointId endpoint) // (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 63e523e1922c80..0bfeb53be180f7 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 a45ccfdcc7b04c..f171149750e181 100644 --- a/examples/lock-app/nrfconnect/main/include/AppEvent.h +++ b/examples/lock-app/nrfconnect/main/include/AppEvent.h @@ -20,27 +20,33 @@ #include -#include "LEDWidget.h" +#include "EventTypes.h" -struct AppEvent; -typedef void (*EventHandler)(AppEvent *); +class LEDWidget; -struct AppEvent +enum class AppEventType : uint8_t { - enum AppEventTypes - { - kEventType_Button = 0, - kEventType_Timer, - kEventType_Lock, - kEventType_Install, - kEventType_UpdateLedState, -#ifdef CONFIG_MCUMGR_SMP_BT - kEventType_StartSMPAdvertising, -#endif - }; + None = 0, + Button, + ButtonPushed, + ButtonReleased, + Timer, + UpdateLedState, + IdentifyStart, + IdentifyStop, + StartSMPAdvertising +}; - uint16_t Type; +enum class FunctionEvent : uint8_t +{ + NoneSelected = 0, + SoftwareUpdate = 0, + FactoryReset, + AdvertisingStart +}; +struct AppEvent +{ union { struct @@ -63,5 +69,6 @@ struct AppEvent } 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 95c3ed2d1f116e..a23ad0f64b4ad7 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); - CHIP_ERROR Init(); + static void IdentifyStartHandler(Identify *); + static void IdentifyStopHandler(Identify *); - static void LockStateChanged(BoltLockManager::State state, BoltLockManager::OperationSource source); - - void CancelTimer(void); +private: + CHIP_ERROR Init(); - void DispatchEvent(AppEvent * event); + void CancelTimer(); + void StartTimer(uint32_t timeoutInMs); - 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 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 940346e176fa2f..8811723cd8421f 100644 --- a/examples/lock-app/nrfconnect/main/include/BoltLockManager.h +++ b/examples/lock-app/nrfconnect/main/include/BoltLockManager.h @@ -82,7 +82,7 @@ class BoltLockManager 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 a20f86082131a4..0c3b58e3d4f196 100644 --- a/examples/lock-app/nrfconnect/main/main.cpp +++ b/examples/lock-app/nrfconnect/main/main.cpp @@ -27,7 +27,7 @@ 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/lock-app/nrfconnect/prj.conf b/examples/lock-app/nrfconnect/prj.conf index e6d757137db86a..676ae5a05f2599 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. +# 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 - -# CHIP configuration -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -# 32774 == 0x8006 (example lock-app) -CONFIG_CHIP_DEVICE_PRODUCT_ID=32774 diff --git a/examples/lock-app/nrfconnect/prj_no_dfu.conf b/examples/lock-app/nrfconnect/prj_no_dfu.conf index 9b0339d336b4e1..839f839fc2e74f 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 @@ 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" -# 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 a71e97536cfd6c..b41ed9ede98909 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_UART_CONSOLE=n 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 c857cc360065c9..c9961063e0407f 100644 --- a/examples/platform/nrfconnect/Rpc.cpp +++ b/examples/platform/nrfconnect/Rpc.cpp @@ -109,7 +109,8 @@ class NrfButton final : public Button 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 00000000000000..1308472505e123 Binary files /dev/null and b/examples/platform/nrfconnect/doc/images/nrf7002dk.jpg differ diff --git a/examples/platform/nrfconnect/util/PWMDevice.cpp b/examples/platform/nrfconnect/util/PWMDevice.cpp index 43e3600a15cec9..b51d33c8e0ac7d 100644 --- a/examples/platform/nrfconnect/util/PWMDevice.cpp +++ b/examples/platform/nrfconnect/util/PWMDevice.cpp @@ -112,16 +112,21 @@ void PWMDevice::SetLevel(uint8_t aLevel) { 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(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 00000000000000..ccd8e69a4fcd86 --- /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 + +#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 00000000000000..557254c6cb9c0a --- /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 3066f1506b89b5..8f25fc783e902b 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 -class UnusedLedsWrapper +class FactoryResetLEDsWrapper { public: using Gpio = uint32_t; using Leds = std::array, size>; - explicit UnusedLedsWrapper(std::array aLeds) + explicit FactoryResetLEDsWrapper(std::array 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 250383efa93c0e..7b1ff5326b3a3d 100644 --- a/examples/platform/nrfconnect/util/include/PWMDevice.h +++ b/examples/platform/nrfconnect/util/include/PWMDevice.h @@ -49,6 +49,8 @@ class PWMDevice 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 @@ class PWMDevice 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 94a99f971ac195..ffa1e2cfd5bcce 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 1ea3730c18e873..c4a02dc8a2ebb0 100644 --- a/examples/pump-app/nrfconnect/README.md +++ b/examples/pump-app/nrfconnect/README.md @@ -54,13 +54,18 @@ and [Zephyr RTOS](https://zephyrproject.org/). Visit Matter's 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. - -The example can be configured to use the secure bootloader and utilize it for -performing over-the-air Device Firmware Upgrade using Bluetooth LE. +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. + +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 @@ following states are possible: Bluetooth LE. - _Short Flash Off (950ms on/50ms off)_ — The device is fully - provisioned, but does not yet have full Thread network or service - connectivity. + provisioned, but does not yet have full connectivity for Thread or Wi-Fi + network. - _Solid On_ — 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 d8ccc47f393f53..209eaa0805b666 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 #include +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 @@ CHIP_ERROR AppTask::Init() 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 @@ CHIP_ERROR AppTask::Init() } // 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 @@ CHIP_ERROR AppTask::StartApp() 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(aEvent->StartEvent.Action); - actor = aEvent->StartEvent.Actor; + action = static_cast(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(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) +void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged) { - AppEvent button_event; - button_event.Type = AppEvent::kEventType_Button; + AppEvent event; + event.Type = AppEventType::Button; - if (START_BUTTON_MASK & button_state & has_changed) + if (START_BUTTON_MASK & buttonState & hasChanged) { - button_event.ButtonEvent.PinNo = START_BUTTON; - button_event.ButtonEvent.Action = BUTTON_PUSH_EVENT; - button_event.Handler = StartActionEventHandler; - sAppTask.PostEvent(&button_event); + event.ButtonEvent.PinNo = START_BUTTON; + event.ButtonEvent.Action = static_cast(AppEventType::Button); + event.Handler = StartActionEventHandler; + PostEvent(event); } - if (FUNCTION_BUTTON_MASK & has_changed) + if (FUNCTION_BUTTON_MASK & hasChanged) { - 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); + event.ButtonEvent.PinNo = FUNCTION_BUTTON; + event.ButtonEvent.Action = + static_cast((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased); + event.Handler = FunctionHandler; + PostEvent(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.Handler = StartBLEAdvertisementHandler; - sAppTask.PostEvent(&button_event); + event.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_BUTTON; + event.ButtonEvent.Action = static_cast(AppEventType::ButtonPushed); + event.Handler = StartBLEAdvertisementHandler; + PostEvent(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) + 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::FunctionTimerEventHandler(AppEvent * aEvent) 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(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::StartBLEAdvertisementHandler(AppEvent *) } } -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 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */ 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 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */ 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::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */ 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 @@ void AppTask::ActionInitiated(PumpManager::Action_t aAction, int32_t aActor) 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(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 @@ void AppTask::UpdateClusterState() 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 e7c0b6240c554b..f24bd3262f45b8 100644 --- a/examples/pump-app/nrfconnect/main/PumpManager.cpp +++ b/examples/pump-app/nrfconnect/main/PumpManager.cpp @@ -25,7 +25,7 @@ #include #include -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 @@ void PumpManager::TimerEventHandler(k_timer * timer) // 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(aEvent->TimerEvent.Context); + PumpManager * pump = static_cast(aEvent.TimerEvent.Context); int32_t actor = 0; // Make sure auto start timer is still armed. @@ -152,11 +152,11 @@ void PumpManager::AutoRestartTimerEventHandler(AppEvent * aEvent) 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(aEvent->TimerEvent.Context); + PumpManager * pump = static_cast(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 49ec8f15946d77..6a1c4334a4eef5 100644 --- a/examples/pump-app/nrfconnect/main/ZclCallbacks.cpp +++ b/examples/pump-app/nrfconnect/main/ZclCallbacks.cpp @@ -51,5 +51,5 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & */ 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 e2e1812ae48718..7bea410efc1fca 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 2f2a0d99f74b0f..3dfff7913f3a47 100644 --- a/examples/pump-app/nrfconnect/main/include/AppEvent.h +++ b/examples/pump-app/nrfconnect/main/include/AppEvent.h @@ -20,27 +20,33 @@ #include -#include "LEDWidget.h" +#include "EventTypes.h" -struct AppEvent; -typedef void (*EventHandler)(AppEvent *); +class LEDWidget; -struct AppEvent +enum class AppEventType : uint8_t { - enum AppEventTypes - { - kEventType_Button = 0, - kEventType_Timer, - kEventType_Start, - kEventType_Install, - kEventType_UpdateLedState, -#ifdef CONFIG_MCUMGR_SMP_BT - kEventType_StartSMPAdvertising, -#endif - }; + None = 0, + Button, + ButtonPushed, + ButtonReleased, + Timer, + UpdateLedState, + StartSMPAdvertising, + Start, + Install +}; - uint16_t Type; +enum class FunctionEvent : uint8_t +{ + NoneSelected = 0, + SoftwareUpdate = 0, + FactoryReset, + AdvertisingStart +}; +struct AppEvent +{ union { struct @@ -63,5 +69,6 @@ struct AppEvent } 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 29a2103925bdb2..a551dae7d2b326 100644 --- a/examples/pump-app/nrfconnect/main/include/AppTask.h +++ b/examples/pump-app/nrfconnect/main/include/AppTask.h @@ -38,62 +38,47 @@ struct k_timer; 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); - - void CancelTimer(void); + static void CancelTimer(); + static void StartTimer(uint32_t timeoutInMs); - void DispatchEvent(AppEvent * event); + static void ActionInitiated(PumpManager::Action_t action, int32_t actor); + static void ActionCompleted(PumpManager::Action_t action, int32_t actor); - 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 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 eb2f0868e1242a..5c1bec2919266f 100644 --- a/examples/pump-app/nrfconnect/main/include/PumpManager.h +++ b/examples/pump-app/nrfconnect/main/include/PumpManager.h @@ -85,9 +85,9 @@ class PumpManager 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 a20f86082131a4..93a0062a0ef219 100644 --- a/examples/pump-app/nrfconnect/main/main.cpp +++ b/examples/pump-app/nrfconnect/main/main.cpp @@ -21,13 +21,13 @@ #include -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 916358d65905c5..3195f884e65720 100644 --- a/examples/pump-app/nrfconnect/prj.conf +++ b/examples/pump-app/nrfconnect/prj.conf @@ -21,22 +21,20 @@ CONFIG_STD_CPP14=y # 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 - -# CHIP configuration -CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" -# 32784 == 0x8010 (example pump-app) -CONFIG_CHIP_DEVICE_PRODUCT_ID=32784 +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 8c102a90dc41d4..67c31871ce797f 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 01c70c0217c02e..adb09f72ef3db2 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_UART_CONSOLE=n 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 94a99f971ac195..d5eb64a514079a 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 c353a93e889416..8fb710d4d272f2 100644 --- a/examples/pump-controller-app/nrfconnect/README.md +++ b/examples/pump-controller-app/nrfconnect/README.md @@ -54,14 +54,19 @@ and [Zephyr RTOS](https://zephyrproject.org/). Visit CHIP's [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 example can be configured to use the secure bootloader and utilize it for -performing over-the-air Device Firmware Upgrade using Bluetooth LE. +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. + +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 @@ following states are possible: Bluetooth LE. - _Short Flash Off (950ms on/50ms off)_ — The device is fully - provisioned, but does not yet have full Thread network or service - connectivity. + provisioned, but does not yet have full connectivity for Thread or Wi-Fi + network. - _Solid On_ — 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 ea4bf106e0c437..248b39255cbd51 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 #include +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 @@ CHIP_ERROR AppTask::Init() 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 @@ CHIP_ERROR AppTask::Init() } // 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 @@ CHIP_ERROR AppTask::StartApp() 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(aEvent->StartEvent.Action); - actor = aEvent->StartEvent.Actor; + action = static_cast(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(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) +void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged) { - AppEvent button_event; - button_event.Type = AppEvent::kEventType_Button; + AppEvent event; + event.Type = AppEventType::Button; - if (START_BUTTON_MASK & button_state & has_changed) + if (START_BUTTON_MASK & buttonState & hasChanged) { - button_event.ButtonEvent.PinNo = START_BUTTON; - button_event.ButtonEvent.Action = BUTTON_PUSH_EVENT; - button_event.Handler = StartActionEventHandler; - sAppTask.PostEvent(&button_event); + event.ButtonEvent.PinNo = START_BUTTON; + event.ButtonEvent.Action = static_cast(AppEventType::Button); + event.Handler = StartActionEventHandler; + PostEvent(event); } - if (FUNCTION_BUTTON_MASK & has_changed) + if (FUNCTION_BUTTON_MASK & hasChanged) { - 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); + event.ButtonEvent.PinNo = FUNCTION_BUTTON; + event.ButtonEvent.Action = + static_cast((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased); + event.Handler = FunctionHandler; + PostEvent(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.Handler = StartBLEAdvertisementHandler; - sAppTask.PostEvent(&button_event); + event.ButtonEvent.PinNo = BLE_ADVERTISEMENT_START_BUTTON; + event.ButtonEvent.Action = static_cast(AppEventType::ButtonPushed); + event.Handler = StartBLEAdvertisementHandler; + PostEvent(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) + 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::FunctionTimerEventHandler(AppEvent * aEvent) 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(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::StartBLEAdvertisementHandler(AppEvent *) } } -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 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */ 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 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */ 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::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */ 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 @@ void AppTask::ActionInitiated(PumpManager::Action_t aAction, int32_t aActor) 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(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 a7f654baeeead6..2b6215dc896938 100644 --- a/examples/pump-controller-app/nrfconnect/main/PumpManager.cpp +++ b/examples/pump-controller-app/nrfconnect/main/PumpManager.cpp @@ -25,7 +25,7 @@ #include #include -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 @@ void PumpManager::TimerEventHandler(k_timer * timer) // 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(aEvent->TimerEvent.Context); + PumpManager * pump = static_cast(aEvent.TimerEvent.Context); int32_t actor = 0; // Make sure auto start timer is still armed. @@ -152,11 +152,11 @@ void PumpManager::AutoRestartTimerEventHandler(AppEvent * aEvent) 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(aEvent->TimerEvent.Context); + PumpManager * pump = static_cast(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 49ec8f15946d77..6a1c4334a4eef5 100644 --- a/examples/pump-controller-app/nrfconnect/main/ZclCallbacks.cpp +++ b/examples/pump-controller-app/nrfconnect/main/ZclCallbacks.cpp @@ -51,5 +51,5 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & */ 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 e63e9d8f2a3588..a6a172ef231052 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 2f2a0d99f74b0f..3dfff7913f3a47 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 -#include "LEDWidget.h" +#include "EventTypes.h" -struct AppEvent; -typedef void (*EventHandler)(AppEvent *); +class LEDWidget; -struct AppEvent +enum class AppEventType : uint8_t { - enum AppEventTypes - { - kEventType_Button = 0, - kEventType_Timer, - kEventType_Start, - kEventType_Install, - kEventType_UpdateLedState, -#ifdef CONFIG_MCUMGR_SMP_BT - kEventType_StartSMPAdvertising, -#endif - }; + None = 0, + Button, + ButtonPushed, + ButtonReleased, + Timer, + UpdateLedState, + StartSMPAdvertising, + Start, + Install +}; - uint16_t Type; +enum class FunctionEvent : uint8_t +{ + NoneSelected = 0, + SoftwareUpdate = 0, + FactoryReset, + AdvertisingStart +}; +struct AppEvent +{ union { struct @@ -63,5 +69,6 @@ struct AppEvent } 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 29a2103925bdb2..5681b25b32313c 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 @@ struct k_timer; 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 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 afc1b571e40acd..f8111e55c64ba2 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 @@ class PumpManager 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 a20f86082131a4..93a0062a0ef219 100644 --- a/examples/pump-controller-app/nrfconnect/main/main.cpp +++ b/examples/pump-controller-app/nrfconnect/main/main.cpp @@ -21,13 +21,13 @@ #include -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 f3936ac83a0291..4a38ec1177c699 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 f946af99d95204..dba7042ad82864 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 bf7f1a452896de..88ea95c777e1a1 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_UART_CONSOLE=n 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 9fd8e4f7cb8a4f..e800b65733f381 100644 --- a/examples/window-app/nrfconnect/README.md +++ b/examples/window-app/nrfconnect/README.md @@ -57,14 +57,18 @@ and [Zephyr RTOS](https://zephyrproject.org/). Visit Matter's 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. - -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. +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. + +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 @@ following states are possible: Bluetooth LE. - _Short Flash Off (950ms on/50ms off)_ — The device is fully - provisioned, but does not yet have full Thread network or service - connectivity. + provisioned, but does not yet have full connectivity for Thread or Wi-Fi + network. - _Solid On_ — 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 00c7b57a192e28..c1672db18b1d2c 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 08df914781835b..311640093e35c0 100644 --- a/examples/window-app/nrfconnect/main/AppTask.cpp +++ b/examples/window-app/nrfconnect/main/AppTask.cpp @@ -23,15 +23,14 @@ #include -#include -#include - #include #include #include +#include #include +#include +#include #include - #include #include @@ -43,36 +42,42 @@ #include #include -#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 @@ CHIP_ERROR AppTask::Init() LEDWidget::SetStateUpdateCallback(LEDStateUpdateHandler); sStatusLED.Init(SYSTEM_STATE_LED); + sIdentifyLED.Init(LIFT_STATE_LED); + sIdentifyLED.Set(false); UpdateStatusLED(); @@ -151,7 +158,7 @@ CHIP_ERROR AppTask::Init() 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 @@ CHIP_ERROR AppTask::Init() 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 @@ CHIP_ERROR AppTask::StartApp() 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 = AppEventType::IdentifyStart; + event.Handler = [](const AppEvent &) { + WindowCovering::Instance().GetLiftIndicator().SuppressOutput(); + sIdentifyLED.Blink(LedConsts::kIdentifyBlinkRate_ms); + }; + PostEvent(event); +} + +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 = 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((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(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((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((CLOSE_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased); + event.Handler = CloseHandler; + PostEvent(event); } } @@ -261,103 +293,108 @@ void AppTask::ButtonEventHandler(uint32_t aButtonState, uint32_t aHasChanged) 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(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::StartBLEAdvertisementHandler(AppEvent *) } } -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(AppEventType::ButtonPushed)) { Instance().mOpenButtonIsPressed = true; if (Instance().mCloseButtonIsPressed) @@ -392,7 +427,7 @@ void AppTask::OpenHandler(AppEvent * aEvent) Instance().ToggleMoveType(); } } - else if (aEvent->ButtonEvent.Action == BUTTON_RELEASE_EVENT) + else if (event.ButtonEvent.Action == static_cast(AppEventType::ButtonReleased)) { if (!Instance().mCloseButtonIsPressed) { @@ -409,14 +444,12 @@ void AppTask::OpenHandler(AppEvent * aEvent) } } -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(AppEventType::ButtonPushed)) { Instance().mCloseButtonIsPressed = true; if (Instance().mOpenButtonIsPressed) @@ -424,7 +457,7 @@ void AppTask::CloseHandler(AppEvent * aEvent) Instance().ToggleMoveType(); } } - else if (aEvent->ButtonEvent.Action == BUTTON_RELEASE_EVENT) + else if (event.ButtonEvent.Action == static_cast(AppEventType::ButtonReleased)) { if (!Instance().mOpenButtonIsPressed) { @@ -456,41 +489,39 @@ void AppTask::ToggleMoveType() 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 @@ void AppTask::UpdateStatusLED() #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 @@ void AppTask::ChipEventHandler(const ChipDeviceEvent * aEvent, intptr_t) 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 @@ void AppTask::CancelTimer() 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 f1fd5a7059cadb..96320a6e92e189 100644 --- a/examples/window-app/nrfconnect/main/WindowCovering.cpp +++ b/examples/window-app/nrfconnect/main/WindowCovering.cpp @@ -27,7 +27,7 @@ #include #include -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 7dadc1bc572667..933cce3b6bb413 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 f6cac85b182b32..035a92cc0d8e20 100644 --- a/examples/window-app/nrfconnect/main/include/AppEvent.h +++ b/examples/window-app/nrfconnect/main/include/AppEvent.h @@ -19,22 +19,32 @@ #include +#include "EventTypes.h" + class LEDWidget; -struct AppEvent +enum class AppEventType : uint8_t { - using EventHandler = void (*)(AppEvent *); - - enum class Type : uint8_t - { - None, - Button, - Timer, - UpdateLedState, - }; + None = 0, + Button, + ButtonPushed, + ButtonReleased, + Timer, + UpdateLedState, + IdentifyStart, + IdentifyStop, + StartSMPAdvertising +}; - Type Type{ Type::None }; +enum class FunctionEvent : uint8_t +{ + NoneSelected = 0, + SoftwareUpdate = 0, + FactoryReset +}; +struct AppEvent +{ union { struct @@ -52,5 +62,6 @@ struct AppEvent } 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 a082c4582aaf59..1d4adb0b97c647 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 @@ -24,9 +26,12 @@ #include #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 @@ class AppTask }; 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 StartTimer(uint32_t timeoutMs); + + 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(); - 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); - OperatingMode mMode{ OperatingMode::Normal }; +#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 99868a9fe41bfb..f03c691fe38018 100644 --- a/examples/window-app/nrfconnect/main/include/WindowCovering.h +++ b/examples/window-app/nrfconnect/main/include/WindowCovering.h @@ -49,6 +49,9 @@ class WindowCovering 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 40233508ccc702..4cbd69782ac199 100644 --- a/examples/window-app/nrfconnect/main/main.cpp +++ b/examples/window-app/nrfconnect/main/main.cpp @@ -19,7 +19,7 @@ #include -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 bb8601bf9c5dbf..a284009a305d99 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_THREAD_SSED=y 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 f2787a7619fe73..3f55608bc1357e 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_THREAD_SSED=y 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 @@ 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 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 caf0ee1a5be1e9..c801e2f86bb9a7 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_THREAD_SSED=y 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_UART_CONSOLE=n 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