Asset Administration Shell Tutorial with Eclipse BaSyx

Asset Administration Shell Tutorial with Eclipse BaSyx

Asset Administration Shell Tutorial: Build a Digital Nameplate with Eclipse BaSyx (2026)

This Asset Administration Shell tutorial takes you from an empty terminal to a queryable, standards-compliant digital twin in about an hour. The Asset Administration Shell (AAS) is the metamodel that the Industrial Digital Twin Association (IDTA) and Plattform Industrie 4.0 chose as the lingua franca for industrial interoperability, and Eclipse BaSyx is the most widely used open-source runtime that implements it. We will use BaSyx v2, deploy it with Docker Compose, model a real IDTA submodel template (the Digital Nameplate), push it through the REST API, query it back, and then connect it to a live data source so the shell stops being a static document and starts behaving like a twin. Everything here is runnable, and where an exact endpoint shape depends on your deployment, the post says so explicitly. What this covers: the AAS metamodel, the BaSyx component architecture, a full hands-on build, live-data wiring, and the gotchas that bite at scale.

What is the Asset Administration Shell and why does it matter?

The Asset Administration Shell is a standardized digital representation of a physical or logical asset, defined by the IDTA metamodel and endorsed by Plattform Industrie 4.0 as the interoperability backbone for Industry 4.0. It gives every machine, component, or product a self-describing, machine-readable identity that any vendor’s software can read the same way — turning point-to-point integrations into a shared data contract.

For thirty years, factory integration meant bespoke connectors — Vendor A’s MES talking to Vendor B’s robot through a custom adapter that one engineer understood and nobody dared touch, with every new asset adding another N-squared edge to the integration graph. The AAS attacks that problem the way the web attacked document exchange: agree on a metamodel, serializations, and an API, and let interoperability fall out of the standard rather than out of heroics.

The AAS is not a product you buy. It is a specification — Details of the Asset Administration Shell, Part 1 (metamodel) and Part 2 (API) maintained by the IDTA — that runtimes like Eclipse BaSyx, FA³ST, and AASX Server implement. Once your asset speaks AAS, any AAS-aware tool can discover it, read its submodels, and act on its data without knowing anything about the vendor that made it.

The metamodel: Shells, Submodels, SubmodelElements, Concept Descriptions

Four building blocks carry almost all the weight. Understanding them is the difference between cargo-culting JSON and actually modelling an asset.

AAS metamodel showing Shell, Asset Information, Submodels, SubmodelElements and Concept Descriptions
Figure 1: The AAS metamodel — a Shell carries AssetInformation and references one or more Submodels, each of which holds SubmodelElements whose meaning is anchored by Concept Descriptions via semanticId.

  • AssetAdministrationShell — the top-level wrapper. It has a globally unique id (an IRI or IRDI), and an assetInformation block that links to the real-world asset via a globalAssetId. The shell itself holds almost no data; it is a registry of references to submodels.
  • Submodel — a coherent bundle of information about one aspect of the asset: its nameplate, its technical data, its current operational status, its maintenance history. Each submodel has its own id and can be reused across many shells. Submodels are where the data actually lives.
  • SubmodelElement — the leaves and branches inside a submodel. The common types are Property (a single typed value), MultiLanguageProperty (a value in several languages), SubmodelElementCollection (a named group of elements), File, Range, ReferenceElement, and Operation. A submodel is a tree of these.
  • ConceptDescription — the semantic anchor. A SubmodelElement carries a semanticId pointing at a ConceptDescription (often an IEC 61360 entry or an eCl@ss IRDI). Two vendors who tag a field with the same semanticId for “serial number” mean the same thing, regardless of what they named the element — that is what makes the data interoperable.

Types vs instances

The spec distinguishes asset types from asset instances via assetInformation.assetKind (Type or Instance). A type shell describes a product line — “ACME Drive 5000” with the technical envelope every unit shares — while an instance shell describes one physical serial-numbered unit and typically references the type. In practice you model the type once in engineering and stamp out instances as you commission hardware.

AASX package format and serializations

An AAS can be serialized several ways, and you will meet all of them:

  • JSON — the format the API speaks and the one this tutorial uses throughout.
  • XML — the original serialization, still common in toolchains and import/export.
  • RDF — for semantic-web and knowledge-graph integration.
  • AASX — the packaging format. An .aasx file is an Open Packaging Conventions (OPC) ZIP container holding the shell and submodels (as JSON or XML) plus supplementary files like CAD models, certificates, and images, all referenced by relationship. AASX is how you ship a complete, file-based twin between organizations.

If you are new to where the AAS fits in the wider stack, our IoT, digital twin, and PLM complete overview places it in context against PLM systems and twin platforms.

Eclipse BaSyx v2 overview

Eclipse BaSyx is an Eclipse Foundation open-source project that provides production-grade implementations of the AAS specification. BaSyx v2 is a deliberate rewrite around small, independently deployable components, each exposing the IDTA Part 2 HTTP/REST API. You run only the pieces you need and scale them separately.

BaSyx v2 components: AAS Environment, AAS Repository, Submodel Repository, Registry, Discovery and Web UI
Figure 2: BaSyx v2 component architecture — repositories store shells and submodels, the registry and discovery services make them findable, and the Web UI and client apps consume the same REST API.

The components

  • AAS Environment — a convenience component bundling an AAS Repository and a Submodel Repository, with the ability to bootstrap from .aasx / JSON / XML files at startup. Great for tutorials and small deployments.
  • AAS Repository — stores and serves Asset Administration Shells over /shells. CRUD on shells, plus management of each shell’s submodel references.
  • Submodel Repository — stores and serves Submodels over /submodels. This is where the bulk of your data sits and where reads concentrate.
  • AAS Registry and Submodel Registry — hold descriptors that map a shell or submodel id to the endpoint(s) where it actually lives. In a federated landscape with many repositories, the registry is your phone book.
  • Discovery Service — answers the question “which shells correspond to this asset?” by mapping specificAssetIds (like a serial number or an RFID) to shell ids. Registry maps id-to-endpoint; discovery maps asset-attribute-to-id.
  • AAS Web UI — a browser front end that talks to the repositories and registry so humans can browse shells and submodels.

The split between registry and discovery confuses everyone at first. The mental model: discovery finds the shell when you only know something about the physical asset; registry finds the data endpoint once you know the shell or submodel id.

Docker Compose deployment

Every BaSyx v2 component ships as a Docker image under the eclipsebasyx/ namespace, configured by Spring-style properties via environment variables or a mounted application.properties. Composing them is the standard deployment path, which is exactly what we do next.

Step-by-step: build a Digital Nameplate with BaSyx

We will stand up the stack, model the IDTA Digital Nameplate submodel template, push everything through the REST API, and read it back. The Digital Nameplate is a standardized IDTA submodel template — the digital equivalent of the metal plate riveted to a machine, carrying manufacturer, designation, serial number, year of construction, and contact data.

Step 1 — Spin up BaSyx with Docker Compose

Create a working directory and a docker-compose.yml. The image tags below pin to the v2 line; check the BaSyx documentation for the latest exact patch tags before a production deploy.

# docker-compose.yml
services:
  aas-environment:
    image: eclipsebasyx/aas-environment:2.0.0
    container_name: aas-environment
    ports:
      - "8081:8081"
    environment:
      BASYX_BACKEND: InMemory
      # Tell the environment its externally reachable URL so submodel
      # references resolve correctly from clients and the UI.
      BASYX_EXTERNALURL: http://localhost:8081
      BASYX_CORS_ALLOWED-ORIGINS: "*"
      BASYX_CORS_ALLOWED-METHODS: "GET,POST,PUT,DELETE,PATCH,OPTIONS,HEAD"

  aas-registry:
    image: eclipsebasyx/aas-registry-log-mem:2.0.0
    container_name: aas-registry
    ports:
      - "8082:8080"
    environment:
      BASYX_CORS_ALLOWED-ORIGINS: "*"
      BASYX_CORS_ALLOWED-METHODS: "GET,POST,PUT,DELETE,PATCH,OPTIONS,HEAD"

  sm-registry:
    image: eclipsebasyx/submodel-registry-log-mem:2.0.0
    container_name: sm-registry
    ports:
      - "8083:8080"
    environment:
      BASYX_CORS_ALLOWED-ORIGINS: "*"
      BASYX_CORS_ALLOWED-METHODS: "GET,POST,PUT,DELETE,PATCH,OPTIONS,HEAD"

  aas-discovery:
    image: eclipsebasyx/aas-discovery:2.0.0
    container_name: aas-discovery
    ports:
      - "8084:8081"
    environment:
      BASYX_CORS_ALLOWED-ORIGINS: "*"

  aas-ui:
    image: eclipsebasyx/aas-gui:v2
    container_name: aas-ui
    ports:
      - "3000:3000"
    environment:
      AAS_DISCOVERY_PATH: http://localhost:8084
      AAS_REGISTRY_PATH: http://localhost:8082
      SUBMODEL_REGISTRY_PATH: http://localhost:8083
      AAS_REPO_PATH: http://localhost:8081/shells
      SUBMODEL_REPO_PATH: http://localhost:8081/submodels

Note on exact image tags and property keys. BaSyx ships frequent releases and the property names occasionally shift between minor versions. The keys above (BASYX_BACKEND, BASYX_EXTERNALURL, the registry image names) match the v2 documentation at time of writing; treat them as the shape to confirm against the wiki for your pinned version rather than as eternal truth. The InMemory backend is for development — production uses MongoDB.

Bring it up and verify:

docker compose up -d
docker compose ps

# The AAS Environment serves the repositories on 8081.
# A healthy repo returns an empty paged result, not a 404.
curl -s http://localhost:8081/shells | python3 -m json.tool

A fresh repository returns a paged envelope like {"result": [], "paging_metadata": {}}. Open the Web UI at http://localhost:3000 and you should see an empty shell list. The stack is live.

Step 2 — Understand the ID encoding rule

This trips up every newcomer. AAS identifiers are full IRIs (for example https://acme.com/aas/drive5000/sn/00042), and you cannot put a slash-laden IRI directly into a URL path. The IDTA Part 2 API mandates that any identifier used as a path parameter be Base64URL-encoded (RFC 4648 URL-safe alphabet, no padding).

So a request for shell https://acme.com/aas/drive5000/sn/00042 becomes GET /shells/{base64url-of-that-iri}. Here is the helper we will reuse:

import base64

def b64url(identifier: str) -> str:
    """Base64URL-encode an AAS/Submodel identifier for use as a path param."""
    raw = base64.urlsafe_b64encode(identifier.encode("utf-8"))
    return raw.decode("ascii").rstrip("=")  # BaSyx accepts unpadded URL-safe

Step 3 — Model the shell and the Digital Nameplate submodel

Let’s look at the structure we are building before the JSON.

Digital Nameplate submodel structure with manufacturer, designation, serial number and contact collection
Figure 3: The Digital Nameplate submodel — top-level properties for identity plus nested SubmodelElementCollections for contact information and conformity markings.

The cleanest way to author AAS data in Python is the official basyx-python-sdk, which gives you typed objects and validated serialization. Install it:

pip install basyx-python-sdk requests

Now build a Type shell, an instance shell, and a Digital Nameplate submodel. The semanticId values shown are the IDTA Digital Nameplate template identifiers; verify the exact strings against the current template version, as IDTA increments them between releases.

# build_nameplate.py
from basyx.aas import model
from basyx.aas.adapter.json import json_serialization
import json

# --- semanticIds from the IDTA Digital Nameplate submodel template ---
# Confirm exact IRIs against the template version you target.
SEM_NAMEPLATE = "https://admin-shell.io/zvei/nameplate/2/0/Nameplate"
SEM_MANUFACTURER = "0173-1#02-AAO677#002"          # ManufacturerName (eCl@ss IRDI)
SEM_DESIGNATION  = "0173-1#02-AAW338#001"          # ManufacturerProductDesignation
SEM_SERIAL       = "0173-1#02-AAM556#002"          # SerialNumber
SEM_YEAR         = "0173-1#02-AAP906#001"          # YearOfConstruction

def prop(id_short, value, value_type=model.datatypes.String, semantic=None):
    return model.Property(
        id_short=id_short,
        value_type=value_type,
        value=value,
        semantic_id=(model.ExternalReference(
            (model.Key(model.KeyTypes.GLOBAL_REFERENCE, semantic),)
        ) if semantic else None),
    )

def mlp(id_short, en_value, semantic=None):
    return model.MultiLanguageProperty(
        id_short=id_short,
        value=model.MultiLanguageTextType({"en": en_value}),
        semantic_id=(model.ExternalReference(
            (model.Key(model.KeyTypes.GLOBAL_REFERENCE, semantic),)
        ) if semantic else None),
    )

# --- contact information collection ---
contact = model.SubmodelElementCollection(id_short="ContactInformation")
contact.value.add(prop("Street", "Industriestrasse 1"))
contact.value.add(prop("CityTown", "Stuttgart"))
contact.value.add(prop("NationalCode", "DE"))

# --- the Digital Nameplate submodel ---
nameplate = model.Submodel(
    id_="https://acme.com/sm/nameplate/drive5000/sn/00042",
    id_short="Nameplate",
    semantic_id=model.ExternalReference(
        (model.Key(model.KeyTypes.GLOBAL_REFERENCE, SEM_NAMEPLATE),)
    ),
)
nameplate.submodel_element.add(mlp("ManufacturerName", "ACME Drives", SEM_MANUFACTURER))
nameplate.submodel_element.add(mlp("ManufacturerProductDesignation", "Drive 5000", SEM_DESIGNATION))
nameplate.submodel_element.add(prop("SerialNumber", "SN-00042", semantic=SEM_SERIAL))
nameplate.submodel_element.add(prop("YearOfConstruction", "2026", semantic=SEM_YEAR))
nameplate.submodel_element.add(contact)

# --- the instance shell that references the submodel ---
shell = model.AssetAdministrationShell(
    id_="https://acme.com/aas/drive5000/sn/00042",
    id_short="Drive5000_SN00042",
    asset_information=model.AssetInformation(
        asset_kind=model.AssetKind.INSTANCE,
        global_asset_id="https://acme.com/asset/drive5000/sn/00042",
    ),
    submodel={model.ModelReference.from_referable(nameplate)},
)

# --- serialize to the JSON the BaSyx REST API expects ---
with open("shell.json", "w") as f:
    json.dump(json_serialization.object_store_to_json(
        model.DictObjectStore([shell])), f, indent=2)

with open("submodel.json", "w") as f:
    json.dump(json_serialization.object_store_to_json(
        model.DictObjectStore([nameplate])), f, indent=2)

print("Wrote shell.json and submodel.json")

The SDK’s serializer wraps objects in an environment-style document. If you prefer to POST a single bare object, the SDK also exposes per-object serialization helpers; the snippet above is intentionally explicit so you can inspect the JSON. Adjust the dump to emit a single shell/submodel object if your SDK version names the helper differently — the shape of the JSON is what the API contracts on.

Step 4 — Push it via the REST API

The IDTA Part 2 API is consistent across components: POST a collection to create, GET an id to read, PUT to replace, PATCH to update, DELETE to remove. Submodels live in the Submodel Repository; the shell references them. Below is the create-then-query flow.

Sequence diagram of creating a shell and submodel then querying them through the BaSyx REST API
Figure 4: REST flow — POST the shell and submodel to their repositories, attach the submodel reference to the shell, register descriptors, then GET the data back (full object and value-only).

# push.py  (pseudocode-adjacent: assumes shell.json / submodel.json from Step 3)
import requests, json
from build_nameplate import b64url  # reuse the encoder

ENV = "http://localhost:8081"
REG = "http://localhost:8082"

shell = json.load(open("shell.json"))      # extract the single shell object
sm    = json.load(open("submodel.json"))   # extract the single submodel object
# If your serializer wrapped them in {"assetAdministrationShells":[...]}, unwrap here:
shell_obj = shell["assetAdministrationShells"][0] if "assetAdministrationShells" in shell else shell
sm_obj    = sm["submodels"][0] if "submodels" in sm else sm

H = {"Content-Type": "application/json"}

# 1) Create the submodel in the Submodel Repository
r = requests.post(f"{ENV}/submodels", headers=H, data=json.dumps(sm_obj))
print("POST /submodels ->", r.status_code)

# 2) Create the shell in the AAS Repository
r = requests.post(f"{ENV}/shells", headers=H, data=json.dumps(shell_obj))
print("POST /shells ->", r.status_code)

# 3) (Optional) register descriptors so the shell is discoverable in a federation
descriptor = {
    "id": shell_obj["id"],
    "idShort": shell_obj.get("idShort"),
    "endpoints": [{
        "interface": "AAS-3.0",
        "protocolInformation": {
            "href": f"{ENV}/shells/{b64url(shell_obj['id'])}"
        }
    }]
}
r = requests.post(f"{REG}/shell-descriptors", headers=H, data=json.dumps(descriptor))
print("POST /shell-descriptors ->", r.status_code)

Expect 201 Created from the repositories. If the submodel reference inside the shell already points at the submodel id (it does, from Step 3), the shell knows about it the moment both exist. Some workflows instead attach the reference after creation via the shell’s submodel-reference endpoint (POST /shells/{id64}/submodel-refs); both approaches are valid.

Step 5 — Query it back

# Base64URL of the submodel id (use the python helper or a one-liner)
SMID=$(python3 -c "import base64;print(base64.urlsafe_b64encode(b'https://acme.com/sm/nameplate/drive5000/sn/00042').decode().rstrip('='))")

# Full submodel
curl -s http://localhost:8081/submodels/$SMID | python3 -m json.tool

# Value-only view: strips metadata, returns just id_short -> value pairs
curl -s http://localhost:8081/submodels/$SMID/\$value | python3 -m json.tool

# A single element by its idShortPath
curl -s http://localhost:8081/submodels/$SMID/submodel-elements/SerialNumber | python3 -m json.tool

The $value serialization is the one you want for dashboards: it returns just the data, no metadata. Nested elements are addressed by dotted idShortPath — for example ContactInformation.City reaches the city inside the collection. Open the Web UI again and your asset now appears with a browsable Nameplate. You have a working, standards-compliant AAS.

Connecting an AAS to a live digital twin

A Nameplate is static, but an AAS earns its keep when a submodel reflects the real-time state of the asset. The pattern is to add an operational data submodel and keep its properties in sync with the shop floor through a bridge.

Live data flow from PLC and OPC UA through an edge bridge and MQTT into the BaSyx submodel repository and dashboards
Figure 5: Connecting the AAS to live data — a bridge reads OPC UA / PLC values, optionally routes them through an MQTT unified namespace, and PATCHes the operational submodel that dashboards and MES read.

There are two common architectures, and they are not mutually exclusive:

  1. Push into the repository. A bridge reads the source (OPC UA, Modbus, an MQTT topic) and PATCHes the submodel element value on a cadence. Simple, and every AAS client sees current data with no extra plumbing. The trade-off is write load on the repository and a polling interval that bounds freshness.
  2. AAS as a façade over a connected source. BaSyx supports backends where a submodel element delegates its value to an external endpoint, so a read of the AAS proxies through to the live source. Lower write load and always-fresh, at the cost of read latency and a dependency on the source being up.

The push pattern is the easiest to demonstrate. The bridge below reads from an MQTT broker — the natural integration point if you run a unified namespace — and patches a Temperature property.

# bridge_mqtt_to_aas.py
import base64, json, requests
import paho.mqtt.client as mqtt

ENV = "http://localhost:8081"
OPS_SM_ID = "https://acme.com/sm/operational/drive5000/sn/00042"
SMID64 = base64.urlsafe_b64encode(OPS_SM_ID.encode()).decode().rstrip("=")

def patch_property(id_short_path: str, value):
    """PATCH a single submodel element's value via the value-only endpoint."""
    url = f"{ENV}/submodels/{SMID64}/submodel-elements/{id_short_path}/$value"
    r = requests.patch(url, headers={"Content-Type": "application/json"},
                       data=json.dumps(value))
    if r.status_code not in (200, 204):
        print("PATCH failed", r.status_code, r.text)

def on_message(client, userdata, msg):
    payload = json.loads(msg.payload.decode())
    # e.g. topic acme/drive5000/sn00042/temp  ->  {"value": 47.2}
    patch_property("Temperature", payload["value"])
    print("synced Temperature =", payload["value"])

client = mqtt.Client()
client.on_message = on_message
client.connect("localhost", 1883, 60)
client.subscribe("acme/drive5000/sn00042/#")
client.loop_forever()

Before running it, create the operational submodel once (same pattern as the Nameplate, with a Temperature Property of value_type=Double and an appropriate semanticId) and attach its reference to the shell. From then on, every MQTT message updates the twin, and any AAS-aware consumer — a dashboard, an MES, another plant — reads current data through the standard API. That is the whole promise of the AAS: one contract, many consumers.

For production you would add: a debounce so you do not hammer the repository on chatty signals, a timestamp element next to each value, a heartbeat/quality flag, and back-pressure handling if the broker outruns the repository.

When you wire OPC UA directly instead of MQTT, the same bridge pattern applies: replace the paho subscription with an asyncua subscription handler, map each monitored node to an idShortPath, and PATCH on the OPC UA data-change callback. The AAS does not care where the value came from; it only cares that the contract — idShort, value_type, and semanticId — stays stable.

Trade-offs and gotchas

The happy path is short. The interesting decisions show up at scale.

  • Registry vs discovery, again. In a single-repository demo you can skip both — the repository is the source of truth and clients hit it directly. The moment you have multiple repositories, plants, or vendors, you need the registry (id-to-endpoint) so clients can resolve where a shell lives, and discovery (asset-attribute-to-id) so a scanner that read a serial number can find the shell at all. Decide your federation topology before you have ten thousand shells, not after.
  • Security and RBAC. The default tutorial stack is wide open with permissive CORS and no auth — fine on a laptop, unacceptable on a network. BaSyx v2 integrates with an OAuth2 / OIDC provider (Keycloak is the common choice) for token-based access and supports fine-grained, rule-based authorization down to the submodel-element level. Budget real time for this; “who may read the Nameplate but not the maintenance log” is a genuine modelling exercise.
  • Versioning. Two axes move independently: the AAS metamodel/API version (v3 of the metamodel underlies BaSyx v2) and your submodel template versions (the IDTA increments Digital Nameplate, Technical Data, and friends). Pin both. When IDTA ships a new Nameplate template, decide deliberately whether to migrate existing instances or run both versions side by side keyed on semanticId.
  • Performance at scale. InMemory is for demos and loses everything on restart. Use the MongoDB backend for persistence. Reads concentrate on the Submodel Repository, so that is what you scale horizontally and cache; the $value endpoint is dramatically cheaper than full serialization for dashboard polling. For high-write live data, prefer the delegation/connected backend or batch your PATCHes rather than writing per-sample.
  • ID hygiene. Identifiers are forever. Use a stable, owned IRI scheme (https://yourcompany.com/...) and never reuse an id for a different asset. Base64URL-encode consistently — an unencoded slash in a path is the single most common cause of a mysterious 404.
  • Eventing and change notification. Polling a repository for changes does not scale. Fan out from one bridge to one broker to many subscribers (the UNS pattern) rather than making ten dashboards poll the same submodel every second.
  • AASX round-tripping. Authoring in the AASX Package Explorer and importing the .aasx into BaSyx is a great workflow, but verify that what you export from BaSyx re-imports cleanly — supplementary files and concept descriptions are the usual casualties. Treat the round trip as a test, not an assumption.

Practical recommendations and checklist

A pragmatic path from this tutorial to something you would run:

  • [ ] Model from templates, not from scratch. Start with IDTA submodel templates (Digital Nameplate, Technical Data, Handover Documentation) so your data is interoperable on day one.
  • [ ] Adopt an IRI scheme for shell, submodel, and asset ids before you create the first real shell. Write it down.
  • [ ] Always tag elements with semanticId. Untagged data is just JSON; semantic ids are what make it an AAS.
  • [ ] Switch the backend to MongoDB the moment data must survive a restart.
  • [ ] Stand up registry + discovery as soon as a second repository or plant appears.
  • [ ] Put Keycloak (or your OIDC provider) in front before anything leaves localhost.
  • [ ] Separate static from operational submodels so live-data write load never touches your nameplate reads.
  • [ ] Pin metamodel and template versions and treat template upgrades as planned migrations.
  • [ ] Use $value for polling, full serialization only when you need metadata.
  • [ ] Ship .aasx packages for cross-organization handover; ship JSON over REST for runtime integration.

FAQ

What is the difference between the Asset Administration Shell and a digital twin?

A digital twin is the broad concept of a synchronized virtual representation of a physical asset. The AAS is a standardized way to structure and expose that representation — a metamodel and API. You can build a digital twin without the AAS, but using the AAS makes your twin interoperable with any other AAS-aware system, which is the entire point for multi-vendor Industry 4.0 environments.

Is Eclipse BaSyx free for commercial use?

Yes. BaSyx is an Eclipse Foundation project released under the Eclipse Public License (EPL), which permits commercial use. You still own the operational concerns — deployment, security, persistence, support — and several vendors offer commercial support and managed BaSyx-based platforms on top.

Do I have to use the BaSyx Python SDK to create an AAS?

No. The SDK is a convenience that gives you typed objects and validated serialization, but the API contracts on JSON. You can author the JSON by hand, generate it from a modelling tool like the AASX Package Explorer, or use SDKs in Java, .NET, or other languages. The REST endpoints behave the same regardless of how the payload was produced.

What is the Digital Nameplate submodel and why use it?

The Digital Nameplate is a standardized IDTA submodel template that digitizes the physical nameplate on a machine — manufacturer, product designation, serial number, year of construction, contact data, and conformity markings (CE, etc.). Using the standard template instead of inventing your own fields means any AAS-aware tool, customs system, or asset register reads your nameplate data without custom mapping, and it supports regulatory and machine-readability initiatives.

Why are AAS identifiers Base64URL-encoded in the URL?

Because AAS identifiers are full IRIs that contain characters — slashes especially — that have structural meaning in a URL path. Base64URL-encoding the identifier turns it into a single safe path segment, so GET /submodels/{base64url-id} is unambiguous. It is mandated by the IDTA Part 2 API, and forgetting to encode is the most common source of 404s for newcomers.

Can the AAS handle real-time operational data, or is it only for static info?

It handles both. Static descriptive data (nameplate, technical specs) lives in one submodel; operational data (temperature, status, counters) lives in another that you keep in sync with the shop floor — either by pushing updates into the repository or by configuring a connected backend that proxies reads to a live source. Keeping the two separate is the recommended pattern so live-data writes do not interfere with descriptive reads.

Further reading

  • Facebook
  • Twitter
  • LinkedIn
  • More Networks
Copy link
Powered by Social Snap