Models #
In order to model a use case, it is possible to define models of sensors and assets that will be used when creating digital twins.
Each sensor or asset is an instance of a previously defined model.
Models can be defined upstream through the backend framework but also dynamically using the API.
Metadata Referential #
The metadata referential holds, in a single document, the metadata shared by the models of an application: their mappings, default translations, editor hint, default value and icon.
The mappings of every referential metadata are merged into the assets, devices and groups collections of every engine, used by a model or not. Asset, device and group models then use a metadata of the referential with { "referential": true } in their metadataMappings, instead of redefining its mappings. This prevents models registered by different parts of an application from defining the same metadata with conflicting mappings.
A referential entry contains the following information:
mappings: metadata mappings, either{ type: "<type>" }or{ properties: { ... } }(See Collection Mappings)locales: default translations of the metadataeditorHint: (optional) default editor hintdefaultValue: (optional) default valueicon: (optional) icon representing the metadata. Free-form string, e.g. a FontAwesome icon name, a URL to a PNG/SVG image, or inline SVG markup
When a model is written, the { "referential": true } marker is kept in its metadataMappings, and the referential values are copied into the model:
metadataDetails: the referentialeditorHintandiconwhen the model does not define them, and the referentiallocalesmerged per locale under the model ones. A locale can override only itsfriendlyNameor itsdescription; a locale missing from the referential defaults to the metadata name and an empty description. Thegroupis defined by the modeldefaultMetadata: the referentialdefaultValuewhen the model does not define one
The get, list and search actions on asset, device and group models return the models resolved: the markers are replaced by the referential mappings, and the details and default values are merged over the current referential values. With rawModel: true they return the stored documents as is: sending one back leaves the model unchanged. Sending back a resolved model turns its referential metadata into inline metadata, so edit a model from its raw document.
Rules:
- using an unknown metadata is rejected (400)
- a model can still define metadata inline with
metadataMappings(legacy behaviour), but an inline metadata with the name of a referential entry and different mappings is rejected (409) - the mappings of a referential entry cannot be modified (400), they are already merged into the engines collections. Its
locales,editorHint,defaultValueandiconcan be updated, they apply to the models written afterwards - a new entry is rejected (409) if it conflicts with an inline metadata of the same name of a model, or with the actual mappings of an engine collection
- a model is rejected (409) if its metadata conflict with the other models or with the actual mappings of its engines collections. Mappings of deleted models or removed metadata stay in Elasticsearch, so they are also checked
- if Elasticsearch rejects the mappings of a new entry or of a model when the engines collections are updated (e.g. an unknown type), the request fails and the previous referential or model is restored, so the next updates are not affected
- writes of the referential and of asset, device and group models are serialized, so their conflicts checks always see each other
- an entry used by a model cannot be deleted. The mappings of a deleted entry stay in the engines collections
- with the
models.metadata.referentialOnlyoption, the models written through the API can only add metadata of the referential, new inline metadata are rejected (400) - an entry registered from code is flagged
managed: trueand cannot be modified or deleted through the API (400). An entry that is no longer registered from code loses the flag at the next startup. Registering from code an entry whose mappings differ from the stored ones, or a new entry conflicting with the existing mappings, prevents the application from starting
It is possible to fill the referential using either:
- the framework with the method
deviceManager.models.registerMetadata, the metadata are written at startup and overwrite the details of the ones with the same name. Registering the same name again is allowed only with an identical definition, so several modules can share a metadata - the API through the
device-manager/models:writeMetadataaction
Example: declaration of a metadata and a model using it
deviceManager.models.registerMetadata("operatingStatus", {
mappings: { type: "keyword" },
locales: {
en: { friendlyName: "Status", description: "Operating status" },
fr: { friendlyName: "Statut", description: "Statut de fonctionnement" },
},
editorHint: {
type: EditorHintEnum.OPTION_SELECTOR,
values: ["active", "inactive"],
},
defaultValue: "active",
icon: "power-off",
});
deviceManager.models.registerAsset(["commons"], "Pole", {
measures: [{ name: "position", type: "position" }],
metadataMappings: {
// Inline metadata, not in the referential
height: { type: "integer" },
operatingStatus: { referential: true },
},
metadataDetails: {
operatingStatus: { icon: "plug", locales: {} },
},
defaultMetadata: {
operatingStatus: "inactive",
},
});The API also allows to:
- get the referential
device-manager/models:getMetadataReferential - delete an unused metadata
device-manager/models:deleteMetadata
Sensor Model #
A sensor model contains the following information:
model: model namemeasures: received measurementsicon: (optional) Icon representing the device model. Free-form string, e.g. a FontAwesome icon name, a URL to a PNG/SVG image, or inline SVG markup — the format is up to the application. Not indexed for search.decoder: (optional) instance of a [Decoder] to normalize the datametadataMappings: (optional) metadata mappings (See Collection Mappings)defaultMetadata: (optional) default metadata valuesmetadataDetails: (optional) Translations, metadata group and editor hint.- Translations: you can use it to keep consistency on translations between your apps.
- Group: metadata can be displayed grouped, you need to define
metadataGroupsto use it. - Editor hint: it unlock functionalities depending on the metadata type you define.
metadataGroups: (optional) Map of group names to their translations. You can use it to group metadata.
It is possible to create new models on the Kuzzle IoT Platform using either:
- the API through the action
device-manager/models:writeDevice - the framework with the method
deviceManager.models.registerDevice
Example: declaration of a model via API
import {
ApiModelWriteDeviceRequest,
ApiModelWriteDeviceResult,
} from "kuzzle-device-manager-types";
(await sdk.query) < ApiModelWriteDeviceRequest,
ApiModelWriteDeviceResult >
{
controller: "device-manager/models",
action: "writeDevice",
body: {
model: "Enginko",
measures: [
{ name: "temperatureInternal", type: "temperature" },
{ name: "temperatureExternal", type: "temperature" },
],
},
};The API also allows to:
- list available devices models
device-manager/models:listDevices - get a device model
device-manager/models:getDevices - search device models
device-manager/models:searchDevices - delete a device model
device-manager/models:deleteDevice
Measure Model #
A measure model contains the following information:
model: model namemeasure: type of the measureicon: (optional) Icon representing the measure model. Free-form string, e.g. a FontAwesome icon name, a URL to a PNG/SVG image, or inline SVG markup — the format is up to the application. Not indexed for search.valuesMappings: measurements mappings (See Collection Mappings)valuesDetails: (optional) Metadata and translations of measurements. You can use it to keep consistency on translations between your appslocales: (optional) Translation for the measure model
It is possible to create new models on the Kuzzle IoT Platform using either:
- the API through the action
device-manager/models:writeMeasure - the framework with the method
deviceManager.models.registerMeasure
Example: declaration of a model via API
await sdk.query({
controller: "device-manager/models",
action: "writeMeasure",
body: {
type: "light",
valuesMappings: {
light: { type: "integer" },
},
valuesDetails: {
light: {
en: {
friendlyName: "Light intensity",
unit: "lux",
},
fr: {
friendlyName: "Intensité lumineuse",
unit: "lux",
},
},
},
locales: {
en: {
modelFriendlyName: "Light measurement",
modelDescription: "Light measurement",
},
fr: {
modelFriendlyName: "Mesure de lumière",
modelDescription: "Mesure de lumière",
},
}
},
});The API also allows to:
- list registered measures
device-manager/models:listMeasures - get a measure model
device-manager/models:getMeasure - search measure models
device-manager/models:searchMeasures - delete a measure model
device-manager/models:deleteMeasure
Asset Model #
Unlike sensors and metrics which are available for all tenant classes, asset models are specific to a particular tenant class.
An asset model contains the following information:
model: model nametenantClasses: tenant classes to which the model belongs (["commons"]for every class).measures: received measurementsicon: (optional) Icon representing the asset model. Free-form string, e.g. a FontAwesome icon name, a URL to a PNG/SVG image, or inline SVG markup — the format is up to the application. Not indexed for search.metadataMappings: (optional) metadata mappings (See Collection Mappings)defaultMetadata: (optional) default metadata values-metadataDetails: (optional) Translations, metadata group and editor hint.- Translations: you can use it to keep consistency on translations between your apps.
- Group: metadata can be displayed grouped, you need to define
metadataGroupsto use it. - Editor hint: it unlock functionalities depending on the metadata type you define.
metadataGroups: (optional) Map of group names to their translations. You can use it to group metadata.tooltipModels: (optional) Tooltip model list, each containing labels and tooltip content to be shown. You can use it to create templates that displays relevant information in dashboardslocales: (optional) Translation for asset model
It is possible to create new models on the Kuzzle IoT Platform using either:
- the API through the
device-manager/models:writeAssetaction - the framework with the method
deviceManager/models.registerAsset
Example: declaration of a model via API
import {
ApiModelWriteAssetRequest,
ApiModelWriteAssetResult,
} from "kuzzle-device-manager-types";
(await sdk.query) < ApiModelWriteAssetRequest,
ApiModelWriteAssetResult >
{
controller: "device-manager/models",
action: "writeAsset",
body: {
model: "Container",
tenantClasses: ["asset_tracking"],
measures: [
{ name: "temperatureInternal", type: "temperature" },
{ name: "temperatureExternal", type: "temperature" },
],
locales: {
en: {
friendlyName: "Container translated by model",
description: "Containerized container",
},
fr: {
friendlyName: "Conteneur traduit par modèle",
description: "Conteneur conteneurisé",
},
}
},
};INFO: If the locales has changed, use updateModelLocales to update all assets manually and make the search on assets up to date
The API also allows to:
- list available models
device-manager/models:listAssets - get a model
device-manager/models:getAssets - search asset models
device-manager/models:searchAssets - delete a asset model
device-manager/models:deleteAsset
Group Model #
A group model defines the structure and metadata for groups of devices or assets. Group models allow you to organize devices and assets into logical collections, apply permissions, and manage group-specific metadata.
A group model contains the following information:
model: Group model name.affinity: Specifies the types and models of elements accepted in the group.type: Array of accepted element types, possible values are"assets"and/or"devices".models: Object specifying which models are accepted for each type.assets: List of asset model names accepted in the group.devices: List of device model names accepted in the group.
strict: Boolean indicating whether the affinities are a strict restriction (true) or just a suggestion (false). Ifstrictistrue, only the specified types and models can be added to the group.
icon: (optional) Icon representing the group model. Free-form string, e.g. a FontAwesome icon name, a URL to a PNG/SVG image, or inline SVG markup — the format is up to the application. Not indexed for search.metadataMappings: (optional) Metadata mappings for group-specific information (see Collection Mappings).defaultMetadata: (optional) Default metadata values for the group.metadataDetails: (optional) Translations, metadata group, and editor hints for group metadata.- Translations: Ensures consistency of metadata translations across applications.
- Group: Allows metadata to be displayed in groups; define
metadataGroupsto use this feature. - Editor hint: Unlocks functionalities depending on the metadata type you define.
metadataGroups: (optional) Map of group names to their translations, used to group metadata fields.tooltipModels: (optional) Tooltip model list, each containing labels and tooltip content to be shown. You can use it to create templates that display relevant information in dashboards.locales: (optional) Translation for group model
You can create new group models on the Kuzzle IoT Platform using either:
- the API through the action
device-manager/models:writeGroup - the framework with the method
deviceManager.models.registerGroup
Example: declaration of a group model via API
await sdk.query({
controller: "device-manager/models",
action: "writeGroup",
body: {
model: "ParkingGroup",
affinity: {
type: ["assets", "devices"],
models: {
assets: ["ParkingSpot", "ParkingBarrier"],
devices: ["ParkingSensor"]
},
strict: true
},
metadataMappings: {
location: { type: "geo_point" }
},
defaultMetadata: {
location: {
lat: 41.12,
lon: -71.34
}
},
metadataDetails: {
location: {
group: "geolocation",
locales: {
en: {
friendlyName: "Parking location",
description: "The coordinates of the parking area"
},
fr: {
friendlyName: "Localisation du parking",
description: "Les coordonnées GPS du parking"
}
}
}
},
metadataGroups: {
geolocation: {
locales: {
en: {
groupFriendlyName: "Parking geolocation",
description: "The parking geolocation"
},
fr: {
groupFriendlyName: "Localisation du parking",
description: "La localisation du parking"
}
}
}
},
tooltipModels: {
defaultTooltipKey: {
tooltipLabel: "Default Tooltip Model",
content: [
{
category: "metadata",
label: {
locales: {
en: {
friendlyName: "Parking location",
description: ""
},
fr: {
friendlyName: "Localisation du parking",
description: ""
}
}
},
metadataPath: "location"
}
]
}
},
locales: {
en: {
friendlyName: "Parking group translated by model",
description: "Group of parking assets and devices"
},
fr: {
friendlyName: "Groupe de parking traduit par modèle",
description: "Groupe d'actifs et d'appareils de parking"
}
}
}
});The API also allows you to:
- list available group models
device-manager/models:listGroups - get a group model
device-manager/models:getGroup - search group models
device-manager/models:searchGroups - delete a group model
device-manager/models:deleteGroup