This option set plugin allows you to query several sensor registries at the same time. Additional questions can be filled in automatically with information from the sensor registries. To use this feature an attribute mapping must be configured.
The following sensor registries are currently implemented:
For every integration it is possible to define multiple instances in the configuration. This is especially necessary for the Sensor Management System (SMS), since there are four productive instances.
This plugin is based on the RDMO Sensor AWI option set plugin with a complete refactoring, to allow configuration and easy extension with more registries if needed.
The docs directory documents how RDMO catalog elements and
sensorsearch.toml work together. Start with the
catalog editor guide, use the
configuration reference for TOML settings,
and consult the Earth Sensor URI map to find the
exact pages, questions, attributes, optionsets, and conditions in
testing/catalogs/earth-sensor+original.xml. Runtime costs and backend constraints are
covered in operations and limitations.
The developer architecture explains the
internal service, handler, and RDMO signal boundaries.
Install the plugins in your RDMO virtual environment using pip (directly from GitHub):
pip install git+https://github.com/rdmorganiser/rdmo-plugins-sensorsearchOr when editing the code you can put the code a folder beneath your RDMO installation and install it with:
pip install -e ../rdmo-plugins-sensorsearchFor development, install the test dependencies and run pytest with:
pip install -e ".[dev]"
pytest -c testing/pytest-unit.iniThe focused Django signal tests use RDMO's real models and transaction hooks in a separate test environment so the lightweight unit suite can continue to run without a host installation:
pip install -e ".[django-test]"
pytest -c testing/pytest-django.iniAdd the plugin to the OPTIONSET_PROVIDERS in config/settings/local.py:
OPTIONSET_PROVIDERS = [
('sensorsearch_devices', _('Device Search'), 'rdmo_sensorsearch.providers.DeviceSearchProvider'),
('sensorsearch_configurations', _('Configuration Search'), 'rdmo_sensorsearch.providers.ConfigurationSearchProvider'),
('sensorsearch_project_configuration_devices', _('Project Configuration Devices'), 'rdmo_sensorsearch.providers.ProjectConfigurationDevicesProvider'),
('sensorsearch_project_data_collection_devices', _('Project Data Collection Devices'), 'rdmo_sensorsearch.providers.ProjectDataCollectionDevicesProvider'),
('sensorsearch_interview_page_refresh', _('Interview Page Refresh'), 'rdmo_sensorsearch.providers.InterviewPageRefreshProvider'),
]Add the plugin to the INSTALLED_APPS in config/settings/local.py:
INSTALLED_APPS = ['rdmo_sensorsearch'] + INSTALLED_APPSIf SMS requests should reuse the currently logged-in user's access token in post-save synchronization, add the auth context middleware after Django's session and authentication middleware:
MIDDLEWARE = [
# ...
'rdmo_sensorsearch.auth.SensorSearchAuthContextMiddleware',
]After restarting RDMO, Device Search should be selectable as a provider
option for option sets. If you enable the additional provider entries, a
separate Configuration Search provider, a project-local reuse provider for
mounted devices, and a data collection devices provider are available as well.
The data collection devices provider uses the same project-local value source
for data collection instrument selection questions. The no-op Interview Page Refresh provider can be attached to metadata refresh trigger questions so
RDMO refetches the current interview page after saving the trigger.
The importable testing/catalogs/example_catalog_sensorsearch.xml
is a complete, independently namespaced (example.com / plugin-dev) mirror
of the Earth Sensor catalog. Its matching test/example-only profile lives at
testing/fixtures/sensorsearch-plugin-dev.toml;
do not copy those entries into the packaged production configuration.
With sensorsearch.toml the providers which should be used can be configured. The
DeviceSearchProvider aggregates the results of the configured providers.
ConfigurationSearchProvider works the same way for configuration backends.
To automatically fill out questions with results of the matching backend record, attribute mapping for the specific catalog(s) must be configured in the configuration file.
The repository-level sensorsearch.toml is the single maintained deployment
configuration and is copied into the installed package when a wheel is built.
Its structure and cross-references are validated when it is first loaded; an
invalid or misspelled setting prevents plugin initialization and reports its
TOML path. The location can be overwritten with
SENSORSEARCH_CONFIG_FILE_PATH in config/settings/local.py or with an
environment variable of the same name. Restart the RDMO application processes
after changing the configuration because the validated model is cached.
[DeviceSearchProvider]
min_search_len = 3
# Optional: restrict SMS device searches to the SMS backend that matches a
# selected configuration in the current project. Leave false for manual
# instrument searches that should query all configured SMS instances.
filter_sms_devices_by_selected_configuration = false
[DeviceSearchProvider.provider_defaults.SensorManagementSystemDeviceProvider]
max_hits = 20
[ConfigurationSearchProvider]
min_search_len = 3
[ProjectConfigurationDevicesProvider]
[[ProjectConfigurationDevicesProvider.catalogs]]
# Omitting catalog_uri/catalog_uris makes this mapping available in all catalogs.
source_attribute_uri = "http://example.com/terms/domain/configuration-set/member-sensor"
[ProjectDataCollectionDevicesProvider]
[[ProjectDataCollectionDevicesProvider.catalogs]]
# Omitting catalog_uri/catalog_uris makes this mapping available in all catalogs.
source_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/selected-devices"
[MetadataRefresh]
configuration_search_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/configuration-search"
device_search_attribute_uri = "https://rdmo.nfdi.de/terms/domain/dataset/usage_technology/keywords"
[[MetadataRefresh.actions]]
kind = "configuration"
trigger_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/refresh-configuration"
status_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/refresh-status"
message_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/refresh-message"
timestamp_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/refresh-timestamp"
[[MetadataRefresh.actions]]
kind = "configuration"
trigger_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/apply-date-range"
status_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/refresh-status"
message_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/refresh-message"
timestamp_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/configuration-set/refresh-timestamp"
replace_existing_collections = true
require_configuration_period = true
input_attribute_uris = [
"https://rdmo.nfdi4earth.de/terms/domain/configuration-set/configuration-start-datetime",
"https://rdmo.nfdi4earth.de/terms/domain/configuration-set/configurations-end-datetime",
]
[[MetadataRefresh.actions]]
kind = "device"
trigger_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/dataset/usage_technology/refresh-device"
status_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/dataset/usage_technology/refresh-status"
message_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/dataset/usage_technology/refresh-message"
timestamp_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/dataset/usage_technology/refresh-timestamp"
[[MetadataRefresh.actions]]
kind = "all_configurations"
trigger_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/metadata-refresh/configurations/trigger"
status_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/metadata-refresh/configurations/status"
message_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/metadata-refresh/configurations/message"
timestamp_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/metadata-refresh/configurations/timestamp"
[[MetadataRefresh.actions]]
kind = "all_devices"
trigger_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/metadata-refresh/devices/trigger"
status_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/metadata-refresh/devices/status"
message_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/metadata-refresh/devices/message"
timestamp_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/metadata-refresh/devices/timestamp"
[[DeviceSearchProvider.providers.O2ARegistryItemProvider]]
[[DeviceSearchProvider.providers.SensorManagementSystemDeviceProvider]]
id_prefix = "gfzsms"
text_prefix = "GFZ Sensor"
base_url = "https://sensors.gfz.de/backend/api/v1/devices"
[[DeviceSearchProvider.providers.SensorManagementSystemDeviceProvider]]
id_prefix = "kitsms"
text_prefix = "KIT Sensor"
base_url = "https://sms.atmohub.kit.edu/backend/api/v1/devices"
[[DeviceSearchProvider.providers.SensorManagementSystemDeviceProvider]]
id_prefix = "ufzsms"
text_prefix = "UFZ Sensor"
base_url = "https://web.app.ufz.de/sms/backend/api/v1/devices"
[[DeviceSearchProvider.providers.GIPPInstrumentProvider]]
[[ConfigurationSearchProvider.providers.SensorManagementSystemConfigurationProvider]]
id_prefix = "gfzcfg"
text_prefix = "GFZ Cfg"
base_url = "https://sensors.gfz.de/backend/api/v1/configurations"
[[ConfigurationSearchProvider.providers.O2ARegistryMissionProvider]]
id_prefix = "o2amission"
text_prefix = "O2A M"
base_url = "https://registry.o2a-data.de/rest/v2/missions"
where_template = "name=ILIKE=\"*{query}*\""
[handlers.SensorManagementSystemConfigurationHandler]
[[handlers.SensorManagementSystemConfigurationHandler.backends]]
id_prefix = "gfzcfg"
base_url = "https://sensors.gfz.de/backend/api/v1"
device_id_prefix = "gfzsms"
[handlers.SensorManagementSystemConfigurationHandler.defaults]
search_attribute_uri = "http://example.com/terms/domain/configuration-set/configuration-search"
configuration_collection_attribute_uri = "http://example.com/terms/domain/configuration-set"
selected_devices_attribute_uri = "http://example.com/terms/domain/configuration-set/member-sensor"
frontend_link_attribute_uri = "https://rdmorganiser.github.io/terms/domain/project/dataset/uri"
api_link_attribute_uri = "https://rdmorganiser.github.io/terms/domain/project/dataset/source"
location_attribute_uri = "https://rdmorganiser.github.io/terms/domain/project/dataset/spatial"
[handlers.SensorManagementSystemConfigurationHandler.defaults.attribute_mapping]
"data.id" = "https://rdmorganiser.github.io/terms/domain/project/dataset/identifier"
"data.attributes.label" = "https://rdmorganiser.github.io/terms/domain/project/dataset/description"
"data.attributes.project" = "https://rdmorganiser.github.io/terms/domain/project/dataset/documentation"
"data.attributes.persistent_identifier" = "https://rdmorganiser.github.io/terms/domain/project/dataset/id"
"data.attributes.description" = "https://rdmorganiser.github.io/terms/domain/project/dataset/annotation"
"data.links.self" = "https://rdmorganiser.github.io/terms/domain/project/dataset/source"
[[handlers.SensorManagementSystemConfigurationHandler.catalogs]]
catalog_uri = "http://example.com/terms/questions/example-configurations-earth-sensor"
[handlers.O2ARegistryMissionHandler]
[handlers.O2ARegistryMissionHandler.defaults]
search_attribute_uri = "http://example.com/terms/domain/configuration-set/configuration-search"
configuration_collection_attribute_uri = "http://example.com/terms/domain/configuration-set"
selected_devices_attribute_uri = "http://example.com/terms/domain/configuration-set/member-sensor"
device_collection_attribute_uri = "http://example.com/terms/domain/instruments/id"
item_id_prefix = "o2aregistry"
item_text_template = "{configuration} {prefix}({item_id}): {name}{serial}"
[handlers.O2ARegistryMissionHandler.defaults.attribute_mapping]
"description" = "http://example.com/terms/domain/configuration-set/description"
[[handlers.O2ARegistryMissionHandler.catalogs]]
catalog_uri = "http://example.com/terms/questions/example-configurations-earth-sensor"
# These are user-entered filtering inputs, not mission metadata outputs.
period_start_attribute_uri = "http://example.com/terms/domain/configuration-set/start"
period_end_attribute_uri = "http://example.com/terms/domain/configuration-set/end"This configures all available providers with three SMS instances to query. The
DeviceSearchProvider will only query the configured providers if at least three
characters are entered.
Provider labels follow a common <backend> <entity>(<id>): <label> convention:
- SMS devices:
GFZ Sensor(2212): ...,KIT Sensor(327): ..., orUFZ Sensor(823): ... - O2A items:
O2A Item(3581): ... - GIPP instruments:
GFZ GIPP Instrument(1): ... - SMS configurations:
GFZ Cfg(12): ...,KIT Cfg(49): ..., orUFZ Cfg(310): ... - O2A missions:
O2A M(30): ...
Devices imported through a configuration retain their compact relationship in
the Device Set, with the configuration or mission first for easier scanning,
for example KIT Cfg(49) KIT Sensor(327): ... or
O2A M(30) O2A Item(4152): .... Device Details tabs use the complete configuration
label and omit the repeated compact relationship, for example
KIT Cfg(49) KIT Sensor(327): ....
Selecting a backend configuration or mission also prefixes the shared
configuration tab while preserving its user-defined alias. For example,
o2a-test becomes O2A M(30): o2a-test. Replacing the selected backend changes
only the managed prefix, while clearing it restores o2a-test. Since the
Configuration/Mission and Device Set pages use the same collection attribute,
the synchronized label identifies the same tab on both pages.
By default, SMS device search is not restricted by configurations already
selected in the project, so manual instrument searches query all configured SMS
instances. Set filter_sms_devices_by_selected_configuration = true in
[DeviceSearchProvider] only if device searches should be narrowed to the SMS
backend corresponding to an already selected configuration, such as
kitcfg -> kitsms.
When RDMO initializes an asynchronous select containing an existing answer, it requests options using the complete stored answer text. The aggregate providers resolve an exact match from current project values when its external ID belongs to an enabled backend. These initialization requests therefore avoid backend authentication and external API calls. Partial or otherwise unmatched searches continue to query the configured backends normally.
The O2ARegistryItemProvider and GIPPInstrumentProvider
use their default values for id_prefix, text_prefix, base_url and
max_hits.
There is no default base_url for SensorManagementSystemDeviceProvider defined,
therefore the base_url for every instance must be set. In addition the
text_prefix and id_prefix is configured. The text_prefix is displayed
before the result, so that the user can identify the correct registry and
device. The id_prefix is used internally, to prefix the id which is saved
along the value in external_id. This is used by the handler to query the
correct registry when filling out questions with attribute mapping
automatically.
In conclusion, every remote provider has the following options:
id_prefixto identify the instance internally and used by the handlertext_prefixis displayed next to the queried result to identify the used registrymax_hitsdefaults to10and limits the results to displaybase_urlthe API URL of the used instance, must be set for theSensorManagementSystemDeviceProviderandSensorManagementSystemConfigurationProvider
To avoid repeating shared provider settings, provider defaults can be declared once per aggregate provider and backend provider class:
[DeviceSearchProvider.provider_defaults.SensorManagementSystemDeviceProvider]
max_hits = 20These defaults are merged into every
[[DeviceSearchProvider.providers.SensorManagementSystemDeviceProvider]] entry. Any value
declared on the concrete provider entry still overrides the default.
SMS device and configuration providers, plus the corresponding handlers, reuse an available bearer token for SMS backend requests. The token is sent as:
Authorization: Bearer <access-token>
Token resolution is intentionally conservative:
- If
SENSORSEARCH_AUTH_TOKEN_RESOLVERis configured, it is used first. The resolver can be a callable or dotted import path acceptinguserandrequestkeyword arguments. - If the auth context middleware is enabled, session keys from
SENSORSEARCH_AUTH_SESSION_TOKEN_KEYSare checked next. Without explicit keys, a single unambiguousaccess_tokenor*.access_tokensession value is used. - If django-allauth social tokens are available for the user, a single
unexpired token is used. If several social tokens exist, configure
SENSORSEARCH_AUTH_SOCIALACCOUNT_PROVIDERS, for example:
SENSORSEARCH_AUTH_SOCIALACCOUNT_PROVIDERS = ['helmholtz-aai']If no unambiguous token can be resolved, the plugin keeps making public SMS
requests without an Authorization header.
The ProjectConfigurationDevicesProvider and
ProjectDataCollectionDevicesProvider are different. They do not query a
remote backend, but read project-local values which were materialized by a
configuration handler after a configuration was selected. For the Earth-Sensor
catalog, ProjectDataCollectionDevicesProvider reads the selected devices from
https://rdmo.nfdi4earth.de/terms/domain/configuration-set/selected-devices.
Metadata refresh actions are ordinary Yes/No catalog questions. Only the Yes
value triggers an action, and the plugin resets it to No after completion
while its own value signals are muted. Four action kinds are supported:
configurationrefreshes the backend configuration in the trigger value's exactset_prefixandset_indexscope;devicerefreshes the backend device in the trigger value's exactset_prefixandset_indexscope;all_configurationsrefreshes every backend configuration stored in the project;all_devicesrefreshes every materialized device detail block stored in the project.
More than one action can use the configuration kind. The Earth Sensor catalog
uses a second configuration action to apply user-entered start and end values
and replace device membership with the matching period. Free-text date changes
do not call a backend. See the
date-range workflow
and exact Earth Sensor date URIs.
Place the configuration and device triggers directly on their respective
collection pages. Place the two bulk triggers on a non-collection maintenance
page. Feedback attributes are optional scalar text questions in the same scope
as their trigger. Status is stored as success, partial, or failed; the
message contains the refreshed target or aggregate counts and backend errors.
Successful single-configuration messages also report how many associated
devices were refreshed. The timestamp uses local server time.
Each user-triggered refresh deduplicates identical backend GET requests for the duration of that action. This is especially relevant for shared reference endpoints such as the O2A unit list and for devices reused by more than one configuration. The cache is shared with the bounded device-fetch workers, returns isolated response copies to handlers, and is discarded as soon as the refresh finishes.
The selected-device collection can be represented either by one collection
Question or by a collection QuestionSet. The plugin resolves the active shape
from selected_devices_page_uri. Initial configuration or mission selection
imports the complete backend device list using that shape and removes values
using the opposite shape in the same configuration scope. This allows an
existing project to be reused after changing between the two catalog
representations.
User-triggered configuration and all_configurations refreshes treat the
current Device Set as user-managed input. They refresh configuration metadata
without replacing its membership, then refresh device details only for devices
currently selected in that configuration scope. Consequently, manually removed
devices are not reintroduced, manually added backend devices are included, and
obsolete device-detail blocks are removed. Preserved membership is also moved
to the active collection layout when the catalog representation has changed,
and legacy device-first labels are normalized to the configuration-first
convention during the refresh.
Duplicate selected rows with the same device external_id are collapsed to
their first row. Failed configuration requests leave the Device Set unchanged.
Removing a device from the Device Set uses a targeted local cleanup: only that device's detail block is deleted, without refreshing the remaining devices or calling an external sensor backend. Adding or changing a selected device still runs the normal synchronization needed to materialize its detail metadata.
Attach an optionset using InterviewPageRefreshProvider to every trigger
question. Its refresh = True flag makes RDMO refetch the current page after
the trigger save completes, so the reset trigger and feedback values are shown
without navigating away.
For the Earth-Sensor catalog, selected data collection devices also drive the
parameter list of the following data collection question. When a device is
selected in
https://rdmorganiser.github.io/terms/domain/project/dataset/collaboration_tools,
the plugin looks up the device detail values already materialized in section 2
and appends missing parameter name/unit pairs to:
https://rdmo.nfdi4earth.de/terms/domain/project/dataset/metadata/dc-variablehttps://rdmo.nfdi4earth.de/terms/domain/project/dataset/metadata/dc-unit
Existing identical parameter name/unit pairs are not added again. Rows generated
by this synchronization are marked with a sensorsearch:dc-variable: external
ID. When a device is removed from the data collection device list, generated
parameter rows are removed again if no remaining selected device still provides
that parameter name/unit pair. Manually entered rows and older unmarked rows are
left untouched.
This synchronization is enabled only for catalogs listed under
DataCollectionVariableSync. The attribute URI settings are optional when the
catalog uses the defaults shown above:
[DataCollectionVariableSync]
[[DataCollectionVariableSync.catalogs]]
catalog_uris = [
"https://rdmo.nfdi4earth.de/terms/questions/earth-sensor-with-refresh-feature-v1",
]
# devices_attribute_uri = "https://rdmorganiser.github.io/terms/domain/project/dataset/collaboration_tools"
# device_collection_attribute_uri = "https://rdmo-sandbox.gfz-potsdam.de/terms/domain/moses/instruments/id"
# parameter_name_attribute_uri = "https://rdmo.nfdi.de/terms/domain/dataset/usage_technology/preservation/parameter/name"
# parameter_unit_attribute_uri = "https://rdmo.nfdi.de/terms/domain/dataset/usage_technology/preservation/parameter/unit"
# variable_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/project/dataset/metadata/dc-variable"
# unit_attribute_uri = "https://rdmo.nfdi4earth.de/terms/domain/project/dataset/metadata/dc-unit"O2A Registry missions are exposed through O2ARegistryMissionProvider. They
follow the same configuration flow as SMS configurations: selecting a mission
can materialize its items into the configured project-local device collection.
The default search query uses the O2A RSQL form name=ILIKE="*{query}*".
Handlers can be used to fill out questions automatically with the use of a configured attribute mapping. For every provider a handler is implemented, which can request additional information from the registry to answer questions.
Handler defaults can also be configured once and then reused by multiple catalogs or even applied as a wildcard mapping for any catalog which uses the same autocomplete field.
[handlers.O2ARegistryItemHandler]
#[[handlers.O2ARegistryItemHandler.backends]]
#id_prefix = "o2aregistry"
[handlers.O2ARegistryItemHandler.defaults]
search_attribute_uri = "http://rdmo-dev.local/terms/domain/sensor/awi/search"
materialize_device_details = true
device_link_attribute_uri = "http://rdmo-dev.local/terms/domain/sensor/device-link"
[handlers.O2ARegistryItemHandler.defaults.attribute_mapping]
"longName" = "http://rdmo-dev.local/terms/domain/sensor/awi/type-name"
"shortName" = "http://rdmo-dev.local/terms/domain/sensor/awi/name"
"serialNumber" = "http://rdmo-dev.local/terms/domain/sensor/awi/serial"
[[handlers.O2ARegistryItemHandler.catalogs]]
catalog_uri = "http://rdmo-dev.local/terms/questions/sensor-awi-test"
# optional per-catalog overrides can be added here
[handlers.SensorManagementSystemDeviceHandler]
[[handlers.SensorManagementSystemDeviceHandler.backends]]
id_prefix = "gfzsms"
base_url = "https://sensors.gfz.de/backend/api/v1"
[[handlers.SensorManagementSystemDeviceHandler.backends]]
id_prefix = "kitsms"
base_url = "https://sms.atmohub.kit.edu/backend/api/v1"
[[handlers.SensorManagementSystemDeviceHandler.backends]]
id_prefix = "ufzsms"
base_url = "https://web.app.ufz.de/sms/backend/api/v1"
[handlers.SensorManagementSystemDeviceHandler.defaults]
search_attribute_uri = "http://rdmo-dev.local/terms/domain/sensor/awi/search"
[handlers.SensorManagementSystemDeviceHandler.defaults.attribute_mapping]
"data.attributes.long_name" = "http://rdmo-dev.local/terms/domain/sensor/awi/type-name"
"data.attributes.short_name" = "http://rdmo-dev.local/terms/domain/sensor/awi/name"
"data.attributes.serial_number" = "http://rdmo-dev.local/terms/domain/sensor/awi/serial"
[[handlers.SensorManagementSystemDeviceHandler.catalogs]]
catalog_uri = "http://rdmo-dev.local/terms/questions/sensor-awi-test"
[handlers.GIPPInstrumentHandler]
[handlers.GIPPInstrumentHandler.defaults]
search_attribute_uri = "http://rdmo-dev.local/terms/domain/sensor/awi/search"
[handlers.GIPPInstrumentHandler.defaults.attribute_mapping]
"Instrument.code" = "http://rdmo-dev.local/terms/domain/sensor/awi/type-name"
"Instrumentcategory.name" = "http://rdmo-dev.local/terms/domain/sensor/awi/name"
"Instrument.serialNo" = "http://rdmo-dev.local/terms/domain/sensor/awi/serial"
[[handlers.GIPPInstrumentHandler.catalogs]]
catalog_uri = "http://rdmo-dev.local/terms/questions/sensor-awi-test"A backends configuration must be defined in the case of
SensorManagementSystemDeviceHandler or if more than one instance of one provider is
used. Here the id_prefix and the base_url is critical and must be the same
as in the providers configuration, so that additional requests can be made
to the correct endpoint.
The catalogs configuration is used to identify the catalog(s) where the
attribute mapping should be used to map values from the API response to
attributes of the catalog. It is possible to configure more than one catalog.
catalog_uriis the uri of the catalog where the handler should map values to attributessearch_attribute_uriis the uri of the question with the option set provider used in the catalogmanaged_attribute_urisadds attributes to the handler's ownership beyond those inattribute_mapping. Every successful refresh is authoritative for this complete set: returned values are created or updated in place, while owned values omitted by the backend are removed. Unmanaged interview values are left untouched. Clearing the source question applies the same ownership rules with an empty result.materialize_device_details = truemarks an item or device handler as eligible for configuration or mission based detail-block synchronization.supports_mount_period_lookup = trueenables the SMS-specific fallback that resolves instrument start/end from device mount actions.
The new defaults table is merged into every catalogs entry for the same
handler. If defaults define search_attribute_uri, they also act as a
wildcard handler configuration for any catalog using that field, even when no
explicit [[handlers.<Handler>.catalogs]] entry exists. Explicit catalog
entries take precedence over the wildcard defaults.
With catalogs.attribute_mapping the mapping from the APIs JSON response is
mapped to attributes of the specified catalog. On the left a
JMESPath for the value from the API and on the right
the uri to the attribute in the catalog.
As of 2026, this plugin has been further developed and maintained through the DMP4NFDI project, as an Incubator for the NFDI4Earth consortium.
DMP4NFDI is a Basic Service of Base4NFDI, funded by the German Research Foundation (DFG) under project 521453681. NFDI4Earth is funded by the DFG under project 460036893. Both projects are part of the German National Research Data Infrastructure (NFDI).