High-level HTTP client for the AAS Part 2 API v3.x
Project description
basyx-client
Python CLI & SDK for the AAS Part 2 API v3.x
A high-level, BaSyx-model-native HTTP client with first-class CLI support.
Why basyx-client?
Working with the AAS Part 2 API directly is painful:
- Identifier encoding - Every identifier must be base64url encoded (without padding!)
- idShortPath encoding - Brackets in paths like
Sensors[0]must be URL-encoded as%5B0%5D - No typed responses - You get raw dictionaries, not BaSyx model objects
- Manual error handling - Status codes must be checked and mapped to meaningful errors
basyx-client eliminates all of this friction:
from basyx_client import AASClient
# All encoding happens automatically
with AASClient("http://localhost:8081") as client:
# Get an AAS - returns basyx.aas.model.AssetAdministrationShell, not dict
aas = client.shells.get("https://acme.org/ids/aas/55")
print(aas.id_short) # Type-safe attribute access
# Access submodel elements with array indices - brackets encoded automatically
temp = client.submodels.elements.get_value(
"https://acme.org/ids/sm/sensors",
"Measurements[0].Temperature" # [0] becomes %5B0%5D automatically
)
Installation
pip install basyx-client
Docker (GHCR)
The GitHub Actions workflow publishes a Docker image on release:
docker pull ghcr.io/hadijannat/basyx-client:<version>
The image contains Python with basyx-client installed and defaults to python.
CLI Quick Start
Install with CLI support:
pip install basyx-client[cli]
Use the basyx command to interact with AAS servers:
# List all AAS shells
basyx shells list --url http://localhost:8081
# Get a specific shell
basyx shells get "urn:example:aas:1" --url http://localhost:8081
# Get a submodel element value
basyx elements get-value "urn:example:sm:1" "Sensors.Temperature"
# Set a value
basyx elements set-value "urn:example:sm:1" "Sensors.Temperature" "25.5"
# Use JSON output for scripting
basyx --format json shells list | jq '.[].id'
CLI Configuration
Save server settings in ~/.basyx/config.yaml:
# Initialize config with defaults
basyx config init
# Set default server URL
basyx config set url http://localhost:8081
# Use named profiles
basyx --profile production shells list
CLI Commands
| Command Group | Operations |
|---|---|
basyx shells |
list, get, create, delete, refs, asset-info |
basyx submodels |
list, get, create, delete, value |
basyx elements |
list, get, get-value, set-value, create, delete, invoke |
basyx registry shells |
list, get, create, delete |
basyx registry submodels |
list, get, create, delete |
basyx aasx |
list, get, download, upload, delete |
basyx discovery |
lookup, link, unlink, list-links |
basyx concepts |
list, get, create, delete |
basyx config |
show, set, get, profiles, init |
See basyx --help or the CLI documentation for full details.
Features
- First-class CLI - Full command-line interface for all API operations
- Automatic encoding - Base64url for identifiers, URL-encoding for idShortPath
- Typed responses - Returns
basyx.aas.model.*objects, not dictionaries - Sync + async - Both synchronous and asynchronous operation support
- Full auth suite - Bearer, Basic, OAuth2 client credentials, mTLS certificates
- Proper exceptions -
ResourceNotFoundError,ConflictError, etc. instead of generic errors - Pagination helpers - Easy iteration through paginated results
- Element helpers -
$metadata,$reference,$path, async operation status/result
Quick Start
Basic Usage
Note: the BaSyx Docker images in docker-compose.yml expose the API at the root
(http://localhost:8081, no /api/v3.0). Some deployments mount the API at
/api/v3.0 — set base_url accordingly.
from basyx_client import AASClient
with AASClient("http://localhost:8081") as client:
# List all AAS
result = client.shells.list()
for aas in result.items:
print(f"{aas.id_short}: {aas.id}")
# Get a specific AAS
aas = client.shells.get("urn:example:aas:machine-001")
# Get a submodel
sm = client.submodels.get("urn:example:sm:operational-data")
# Get/set element values
temp = client.submodels.elements.get_value(
"urn:example:sm:operational-data",
"Sensors.Temperature"
)
client.submodels.elements.set_value(
"urn:example:sm:operational-data",
"Sensors.Temperature",
25.5
)
Async Usage
import asyncio
from basyx_client import AASClient
async def main():
async with AASClient("http://localhost:8081") as client:
# Concurrent fetches
aas1, aas2 = await asyncio.gather(
client.shells.get_async("urn:example:aas:1"),
client.shells.get_async("urn:example:aas:2"),
)
print(aas1.id_short, aas2.id_short)
asyncio.run(main())
Authentication
from basyx_client import AASClient
from basyx_client.auth import BearerAuth, OAuth2ClientCredentials
# Bearer token
client = AASClient("http://localhost:8081", auth=BearerAuth("my-token"))
# Basic auth (shorthand)
client = AASClient("http://localhost:8081", auth=("username", "password"))
# OAuth2 client credentials
client = AASClient("http://localhost:8081", auth=OAuth2ClientCredentials(
token_url="https://auth.example.com/oauth/token",
client_id="my-client",
client_secret="my-secret",
scope="aas:read aas:write",
))
# mTLS
client = AASClient(
"https://secure.example.com",
cert=("/path/to/cert.pem", "/path/to/key.pem"),
)
Error Handling
from basyx_client import AASClient
from basyx_client.exceptions import ResourceNotFoundError, ConflictError
with AASClient("http://localhost:8081") as client:
try:
aas = client.shells.get("urn:nonexistent:aas")
except ResourceNotFoundError as e:
print(f"AAS not found: {e.message}")
print(f"URL: {e.url}")
try:
client.shells.create(my_aas)
except ConflictError:
print("AAS already exists")
Pagination
from basyx_client import AASClient
from basyx_client.pagination import iterate_pages
with AASClient("http://localhost:8081/api/v3.0") as client:
# Manual pagination
result = client.shells.list(limit=10)
while result.has_more:
for aas in result.items:
process(aas)
result = client.shells.list(limit=10, cursor=result.cursor)
# Automatic pagination
for aas in iterate_pages(lambda limit, cursor: client.shells.list(limit, cursor)):
process(aas)
API Coverage
| Endpoint | Status |
|---|---|
AAS Repository (/shells) |
✅ Full |
Submodel Repository (/submodels) |
✅ Full |
Submodel Elements (/submodels/{id}/submodel-elements/{path}) |
✅ Full |
Concept Descriptions (/concept-descriptions) |
✅ Full |
AAS Registry (/shell-descriptors) |
✅ Full |
Submodel Registry (/submodel-descriptors) |
✅ Full |
AASX Server (/packages) |
✅ Full |
Discovery (/lookup/shells) |
✅ Full |
Documentation
Full documentation is available at the docs site:
Development
# Install with all dependencies
pip install -e ".[dev,cli,docs]"
# Run tests
pytest tests/unit -v
# Run linter
ruff check src tests
# Type checking
mypy src
# Build documentation
mkdocs serve # Preview at localhost:8000
# Integration tests (requires Docker)
docker compose up -d
pytest tests/integration -v
docker compose down
Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
License
Apache License 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file basyx_client-0.1.4.tar.gz.
File metadata
- Download URL: basyx_client-0.1.4.tar.gz
- Upload date:
- Size: 84.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f94ab36143f569793ee00366ea84939e760fbe80e6853ea016c210619babf92
|
|
| MD5 |
92316eb342eedd287428f7a8162319ab
|
|
| BLAKE2b-256 |
06585d6b17b3ac734c891130a8654e7a3f8143b112caa464bf8d11d02bc9b714
|
Provenance
The following attestation bundles were made for basyx_client-0.1.4.tar.gz:
Publisher:
publish.yml on hadijannat/basyx-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
basyx_client-0.1.4.tar.gz -
Subject digest:
4f94ab36143f569793ee00366ea84939e760fbe80e6853ea016c210619babf92 - Sigstore transparency entry: 843385739
- Sigstore integration time:
-
Permalink:
hadijannat/basyx-client@2bb41c234c35b76c417923ee1b73735626fea560 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/hadijannat
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2bb41c234c35b76c417923ee1b73735626fea560 -
Trigger Event:
release
-
Statement type:
File details
Details for the file basyx_client-0.1.4-py3-none-any.whl.
File metadata
- Download URL: basyx_client-0.1.4-py3-none-any.whl
- Upload date:
- Size: 56.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21155c055c91aeca35b4dc8442188b074e01e6a45b065a42c5c461560e464228
|
|
| MD5 |
306cc630100d2041e4b11503c5555f92
|
|
| BLAKE2b-256 |
5e4dd6c2a907e4715b6433b9a206b50c531f2bbab74db48ac7d30d294b7164fe
|
Provenance
The following attestation bundles were made for basyx_client-0.1.4-py3-none-any.whl:
Publisher:
publish.yml on hadijannat/basyx-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
basyx_client-0.1.4-py3-none-any.whl -
Subject digest:
21155c055c91aeca35b4dc8442188b074e01e6a45b065a42c5c461560e464228 - Sigstore transparency entry: 843385748
- Sigstore integration time:
-
Permalink:
hadijannat/basyx-client@2bb41c234c35b76c417923ee1b73735626fea560 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/hadijannat
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2bb41c234c35b76c417923ee1b73735626fea560 -
Trigger Event:
release
-
Statement type: