Use Submodel Descriptor Templates

Submodel Descriptor Templates are an abstraction over Submodel Descriptors sharing common features among multiple Asset Administration Shells.

Purpose

There are two main advantages in using Submodel Descriptor Templates.

  1. Scalability: field observations show that many Shells will have near-identical Submodels in common. Reducing those Submodels to their common features implies smaller network and persistence loads for the Asset Administration Shell Registry.

  2. Maintainability: individuals in charge of creating and maintaining Submodels can leverage the Submodel Templates feature to drastically reduce the number of Submodels in their care.

Submodel Descriptor Template lifecycle

A Submodel Descriptor Template is an abstraction over a number of traits common to multiple Submodel Descriptors. The variable part of a Submodel Descriptor Template is defined in its endpoints, in the form of one or multiple placeholders in the endpoint’s href.

  • Submodel Descriptor Templates are created in association with a Shell Group.

  • Any Shell in that group can leverage all its associated Submodel Descriptor Templates, thus reducing the required number of concrete Submodel Descriptors for all Shells.

  • When Shell data is requested from the Asset Administration Shell Registry, all Submodel Descriptor Templates within the given Shell’s group(s) are instantiated and featured with the Shell, just as if they were concrete Submodel Descriptors.

  • Instantiated Submodel Descriptors are runtime-only data: they display as concrete Submodel Descriptors but are never persisted.

  • The endpoints of instantiated Submodel Descriptors may have placeholders that are resolved at runtime, when fetching the associated Shell.

  • Submodel Descriptor Templates can be suppressed if they collide with any concrete Submodel Descriptor the given Shell features. A concrete Submodel Descriptor will always be favored.

  • A collision between a concrete Submodel Descriptor and a Submodel Descriptor instantiated from a Template exists if both have the same ID.

  • Submodel Descriptor Templates can be modified or removed from their Shell Group, with immediate impact on the associated Shell’s Submodel Descriptors.

  • Similarly, removing a Shell from a group implies the Shell will immediately stop featuring Submodel Descriptors instantiated through Submodel Descriptor Templates.

URL Placeholders and syntax

The variable data in a template is defined in the href of its endpoints, in the form of placeholders. Endpoint placeholders can leverage runtime data coming from the Asset Administration Shell. The table below illustrates the capabilities available for URL placeholders.

Syntax Description Path variable support Query parameter support Multiple instances support May fail to resolve at runtime Example

{shellId}

Resolves to the Shell ID

Yes

Yes

Yes

No

https://mydomain.com/{shellId}/?id={shellId}

{tenantId}

Resolves to the Shell’s owning tenant ID

Yes

Yes

Yes

No

https://mydomain.com/{tenantId}/?id={tenantId}

{specificAssetId=(<name>)}

Resolves to a name-value pair of a matching specificAssetId

No

Yes

Yes

Yes

https://mydomain.com/?{specificAssetId=(<name>)}

{assetKind}

Resolves to the Shell’s assetKind

Yes

Yes

Yes

Yes

https://mydomain.com/{assetKind}/?assetKind={assetKind}

Submodel Descriptor IDs and suppression

Regular Submodel Descriptors require a unique ID. To ensure uniqueness for instantiated Submodel Descriptor Templates, these IDs are generated automatically following this pattern:

<shellId>_<submodelDescriptorTemplateId>

This is a fixed pattern and currently there is no way to influence the generation of this ID, besides changing the shellId.

However it is possible to cause a collision between a concrete Submodel Descriptor and an instantiated template, when the concrete Submodel has the same Submodel ID assigned. Concrete Submodels are always prefered over templated ones. Instantiated Submodel Descriptors will be omitted in such cases.

Validation

  • The endpoint placeholders are validated syntactically upon creating or modifying a template.

  • The URI syntax of the endpoint is also validated for convenience.

  • The validation of the URI syntax temporarily ignores the curly brackets surrounding path variable placeholders.

  • This static validation does not attempt to resolve any data, therefore referencing a SpecificAssetId that is not present in a Shell featuring the given template will not result in an invalid template.

Resolution

  • Both {shellId} and {tenantId} placeholders will always resolve to their respective values from the Shell.

  • The {specificAssetId=(<name>)} may not successfully resolve if the Shell does not have a matching SpecificAssetId.

  • {assetKind} may not successfully resolve if the Shell does not have this field.

  • In those cases, the placeholder will not be substituted, thus resulting in an invalid URL at runtime for the endpoint of the given Submodel, which will be displayed as-is instead of generating an error response.

Examples

This section illustrates a series of examples on how a template’s endpoint will either:

  • Fail to validate (preventing the end user from creating or modifying the Submodel Descriptor Template), or

  • Successfully resolve at runtime, or

  • Leniently fail to fully resolve at runtime (only applicable to SpecificAssetIds).

In this example, the Shell against which the Template Submodel Descriptors are resolved has the following properties:

Property

Value

Shell ID

shell123

Owning tenant ID

12345678-9012-3456-7890-123456789012

SpecificAssetId name name1

value1

SpecificAssetId name name2

value2

Asset Kind

kind1

The table below displays a non-exhaustive list of examples:

Example

Validation

Resolution

Explanation

http://mydomain.com/{tenantId}/{shellId}?{specificAssetId=(<name1>)}

Pass

http://mydomain.com/12345678-9012-3456-7890-123456789012/shell123?name1=value1

Tenant and Shell IDs are resolved as path variables. SpecificAssetId name1 exists in the Shell and therefore can be resolved

http://mydomain.com/{assetKind}/

Pass

http://mydomain.com/assetKind

Asset Kind is resolved as path variable

http://mydomain.com/{tenantId}/?shellId={shellId}&assetKind={assetKind}

Pass

http://mydomain.com/12345678-9012-3456-7890-123456789012/?shellId=shell123&assetKind=kind1

Tenant ID is resolved as a path variable. Shell ID and Asset Kind are resolved as query parameters with the given keys

http://mydomain.com/{tenantId}/?{specificAssetId=(<name1>)}&{specificAssetId=(<name2>)}

Pass

http://mydomain.com/12345678-9012-3456-7890-123456789012/?name1=value1&name2=value2

Multiple SpecificAssetIds are supported. However, they require query parameter separators between one another

http://mydomain.com/{tenantId}/?{specificAssetId=(<name1>)}{specificAssetId=(<name2>)}

Pass

http://mydomain.com/12345678-9012-3456-7890-123456789012/?name1=value1name2=value2

The only difference with the previous example is that the SpecificAssetIds have not been separated with &. As a result, the endpoint is valid but it will resolve into an invalid URL at runtime

http://mydomain.com/{specificAssetId=(<name1>)}/?shellId={shellId}

Fail

n/a

SpecificAssetId placeholders can only be used as query parameters

http://mydomain.com/{tenant Id}/

Fail

n/a

Malformed tenant ID placeholder

http://mydomain.com/{shellId/

Fail

n/a

Malformed Shell ID placeholder

http://mydomain.com/{tenantId}/?{specificAssetId=(<notExisting>)}

Pass

http://mydomain.com/12345678-9012-3456-7890-123456789012/?{specificAssetId=(<notExisting>)}

The endpoint is valid, but the runtime cannot resolve notExisting for the given Shell, so the whole sequence is not resolved

http://mydomain.com/{specificAssetId=name1}

Fail

n/a

Incorrect SpecificAssetId placeholder syntax

Managing Submodel Descriptor Templates

Submodel Templates and Submodel endpoint templates have their own REST resource that offers the corresponding CRUD operations to create, retrieve, replace, patch or delete a Submodel Template:

Example for a Submodel Descriptor Template

{
    "endpointTemplates": [
        {
            "interfaceNameTemplate": "testInterface",
            "protocolInformationTemplate": {
                "hrefTemplate": "https://testTemplate.com/{tenantId}/{shellId}/{assetKind}?{specificAssetId=(<name1>)}",
                "endpointTemplateProtocol":"http",
                "endpointTemplateProtocolVersions": [
                    "1.0.0"
                ],
                "subprotocolTemplate": "testSubprotocolTemplate",
                "subprotocolBodyTemplate": "testSubprotocolBodyTemplate",
                "subprotocolBodyEncodingTemplate": "testSubprotocolBodyEncodingTemplate",
                "securityAttributeTemplates": [
                    {
                        "type": "RFC_TLSA",
                        "key": "testSecurityAttributeKey",
                        "value": "testSecurityAttributeValue"
                    }
                ]
            }
        }
    ],
    "idShort": "f2f78bc0-4367-4ab5-a8ee-cbae64820bae",
    "semanticId": {
        "type": "ExternalReference",
        "keys": [
            {
                "type": "Property",
                "value": "testProperty"
            }
        ]
    },
    "supplementalSemanticId": [
        {
            "type": "ExternalReference",
            "keys": [
                {
                    "type": "Property",
                    "value": "testPropertySupplementalSemanticId"
                }
            ]
        }
    ],
    "groups": [1],
    "description": [
        {
            "language": "en",
            "text": "Example description"
        }
    ],
    "displayName": [
        {
            "language": "en",
            "text": "Example displayName"
        }
    ]
}