kapps-semantic-middleware 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kapps_semantic_middleware-0.1.0/.env.example +14 -0
- kapps_semantic_middleware-0.1.0/.github/workflows/hygiene.yml +40 -0
- kapps_semantic_middleware-0.1.0/.github/workflows/publish.yml +30 -0
- kapps_semantic_middleware-0.1.0/.gitignore +22 -0
- kapps_semantic_middleware-0.1.0/.python-version +1 -0
- kapps_semantic_middleware-0.1.0/AGENTS.md +170 -0
- kapps_semantic_middleware-0.1.0/CHANGELOG.md +46 -0
- kapps_semantic_middleware-0.1.0/CLAUDE.md +1 -0
- kapps_semantic_middleware-0.1.0/CONTEXT-MAP.md +59 -0
- kapps_semantic_middleware-0.1.0/LICENSE +21 -0
- kapps_semantic_middleware-0.1.0/PKG-INFO +142 -0
- kapps_semantic_middleware-0.1.0/README.md +117 -0
- kapps_semantic_middleware-0.1.0/demo/__init__.py +9 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/CONTEXT.md +77 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/README.md +220 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/__init__.py +24 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/__main__.py +43 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/algorithm.py +398 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/control_station.py +206 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/controller.py +1105 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/factory.ttl +16 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/index.py +170 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/launcher.py +485 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/middleware.py +187 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/plc/__init__.py +10 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/plc/__main__.py +87 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/plc/panel.py +202 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/plc/static/transferunit.svg +99 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/plc/templates/panel.html +181 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/plc/transfer_unit.py +449 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/seed.py +259 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/station_board.py +631 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/templates/index.html +311 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/templates/station_board.html +404 -0
- kapps_semantic_middleware-0.1.0/demo/transferunits/transferunit.ttl +114 -0
- kapps_semantic_middleware-0.1.0/docs/mechanics/01-instantiation-and-lifecycle.md +75 -0
- kapps_semantic_middleware-0.1.0/docs/mechanics/02-workflow-registration.md +103 -0
- kapps_semantic_middleware-0.1.0/docs/mechanics/03-state-and-parameters.md +79 -0
- kapps_semantic_middleware-0.1.0/docs/mechanics/04-connector-binding.md +131 -0
- kapps_semantic_middleware-0.1.0/docs/mechanics/05-operation-coordination.md +108 -0
- kapps_semantic_middleware-0.1.0/docs/mechanics/06-views-and-projection.md +86 -0
- kapps_semantic_middleware-0.1.0/docs/mechanics/07-writing-to-the-graph-and-to-devices.md +48 -0
- kapps_semantic_middleware-0.1.0/docs/mechanics/08-provisioning-and-seeding.md +109 -0
- kapps_semantic_middleware-0.1.0/docs/site/_static/custom.css +93 -0
- kapps_semantic_middleware-0.1.0/docs/site/_static/sfb-logo.png +0 -0
- kapps_semantic_middleware-0.1.0/docs/site/_static/switcher.json +8 -0
- kapps_semantic_middleware-0.1.0/docs/site/concepts.md +54 -0
- kapps_semantic_middleware-0.1.0/docs/site/conf.py +160 -0
- kapps_semantic_middleware-0.1.0/docs/site/guide/01-instantiation-and-lifecycle.md +80 -0
- kapps_semantic_middleware-0.1.0/docs/site/guide/02-workflow-registration.md +108 -0
- kapps_semantic_middleware-0.1.0/docs/site/guide/03-state-and-parameters.md +83 -0
- kapps_semantic_middleware-0.1.0/docs/site/guide/04-connector-binding.md +136 -0
- kapps_semantic_middleware-0.1.0/docs/site/guide/05-operation-coordination.md +113 -0
- kapps_semantic_middleware-0.1.0/docs/site/guide/06-views-and-projection.md +90 -0
- kapps_semantic_middleware-0.1.0/docs/site/guide/07-writing-to-the-graph-and-to-devices.md +52 -0
- kapps_semantic_middleware-0.1.0/docs/site/guide/08-provisioning-and-seeding.md +115 -0
- kapps_semantic_middleware-0.1.0/docs/site/guide/index.md +164 -0
- kapps_semantic_middleware-0.1.0/docs/site/index.md +140 -0
- kapps_semantic_middleware-0.1.0/docs/site/publish-workflow.yml +140 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/activity.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/connectors/knowledge_graph_connector.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/connectors/mqtt_binding.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/connectors/rest_binding.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/connectors/semantic.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/connectors/wiring.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/index.md +50 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/middleware.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/modes.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/projection.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/registration.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/rest_router.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/seeding.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/shacl_interop/shape_from_typehints.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/reference/vocabulary.md +9 -0
- kapps_semantic_middleware-0.1.0/docs/site/requirements.txt +10 -0
- kapps_semantic_middleware-0.1.0/docs/site/scenarios/factory.md +153 -0
- kapps_semantic_middleware-0.1.0/docs/site/scenarios/index.md +16 -0
- kapps_semantic_middleware-0.1.0/examples/CONTEXT.md +45 -0
- kapps_semantic_middleware-0.1.0/examples/__init__.py +8 -0
- kapps_semantic_middleware-0.1.0/examples/demo_handover.ttl +42 -0
- kapps_semantic_middleware-0.1.0/examples/demo_scenario1.ttl +66 -0
- kapps_semantic_middleware-0.1.0/examples/demo_scenario2.ttl +75 -0
- kapps_semantic_middleware-0.1.0/examples/docker/docker-compose.yml +36 -0
- kapps_semantic_middleware-0.1.0/examples/docker/graphdb-repo-config.ttl +74 -0
- kapps_semantic_middleware-0.1.0/examples/docs/transferunit-ontology.md +275 -0
- kapps_semantic_middleware-0.1.0/examples/handlers.py +64 -0
- kapps_semantic_middleware-0.1.0/examples/scenario1_hello_world.ipynb +432 -0
- kapps_semantic_middleware-0.1.0/examples/scenario1_hello_world.py +282 -0
- kapps_semantic_middleware-0.1.0/examples/scenario2_door.ipynb +438 -0
- kapps_semantic_middleware-0.1.0/examples/scenario2_door.py +285 -0
- kapps_semantic_middleware-0.1.0/examples/seed.py +269 -0
- kapps_semantic_middleware-0.1.0/examples/transferunit.ttl +114 -0
- kapps_semantic_middleware-0.1.0/pyproject.toml +214 -0
- kapps_semantic_middleware-0.1.0/scripts/release_checks.py +419 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/CONTEXT.md +349 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/__init__.py +38 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/activity.py +384 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/connectors/__init__.py +42 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/connectors/knowledge_graph_connector.py +140 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/connectors/mqtt_binding.py +371 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/connectors/rest_binding.py +437 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/connectors/semantic.py +346 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/connectors/wiring.py +506 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/credentials.py +90 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/docs/mqtt-payloads.md +98 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/examples_cli.py +199 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/middleware.py +1255 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/modes.py +47 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/ontology/core.ttl +755 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/ontology/mes.ttl +90 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/ontology/service.ttl +178 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/projection.py +314 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/py.typed +0 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/registration.py +877 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/rest_router.py +356 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/seeding.py +99 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/shacl_interop/CONTEXT.md +33 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/shacl_interop/__init__.py +5 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/shacl_interop/shape_from_typehints.py +159 -0
- kapps_semantic_middleware-0.1.0/src/kapps_semantic_middleware/vocabulary.py +213 -0
- kapps_semantic_middleware-0.1.0/tests/conftest.py +215 -0
- kapps_semantic_middleware-0.1.0/tests/test_activity_feed.py +559 -0
- kapps_semantic_middleware-0.1.0/tests/test_algorithm_loop.py +224 -0
- kapps_semantic_middleware-0.1.0/tests/test_controller_discovery.py +339 -0
- kapps_semantic_middleware-0.1.0/tests/test_controller_rebuild_view.py +194 -0
- kapps_semantic_middleware-0.1.0/tests/test_controller_view.py +471 -0
- kapps_semantic_middleware-0.1.0/tests/test_demo_activity_feed_wiring.py +101 -0
- kapps_semantic_middleware-0.1.0/tests/test_demo_broker_transport.py +98 -0
- kapps_semantic_middleware-0.1.0/tests/test_event_trigger_integration.py +418 -0
- kapps_semantic_middleware-0.1.0/tests/test_examples_cli.py +118 -0
- kapps_semantic_middleware-0.1.0/tests/test_examples_serve_their_middlewares.py +138 -0
- kapps_semantic_middleware-0.1.0/tests/test_factory_deregistration.py +220 -0
- kapps_semantic_middleware-0.1.0/tests/test_factory_smoke.py +791 -0
- kapps_semantic_middleware-0.1.0/tests/test_failure_dump_unit.py +61 -0
- kapps_semantic_middleware-0.1.0/tests/test_favicon_routes.py +76 -0
- kapps_semantic_middleware-0.1.0/tests/test_graphdb_credentials.py +92 -0
- kapps_semantic_middleware-0.1.0/tests/test_handover_integration.py +143 -0
- kapps_semantic_middleware-0.1.0/tests/test_lap_measurement.py +150 -0
- kapps_semantic_middleware-0.1.0/tests/test_launcher_factory.py +377 -0
- kapps_semantic_middleware-0.1.0/tests/test_launcher_index_guard.py +68 -0
- kapps_semantic_middleware-0.1.0/tests/test_launcher_index_links.py +44 -0
- kapps_semantic_middleware-0.1.0/tests/test_launcher_seeding.py +272 -0
- kapps_semantic_middleware-0.1.0/tests/test_liveness_integration.py +106 -0
- kapps_semantic_middleware-0.1.0/tests/test_middleware_connector_flavours.py +148 -0
- kapps_semantic_middleware-0.1.0/tests/test_modes.py +59 -0
- kapps_semantic_middleware-0.1.0/tests/test_northbound_sync_integration.py +289 -0
- kapps_semantic_middleware-0.1.0/tests/test_optional_transport_stacks.py +245 -0
- kapps_semantic_middleware-0.1.0/tests/test_panel_convergence.py +105 -0
- kapps_semantic_middleware-0.1.0/tests/test_persistence_factory_warning.py +154 -0
- kapps_semantic_middleware-0.1.0/tests/test_plc_guard.py +62 -0
- kapps_semantic_middleware-0.1.0/tests/test_queue_durability_integration.py +152 -0
- kapps_semantic_middleware-0.1.0/tests/test_recursive_rest_router.py +720 -0
- kapps_semantic_middleware-0.1.0/tests/test_recursive_rest_router_integration.py +306 -0
- kapps_semantic_middleware-0.1.0/tests/test_rest_binding.py +357 -0
- kapps_semantic_middleware-0.1.0/tests/test_scenario1_integration.py +164 -0
- kapps_semantic_middleware-0.1.0/tests/test_scenario2_integration.py +202 -0
- kapps_semantic_middleware-0.1.0/tests/test_scenario3_roundtrip_integration.py +272 -0
- kapps_semantic_middleware-0.1.0/tests/test_scenario3_seed_integration.py +147 -0
- kapps_semantic_middleware-0.1.0/tests/test_scenario3_wiring_integration.py +683 -0
- kapps_semantic_middleware-0.1.0/tests/test_semantic_connectors.py +729 -0
- kapps_semantic_middleware-0.1.0/tests/test_service_identity.py +183 -0
- kapps_semantic_middleware-0.1.0/tests/test_shape_from_typehints.py +72 -0
- kapps_semantic_middleware-0.1.0/tests/test_southbound_echo_integration.py +371 -0
- kapps_semantic_middleware-0.1.0/tests/test_station_board_guard.py +178 -0
- kapps_semantic_middleware-0.1.0/tests/test_station_board_set_route.py +139 -0
- kapps_semantic_middleware-0.1.0/tests/test_station_board_state_route.py +630 -0
- kapps_semantic_middleware-0.1.0/tests/test_transfer_unit_plc.py +335 -0
- kapps_semantic_middleware-0.1.0/tests/test_vocabulary.py +88 -0
- kapps_semantic_middleware-0.1.0/tests/test_write_status.py +301 -0
- kapps_semantic_middleware-0.1.0/uv.lock +3729 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# GraphDB connection for examples and demo.
|
|
2
|
+
# GraphDB runs with security disabled in the local Docker image, so username/password
|
|
3
|
+
# are placeholders that the client merely requires.
|
|
4
|
+
#
|
|
5
|
+
# Only these three variables are read. The examples and the demo name their own
|
|
6
|
+
# repository in code -- kapps-demo, the one docker/docker-compose.yml creates -- and the
|
|
7
|
+
# test suite names its own. A GRAPHDB_REPOSITORY left in your environment is ignored by
|
|
8
|
+
# all of them (issue #146), because whatever they connect to, they wipe and re-seed.
|
|
9
|
+
#
|
|
10
|
+
# WARNING: point GRAPHDB_URL at a GraphDB you are allowed to overwrite. The repository is
|
|
11
|
+
# pinned, but the server is not.
|
|
12
|
+
GRAPHDB_URL=http://localhost:7200
|
|
13
|
+
GRAPHDB_USERNAME=admin
|
|
14
|
+
GRAPHDB_PASSWORD=root
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# This workflow is the backstop for commits made directly in the public repo.
|
|
2
|
+
# The pre-push gate in the dev checkout cannot see those commits, so the public
|
|
3
|
+
# repo needs its own CI that runs the same hygiene checks.
|
|
4
|
+
#
|
|
5
|
+
# Checks 2-5. Only check 1 (remotes) is left out: a runner's remote is whatever
|
|
6
|
+
# actions/checkout configured and says nothing about the release. Check 2 is the
|
|
7
|
+
# reason this file exists, and fetch-depth: 0 below is what lets it read the
|
|
8
|
+
# whole history rather than the one commit a shallow checkout would give it.
|
|
9
|
+
|
|
10
|
+
name: hygiene
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
push:
|
|
14
|
+
pull_request:
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
hygiene:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 0
|
|
23
|
+
- uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: '3.12'
|
|
26
|
+
- name: Run the release hygiene checks
|
|
27
|
+
run: python scripts/release_checks.py .
|
|
28
|
+
|
|
29
|
+
# A tool published under the org but carrying no cf-tool topic is absent
|
|
30
|
+
# from the front door, which is a thing nobody notices by looking at the
|
|
31
|
+
# repository. release_checks.py is not the place for it: that file is
|
|
32
|
+
# stdlib-only and judges a tree, and this needs the API.
|
|
33
|
+
- name: Front-door registration
|
|
34
|
+
if: startsWith(github.repository, 'circularfactory/')
|
|
35
|
+
run: |
|
|
36
|
+
gh api repos/${{ github.repository }} --jq '.topics[]' | grep -qx cf-tool || {
|
|
37
|
+
echo "::error::Published under circularfactory but carries no cf-tool topic, so it is absent from the front door."
|
|
38
|
+
exit 1; }
|
|
39
|
+
env:
|
|
40
|
+
GH_TOKEN: ${{ github.token }}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Publish to PyPI when publish_release.py pushes a version tag.
|
|
2
|
+
#
|
|
3
|
+
# id-token: write is what makes trusted publishing work, and is why no API token
|
|
4
|
+
# is stored anywhere. The tag push from publish_release.py is what fires this.
|
|
5
|
+
#
|
|
6
|
+
# PyPI supports trusted publishing from GitHub and from gitlab.com only, not from
|
|
7
|
+
# a self-hosted GitLab. That is the whole reason this project is published from a
|
|
8
|
+
# repository here while development happens elsewhere.
|
|
9
|
+
|
|
10
|
+
name: publish
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
push:
|
|
14
|
+
tags: ['v*']
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
publish:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
environment: pypi
|
|
20
|
+
permissions:
|
|
21
|
+
id-token: write
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
- uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: '3.12'
|
|
27
|
+
- name: Build the distributions
|
|
28
|
+
run: pipx run build
|
|
29
|
+
- name: Publish to PyPI
|
|
30
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
__pycache__/
|
|
3
|
+
.pytest_cache/
|
|
4
|
+
.mypy_cache/
|
|
5
|
+
.ruff_cache/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
*.egg-info/
|
|
9
|
+
.ipynb_checkpoints/
|
|
10
|
+
.env
|
|
11
|
+
|
|
12
|
+
# Written by scripts/prepare_release.py: the reviewed branch tip that publish_release.py
|
|
13
|
+
# refuses to move past. Local state about one release run, not a fact about the project.
|
|
14
|
+
.release-state.json
|
|
15
|
+
# Sphinx build output (#116). The docs site is deployed as a Pages artifact,
|
|
16
|
+
# never committed -- the release repo keeps one clean commit of source only.
|
|
17
|
+
docs/site/_build/
|
|
18
|
+
# The scenario pages are the notebooks themselves, copied in from examples/ by
|
|
19
|
+
# conf.py at build time (#141). Generated, so never committed -- same rule as the
|
|
20
|
+
# build output above.
|
|
21
|
+
docs/site/scenarios/hello-world.ipynb
|
|
22
|
+
docs/site/scenarios/door.ipynb
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Orientation for an agent building against `kapps_semantic_middleware`.
|
|
4
|
+
|
|
5
|
+
This library lets a piece of Python code running on or next to a shopfloor resource expose its
|
|
6
|
+
functionality through an RDF knowledge graph, and lets other middleware instances discover and
|
|
7
|
+
invoke that functionality through the graph rather than through hardcoded network references.
|
|
8
|
+
|
|
9
|
+
If you are prototyping against this middleware, read the consumption rules below first. They are
|
|
10
|
+
constraints that **do not surface in type signatures** — most of them fail silently, producing
|
|
11
|
+
structurally wrong behavior rather than an exception. Then read the mechanics pages for whichever
|
|
12
|
+
part you are touching.
|
|
13
|
+
|
|
14
|
+
## Where to read what
|
|
15
|
+
|
|
16
|
+
**Vocabulary — what the words mean.** Read these before the mechanics pages; the mechanics pages
|
|
17
|
+
assume their terms and do not re-define them.
|
|
18
|
+
|
|
19
|
+
| File | Covers |
|
|
20
|
+
|---|---|
|
|
21
|
+
| [`CONTEXT-MAP.md`](CONTEXT-MAP.md) | The five contexts, how they depend on each other, and the three-module ontology layering |
|
|
22
|
+
| [`src/kapps_semantic_middleware/CONTEXT.md`](src/kapps_semantic_middleware/CONTEXT.md) | The core vocabulary: Service, Workflow, Parameter, ClassScope, Projection, Binding descriptor, Operation, Mode |
|
|
23
|
+
| [`src/kapps_semantic_middleware/shacl_interop/CONTEXT.md`](src/kapps_semantic_middleware/shacl_interop/CONTEXT.md) | Precondition and outcome shapes derived from a function's type hints |
|
|
24
|
+
| [`examples/CONTEXT.md`](examples/CONTEXT.md) | The self-contained scenario notebooks |
|
|
25
|
+
| [`demo/transferunits/CONTEXT.md`](demo/transferunits/CONTEXT.md) | The runnable multi-process factory demonstration |
|
|
26
|
+
|
|
27
|
+
**Mechanics — how to use it.** Written in construction order; a reader can go start to finish
|
|
28
|
+
without forward references.
|
|
29
|
+
|
|
30
|
+
| Page | Covers |
|
|
31
|
+
|---|---|
|
|
32
|
+
| [`docs/mechanics/01-instantiation-and-lifecycle.md`](docs/mechanics/01-instantiation-and-lifecycle.md) | Constructing an instance, choosing a mode, what appears in the graph at startup, heartbeat, deregistration |
|
|
33
|
+
| [`docs/mechanics/02-workflow-registration.md`](docs/mechanics/02-workflow-registration.md) | Declaring what a Service exposes, the ontology prerequisites, signature-derived shapes, address vs. endpoint |
|
|
34
|
+
| [`docs/mechanics/03-state-and-parameters.md`](docs/mechanics/03-state-and-parameters.md) | Modelling resource state as Parameters, committed value vs. locator, where a parameter's shape comes from |
|
|
35
|
+
| [`docs/mechanics/04-connector-binding.md`](docs/mechanics/04-connector-binding.md) | The recognition chain, adding a protocol the library does not ship, connector wiring, transports |
|
|
36
|
+
| [`docs/mechanics/05-operation-coordination.md`](docs/mechanics/05-operation-coordination.md) | Dispatch, the event trigger, pull-and-run, the status lifecycle, handover, recovery |
|
|
37
|
+
| [`docs/mechanics/06-views-and-projection.md`](docs/mechanics/06-views-and-projection.md) | Defining a ClassScope, what a view cannot select, what the northbound projection removes |
|
|
38
|
+
| [`docs/mechanics/07-writing-to-the-graph-and-to-devices.md`](docs/mechanics/07-writing-to-the-graph-and-to-devices.md) | Every path that causes a write, naming the field that moved, northbound vs. southbound, IRI handling |
|
|
39
|
+
| [`docs/mechanics/08-provisioning-and-seeding.md`](docs/mechanics/08-provisioning-and-seeding.md) | **Read first if `ogm=` is a mystery.** The bootstrap order, loading the shared ontologies, authoring the domain TBox, and seeding the instance data a Parameter needs |
|
|
40
|
+
|
|
41
|
+
### A note on the citations you will find in the glossaries
|
|
42
|
+
|
|
43
|
+
The `CONTEXT.md` files cite architecture decision records as **ADR 00nn** and **root ADR
|
|
44
|
+
000n**. Those records are development-repository material and are **not part of this
|
|
45
|
+
distribution** — no copy of them ships, and the release rewrites every path that pointed
|
|
46
|
+
at one, so a citation here is never a link you can follow.
|
|
47
|
+
|
|
48
|
+
**Do not go looking for them.** The citations are provenance markers, not links. Every mechanism a
|
|
49
|
+
glossary cites a record for is explained in full by the mechanics page covering it — ADR 0004's
|
|
50
|
+
subject is the "Address and endpoint" section of
|
|
51
|
+
[`02-workflow-registration.md`](docs/mechanics/02-workflow-registration.md), ADR 0006's is "The
|
|
52
|
+
graph-facing connector" in [`04-connector-binding.md`](docs/mechanics/04-connector-binding.md), and
|
|
53
|
+
so on. If a citation seems to point at something the mechanics pages do not cover, that is a
|
|
54
|
+
documentation bug worth reporting, not a missing file worth hunting.
|
|
55
|
+
|
|
56
|
+
## Where the names come from
|
|
57
|
+
|
|
58
|
+
This library re-exports much of its surface from its three dependencies, so the import you need is
|
|
59
|
+
often *not* from `kapps_semantic_middleware`. Use this table rather than guessing.
|
|
60
|
+
|
|
61
|
+
| Name | Import from |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `SemanticMiddleware`, `Mode` | `kapps_semantic_middleware` |
|
|
64
|
+
| `IRI`, `GraphDB` | `kapps_triplestore_interface` |
|
|
65
|
+
| `OGM` | `kapps_ogm` |
|
|
66
|
+
| `ClassScope` | `kapps_ogm.utils.class_scope` |
|
|
67
|
+
| `SyncDirection` | `transitional_sync_middleware.middleware.sync.synced_connector` |
|
|
68
|
+
| `ConnectionInfo` | `transitional_sync_middleware.middleware.registries` |
|
|
69
|
+
| `INF` (the interface vocabulary) | `kapps_semantic_middleware.vocabulary` |
|
|
70
|
+
| `graphdb_for`, `credentials_for` | `kapps_semantic_middleware.credentials` |
|
|
71
|
+
| `DataModel`, `Reference`, `Identifier` | `kapps_semantic_middleware` (re-exported from `transitional_sync_middleware`) |
|
|
72
|
+
|
|
73
|
+
Binding internals, if you are adding a protocol, live under
|
|
74
|
+
`kapps_semantic_middleware.connectors` — `semantic`, `mqtt_binding`, `rest_binding`,
|
|
75
|
+
`knowledge_graph_connector`, `wiring`.
|
|
76
|
+
|
|
77
|
+
> `kapps_semantic_middleware/ontology/` is **not** a Python module. It is the directory holding the
|
|
78
|
+
> three vocabulary files (`core.ttl`, `mes.ttl`, `service.ttl`). Importing from it fails.
|
|
79
|
+
|
|
80
|
+
## Consumption rules
|
|
81
|
+
|
|
82
|
+
### These fail silently
|
|
83
|
+
|
|
84
|
+
**`GraphDB.from_env()` connects to whatever `GRAPHDB_REPOSITORY` names, and seeding destroys what it
|
|
85
|
+
connects to.** `seeding.clear_repository` clears the default graph of the client's current
|
|
86
|
+
repository, so a value left over in a shell — from another project, another checkout, a `.bashrc`
|
|
87
|
+
written months ago — silently redirects a wipe. Nothing validates that the repository was the one you
|
|
88
|
+
meant; it only has to exist. Use `credentials.graphdb_for("name")`, which names the repository in
|
|
89
|
+
code and ignores the variable, for anything that seeds, clears, or re-seeds. Note this hazard belongs
|
|
90
|
+
to the *variable*, not the server: pinning the repository does not stop `GRAPHDB_URL` pointing at a
|
|
91
|
+
shared instance.
|
|
92
|
+
|
|
93
|
+
**A `ClassScope` terminates at a Parameter and cannot select within one.** Any chain element below
|
|
94
|
+
a complex property is silently discarded during fetch. A view that tries to reach inside a
|
|
95
|
+
parameter blanknode materializes only as far as the parameter itself, with no error raised. A scope
|
|
96
|
+
chooses *which* parameters, never *which parts* of one.
|
|
97
|
+
|
|
98
|
+
**Connector bindings must be registered at construction, not later.** The framework calls
|
|
99
|
+
`connect()` on everything in the connection registry before it runs `on_start_up` callbacks. A
|
|
100
|
+
connector registered after construction never has `connect()` called, so inbound traffic dies
|
|
101
|
+
silently — the listener task never starts and the queue is never fed — while outbound may limp
|
|
102
|
+
along, making the fault one-directional and quiet.
|
|
103
|
+
|
|
104
|
+
**A Parameter's shape comes from the TBox restriction on its property's range, not from the
|
|
105
|
+
instance data.** Anything the restriction does not declare is dropped at materialization with only
|
|
106
|
+
a warning logged. Metadata a connector needs must be declared in the restriction or it never
|
|
107
|
+
arrives, and the connector fails with nothing raised.
|
|
108
|
+
|
|
109
|
+
**Under the locator pattern a Parameter's value is not in the graph at all.** Fast-changing
|
|
110
|
+
parameters keep only metadata in the graph; the live value exists only in the datamodel and over
|
|
111
|
+
REST. An unobserved parameter materializes as an empty list, which means *not yet read* — not zero,
|
|
112
|
+
and not null. Handle the empty case.
|
|
113
|
+
|
|
114
|
+
**A persistence write must name the region of the model that changed.** The fan-out notifies only
|
|
115
|
+
the connectors that region covers. A write that does not name its field notifies every synced
|
|
116
|
+
connector, so devices are written that nobody touched — and for a settable parameter that
|
|
117
|
+
fabricates a command rather than merely wasting traffic.
|
|
118
|
+
|
|
119
|
+
**The northbound REST payload never carries protocol connection metadata.** Broker addresses,
|
|
120
|
+
topics and endpoints are pruned from the served datamodel *before* any data is fetched. This is
|
|
121
|
+
structural, not a permission check: the northbound model has no field able to carry a broker
|
|
122
|
+
address. It stops a peer *learning* an address from this surface; it does not stop someone who
|
|
123
|
+
already knows it.
|
|
124
|
+
|
|
125
|
+
**OWL existential restrictions do not make a field required.** Only SHACL shapes enforce
|
|
126
|
+
requiredness, and only at admission. A parameter with no observed value does not raise a validation
|
|
127
|
+
error on materialization merely because its restriction declares `owl:someValuesFrom`. Absence of a
|
|
128
|
+
triple means *unknown*, never *false*.
|
|
129
|
+
|
|
130
|
+
**Any prettified or shortened IRI is display only.** Production code carries fully back-resolvable
|
|
131
|
+
IRIs in their mangled form — REST path segments, datamodel field names, `svc:endpoint` triples. A
|
|
132
|
+
consumer that parses a displayed IRI, or round-trips one back into a query, gets a wrong answer
|
|
133
|
+
with no exception raised.
|
|
134
|
+
|
|
135
|
+
### These fail loudly
|
|
136
|
+
|
|
137
|
+
**Every class you register against must already exist in the ontology.** The middleware creates
|
|
138
|
+
instances automatically but never mints classes. A domain-specific subclass of `svc:Service`,
|
|
139
|
+
`svc:Workflow` or `svc:StateProperty`, and the `cfc:Capability` subclass a Workflow realizes, must
|
|
140
|
+
all pre-exist. Startup fails immediately, naming the missing class.
|
|
141
|
+
|
|
142
|
+
**All knowledge-graph writes go through the OGM.** Raw SPARQL `UPDATE` or direct
|
|
143
|
+
`kapps_triplestore_interface` mutation calls bypass the validated write path, so the written node passes no
|
|
144
|
+
shape check and a property replacement loses its atomicity — the intermediate state fails
|
|
145
|
+
validation. Reads may use the access module directly; only writes are constrained.
|
|
146
|
+
|
|
147
|
+
**`@mw.workflow` and `@mw.state` are resource-mode only.** Each raises `RuntimeError` when called
|
|
148
|
+
on an instance in any other mode, and `ValueError` when a required class IRI is missing.
|
|
149
|
+
|
|
150
|
+
### Structural facts
|
|
151
|
+
|
|
152
|
+
**Build against `src/kapps_semantic_middleware/`. `examples/` and `demo/` are illustrations, not
|
|
153
|
+
API.** They are teaching vehicles seeded against throwaway repositories, not production patterns to
|
|
154
|
+
copy.
|
|
155
|
+
|
|
156
|
+
**The demo imports as `kapps_semantic_middleware.demonstrations`, not `demo`.** The wheel remaps
|
|
157
|
+
the `demo/` directory into the library namespace. `import demo.transferunits` works only in a
|
|
158
|
+
development checkout.
|
|
159
|
+
|
|
160
|
+
**There is one Service per middleware *instance*, not per Resource.** Several instances may wrap
|
|
161
|
+
one Resource — a controller and a monitor, say — each owning its own Service node, address and
|
|
162
|
+
heartbeat, all linked by `svc:isServiceOf`. Discovery may therefore return several Services for one
|
|
163
|
+
Resource; select by address or by advertised capability rather than assuming exactly one.
|
|
164
|
+
|
|
165
|
+
**Only `resource` and `watchdog` modes are implemented.** `server` is reserved and raises
|
|
166
|
+
`NotImplementedError`. A graph-*consuming* participant — a planner, a controller, a mobile robot —
|
|
167
|
+
is a resource-mode instance with its own Resource, not a server-mode one.
|
|
168
|
+
|
|
169
|
+
**Docker is a prerequisite for running the examples, never for using the library.** The bundled
|
|
170
|
+
`docker compose` file provides the GraphDB the scenarios and the factory need.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to `kapps-semantic-middleware`. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this project uses
|
|
5
|
+
[semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
`prepare_release.py` turns the Unreleased heading below into the dated entry for the version
|
|
8
|
+
being released, and stops the release if there is no such heading. Write the entry as the work
|
|
9
|
+
lands, not at release time.
|
|
10
|
+
|
|
11
|
+
(That sentence deliberately does not spell the heading out. `edit_changelog` insists on finding
|
|
12
|
+
exactly one of it, and prose naming it is a second occurrence — which stopped a release the
|
|
13
|
+
first time this file was written.)
|
|
14
|
+
|
|
15
|
+
## 0.1.0 — 2026-08-12
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **First public release.** A resource's state is described in an RDF knowledge graph as a
|
|
20
|
+
protocol-interface parameter, and the middleware wires that description to a real device:
|
|
21
|
+
peer discovery through the graph, a northbound REST surface, and southbound connectors that
|
|
22
|
+
keep graph and device in step.
|
|
23
|
+
- Two runnable scenarios and a six-process factory demonstration, copied out of the installed
|
|
24
|
+
package with `kapps-examples` — including the `docker compose` files that stand up the
|
|
25
|
+
GraphDB they need, which previously reached only a reader of the source repository.
|
|
26
|
+
- `kapps-transferunit-factory`, a console script that boots the factory demonstration.
|
|
27
|
+
- Agent-facing documentation inside the distribution: `AGENTS.md`, `CONTEXT-MAP.md` and the
|
|
28
|
+
eight `docs/mechanics/` pages, so a consuming agent reading `site-packages` finds the rules
|
|
29
|
+
that explain what it is reading.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- The synchronization layer is now `transitional-sync-middleware`, imported as
|
|
34
|
+
`transitional_sync_middleware`. It is the same code this project has always built on — a
|
|
35
|
+
transitional fork of `aas-middleware` carrying four synchronization fixes — published under
|
|
36
|
+
its own name. **It is retired within a few releases; do not build on it directly.**
|
|
37
|
+
|
|
38
|
+
### Known limitations
|
|
39
|
+
|
|
40
|
+
- Only `resource` and `watchdog` modes are implemented. `server` is reserved and raises
|
|
41
|
+
`NotImplementedError`.
|
|
42
|
+
- A `ClassScope` selects *which* parameters, never *which parts* of one. Any chain element
|
|
43
|
+
below a complex property is discarded during fetch, with nothing raised.
|
|
44
|
+
- Several consumption rules fail silently rather than raising. They are listed in `AGENTS.md`
|
|
45
|
+
under "These fail silently", and reading that section is not optional if you are writing code
|
|
46
|
+
against this library.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
See [AGENTS.md](AGENTS.md).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Context Map
|
|
2
|
+
|
|
3
|
+
## Contexts
|
|
4
|
+
|
|
5
|
+
- [Core Middleware](./src/kapps_semantic_middleware/CONTEXT.md) — the middleware library itself.
|
|
6
|
+
It holds the Service/Workflow/Capability/Operation/Mode registration machinery and the
|
|
7
|
+
execution machinery.
|
|
8
|
+
- [SHACL Interop](./src/kapps_semantic_middleware/shacl_interop/CONTEXT.md) — the temporary SHACL
|
|
9
|
+
seam for workflow precondition shapes and outcome shapes. It generates and parses them. It is
|
|
10
|
+
explicit scaffolding, will move to `kapps_ogm` (see its ADR 0001).
|
|
11
|
+
- [Example Scenarios](./examples/CONTEXT.md) — self-contained demonstration notebooks, plus the
|
|
12
|
+
seed-data logic and the ontology-provisioning logic under them. That logic makes each notebook
|
|
13
|
+
reproducible against a dummy repository, and never against the production state.
|
|
14
|
+
- [TransferUnit Factory](./demo/transferunits/CONTEXT.md) — the runnable multi-process demo. A
|
|
15
|
+
launcher seeds N units and starts one process per participant (ADR 0029). Its decisions live
|
|
16
|
+
with the Core Middleware ADRs, next to ADR 0029.
|
|
17
|
+
- **Module Requirements** — requirements this project places on sibling KAPPS-family
|
|
18
|
+
modules (`kapps_ogm`, the not-yet-created visual-toolbox GUI). Not a code context, and its
|
|
19
|
+
documents are development-repository material that does not ship.
|
|
20
|
+
|
|
21
|
+
## Relationships
|
|
22
|
+
|
|
23
|
+
- **Core Middleware → SHACL Interop**: Core Middleware calls into SHACL Interop to read or write
|
|
24
|
+
a shape. The shape belongs to a Workflow class or a StateProperty class. The call happens when
|
|
25
|
+
`@mw.workflow` or `@mw.state` registers or resolves one. SHACL Interop has no dependency back
|
|
26
|
+
on Core Middleware. It operates on class IRIs and shapes, and not on types of the Core Middleware.
|
|
27
|
+
- **Example Scenarios → Core Middleware**: Example Scenarios instantiate and exercise Core
|
|
28
|
+
Middleware end-to-end, against the ontology and the instance data they seed themselves. Core Middleware
|
|
29
|
+
has no dependency on Example Scenarios.
|
|
30
|
+
- **TransferUnit Factory → Core Middleware**: the factory runs several instances of the library
|
|
31
|
+
in separate processes. That is one instance per unit, plus a controller. A monitor is
|
|
32
|
+
milestone 2 (ADR 0032) and is not built. Core Middleware has no dependency on the factory.
|
|
33
|
+
- **Module Requirements** records obligations that Core Middleware and SHACL Interop place on
|
|
34
|
+
`kapps_ogm` and the visual-toolbox repo. It does not depend on the code contexts, and no code
|
|
35
|
+
context depends on it. It is a record for work that belongs elsewhere.
|
|
36
|
+
|
|
37
|
+
## Ontology-module layering
|
|
38
|
+
|
|
39
|
+
The vocabulary of the project is layered across three modules (Core Middleware ADR 0012):
|
|
40
|
+
|
|
41
|
+
- **`cfc:` — Core** (`.../Core#`): published, external, superior — `Operation`/`Capability`/
|
|
42
|
+
`Resource`/`Task`. The system imports and specializes it. The system does not modify it.
|
|
43
|
+
- **`mes:` — MES** (`.../MES#`, `src/kapps_semantic_middleware/ontology/mes.ttl`): a
|
|
44
|
+
**domain** ontology that imports Core and details it out — possession + handover ability.
|
|
45
|
+
What domain experts touch.
|
|
46
|
+
- **`svc:` — Service** (`.../Service#`, `ontology/service.ttl`): middleware-to-middleware
|
|
47
|
+
**reachability and coordination only**, domain code does not touch it. It holds Service, Workflow and
|
|
48
|
+
StateProperty, the address, the endpoint and the heartbeat. It also holds the resolution chain,
|
|
49
|
+
and an Operation's status and provenance.
|
|
50
|
+
|
|
51
|
+
`mes:` and `svc:` are siblings that both import Core. `mes:` is domain-facing, `svc:` is
|
|
52
|
+
middleware-facing.
|
|
53
|
+
|
|
54
|
+
## Where the decisions are written down
|
|
55
|
+
|
|
56
|
+
The architecture decision records are development-repository material and are not part of
|
|
57
|
+
this distribution. What they decided is described, without the deliberation, in
|
|
58
|
+
[`docs/mechanics/`](docs/mechanics/); [`AGENTS.md`](AGENTS.md) indexes those pages.
|
|
59
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Etienne Hoffmann
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: kapps-semantic-middleware
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Semantic middleware for industrial data integration, built on transitional-sync-middleware
|
|
5
|
+
Author-email: Etienne Hoffmann <etienne.hoffmann@kit.edu>, Sören Weindel <soeren.weindel@kit.edu>
|
|
6
|
+
Maintainer-email: Etienne Hoffmann <etienne.hoffmann@kit.edu>, Sören Weindel <soeren.weindel@kit.edu>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Requires-Dist: aiomqtt>=2.1.0
|
|
11
|
+
Requires-Dist: fastapi>=0.111.0
|
|
12
|
+
Requires-Dist: httpx>=0.27.0
|
|
13
|
+
Requires-Dist: kapps-ogm>=0.2.0
|
|
14
|
+
Requires-Dist: kapps-triplestore-interface>=2.1.0
|
|
15
|
+
Requires-Dist: transitional-sync-middleware>=0.1.0
|
|
16
|
+
Provides-Extra: examples
|
|
17
|
+
Requires-Dist: amqtt>=0.11.0; extra == 'examples'
|
|
18
|
+
Requires-Dist: rdflib>=7.1.3; extra == 'examples'
|
|
19
|
+
Requires-Dist: uvicorn>=0.29.0; extra == 'examples'
|
|
20
|
+
Provides-Extra: notebooks
|
|
21
|
+
Requires-Dist: jupyter>=1.1.1; extra == 'notebooks'
|
|
22
|
+
Requires-Dist: jupytext>=1.16.0; extra == 'notebooks'
|
|
23
|
+
Requires-Dist: nbconvert>=7.16.0; extra == 'notebooks'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# kapps_semantic_middleware
|
|
27
|
+
|
|
28
|
+
Let a piece of Python running on or beside a shopfloor resource expose what it can do through an
|
|
29
|
+
RDF knowledge graph — and let other instances discover and invoke that capability **through the
|
|
30
|
+
graph**, rather than through hardcoded network addresses.
|
|
31
|
+
|
|
32
|
+
A resource's state is described in the graph as a protocol-interface **parameter**. The middleware
|
|
33
|
+
wires that description to the real device: it discovers peers, serves them over REST, and keeps the
|
|
34
|
+
graph and the device in step.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install kapps-semantic-middleware
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Python 3.12 or newer. Nothing else is required to use the library.
|
|
41
|
+
|
|
42
|
+
## Run the examples
|
|
43
|
+
|
|
44
|
+
The scenarios and the factory demo need a few more packages and a running GraphDB. One extra
|
|
45
|
+
covers the packages:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install "kapps-semantic-middleware[examples]"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Copy the runnable files out of the installed package into a directory you own — a notebook inside
|
|
52
|
+
`site-packages` cannot be opened, edited or re-run:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
kapps-examples ./kapps-examples
|
|
56
|
+
cd kapps-examples
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
You now have scenario 1 and scenario 2 (each as a `.py` and a `.ipynb`), the seed data they load,
|
|
60
|
+
and a `docker/` directory. Add the `[notebooks]` extra if you want to open the `.ipynb` files in
|
|
61
|
+
Jupyter; the `.py` versions run with `[examples]` alone.
|
|
62
|
+
|
|
63
|
+
### Start a GraphDB
|
|
64
|
+
|
|
65
|
+
Docker is needed for the examples and the demo, **never for the library itself**.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cd docker
|
|
69
|
+
docker compose up -d
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
GraphDB comes up on <http://localhost:7200> and the `kapps-demo` repository is created for you.
|
|
73
|
+
This works the same on Linux, macOS and Windows.
|
|
74
|
+
|
|
75
|
+
Then point the library at it:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
export GRAPHDB_URL=http://localhost:7200
|
|
79
|
+
export GRAPHDB_USERNAME=admin
|
|
80
|
+
export GRAPHDB_PASSWORD=root
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Three variables, not four. `GraphDBCredentials.from_env()` in `kapps_triplestore_interface` also
|
|
84
|
+
reads `GRAPHDB_REPOSITORY`, and your own code may well use it — but nothing here does. The examples
|
|
85
|
+
and the demo name `kapps-demo` in code, and the test suite names its own. **A `GRAPHDB_REPOSITORY`
|
|
86
|
+
you already have set is ignored rather than obeyed**, because these are the parts that wipe and
|
|
87
|
+
re-seed whatever they connect to.
|
|
88
|
+
|
|
89
|
+
> **Never point `GRAPHDB_URL` at a GraphDB you care about.** The examples and the demo clear the
|
|
90
|
+
> repository they use on every run. `docker compose down -v` wipes the throwaway one; the next run
|
|
91
|
+
> re-seeds it.
|
|
92
|
+
|
|
93
|
+
### Run a scenario
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
python scenario1_hello_world.py # operation coordination through the graph
|
|
97
|
+
python scenario2_door.py # direct state discovery and control
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Run the factory demo
|
|
101
|
+
|
|
102
|
+
A small factory as six real processes — one per mock PLC, one per middleware instance, and a
|
|
103
|
+
controller that discovers every unit *in the graph* and drives it over REST. You watch it from a
|
|
104
|
+
browser.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
kapps-transferunit-factory
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Where to read what
|
|
111
|
+
|
|
112
|
+
| | |
|
|
113
|
+
|---|---|
|
|
114
|
+
| [`AGENTS.md`](AGENTS.md) | **Start here to build against this.** The consumption rules — including the ones that fail *silently* — and which name to import from where. |
|
|
115
|
+
| [`docs/mechanics/`](docs/mechanics/) | How each mechanism actually works, one page each, in construction order. |
|
|
116
|
+
| [`CONTEXT-MAP.md`](CONTEXT-MAP.md) | The five contexts and how they relate. |
|
|
117
|
+
| `examples/` | Scenario 1 and scenario 2, self-contained. |
|
|
118
|
+
| `demo/transferunits/` | The factory demo. |
|
|
119
|
+
|
|
120
|
+
If you are writing code against this library, read `AGENTS.md` first. Several of its rules are
|
|
121
|
+
constraints that **do not appear in any type signature** and fail by producing quietly wrong
|
|
122
|
+
behaviour rather than an exception.
|
|
123
|
+
|
|
124
|
+
## Status
|
|
125
|
+
|
|
126
|
+
`0.1.0` is the first public release. It is usable — the scenarios and the factory demo run end to
|
|
127
|
+
end — but the API may still move. See [`CHANGELOG.md`](CHANGELOG.md).
|
|
128
|
+
|
|
129
|
+
## Contributing
|
|
130
|
+
|
|
131
|
+
Development happens in a private repository and this one is the published half: it carries one
|
|
132
|
+
commit per release and no ancestry, so there is nothing here to branch from.
|
|
133
|
+
|
|
134
|
+
Bug reports and questions are welcome as issues on this repository. A patch is welcome too --
|
|
135
|
+
say what it changes and why, and it will be applied on the development side and credited in
|
|
136
|
+
`CHANGELOG.md` for the release that carries it.
|
|
137
|
+
|
|
138
|
+
## Acknowledgements
|
|
139
|
+
|
|
140
|
+
This package is developed as part of the INF subproject of the CRC 1574: Circular Factory for the
|
|
141
|
+
Perpetual Product. This work is therefore supported by the Deutsche Forschungsgemeinschaft (DFG,
|
|
142
|
+
German Research Foundation) [grant-number: SFB-1574-471687386].
|