Detecting Unwanted Location Trackers (DULT) integration

The Detecting Unwanted Location Trackers (DULT) is a specification that lists a set of best practices and protocols for manufacturers of products with built-in location tracking capabilities. Following the specification improves the privacy and safety of individuals by preventing the location tracking products from tracking users without their knowledge or consent. For detailed information about supported functionalities, see the official DULT documentation.

Note

The DULT documentation has the Internet-Draft status, which means it is valid for a maximum of six months and subject to change or obsolescence. For more details, refer to the DULT status section from the DULT specification.

The DULT support in the nRF Connect SDK is experimental. Breaking updates in the DULT support might be implemented in response to changes in the DULT specification. Not all optional features are supported.

Integration prerequisites

Before you start the nRF Connect SDK integration with DULT, make sure that the following prerequisites are fulfilled:

Solution architecture

The nRF Connect SDK integrates the location-tracking accessory role, facilitating communication between the accessory-locating network (typically a smartphone) and the accessory (your device). The integration requires completing the Integration steps section.

Integration steps

The DULT integration in the nRF Connect SDK consists of the following steps:

  1. Registering the device

  2. Performing prerequisite operations

  3. Handling multiple accessory-locating networks

  4. Managing the near-owner state

  5. Customizing the access policy to the accessory non-owner service

  6. Building the location-enabled advertising payload

  7. Managing the identification process

  8. Using the sound callbacks and managing the sound state

  9. Interacting with the motion detector

  10. Managing the battery information

These steps are described in the following sections.

The DULT standard implementation in the nRF Connect SDK integrates the location-tracking accessory role. For an integration example, see the Find Hub Network (FHN) extension of the Google Fast Pair Service (GFPS). Also see the Bluetooth Fast Pair: Locator tag sample that integrates the Fast Pair with the FHN extension, which integrates the Detecting Unwanted Location Trackers (DULT) module.

Registering the device

The location-tracking accessory must be registered with the accessory-locating network that it aims to join. Upon registration, the network provider generates registration data for the accessory. The location-tracking accessory uses the registration data for procedures defined by the DULT standard.

Check with the network provider for information on how to register the accessory and obtain the necessary data. After registration, you should have the following data:

  • Product data - A unique identifier for the accessory make and model.

  • Manufacturer name - The name of the company that produces the accessory.

  • Model name - The name of the specific model of the accessory.

  • Accessory category - Choose the appropriate category value from the DULT Accessory Category Values table.

  • Network ID - Accessory-locating network ID. See the DULT Manufacturer Network ID Registry from the DULT specification for a list of network IDs.

  • Network version (optional) - The version of the accessory-locating network implementation running on the accessory.

  • Knowledge on how to construct the Identifier Payload - The accessory-locating network defines its own identifier that allows the network to identify the accessory in case of unwanted tracking, and to share obfuscated accessory owner information with a tracked individual.

Performing prerequisite operations

You must enable the CONFIG_DULT Kconfig option to support the DULT standard in your project.

Several Kconfig options are available to configure the DULT integration. For more details, see the Configuration section of the Detecting Unwanted Location Trackers (DULT).

DULT API variant

The DULT subsystem provides two API contracts that differ in the number of supported DULT users and in the user lifecycle. Select one with the CONFIG_DULT_API_VARIANT_V1 or the CONFIG_DULT_API_VARIANT_V2 Kconfig option.

API variant v1 (CONFIG_DULT_API_VARIANT_V1):

  • Only one DULT user can be registered at a time.

  • The dult_reset() function is the terminal teardown. It releases the DULT subsystem, unregisters the DULT user together with its callbacks, and clears the preset configuration.

  • The dult_user_unregister(), dult_multi_user_cb_register(), and dult_multi_user_conn_claim() functions are not supported.

  • In a typical integration, the DULT association follows the lifetime of the accessory-locating network stack. The network stack claims the DULT association with the dult_enable() function during its enable operation and releases it with the dult_reset() function during its disable operation.

API variant v2 (CONFIG_DULT_API_VARIANT_V2):

  • Up to CONFIG_DULT_USER_MAX DULT users can be registered at the same time, but just one of them is the associated user.

  • The dult_reset() function is not terminal. It releases the association and keeps the DULT user registered, so the user can be enabled again with the dult_enable() function.

  • The dult_user_unregister() function is the terminal teardown that frees the user.

  • The registered callbacks, the battery level, and the near-owner state are preserved across the dult_reset() function call and cleared by the dult_user_unregister() function call.

  • In a typical integration, the DULT association follows the association state with the accessory-locating network. The network stack claims the DULT association when the accessory is being associated with this network, or during the stack enable procedure if the accessory is already associated. For example, the FHN extension of the Fast Pair module claims the association during its provisioning operation. The stack releases the DULT association when the accessory association with this network is being removed or during the stack disable procedure.

Whenever the integration of the DULT subsystem is different for the selected API variant, it is highlighted with tabs consistently throughout this guide.

For an example of both integrations, see the DULT integration section of the Fast Pair integration guide.

Note

The CONFIG_DULT_API_VARIANT_V1 option is selected by default for backwards compatibility, but it is deprecated. Use the CONFIG_DULT_API_VARIANT_V2 option for new integrations.

Accessory type

Declare the size and the discoverability of your accessory with the CONFIG_DULT_ACCESSORY_TYPE_SMALL or the CONFIG_DULT_ACCESSORY_TYPE_LARGE Kconfig option. The CONFIG_DULT_ACCESSORY_TYPE_SMALL option is selected by default. Check the size and discoverability requirements in the DULT specification to determine the accessory type for your product.

The DULT specification best practices are required for accessories that are small and not easily discoverable, and only recommended for accessories that are large and easily discoverable. The requirements for large accessories are therefore more relaxed:

DULT user

The DULT subsystem introduces the concept of a DULT user. Each DULT user represents one accessory-locating network, identified by its network ID. The number of users that can be registered at the same time depends on the selected DULT API variant. To use the DULT subsystem, you must register a DULT user by calling the dult_user_register() function before you can call any other function from the DULT API. Upon registration, you must provide the DULT user configuration to the DULT subsystem. The DULT user configuration includes the following data:

  • Registration data - The data obtained during registering the device.

  • Accessory capabilities - Capabilities of your accessory. Set appropriate bits in the bitmask to indicate the supported capabilities. There are following capabilities available:

    • Play sound (DULT_ACCESSORY_CAPABILITY_PLAY_SOUND_BIT_POS) - A feature that enables the accessory to emit sound signals.

    • Motion detector unwanted tracking (DULT_ACCESSORY_CAPABILITY_MOTION_DETECTOR_UT_BIT_POS) - A feature that improves security by preventing unwanted tracking.

    • Identifier lookup by NFC (DULT_ACCESSORY_CAPABILITY_ID_LOOKUP_NFC_BIT_POS) - A feature supporting identifier lookup by NFC functionality.

    • Identifier lookup by Bluetooth® LE (DULT_ACCESSORY_CAPABILITY_ID_LOOKUP_BLE_BIT_POS) - A feature supporting identifier lookup by Bluetooth LE functionality.

  • Firmware version - The firmware version of your accessory.

  • Network version - The version of the accessory-locating network implementation, provided through the dult_user.network_version field. This field is optional. Leave it as NULL if the accessory-locating network does not define a network version.

The DULT user registration fails if a mandatory accessory capability is missing. Which capabilities are mandatory depends on the declared Accessory type:

  • With the CONFIG_DULT_ACCESSORY_TYPE_SMALL Kconfig option, the play sound capability is mandatory, and at least one of the identifier lookup capabilities, by NFC or by Bluetooth LE, must be declared. The motion detector unwanted tracking capability is optional.

  • With the CONFIG_DULT_ACCESSORY_TYPE_LARGE Kconfig option, all accessory capabilities are optional and the DULT subsystem does not validate them.

The DULT user registration also fails if the same DULT user structure is already registered or if another registered DULT user uses the same network ID in the dult_user.network_id field. Each registered DULT user must represent a different accessory-locating network.

How you release a registered DULT user depends on the selected DULT API variant:

Call the dult_reset() function. This function unregisters the registered DULT user information and callbacks, so you must register them again to change the DULT user.

Callback registration

An application can communicate with the DULT subsystem using API calls and registered callbacks. The DULT subsystem uses the registered callbacks to inform the application about the DULT-related events and to retrieve the necessary information from the application.

The application must register the required callbacks before it enables the DULT subsystem and starts to operate as the location-tracking accessory. To identify the callback registration functions in the DULT API, look for the _cb_register suffix. Set your application-specific callback functions in the callback structure, which serves as the input parameter for the ..._cb_register API function. Each callback structure is registered for each DULT user. The callback structure must persist in the application memory (static declaration), as during the registration, the DULT subsystem stores only the memory pointer to it. Use the following functions to register callbacks:

The lifetime of the registered callbacks depends on the selected DULT API variant:

The callbacks are cleared by the dult_reset() function and must be registered again after each subsequent DULT user registration.

Preset configuration

Before enabling the DULT subsystem, you should preset the initial accessory configuration with dedicated APIs that depend on the chosen feature set or the accessory state. The preset configuration is available for the following API functions:

The preset configuration is stored for each DULT user, in the same way as the registered callbacks. Only the preset configuration of the associated user is effective. A user that wins the association arbitration always applies its own preset configuration, and the values preset by the other registered users are never used on its behalf.

Enabling the DULT subsystem

After the DULT user registration, callbacks registration and preset configuration, you must enable the DULT subsystem with the dult_enable() function. The DULT user that successfully calls this function becomes the associated user. In the DULT subsystem disabled state, most of the DULT APIs are not available.

The teardown depends on the selected DULT API variant:

The dult_reset() function unregisters the current DULT user and callbacks, resets the preset configuration, and disables the DULT subsystem.

Use the dult_user_is_associated() and dult_is_any_associated() functions to query the current association state.

Handling multiple accessory-locating networks

This step applies only to products that support multiple DULT-based accessory-locating networks. Skip it if your product registers a single accessory-locating network.

To support this use case, enable the CONFIG_DULT_API_VARIANT_V2 Kconfig option and set the value of the CONFIG_DULT_USER_MAX Kconfig option to the number of accessory-locating networks that your product registers. The CONFIG_DULT_API_VARIANT_V1 Kconfig option supports a single DULT user and emits no association notifications. All registered users share the DULT subsystem during the pre-association window, but just one of them is the associated user.

The associated user is arbitrated by the dult_enable() function and processed in the order received. The first registered user that calls it becomes the associated user, and every other registered user is evicted. While the association is held, the dult_enable() function called by another registered user fails, so the associated user is never preempted. The DULT subsystem notifies all registered users about the arbitration outcome through the dult_multi_user_cb.ownership_claimed callback. The callback’s is_owner parameter is set to true for the user that won the arbitration, and to false for a user that was evicted. Releasing the association with the dult_reset() function notifies all registered users through the dult_multi_user_cb.ownership_released callback. The callback’s was_owner parameter is set to true for the user whose association just ended, and to false for a registered bystander that can claim the association again.

An evicted user stays registered until it calls the dult_user_unregister() function as part of its own teardown. While another accessory-locating network stack holds the DULT association, every evicted user must block its own association flow, so that the accessory cannot be associated with two accessory-locating networks at the same time. The way to achieve this depends on the capabilities of the evicted accessory-locating network stack.

If the eviction is related to a network stack that must be disabled to block the association flow, you have the following options to satisfy this requirement:

Otherwise, you can keep the evicted user registered and block its association flow at the application code level until the association is released. Consult the network-specific documentation to find the guidance on the recommended approach.

Claiming the association again is a decision of the user that owns the accessory state, not an automatic consequence of the dult_multi_user_cb.ownership_released callback.

Both notifications are delivered from the system workqueue, so you can drive the DULT user lifecycle directly from the callback. Transitions are delivered in order, but toggling the association repeatedly within a single execution context without yielding may collapse cancelling transitions and lose intermediate states. The final association state is always reported correctly, and two consecutive notifications of the same kind are never delivered.

Managing the near-owner state

The location-tracking accessory can be in one of the two modes of the DULT near-owner state:

  • Separated mode - The accessory is separated from the owner.

  • Near-owner mode - The accessory is near the owner.

Check with your accessory-locating network provider for information on how to switch between the two modes. Call the dult_near_owner_state_set() function to set the appropriate DULT near-owner state after registering the DULT user and whenever the state changes. By default, the DULT near-owner state is set to the near-owner mode on boot. The state is stored for each DULT user, and the accessory reports the value of the currently associated user.

The lifetime of the preset state depends on the selected DULT API variant:

The state is also reset to the near-owner mode when the dult_reset() function is called.

While no user is associated, the effective near-owner state is the near-owner mode, regardless of the values preset by the registered users. A value preset with the dult_near_owner_state_set() function becomes effective when the user becomes the associated user.

In the near-owner mode, most of the DULT functionalities are unavailable to protect the owner’s privacy.

Customizing the access policy to the accessory non-owner service

By default, the accessory non-owner service (ANOS) accepts operations only in the separated near-owner state, as required by the DULT specification. Your accessory-locating network stack can override this gate for the Accessory Information operations by registering the dult_bt_anos_cb structure with the dult_bt_anos_cb_register() function. This step is optional and available with both DULT API variants.

The order in which the ANOS verifies each operation depends on whether the dult_bt_anos_cb callback structure is registered:

  1. Operations that are not defined by the DULT specification are rejected.

  2. All operations are rejected outside the separated near-owner state.

  3. Operation-specific preconditions are verified, and a failed precondition is reported with the status defined for that operation. For example, operations that depend on an accessory capability that is not declared are rejected.

Register the callback structure as described in the Callback registration section.

While a DULT user is associated, the ANOS consults the access policy of the associated user. The callback can then relax the near-owner state gate and allow the Accessory Information operations in the near-owner mode.

When no DULT user is associated, the ANOS rejects all operations unless the Bluetooth LE connection is claimed with the dult_multi_user_conn_claim() function. This function is available only with the CONFIG_DULT_API_VARIANT_V2 Kconfig option, see the Accessing ANOS before associating with an accessory-locating network section for details.

Note

Granting access to the accessory non-owner service operations outside the separated near-owner state is a deviation from the DULT specification. Make sure that the policy implemented by the dult_bt_anos_cb.access_verify callback matches the specification of the accessory-locating network layered on top of DULT.

Accessing ANOS before associating with an accessory-locating network

This section applies to products that must serve the Accessory Information operations before the accessory is associated with its accessory-locating network, for example during the accessory association flow.

Two associations are involved in this flow:

  • The association with the accessory-locating network, which that network defines, for example the provisioning operation of the FHN extension of the Fast Pair module.

  • The DULT association, which is claimed with the dult_enable() function and is internal to the DULT subsystem.

The DULT association can be claimed at any point before the accessory is associated with the accessory-locating network. How early the ANOS can serve the Accessory Information operations depends on the selected DULT API variant:

The ANOS rejects every operation until the DULT association is claimed. Register the access policy callback while the DULT subsystem is still disabled, and call the dult_enable() function as soon as your accessory-locating network stack is ready to serve the Accessory Information operations.

Before the accessory is associated with the accessory-locating network, it typically stays in the near-owner mode, so the access policy callback can grant access to the Accessory Information operations only. The Non-owner controls operations stay unavailable until the accessory switches to the separated mode, see Managing the near-owner state.

Building the location-enabled advertising payload

The DULT specification defines a location-enabled advertising payload with a fixed part that is common to every accessory-locating network. Integrating this payload is up to the accessory-locating network, and not every network uses it. Some networks might define their own advertising payload structure instead. Check with your accessory-locating network provider whether the network relies on the DULT payload, and skip this step if it does not.

If your accessory-locating network does integrate the DULT location-enabled advertising payload, the network stack is responsible for advertising it. Use the dult_bt_adv_data_fill() function to encode the DULT Advertising Data (AD) into the bt_data structure. Pass the network-specific proprietary data through the dult_bt_adv_data structure as the function input parameter, and provide the memory for the bt_data structure and the associated buffer (buf and buf_size) as output parameters. The buffer must remain valid for as long as the resulting bt_data structure is referenced by your advertising set. Initialize the dult_bt_adv_data structure with one of the following macros, depending on the level of customization you require:

For the first two macros, set the dult_bt_adv_data.flags_present field according to whether the surrounding advertising payload includes the optional Flags AD type. The field selects the proprietary data length limit:

Note

The extended limit exceeds the proprietary data field size defined by the DULT specification. Use it only if you can guarantee that the surrounding advertising payload emits no Flags AD type.

Only the currently associated DULT user can call the dult_bt_adv_data_fill() function, because the location-enabled advertising payload is defined only for an associated accessory. Build the payload after the dult_enable() function call succeeds and stop advertising it once the association is released. The serialized payload carries the near-owner state as it was at the time of the call. Serialize the payload again and update your advertising set whenever the DULT near-owner state changes, so that the advertised near-owner state stays accurate.

Note

The DULT module is only responsible for serializing the DULT Advertising Data (AD) payload. The remaining requirements for the location-enabled Bluetooth LE advertising, such as the advertising interval and the Bluetooth LE address, are defined by the DULT specification. The code that manages the Bluetooth LE advertising with the DULT payload must comply with all of these requirements.

Managing the identification process

The accessory is required to include a way to uniquely identify it. One way to satisfy this requirement is to add a mechanism for retrieving the Identifier Payload defined by the accessory-locating network. The identifier can be retrieved over Bluetooth LE.

Identifier retrieval over Bluetooth LE

When identifier retrieval over Bluetooth LE is supported, the DULT specification requires the accessory to provide a physical mechanism (for example, button press and hold) that can be utilized to enter the identifier read state for a limited amount of time. In this state, the DULT subsystem allows the accessory-locating network to read the Identifier Payload.

Set the identifier lookup by Bluetooth LE accessory capability bit (DULT_ACCESSORY_CAPABILITY_ID_LOOKUP_BLE_BIT_POS) in the accessory capabilities bitmask when registering the DULT user if you support this method of retrieving the identifier.

To register the identifier read state callbacks, use the dult_id_read_state_cb_register() function. Call the dult_id_read_state_enter() function to enter the identifier read state. The identifier read state is automatically exited after a timeout. Calling the dult_id_read_state_enter() function while the accessory is already in the identifier read state resets the timeout. When the identifier read state is exited, the DULT subsystem calls the dult_id_read_state_cb.exited callback to inform the application about this event. Upon receiving the identifier read request, when the accessory is in the identifier read state, the DULT subsystem calls the dult_id_read_state_cb.payload_get callback to get the Identifier Payload from the application. During the callback execution, you must provide the Identifier Payload using callback output parameters. The Identifier Payload must be constructed according to the requirements defined by the chosen accessory-locating network.

The connected non-owner device requests the identification information using the accessory non-owner service (ANOS) through GATT write operation. The accessory responds with the Identifier Payload using the ANOS through GATT indication operation. Configure the CONFIG_DULT_BT_ANOS_ID_PAYLOAD_LEN_MAX Kconfig option to set the maximum length of your accessory-locating network Identifier Payload.

Using the sound callbacks and managing the sound state

The DULT specification requires the accessory to support the play sound functionality. For details about the sound maker, see the DULT Sound maker section of the DULT documentation.

To integrate the play sound functionality, set the play sound accessory capability bit (DULT_ACCESSORY_CAPABILITY_PLAY_SOUND_BIT_POS) in the accessory capabilities bitmask. You must do this when registering the DULT user to indicate support for this functionality.

There are following sound sources available:

  • Bluetooth GATT (DULT_SOUND_SRC_BT_GATT) - Sound source type originating from the Bluetooth ANOS. The non-owner device can trigger the sound callbacks by sending the relevant request message over the DULT GATT service.

  • Motion detector (DULT_SOUND_SRC_MOTION_DETECTOR) - Sound source type originating from the motion detector. The motion detector may trigger the sound callbacks if the accessory separated from the owner for an amount of time controlled by the CONFIG_DULT_MOTION_DETECTOR_SEPARATED_UT_TIMEOUT_PERIOD_MIN and CONFIG_DULT_MOTION_DETECTOR_SEPARATED_UT_TIMEOUT_PERIOD_MAX Kconfig options is moving. Used only when the CONFIG_DULT_MOTION_DETECTOR Kconfig option is enabled.

  • External (DULT_SOUND_SRC_EXTERNAL) - Sound source type originating from the location unknown to the DULT module. The accessory-locating network often provides a native mechanism for playing sounds. The DULT_SOUND_SRC_EXTERNAL sound source is used to notify the DULT module that externally defined sound action is in progress.

To register the sound callbacks, use the dult_sound_cb_register() function. All sound callbacks defined in the dult_sound_cb structure are mandatory to register:

  • The sound start request is indicated by the dult_sound_cb.sound_start callback. The minimum duration for the DULT sound action originating from the Bluetooth ANOS is defined by the DULT_SOUND_DURATION_BT_GATT_MIN_MS. The upper layer determines the sound duration, and for the sound action originating from the Bluetooth ANOS, the duration must exceed the value set in the DULT_SOUND_DURATION_BT_GATT_MIN_MS macro. In case of the sound action originating from the motion detector, the minimum duration is not defined.

  • The sound stop request is indicated by the dult_sound_cb.sound_stop callback.

All callbacks pass the sound source as a first parameter and only report the internal sound sources (DULT_SOUND_SRC_BT_GATT or DULT_SOUND_SRC_MOTION_DETECTOR). The DULT_SOUND_SRC_EXTERNAL never appears as the callback parameter as the external sound source cannot originate from the DULT module. You must treat all callbacks from the dult_sound_cb structure as requests. The internal sound state of the DULT subsystem is not automatically changed on any callback event. The state is only changed when you acknowledge such a request in your application using the dult_sound_state_update() function. The application is the ultimate owner of the sound state and only notifies the DULT subsystem about each change. The dult_sound_state_update() function should be called by the application on each sound state change as defined by the dult_sound_state_param structure. All fields defined in this structure compose the sound state. You must configure the following fields in the dult_sound_state_param structure that is passed to the dult_sound_state_update() function:

  • Sound state active flag - Determines whether the sound is currently playing.

  • Source of the new sound state - The sound source that triggered the sound state change.

The dult_sound_state_update() function can be used to change the sound state asynchronously, as it is often impossible to execute sound playing action on the speaker device in the context of the requesting callbacks. Asynchronous support is also necessary to report sound state changes that are triggered by an external source unknown to the DULT subsystem.

Interacting with the motion detector

DULT motion detector is an optional feature of the DULT subsystem. For more details, see the DULT motion detector section of the DULT documentation. To support the DULT motion detector feature in your project, enable the CONFIG_DULT_MOTION_DETECTOR Kconfig option.

To integrate the motion detector feature, set the motion detector unwanted tracking accessory capability bit (DULT_ACCESSORY_CAPABILITY_MOTION_DETECTOR_UT_BIT_POS) in the accessory capabilities bitmask. You must do this when registering the DULT user to indicate support for this feature.

To register the motion detector callbacks, use the dult_motion_detector_cb_register() function. You must register all motion detector callbacks defined in the dult_motion_detector_cb structure:

  • The motion detector start request is indicated by the dult_motion_detector_cb.start callback. After this callback is called, the motion detector events are polled periodically with the dult_motion_detector_cb.period_expired callback. A typical action after the motion detector start request is to power up the accelerometer and start collecting motion data.

  • The motion detector period expired event is indicated by the dult_motion_detector_cb.period_expired callback. This callback is called at the end of each motion detector period. The dult_motion_detector_cb.start callback indicates the beginning of the first motion detector period. The next period is started as soon as the previous period expires. The user should notify the DULT module if motion was detected in the previous period. The return value of this callback is used to pass this information. The motion must be considered as detected if it fulfills the requirements defined in the DULT motion detector section of the DULT documentation.

  • The motion detector stop request is indicated by the dult_motion_detector_cb.stop callback. It concludes the motion detector activity that was started by the dult_motion_detector_cb.start callback. A typical action after the motion detector stop request is to power down the accelerometer.

The motion detector is started by the DULT subsystem when the accessory is in the separated state for an amount of time controlled by the CONFIG_DULT_MOTION_DETECTOR_SEPARATED_UT_TIMEOUT_PERIOD_MIN and CONFIG_DULT_MOTION_DETECTOR_SEPARATED_UT_TIMEOUT_PERIOD_MAX Kconfig options. When the motion is detected during the motion detector active period, the DULT subsystem calls the dult_sound_cb.sound_start callback to request the sound action with the DULT_SOUND_SRC_MOTION_DETECTOR parameter as the sound source. Emitted sounds help to alert the non-owner that they are carrying an accessory that does not belong to them and might be used by the original owner to track their location.

Test mode

Enable the CONFIG_DULT_MOTION_DETECTOR_TEST_MODE Kconfig option to shorten the separated unwanted tracking timings, so that the motion detector can be exercised without waiting for the production periods. With this option enabled, the CONFIG_DULT_MOTION_DETECTOR_SEPARATED_UT_BACKOFF_PERIOD, CONFIG_DULT_MOTION_DETECTOR_SEPARATED_UT_TIMEOUT_PERIOD_MIN, and CONFIG_DULT_MOTION_DETECTOR_SEPARATED_UT_TIMEOUT_PERIOD_MAX Kconfig options become configurable and default to short test values.

You can also override the same timings at runtime with the dult_test_motion_detector_separated_ut_period_set() function:

  • The runtime values in the dult_test_motion_detector_separated_ut_period structure are expressed in seconds, while the Kconfig options are expressed in minutes.

  • New values take effect on the next timer arm and do not restart a timer that is already running.

For the accepted value ranges, see the API documentation of the Detecting Unwanted Location Trackers (DULT) library.

Caution

The CONFIG_DULT_MOTION_DETECTOR_TEST_MODE option selects the CONFIG_DULT_TEST option, which enables the test-only layer of the DULT module. Use it for qualification and debugging only, and never enable it in a production build.

Managing the battery information

DULT battery information is an optional feature of the DULT GATT service. You can enable the CONFIG_DULT_BATTERY Kconfig option to support the DULT battery information in your project. Select the battery type that your device uses (see the CONFIG_DULT_BATTERY_TYPE choice configuration). You can also configure the CONFIG_DULT_BATTERY_LEVEL_CRITICAL_THR, CONFIG_DULT_BATTERY_LEVEL_LOW_THR, and CONFIG_DULT_BATTERY_LEVEL_MEDIUM_THR Kconfig options to specify the mapping between a battery level expressed as a percentage value and battery levels defined in the DULT specification. The battery level expressed as a percentage value is mapped to one of four battery levels defined in the DULT specification:

When the battery information is enabled, use the dult_battery_level_set() function to set the current battery level. The battery level is stored for each DULT user, so each registered user must set its own value after its registration.

The point at which you must set the battery level depends on the selected DULT API variant:

You must set the battery level before enabling DULT, as the dult_enable() function fails otherwise.

To keep the battery level information accurate, you should set the battery level to the new value with the help of this function as soon as the device battery level changes. If the CONFIG_DULT_BATTERY Kconfig option is disabled, the dult_battery_level_set() function must not be used.

Applications and samples

The following sample use the DULT integration in the nRF Connect SDK:

Library support

The following nRF Connect SDK library support the DULT integration:

Terms and licensing

The use of DULT may be subject to terms and licensing. Refer to the official DULT documentation for development-related licensing information.

Dependencies

The following are the required dependencies for the DULT integration: