diff --git a/examples/window-app/nrfconnect/README.md b/examples/window-app/nrfconnect/README.md index 526a19004bf8bd..4f6ce47c8f74cb 100644 --- a/examples/window-app/nrfconnect/README.md +++ b/examples/window-app/nrfconnect/README.md @@ -111,6 +111,20 @@ requests to start sending the update packages. An OTA Requestor is a node that wants to download a new firmware image and sends requests to an OTA Provider to start the update process. +#### Simple Management Protocol + +Simple Management Protocol (SMP) is a basic transfer encoding that is used for +device management purposes, including application image management. SMP supports +using different transports, such as Bluetooth LE, UDP, or serial USB/UART. + +In this example, the Matter device runs the SMP Server to download the +application update image using the Bluetooth LE transport. + +See the +[Building with Device Firmware Upgrade support](#building-with-device-firmware-upgrade-support) +section to learn how to enable SMP and use it for the DFU purpose in this +example. + #### Bootloader MCUboot is a secure bootloader used for swapping firmware images of different @@ -394,6 +408,14 @@ For example, use the following command for `nrf52840dk_nrf52840`: Support for DFU using Matter OTA is enabled by default. +To enable DFU over Bluetooth LE, run the following command with _build-target_ +replaced with the build target name of the Nordic Semiconductor kit you are +using (for example `nrf52840dk_nrf52840`): + + ``` + $ west build -b build-target -- -DCONFIG_CHIP_DFU_OVER_BT_SMP=y + ``` + To completely disable support for DFU, run the following command with _build-target_ replaced with the build target name of the Nordic Semiconductor kit you are using (for example `nrf52840dk_nrf52840`): diff --git a/examples/window-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay b/examples/window-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay index 096e3208740df9..00c7b57a192e28 100644 --- a/examples/window-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay +++ b/examples/window-app/nrfconnect/boards/nrf52840dk_nrf52840.overlay @@ -18,7 +18,10 @@ chosen { nordic,pm-ext-flash = &mx25r64; }; +}; + +/ { /* * In some default configurations within the nRF Connect SDK, * e.g. on nRF52840, the chosen zephyr,entropy node is &cryptocell. @@ -30,9 +33,8 @@ }; /* - * By default, PWM module is only configured for led0 (LED1 on the board). - * The window-app, however, uses LED2 to show the state of the window cover, - * by using the LED's brightness level. + * Configure LED2 and LED3 to show the state of the + * window cover,by using the LED's brightness level. */ aliases { pwm-led1 = &pwm_led1; @@ -40,7 +42,6 @@ }; pwmleds { - compatible = "pwm-leds"; pwm_led1: pwm_led_1 { pwms = <&pwm0 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>; }; @@ -82,15 +83,15 @@ &pinctrl { pwm0_default_alt: pwm0_default_alt { group1 { - psels = , ; + psels = , ; nordic,invert; }; }; pwm0_sleep_alt: pwm0_sleep_alt { group1 { - psels = , ; + psels = , ; low-power-enable; }; }; -}; \ No newline at end of file +}; diff --git a/examples/window-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay b/examples/window-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay index b87553d5dd7b11..4b450586a3baa5 100644 --- a/examples/window-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/examples/window-app/nrfconnect/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -20,9 +20,8 @@ }; /* - * By default, PWM module is only configured for led0 (LED1 on the board). - * The lighting-app, however, uses LED2 to show the state of the lighting, - * including its brightness level. + * Configure LED2 and LED3 to show the state of the + * window cover,by using the LED's brightness level. */ aliases { pwm-led1 = &pwm_led1; @@ -30,6 +29,7 @@ }; pwmleds { + compatible = "pwm-leds"; pwm_led1: pwm_led_1 { pwms = <&pwm0 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>; }; @@ -81,9 +81,9 @@ }; }; }; - }; + /* Disable unused peripherals to reduce power consumption */ &adc { status = "disabled"; @@ -110,14 +110,14 @@ &pinctrl { pwm0_default_alt: pwm0_default_alt { group1 { - psels = , ; + psels = , ; nordic,invert; }; }; pwm0_sleep_alt: pwm0_sleep_alt { group1 { - psels = , ; + psels = , ; low-power-enable; }; }; diff --git a/examples/window-app/nrfconnect/main/AppTask.cpp b/examples/window-app/nrfconnect/main/AppTask.cpp index 976b3d69a40a71..01055a4935f54d 100644 --- a/examples/window-app/nrfconnect/main/AppTask.cpp +++ b/examples/window-app/nrfconnect/main/AppTask.cpp @@ -141,6 +141,12 @@ CHIP_ERROR AppTask::Init() k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr); k_timer_user_data_set(&sFunctionTimer, this); +#ifdef CONFIG_MCUMGR_SMP_BT + /* Initialize DFU over SMP */ + GetDFUOverSMP().Init(RequestSMPAdvertisingStart); + GetDFUOverSMP().ConfirmNewImage(); +#endif + // Initialize CHIP server SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); @@ -224,6 +230,16 @@ void AppTask::ButtonEventHandler(uint32_t aButtonState, uint32_t aHasChanged) } } +#ifdef CONFIG_MCUMGR_SMP_BT +void AppTask::RequestSMPAdvertisingStart(void) +{ + AppEvent event; + event.Type = AppEvent::Type::StartSMPAdvertising; + event.Handler = [](AppEvent *) { GetDFUOverSMP().StartBLEAdvertising(); }; + PostEvent(&event); +} +#endif + void AppTask::FunctionTimerTimeoutCallback(k_timer * aTimer) { if (!aTimer) @@ -295,7 +311,11 @@ void AppTask::FunctionHandler(AppEvent * aEvent) 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; diff --git a/examples/window-app/nrfconnect/main/WindowCovering.cpp b/examples/window-app/nrfconnect/main/WindowCovering.cpp index f4041c254e27bc..cd4dc07fc127eb 100644 --- a/examples/window-app/nrfconnect/main/WindowCovering.cpp +++ b/examples/window-app/nrfconnect/main/WindowCovering.cpp @@ -35,8 +35,7 @@ using namespace chip::app::Clusters::WindowCovering; static const struct pwm_dt_spec sLiftPwmDevice = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led1)); static const struct pwm_dt_spec sTiltPwmDevice = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led2)); -static k_timer sLiftTimer; -static k_timer sTiltTimer; + static constexpr uint32_t sMoveTimeoutMs{ 200 }; WindowCovering::WindowCovering() @@ -52,24 +51,6 @@ WindowCovering::WindowCovering() { LOG_ERR("Cannot initialize the tilt indicator"); } - - k_timer_init(&sLiftTimer, MoveTimerTimeoutCallback, nullptr); - k_timer_init(&sTiltTimer, MoveTimerTimeoutCallback, nullptr); -} - -void WindowCovering::MoveTimerTimeoutCallback(k_timer * aTimer) -{ - if (!aTimer) - return; - - if (aTimer == &sLiftTimer) - { - chip::DeviceLayer::PlatformMgr().ScheduleWork(DriveCurrentLiftPosition); - } - else if (aTimer == &sTiltTimer) - { - chip::DeviceLayer::PlatformMgr().ScheduleWork(DriveCurrentTiltPosition); - } } void WindowCovering::DriveCurrentLiftPosition(intptr_t) @@ -162,14 +143,29 @@ bool WindowCovering::TargetCompleted(MoveType aMoveType, NPercent100ths aCurrent void WindowCovering::StartTimer(MoveType aMoveType, uint32_t aTimeoutMs) { - if (aMoveType == MoveType::LIFT) + MoveType * moveType = chip::Platform::New(); + VerifyOrReturn(moveType != nullptr); + + *moveType = aMoveType; + (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(aTimeoutMs), MoveTimerTimeoutCallback, + reinterpret_cast(moveType)); +} + +void WindowCovering::MoveTimerTimeoutCallback(chip::System::Layer * systemLayer, void * appState) +{ + MoveType * moveType = reinterpret_cast(appState); + VerifyOrReturn(moveType != nullptr); + + if (*moveType == MoveType::LIFT) { - k_timer_start(&sLiftTimer, K_MSEC(sMoveTimeoutMs), K_NO_WAIT); + chip::DeviceLayer::PlatformMgr().ScheduleWork(WindowCovering::DriveCurrentLiftPosition); } - else if (aMoveType == MoveType::TILT) + else if (*moveType == MoveType::TILT) { - k_timer_start(&sTiltTimer, K_MSEC(sMoveTimeoutMs), K_NO_WAIT); + chip::DeviceLayer::PlatformMgr().ScheduleWork(WindowCovering::DriveCurrentTiltPosition); } + + chip::Platform::Delete(moveType); } void WindowCovering::DriveCurrentTiltPosition(intptr_t) diff --git a/examples/window-app/nrfconnect/main/include/WindowCovering.h b/examples/window-app/nrfconnect/main/include/WindowCovering.h index 2b5b6ef792d9fd..99868a9fe41bfb 100644 --- a/examples/window-app/nrfconnect/main/include/WindowCovering.h +++ b/examples/window-app/nrfconnect/main/include/WindowCovering.h @@ -69,7 +69,7 @@ class WindowCovering static chip::Percent100ths CalculateSingleStep(MoveType aMoveType); static void DriveCurrentLiftPosition(intptr_t); static void DriveCurrentTiltPosition(intptr_t); - static void MoveTimerTimeoutCallback(k_timer * aTimer); + static void MoveTimerTimeoutCallback(chip::System::Layer * systemLayer, void * appState); static void DoPostAttributeChange(intptr_t aArg); MoveType mCurrentUIMoveType;