Migration guide for nRF Connect SDK v2.6.0
This document describes the changes required or recommended when migrating your application from nRF Connect SDK v2.5.0 to nRF Connect SDK v2.6.0.
Required changes
The following changes are mandatory to make your application work in the same way as in previous releases.
Samples and applications
This section describes the changes related to samples and applications.
Serial LTE Modem (SLM)
The Zephyr settings backend has been changed from FCB to NVS. Because of this, one setting is restored to its default value after the switch if you are using the LwM2M carrier library. The setting controls whether the SLM connects automatically to the network on startup. You can read and write it using the
AT#XCARRIER="auto_connect"
command.The
AT#XCMNG
AT command, which is activated with theoverlay-native_tls.conf
overlay file, has been changed from using modem certificate storage to Zephyr settings storage. You need to use theAT#XCMNG
command to store previously stored credentials again.The
CONFIG_SLM_WAKEUP_PIN
Kconfig option was renamed to CONFIG_SLM_POWER_PIN. If you have defined it separately from the default configurations, you need to update its name accordingly.
Matter
For the Matter samples and applications using Intermittently Connected Devices configuration (formerly called Sleepy End Devices):
The naming convention for the energy-optimized devices has been changed from Sleepy End Devices (SED) to Intermittently Connected Devices (ICD). Because of this, the Kconfig options used to manage this configuration have been aligned as well. If your application uses the following Kconfig options, they require name changes:
The
CONFIG_CHIP_ENABLE_SLEEPY_END_DEVICE_SUPPORT
Kconfig option was renamed toCONFIG_CHIP_ENABLE_ICD_SUPPORT
.The
CONFIG_CHIP_SED_IDLE_INTERVAL
Kconfig option was renamed toCONFIG_CHIP_ICD_SLOW_POLL_INTERVAL
.The
CONFIG_CHIP_SED_ACTIVE_INTERVAL
Kconfig option was renamed toCONFIG_CHIP_ICD_FAST_POLLING_INTERVAL
.The
CONFIG_CHIP_SED_ACTIVE_THRESHOLD
Kconfig option was renamed toCONFIG_CHIP_ICD_ACTIVE_MODE_THRESHOLD
.
For Matter over Thread samples, starting from this release, the cryptography backend enabled by default is PSA Crypto API instead of Mbed TLS. Be aware of the change and consider the following when migrating to nRF Connect SDK v2.6.0:
You can keep using Mbed TLS API as the cryptography backend by disabling PSA Crypto API. You can disable it by setting the
CONFIG_CHIP_CRYPTO_PSA
Kconfig option ton
.Thread libraries will be built with PSA Crypto API enabled without Mbed TLS support. This means that if you set the
CONFIG_CHIP_CRYPTO_PSA
Kconfig option ton
, you must also build the Thread libraries from sources.To inherit Thread certification from Nordic Semiconductor, you must use the PSA Crypto API backend.
The device can automatically migrate all operational keys from the Matter’s generic persistent storage to the PSA ITS secure storage. This means that all keys needed to establish the secure connection between Matter nodes will be moved to the PSA ITS secure storage. To enable operational keys migration, set the
CONFIG_NCS_SAMPLE_MATTER_OPERATIONAL_KEYS_MIGRATION_TO_ITS
Kconfig option toy
.The default reaction to migration failure in nRF Connect SDK Matter samples is a factory reset of the device. To change the default reaction, set the
CONFIG_NCS_SAMPLE_MATTER_FACTORY_RESET_ON_KEY_MIGRATION_FAILURE
Kconfig option ton
and implement the reaction in your Matter event handler.When the Device Attestation Certificate (DAC) private key exists in the factory data set, it can migrate to the PSA ITS secure storage.
You can also have the DAC private key replaced by zeros in the factory data partition by setting the
CONFIG_CHIP_CRYPTO_PSA_MIGRATE_DAC_PRIV_KEY
Kconfig option toy
. This functionality is experimental.
For the Matter samples and applications using the
samples/matter/common
directory:The structure of the files located in the
common
directory has been changed. Align the appropriate paths in your application’sCMakeLists.txt
file and source files, including header files located in thecommon
directory.The
event_types.h
header file was removed. If your application uses it, add theevent_types.h
file in your application’ssrc
directory with the following code in the file:#pragma once struct AppEvent; /* needs to be implemented in the application code */ using EventHandler = void (*)(const AppEvent &);
The
board_util.h
header file was renamed toboard_config.h
and moved to thesamples/matter/common/src/board
directory. Align any source files that include it to use the new name.The new
Nrf
andMatter
namespaces have been added to the files located in thecommon
directory. Align the source files using these files to use the appropriate namespaces.
Wi-Fi®
For samples using Wi-Fi features:
A few Kconfig options related to scan operations have been removed in the current release.
If your application uses scan operations, they need to be updated to remove the dependency on the following options:
CONFIG_WIFI_MGMT_SCAN_BANDS
CONFIG_WIFI_MGMT_SCAN_SSID_FILT
CONFIG_WIFI_MGMT_SCAN_CHAN
Instead of the
CONFIG_WIFI_MGMT_SCAN_MAX_BSS_CNT
Kconfig option, a newCONFIG_NRF_WIFI_SCAN_MAX_BSS_CNT
Kconfig option is added.The Wi-Fi interface is now renamed from
wlan0
tonordic_wlan0
, and for easier fetching of the handler, an entry in the DTS file is addedzephyr_wifi
.If your application was using
device_get_binding("wlan0")
, replace withDEVICE_DT_GET(DT_CHOSEN(zephyr_wifi))
.Optionally, you can override the label zephyr_wifi in the DTS file with a different Wi-Fi interface name.
Libraries
Modem library integration layer
For applications using Modem library integration layer:
The
lte_connectivity
module is renamed tolte_net_if
. Make sure that all references are updated accordingly, including function names and Kconfig options.If your application is using the
lte_net_if
(formerlylte_connectivity
) without disablingCONFIG_NRF_MODEM_LIB_NET_IF_AUTO_START
,CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_CONNECT
, andCONFIG_NRF_MODEM_LIB_NET_IF_AUTO_DOWN
Kconfig options, changes are required as the default values are changed from enabled to disabled.Consider using the
conn_mgr_all_if_up()
,conn_mgr_if_connect()
andconn_mgr_if_disconnect()
functions instead of enabling the Kconfig options to have better control of the initialization and connection establishment.
The Release Assistance Indication (RAI) socket options have been deprecated and replaced with a new consolidated socket option. If your application uses
SO_RAI_*
socket options, you need to update your socket configuration as follows:Replace the deprecated socket options
SO_RAI_NO_DATA
,SO_RAI_LAST
,SO_RAI_ONE_RESP
,SO_RAI_ONGOING
, andSO_RAI_WAIT_MORE
with the newSO_RAI
option.Set the optval parameter of the
SO_RAI
socket option to one of the new valuesRAI_NO_DATA
,RAI_LAST
,RAI_ONE_RESP
,RAI_ONGOING
, orRAI_WAIT_MORE
to specify the desired indication.
Example of migration:
/* Before migration. */ setsockopt(socket_fd, SOL_SOCKET, SO_RAI_LAST, NULL, 0); /* After migration. */ int rai_option = RAI_LAST; setsockopt(socket_fd, SOL_SOCKET, SO_RAI, &rai_option, sizeof(rai_option));
nRF Cloud
The
nrf_cloud_obj_location_request_create()
function has changed. The parameterconst bool request_loc
has been changed toconst struct nrf_cloud_location_config *const config
.To migrate to the new API, you need to declare a
nrf_cloud_location_config
structure and set the structure’sdo_reply
variable to the value used forrequest_loc
. Set the two remaining structure variables,hi_conf
andfallback
, according to your application’s needs. You also must provide a pointer to the structure to thenrf_cloud_obj_location_request_create()
function instead of the boolean value.
Security
For samples using
CONFIG_NRF_SECURITY
:RSA keys are no longer enabled by default. This reduces the code size by 30 kB if not using RSA keys. This also breaks the configuration if using the RSA keys without explicitly enabling an RSA key size. Enable the required key size to fix the configuration, for example by setting the Kconfig option
CONFIG_PSA_WANT_RSA_KEY_SIZE_2048
if 2048-bit RSA keys are required.The PSA config is now validated by the
ncs/nrf/ext/oberon/psa/core/library/check_crypto_config.h
file. Users with invalid configurations must update their PSA configuration according to the error messages that thecheck_crypto_config.h
file provides.
For the Crypto: Persistent key storage sample:
The Kconfig option
CONFIG_PSA_NATIVE_ITS
is replaced by the Kconfig optionCONFIG_TRUSTED_STORAGE
, which enables the new Trusted storage library. The Trusted storage library provides the PSA Internal Trusted Storage (ITS) API for board targets without TF-M. It is not backward compatible with the previous PSA ITS implementation. Migrating from the PSA ITS implementation, enabled by theCONFIG_PSA_NATIVE_ITS
option, to the new Trusted storage library requires manual data migration.
For Wi-Fi credentials library and Wi-Fi samples:
CONFIG_WIFI_CREDENTIALS_BACKEND_PSA_UID_OFFSET
has been removed because it was specific to the previous solution that used PSA Protected Storage instead of PSA Internal Trusted Storage (ITS). UseCONFIG_WIFI_CREDENTIALS_BACKEND_PSA_OFFSET
to specify the key offset for PSA ITS. Be aware that Wi-Fi credentials stored in Protected Storage will not appear in ITS when switching. To avoid re-provisioning Wi-Fi credentials, manually read out the old credentials from Protected Storage in the previously used UID and store to ITS.
zcbor
If you have zcbor-generated code that relies on the zcbor libraries through Zephyr, you must regenerate the files using zcbor 0.8.1. Note that the names of generated types and members has been overhauled, so the code using the generated code must likely be changed.
For example:
Leading single underscores and all double underscores are largely gone.
Names sometimes gain suffixes like
_m
or_l
for disambiguation.All enum (choice) names have now gained a
_c
suffix, so the enum name no longer matches the corresponding member name exactly (because this broke C++ namespace rules).
The function
zcbor_new_state()
,zcbor_new_decode_state()
and the macroZCBOR_STATE_D
have gained new parameters related to decoding of unordered maps. Unless you are using that new functionality, these can all be set to NULL or 0.The functions
zcbor_bstr_put_term()
andzcbor_tstr_put_term()
have gained a new parametermaxlen
, referring to the maximum length of the parameterstr
. This parameter is passed directly tostrnlen()
under the hood.The function
zcbor_tag_encode()
has been renamed tozcbor_tag_put()
.Printing has been changed significantly, for example,
zcbor_print()
is now calledzcbor_log()
, andzcbor_trace()
with no parameters is gone, and in its place arezcbor_trace_file()
andzcbor_trace()
, both of which take astate
parameter.
Recommended changes
The following changes are recommended for your application to work optimally after the migration.
Samples and applications
This section describes the changes related to samples and applications.
Matter
For the Matter samples and applications:
The new API and helper modules have been added to the
samples/matter/common
directory. All Matter samples and applications have been changed to use the common software modules.The inclusion of common software module source code in the CMake application target has been moved to the
samples/matter/common/cmake/source_common.cmake
file. Source code for specific software modules is added automatically based on the selected Kconfig options. To include all required source code files, add the following line to theCMakeLists.txt
file in your project directory:include(${ZEPHYR_NRF_MODULE_DIR}/samples/matter/common/cmake/source_common.cmake)
You can follow the new approach and migrate your application to use the common software modules. This will significantly reduce the size of the code required to be implemented in the application. You can also choose to keep using the previous approach, but due to the structural differences, it may be harder to use Matter samples and applications as a reference for an application using the older approach.
The following steps use the Matter: Template sample as an example. To migrate the application from nRF Connect SDK v2.5.0 and start using the common software modules used in nRF Connect SDK v2.6.0:
Replace the code used for initialization and handling of the board’s components, like LEDs or buttons, with the common
board
module. Theboard
module handles buttons and LEDs in a way consistent with Matter samples UI. It uses thetask_executor
common module for posting a board-related event. You can also use thetask_executor
module for posting and dispatching events in your application.To replace the nRF Connect SDK v2.5.0 compliant implementation with the
board
module, complete the following steps:Remove the following code from the
app_task.h
file:#include "app_event.h" #include "led_widget.h" static void PostEvent(const AppEvent &event); void CancelTimer(); void StartTimer(uint32_t timeoutInMs); static void DispatchEvent(const AppEvent &event); static void UpdateLedStateEventHandler(const AppEvent &event); static void FunctionHandler(const AppEvent &event); static void FunctionTimerEventHandler(const AppEvent &event); static void ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged); static void LEDStateUpdateHandler(LEDWidget &ledWidget); static void FunctionTimerTimeoutCallback(k_timer *timer); static void UpdateStatusLED(); FunctionEvent mFunction = FunctionEvent::NoneSelected; bool mFunctionTimerActive = false;
Remove the following code from the
app_task.cpp
file:#include "app_config.h" #include "led_util.h" #include "board_util.h" #include <dk_buttons_and_leds.h> namespace { constexpr size_t kAppEventQueueSize = 10; constexpr uint32_t kFactoryResetTriggerTimeout = 6000; K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent)); k_timer sFunctionTimer; LEDWidget sStatusLED; #if NUMBER_OF_LEDS == 2 FactoryResetLEDsWrapper<1> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED } }; #else FactoryResetLEDsWrapper<3> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTORY_RESET_SIGNAL_LED1, FACTORY_RESET_SIGNAL_LED2 } }; #endif bool sIsNetworkProvisioned = false; bool sIsNetworkEnabled = false; bool sHaveBLEConnections = false; } /* namespace */ namespace LedConsts { 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 */ void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged) { AppEvent button_event; button_event.Type = AppEventType::Button; if (FUNCTION_BUTTON_MASK & hasChanged) { button_event.ButtonEvent.PinNo = FUNCTION_BUTTON; button_event.ButtonEvent.Action = static_cast<uint8_t>((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed : AppEventType::ButtonReleased); button_event.Handler = FunctionHandler; PostEvent(button_event); } } void AppTask::FunctionTimerTimeoutCallback(k_timer *timer) { if (!timer) { return; } AppEvent event; event.Type = AppEventType::Timer; event.TimerEvent.Context = k_timer_user_data_get(timer); event.Handler = FunctionTimerEventHandler; PostEvent(event); } void AppTask::FunctionTimerEventHandler(const AppEvent &) { if (Instance().mFunction == FunctionEvent::FactoryReset) { Instance().mFunction = FunctionEvent::NoneSelected; LOG_INF("Factory Reset triggered"); sStatusLED.Set(true); sFactoryResetLEDs.Set(true); chip::Server::GetInstance().ScheduleFactoryReset(); } } void AppTask::FunctionHandler(const AppEvent &event) { if (event.ButtonEvent.PinNo != FUNCTION_BUTTON) return; if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed)) { Instance().StartTimer(kFactoryResetTriggerTimeout); Instance().mFunction = FunctionEvent::FactoryReset; } else if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonReleased)) { if (Instance().mFunction == FunctionEvent::FactoryReset) { sFactoryResetLEDs.Set(false); UpdateStatusLED(); Instance().CancelTimer(); Instance().mFunction = FunctionEvent::NoneSelected; LOG_INF("Factory Reset has been Canceled"); } } } void AppTask::LEDStateUpdateHandler(LEDWidget &ledWidget) { AppEvent event; event.Type = AppEventType::UpdateLedState; event.Handler = UpdateLedStateEventHandler; event.UpdateLedStateEvent.LedWidget = &ledWidget; PostEvent(event); } void AppTask::UpdateLedStateEventHandler(const AppEvent &event) { if (event.Type == AppEventType::UpdateLedState) { event.UpdateLedStateEvent.LedWidget->UpdateState(); } } void AppTask::UpdateStatusLED() { /* Update the status LED. * * If IPv6 networking 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(LedConsts::StatusLed::Unprovisioned::kOn_ms, LedConsts::StatusLed::Unprovisioned::kOff_ms); } else { sStatusLED.Blink(LedConsts::StatusLed::Provisioned::kOn_ms, LedConsts::StatusLed::Provisioned::kOff_ms); } } void AppTask::CancelTimer() { k_timer_stop(&sFunctionTimer); } void AppTask::StartTimer(uint32_t timeoutInMs) { k_timer_start(&sFunctionTimer, K_MSEC(timeoutInMs), K_NO_WAIT); } void AppTask::PostEvent(const AppEvent &event) { if (k_msgq_put(&sAppEventQueue, &event, K_NO_WAIT) != 0) { LOG_INF("Failed to post event to app task event queue"); } } void AppTask::DispatchEvent(const AppEvent &event) { if (event.Handler) { event.Handler(event); } else { LOG_INF("Event received with no handler. Dropping event."); } }
Include the
board
andtask_executor
modules to theapp_task.cpp
file.#include "app/task_executor.h" #include "board/board.h"
Replace the code in the
Init()
method, in theapp_task.cpp
file. TheInit()
method from theboard
module has two optional arguments, that you can use to pass your own handler implementations for handling buttons or LEDs.Remove:
/* Initialize LEDs */ LEDWidget::InitGpio(); LEDWidget::SetStateUpdateCallback(LEDStateUpdateHandler); sStatusLED.Init(SYSTEM_STATE_LED); UpdateStatusLED(); /* Initialize buttons */ int ret = dk_buttons_init(ButtonEventHandler); if (ret) { LOG_ERR("dk_buttons_init() failed"); return chip::System::MapErrorZephyr(ret); } /* Initialize function timer */ k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr); k_timer_user_data_set(&sFunctionTimer, this);
Add:
if (!Nrf::GetBoard().Init()) { LOG_ERR("User interface initialization failed."); return CHIP_ERROR_INCORRECT_STATE; }
Replace the code in the
StartApp()
method, in theapp_task.cpp
file:Remove:
AppEvent event = {}; k_msgq_get(&sAppEventQueue, &event, K_FOREVER); DispatchEvent(event);
Add in the while loop:
Nrf::DispatchNextTask();
Replace the code in the
ChipEventHandler()
method, in theapp_task.cpp
file:Add at the top of the method:
bool sIsNetworkProvisioned = false; bool sIsNetworkEnabled = false;
Remove for the
kCHIPoBLEAdvertisingChange
enum:sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0; UpdateStatusLED();
Add for the
kCHIPoBLEAdvertisingChange
enum:if (ConnectivityMgr().NumBLEConnections() != 0) { Nrf::GetBoard().UpdateDeviceState(Nrf::DeviceState::DeviceConnectedBLE); }
Remove for the
kThreadStateChange
and thekWiFiConnectivityChange
enums:UpdateStatusLED();
Add for the
kThreadStateChange
and thekWiFiConnectivityChange
enums:if (sIsNetworkProvisioned && sIsNetworkEnabled) { Nrf::GetBoard().UpdateDeviceState(Nrf::DeviceState::DeviceProvisioned); } else { Nrf::GetBoard().UpdateDeviceState(Nrf::DeviceState::DeviceDisconnected); }
Add the
board
andtask_executor
modules to the compilation. Edit theCMakeLists.txt
file as follows:target_sources(app PRIVATE ${COMMON_ROOT}/src/app/task_executor.cpp ${COMMON_ROOT}/src/board/board.cpp )
Add the common
Kconfig
file to the list of sourced Kconfig files. To do so, edit your applicationKconfig
file and add the following code one line before sourcing theKconfig.zephyr
file:source "${ZEPHYR_BASE}/../nrf/samples/matter/common/src/Kconfig"
Replace the code used for Matter stack initialization with the common
matter_init
module. Thematter_init
module initializes the Matter stack in a safe way, which means it takes care of the proper order of initialization for software modules. It uses thematter_event_handler
common module for defining a default Matter event handler. You can customize the module behavior by injecting your own initialization parameters and callbacks.To replace the nRF Connect SDK v2.5.0 compliant implementation with the
matter_init
module, complete the following steps:Remove the following code from the
app_task.h
file:#if CONFIG_CHIP_FACTORY_DATA #include <platform/nrfconnect/FactoryDataProvider.h> #else #include <platform/nrfconnect/DeviceInstanceInfoProviderImpl.h> #endif
Replace the code in the
AppTask
class, in theapp_task.h
file:Remove:
static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent *event, intptr_t arg); #if CONFIG_CHIP_FACTORY_DATA chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider; #endif
Add:
static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent *event, intptr_t arg);
Remove the following code from the
app_task.cpp
file:#include "fabric_table_delegate.h" #include <platform/CHIPDeviceLayer.h> #include <app/server/Server.h> #include <credentials/DeviceAttestationCredsProvider.h> #include <credentials/examples/DeviceAttestationCredsExample.h> #include <lib/support/CHIPMem.h> #include <lib/support/CodeUtils.h> #include <system/SystemError.h> #ifdef CONFIG_CHIP_WIFI #include <app/clusters/network-commissioning/network-commissioning.h> #include <platform/nrfconnect/wifi/NrfWiFiDriver.h> #endif #include <zephyr/kernel.h> using namespace ::chip::Credentials; #ifdef CONFIG_CHIP_WIFI app::Clusters::NetworkCommissioning::Instance sWiFiCommissioningInstance(0, &(NetworkCommissioning::NrfWiFiDriver::Instance())); #endif
Include the
matter_init
module to theapp_task.cpp
file.#include "app/matter_init.h"
Rename the
ChipEventHandler()
method, in theapp_task.cpp
file, to theMatterEventHandler()
method.Replace the code in the
Init()
method, in theapp_task.cpp
file:Remove:
/* Initialize CHIP stack */ LOG_INF("Init CHIP stack"); CHIP_ERROR err = chip::Platform::MemoryInit(); if (err != CHIP_NO_ERROR) { LOG_ERR("Platform::MemoryInit() failed"); return err; } err = PlatformMgr().InitChipStack(); if (err != CHIP_NO_ERROR) { LOG_ERR("PlatformMgr().InitChipStack() failed"); return err; } #if defined(CONFIG_NET_L2_OPENTHREAD) err = ThreadStackMgr().InitThreadStack(); if (err != CHIP_NO_ERROR) { LOG_ERR("ThreadStackMgr().InitThreadStack() failed: %s", ErrorStr(err)); return err; } #ifdef CONFIG_OPENTHREAD_MTD_SED err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); #elif CONFIG_OPENTHREAD_MTD err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); #else err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); #endif /* CONFIG_OPENTHREAD_MTD_SED */ if (err != CHIP_NO_ERROR) { LOG_ERR("ConnectivityMgr().SetThreadDeviceType() failed: %s", ErrorStr(err)); return err; } #elif defined(CONFIG_CHIP_WIFI) sWiFiCommissioningInstance.Init(); #else return CHIP_ERROR_INTERNAL; #endif /* CONFIG_NET_L2_OPENTHREAD */ #ifdef CONFIG_CHIP_OTA_REQUESTOR /* OTA image confirmation must be done before the factory data init. */ OtaConfirmNewImage(); #endif /* Initialize CHIP server */ #if CONFIG_CHIP_FACTORY_DATA ReturnErrorOnFailure(mFactoryDataProvider.Init()); SetDeviceInstanceInfoProvider(&mFactoryDataProvider); SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider); SetCommissionableDataProvider(&mFactoryDataProvider); #else SetDeviceInstanceInfoProvider(&DeviceInstanceInfoProviderMgrImpl()); SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); #endif static chip::CommonCaseDeviceServerInitParams initParams; (void)initParams.InitializeStaticResourcesBeforeServerInit(); ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); ConfigurationMgr().LogDeviceConfig(); PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); AppFabricTableDelegate::Init(); /* * Add CHIP event handler and start CHIP thread. * Note that all the initialization code should happen prior to this point to avoid data races * between the main and the CHIP threads. */ PlatformMgr().AddEventHandler(ChipEventHandler, 0); err = PlatformMgr().StartEventLoopTask(); if (err != CHIP_NO_ERROR) { LOG_ERR("PlatformMgr().StartEventLoopTask() failed"); return err; } return CHIP_NO_ERROR;
Add the following code before the board components initialization. The
PrepareServer()
method has two optional arguments that you can use to pass your own Matter event handler and initialization data, including custom callbacks to invoke before and after the initialization./* Initialize Matter stack */ ReturnErrorOnFailure(Nrf::Matter::PrepareServer(MatterEventHandler));
Add the following code at the end of
Init()
method:return Nrf::Matter::StartServer();
Add the
main_init
andmatter_event_handler
modules to the compilation. Edit theCMakeLists.txt
file as follows:
target_sources(app PRIVATE ${COMMON_ROOT}/src/app/matter_init.cpp ${COMMON_ROOT}/src/app/matter_event_handler.cpp )
Replace the code used for Matter event handling with the common
matter_event_handler
module. Thematter_event_handler
module handles events generated by the Matter stack in a Nordic platform-specific way. You can customize the module behavior by registering your own Matter event handler that extends the default implementation.To replace the nRF Connect SDK v2.5.0 compliant implementation with the
matter_event_handler
module, complete the following steps:Remove the
MatterEventHandler()
method declaration from theapp_task.h
file.Remove the
MatterEventHandler()
method implementation from theapp_task.cpp
file.Replace the code in the
Init()
method, in theapp_task.cpp
file:Remove:
ReturnErrorOnFailure(Nrf::Matter::PrepareServer(MatterEventHandler));
Add:
ReturnErrorOnFailure(Nrf::Matter::PrepareServer()); /* Register Matter event handler that controls the connectivity status LED based on the captured Matter network * state. */ ReturnErrorOnFailure(Nrf::Matter::RegisterEventHandler(Nrf::Board::DefaultMatterEventHandler, 0));
Add the
matter_event_handler
module to the compilation. EditCMakeLists.txt
file as follows:target_sources(app PRIVATE ${COMMON_ROOT}/src/app/matter_event_handler.cpp )
LwM2M
For LwM2M applications, replace the
CONFIG_LWM2M_CLIENT_UTILS_DTLS_CID
Kconfig option withCONFIG_LWM2M_DTLS_CID
.
nRF5340 Audio applications
The nRF5340 Audio applications have changed the default controller from the LE Audio controller for nRF5340 library to Nordic Semiconductor’s standard SoftDevice Controller (LE Isochronous Channels). SoftDevice Controller is included and built automatically. For nRF Connect SDK 2.6.0, tests have been run and issues documented as before for the previously used LE Audio controller for nRF5340 library. However, the LE Audio controller for nRF5340 library is marked as deprecated, it will be removed soon, and there will be no new features or fixes to this controller. Make sure to remove references to LE Audio controller for nRF5340 from your application and transition to the new controller. There should be no negative impact on performance of the nRF5340 Audio applications with the SoftDevice Controller. This change enables the use of standard nRF Connect SDK tools and procedures for building, configuring and DFU.
Bluetooth® Mesh
For the Bluetooth Mesh samples and applications, a new sensor API (see Bluetooth Mesh sensors) is introduced with nRF Connect SDK v2.6.0. The previous sensor API is deprecated.
The usage of the new sensor API is demonstrated in samples Bluetooth Mesh: Sensor observer, Bluetooth Mesh: Sensor and Bluetooth Mesh: Light fixture.
The Kconfig option
CONFIG_BT_MESH_SENSOR_USE_LEGACY_SENSOR_VALUE
is enabled by default in the deprecation period. This means that the existing samples and applications can continue using the deprecated sensor API as normal during the deprecation period, without the additional configuration. The samples and applications will get a deprecation warning when compiled, that the user can choose to disregard.When the deprecation period is over, the deprecated sensor API will be removed, and the samples and applications will no longer compile unless updated to the new sensor API.
To use the new sensor API for new and existing samples and applications, disable the Kconfig option
CONFIG_BT_MESH_SENSOR_USE_LEGACY_SENSOR_VALUE
in the configuration. This configuration option will be removed when the deprecation period is over, and then it has to be removed from the sample and application configuration. It is also recommended to enable the Kconfig optionCONFIG_FPU
to support the accelerated floating point operations, and the Kconfig optionCONFIG_CBPRINTF_FP_SUPPORT
to support the floating point printing.Sensor API arguments and callback parameters previously defined with
sensor_value
now usebt_mesh_sensor_value
instead.The
bt_mesh_sensor_value.format
needs to be filled by the application for variables passed to the sensor API.There are several different types of
bt_mesh_sensor_format
described in the fileinclude/bluetooth/mesh/sensor_types.h
.When filling in sensor values for a channel, the format can be found through
sensor->type.channels[i].format
defined for the givenbt_mesh_sensor
sensor.bt_mesh_sensor_value
with a valid format can be converted to and from integer, float andsensor_value
throughbt_mesh_sensor_value_to/from*
functions.Where the applications previously just added values directly to
sensor_value.val1
andsensor_value.val2
, the correct way is to usebt_mesh_sensor_value_to/from*
functions to either set or extract the values.
Example of changes that need to be done for a sensor using sensor values, from e.g. the file
drivers/sensor.h
:static int chip_temp_get(struct bt_mesh_sensor_srv *srv, struct bt_mesh_sensor *sensor, struct bt_mesh_msg_ctx *ctx, - struct sensor_value *rsp) + struct bt_mesh_sensor_value *rsp) { + struct sensor_value channel_val; int err; sensor_sample_fetch(dev); - err = sensor_channel_get(dev, SENSOR_DATA_TYPE, rsp); + err = sensor_channel_get(dev, SENSOR_DATA_TYPE, &channel_val); if (err) { printk("Error getting temperature sensor data (%d)\n", err); } + err = bt_mesh_sensor_value_from_sensor_value( + sensor->type->channels[0].format, &channel_val, rsp); + if (err) { + printk("Error encoding temperature sensor data (%d)\n", err); + } return err; }
Example of changes that need to be done for a sensor using the float values:
static int amb_light_level_get(struct bt_mesh_sensor_srv *srv, struct bt_mesh_sensor *sensor, struct bt_mesh_msg_ctx *ctx, - struct sensor_value *rsp) + struct bt_mesh_sensor_value *rsp) { int err; /* Report ambient light as dummy value, and changing it by pressing * a button. The logic and hardware for measuring the actual ambient * light usage of the device should be implemented here. */ - double reported_value = amb_light_level_gain * dummy_ambient_light_value; + float reported_value = amb_light_level_gain * dummy_ambient_light_value; - err = sensor_value_from_double(rsp, reported_value); + err = bt_mesh_sensor_value_from_float(sensor->type->channels[0].format, + reported_value, rsp); - if (err) { + if (err && err != -ERANGE) { printk("Error encoding ambient light level sensor data (%d)\n", err); return err; } return 0; }